@xom11/whiteboard 0.24.1 → 0.25.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 (85) hide show
  1. package/README.md +85 -12
  2. package/dist/ai.d.mts +472 -0
  3. package/dist/ai.d.ts +472 -0
  4. package/dist/ai.js +2156 -0
  5. package/dist/ai.js.map +1 -0
  6. package/dist/ai.mjs +1495 -0
  7. package/dist/ai.mjs.map +1 -0
  8. package/dist/catalog.json +4 -4
  9. package/dist/chunk-73Q7ADVL.mjs +35 -0
  10. package/dist/chunk-73Q7ADVL.mjs.map +1 -0
  11. package/dist/{chunk-BKSXPNPQ.mjs → chunk-AYSFWUPK.mjs} +4 -3
  12. package/dist/chunk-AYSFWUPK.mjs.map +1 -0
  13. package/dist/chunk-B4NJJZFR.mjs +18 -0
  14. package/dist/chunk-B4NJJZFR.mjs.map +1 -0
  15. package/dist/{chunk-LVNCYP4J.mjs → chunk-CJBLJUWG.mjs} +5 -5
  16. package/dist/{chunk-LVNCYP4J.mjs.map → chunk-CJBLJUWG.mjs.map} +1 -1
  17. package/dist/{chunk-YIPI3WUL.mjs → chunk-ESVPQWHX.mjs} +5 -5
  18. package/dist/{chunk-YIPI3WUL.mjs.map → chunk-ESVPQWHX.mjs.map} +1 -1
  19. package/dist/{chunk-IBTRMWD6.mjs → chunk-I24QOHPU.mjs} +3 -3
  20. package/dist/{chunk-IBTRMWD6.mjs.map → chunk-I24QOHPU.mjs.map} +1 -1
  21. package/dist/{chunk-ZBJBQKJ2.mjs → chunk-IHUFOV7L.mjs} +4 -19
  22. package/dist/chunk-IHUFOV7L.mjs.map +1 -0
  23. package/dist/{chunk-AZIARTGX.mjs → chunk-M42TGYT6.mjs} +3 -3
  24. package/dist/{chunk-AZIARTGX.mjs.map → chunk-M42TGYT6.mjs.map} +1 -1
  25. package/dist/{chunk-WWMQ2VHZ.mjs → chunk-NDEZJKNY.mjs} +4 -4
  26. package/dist/{chunk-WWMQ2VHZ.mjs.map → chunk-NDEZJKNY.mjs.map} +1 -1
  27. package/dist/{chunk-CSCF3YFZ.mjs → chunk-ONBCUWVI.mjs} +6 -4
  28. package/dist/chunk-ONBCUWVI.mjs.map +1 -0
  29. package/dist/{chunk-6V4SH4JJ.mjs → chunk-REIJZDVZ.mjs} +6 -35
  30. package/dist/chunk-REIJZDVZ.mjs.map +1 -0
  31. package/dist/{chunk-4D5CSIJO.mjs → chunk-TB4CL25L.mjs} +10 -8
  32. package/dist/chunk-TB4CL25L.mjs.map +1 -0
  33. package/dist/chunk-VNCCIV6O.mjs +938 -0
  34. package/dist/chunk-VNCCIV6O.mjs.map +1 -0
  35. package/dist/{chunk-MFOGFFIL.mjs → chunk-VRHWDZ66.mjs} +6 -5
  36. package/dist/chunk-VRHWDZ66.mjs.map +1 -0
  37. package/dist/{chunk-CRAPWQKJ.mjs → chunk-YSJOVBCD.mjs} +4 -4
  38. package/dist/{chunk-CRAPWQKJ.mjs.map → chunk-YSJOVBCD.mjs.map} +1 -1
  39. package/dist/geometry-2d.d.mts +2 -1
  40. package/dist/geometry-2d.d.ts +2 -1
  41. package/dist/geometry-2d.js +1383 -23
  42. package/dist/geometry-2d.js.map +1 -1
  43. package/dist/geometry-2d.mjs +7 -5
  44. package/dist/geometry-3d.d.mts +2 -1
  45. package/dist/geometry-3d.d.ts +2 -1
  46. package/dist/geometry-3d.js +2 -2
  47. package/dist/geometry-3d.js.map +1 -1
  48. package/dist/geometry-3d.mjs +6 -4
  49. package/dist/graph-2d.d.mts +2 -1
  50. package/dist/graph-2d.d.ts +2 -1
  51. package/dist/graph-2d.js +2 -2
  52. package/dist/graph-2d.js.map +1 -1
  53. package/dist/graph-2d.mjs +9 -7
  54. package/dist/{host-TLIXN4CF.mjs → host-A64ITWVX.mjs} +8 -6
  55. package/dist/host-A64ITWVX.mjs.map +1 -0
  56. package/dist/{host-DOAYVL35.mjs → host-L7FMFZUW.mjs} +228 -30
  57. package/dist/host-L7FMFZUW.mjs.map +1 -0
  58. package/dist/{host-GKNQBBUE.mjs → host-QK53UYMD.mjs} +12 -10
  59. package/dist/host-QK53UYMD.mjs.map +1 -0
  60. package/dist/index.d.mts +4 -616
  61. package/dist/index.d.ts +4 -616
  62. package/dist/index.js +8889 -8529
  63. package/dist/index.js.map +1 -1
  64. package/dist/index.mjs +21 -1012
  65. package/dist/index.mjs.map +1 -1
  66. package/dist/latex.d.mts +2 -1
  67. package/dist/latex.d.ts +2 -1
  68. package/dist/render-3WTY7NZB.mjs +9 -0
  69. package/dist/{render-SA4JTOW3.mjs.map → render-3WTY7NZB.mjs.map} +1 -1
  70. package/dist/serialize-SRJVKYUG.mjs +8 -0
  71. package/dist/{serialize-3NZS6A6Q.mjs.map → serialize-SRJVKYUG.mjs.map} +1 -1
  72. package/dist/{types-rA4slL08.d.ts → types-DWRyCa2m.d.mts} +139 -1
  73. package/dist/{types-rA4slL08.d.mts → types-DWRyCa2m.d.ts} +139 -1
  74. package/package.json +6 -1
  75. package/dist/chunk-4D5CSIJO.mjs.map +0 -1
  76. package/dist/chunk-6V4SH4JJ.mjs.map +0 -1
  77. package/dist/chunk-BKSXPNPQ.mjs.map +0 -1
  78. package/dist/chunk-CSCF3YFZ.mjs.map +0 -1
  79. package/dist/chunk-MFOGFFIL.mjs.map +0 -1
  80. package/dist/chunk-ZBJBQKJ2.mjs.map +0 -1
  81. package/dist/host-DOAYVL35.mjs.map +0 -1
  82. package/dist/host-GKNQBBUE.mjs.map +0 -1
  83. package/dist/host-TLIXN4CF.mjs.map +0 -1
  84. package/dist/render-SA4JTOW3.mjs +0 -8
  85. package/dist/serialize-3NZS6A6Q.mjs +0 -6
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/stamps/graph-2d/index.tsx"],"names":[],"mappings":";;;;;;;AAUA,IAAM,gBAAA,GAAmB,IAAA;AAAA,EAAK,MAC5B,OAAO,qBAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,gBAAA,EAAiB,CAAE;AAChE,CAAA;AAEA,IAAM,WAAA,mBACJ,IAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,KAAA,EAAM,IAAA;AAAA,IACN,MAAA,EAAO,IAAA;AAAA,IACP,OAAA,EAAQ,WAAA;AAAA,IACR,IAAA,EAAK,MAAA;AAAA,IACL,MAAA,EAAO,cAAA;AAAA,IACP,WAAA,EAAY,KAAA;AAAA,IACZ,aAAA,EAAc,OAAA;AAAA,IACd,cAAA,EAAe,OAAA;AAAA,IACf,aAAA,EAAY,MAAA;AAAA,IAEZ,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,iBAAA,EAAkB,CAAA;AAAA,sBAC1B,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,4BAAA,EAA6B;AAAA;AAAA;AACvC,CAAA;AAGK,IAAM,YAAA,GAA6C;AAAA,EACxD,IAAA,EAAM,SAAA;AAAA,EACN,WAAA,EAAa,GAAA;AAAA,EACb,YAAA,EAAc,WAAA;AAAA,EACd,YAAA,EAAc,sCAAA;AAAA,EACd,WAAA,EAAa,WAAA;AAAA,EACb,aAAA,EAAe,eAAA;AAAA,EACf,YAAA,EAAc,IAAA;AAAA,EACd,iBAAA,EAAmB,mBAAA;AAAA,EAEnB,MAAM,wBAAwB,IAAA,EAAgC;AAC5D,IAAA,IAAI,CAAC,mBAAA,CAAoB,IAAI,CAAA,EAAG;AAC9B,MAAA,MAAM,IAAI,MAAM,gFAAwE,CAAA;AAAA,IAC1F;AACA,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,IAAA,CAAK,SAAS,CAAA;AAC5C,IAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,MAAM,2EAA8D,CAAA;AAC1F,IAAA,OAAO,uBAAA,CAAwB,OAAO,KAAK,CAAA;AAAA,EAC7C,CAAA;AAAA,EAEA,MAAM,0BAA0B,OAAA,EAA4C;AAC1E,IAAA,MAAM,OAAO,OAAA,CAAQ,UAAA;AACrB,IAAA,MAAM,SAAU,OAAA,CAAuC,MAAA;AACvD,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,mBAAA,CAAoB,IAAI,GAAG,OAAO,IAAA;AAClD,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,IAAA,CAAK,SAAS,CAAA;AAC5C,IAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,IAAA,MAAM,SAAA,GAAY,MAAM,uBAAA,CAAwB,KAAA,EAAO,KAAK,CAAA;AAC5D,IAAA,OAAO,cAAA,CAAe,WAAW,MAAM,CAAA;AAAA,EACzC,CAAA;AAAA,EAEA,IAAA,EAAM;AACR","file":"chunk-YIPI3WUL.mjs","sourcesContent":["'use client';\nimport { lazy, type ReactNode } from 'react';\nimport { renderGraphSvgFromState } from './render';\nimport { isGraph2DCustomData, type Graph2DCustomData } from './types';\nimport { parseSceneState } from './serialize';\nimport { svgToStampFile } from '../shared/svgToStampFile';\nimport type { RestoredStampFile, StampType } from '../shared/types';\n\nexport type { Graph2DCustomData };\n\nconst Graph2DStampHost = lazy(() =>\n import('./host').then((m) => ({ default: m.Graph2DStampHost })),\n);\n\nconst Graph2DIcon: ReactNode = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 3L3 21L21 21\" />\n <path d=\"M6 16Q9 8 12 10Q15 12 18 6\" />\n </svg>\n);\n\nexport const graph2dStamp: StampType<Graph2DCustomData> = {\n kind: 'graph2d',\n shortcutKey: 'h',\n toolbarLabel: '📈',\n toolbarTitle: 'Chèn đồ thị 2D (H)',\n toolbarIcon: Graph2DIcon,\n toolbarTestId: 'graph2d-stamp',\n experimental: true,\n matchesCustomData: isGraph2DCustomData,\n\n async renderSvgFromCustomData(data: unknown): Promise<string> {\n if (!isGraph2DCustomData(data)) {\n throw new Error('graph2dStamp.renderSvgFromCustomData: customData không phải graph2d v2');\n }\n const state = parseSceneState(data.jsonState);\n if (!state) throw new Error('graph2dStamp.renderSvgFromCustomData: jsonState không hợp lệ');\n return renderGraphSvgFromState(state, false);\n },\n\n async restoreFileFromCustomData(element): Promise<RestoredStampFile | null> {\n const data = element.customData;\n const fileId = (element as { fileId?: string | null }).fileId;\n if (!fileId || !isGraph2DCustomData(data)) return null;\n const state = parseSceneState(data.jsonState);\n if (!state) return null;\n const svgString = await renderGraphSvgFromState(state, false);\n return svgToStampFile(svgString, fileId);\n },\n\n Host: Graph2DStampHost,\n};\n"]}
1
+ {"version":3,"sources":["../src/stamps/graph-2d/index.tsx"],"names":[],"mappings":";;;;;;;AAUA,IAAM,gBAAA,GAAmB,IAAA;AAAA,EAAK,MAC5B,OAAO,qBAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,gBAAA,EAAiB,CAAE;AAChE,CAAA;AAEA,IAAM,WAAA,mBACJ,IAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,KAAA,EAAM,IAAA;AAAA,IACN,MAAA,EAAO,IAAA;AAAA,IACP,OAAA,EAAQ,WAAA;AAAA,IACR,IAAA,EAAK,MAAA;AAAA,IACL,MAAA,EAAO,cAAA;AAAA,IACP,WAAA,EAAY,KAAA;AAAA,IACZ,aAAA,EAAc,OAAA;AAAA,IACd,cAAA,EAAe,OAAA;AAAA,IACf,aAAA,EAAY,MAAA;AAAA,IAEZ,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,iBAAA,EAAkB,CAAA;AAAA,sBAC1B,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,4BAAA,EAA6B;AAAA;AAAA;AACvC,CAAA;AAGK,IAAM,YAAA,GAA6C;AAAA,EACxD,IAAA,EAAM,SAAA;AAAA,EACN,WAAA,EAAa,GAAA;AAAA,EACb,YAAA,EAAc,WAAA;AAAA,EACd,YAAA,EAAc,sCAAA;AAAA,EACd,WAAA,EAAa,WAAA;AAAA,EACb,aAAA,EAAe,eAAA;AAAA,EACf,YAAA,EAAc,IAAA;AAAA,EACd,iBAAA,EAAmB,mBAAA;AAAA,EAEnB,MAAM,wBAAwB,IAAA,EAAgC;AAC5D,IAAA,IAAI,CAAC,mBAAA,CAAoB,IAAI,CAAA,EAAG;AAC9B,MAAA,MAAM,IAAI,MAAM,gFAAwE,CAAA;AAAA,IAC1F;AACA,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,IAAA,CAAK,SAAS,CAAA;AAC5C,IAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,MAAM,2EAA8D,CAAA;AAC1F,IAAA,OAAO,uBAAA,CAAwB,OAAO,KAAK,CAAA;AAAA,EAC7C,CAAA;AAAA,EAEA,MAAM,0BAA0B,OAAA,EAA4C;AAC1E,IAAA,MAAM,OAAO,OAAA,CAAQ,UAAA;AACrB,IAAA,MAAM,SAAU,OAAA,CAAuC,MAAA;AACvD,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,mBAAA,CAAoB,IAAI,GAAG,OAAO,IAAA;AAClD,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,IAAA,CAAK,SAAS,CAAA;AAC5C,IAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,IAAA,MAAM,SAAA,GAAY,MAAM,uBAAA,CAAwB,KAAA,EAAO,KAAK,CAAA;AAC5D,IAAA,OAAO,cAAA,CAAe,WAAW,MAAM,CAAA;AAAA,EACzC,CAAA;AAAA,EAEA,IAAA,EAAM;AACR","file":"chunk-ESVPQWHX.mjs","sourcesContent":["'use client';\nimport { lazy, type ReactNode } from 'react';\nimport { renderGraphSvgFromState } from './render';\nimport { isGraph2DCustomData, type Graph2DCustomData } from './types';\nimport { parseSceneState } from './serialize';\nimport { svgToStampFile } from '../shared/svgToStampFile';\nimport type { RestoredStampFile, StampType } from '../shared/types';\n\nexport type { Graph2DCustomData };\n\nconst Graph2DStampHost = lazy(() =>\n import('./host').then((m) => ({ default: m.Graph2DStampHost })),\n);\n\nconst Graph2DIcon: ReactNode = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 3L3 21L21 21\" />\n <path d=\"M6 16Q9 8 12 10Q15 12 18 6\" />\n </svg>\n);\n\nexport const graph2dStamp: StampType<Graph2DCustomData> = {\n kind: 'graph2d',\n shortcutKey: 'h',\n toolbarLabel: '📈',\n toolbarTitle: 'Chèn đồ thị 2D (H)',\n toolbarIcon: Graph2DIcon,\n toolbarTestId: 'graph2d-stamp',\n experimental: true,\n matchesCustomData: isGraph2DCustomData,\n\n async renderSvgFromCustomData(data: unknown): Promise<string> {\n if (!isGraph2DCustomData(data)) {\n throw new Error('graph2dStamp.renderSvgFromCustomData: customData không phải graph2d v2');\n }\n const state = parseSceneState(data.jsonState);\n if (!state) throw new Error('graph2dStamp.renderSvgFromCustomData: jsonState không hợp lệ');\n return renderGraphSvgFromState(state, false);\n },\n\n async restoreFileFromCustomData(element): Promise<RestoredStampFile | null> {\n const data = element.customData;\n const fileId = (element as { fileId?: string | null }).fileId;\n if (!fileId || !isGraph2DCustomData(data)) return null;\n const state = parseSceneState(data.jsonState);\n if (!state) return null;\n const svgString = await renderGraphSvgFromState(state, false);\n return svgToStampFile(svgString, fileId);\n },\n\n Host: Graph2DStampHost,\n};\n"]}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { serializeScene } from './chunk-6V4SH4JJ.mjs';
2
+ import { serializeScene } from './chunk-REIJZDVZ.mjs';
3
3
 
4
4
  // src/stamps/graph-2d/serialize.ts
5
5
  function stringifySceneState(state) {
@@ -24,5 +24,5 @@ function parseSceneState(json) {
24
24
  }
25
25
 
26
26
  export { parseSceneState, stringifySceneState };
27
- //# sourceMappingURL=chunk-IBTRMWD6.mjs.map
28
- //# sourceMappingURL=chunk-IBTRMWD6.mjs.map
27
+ //# sourceMappingURL=chunk-I24QOHPU.mjs.map
28
+ //# sourceMappingURL=chunk-I24QOHPU.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/stamps/graph-2d/serialize.ts"],"names":[],"mappings":";;;AASO,SAAS,oBAAoB,KAAA,EAAsB;AACxD,EAAA,OAAO,eAAe,KAAK,CAAA;AAC7B;AAEO,SAAS,gBAAgB,IAAA,EAA4B;AAC1D,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EACvB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,UAAU,OAAO,IAAA;AAC5C,EAAA,MAAM,CAAA,GAAI,GAAA;AACV,EAAA,IAAI,CAAA,CAAE,IAAA,EAAM,MAAA,KAAW,SAAA,EAAW,OAAO,IAAA;AACzC,EAAA,IAAI,CAAC,EAAE,IAAA,EAAM,IAAA,IAAQ,OAAO,CAAA,CAAE,IAAA,CAAK,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AAC7D,EAAA,IAAI,OAAO,CAAA,CAAE,OAAA,KAAY,QAAA,EAAU,OAAO,IAAA;AAC1C,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,KAAK,GAAG,OAAO,IAAA;AACpC,EAAA,IAAI,CAAC,CAAA,CAAE,OAAA,IAAW,OAAO,CAAA,CAAE,OAAA,KAAY,UAAU,OAAO,IAAA;AACxD,EAAA,OAAO,GAAA;AACT","file":"chunk-IBTRMWD6.mjs","sourcesContent":["// src/stamps/graph-2d/serialize.ts\n//\n// graph-2d đã dùng plain State (không envelope) ngay từ đầu. Sau Tier D PR 3,\n// thin wrapper qua shared helper cho serialize. parseSceneState giữ behavior\n// null-on-invalid để host/index.tsx có thể discriminate \"customData hỏng\".\n\nimport { serializeScene } from '../shared/serializeScene';\nimport type { State } from '../../core/scene/types';\n\nexport function stringifySceneState(state: State): string {\n return serializeScene(state);\n}\n\nexport function parseSceneState(json: string): State | null {\n if (!json) return null;\n let raw: unknown;\n try {\n raw = JSON.parse(json);\n } catch {\n return null;\n }\n if (!raw || typeof raw !== 'object') return null;\n const v = raw as Partial<State>;\n if (v.meta?.domain !== 'graph2d') return null;\n if (!v.meta?.view || typeof v.meta.view !== 'object') return null;\n if (typeof v.counter !== 'number') return null;\n if (!Array.isArray(v.order)) return null;\n if (!v.objects || typeof v.objects !== 'object') return null;\n return raw as State;\n}\n"]}
1
+ {"version":3,"sources":["../src/stamps/graph-2d/serialize.ts"],"names":[],"mappings":";;;AASO,SAAS,oBAAoB,KAAA,EAAsB;AACxD,EAAA,OAAO,eAAe,KAAK,CAAA;AAC7B;AAEO,SAAS,gBAAgB,IAAA,EAA4B;AAC1D,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EACvB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,UAAU,OAAO,IAAA;AAC5C,EAAA,MAAM,CAAA,GAAI,GAAA;AACV,EAAA,IAAI,CAAA,CAAE,IAAA,EAAM,MAAA,KAAW,SAAA,EAAW,OAAO,IAAA;AACzC,EAAA,IAAI,CAAC,EAAE,IAAA,EAAM,IAAA,IAAQ,OAAO,CAAA,CAAE,IAAA,CAAK,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AAC7D,EAAA,IAAI,OAAO,CAAA,CAAE,OAAA,KAAY,QAAA,EAAU,OAAO,IAAA;AAC1C,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,KAAK,GAAG,OAAO,IAAA;AACpC,EAAA,IAAI,CAAC,CAAA,CAAE,OAAA,IAAW,OAAO,CAAA,CAAE,OAAA,KAAY,UAAU,OAAO,IAAA;AACxD,EAAA,OAAO,GAAA;AACT","file":"chunk-I24QOHPU.mjs","sourcesContent":["// src/stamps/graph-2d/serialize.ts\n//\n// graph-2d đã dùng plain State (không envelope) ngay từ đầu. Sau Tier D PR 3,\n// thin wrapper qua shared helper cho serialize. parseSceneState giữ behavior\n// null-on-invalid để host/index.tsx có thể discriminate \"customData hỏng\".\n\nimport { serializeScene } from '../shared/serializeScene';\nimport type { State } from '../../core/scene/types';\n\nexport function stringifySceneState(state: State): string {\n return serializeScene(state);\n}\n\nexport function parseSceneState(json: string): State | null {\n if (!json) return null;\n let raw: unknown;\n try {\n raw = JSON.parse(json);\n } catch {\n return null;\n }\n if (!raw || typeof raw !== 'object') return null;\n const v = raw as Partial<State>;\n if (v.meta?.domain !== 'graph2d') return null;\n if (!v.meta?.view || typeof v.meta.view !== 'object') return null;\n if (typeof v.counter !== 'number') return null;\n if (!Array.isArray(v.order)) return null;\n if (!v.objects || typeof v.objects !== 'object') return null;\n return raw as State;\n}\n"]}
@@ -1,22 +1,7 @@
1
1
  "use client";
2
+ import { getKind } from './chunk-B4NJJZFR.mjs';
2
3
  import { produce } from 'immer';
3
4
 
4
- // src/core/scene/store.ts
5
-
6
- // src/core/scene/registry.ts
7
- var registry = /* @__PURE__ */ new Map();
8
- function registerKind(def) {
9
- if (registry.has(def.type)) {
10
- console.warn(`[scene] kind "${def.type}" \u0111\xE3 \u0111\u01B0\u1EE3c \u0111\u0103ng k\xFD \u2014 ghi \u0111\xE8 \u0111\u1ECBnh ngh\u0129a c\u0169`);
11
- }
12
- registry.set(def.type, def);
13
- }
14
- function getKind(type) {
15
- const def = registry.get(type);
16
- if (!def) throw new Error(`[scene] unknown kind: ${type}`);
17
- return def;
18
- }
19
-
20
5
  // src/core/scene/reducer.ts
21
6
  function collectDependents(state, rootId) {
22
7
  const dependents = /* @__PURE__ */ new Set([rootId]);
@@ -325,6 +310,6 @@ function collectFreeVars(expression) {
325
310
  return out.sort();
326
311
  }
327
312
 
328
- export { collectFreeVars, compile, createStore, getKind, registerKind, validate };
329
- //# sourceMappingURL=chunk-ZBJBQKJ2.mjs.map
330
- //# sourceMappingURL=chunk-ZBJBQKJ2.mjs.map
313
+ export { collectFreeVars, compile, createStore, validate };
314
+ //# sourceMappingURL=chunk-IHUFOV7L.mjs.map
315
+ //# sourceMappingURL=chunk-IHUFOV7L.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/scene/reducer.ts","../src/core/scene/store.ts","../src/core/scene/expressions/parser.ts"],"names":[],"mappings":";;;;AAKA,SAAS,iBAAA,CAAkB,OAA6B,MAAA,EAA6B;AACnF,EAAA,MAAM,UAAA,mBAAa,IAAI,GAAA,CAAY,CAAC,MAAM,CAAC,CAAA;AAC3C,EAAA,IAAI,IAAA,GAAO,IAAA;AACX,EAAA,OAAO,IAAA,EAAM;AACX,IAAA,IAAA,GAAO,KAAA;AACP,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,EAAoB;AAC/D,MAAA,IAAI,UAAA,CAAW,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA,EAAG;AAC5B,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI;AAAE,QAAA,OAAA,GAAU,OAAA,CAAQ,IAAI,IAAI,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAE,QAAA;AAAA,MAAU;AACvD,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,SAAA,CAAU,GAAA,CAAI,KAAc,CAAA;AACjD,MAAA,IAAI,KAAK,IAAA,CAAK,CAAA,CAAA,KAAK,WAAW,GAAA,CAAI,CAAC,CAAC,CAAA,EAAG;AACrC,QAAA,UAAA,CAAW,GAAA,CAAI,IAAI,EAAE,CAAA;AACrB,QAAA,IAAA,GAAO,IAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,UAAA;AACT;AAEO,SAAS,MAAA,CAAO,OAAqB,MAAA,EAAsB;AAChE,EAAA,QAAQ,OAAO,IAAA;AAAM,IACnB,KAAK,KAAA,EAAO;AACV,MAAA,MAAM,EAAE,GAAA,EAAI,GAAI,MAAA,CAAO,OAAA;AACvB,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,CAAA,YAAA,EAAe,GAAA,CAAI,EAAE,CAAA,8BAAA,CAAc,CAAA;AAC9E,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AAChC,MAAA,OAAA,CAAQ,QAAA,GAAW,IAAI,KAAc,CAAA;AACrC,MAAA,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA,GAAI,GAAA;AACxB,MAAA,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA;AACvB,MAAA,KAAA,CAAM,OAAA,IAAW,CAAA;AACjB,MAAA;AAAA,IACF;AAAA,IACA,KAAK,QAAA,EAAU;AACb,MAAA,MAAM,EAAE,EAAA,EAAI,KAAA,EAAM,GAAI,MAAA,CAAO,OAAA;AAC7B,MAAA,MAAM,GAAA,GAAM,KAAA,CAAM,OAAA,CAAQ,EAAE,CAAA;AAC5B,MAAA,IAAI,CAAC,GAAA,EAAK;AACV,MAAA,MAAA,CAAO,MAAA,CAAO,KAAK,KAAK,CAAA;AACxB,MAAA;AAAA,IACF;AAAA,IACA,KAAK,cAAA,EAAgB;AACnB,MAAA,MAAM,EAAE,EAAA,EAAI,KAAA,EAAM,GAAI,MAAA,CAAO,OAAA;AAC7B,MAAA,MAAM,GAAA,GAAM,KAAA,CAAM,OAAA,CAAQ,EAAE,CAAA;AAC5B,MAAA,IAAI,CAAC,GAAA,EAAK;AACV,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AAChC,MAAA,MAAM,YAAY,EAAE,GAAI,GAAA,CAAI,KAAA,EAAkB,GAAG,KAAA,EAAM;AACvD,MAAA,OAAA,CAAQ,WAAW,SAAkB,CAAA;AACrC,MAAA,GAAA,CAAI,KAAA,GAAQ,SAAA;AACZ,MAAA;AAAA,IACF;AAAA,IACA,KAAK,QAAA,EAAU;AACb,MAAA,MAAM,EAAE,EAAA,EAAG,GAAI,MAAA,CAAO,OAAA;AACtB,MAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,EAAE,CAAA,EAAG;AACxB,MAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,KAAA,EAAO,EAAE,CAAA;AAC5C,MAAA,KAAA,MAAW,SAAS,QAAA,EAAU;AAC5B,QAAA,OAAO,KAAA,CAAM,QAAQ,KAAK,CAAA;AAAA,MAC5B;AACA,MAAA,KAAA,CAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,MAAA,CAAO,OAAK,CAAC,QAAA,CAAS,GAAA,CAAI,CAAC,CAAC,CAAA;AACtD,MAAA;AAAA,IACF;AAAA,IACA,KAAK,OAAA,EAAS;AACZ,MAAA,KAAA,CAAM,UAAU,EAAC;AACjB,MAAA,KAAA,CAAM,QAAQ,EAAC;AACf,MAAA,KAAA,CAAM,OAAA,GAAU,CAAA;AAChB,MAAA;AAAA,IACF;AAAA,IACA,KAAK,MAAA,EAAQ;AACX,MAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAA,CAAO,OAAA;AACzB,MAAA,KAAA,CAAM,OAAA,GAAU,EAAE,GAAG,KAAA,CAAM,OAAA,EAAQ;AACnC,MAAA,KAAA,CAAM,KAAA,GAAQ,CAAC,GAAG,KAAA,CAAM,KAAK,CAAA;AAC7B,MAAA,KAAA,CAAM,UAAU,KAAA,CAAM,OAAA;AAGtB,MAAA,KAAA,CAAM,IAAA,GAAO,EAAE,GAAG,KAAA,CAAM,IAAA,EAAK;AAC7B,MAAA;AAAA,IACF;AAAA,IACA,KAAK,aAAA,EAAe;AAClB,MAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,OAAA,CAAQ,OAAA,EAAS;AACxC,QAAA,MAAA,CAAO,OAAO,GAAG,CAAA;AAAA,MACnB;AACA,MAAA;AAAA,IACF;AAAA,IACA,KAAK,aAAA,EAAe;AAGlB,MAAA,IAAI,KAAA,CAAM,IAAA,CAAK,MAAA,KAAW,SAAA,EAAW;AACrC,MAAA,MAAA,CAAO,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,EAAM,MAAA,CAAO,QAAQ,KAAK,CAAA;AACnD,MAAA;AAAA,IACF;AAAA;AAEJ;;;ACxEA,IAAM,eAAA,GAAkB,GAAA;AAExB,IAAM,WAAA,GAAsB,EAAE,IAAA,EAAM,aAAA,EAAe,SAAS,EAAE,OAAA,EAAS,EAAC,EAAE,EAAE;AAC5E,IAAM,WAAA,GAAsB,EAAE,IAAA,EAAM,aAAA,EAAe,SAAS,EAAE,OAAA,EAAS,EAAC,EAAE,EAAE;AAErE,SAAS,WAAA,CAAY,OAAA,EAAgB,OAAA,GAAwB,EAAC,EAAU;AAC7E,EAAA,MAAM,KAAA,GAAQ,QAAQ,YAAA,IAAgB,eAAA;AACtC,EAAA,IAAI,KAAA,GAAQ,OAAA;AACZ,EAAA,MAAM,OAAgB,EAAC;AACvB,EAAA,MAAM,SAAkB,EAAC;AACzB,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAmB;AACzC,EAAA,IAAI,WAAA,GAAc,KAAA;AAClB,EAAA,IAAI,cAAA,GAAiB,KAAA;AACrB,EAAA,IAAI,kBAAA,GAAsC,IAAA;AAE1C,EAAA,SAAS,MAAA,CAAO,MAAa,MAAA,EAAsB;AACjD,IAAA,SAAA,CAAU,QAAQ,CAAA,CAAA,KAAK,CAAA,CAAE,KAAA,EAAO,IAAA,EAAM,MAAM,CAAC,CAAA;AAAA,EAC/C;AAEA,EAAA,SAAS,YAAY,IAAA,EAAmB;AACtC,IAAA,IAAI,cAAA,EAAgB;AACpB,IAAA,IAAA,CAAK,KAAK,IAAI,CAAA;AACd,IAAA,IAAI,IAAA,CAAK,MAAA,GAAS,KAAA,EAAO,IAAA,CAAK,KAAA,EAAM;AACpC,IAAA,MAAA,CAAO,MAAA,GAAS,CAAA;AAAA,EAClB;AAEA,EAAA,SAAS,YAAY,MAAA,EAAsB;AACzC,IAAA,MAAM,IAAA,GAAO,KAAA;AACb,IAAA,KAAA,GAAQ,OAAA,CAAQ,OAAO,CAAA,KAAA,KAAS;AAAE,MAAA,MAAA,CAAO,OAAO,MAAM,CAAA;AAAA,IAAG,CAAC,CAAA;AAC1D,IAAA,IAAI,UAAU,IAAA,EAAM;AAClB,MAAA,WAAA,CAAY,IAAI,CAAA;AAChB,MAAA,MAAA,CAAO,MAAM,MAAM,CAAA;AAAA,IACrB;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,UAAU,MAAM,KAAA;AAAA,IAEhB,SAAS,MAAA,EAAgB;AACvB,MAAA,IAAI,WAAA,EAAa,MAAM,IAAI,KAAA,CAAM,gEAA8C,CAAA;AAC/E,MAAA,IAAI,kBAAA,EAAoB;AACtB,QAAA,kBAAA,CAAmB,KAAK,MAAM,CAAA;AAC9B,QAAA;AAAA,MACF;AACA,MAAA,WAAA,GAAc,IAAA;AACd,MAAA,IAAI;AAAE,QAAA,WAAA,CAAY,MAAM,CAAA;AAAA,MAAG,CAAA,SAAE;AAAU,QAAA,WAAA,GAAc,KAAA;AAAA,MAAO;AAAA,IAC9D,CAAA;AAAA,IAEA,UAAU,QAAA,EAAU;AAClB,MAAA,SAAA,CAAU,IAAI,QAAQ,CAAA;AACtB,MAAA,OAAO,MAAM;AAAE,QAAA,SAAA,CAAU,OAAO,QAAQ,CAAA;AAAA,MAAG,CAAA;AAAA,IAC7C,CAAA;AAAA,IAEA,IAAA,GAAO;AACL,MAAA,MAAM,IAAA,GAAO,KAAK,GAAA,EAAI;AACtB,MAAA,IAAI,CAAC,IAAA,EAAM;AACX,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,MAAA,MAAM,GAAA,GAAM,KAAA;AACZ,MAAA,KAAA,GAAQ,IAAA;AACR,MAAA,MAAA,CAAO,KAAK,WAAW,CAAA;AAAA,IACzB,CAAA;AAAA,IAEA,IAAA,GAAO;AACL,MAAA,MAAM,IAAA,GAAO,OAAO,GAAA,EAAI;AACxB,MAAA,IAAI,CAAC,IAAA,EAAM;AACX,MAAA,IAAA,CAAK,KAAK,KAAK,CAAA;AACf,MAAA,IAAI,IAAA,CAAK,MAAA,GAAS,KAAA,EAAO,IAAA,CAAK,KAAA,EAAM;AACpC,MAAA,MAAM,GAAA,GAAM,KAAA;AACZ,MAAA,KAAA,GAAQ,IAAA;AACR,MAAA,MAAA,CAAO,KAAK,WAAW,CAAA;AAAA,IACzB,CAAA;AAAA,IAEA,OAAA,EAAS,MAAM,IAAA,CAAK,MAAA,GAAS,CAAA;AAAA,IAC7B,OAAA,EAAS,MAAM,MAAA,CAAO,MAAA,GAAS,CAAA;AAAA,IAE/B,YAAY,EAAA,EAAI;AACd,MAAA,IAAI,kBAAA,EAAoB,MAAM,IAAI,KAAA,CAAM,8DAA4C,CAAA;AACpF,MAAA,kBAAA,GAAqB,EAAC;AACtB,MAAA,IAAI;AAAE,QAAA,EAAA,CAAG,CAAC,CAAA,KAAM;AAAE,UAAA,kBAAA,CAAoB,KAAK,CAAC,CAAA;AAAA,QAAG,CAAC,CAAA;AAAA,MAAG,CAAA,SACnD;AACE,QAAA,MAAM,OAAA,GAAU,kBAAA;AAChB,QAAA,kBAAA,GAAqB,IAAA;AACrB,QAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,UAAA,WAAA,CAAY,EAAE,IAAA,EAAM,aAAA,EAAe,SAAS,EAAE,OAAA,IAAW,CAAA;AAAA,QAC3D;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IAEA,eAAe,EAAA,EAAI;AACjB,MAAA,MAAM,WAAA,GAAc,cAAA;AACpB,MAAA,cAAA,GAAiB,IAAA;AACjB,MAAA,IAAI;AAAE,QAAA,EAAA,EAAG;AAAA,MAAG,CAAA,SAAE;AAAU,QAAA,cAAA,GAAiB,WAAA;AAAA,MAAa;AAAA,IACxD;AAAA,GACF;AACF;;;AChHO,IAAM,iBAAA,GAAoB,CAAC,IAAA,EAAM,GAAG,CAAA;AACpC,IAAM,iBAAA,GAAoB;AAAA,EAC/B,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EACd,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,OAAA;AAAA,EACxB,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,MAAA;AAAA,EAChB,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,OAAA;AAAA,EAAS,IAAA;AAAA,EACvB,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,KAAA;AAAA,EAChB,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,OAAA;AAAA,EACjB,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO;AAChB,CAAA;AAEA,IAAM,KAAA,GAAQ,yBAAA;AACd,IAAM,SAAA,GAAY,4FAAA;AAElB,IAAM,SAAA,GAAY,yCAAA;AAKlB,IAAM,YAAA,GAAe,gCAAA;AAGd,SAAS,SAAS,UAAA,EAAoC;AAC3D,EAAA,MAAM,OAAA,GAAU,WAAW,IAAA,EAAK;AAChC,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,OAAO,+BAAA,EAAiB;AAC1D,EAAA,IAAI,SAAA,CAAU,KAAK,OAAO,CAAA,SAAU,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,yFAAA,EAAwD;AAGhH,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA;AAG1C,EAAA,IAAI,EAAA;AACJ,EAAA,YAAA,CAAa,SAAA,GAAY,CAAA;AACzB,EAAA,OAAA,CAAQ,EAAA,GAAK,YAAA,CAAa,IAAA,CAAK,MAAM,OAAO,IAAA,EAAM;AAChD,IAAA,MAAM,MAAA,GAAS,GAAG,CAAC,CAAA;AACnB,IAAA,IAAI,CAAE,iBAAA,CAAwC,QAAA,CAAS,MAAM,CAAA,EAAG;AAC9D,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,CAAA,kCAAA,EAAqB,MAAM,CAAA,CAAA,EAAG;AAAA,IAC3D;AAAA,EACF;AAGA,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,EAAA,IAAI,CAAA;AACJ,EAAA,KAAA,CAAM,SAAA,GAAY,CAAA;AAClB,EAAA,OAAA,CAAQ,CAAA,GAAI,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA,MAAO,MAAM,GAAA,CAAI,GAAA,CAAI,CAAA,CAAE,CAAC,CAAC,CAAA;AAEtD,EAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AACpB,IAAA,IAAI,OAAO,GAAA,EAAK;AAChB,IAAA,IAAK,iBAAA,CAAwC,QAAA,CAAS,EAAE,CAAA,EAAG;AAC3D,IAAA,IAAK,iBAAA,CAAwC,QAAA,CAAS,EAAE,CAAA,EAAG;AAE3D,IAAA,IAAI,CAAC,0BAAA,CAA2B,IAAA,CAAK,EAAE,CAAA,EAAG;AACxC,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,CAAA,sCAAA,EAA4B,EAAE,CAAA,CAAA,EAAG;AAAA,IAC9D;AAAA,EACF;AAGA,EAAA,IAAI;AACF,IAAA,iBAAA,CAAkB,MAAA,EAAQ,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA;AAAA,MACxC,CAAC,EAAA,KAAO,EAAA,KAAO,GAAA,IAAO,CAAE,iBAAA,CAAwC,QAAA,CAAS,EAAE,CAAA,IAAK,CAAE,iBAAA,CAAwC,QAAA,CAAS,EAAE;AAAA,KACtI,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,OAAO,CAAA,wBAAA,EAAiB,GAAA,CAAc,OAAO,CAAA,CAAA,EAAG;AAAA,EACtE;AAEA,EAAA,OAAO,EAAE,IAAI,IAAA,EAAK;AACpB;AAOO,SAAS,OAAA,CACd,YACA,MAAA,EACkC;AAClC,EAAA,MAAM,CAAA,GAAI,SAAS,UAAU,CAAA;AAC7B,EAAA,IAAI,CAAC,CAAA,CAAE,EAAA,EAAI,OAAO,CAAA,CAAE,KAAA;AACpB,EAAA,MAAM,SAAS,UAAA,CAAW,IAAA,EAAK,CAAE,OAAA,CAAQ,OAAO,IAAI,CAAA;AAEpD,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,EAAA,IAAI,CAAA;AACJ,EAAA,KAAA,CAAM,SAAA,GAAY,CAAA;AAClB,EAAA,OAAA,CAAQ,CAAA,GAAI,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA,MAAO,MAAM,GAAA,CAAI,GAAA,CAAI,CAAA,CAAE,CAAC,CAAC,CAAA;AAEtD,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AACpB,IAAA,IAAI,OAAO,GAAA,EAAK;AAChB,IAAA,IAAK,iBAAA,CAAwC,QAAA,CAAS,EAAE,CAAA,EAAG;AAC3D,IAAA,IAAK,iBAAA,CAAwC,QAAA,CAAS,EAAE,CAAA,EAAG;AAC3D,IAAA,UAAA,CAAW,KAAK,EAAE,CAAA;AAAA,EACpB;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,iBAAA,CAAkB,MAAA,EAAQ,UAAU,CAAA;AAEjD,IAAA,MAAM,KAAK,IAAI,QAAA,CAAS,GAAA,EAAK,GAAG,YAAY,IAAI,CAAA;AAIhD,IAAA,MAAM,IAAA,GAAO,WAAW,GAAA,CAAI,CAAC,SAAS,MAAA,CAAO,IAAI,KAAK,GAAG,CAAA;AACzD,IAAA,OAAO,CAAC,CAAA,KAAc,EAAA,CAAG,CAAA,EAAG,GAAG,IAAI,CAAA;AAAA,EACrC,SAAS,GAAA,EAAK;AACZ,IAAA,OAAO,CAAA,eAAA,EAAmB,IAAc,OAAO,CAAA,CAAA;AAAA,EACjD;AACF;AAEA,SAAS,iBAAA,CAAkB,QAAgB,WAAA,EAA+B;AAGxE,EAAA,IAAI,IAAA,GAAO,MAAA;AACX,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,UAAU,CAAA;AACzC,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,YAAY,CAAA;AAC5C,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,WAAW,CAAA;AAC1C,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,cAAA,EAAgB,UAAU,CAAA;AAC9C,EAAA,KAAA,MAAW,MAAM,iBAAA,EAAmB;AAClC,IAAA,IAAI,EAAA,KAAO,KAAA,IAAS,EAAA,KAAO,OAAA,EAAS;AACpC,IAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,IAAI,MAAA,CAAO,CAAA,GAAA,EAAM,EAAE,CAAA,GAAA,CAAA,EAAO,GAAG,CAAA,EAAG,CAAA,KAAA,EAAQ,EAAE,CAAA,CAAE,CAAA;AAAA,EAClE;AACA,EAAA,OAAO,yBAAyB,IAAI,CAAA,EAAA,CAAA;AACtC;AAGO,SAAS,gBAAgB,UAAA,EAA8B;AAC5D,EAAA,MAAM,CAAA,GAAI,SAAS,UAAU,CAAA;AAC7B,EAAA,IAAI,CAAC,CAAA,CAAE,EAAA,EAAI,OAAO,EAAC;AACnB,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,EAAA,IAAI,CAAA;AACJ,EAAA,KAAA,CAAM,SAAA,GAAY,CAAA;AAClB,EAAA,OAAA,CAAQ,CAAA,GAAI,KAAA,CAAM,IAAA,CAAK,UAAU,CAAA,MAAO,MAAM,GAAA,CAAI,GAAA,CAAI,CAAA,CAAE,CAAC,CAAC,CAAA;AAC1D,EAAA,MAAM,MAAgB,EAAC;AACvB,EAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AACpB,IAAA,IAAI,OAAO,GAAA,EAAK;AAChB,IAAA,IAAK,iBAAA,CAAwC,QAAA,CAAS,EAAE,CAAA,EAAG;AAC3D,IAAA,IAAK,iBAAA,CAAwC,QAAA,CAAS,EAAE,CAAA,EAAG;AAC3D,IAAA,IAAI,SAAA,CAAU,IAAA,CAAK,EAAE,CAAA,EAAG;AACxB,IAAA,GAAA,CAAI,KAAK,EAAE,CAAA;AAAA,EACb;AACA,EAAA,OAAO,IAAI,IAAA,EAAK;AAClB","file":"chunk-IHUFOV7L.mjs","sourcesContent":["// src/core/scene/reducer.ts\nimport type { Draft } from 'immer';\nimport type { Action, State, SceneObject } from './types';\nimport { getKind } from './registry';\n\nfunction collectDependents(state: Draft<State> | State, rootId: string): Set<string> {\n const dependents = new Set<string>([rootId]);\n let grew = true;\n while (grew) {\n grew = false;\n for (const obj of Object.values(state.objects) as SceneObject[]) {\n if (dependents.has(obj.id)) continue;\n let kindDef;\n try { kindDef = getKind(obj.kind); } catch { continue; }\n const refs = kindDef.dependsOn(obj.attrs as never);\n if (refs.some(r => dependents.has(r))) {\n dependents.add(obj.id);\n grew = true;\n }\n }\n }\n return dependents;\n}\n\nexport function reduce(draft: Draft<State>, action: Action): void {\n switch (action.type) {\n case 'ADD': {\n const { obj } = action.payload;\n if (draft.objects[obj.id]) throw new Error(`[scene] id \"${obj.id}\" đã tồn tại`);\n const kindDef = getKind(obj.kind);\n kindDef.validate?.(obj.attrs as never);\n draft.objects[obj.id] = obj;\n draft.order.push(obj.id);\n draft.counter += 1;\n return;\n }\n case 'UPDATE': {\n const { id, patch } = action.payload;\n const obj = draft.objects[id];\n if (!obj) return;\n Object.assign(obj, patch);\n return;\n }\n case 'UPDATE_ATTRS': {\n const { id, patch } = action.payload;\n const obj = draft.objects[id];\n if (!obj) return;\n const kindDef = getKind(obj.kind);\n const nextAttrs = { ...(obj.attrs as object), ...patch };\n kindDef.validate?.(nextAttrs as never);\n obj.attrs = nextAttrs;\n return;\n }\n case 'DELETE': {\n const { id } = action.payload;\n if (!draft.objects[id]) return;\n const toDelete = collectDependents(draft, id);\n for (const delId of toDelete) {\n delete draft.objects[delId];\n }\n draft.order = draft.order.filter(x => !toDelete.has(x));\n return;\n }\n case 'RESET': {\n draft.objects = {};\n draft.order = [];\n draft.counter = 0;\n return;\n }\n case 'LOAD': {\n const { state } = action.payload;\n draft.objects = { ...state.objects };\n draft.order = [...state.order];\n draft.counter = state.counter;\n // Cast qua Draft<State['meta']> — immer chấp nhận structurally\n // identical shape, chỉ stricter readonly.\n draft.meta = { ...state.meta } as typeof draft.meta;\n return;\n }\n case 'TRANSACTION': {\n for (const sub of action.payload.actions) {\n reduce(draft, sub);\n }\n return;\n }\n case 'UPDATE_VIEW': {\n // Action payload typed cho graph-2d ViewSettings. Bỏ qua nếu domain\n // khác (view shape không tương thích — 2d dùng bbox, 3d dùng bbox3D).\n if (draft.meta.domain !== 'graph2d') return;\n Object.assign(draft.meta.view, action.payload.patch);\n return;\n }\n }\n}\n","// src/core/scene/store.ts\nimport { produce } from 'immer';\nimport { reduce } from './reducer';\nimport type { Action, State } from './types';\n\nexport type StoreListener = (next: State, prev: State, action: Action) => void;\n\nexport interface Store {\n getState(): State;\n dispatch(action: Action): void;\n subscribe(listener: StoreListener): () => void;\n undo(): void;\n redo(): void;\n canUndo(): boolean;\n canRedo(): boolean;\n transaction(fn: (dispatch: (a: Action) => void) => void): void;\n withoutHistory(fn: () => void): void;\n}\n\nexport type StoreOptions = { historyLimit?: number };\n\nconst HISTORY_DEFAULT = 100;\n\nconst UNDO_ACTION: Action = { type: 'TRANSACTION', payload: { actions: [] } };\nconst REDO_ACTION: Action = { type: 'TRANSACTION', payload: { actions: [] } };\n\nexport function createStore(initial: State, options: StoreOptions = {}): Store {\n const limit = options.historyLimit ?? HISTORY_DEFAULT;\n let state = initial;\n const past: State[] = [];\n const future: State[] = [];\n const listeners = new Set<StoreListener>();\n let dispatching = false;\n let suspendHistory = false;\n let transactionActions: Action[] | null = null;\n\n function notify(prev: State, action: Action): void {\n listeners.forEach(l => l(state, prev, action));\n }\n\n function pushHistory(prev: State): void {\n if (suspendHistory) return;\n past.push(prev);\n if (past.length > limit) past.shift();\n future.length = 0;\n }\n\n function applyAction(action: Action): void {\n const prev = state;\n state = produce(state, draft => { reduce(draft, action); });\n if (state !== prev) {\n pushHistory(prev);\n notify(prev, action);\n }\n }\n\n return {\n getState: () => state,\n\n dispatch(action: Action) {\n if (dispatching) throw new Error('[scene] không được dispatch trong subscriber');\n if (transactionActions) {\n transactionActions.push(action);\n return;\n }\n dispatching = true;\n try { applyAction(action); } finally { dispatching = false; }\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n },\n\n undo() {\n const prev = past.pop();\n if (!prev) return;\n future.push(state);\n const old = state;\n state = prev;\n notify(old, UNDO_ACTION);\n },\n\n redo() {\n const next = future.pop();\n if (!next) return;\n past.push(state);\n if (past.length > limit) past.shift();\n const old = state;\n state = next;\n notify(old, REDO_ACTION);\n },\n\n canUndo: () => past.length > 0,\n canRedo: () => future.length > 0,\n\n transaction(fn) {\n if (transactionActions) throw new Error('[scene] transaction lồng nhau không hỗ trợ');\n transactionActions = [];\n try { fn((a) => { transactionActions!.push(a); }); }\n finally {\n const actions = transactionActions;\n transactionActions = null;\n if (actions.length > 0) {\n applyAction({ type: 'TRANSACTION', payload: { actions } });\n }\n }\n },\n\n withoutHistory(fn) {\n const prevSuspend = suspendHistory;\n suspendHistory = true;\n try { fn(); } finally { suspendHistory = prevSuspend; }\n },\n };\n}\n","// src/core/scene/expressions/parser.ts\n// Pure expression parser cho function2d kind. Không import JSXGraph/React.\n\nexport const ALLOWED_CONSTANTS = ['pi', 'e'] as const;\nexport const ALLOWED_FUNCTIONS = [\n 'sin', 'cos', 'tan',\n 'asin', 'acos', 'atan', 'atan2',\n 'sinh', 'cosh', 'tanh',\n 'exp', 'log', 'log10', 'ln',\n 'sqrt', 'cbrt', 'abs',\n 'floor', 'ceil', 'round',\n 'min', 'max', 'pow',\n] as const;\n\nconst ID_RE = /[A-Za-z_][A-Za-z0-9_]*/g;\nconst UNSAFE_RE = /[=;{}]|\\beval\\b|\\bnew\\b|\\breturn\\b|\\bthis\\b|\\bwindow\\b|\\bdocument\\b|\\bglobal\\b|\\bprocess\\b/;\n\nconst NUMBER_RE = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/;\n\nexport type ValidateResult = { ok: true } | { ok: false; error: string };\n\n// Detect identifiers used as function calls (followed by '(')\nconst FUNC_CALL_RE = /([A-Za-z_][A-Za-z0-9_]*)\\s*\\(/g;\n\n/** Kiểm tra expression có hợp lệ không. */\nexport function validate(expression: string): ValidateResult {\n const trimmed = expression.trim();\n if (!trimmed) return { ok: false, error: 'Biểu thức rỗng' };\n if (UNSAFE_RE.test(trimmed)) return { ok: false, error: 'Biểu thức chứa toán tử hoặc identifier không cho phép' };\n\n // Replace ^ với ** (JS không có ^)\n const jsExpr = trimmed.replace(/\\^/g, '**');\n\n // Check function call identifiers — must be in ALLOWED_FUNCTIONS\n let fm: RegExpExecArray | null;\n FUNC_CALL_RE.lastIndex = 0;\n while ((fm = FUNC_CALL_RE.exec(jsExpr)) !== null) {\n const fnName = fm[1];\n if (!(ALLOWED_FUNCTIONS as readonly string[]).includes(fnName)) {\n return { ok: false, error: `Hàm không hợp lệ: ${fnName}` };\n }\n }\n\n // Check identifiers\n const ids = new Set<string>();\n let m: RegExpExecArray | null;\n ID_RE.lastIndex = 0;\n while ((m = ID_RE.exec(jsExpr)) !== null) ids.add(m[0]);\n\n for (const id of ids) {\n if (id === 'x') continue;\n if ((ALLOWED_CONSTANTS as readonly string[]).includes(id)) continue;\n if ((ALLOWED_FUNCTIONS as readonly string[]).includes(id)) continue;\n // Remaining identifiers treat as parameter — OK at validate time.\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(id)) {\n return { ok: false, error: `Identifier không hợp lệ: ${id}` };\n }\n }\n\n // Try syntactic compile (with dummy params) to catch syntax errors.\n try {\n buildFunctionBody(jsExpr, Array.from(ids).filter(\n (id) => id !== 'x' && !(ALLOWED_CONSTANTS as readonly string[]).includes(id) && !(ALLOWED_FUNCTIONS as readonly string[]).includes(id),\n ));\n } catch (err) {\n return { ok: false, error: `Cú pháp lỗi: ${(err as Error).message}` };\n }\n\n return { ok: true };\n}\n\n/**\n * Compile expression thành function (x: number) => number.\n * - `params` map từ identifier → value để inline vào closure.\n * - Trả string error nếu invalid.\n */\nexport function compile(\n expression: string,\n params: Record<string, number>,\n): ((x: number) => number) | string {\n const v = validate(expression);\n if (!v.ok) return v.error;\n const jsExpr = expression.trim().replace(/\\^/g, '**');\n\n const ids = new Set<string>();\n let m: RegExpExecArray | null;\n ID_RE.lastIndex = 0;\n while ((m = ID_RE.exec(jsExpr)) !== null) ids.add(m[0]);\n\n const paramNames: string[] = [];\n for (const id of ids) {\n if (id === 'x') continue;\n if ((ALLOWED_CONSTANTS as readonly string[]).includes(id)) continue;\n if ((ALLOWED_FUNCTIONS as readonly string[]).includes(id)) continue;\n paramNames.push(id);\n }\n\n try {\n const body = buildFunctionBody(jsExpr, paramNames);\n \n const fn = new Function('x', ...paramNames, body) as (\n x: number,\n ...args: number[]\n ) => number;\n const args = paramNames.map((name) => params[name] ?? NaN);\n return (x: number) => fn(x, ...args);\n } catch (err) {\n return `Compile error: ${(err as Error).message}`;\n }\n}\n\nfunction buildFunctionBody(jsExpr: string, _paramNames: string[]): string {\n // Inline Math constants and functions.\n // sin → Math.sin, pi → Math.PI, e → Math.E, ln → Math.log.\n let body = jsExpr;\n body = body.replace(/\\bln\\b/g, 'Math.log');\n body = body.replace(/\\blog\\b/g, 'Math.log10');\n body = body.replace(/\\bpi\\b/g, '(Math.PI)');\n body = body.replace(/\\be\\b(?!\\w)/g, '(Math.E)');\n for (const fn of ALLOWED_FUNCTIONS) {\n if (fn === 'log' || fn === 'log10') continue; // already handled\n body = body.replace(new RegExp(`\\\\b${fn}\\\\b`, 'g'), `Math.${fn}`);\n }\n return `\"use strict\"; return (${body});`;\n}\n\n/** Liệt kê free identifiers (≠ x, ≠ allowed const/func). */\nexport function collectFreeVars(expression: string): string[] {\n const v = validate(expression);\n if (!v.ok) return [];\n const ids = new Set<string>();\n let m: RegExpExecArray | null;\n ID_RE.lastIndex = 0;\n while ((m = ID_RE.exec(expression)) !== null) ids.add(m[0]);\n const out: string[] = [];\n for (const id of ids) {\n if (id === 'x') continue;\n if ((ALLOWED_CONSTANTS as readonly string[]).includes(id)) continue;\n if ((ALLOWED_FUNCTIONS as readonly string[]).includes(id)) continue;\n if (NUMBER_RE.test(id)) continue;\n out.push(id);\n }\n return out.sort();\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { DEFAULT_THEME_2D } from './chunk-BKSXPNPQ.mjs';
2
+ import { DEFAULT_THEME_2D } from './chunk-AYSFWUPK.mjs';
3
3
 
4
4
  // src/stamps/graph-2d/editor/theme.ts
5
5
  var GRAPH_THEME_LIGHT = {
@@ -19,5 +19,5 @@ function paletteFor(isDark) {
19
19
  }
20
20
 
21
21
  export { paletteFor };
22
- //# sourceMappingURL=chunk-AZIARTGX.mjs.map
23
- //# sourceMappingURL=chunk-AZIARTGX.mjs.map
22
+ //# sourceMappingURL=chunk-M42TGYT6.mjs.map
23
+ //# sourceMappingURL=chunk-M42TGYT6.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/stamps/graph-2d/editor/theme.ts"],"names":[],"mappings":";;;AAIO,IAAM,iBAAA,GAA6B;AAAA,EACxC,GAAG;AACL,CAAA;AAEO,IAAM,gBAAA,GAA4B;AAAA,EACvC,GAAG,gBAAA;AAAA,EACH,MAAA,EAAQ,SAAA;AAAA,EACR,IAAA,EAAM,SAAA;AAAA,EACN,KAAA,EAAO,SAAA;AAAA,EACP,IAAA,EAAM,SAAA;AAAA,EACN,IAAA,EAAM,SAAA;AAAA,EACN,SAAA,EAAW;AACb,CAAA;AAEO,SAAS,WAAW,MAAA,EAA0B;AACnD,EAAA,OAAO,SAAS,gBAAA,GAAmB,iBAAA;AACrC","file":"chunk-AZIARTGX.mjs","sourcesContent":["// src/stamps/graph-2d/editor/theme.ts\nimport type { Theme2D } from '../../../core/scene/render/types2d';\nimport { DEFAULT_THEME_2D } from '../../../core/scene/render/types2d';\n\nexport const GRAPH_THEME_LIGHT: Theme2D = {\n ...DEFAULT_THEME_2D,\n};\n\nexport const GRAPH_THEME_DARK: Theme2D = {\n ...DEFAULT_THEME_2D,\n stroke: '#f1f5f9',\n fill: '#3b82f6',\n label: '#f1f5f9',\n axis: '#475569',\n grid: '#334155',\n pointFill: '#93c5fd',\n};\n\nexport function paletteFor(isDark: boolean): Theme2D {\n return isDark ? GRAPH_THEME_DARK : GRAPH_THEME_LIGHT;\n}\n\nexport const FUNCTION_COLORS = [\n '#2563eb', '#dc2626', '#16a34a', '#9333ea',\n '#ea580c', '#0891b2', '#db2777', '#65a30d',\n] as const;\n\nexport const FUNCTION_NAMES = ['f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'] as const;\nexport const PARAMETER_NAMES = ['a', 'b', 'c', 'd', 'k', 't', 'm', 'n'] as const;\n"]}
1
+ {"version":3,"sources":["../src/stamps/graph-2d/editor/theme.ts"],"names":[],"mappings":";;;AAIO,IAAM,iBAAA,GAA6B;AAAA,EACxC,GAAG;AACL,CAAA;AAEO,IAAM,gBAAA,GAA4B;AAAA,EACvC,GAAG,gBAAA;AAAA,EACH,MAAA,EAAQ,SAAA;AAAA,EACR,IAAA,EAAM,SAAA;AAAA,EACN,KAAA,EAAO,SAAA;AAAA,EACP,IAAA,EAAM,SAAA;AAAA,EACN,IAAA,EAAM,SAAA;AAAA,EACN,SAAA,EAAW;AACb,CAAA;AAEO,SAAS,WAAW,MAAA,EAA0B;AACnD,EAAA,OAAO,SAAS,gBAAA,GAAmB,iBAAA;AACrC","file":"chunk-M42TGYT6.mjs","sourcesContent":["// src/stamps/graph-2d/editor/theme.ts\nimport type { Theme2D } from '../../../core/scene/render/types2d';\nimport { DEFAULT_THEME_2D } from '../../../core/scene/render/types2d';\n\nexport const GRAPH_THEME_LIGHT: Theme2D = {\n ...DEFAULT_THEME_2D,\n};\n\nexport const GRAPH_THEME_DARK: Theme2D = {\n ...DEFAULT_THEME_2D,\n stroke: '#f1f5f9',\n fill: '#3b82f6',\n label: '#f1f5f9',\n axis: '#475569',\n grid: '#334155',\n pointFill: '#93c5fd',\n};\n\nexport function paletteFor(isDark: boolean): Theme2D {\n return isDark ? GRAPH_THEME_DARK : GRAPH_THEME_LIGHT;\n}\n\nexport const FUNCTION_COLORS = [\n '#2563eb', '#dc2626', '#16a34a', '#9333ea',\n '#ea580c', '#0891b2', '#db2777', '#65a30d',\n] as const;\n\nexport const FUNCTION_NAMES = ['f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'] as const;\nexport const PARAMETER_NAMES = ['a', 'b', 'c', 'd', 'k', 't', 'm', 'n'] as const;\n"]}
@@ -1,11 +1,11 @@
1
1
  "use client";
2
- import { isGeometry3DCustomData, renderGeometry3DSvgFromState } from './chunk-CSCF3YFZ.mjs';
2
+ import { isGeometry3DCustomData, renderGeometry3DSvgFromState } from './chunk-ONBCUWVI.mjs';
3
3
  import { svgToStampFile } from './chunk-5UTGXHLJ.mjs';
4
4
  import { lazy } from 'react';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
6
6
 
7
7
  var Geometry3DStampHost = lazy(
8
- () => import('./host-TLIXN4CF.mjs').then((m) => ({ default: m.Geometry3DStampHost }))
8
+ () => import('./host-A64ITWVX.mjs').then((m) => ({ default: m.Geometry3DStampHost }))
9
9
  );
10
10
  var Geometry3DIcon = /* @__PURE__ */ jsxs(
11
11
  "svg",
@@ -57,5 +57,5 @@ var geometry3dStamp = {
57
57
  };
58
58
 
59
59
  export { geometry3dStamp };
60
- //# sourceMappingURL=chunk-WWMQ2VHZ.mjs.map
61
- //# sourceMappingURL=chunk-WWMQ2VHZ.mjs.map
60
+ //# sourceMappingURL=chunk-NDEZJKNY.mjs.map
61
+ //# sourceMappingURL=chunk-NDEZJKNY.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/stamps/geometry-3d/index.tsx"],"names":[],"mappings":";;;;;AAgBA,IAAM,mBAAA,GAAsB,IAAA;AAAA,EAAK,MAC/B,OAAO,qBAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,mBAAA,EAAoB,CAAE;AACnE,CAAA;AAEA,IAAM,cAAA,mBACJ,IAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,KAAA,EAAM,IAAA;AAAA,IACN,MAAA,EAAO,IAAA;AAAA,IACP,OAAA,EAAQ,WAAA;AAAA,IACR,IAAA,EAAK,MAAA;AAAA,IACL,MAAA,EAAO,cAAA;AAAA,IACP,WAAA,EAAY,KAAA;AAAA,IACZ,aAAA,EAAc,OAAA;AAAA,IACd,cAAA,EAAe,OAAA;AAAA,IACf,aAAA,EAAY,MAAA;AAAA,IAGZ,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,2BAAA,EAA4B,CAAA;AAAA,sBAEpC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,0BAAA,EAA2B,CAAA;AAAA,sBAEnC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,6BAAA,EAA8B;AAAA;AAAA;AACxC,CAAA;AAGK,IAAM,eAAA,GAAmD;AAAA,EAC9D,IAAA,EAAM,YAAA;AAAA,EACN,YAAA,EAAc,IAAA;AAAA,EACd,WAAA,EAAa,GAAA;AAAA,EACb,YAAA,EAAc,GAAA;AAAA,EACd,YAAA,EAAc,gBAAA;AAAA,EACd,WAAA,EAAa,cAAA;AAAA,EACb,aAAA,EAAe,0BAAA;AAAA,EACf,iBAAA,EAAmB,sBAAA;AAAA,EACnB,MAAM,wBAAwB,IAAA,EAAgC;AAC5D,IAAA,IAAI,CAAC,sBAAA,CAAuB,IAAI,CAAA,EAAG;AACjC,MAAA,MAAM,IAAI,MAAM,mFAA2E,CAAA;AAAA,IAC7F;AACA,IAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,4BAAA,CAA6B,KAAK,SAAS,CAAA;AACvE,IAAA,OAAO,SAAA;AAAA,EACT,CAAA;AAAA,EACA,yBAAA,EAA2B,OAAO,OAAA,KAA+C;AAC/E,IAAA,MAAM,OAAO,OAAA,CAAQ,UAAA;AACrB,IAAA,MAAM,SAAU,OAAA,CAAuC,MAAA;AACvD,IAAA,IAAI,CAAC,QAAQ,CAAC,MAAA,IAAU,CAAC,sBAAA,CAAuB,IAAI,GAAG,OAAO,IAAA;AAC9D,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,4BAAA,CAA6B,KAAK,SAAS,CAAA;AACvE,MAAA,OAAO,cAAA,CAAe,WAAW,MAAM,CAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AAAA,EACA,IAAA,EAAM;AACR","file":"chunk-WWMQ2VHZ.mjs","sourcesContent":["'use client';\n\nimport { lazy, type ReactNode } from 'react';\nimport {\n isGeometry3DCustomData,\n type Geometry3DCustomData,\n} from './serialize';\nimport { renderGeometry3DSvgFromState } from './render';\nimport type {\n RestoredStampFile,\n StampType,\n} from '../shared/types';\nimport { svgToStampFile } from '../shared/svgToStampFile';\n\nexport type { Geometry3DCustomData };\n\nconst Geometry3DStampHost = lazy(() =>\n import('./host').then((m) => ({ default: m.Geometry3DStampHost })),\n);\n\nconst Geometry3DIcon: ReactNode = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n {/* Mặt trước */}\n <path d=\"M4 9 L4 20 L14 20 L14 9 Z\" />\n {/* Mặt trên */}\n <path d=\"M4 9 L10 4 L20 4 L14 9 Z\" />\n {/* Mặt phải */}\n <path d=\"M14 9 L20 4 L20 15 L14 20 Z\" />\n </svg>\n);\n\nexport const geometry3dStamp: StampType<Geometry3DCustomData> = {\n kind: 'geometry3d',\n experimental: true,\n shortcutKey: 'd',\n toolbarLabel: 'D',\n toolbarTitle: 'Hình 3D (D)',\n toolbarIcon: Geometry3DIcon,\n toolbarTestId: 'stamp-toolbar-geometry3d',\n matchesCustomData: isGeometry3DCustomData,\n async renderSvgFromCustomData(data: unknown): Promise<string> {\n if (!isGeometry3DCustomData(data)) {\n throw new Error('geometry3dStamp.renderSvgFromCustomData: customData không phải geometry3d');\n }\n const { svgString } = await renderGeometry3DSvgFromState(data.jsonState);\n return svgString;\n },\n restoreFileFromCustomData: async (element): Promise<RestoredStampFile | null> => {\n const data = element.customData as Geometry3DCustomData | undefined;\n const fileId = (element as { fileId?: string | null }).fileId;\n if (!data || !fileId || !isGeometry3DCustomData(data)) return null;\n try {\n const { svgString } = await renderGeometry3DSvgFromState(data.jsonState);\n return svgToStampFile(svgString, fileId);\n } catch {\n return null;\n }\n },\n Host: Geometry3DStampHost,\n};\n"]}
1
+ {"version":3,"sources":["../src/stamps/geometry-3d/index.tsx"],"names":[],"mappings":";;;;;AAgBA,IAAM,mBAAA,GAAsB,IAAA;AAAA,EAAK,MAC/B,OAAO,qBAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,mBAAA,EAAoB,CAAE;AACnE,CAAA;AAEA,IAAM,cAAA,mBACJ,IAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,KAAA,EAAM,IAAA;AAAA,IACN,MAAA,EAAO,IAAA;AAAA,IACP,OAAA,EAAQ,WAAA;AAAA,IACR,IAAA,EAAK,MAAA;AAAA,IACL,MAAA,EAAO,cAAA;AAAA,IACP,WAAA,EAAY,KAAA;AAAA,IACZ,aAAA,EAAc,OAAA;AAAA,IACd,cAAA,EAAe,OAAA;AAAA,IACf,aAAA,EAAY,MAAA;AAAA,IAGZ,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,2BAAA,EAA4B,CAAA;AAAA,sBAEpC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,0BAAA,EAA2B,CAAA;AAAA,sBAEnC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,6BAAA,EAA8B;AAAA;AAAA;AACxC,CAAA;AAGK,IAAM,eAAA,GAAmD;AAAA,EAC9D,IAAA,EAAM,YAAA;AAAA,EACN,YAAA,EAAc,IAAA;AAAA,EACd,WAAA,EAAa,GAAA;AAAA,EACb,YAAA,EAAc,GAAA;AAAA,EACd,YAAA,EAAc,gBAAA;AAAA,EACd,WAAA,EAAa,cAAA;AAAA,EACb,aAAA,EAAe,0BAAA;AAAA,EACf,iBAAA,EAAmB,sBAAA;AAAA,EACnB,MAAM,wBAAwB,IAAA,EAAgC;AAC5D,IAAA,IAAI,CAAC,sBAAA,CAAuB,IAAI,CAAA,EAAG;AACjC,MAAA,MAAM,IAAI,MAAM,mFAA2E,CAAA;AAAA,IAC7F;AACA,IAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,4BAAA,CAA6B,KAAK,SAAS,CAAA;AACvE,IAAA,OAAO,SAAA;AAAA,EACT,CAAA;AAAA,EACA,yBAAA,EAA2B,OAAO,OAAA,KAA+C;AAC/E,IAAA,MAAM,OAAO,OAAA,CAAQ,UAAA;AACrB,IAAA,MAAM,SAAU,OAAA,CAAuC,MAAA;AACvD,IAAA,IAAI,CAAC,QAAQ,CAAC,MAAA,IAAU,CAAC,sBAAA,CAAuB,IAAI,GAAG,OAAO,IAAA;AAC9D,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,4BAAA,CAA6B,KAAK,SAAS,CAAA;AACvE,MAAA,OAAO,cAAA,CAAe,WAAW,MAAM,CAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AAAA,EACA,IAAA,EAAM;AACR","file":"chunk-NDEZJKNY.mjs","sourcesContent":["'use client';\n\nimport { lazy, type ReactNode } from 'react';\nimport {\n isGeometry3DCustomData,\n type Geometry3DCustomData,\n} from './serialize';\nimport { renderGeometry3DSvgFromState } from './render';\nimport type {\n RestoredStampFile,\n StampType,\n} from '../shared/types';\nimport { svgToStampFile } from '../shared/svgToStampFile';\n\nexport type { Geometry3DCustomData };\n\nconst Geometry3DStampHost = lazy(() =>\n import('./host').then((m) => ({ default: m.Geometry3DStampHost })),\n);\n\nconst Geometry3DIcon: ReactNode = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n {/* Mặt trước */}\n <path d=\"M4 9 L4 20 L14 20 L14 9 Z\" />\n {/* Mặt trên */}\n <path d=\"M4 9 L10 4 L20 4 L14 9 Z\" />\n {/* Mặt phải */}\n <path d=\"M14 9 L20 4 L20 15 L14 20 Z\" />\n </svg>\n);\n\nexport const geometry3dStamp: StampType<Geometry3DCustomData> = {\n kind: 'geometry3d',\n experimental: true,\n shortcutKey: 'd',\n toolbarLabel: 'D',\n toolbarTitle: 'Hình 3D (D)',\n toolbarIcon: Geometry3DIcon,\n toolbarTestId: 'stamp-toolbar-geometry3d',\n matchesCustomData: isGeometry3DCustomData,\n async renderSvgFromCustomData(data: unknown): Promise<string> {\n if (!isGeometry3DCustomData(data)) {\n throw new Error('geometry3dStamp.renderSvgFromCustomData: customData không phải geometry3d');\n }\n const { svgString } = await renderGeometry3DSvgFromState(data.jsonState);\n return svgString;\n },\n restoreFileFromCustomData: async (element): Promise<RestoredStampFile | null> => {\n const data = element.customData as Geometry3DCustomData | undefined;\n const fileId = (element as { fileId?: string | null }).fileId;\n if (!data || !fileId || !isGeometry3DCustomData(data)) return null;\n try {\n const { svgString } = await renderGeometry3DSvgFromState(data.jsonState);\n return svgToStampFile(svgString, fileId);\n } catch {\n return null;\n }\n },\n Host: Geometry3DStampHost,\n};\n"]}
@@ -1,8 +1,10 @@
1
1
  "use client";
2
2
  import { paletteFor } from './chunk-R5FL6S7L.mjs';
3
3
  import { renderJsxgOffscreen } from './chunk-ICR4CVOE.mjs';
4
- import { serializeScene, deserializeScene, DEFAULT_VIEW_3D } from './chunk-6V4SH4JJ.mjs';
5
- import { getKind, createStore } from './chunk-ZBJBQKJ2.mjs';
4
+ import { serializeScene, deserializeScene } from './chunk-REIJZDVZ.mjs';
5
+ import { createStore } from './chunk-IHUFOV7L.mjs';
6
+ import { DEFAULT_VIEW_3D } from './chunk-73Q7ADVL.mjs';
7
+ import { getKind } from './chunk-B4NJJZFR.mjs';
6
8
 
7
9
  // src/stamps/geometry-3d/serialize.ts
8
10
  function isGeometry3DCustomData(data) {
@@ -384,5 +386,5 @@ async function renderGeometry3DSvgFromState(jsonState) {
384
386
  }
385
387
 
386
388
  export { DEFAULT_VIEW3D, GROUND_PLANE_ATTRS, GROUND_PLANE_RANGE, JxgRenderer3D, VIEW3D_ATTRS, deserializeBoard3D, isGeometry3DCustomData, paletteFor2 as paletteFor, renderGeometry3DSvgFromState, serializeBoard3D };
387
- //# sourceMappingURL=chunk-CSCF3YFZ.mjs.map
388
- //# sourceMappingURL=chunk-CSCF3YFZ.mjs.map
389
+ //# sourceMappingURL=chunk-ONBCUWVI.mjs.map
390
+ //# sourceMappingURL=chunk-ONBCUWVI.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/stamps/geometry-3d/serialize.ts","../src/core/scene/render/types.ts","../src/core/scene/render/JxgRenderer3D.ts","../src/stamps/geometry-3d/editor/theme.ts","../src/stamps/geometry-3d/render.ts"],"names":["paletteFor"],"mappings":"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","file":"chunk-ONBCUWVI.mjs","sourcesContent":["// src/stamps/geometry-3d/serialize.ts\n//\n// Sau Tier D PR 3: customData.jsonState chỉ chứa `JSON.stringify(state)`.\n// View info (bbox3D/azimuth/elevation) nằm trong `state.meta.view` (View3D shape).\n//\n// Type guard `isGeometry3DCustomData` giữ ở đây để index.tsx + host import từ\n// 1 chỗ.\n\nimport { serializeScene, deserializeScene } from '../shared/serializeScene';\nimport type { State, View3D } from '../../core/scene';\nimport type { BaseStampCustomData } from '../shared/types';\n\nexport interface Geometry3DCustomData extends BaseStampCustomData {\n kind: 'geometry3d';\n version: 2;\n jsonState: string;\n}\n\nexport function isGeometry3DCustomData(data: unknown): data is Geometry3DCustomData {\n if (!data || typeof data !== 'object') return false;\n const d = data as Partial<Geometry3DCustomData>;\n return (\n d.kind === 'geometry3d' &&\n d.version === 2 &&\n typeof d.jsonState === 'string'\n );\n}\n\nexport function serializeBoard3D(state: State, view: View3D): string {\n const withView: State = {\n ...state,\n meta: { domain: '3d', version: state.meta.version, view },\n };\n return serializeScene(withView);\n}\n\nexport function deserializeBoard3D(raw: string): State {\n return deserializeScene('3d', raw);\n}\n","// src/core/scene/render/types.ts\nimport type { RenderCtx } from '../types';\n\nexport type Theme3D = {\n point: { size: number; color: string };\n line: { strokeWidth: number; color: string };\n plane: { fillOpacity: number; color: string };\n};\n\nexport const DEFAULT_THEME_3D: Theme3D = {\n point: { size: 4, color: '#1e40af' },\n line: { strokeWidth: 2, color: '#0f172a' },\n plane: { fillOpacity: 0.15, color: '#60a5fa' },\n};\n\nexport type RenderCtx3D = RenderCtx & {\n theme: Theme3D;\n};\n","// src/core/scene/render/JxgRenderer3D.ts\nimport type { Store } from '../store';\nimport type { State, SceneObject, RenderCtx } from '../types';\nimport { getKind } from '../registry';\nimport { DEFAULT_THEME_3D, type Theme3D } from './types';\n\nexport type JxgRenderer3DOptions = { theme?: Theme3D };\n\nexport class JxgRenderer3D {\n private view: unknown;\n private store: Store;\n private theme: Theme3D;\n private elements = new Map<string, unknown>();\n private unsubscribe: () => void;\n private disposed = false;\n\n constructor(store: Store, view: unknown, options: JxgRenderer3DOptions = {}) {\n this.store = store;\n this.view = view;\n this.theme = options.theme ?? DEFAULT_THEME_3D;\n // Subscribe first, then render current state.\n this.unsubscribe = store.subscribe((next, prev) => this.applyDiff(prev, next));\n // Render initial state (e.g. if LOAD ran before subscribe).\n this.applyDiff(undefined, store.getState());\n }\n\n private ctx(): RenderCtx {\n return {\n jxg: this.view,\n resolveRef: (id: string) => {\n const el = this.elements.get(id);\n if (el === undefined) {\n throw new Error(`[scene] resolveRef: chưa render id=\"${id}\"`);\n }\n return el;\n },\n defaults: {},\n };\n }\n\n private create(obj: SceneObject): void {\n try {\n const def = getKind(obj.kind);\n const el = def.render(obj, this.ctx());\n this.elements.set(obj.id, el);\n } catch (err) {\n console.warn(`[scene/render] không render được ${obj.kind} id=\"${obj.id}\":`, err);\n }\n }\n\n private remove(id: string): void {\n // Selection halo phải bị xoá TRƯỚC element gốc (halo tham chiếu parent).\n this.removeHalo(id);\n this.selectedIds.delete(id);\n const el = this.elements.get(id);\n if (el === undefined) return;\n try {\n this.removeFromView(el);\n } catch (err) {\n console.warn(`[scene/render] không remove được id=\"${id}\":`, err);\n }\n this.elements.delete(id);\n }\n\n private removeFromView(el: unknown): void {\n const view = this.view as { removeObject?: (e: unknown) => void };\n if (el && typeof el === 'object') {\n const asObj = el as Record<string, unknown>;\n // Composite shape: { faces: [] } for polyhedron/cylinder/cone.\n if (Array.isArray(asObj['faces'])) {\n for (const face of asObj['faces'] as unknown[]) {\n view.removeObject?.(face);\n }\n // Also remove hidden vertex points if present (_verts).\n if (Array.isArray(asObj['_verts'])) {\n for (const v of asObj['_verts'] as unknown[]) {\n view.removeObject?.(v);\n }\n }\n return;\n }\n }\n view.removeObject?.(el);\n }\n\n private applyDiff(prev: State | undefined, next: State): void {\n if (this.disposed) return;\n const prevObjs = prev?.objects ?? {};\n const nextObjs = next.objects;\n\n // Remove ids that disappeared (iterate in order of prev to respect dependencies).\n for (const id of Object.keys(prevObjs)) {\n if (!(id in nextObjs)) {\n this.remove(id);\n }\n }\n\n // Add or update in next.order (preserves dependency order).\n for (const id of next.order) {\n const cur = nextObjs[id] as SceneObject | undefined;\n if (!cur) continue;\n const old = prevObjs[id] as SceneObject | undefined;\n if (!old) {\n // New object.\n this.create(cur);\n continue;\n }\n if (Object.is(old, cur)) {\n // Unchanged (same Immer reference).\n continue;\n }\n // Changed: try update hook, otherwise remove + recreate.\n let def;\n try { def = getKind(cur.kind); } catch { continue; }\n const existing = this.elements.get(id);\n if (def.update && existing !== undefined) {\n try {\n def.update(cur, old, this.ctx(), existing);\n continue;\n } catch (err) {\n console.warn(`[scene/render] update fail, recreate id=\"${id}\":`, err);\n }\n }\n this.remove(id);\n this.create(cur);\n }\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.unsubscribe();\n this.disposed = true;\n for (const id of Array.from(this.elements.keys())) {\n this.remove(id);\n }\n }\n\n listElements(): Map<string, unknown> {\n return this.elements;\n }\n\n // Selection halo overlay (3D): multi-select, halo phía sau element gốc cho\n // các kind đơn giản (point3d, segment/line/ray/vector). Các composite shape\n // (polyhedron/cone/cylinder/plane) chưa hỗ trợ halo overlay — bỏ qua.\n private selectedIds: Set<string> = new Set();\n private haloMap: Map<string, unknown[]> = new Map();\n\n highlight(ids: string | string[] | null): void {\n if (this.disposed) return;\n const newIds = new Set<string>(\n ids == null ? [] : Array.isArray(ids) ? ids : [ids],\n );\n for (const id of this.selectedIds) {\n if (!newIds.has(id)) this.removeHalo(id);\n }\n for (const id of newIds) {\n if (!this.selectedIds.has(id) && this.elements.has(id)) this.addHalo(id);\n }\n this.selectedIds = newIds;\n try {\n (this.view as { update?: () => void }).update?.();\n } catch { /* ignore */ }\n }\n\n private removeHalo(id: string): void {\n const halos = this.haloMap.get(id);\n if (!halos) return;\n const view = this.view as { removeObject?: (e: unknown) => void };\n for (const h of halos) {\n try { view.removeObject?.(h); } catch { /* ignore */ }\n }\n this.haloMap.delete(id);\n }\n\n private addHalo(id: string): void {\n const el = this.elements.get(id) as\n | {\n elType?: string;\n getAttribute?: (k: string) => unknown;\n point1?: unknown;\n point2?: unknown;\n element2D?: { X?: () => number; Y?: () => number };\n }\n | undefined;\n if (!el) return;\n const view = this.view as {\n create?: (kind: string, parents: unknown[], attrs?: unknown) => unknown;\n };\n if (!view.create) return;\n\n const SEL_STROKE = '#475569';\n const SEL_FILL = '#cbd5e1';\n const haloBase = {\n strokeColor: SEL_STROKE,\n strokeOpacity: 0.55,\n fillColor: SEL_FILL,\n fillOpacity: 0.3,\n fixed: true,\n withLabel: false,\n name: '',\n highlight: false,\n needsRegularUpdate: true,\n };\n const halos: unknown[] = [];\n try {\n switch (el.elType) {\n case 'point3d': {\n // 3D point: tạo point3d ở cùng coords với size to + gray. Lấy coords\n // qua element2D.X/Y (JSXGraph 3D nội bộ chiếu xuống 2D plane), nhưng\n // an toàn nhất là reference element gốc và đọc Z() / coords() runtime.\n const elAny = el as unknown as {\n X?: () => number; Y?: () => number; Z?: () => number;\n getAttribute?: (k: string) => unknown;\n };\n const baseSize = (elAny.getAttribute?.('size') as number | undefined) ?? 4;\n if (typeof elAny.X === 'function' && typeof elAny.Y === 'function' && typeof elAny.Z === 'function') {\n const halo = view.create('point3d', [\n () => elAny.X?.() ?? 0,\n () => elAny.Y?.() ?? 0,\n () => elAny.Z?.() ?? 0,\n ], {\n ...haloBase,\n size: baseSize + 6,\n face: 'o',\n strokeWidth: 2,\n strokeOpacity: 0.75,\n fillOpacity: 0.25,\n });\n halos.push(halo);\n }\n break;\n }\n case 'line3d': {\n if (el.point1 && el.point2) {\n const halo = view.create('line3d', [el.point1, el.point2], {\n ...haloBase,\n strokeWidth: 9,\n straightFirst: (el.getAttribute?.('straightFirst') as boolean | undefined) ?? false,\n straightLast: (el.getAttribute?.('straightLast') as boolean | undefined) ?? false,\n });\n halos.push(halo);\n }\n break;\n }\n default:\n // Composite/plane/sphere/cone/cylinder/polygon3d/polyhedron3d:\n // halo overlay khó (composite faces, depth ordering) — bỏ qua.\n // Selection visible qua ObjectListPanel row highlight thay vì\n // halo trên canvas.\n break;\n }\n } catch (err) {\n console.warn('[scene/render/3d] halo create fail:', err);\n }\n if (halos.length) this.haloMap.set(id, halos);\n }\n}\n","import {\n paletteFor as palette2D,\n} from '../../geometry-2d/editor/theme';\nimport type { Theme2D } from '../../../core/scene/render/types2d';\n\nexport type Geom3DPalette = Theme2D & {\n view3dBg: string;\n axisX: string;\n axisY: string;\n axisZ: string;\n};\n\nexport function paletteFor(isDark: boolean): Geom3DPalette {\n const base = palette2D(isDark);\n return {\n ...base,\n view3dBg: isDark ? '#1a1a1a' : '#ffffff',\n axisX: '#d63b3b',\n axisY: '#2d8a2d',\n axisZ: '#2d6dd6',\n };\n}\n\nexport const DEFAULT_VIEW3D: {\n azimuth: number;\n elevation: number;\n bbox3D: [number, number, number, number, number, number];\n} = {\n azimuth: 0.7,\n elevation: 0.4,\n bbox3D: [-3, -3, -3, 3, 3, 3],\n};\n\nexport const VIEW3D_ATTRS = (isDark: boolean) => {\n const p = paletteFor(isDark);\n const axisLabel = (color: string) => ({\n strokeColor: color,\n fontSize: 14,\n offset: [10, 0] as [number, number],\n });\n return {\n az: { slider: { visible: false }, point2: { visible: false } },\n el: { slider: { visible: false } },\n projection: 'central' as const,\n // GeoGebra-style: axes pass through origin (0,0,0) instead of bbox border.\n axesPosition: 'center' as const,\n xAxis: {\n strokeColor: p.axisX,\n strokeWidth: 2,\n lastArrow: { type: 2, size: 8 },\n name: 'x',\n withLabel: true,\n label: axisLabel(p.axisX),\n },\n yAxis: {\n strokeColor: p.axisY,\n strokeWidth: 2,\n lastArrow: { type: 2, size: 8 },\n name: 'y',\n withLabel: true,\n label: axisLabel(p.axisY),\n },\n zAxis: {\n strokeColor: p.axisZ,\n strokeWidth: 2,\n lastArrow: { type: 2, size: 8 },\n name: 'z',\n withLabel: true,\n label: axisLabel(p.axisZ),\n },\n // GeoGebra-style: hide ALL bbox wall planes; the XY ground plane is drawn\n // explicitly at z=0 via the helper below (so it coincides with Ox/Oy).\n xPlaneRear: { visible: false, mesh3d: { visible: false } },\n yPlaneRear: { visible: false, mesh3d: { visible: false } },\n zPlaneRear: { visible: false, mesh3d: { visible: false } },\n };\n};\n\nexport const GROUND_PLANE_ATTRS = (isDark: boolean) => ({\n fillColor: isDark ? '#2a2a2a' : '#e6e6e6',\n fillOpacity: isDark ? 0.5 : 0.55,\n strokeColor: isDark ? '#3a3a3a' : '#cfcfcf',\n strokeOpacity: 0.7,\n strokeWidth: 1,\n fixed: true,\n highlight: false,\n withLabel: false,\n layer: 0,\n});\n\n/** XY ground plane extent (square around origin in user units). */\nexport const GROUND_PLANE_RANGE: [number, number] = [-3, 3];\n","\"use client\";\n\nimport { deserializeBoard3D } from './serialize';\nimport { createStore } from '../../core/scene';\nimport { DEFAULT_VIEW_3D, type View3D } from '../../core/scene/types';\nimport { JxgRenderer3D } from '../../core/scene/render/JxgRenderer3D';\nimport { GROUND_PLANE_ATTRS, GROUND_PLANE_RANGE, VIEW3D_ATTRS } from './editor/theme';\nimport { renderJsxgOffscreen } from '../shared/jxgOffscreenRender';\n\nexport interface RenderResult {\n svgString: string;\n width: number;\n height: number;\n}\n\nconst OUTPUT_WIDTH = 1024;\nconst OUTPUT_HEIGHT = 768;\nconst BBOX_2D: [number, number, number, number] = [-6, 6, 6, -6];\n\n \ntype JxgObj = any;\n\nexport async function renderGeometry3DSvgFromState(jsonState: string): Promise<RenderResult> {\n const state = deserializeBoard3D(jsonState);\n const view3DInfo: View3D = state.meta.domain === '3d' ? state.meta.view : DEFAULT_VIEW_3D;\n\n const { svgString } = await renderJsxgOffscreen({\n bbox: BBOX_2D,\n dims: { width: OUTPUT_WIDTH, height: OUTPUT_HEIGHT },\n axis: false,\n grid: false,\n keepAspectRatio: true,\n applyOptions: (JXG) => {\n JXG.Options.text.display = 'internal';\n },\n setup: (board) => {\n const baseAttrs = VIEW3D_ATTRS(false);\n const view: JxgObj = (board as { create: (k: string, p: unknown[], a: unknown) => JxgObj }).create(\n 'view3d',\n [\n [-5, -5],\n [10, 10],\n [\n [view3DInfo.bbox3D[0], view3DInfo.bbox3D[3]],\n [view3DInfo.bbox3D[1], view3DInfo.bbox3D[4]],\n [view3DInfo.bbox3D[2], view3DInfo.bbox3D[5]],\n ],\n ],\n {\n ...baseAttrs,\n az: { ...baseAttrs.az, slider: { ...baseAttrs.az.slider, start: view3DInfo.azimuth } },\n el: { ...baseAttrs.el, slider: { ...baseAttrs.el.slider, start: view3DInfo.elevation } },\n },\n );\n\n try {\n \n const v = view as any;\n v?.az_slide?.setValue?.(view3DInfo.azimuth);\n v?.el_slide?.setValue?.(view3DInfo.elevation);\n v?.board?.update?.();\n } catch {\n /* older JSXGraph may not expose az_slide on view3d */\n }\n\n try {\n (view as { create: (k: string, p: unknown[], a: unknown) => JxgObj }).create(\n 'plane3d',\n [\n [0, 0, 0],\n [1, 0, 0],\n [0, 1, 0],\n GROUND_PLANE_RANGE,\n GROUND_PLANE_RANGE,\n ],\n GROUND_PLANE_ATTRS(false),\n );\n } catch {\n /* swallow */\n }\n\n const store = createStore(state);\n const renderer = new JxgRenderer3D(store, view);\n\n try {\n \n (view as any)?.board?.update?.();\n } catch {\n /* swallow */\n }\n\n return renderer;\n },\n postProcessSvg: (clone) => {\n clone.setAttribute('width', String(OUTPUT_WIDTH));\n clone.setAttribute('height', String(OUTPUT_HEIGHT));\n },\n });\n\n return { svgString, width: OUTPUT_WIDTH, height: OUTPUT_HEIGHT };\n}\n"]}
@@ -1,38 +1,9 @@
1
1
  "use client";
2
- import { registerKind, compile, validate } from './chunk-ZBJBQKJ2.mjs';
2
+ import { compile, validate } from './chunk-IHUFOV7L.mjs';
3
+ import { createEmptyState } from './chunk-73Q7ADVL.mjs';
4
+ import { registerKind } from './chunk-B4NJJZFR.mjs';
3
5
  import * as React from 'react';
4
6
 
5
- // src/core/scene/types.ts
6
- var DEFAULT_VIEW_2D = {
7
- bbox: [-10, 10, 10, -10],
8
- showAxis: false,
9
- showGrid: false
10
- };
11
- var DEFAULT_VIEW_3D = {
12
- bbox3D: [-5, 5, -5, 5, -5, 5],
13
- azimuth: 60,
14
- elevation: 30
15
- };
16
- var DEFAULT_VIEW_GRAPH2D = {
17
- xMin: -10,
18
- xMax: 10,
19
- yMin: -10,
20
- yMax: 10,
21
- showAxis: true,
22
- showGrid: true
23
- };
24
- function createEmptyState(domain) {
25
- const base = { objects: {}, order: [], counter: 0 };
26
- switch (domain) {
27
- case "2d":
28
- return { ...base, meta: { domain: "2d", version: 1, view: DEFAULT_VIEW_2D } };
29
- case "3d":
30
- return { ...base, meta: { domain: "3d", version: 1, view: DEFAULT_VIEW_3D } };
31
- case "graph2d":
32
- return { ...base, meta: { domain: "graph2d", version: 1, view: DEFAULT_VIEW_GRAPH2D } };
33
- }
34
- }
35
-
36
7
  // src/core/scene/selectors.ts
37
8
  function listObjects(state) {
38
9
  return state.order.map((id) => state.objects[id]).filter((o) => o !== void 0);
@@ -1796,6 +1767,6 @@ function deserializeScene(domain, raw) {
1796
1767
  return createEmptyState(domain);
1797
1768
  }
1798
1769
 
1799
- export { DEFAULT_VIEW_2D, DEFAULT_VIEW_3D, createEmptyState, deserializeScene, listObjects, nextLabel, serializeScene, useEditorState };
1800
- //# sourceMappingURL=chunk-6V4SH4JJ.mjs.map
1801
- //# sourceMappingURL=chunk-6V4SH4JJ.mjs.map
1770
+ export { deserializeScene, listObjects, nextLabel, serializeScene, useEditorState };
1771
+ //# sourceMappingURL=chunk-REIJZDVZ.mjs.map
1772
+ //# sourceMappingURL=chunk-REIJZDVZ.mjs.map