@xom11/whiteboard 0.30.0 → 0.31.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 (88) hide show
  1. package/dist/ai.d.mts +226 -32
  2. package/dist/ai.d.ts +226 -32
  3. package/dist/ai.js +5126 -351
  4. package/dist/ai.js.map +1 -1
  5. package/dist/ai.mjs +4970 -352
  6. package/dist/ai.mjs.map +1 -1
  7. package/dist/catalog.json +5 -5
  8. package/dist/{chunk-V3YJ6JFL.mjs → chunk-44JY2AKC.mjs} +3 -3
  9. package/dist/{chunk-V3YJ6JFL.mjs.map → chunk-44JY2AKC.mjs.map} +1 -1
  10. package/dist/{chunk-XVVLT6B3.mjs → chunk-BMYC2ILT.mjs} +4 -4
  11. package/dist/{chunk-XVVLT6B3.mjs.map → chunk-BMYC2ILT.mjs.map} +1 -1
  12. package/dist/{chunk-PPKHCRRE.mjs → chunk-C76SOFXF.mjs} +3 -3
  13. package/dist/{chunk-PPKHCRRE.mjs.map → chunk-C76SOFXF.mjs.map} +1 -1
  14. package/dist/{chunk-IHUFOV7L.mjs → chunk-CH6SFONH.mjs} +15 -3
  15. package/dist/chunk-CH6SFONH.mjs.map +1 -0
  16. package/dist/{chunk-SF3U7ZF4.mjs → chunk-DWIEVCGK.mjs} +180 -15
  17. package/dist/chunk-DWIEVCGK.mjs.map +1 -0
  18. package/dist/{chunk-SZDAS7LK.mjs → chunk-IE2GGHNF.mjs} +131 -81
  19. package/dist/chunk-IE2GGHNF.mjs.map +1 -0
  20. package/dist/{chunk-ZTQBUKLJ.mjs → chunk-JJ4FPCBE.mjs} +142 -22
  21. package/dist/chunk-JJ4FPCBE.mjs.map +1 -0
  22. package/dist/{chunk-QRUAEXLR.mjs → chunk-K5BS2H56.mjs} +5 -5
  23. package/dist/{chunk-QRUAEXLR.mjs.map → chunk-K5BS2H56.mjs.map} +1 -1
  24. package/dist/{chunk-BNBOIDO5.mjs → chunk-K7VJU7LQ.mjs} +3 -3
  25. package/dist/{chunk-BNBOIDO5.mjs.map → chunk-K7VJU7LQ.mjs.map} +1 -1
  26. package/dist/{chunk-H22OZYTW.mjs → chunk-KOXOC2FI.mjs} +48 -39
  27. package/dist/chunk-KOXOC2FI.mjs.map +1 -0
  28. package/dist/{chunk-CXHNVYMD.mjs → chunk-KWDBVLST.mjs} +5 -5
  29. package/dist/{chunk-CXHNVYMD.mjs.map → chunk-KWDBVLST.mjs.map} +1 -1
  30. package/dist/{chunk-OQIQNKPQ.mjs → chunk-LTLLQUMN.mjs} +4 -4
  31. package/dist/{chunk-OQIQNKPQ.mjs.map → chunk-LTLLQUMN.mjs.map} +1 -1
  32. package/dist/{chunk-QGNU34T7.mjs → chunk-QLQ4MJNO.mjs} +10 -4
  33. package/dist/chunk-QLQ4MJNO.mjs.map +1 -0
  34. package/dist/{chunk-BU5KLO3P.mjs → chunk-T3N4BSJV.mjs} +4 -4
  35. package/dist/{chunk-BU5KLO3P.mjs.map → chunk-T3N4BSJV.mjs.map} +1 -1
  36. package/dist/{chunk-5JM35CXV.mjs → chunk-TMRFSOM7.mjs} +4 -4
  37. package/dist/{chunk-5JM35CXV.mjs.map → chunk-TMRFSOM7.mjs.map} +1 -1
  38. package/dist/geometry-2d.d.mts +1 -1
  39. package/dist/geometry-2d.d.ts +1 -1
  40. package/dist/geometry-2d.js +449 -172
  41. package/dist/geometry-2d.js.map +1 -1
  42. package/dist/geometry-2d.mjs +5 -5
  43. package/dist/geometry-3d.d.mts +1 -1
  44. package/dist/geometry-3d.d.ts +1 -1
  45. package/dist/geometry-3d.js +172 -22
  46. package/dist/geometry-3d.js.map +1 -1
  47. package/dist/geometry-3d.mjs +4 -4
  48. package/dist/graph-2d.d.mts +1 -1
  49. package/dist/graph-2d.d.ts +1 -1
  50. package/dist/graph-2d.js +307 -100
  51. package/dist/graph-2d.js.map +1 -1
  52. package/dist/graph-2d.mjs +7 -7
  53. package/dist/{host-HOSJHQ5H.mjs → host-4FIUNIDQ.mjs} +13 -12
  54. package/dist/host-4FIUNIDQ.mjs.map +1 -0
  55. package/dist/{host-2ISGVO7O.mjs → host-4ZB4XD4S.mjs} +9 -8
  56. package/dist/host-4ZB4XD4S.mjs.map +1 -0
  57. package/dist/{host-ZQCDAT6O.mjs → host-H2IGOKJU.mjs} +3 -3
  58. package/dist/{host-ZQCDAT6O.mjs.map → host-H2IGOKJU.mjs.map} +1 -1
  59. package/dist/{host-3UFGFMJ2.mjs → host-KMWP7KBT.mjs} +90 -43
  60. package/dist/host-KMWP7KBT.mjs.map +1 -0
  61. package/dist/index.d.mts +2 -2
  62. package/dist/index.d.ts +2 -2
  63. package/dist/index.js +453 -174
  64. package/dist/index.js.map +1 -1
  65. package/dist/index.mjs +21 -21
  66. package/dist/latex.d.mts +1 -1
  67. package/dist/latex.d.ts +1 -1
  68. package/dist/latex.js +8 -2
  69. package/dist/latex.js.map +1 -1
  70. package/dist/latex.mjs +1 -1
  71. package/dist/render-NMS7OAV6.mjs +10 -0
  72. package/dist/{render-ZX2O2IK7.mjs.map → render-NMS7OAV6.mjs.map} +1 -1
  73. package/dist/serialize-PGHQZEPV.mjs +9 -0
  74. package/dist/{serialize-N4G6RFBB.mjs.map → serialize-PGHQZEPV.mjs.map} +1 -1
  75. package/dist/{types-C3FjpoUi.d.ts → types-tePd94vW.d.mts} +8 -0
  76. package/dist/{types-C3FjpoUi.d.mts → types-tePd94vW.d.ts} +8 -0
  77. package/package.json +1 -1
  78. package/dist/chunk-H22OZYTW.mjs.map +0 -1
  79. package/dist/chunk-IHUFOV7L.mjs.map +0 -1
  80. package/dist/chunk-QGNU34T7.mjs.map +0 -1
  81. package/dist/chunk-SF3U7ZF4.mjs.map +0 -1
  82. package/dist/chunk-SZDAS7LK.mjs.map +0 -1
  83. package/dist/chunk-ZTQBUKLJ.mjs.map +0 -1
  84. package/dist/host-2ISGVO7O.mjs.map +0 -1
  85. package/dist/host-3UFGFMJ2.mjs.map +0 -1
  86. package/dist/host-HOSJHQ5H.mjs.map +0 -1
  87. package/dist/render-ZX2O2IK7.mjs +0 -10
  88. package/dist/serialize-N4G6RFBB.mjs +0 -9
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/stamps/latex/editor/LeftPanel.tsx","../src/stamps/latex/editor/EditorPopover.tsx","../src/stamps/latex/host.tsx"],"names":["EditorPopover","jsxs","jsx","forwardRef","LatexStampHost","useRef","useState","useCallback","useImperativeHandle","Fragment"],"mappings":";;;;;;;;AAgBA,SAAS,KAAA,CAAM,EAAE,KAAA,EAAO,IAAA,EAAM,SAAS,QAAA,EAAU,QAAA,EAAU,UAAA,EAAY,aAAA,EAAc,EAAe;AAClG,EAAA,MAAM,cAAc,QAAA,GAChB;AAAA,IACE,oBAAA,EAAsB,MAAA;AAAA,IACtB,mBAAA,EAAqB,aAAa,MAAA,GAAS;AAAA,MAE7C,EAAC;AACL,EAAA,MAAM,oBAAoB,MAAM;AAC9B,IAAA,IAAI,UAAU,aAAA,IAAgB;AAAA,SACzB,OAAA,EAAQ;AAAA,EACf,CAAA;AACA,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,QAAA,IAAY,UAAA,oBACX,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAU,uBAAA;AAAA,QACV,aAAA,EAAe,aAAA;AAAA,QACf,aAAA,EAAY;AAAA;AAAA,KACd;AAAA,oBAEF,IAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,eAAA;AAAA,QACL,YAAA,EAAY,KAAA;AAAA,QACZ,aAAA,EAAa,QAAA,IAAY,CAAC,UAAA,GAAa,MAAA,GAAS,MAAA;AAAA,QAChD,aAAA,EAAY,kBAAA;AAAA,QACZ,iBAAA,EAAgB,MAAA;AAAA,QACf,GAAG,WAAA;AAAA,QACJ,SAAA,EACE,WACI,gFAAA,GACA,8IAAA;AAAA,QAGN,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,QAAA,EAAA,EAAO,WAAU,+GAAA,EAChB,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,IAAA,EAAA,EAAG,WAAU,8DAAA,EACZ,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,wBAAA,EAA0B,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,cAC9C;AAAA,aAAA,EACH,CAAA;AAAA,4BACA,GAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,OAAA,EAAS,iBAAA;AAAA,gBACT,YAAA,EAAY,WAAW,wCAAA,GAAsB,cAAA;AAAA,gBAC7C,SAAA,EAAU,+EAAA;AAAA,gBAEV,+BAAC,KAAA,EAAA,EAAI,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,MAAK,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAK,MAAA,EAAO,QAAO,cAAA,EAAe,WAAA,EAAY,KAAI,aAAA,EAAc,OAAA,EAAQ,gBAAe,OAAA,EACrI,QAAA,EAAA;AAAA,kCAAA,GAAA,CAAC,MAAA,EAAA,EAAK,IAAG,GAAA,EAAI,EAAA,EAAG,KAAI,EAAA,EAAG,IAAA,EAAK,IAAG,IAAA,EAAK,CAAA;AAAA,kCACpC,GAAA,CAAC,UAAK,EAAA,EAAG,IAAA,EAAK,IAAG,GAAA,EAAI,EAAA,EAAG,GAAA,EAAI,EAAA,EAAG,IAAA,EAAK;AAAA,iBAAA,EACtC;AAAA;AAAA;AACF,WAAA,EACF,CAAA;AAAA,0BACA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8CAAA,EAAgD,QAAA,EAAS;AAAA;AAAA;AAAA;AAC1E,GAAA,EACF,CAAA;AAEJ;AAEA,SAAS,OAAA,CAAQ,EAAE,KAAA,EAAO,QAAA,EAAS,EAAiD;AAClF,EAAA,4BACG,SAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,0EAAA,EACX,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,IACC;AAAA,GAAA,EACH,CAAA;AAEJ;AAoBA,IAAM,QAAA,GAAqD;AAAA,EACzD;AAAA,IACE,KAAA,EAAO,sCAAA;AAAA,IACP,KAAA,EAAO;AAAA,MACL,EAAE,KAAA,EAAO,iBAAA,EAAW,OAAA,EAAS,UAAA,EAAO,SAAS,cAAA,EAAe;AAAA,MAC5D,EAAE,KAAA,EAAO,oBAAA,EAAY,OAAA,EAAS,OAAA,EAAM,SAAS,MAAA,EAAO;AAAA,MACpD,EAAE,KAAA,EAAO,kBAAA,EAAU,OAAA,EAAS,SAAA,EAAM,SAAS,MAAA,EAAO;AAAA,MAClD,EAAE,KAAA,EAAO,UAAA,EAAO,OAAA,EAAS,SAAA,EAAM,SAAS,WAAA,EAAY;AAAA,MACpD,EAAE,KAAA,EAAO,YAAA,EAAS,OAAA,EAAS,eAAA,EAAO,SAAS,cAAA;AAAe;AAC5D,GACF;AAAA,EACA;AAAA,IACE,KAAA,EAAO,6BAAA;AAAA,IACP,KAAA,EAAO;AAAA,MACL,EAAE,KAAA,EAAO,WAAA,EAAQ,OAAA,EAAS,QAAA,EAAK,SAAS,iBAAA,EAAkB;AAAA,MAC1D,EAAE,KAAA,EAAO,SAAA,EAAQ,OAAA,EAAS,QAAA,EAAK,SAAS,kBAAA,EAAmB;AAAA,MAC3D,EAAE,KAAA,EAAO,iBAAA,EAAa,OAAA,EAAS,QAAA,EAAK,SAAS,eAAA,EAAgB;AAAA,MAC7D,EAAE,KAAA,EAAO,oBAAA,EAAY,OAAA,EAAS,KAAA,EAAO,SAAS,kBAAA;AAAmB;AACnE,GACF;AAAA,EACA;AAAA,IACE,KAAA,EAAO,iBAAA;AAAA,IACP,KAAA,EAAO;AAAA,MACL,EAAE,KAAA,EAAO,QAAA,EAAK,OAAA,EAAS,QAAA,EAAK,SAAS,SAAA,EAAU;AAAA,MAC/C,EAAE,KAAA,EAAO,QAAA,EAAK,OAAA,EAAS,QAAA,EAAK,SAAS,QAAA,EAAS;AAAA,MAC9C,EAAE,KAAA,EAAO,QAAA,EAAK,OAAA,EAAS,QAAA,EAAK,SAAS,MAAA,EAAO;AAAA,MAC5C,EAAE,KAAA,EAAO,QAAA,EAAK,OAAA,EAAS,QAAA,EAAK,SAAS,SAAA,EAAU;AAAA,MAC/C,EAAE,KAAA,EAAO,QAAA,EAAK,OAAA,EAAS,QAAA,EAAK,SAAS,OAAA,EAAQ;AAAA,MAC7C,EAAE,KAAA,EAAO,QAAA,EAAK,OAAA,EAAS,QAAA,EAAK,SAAS,OAAA,EAAQ;AAAA,MAC7C,EAAE,KAAA,EAAO,QAAA,EAAK,OAAA,EAAS,QAAA,EAAK,SAAS,OAAA,EAAQ;AAAA,MAC7C,EAAE,KAAA,EAAO,QAAA,EAAK,OAAA,EAAS,QAAA,EAAK,SAAS,SAAA,EAAU;AAAA,MAC/C,EAAE,KAAA,EAAO,QAAA,EAAK,OAAA,EAAS,QAAA,EAAK,SAAS,MAAA;AAAO;AAC9C;AAEJ,CAAA;AAEO,SAAS,SAAA,CAAU;AAAA,EACxB,WAAA;AAAA,EACA,mBAAA;AAAA,EACA,eAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,EAAwB;AACtB,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,yBAAA;AAAA,MACN,IAAA,EAAK,QAAA;AAAA,MACL,OAAA;AAAA,MACA,QAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAA;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,WAAQ,KAAA,EAAM,0CAAA,EACb,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,0BAAA,EACb,QAAA,EAAA;AAAA,0BAAA,IAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,OAAA,EAAS,MAAM,mBAAA,CAAoB,KAAK,CAAA;AAAA,cACxC,gBAAc,CAAC,WAAA;AAAA,cACf,SAAA,EAAW;AAAA,gBACT,kDAAA;AAAA,gBACA,CAAC,cACG,2EAAA,GACA;AAAA,eACN,CAAE,KAAK,GAAG,CAAA;AAAA,cAEV,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mBAAA,EAAoB,QAAA,EAAA,QAAA,EAAM,CAAA;AAAA,gCAC1C,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kCAAA,EAAmC,QAAA,EAAA,SAAA,EAAO;AAAA;AAAA;AAAA,WAC5D;AAAA,0BACA,IAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,OAAA,EAAS,MAAM,mBAAA,CAAoB,IAAI,CAAA;AAAA,cACvC,cAAA,EAAc,WAAA;AAAA,cACd,SAAA,EAAW;AAAA,gBACT,kDAAA;AAAA,gBACA,cACI,2EAAA,GACA;AAAA,eACN,CAAE,KAAK,GAAG,CAAA;AAAA,cAEV,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mBAAA,EAAoB,QAAA,EAAA,OAAA,EAAK,CAAA;AAAA,gCACzC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kCAAA,EAAmC,QAAA,EAAA,WAAA,EAAS;AAAA;AAAA;AAAA;AAC9D,SAAA,EACF,CAAA,EACF,CAAA;AAAA,QAEC,SAAS,GAAA,CAAI,CAAC,KAAA,qBACb,GAAA,CAAC,WAA0B,KAAA,EAAO,KAAA,CAAM,KAAA,EACtC,QAAA,kBAAA,GAAA,CAAC,SAAI,SAAA,EAAU,sBAAA,EACZ,gBAAM,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,qBAChB,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YAEC,IAAA,EAAK,QAAA;AAAA,YACL,gBAAc,CAAA,CAAE,OAAA;AAAA,YAChB,OAAA,EAAS,MAAM,eAAA,CAAgB,CAAA,CAAE,OAAO,CAAA;AAAA,YACxC,OAAO,CAAA,CAAE,OAAA;AAAA,YACT,SAAA,EAAU,0JAAA;AAAA,YAET,QAAA,EAAA,CAAA,CAAE;AAAA,WAAA;AAAA,UAPE,CAAA,CAAE;AAAA,SASV,CAAA,EACH,CAAA,EAAA,EAdY,KAAA,CAAM,KAepB,CACD,CAAA;AAAA,4BAEA,OAAA,EAAA,EAAQ,KAAA,EAAM,oBACb,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,iDAAA,EACb,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,gCAAA,EACd,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qEAAA,EAAsE,QAAA,EAAA,OAAA,EAAK,CAAA;AAAA,YAAM;AAAA,WAAA,EAElG,CAAA;AAAA,0BACA,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gCAAA,EACd,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qEAAA,EAAsE,QAAA,EAAA,KAAA,EAAG,CAAA;AAAA,YAAM;AAAA,WAAA,EAEhG;AAAA,SAAA,EACF,CAAA,EACF;AAAA;AAAA;AAAA,GACF;AAEJ;AClLA,IAAM,WAAA,GAAc,GAAA;AAEb,IAAM,aAAA,GAAgB,UAAA,CAAuC,SAASA,cAAAA,CAC3E;AAAA,EACE,CAAA;AAAA,EACA,CAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA,EAAa,qBAAA;AAAA,EACb,mBAAA;AAAA,EACA,aAAA,GAAgB,KAAA;AAAA,EAChB,QAAA,GAAW,KAAA;AAAA,EACX;AACF,CAAA,EACA,GAAA,EACA;AACA,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,YAAY,CAAA;AAC/C,EAAA,MAAM,CAAC,mBAAmB,CAAA,GAAI,QAAA,CAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,cAAc,qBAAA,IAAyB,mBAAA;AAI7C,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAwB,IAAI,CAAA;AAChE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AACtD,EAAA,MAAM,WAAA,GAAc,OAA6C,IAAI,CAAA;AACrE,EAAA,MAAM,QAAA,GAAW,OAAyB,IAAI,CAAA;AAE9C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,WAAA,CAAY,OAAA,EAAS,YAAA,CAAa,WAAA,CAAY,OAAO,CAAA;AACzD,IAAA,WAAA,CAAY,OAAA,GAAU,WAAW,YAAY;AAC3C,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,MAAM,gBAAA,CAAiB,KAAA,EAAO,WAAW,CAAA;AACrD,QAAA,aAAA,CAAc,GAAG,CAAA;AACjB,QAAA,QAAA,CAAS,IAAI,CAAA;AAAA,MACf,SAAS,GAAA,EAAK;AACZ,QAAA,aAAA,CAAc,IAAI,CAAA;AAClB,QAAA,QAAA,CAAU,IAAc,OAAO,CAAA;AAAA,MACjC;AAAA,IACF,GAAG,WAAW,CAAA;AACd,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,WAAA,CAAY,OAAA,EAAS,YAAA,CAAa,WAAA,CAAY,OAAO,CAAA;AAAA,IAC3D,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,KAAA,EAAO,WAAW,CAAC,CAAA;AAEvB,EAAA,MAAM,YAAA,GAAe,YAAY,MAAM;AACrC,IAAA,IAAI,CAAC,UAAA,EAAY;AACjB,IAAA,QAAA,CAAS,UAAA,EAAY,OAAO,WAAW,CAAA;AAAA,EACzC,GAAG,CAAC,UAAA,EAAY,KAAA,EAAO,WAAA,EAAa,QAAQ,CAAC,CAAA;AAE7C,EAAA,MAAM,aAAA,GAAgB,WAAA;AAAA,IACpB,CAAC,CAAA,KAA2B;AAC1B,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,QAAA,EAAU,OAAA,EAAQ;AAChC,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,OAAA,IAAW,CAAC,EAAE,QAAA,EAAU;AACpC,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,YAAA,EAAa;AAAA,MACf;AAAA,IACF,CAAA;AAAA,IACA,CAAC,SAAS,YAAY;AAAA,GACxB;AAGA,EAAA,mBAAA;AAAA,IACE,GAAA;AAAA,IACA,OAAO;AAAA,MACL,cAAA,EAAgB,CAAC,OAAA,KAAoB;AACnC,QAAA,MAAM,KAAK,QAAA,CAAS,OAAA;AACpB,QAAA,IAAI,CAAC,EAAA,EAAI;AACP,UAAA,QAAA,CAAS,CAAC,CAAA,KAAM,CAAA,GAAI,OAAO,CAAA;AAC3B,UAAA;AAAA,QACF;AACA,QAAA,MAAM,KAAA,GAAQ,EAAA,CAAG,cAAA,IAAkB,KAAA,CAAM,MAAA;AACzC,QAAA,MAAM,GAAA,GAAM,EAAA,CAAG,YAAA,IAAgB,KAAA,CAAM,MAAA;AACrC,QAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA,GAAI,OAAA,GAAU,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA;AAC9D,QAAA,QAAA,CAAS,IAAI,CAAA;AACb,QAAA,qBAAA,CAAsB,MAAM;AAC1B,UAAA,EAAA,CAAG,KAAA,EAAM;AACT,UAAA,MAAM,GAAA,GAAM,QAAQ,OAAA,CAAQ,MAAA;AAC5B,UAAA,IAAI;AACF,YAAA,EAAA,CAAG,iBAAA,CAAkB,KAAK,GAAG,CAAA;AAAA,UAC/B,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACF,CAAC,CAAA;AAAA,MACH,CAAA;AAAA,MACA,UAAA,EAAY,MAAM,KAAA,CAAM,IAAA,EAAK,CAAE,SAAS,CAAA,IAAK,CAAC,CAAC,UAAA,IAAc,CAAC,KAAA;AAAA,MAC9D,WAAW,MAAM;AACf,QAAA,IAAI,CAAC,UAAA,IAAc,KAAA,IAAS,CAAC,KAAA,CAAM,IAAA,IAAQ,OAAO,KAAA;AAClD,QAAA,QAAA,CAAS,UAAA,EAAY,OAAO,WAAW,CAAA;AACvC,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,KACF,CAAA;AAAA,IACA,CAAC,KAAA,EAAO,UAAA,EAAY,KAAA,EAAO,aAAa,QAAQ;AAAA,GAClD;AAGA,EAAA,MAAM,gBAAA,GAAmB,CAAA,GAAI,CAAA,IAAK,CAAA,GAAI,CAAA;AACtC,EAAA,MAAM,YAAA,GAAoC,WACtC,EAAE,QAAA,EAAU,SAAS,KAAA,EAAO,CAAA,EAAG,QAAQ,EAAA,EAAG,GAC1C,mBACE,EAAE,QAAA,EAAU,YAAY,GAAA,EAAK,CAAA,EAAG,MAAM,CAAA,EAAG,MAAA,EAAQ,IAAG,GACpD;AAAA,IACE,QAAA,EAAU,UAAA;AAAA,IACV,GAAA,EAAK,KAAA;AAAA,IACL,IAAA,EAAM,gBAAgB,mBAAA,GAAsB,KAAA;AAAA,IAC5C,SAAA,EAAW,uBAAA;AAAA,IACX,MAAA,EAAQ;AAAA,GACV;AAEN,EAAA,uBACEC,IAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,YAAA;AAAA,MACP,iBAAA,EAAgB,MAAA;AAAA,MAChB,oBAAA,EAAoB,WAAW,MAAA,GAAS,MAAA;AAAA,MACxC,SAAA,EACE,WACI,sCAAA,GACA,gHAAA;AAAA,MAEN,IAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAW,mCAAA;AAAA,MAEX,QAAA,EAAA;AAAA,wBAAAA,KAAC,QAAA,EAAA,EAAO,SAAA,EAAW,wHAAwH,QAAA,GAAW,EAAA,GAAK,eAAe,CAAA,CAAA,EACvK,QAAA,EAAA;AAAA,UAAA,QAAA,oBACCC,GAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,OAAA,EAAS,YAAA;AAAA,cACT,YAAA,EAAW,2BAAA;AAAA,cACX,SAAA,EAAU,8FAAA;AAAA,cAEV,0BAAAD,IAAAA,CAAC,KAAA,EAAA,EAAI,OAAM,IAAA,EAAK,MAAA,EAAO,MAAK,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAK,MAAA,EAAO,QAAO,cAAA,EAAe,WAAA,EAAY,KAAI,aAAA,EAAc,OAAA,EAAQ,gBAAe,OAAA,EACrI,QAAA,EAAA;AAAA,gCAAAC,GAAAA,CAAC,UAAK,EAAA,EAAG,GAAA,EAAI,IAAG,GAAA,EAAI,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,GAAA,EAAI,CAAA;AAAA,gCACnCA,GAAAA,CAAC,MAAA,EAAA,EAAK,EAAA,EAAG,GAAA,EAAI,IAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,CAAA;AAAA,gCACrCA,GAAAA,CAAC,MAAA,EAAA,EAAK,EAAA,EAAG,GAAA,EAAI,IAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK;AAAA,eAAA,EACvC;AAAA;AAAA,WACF;AAAA,0BAEFD,IAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,sDAAA,EACZ,QAAA,EAAA;AAAA,4BAAAC,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,wBAAA,EAAyB,QAAA,EAAA,QAAA,EAAC,CAAA;AAAA,YAAO;AAAA,WAAA,EAEnD,CAAA;AAAA,UACC,4BACCA,GAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,OAAA,EAAS,YAAA;AAAA,cACT,QAAA,EAAU,CAAC,UAAA,IAAc,CAAC,CAAC,KAAA;AAAA,cAC3B,aAAA,EAAY,yBAAA;AAAA,cACZ,SAAA,EAAU,wGAAA;AAAA,cACX,QAAA,EAAA;AAAA;AAAA,WAED;AAAA,0BAEFA,GAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAS,OAAA;AAAA,cACT,YAAA,EAAW,cAAA;AAAA,cACX,SAAA,EAAU,sFAAA;AAAA,cAEV,0BAAAD,IAAAA,CAAC,KAAA,EAAA,EAAI,OAAM,IAAA,EAAK,MAAA,EAAO,MAAK,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAK,MAAA,EAAO,QAAO,cAAA,EAAe,WAAA,EAAY,KAAI,aAAA,EAAc,OAAA,EAAQ,gBAAe,OAAA,EACrI,QAAA,EAAA;AAAA,gCAAAC,GAAAA,CAAC,UAAK,EAAA,EAAG,GAAA,EAAI,IAAG,GAAA,EAAI,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,CAAA;AAAA,gCACpCA,GAAAA,CAAC,MAAA,EAAA,EAAK,EAAA,EAAG,IAAA,EAAK,IAAG,GAAA,EAAI,EAAA,EAAG,GAAA,EAAI,EAAA,EAAG,IAAA,EAAK;AAAA,eAAA,EACtC;AAAA;AAAA;AACF,SAAA,EACF,CAAA;AAAA,wBACAD,KAAC,KAAA,EAAA,EAAI,SAAA,EAAW,gBAAgB,QAAA,GAAW,+BAAA,GAAkC,EAAE,CAAA,CAAA,EAC7E,QAAA,EAAA;AAAA,0BAAAC,GAAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,GAAA,EAAK,QAAA;AAAA,cACL,IAAA,EAAK,MAAA;AAAA,cACL,IAAA,EAAK,SAAA;AAAA,cACL,KAAA;AAAA,cACA,UAAU,CAAC,CAAA,KAAM,QAAA,CAAS,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,cACxC,SAAA,EAAW,aAAA;AAAA,cACX,WAAA,EAAY,wBAAA;AAAA,cACZ,SAAA,EAAW,CAAA,oIAAA,EACT,QAAA,GAAW,yBAAA,GAA4B,UACzC,CAAA,CAAA;AAAA,cACA,SAAA,EAAS;AAAA;AAAA,WACX;AAAA,0BACAA,GAAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW;AAAA,gBACT,iEAAA;AAAA,gBACA,WAAW,8BAAA,GAAiC,cAAA;AAAA,gBAC5C,QAAQ,0CAAA,GAA6C;AAAA,eACvD,CAAE,KAAK,GAAG,CAAA;AAAA,cAET,QAAA,EAAA,KAAA,mBACCD,IAAAA,CAAC,MAAA,EAAA,EAAK,WAAU,SAAA,EAAU,QAAA,EAAA;AAAA,gBAAA,YAAA;AAAA,gBAAM,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,EAAE;AAAA,eAAA,EAAE,IACjD,UAAA,mBACFC,GAAAA,CAAC,MAAA,EAAA,EAAK,yBAAyB,EAAE,MAAA,EAAQ,UAAA,EAAW,EAAG,oBAEvDA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0BAAyB,QAAA,EAAA,uBAAA,EAAW;AAAA;AAAA,WAExD;AAAA,UACC,CAAC,QAAA,oBACAD,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,mCAAA,EACb,QAAA,EAAA;AAAA,4BAAAA,IAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,4BAAA,EACb,QAAA,EAAA;AAAA,cAAA,WAAA,GAAc,OAAA,GAAU,QAAA;AAAA,cAAS;AAAA,aAAA,EACpC,CAAA;AAAA,4BACAA,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,YAAA,EACb,QAAA,EAAA;AAAA,8BAAAC,GAAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,OAAA,EAAS,OAAA;AAAA,kBACT,SAAA,EAAU,qHAAA;AAAA,kBACX,QAAA,EAAA;AAAA;AAAA,eAED;AAAA,8BACAA,GAAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,OAAA,EAAS,YAAA;AAAA,kBACT,QAAA,EAAU,CAAC,UAAA,IAAc,CAAC,CAAC,KAAA;AAAA,kBAC3B,SAAA,EAAU,mHAAA;AAAA,kBACX,QAAA,EAAA;AAAA;AAAA;AAED,aAAA,EACF;AAAA,WAAA,EACF,CAAA;AAAA,UAED,QAAA,oBACCD,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,wCAAA,EACZ,QAAA,EAAA;AAAA,YAAA,WAAA,GAAc,OAAA,GAAU,QAAA;AAAA,YAAS;AAAA,WAAA,EACpC;AAAA,SAAA,EAEJ;AAAA;AAAA;AAAA,GACF;AAEJ,CAAC,CAAA;ACpPM,IAAM,cAAA,GAAiBE,UAAAA;AAAA,EAC5B,SAASC,eAAAA,CAAe,EAAE,KAAK,cAAA,EAAgB,OAAA,IAAW,GAAA,EAAK;AAC7D,IAAA,MAAM,SAAA,GAAYC,OAAiC,IAAI,CAAA;AACvD,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,WAAA,EAAY;AACjC,IAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAIC,SAAS,KAAK,CAAA;AAElD,IAAA,MAAM,OAAA,GAAU,QAAQ,MAAM;AAC5B,MAAA,IAAI,cAAA,IAAkB,iBAAA,CAAkB,cAAA,CAAe,UAAU,CAAA,EAAG;AAClE,QAAA,OAAO;AAAA,UACL,YAAA,EAAc,eAAe,UAAA,CAAW,GAAA;AAAA,UACxC,WAAA,EAAa,CAAC,CAAC,cAAA,CAAe,UAAA,CAAW;AAAA,SAC3C;AAAA,MACF;AACA,MAAA,OAAO,EAAE,YAAA,EAAc,EAAA,EAAI,WAAA,EAAa,KAAA,EAAM;AAAA,IAChD,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAEnB,IAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIA,QAAAA,CAAS,QAAQ,WAAW,CAAA;AAElE,IAAA,MAAM,YAAA,GAAeC,WAAAA;AAAA,MACnB,OAAO,SAAA,EAAmB,GAAA,EAAa,EAAA,KAAgB;AACrD,QAAA,IAAI,CAAC,GAAA,EAAK;AACV,QAAA,IAAI;AACF,UAAA,MAAM,iBAAiB,GAAA,EAAK;AAAA,YAC1B,SAAA;AAAA,YACA,gBAAgB,OAAwB;AAAA,cACtC,IAAA,EAAM,OAAA;AAAA,cACN,OAAA,EAAS,CAAA;AAAA,cACT,GAAA;AAAA,cACA,WAAA,EAAa;AAAA,aACf,CAAA;AAAA,YACA,gBAAA,EAAkB,gBAAgB,EAAA,IAAM;AAAA,WACzC,CAAA;AAAA,QACH,SAAS,GAAA,EAAK;AACZ,UAAA,OAAA,CAAQ,KAAA,CAAM,wBAAwB,GAAG,CAAA;AAAA,QAC3C;AACA,QAAA,OAAA,EAAQ;AAAA,MACV,CAAA;AAAA,MACA,CAAC,GAAA,EAAK,cAAA,EAAgB,EAAA,EAAI,OAAO;AAAA,KACnC;AAEA,IAAAC,mBAAAA;AAAA,MACE,GAAA;AAAA,MACA,OAAO;AAAA,QACL,SAAA,EAAW,MAAM,SAAA,CAAU,OAAA,EAAS,WAAU,IAAK,KAAA;AAAA,QACnD,UAAA,EAAY,MAAM,SAAA,CAAU,OAAA,EAAS,YAAW,IAAK;AAAA,OACvD,CAAA;AAAA,MACA;AAAC,KACH;AAEA,IAAA,uBACEP,IAAAA,CAAAQ,QAAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAAP,GAAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACC,WAAA;AAAA,UACA,mBAAA,EAAqB,cAAA;AAAA,UACrB,iBAAiB,CAAC,CAAA,KAAM,SAAA,CAAU,OAAA,EAAS,eAAe,CAAC,CAAA;AAAA,UAC3D,OAAA;AAAA,UACA,QAAA;AAAA,UACA,UAAA;AAAA,UACA,aAAA,EAAe,MAAM,aAAA,CAAc,KAAK;AAAA;AAAA,OAC1C;AAAA,sBACAA,GAAAA;AAAA,QAAC,aAAA;AAAA,QAAA;AAAA,UACC,GAAA,EAAK,SAAA;AAAA,UACL,CAAA,EAAG,CAAA;AAAA,UACH,CAAA,EAAG,CAAA;AAAA,UACH,cAAc,OAAA,CAAQ,YAAA;AAAA,UACtB,WAAA;AAAA,UACA,mBAAA,EAAqB,cAAA;AAAA,UACrB,QAAA,EAAU,YAAA;AAAA,UACV,OAAA;AAAA,UACA,eAAe,CAAC,QAAA;AAAA,UAChB,QAAA;AAAA,UACA,YAAA,EAAc,MAAM,aAAA,CAAc,IAAI;AAAA;AAAA;AACxC,KAAA,EACF,CAAA;AAAA,EAEJ;AACF","file":"host-ZQCDAT6O.mjs","sourcesContent":["'use client';\n\nimport React from 'react';\n\n// ---------- Shared shell (latex copy — geometry copy stays in src/stamp/StampLeftPanel.tsx) ----------\n\ninterface ShellProps {\n title: string;\n icon: React.ReactNode;\n onClose: () => void;\n children: React.ReactNode;\n isMobile?: boolean;\n drawerOpen?: boolean;\n onDrawerClose?: () => void;\n}\n\nfunction Shell({ title, icon, onClose, children, isMobile, drawerOpen, onDrawerClose }: ShellProps) {\n const mobileAttrs = isMobile\n ? {\n 'data-mobile-drawer': 'true',\n 'data-drawer-state': drawerOpen ? 'open' : 'closed',\n }\n : {};\n const handleHeaderClose = () => {\n if (isMobile) onDrawerClose?.();\n else onClose();\n };\n return (\n <>\n {isMobile && drawerOpen && (\n <div\n className=\"stamp-drawer-backdrop\"\n onPointerDown={onDrawerClose}\n aria-hidden=\"true\"\n />\n )}\n <aside\n role=\"complementary\"\n aria-label={title}\n aria-hidden={isMobile && !drawerOpen ? 'true' : undefined}\n data-testid=\"stamp-left-panel\"\n data-stamp-area=\"true\"\n {...mobileAttrs}\n className={\n isMobile\n ? 'stamp-drawer-mobile flex flex-col border-r border-slate-200 bg-white shadow-md'\n : 'absolute left-0 top-0 z-30 flex h-full w-60 flex-col border-r border-slate-200 bg-white shadow-md animate-in slide-in-from-left duration-200'\n }\n >\n <header className=\"flex items-center justify-between border-b border-slate-200 bg-gradient-to-r from-slate-50 to-white px-3 py-2\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-slate-800\">\n <span className=\"text-base leading-none\">{icon}</span>\n {title}\n </h3>\n <button\n onClick={handleHeaderClose}\n aria-label={isMobile ? 'Đóng ngăn công cụ' : 'Đóng'}\n className=\"rounded p-1 text-slate-500 transition hover:bg-slate-100 hover:text-slate-800\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n </svg>\n </button>\n </header>\n <div className=\"min-h-0 flex-1 overflow-y-auto p-3 space-y-4\">{children}</div>\n </aside>\n </>\n );\n}\n\nfunction Section({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <section>\n <h4 className=\"mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-slate-500\">\n {label}\n </h4>\n {children}\n </section>\n );\n}\n\n// ---------- LaTeX left panel ----------\n\ninterface LatexLeftPanelProps {\n displayMode: boolean;\n onDisplayModeChange: (b: boolean) => void;\n onInsertSnippet: (snippet: string) => void;\n onClose: () => void;\n isMobile?: boolean;\n drawerOpen?: boolean;\n onDrawerClose?: () => void;\n}\n\ninterface SnippetDef {\n label: string;\n preview: string;\n snippet: string;\n}\n\nconst SNIPPETS: { group: string; items: SnippetDef[] }[] = [\n {\n group: 'Phân số & luỹ thừa',\n items: [\n { label: 'Phân số', preview: 'a⁄b', snippet: '\\\\frac{a}{b}' },\n { label: 'Luỹ thừa', preview: 'x²', snippet: '^{2}' },\n { label: 'Chỉ số', preview: 'x₁', snippet: '_{1}' },\n { label: 'Căn', preview: '√x', snippet: '\\\\sqrt{x}' },\n { label: 'Căn n', preview: 'ⁿ√x', snippet: '\\\\sqrt[n]{x}' },\n ],\n },\n {\n group: 'Tổng & tích phân',\n items: [\n { label: 'Tổng', preview: 'Σ', snippet: '\\\\sum_{i=1}^{n}' },\n { label: 'Tích', preview: 'Π', snippet: '\\\\prod_{i=1}^{n}' },\n { label: 'Tích phân', preview: '∫', snippet: '\\\\int_{a}^{b}' },\n { label: 'Giới hạn', preview: 'lim', snippet: '\\\\lim_{x \\\\to 0}' },\n ],\n },\n {\n group: 'Ký hiệu',\n items: [\n { label: 'α', preview: 'α', snippet: '\\\\alpha' },\n { label: 'β', preview: 'β', snippet: '\\\\beta' },\n { label: 'π', preview: 'π', snippet: '\\\\pi' },\n { label: 'θ', preview: 'θ', snippet: '\\\\theta' },\n { label: '≠', preview: '≠', snippet: '\\\\neq' },\n { label: '≤', preview: '≤', snippet: '\\\\leq' },\n { label: '≥', preview: '≥', snippet: '\\\\geq' },\n { label: '∞', preview: '∞', snippet: '\\\\infty' },\n { label: '→', preview: '→', snippet: '\\\\to' },\n ],\n },\n];\n\nexport function LeftPanel({\n displayMode,\n onDisplayModeChange,\n onInsertSnippet,\n onClose,\n isMobile,\n drawerOpen,\n onDrawerClose,\n}: LatexLeftPanelProps) {\n return (\n <Shell\n title=\"Công thức LaTeX\"\n icon=\"∑\"\n onClose={onClose}\n isMobile={isMobile}\n drawerOpen={drawerOpen}\n onDrawerClose={onDrawerClose}\n >\n <Section label=\"Chế độ hiển thị\">\n <div className=\"grid grid-cols-2 gap-1.5\">\n <button\n type=\"button\"\n onClick={() => onDisplayModeChange(false)}\n aria-pressed={!displayMode}\n className={[\n 'rounded-md border px-2 py-1.5 text-xs transition',\n !displayMode\n ? 'border-emerald-500 bg-emerald-50 text-emerald-700 ring-1 ring-emerald-300'\n : 'border-slate-200 bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50',\n ].join(' ')}\n >\n <span className=\"block font-medium\">Inline</span>\n <span className=\"block text-[10px] text-slate-500\">$ ... $</span>\n </button>\n <button\n type=\"button\"\n onClick={() => onDisplayModeChange(true)}\n aria-pressed={displayMode}\n className={[\n 'rounded-md border px-2 py-1.5 text-xs transition',\n displayMode\n ? 'border-emerald-500 bg-emerald-50 text-emerald-700 ring-1 ring-emerald-300'\n : 'border-slate-200 bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50',\n ].join(' ')}\n >\n <span className=\"block font-medium\">Block</span>\n <span className=\"block text-[10px] text-slate-500\">$$ ... $$</span>\n </button>\n </div>\n </Section>\n\n {SNIPPETS.map((group) => (\n <Section key={group.group} label={group.group}>\n <div className=\"flex flex-wrap gap-1\">\n {group.items.map((s) => (\n <button\n key={s.snippet}\n type=\"button\"\n data-snippet={s.snippet}\n onClick={() => onInsertSnippet(s.snippet)}\n title={s.snippet}\n className=\"rounded border border-slate-200 bg-white px-2 py-1 text-xs text-slate-700 transition hover:border-emerald-300 hover:bg-emerald-50 hover:text-emerald-700\"\n >\n {s.preview}\n </button>\n ))}\n </div>\n </Section>\n ))}\n\n <Section label=\"Phím tắt\">\n <div className=\"flex flex-wrap gap-2 text-[11px] text-slate-600\">\n <span className=\"inline-flex items-center gap-1\">\n <kbd className=\"rounded border border-slate-300 bg-slate-50 px-1.5 py-0.5 font-mono\">Enter</kbd>\n chèn\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <kbd className=\"rounded border border-slate-300 bg-slate-50 px-1.5 py-0.5 font-mono\">Esc</kbd>\n đóng\n </span>\n </div>\n </Section>\n </Shell>\n );\n}\n\n// Back-compat alias\nexport { LeftPanel as LatexLeftPanel };\n","'use client';\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport { renderLatexToSvg } from '../render';\n\ninterface Props {\n /**\n * Legacy: vị trí absolute x/y nếu cần (test). Khi cả 2 = 0 và `centered` !== false,\n * popover sẽ tự center floating ở giữa khu vực bảng. Khi `withLeftPanel` = true,\n * vị trí center được offset 120px để chừa chỗ panel trái.\n */\n x: number;\n y: number;\n initialValue: string;\n onInsert: (svgString: string, src: string, displayMode: boolean) => void;\n onClose: () => void;\n /** Khi controlled từ parent (StampLeftPanel), parent set giá trị này. */\n displayMode?: boolean;\n onDisplayModeChange?: (b: boolean) => void;\n /** Khi true, position center offset cho panel trái. */\n withLeftPanel?: boolean;\n /** Mobile mode: full-screen + hamburger header. */\n isMobile?: boolean;\n /** Trigger mở snippet drawer trên mobile. */\n onOpenDrawer?: () => void;\n}\n\nexport interface EditorPopoverHandle {\n /** Chèn snippet vào vị trí con trỏ trong textbox. */\n insertAtCursor: (snippet: string) => void;\n /** Có content hợp lệ để chèn không (input không rỗng + preview ok). */\n hasContent: () => boolean;\n /** Trigger insert programmatically — return true nếu chèn thành công. */\n tryInsert: () => boolean;\n}\n\nconst DEBOUNCE_MS = 100;\n\nexport const EditorPopover = forwardRef<EditorPopoverHandle, Props>(function EditorPopover(\n {\n x,\n y,\n initialValue,\n onInsert,\n onClose,\n displayMode: controlledDisplayMode,\n onDisplayModeChange,\n withLeftPanel = false,\n isMobile = false,\n onOpenDrawer,\n },\n ref,\n) {\n const [value, setValue] = useState(initialValue);\n const [internalDisplayMode] = useState(false);\n const displayMode = controlledDisplayMode ?? internalDisplayMode;\n // onDisplayModeChange chỉ dùng khi controlled từ parent — không cần local setter\n void onDisplayModeChange;\n\n const [previewSvg, setPreviewSvg] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(async () => {\n try {\n const svg = await renderLatexToSvg(value, displayMode);\n setPreviewSvg(svg);\n setError(null);\n } catch (err) {\n setPreviewSvg(null);\n setError((err as Error).message);\n }\n }, DEBOUNCE_MS);\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n };\n }, [value, displayMode]);\n\n const handleInsert = useCallback(() => {\n if (!previewSvg) return;\n onInsert(previewSvg, value, displayMode);\n }, [previewSvg, value, displayMode, onInsert]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleInsert();\n }\n },\n [onClose, handleInsert],\n );\n\n // Imperative API: snippet button trong panel trái gọi vào, click-outside auto-insert.\n useImperativeHandle(\n ref,\n () => ({\n insertAtCursor: (snippet: string) => {\n const el = inputRef.current;\n if (!el) {\n setValue((v) => v + snippet);\n return;\n }\n const start = el.selectionStart ?? value.length;\n const end = el.selectionEnd ?? value.length;\n const next = value.slice(0, start) + snippet + value.slice(end);\n setValue(next);\n requestAnimationFrame(() => {\n el.focus();\n const pos = start + snippet.length;\n try {\n el.setSelectionRange(pos, pos);\n } catch {\n /* ignore */\n }\n });\n },\n hasContent: () => value.trim().length > 0 && !!previewSvg && !error,\n tryInsert: () => {\n if (!previewSvg || error || !value.trim()) return false;\n onInsert(previewSvg, value, displayMode);\n return true;\n },\n }),\n [value, previewSvg, error, displayMode, onInsert],\n );\n\n // Position: nếu x/y > 0 → dùng legacy absolute (cho tests cũ). Còn không thì center floating.\n const isLegacyPosition = x > 0 || y > 0;\n const wrapperStyle: React.CSSProperties = isMobile\n ? { position: 'fixed', inset: 0, zIndex: 50 }\n : isLegacyPosition\n ? { position: 'absolute', top: y, left: x, zIndex: 50 }\n : {\n position: 'absolute',\n top: '50%',\n left: withLeftPanel ? 'calc(50% + 120px)' : '50%',\n transform: 'translate(-50%, -50%)',\n zIndex: 50,\n };\n\n return (\n <div\n style={wrapperStyle}\n data-stamp-area=\"true\"\n data-mobile-editor={isMobile ? 'true' : undefined}\n className={\n isMobile\n ? 'flex h-full w-full flex-col bg-white'\n : 'w-[420px] max-w-[calc(100vw-280px)] rounded-lg border border-slate-300 bg-white shadow-2xl ring-1 ring-black/5'\n }\n role=\"dialog\"\n aria-label=\"Nhập công thức LaTeX\"\n >\n <header className={`flex items-center gap-2 border-b border-slate-200 bg-gradient-to-r from-indigo-600 to-purple-600 px-3 py-2 text-white${isMobile ? '' : ' rounded-t-lg'}`}>\n {isMobile && (\n <button\n type=\"button\"\n onClick={onOpenDrawer}\n aria-label=\"Mở ngăn snippet\"\n className=\"-ml-1 inline-flex h-10 w-10 items-center justify-center rounded transition hover:bg-white/15\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"4\" y1=\"6\" x2=\"20\" y2=\"6\" />\n <line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\" />\n <line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\" />\n </svg>\n </button>\n )}\n <h3 className=\"flex flex-1 items-center gap-2 text-sm font-semibold\">\n <span className=\"text-base leading-none\">∑</span>\n Công thức LaTeX\n </h3>\n {isMobile && (\n <button\n type=\"button\"\n onClick={handleInsert}\n disabled={!previewSvg || !!error}\n data-testid=\"latex-insert-btn-mobile\"\n className=\"rounded bg-white/15 px-3 py-1.5 text-xs font-semibold transition hover:bg-white/25 disabled:opacity-50\"\n >\n Chèn\n </button>\n )}\n <button\n onClick={onClose}\n aria-label=\"Đóng\"\n className=\"inline-flex h-9 w-9 items-center justify-center rounded transition hover:bg-white/15\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n </svg>\n </button>\n </header>\n <div className={`space-y-2 p-3${isMobile ? ' flex min-h-0 flex-1 flex-col' : ''}`}>\n <input\n ref={inputRef}\n type=\"text\"\n role=\"textbox\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Vd: \\frac{a^2+b^2}{c}\"\n className={`w-full rounded border border-slate-300 px-2 py-1.5 font-mono outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-200${\n isMobile ? ' min-h-[44px] text-base' : ' text-sm'\n }`}\n autoFocus\n />\n <div\n className={[\n 'flex items-center justify-center rounded border p-3 text-center',\n isMobile ? 'min-h-0 flex-1 overflow-auto' : 'min-h-[64px]',\n error ? 'border-rose-300 bg-rose-50 text-rose-700' : 'border-slate-200 bg-slate-50',\n ].join(' ')}\n >\n {error ? (\n <span className=\"text-xs\">Lỗi: {error.slice(0, 80)}</span>\n ) : previewSvg ? (\n <span dangerouslySetInnerHTML={{ __html: previewSvg }} />\n ) : (\n <span className=\"text-xs text-slate-400\">(xem trước)</span>\n )}\n </div>\n {!isMobile && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-[11px] text-slate-500\">\n {displayMode ? 'Block' : 'Inline'} · Enter để chèn\n </span>\n <div className=\"flex gap-2\">\n <button\n onClick={onClose}\n className=\"rounded border border-slate-300 bg-white px-3 py-1 text-xs font-medium text-slate-700 transition hover:bg-slate-100\"\n >\n Huỷ\n </button>\n <button\n onClick={handleInsert}\n disabled={!previewSvg || !!error}\n className=\"rounded bg-indigo-600 px-3 py-1 text-xs font-medium text-white transition hover:bg-indigo-700 disabled:opacity-50\"\n >\n Chèn\n </button>\n </div>\n </div>\n )}\n {isMobile && (\n <div className=\"text-center text-[11px] text-slate-500\">\n {displayMode ? 'Block' : 'Inline'} · Bấm Chèn ở thanh trên\n </div>\n )}\n </div>\n </div>\n );\n});\n\n// Back-compat aliases\nexport { EditorPopover as LatexEditorPopover };\nexport type { EditorPopoverHandle as LatexEditorHandle };\n","'use client';\n\nimport {\n forwardRef,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { LeftPanel as LatexLeftPanel } from './editor/LeftPanel';\nimport {\n EditorPopover as LatexEditorPopover,\n type EditorPopoverHandle as LatexEditorHandle,\n} from './editor/EditorPopover';\nimport { insertStampImage } from '../shared/insertImage';\nimport { useIsMobile } from '../shared/useIsMobile';\nimport { isLatexCustomData, type LatexCustomData } from './types';\nimport type { StampHostProps, StampHostHandle } from '../shared/types';\n\nexport const LatexStampHost = forwardRef<StampHostHandle, StampHostProps>(\n function LatexStampHost({ api, editingElement, onClose }, ref) {\n const editorRef = useRef<LatexEditorHandle | null>(null);\n const { isMobile } = useIsMobile();\n const [drawerOpen, setDrawerOpen] = useState(false);\n\n const initial = useMemo(() => {\n if (editingElement && isLatexCustomData(editingElement.customData)) {\n return {\n initialValue: editingElement.customData.src,\n displayMode: !!editingElement.customData.displayMode,\n };\n }\n return { initialValue: '', displayMode: false };\n }, [editingElement]);\n\n const [displayMode, setDisplayMode] = useState(initial.displayMode);\n\n const handleInsert = useCallback(\n async (svgString: string, src: string, dm: boolean) => {\n if (!api) return;\n try {\n await insertStampImage(api, {\n svgString,\n makeCustomData: (): LatexCustomData => ({\n kind: 'latex',\n version: 1,\n src,\n displayMode: dm,\n }),\n editingElementId: editingElement?.id ?? null,\n });\n } catch (err) {\n console.error('Latex insert failed:', err);\n }\n onClose();\n },\n [api, editingElement?.id, onClose],\n );\n\n useImperativeHandle(\n ref,\n () => ({\n tryInsert: () => editorRef.current?.tryInsert() ?? false,\n hasContent: () => editorRef.current?.hasContent() ?? false,\n }),\n [],\n );\n\n return (\n <>\n <LatexLeftPanel\n displayMode={displayMode}\n onDisplayModeChange={setDisplayMode}\n onInsertSnippet={(s) => editorRef.current?.insertAtCursor(s)}\n onClose={onClose}\n isMobile={isMobile}\n drawerOpen={drawerOpen}\n onDrawerClose={() => setDrawerOpen(false)}\n />\n <LatexEditorPopover\n ref={editorRef}\n x={0}\n y={0}\n initialValue={initial.initialValue}\n displayMode={displayMode}\n onDisplayModeChange={setDisplayMode}\n onInsert={handleInsert}\n onClose={onClose}\n withLeftPanel={!isMobile}\n isMobile={isMobile}\n onOpenDrawer={() => setDrawerOpen(true)}\n />\n </>\n );\n },\n);\n"]}
1
+ {"version":3,"sources":["../src/stamps/latex/editor/LeftPanel.tsx","../src/stamps/latex/editor/EditorPopover.tsx","../src/stamps/latex/host.tsx"],"names":["EditorPopover","jsxs","jsx","forwardRef","LatexStampHost","useRef","useState","useCallback","useImperativeHandle","Fragment"],"mappings":"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","file":"host-H2IGOKJU.mjs","sourcesContent":["'use client';\n\nimport React from 'react';\n\n// ---------- Shared shell (latex copy — geometry copy stays in src/stamp/StampLeftPanel.tsx) ----------\n\ninterface ShellProps {\n title: string;\n icon: React.ReactNode;\n onClose: () => void;\n children: React.ReactNode;\n isMobile?: boolean;\n drawerOpen?: boolean;\n onDrawerClose?: () => void;\n}\n\nfunction Shell({ title, icon, onClose, children, isMobile, drawerOpen, onDrawerClose }: ShellProps) {\n const mobileAttrs = isMobile\n ? {\n 'data-mobile-drawer': 'true',\n 'data-drawer-state': drawerOpen ? 'open' : 'closed',\n }\n : {};\n const handleHeaderClose = () => {\n if (isMobile) onDrawerClose?.();\n else onClose();\n };\n return (\n <>\n {isMobile && drawerOpen && (\n <div\n className=\"stamp-drawer-backdrop\"\n onPointerDown={onDrawerClose}\n aria-hidden=\"true\"\n />\n )}\n <aside\n role=\"complementary\"\n aria-label={title}\n aria-hidden={isMobile && !drawerOpen ? 'true' : undefined}\n data-testid=\"stamp-left-panel\"\n data-stamp-area=\"true\"\n {...mobileAttrs}\n className={\n isMobile\n ? 'stamp-drawer-mobile flex flex-col border-r border-slate-200 bg-white shadow-md'\n : 'absolute left-0 top-0 z-30 flex h-full w-60 flex-col border-r border-slate-200 bg-white shadow-md animate-in slide-in-from-left duration-200'\n }\n >\n <header className=\"flex items-center justify-between border-b border-slate-200 bg-gradient-to-r from-slate-50 to-white px-3 py-2\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-slate-800\">\n <span className=\"text-base leading-none\">{icon}</span>\n {title}\n </h3>\n <button\n onClick={handleHeaderClose}\n aria-label={isMobile ? 'Đóng ngăn công cụ' : 'Đóng'}\n className=\"rounded p-1 text-slate-500 transition hover:bg-slate-100 hover:text-slate-800\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n </svg>\n </button>\n </header>\n <div className=\"min-h-0 flex-1 overflow-y-auto p-3 space-y-4\">{children}</div>\n </aside>\n </>\n );\n}\n\nfunction Section({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <section>\n <h4 className=\"mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-slate-500\">\n {label}\n </h4>\n {children}\n </section>\n );\n}\n\n// ---------- LaTeX left panel ----------\n\ninterface LatexLeftPanelProps {\n displayMode: boolean;\n onDisplayModeChange: (b: boolean) => void;\n onInsertSnippet: (snippet: string) => void;\n onClose: () => void;\n isMobile?: boolean;\n drawerOpen?: boolean;\n onDrawerClose?: () => void;\n}\n\ninterface SnippetDef {\n label: string;\n preview: string;\n snippet: string;\n}\n\nconst SNIPPETS: { group: string; items: SnippetDef[] }[] = [\n {\n group: 'Phân số & luỹ thừa',\n items: [\n { label: 'Phân số', preview: 'a⁄b', snippet: '\\\\frac{a}{b}' },\n { label: 'Luỹ thừa', preview: 'x²', snippet: '^{2}' },\n { label: 'Chỉ số', preview: 'x₁', snippet: '_{1}' },\n { label: 'Căn', preview: '√x', snippet: '\\\\sqrt{x}' },\n { label: 'Căn n', preview: 'ⁿ√x', snippet: '\\\\sqrt[n]{x}' },\n ],\n },\n {\n group: 'Tổng & tích phân',\n items: [\n { label: 'Tổng', preview: 'Σ', snippet: '\\\\sum_{i=1}^{n}' },\n { label: 'Tích', preview: 'Π', snippet: '\\\\prod_{i=1}^{n}' },\n { label: 'Tích phân', preview: '∫', snippet: '\\\\int_{a}^{b}' },\n { label: 'Giới hạn', preview: 'lim', snippet: '\\\\lim_{x \\\\to 0}' },\n ],\n },\n {\n group: 'Ký hiệu',\n items: [\n { label: 'α', preview: 'α', snippet: '\\\\alpha' },\n { label: 'β', preview: 'β', snippet: '\\\\beta' },\n { label: 'π', preview: 'π', snippet: '\\\\pi' },\n { label: 'θ', preview: 'θ', snippet: '\\\\theta' },\n { label: '≠', preview: '≠', snippet: '\\\\neq' },\n { label: '≤', preview: '≤', snippet: '\\\\leq' },\n { label: '≥', preview: '≥', snippet: '\\\\geq' },\n { label: '∞', preview: '∞', snippet: '\\\\infty' },\n { label: '→', preview: '→', snippet: '\\\\to' },\n ],\n },\n];\n\nexport function LeftPanel({\n displayMode,\n onDisplayModeChange,\n onInsertSnippet,\n onClose,\n isMobile,\n drawerOpen,\n onDrawerClose,\n}: LatexLeftPanelProps) {\n return (\n <Shell\n title=\"Công thức LaTeX\"\n icon=\"∑\"\n onClose={onClose}\n isMobile={isMobile}\n drawerOpen={drawerOpen}\n onDrawerClose={onDrawerClose}\n >\n <Section label=\"Chế độ hiển thị\">\n <div className=\"grid grid-cols-2 gap-1.5\">\n <button\n type=\"button\"\n onClick={() => onDisplayModeChange(false)}\n aria-pressed={!displayMode}\n className={[\n 'rounded-md border px-2 py-1.5 text-xs transition',\n !displayMode\n ? 'border-emerald-500 bg-emerald-50 text-emerald-700 ring-1 ring-emerald-300'\n : 'border-slate-200 bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50',\n ].join(' ')}\n >\n <span className=\"block font-medium\">Inline</span>\n <span className=\"block text-[10px] text-slate-500\">$ ... $</span>\n </button>\n <button\n type=\"button\"\n onClick={() => onDisplayModeChange(true)}\n aria-pressed={displayMode}\n className={[\n 'rounded-md border px-2 py-1.5 text-xs transition',\n displayMode\n ? 'border-emerald-500 bg-emerald-50 text-emerald-700 ring-1 ring-emerald-300'\n : 'border-slate-200 bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50',\n ].join(' ')}\n >\n <span className=\"block font-medium\">Block</span>\n <span className=\"block text-[10px] text-slate-500\">$$ ... $$</span>\n </button>\n </div>\n </Section>\n\n {SNIPPETS.map((group) => (\n <Section key={group.group} label={group.group}>\n <div className=\"flex flex-wrap gap-1\">\n {group.items.map((s) => (\n <button\n key={s.snippet}\n type=\"button\"\n data-snippet={s.snippet}\n onClick={() => onInsertSnippet(s.snippet)}\n title={s.snippet}\n className=\"rounded border border-slate-200 bg-white px-2 py-1 text-xs text-slate-700 transition hover:border-emerald-300 hover:bg-emerald-50 hover:text-emerald-700\"\n >\n {s.preview}\n </button>\n ))}\n </div>\n </Section>\n ))}\n\n <Section label=\"Phím tắt\">\n <div className=\"flex flex-wrap gap-2 text-[11px] text-slate-600\">\n <span className=\"inline-flex items-center gap-1\">\n <kbd className=\"rounded border border-slate-300 bg-slate-50 px-1.5 py-0.5 font-mono\">Enter</kbd>\n chèn\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <kbd className=\"rounded border border-slate-300 bg-slate-50 px-1.5 py-0.5 font-mono\">Esc</kbd>\n đóng\n </span>\n </div>\n </Section>\n </Shell>\n );\n}\n\n// Back-compat alias\nexport { LeftPanel as LatexLeftPanel };\n","'use client';\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport { renderLatexToSvg } from '../render';\n\ninterface Props {\n /**\n * Legacy: vị trí absolute x/y nếu cần (test). Khi cả 2 = 0 và `centered` !== false,\n * popover sẽ tự center floating ở giữa khu vực bảng. Khi `withLeftPanel` = true,\n * vị trí center được offset 120px để chừa chỗ panel trái.\n */\n x: number;\n y: number;\n initialValue: string;\n onInsert: (svgString: string, src: string, displayMode: boolean) => void;\n onClose: () => void;\n /** Khi controlled từ parent (StampLeftPanel), parent set giá trị này. */\n displayMode?: boolean;\n onDisplayModeChange?: (b: boolean) => void;\n /** Khi true, position center offset cho panel trái. */\n withLeftPanel?: boolean;\n /** Mobile mode: full-screen + hamburger header. */\n isMobile?: boolean;\n /** Trigger mở snippet drawer trên mobile. */\n onOpenDrawer?: () => void;\n}\n\nexport interface EditorPopoverHandle {\n /** Chèn snippet vào vị trí con trỏ trong textbox. */\n insertAtCursor: (snippet: string) => void;\n /** Có content hợp lệ để chèn không (input không rỗng + preview ok). */\n hasContent: () => boolean;\n /** Trigger insert programmatically — return true nếu chèn thành công. */\n tryInsert: () => boolean;\n}\n\nconst DEBOUNCE_MS = 100;\n\nexport const EditorPopover = forwardRef<EditorPopoverHandle, Props>(function EditorPopover(\n {\n x,\n y,\n initialValue,\n onInsert,\n onClose,\n displayMode: controlledDisplayMode,\n onDisplayModeChange,\n withLeftPanel = false,\n isMobile = false,\n onOpenDrawer,\n },\n ref,\n) {\n const [value, setValue] = useState(initialValue);\n const [internalDisplayMode] = useState(false);\n const displayMode = controlledDisplayMode ?? internalDisplayMode;\n // onDisplayModeChange chỉ dùng khi controlled từ parent — không cần local setter\n void onDisplayModeChange;\n\n const [previewSvg, setPreviewSvg] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(async () => {\n try {\n const svg = await renderLatexToSvg(value, displayMode);\n setPreviewSvg(svg);\n setError(null);\n } catch (err) {\n setPreviewSvg(null);\n setError((err as Error).message);\n }\n }, DEBOUNCE_MS);\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n };\n }, [value, displayMode]);\n\n const handleInsert = useCallback(() => {\n if (!previewSvg) return;\n onInsert(previewSvg, value, displayMode);\n }, [previewSvg, value, displayMode, onInsert]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleInsert();\n }\n },\n [onClose, handleInsert],\n );\n\n // Imperative API: snippet button trong panel trái gọi vào, click-outside auto-insert.\n useImperativeHandle(\n ref,\n () => ({\n insertAtCursor: (snippet: string) => {\n const el = inputRef.current;\n if (!el) {\n setValue((v) => v + snippet);\n return;\n }\n const start = el.selectionStart ?? value.length;\n const end = el.selectionEnd ?? value.length;\n const next = value.slice(0, start) + snippet + value.slice(end);\n setValue(next);\n requestAnimationFrame(() => {\n el.focus();\n const pos = start + snippet.length;\n try {\n el.setSelectionRange(pos, pos);\n } catch {\n /* ignore */\n }\n });\n },\n hasContent: () => value.trim().length > 0 && !!previewSvg && !error,\n tryInsert: () => {\n if (!previewSvg || error || !value.trim()) return false;\n onInsert(previewSvg, value, displayMode);\n return true;\n },\n }),\n [value, previewSvg, error, displayMode, onInsert],\n );\n\n // Position: nếu x/y > 0 → dùng legacy absolute (cho tests cũ). Còn không thì center floating.\n const isLegacyPosition = x > 0 || y > 0;\n const wrapperStyle: React.CSSProperties = isMobile\n ? { position: 'fixed', inset: 0, zIndex: 50 }\n : isLegacyPosition\n ? { position: 'absolute', top: y, left: x, zIndex: 50 }\n : {\n position: 'absolute',\n top: '50%',\n left: withLeftPanel ? 'calc(50% + 120px)' : '50%',\n transform: 'translate(-50%, -50%)',\n zIndex: 50,\n };\n\n return (\n <div\n style={wrapperStyle}\n data-stamp-area=\"true\"\n data-mobile-editor={isMobile ? 'true' : undefined}\n className={\n isMobile\n ? 'flex h-full w-full flex-col bg-white'\n : 'w-[420px] max-w-[calc(100vw-280px)] rounded-lg border border-slate-300 bg-white shadow-2xl ring-1 ring-black/5'\n }\n role=\"dialog\"\n aria-label=\"Nhập công thức LaTeX\"\n >\n <header className={`flex items-center gap-2 border-b border-slate-200 bg-gradient-to-r from-indigo-600 to-purple-600 px-3 py-2 text-white${isMobile ? '' : ' rounded-t-lg'}`}>\n {isMobile && (\n <button\n type=\"button\"\n onClick={onOpenDrawer}\n aria-label=\"Mở ngăn snippet\"\n className=\"-ml-1 inline-flex h-10 w-10 items-center justify-center rounded transition hover:bg-white/15\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"4\" y1=\"6\" x2=\"20\" y2=\"6\" />\n <line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\" />\n <line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\" />\n </svg>\n </button>\n )}\n <h3 className=\"flex flex-1 items-center gap-2 text-sm font-semibold\">\n <span className=\"text-base leading-none\">∑</span>\n Công thức LaTeX\n </h3>\n {isMobile && (\n <button\n type=\"button\"\n onClick={handleInsert}\n disabled={!previewSvg || !!error}\n data-testid=\"latex-insert-btn-mobile\"\n className=\"rounded bg-white/15 px-3 py-1.5 text-xs font-semibold transition hover:bg-white/25 disabled:opacity-50\"\n >\n Chèn\n </button>\n )}\n <button\n onClick={onClose}\n aria-label=\"Đóng\"\n className=\"inline-flex h-9 w-9 items-center justify-center rounded transition hover:bg-white/15\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n </svg>\n </button>\n </header>\n <div className={`space-y-2 p-3${isMobile ? ' flex min-h-0 flex-1 flex-col' : ''}`}>\n <input\n ref={inputRef}\n type=\"text\"\n role=\"textbox\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Vd: \\frac{a^2+b^2}{c}\"\n className={`w-full rounded border border-slate-300 px-2 py-1.5 font-mono outline-none focus:border-indigo-400 focus:ring-2 focus:ring-indigo-200${\n isMobile ? ' min-h-[44px] text-base' : ' text-sm'\n }`}\n autoFocus\n />\n <div\n className={[\n 'flex items-center justify-center rounded border p-3 text-center',\n isMobile ? 'min-h-0 flex-1 overflow-auto' : 'min-h-[64px]',\n error ? 'border-rose-300 bg-rose-50 text-rose-700' : 'border-slate-200 bg-slate-50',\n ].join(' ')}\n >\n {error ? (\n <span className=\"text-xs\">Lỗi: {error.slice(0, 80)}</span>\n ) : previewSvg ? (\n <span dangerouslySetInnerHTML={{ __html: previewSvg }} />\n ) : (\n <span className=\"text-xs text-slate-400\">(xem trước)</span>\n )}\n </div>\n {!isMobile && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-[11px] text-slate-500\">\n {displayMode ? 'Block' : 'Inline'} · Enter để chèn\n </span>\n <div className=\"flex gap-2\">\n <button\n onClick={onClose}\n className=\"rounded border border-slate-300 bg-white px-3 py-1 text-xs font-medium text-slate-700 transition hover:bg-slate-100\"\n >\n Huỷ\n </button>\n <button\n onClick={handleInsert}\n disabled={!previewSvg || !!error}\n className=\"rounded bg-indigo-600 px-3 py-1 text-xs font-medium text-white transition hover:bg-indigo-700 disabled:opacity-50\"\n >\n Chèn\n </button>\n </div>\n </div>\n )}\n {isMobile && (\n <div className=\"text-center text-[11px] text-slate-500\">\n {displayMode ? 'Block' : 'Inline'} · Bấm Chèn ở thanh trên\n </div>\n )}\n </div>\n </div>\n );\n});\n\n// Back-compat aliases\nexport { EditorPopover as LatexEditorPopover };\nexport type { EditorPopoverHandle as LatexEditorHandle };\n","'use client';\n\nimport {\n forwardRef,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { LeftPanel as LatexLeftPanel } from './editor/LeftPanel';\nimport {\n EditorPopover as LatexEditorPopover,\n type EditorPopoverHandle as LatexEditorHandle,\n} from './editor/EditorPopover';\nimport { insertStampImage } from '../shared/insertImage';\nimport { useIsMobile } from '../shared/useIsMobile';\nimport { isLatexCustomData, type LatexCustomData } from './types';\nimport type { StampHostProps, StampHostHandle } from '../shared/types';\n\nexport const LatexStampHost = forwardRef<StampHostHandle, StampHostProps>(\n function LatexStampHost({ api, editingElement, onClose }, ref) {\n const editorRef = useRef<LatexEditorHandle | null>(null);\n const { isMobile } = useIsMobile();\n const [drawerOpen, setDrawerOpen] = useState(false);\n\n const initial = useMemo(() => {\n if (editingElement && isLatexCustomData(editingElement.customData)) {\n return {\n initialValue: editingElement.customData.src,\n displayMode: !!editingElement.customData.displayMode,\n };\n }\n return { initialValue: '', displayMode: false };\n }, [editingElement]);\n\n const [displayMode, setDisplayMode] = useState(initial.displayMode);\n\n const handleInsert = useCallback(\n async (svgString: string, src: string, dm: boolean) => {\n if (!api) return;\n try {\n await insertStampImage(api, {\n svgString,\n makeCustomData: (): LatexCustomData => ({\n kind: 'latex',\n version: 1,\n src,\n displayMode: dm,\n }),\n editingElementId: editingElement?.id ?? null,\n });\n } catch (err) {\n console.error('Latex insert failed:', err);\n }\n onClose();\n },\n [api, editingElement?.id, onClose],\n );\n\n useImperativeHandle(\n ref,\n () => ({\n tryInsert: () => editorRef.current?.tryInsert() ?? false,\n hasContent: () => editorRef.current?.hasContent() ?? false,\n }),\n [],\n );\n\n return (\n <>\n <LatexLeftPanel\n displayMode={displayMode}\n onDisplayModeChange={setDisplayMode}\n onInsertSnippet={(s) => editorRef.current?.insertAtCursor(s)}\n onClose={onClose}\n isMobile={isMobile}\n drawerOpen={drawerOpen}\n onDrawerClose={() => setDrawerOpen(false)}\n />\n <LatexEditorPopover\n ref={editorRef}\n x={0}\n y={0}\n initialValue={initial.initialValue}\n displayMode={displayMode}\n onDisplayModeChange={setDisplayMode}\n onInsert={handleInsert}\n onClose={onClose}\n withLeftPanel={!isMobile}\n isMobile={isMobile}\n onOpenDrawer={() => setDrawerOpen(true)}\n />\n </>\n );\n },\n);\n"]}
@@ -1,19 +1,19 @@
1
1
  "use client";
2
2
  import { useChordShortcut } from './chunk-HNQLZIEP.mjs';
3
3
  import { useToolStateMachine } from './chunk-NVJ7K3DK.mjs';
4
- import { safeJsx, initJxgBoard, attachJxgWheelZoom, useToast, ToastHost, STAMP_PANEL_DESKTOP, ToastProvider, useStampStore, StampLeftPanel, ObjectRow } from './chunk-OQIQNKPQ.mjs';
5
- import { serializeBoard, renderGeometrySvgFromState, isGeometryCustomData, deserializeBoard } from './chunk-H22OZYTW.mjs';
4
+ import { safeJsx, initJxgBoard, attachJxgWheelZoom, useToast, ToastHost, STAMP_PANEL_DESKTOP, ToastProvider, useStampStore, StampLeftPanel, ObjectRow } from './chunk-LTLLQUMN.mjs';
5
+ import { isDefaultBbox, autoFitBoardToContent, serializeBoard, renderGeometrySvgFromState, isGeometryCustomData, deserializeBoard } from './chunk-KOXOC2FI.mjs';
6
6
  import { themeLabel, paletteFor, themeAxis, themeGrid } from './chunk-R5FL6S7L.mjs';
7
- import { JxgRenderer } from './chunk-SZDAS7LK.mjs';
7
+ import { JxgRenderer } from './chunk-IE2GGHNF.mjs';
8
8
  import './chunk-ICR4CVOE.mjs';
9
- import { nextLabel, useEditorState, listObjects } from './chunk-ZTQBUKLJ.mjs';
10
- import './chunk-IHUFOV7L.mjs';
11
- import { validateFile, fileToImagePart, describeDsl } from './chunk-SF3U7ZF4.mjs';
9
+ import { nextLabel, useEditorState, listObjects } from './chunk-JJ4FPCBE.mjs';
10
+ import './chunk-CH6SFONH.mjs';
11
+ import { validateFile, fileToImagePart, describeDsl } from './chunk-DWIEVCGK.mjs';
12
12
  import { handleExtractProblem } from './chunk-QK6OVDLC.mjs';
13
13
  import { DEFAULT_VIEW_2D } from './chunk-73Q7ADVL.mjs';
14
14
  import './chunk-B4NJJZFR.mjs';
15
15
  import { useIsMobile } from './chunk-P2AOIF7S.mjs';
16
- import { insertStampImage } from './chunk-QGNU34T7.mjs';
16
+ import { insertStampImage } from './chunk-QLQ4MJNO.mjs';
17
17
  import './chunk-5UTGXHLJ.mjs';
18
18
  import { __export } from './chunk-J5LGTIGS.mjs';
19
19
  import { forwardRef, useRef, useId, useState, useEffect, useCallback, useImperativeHandle, useMemo, useLayoutEffect } from 'react';
@@ -331,41 +331,48 @@ var Icon = {
331
331
  /* @__PURE__ */ jsx("circle", { cx: "4", cy: "4", r: "1.7", fill: C_POINT })
332
332
  ] }),
333
333
  // ===== Nâng cao / kind chưa có icon =====
334
- excenter: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
335
- /* @__PURE__ */ jsx("path", { d: "M5 16 L12 5 L19 16 Z", stroke: "currentColor", strokeWidth: "1.3" }),
336
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "20", r: "3", fill: "none", stroke: C_CONSTRUCT, strokeWidth: "1.3" }),
337
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "20", r: "1.4", fill: C_CONSTRUCT })
334
+ // Hệ màu đồng bộ: XANH = input click sẵn, ĐỎ = output suy ra. Toạ độ tính để
335
+ // điểm nằm ĐÚNG trên đường tròn/cung/tiếp tuyến (không trôi nổi).
336
+ excenter: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", strokeLinejoin: "round", children: [
337
+ /* @__PURE__ */ jsx("polygon", { points: "12,3 15,15 9,15", stroke: "currentColor", strokeWidth: "1.4", fill: "none" }),
338
+ /* @__PURE__ */ jsx("line", { x1: "9", y1: "15", x2: "8", y2: "18.9", stroke: "#94a3b8", strokeWidth: "1", strokeDasharray: "1.6 1.6" }),
339
+ /* @__PURE__ */ jsx("line", { x1: "15", y1: "15", x2: "16", y2: "18.9", stroke: "#94a3b8", strokeWidth: "1", strokeDasharray: "1.6 1.6" }),
340
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "18.9", r: "3.8", stroke: "currentColor", strokeWidth: "1.3" }),
341
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "3", r: "1.6", fill: C_POINT }),
342
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "15", r: "1.6", fill: C_POINT }),
343
+ /* @__PURE__ */ jsx("circle", { cx: "15", cy: "15", r: "1.6", fill: C_POINT }),
344
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "18.9", r: "2.2", fill: C_CONSTRUCT })
338
345
  ] }),
339
- tangencyPoint: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
340
- /* @__PURE__ */ jsx("circle", { cx: "10", cy: "12", r: "6.5", stroke: "currentColor", strokeWidth: "1.3" }),
341
- /* @__PURE__ */ jsx("line", { x1: "16.5", y1: "3", x2: "16.5", y2: "21", stroke: "currentColor", strokeWidth: "1.3" }),
342
- /* @__PURE__ */ jsx("circle", { cx: "16.5", cy: "12", r: "2.2", fill: C_CONSTRUCT })
346
+ tangencyPoint: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", children: [
347
+ /* @__PURE__ */ jsx("circle", { cx: "9.5", cy: "12", r: "7", stroke: "currentColor", strokeWidth: "1.4" }),
348
+ /* @__PURE__ */ jsx("line", { x1: "16.5", y1: "3.5", x2: "16.5", y2: "20.5", stroke: "currentColor", strokeWidth: "1.4" }),
349
+ /* @__PURE__ */ jsx("circle", { cx: "16.5", cy: "12", r: "2.3", fill: C_CONSTRUCT })
343
350
  ] }),
344
- secondIntersection: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
345
- /* @__PURE__ */ jsx("circle", { cx: "11", cy: "12", r: "6.5", stroke: "currentColor", strokeWidth: "1.3" }),
346
- /* @__PURE__ */ jsx("line", { x1: "2", y1: "8", x2: "22", y2: "16", stroke: "currentColor", strokeWidth: "1.3" }),
347
- /* @__PURE__ */ jsx("circle", { cx: "6.2", cy: "9.6", r: "1.6", fill: "currentColor" }),
348
- /* @__PURE__ */ jsx("circle", { cx: "15.8", cy: "14.4", r: "2.4", fill: C_CONSTRUCT })
351
+ secondIntersection: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", children: [
352
+ /* @__PURE__ */ jsx("circle", { cx: "11", cy: "12", r: "6.5", stroke: "currentColor", strokeWidth: "1.4" }),
353
+ /* @__PURE__ */ jsx("line", { x1: "2.4", y1: "8.2", x2: "20.4", y2: "11.4", stroke: "currentColor", strokeWidth: "1.4" }),
354
+ /* @__PURE__ */ jsx("circle", { cx: "5.37", cy: "8.75", r: "1.8", fill: C_POINT }),
355
+ /* @__PURE__ */ jsx("circle", { cx: "17.4", cy: "10.87", r: "2.4", fill: C_CONSTRUCT })
349
356
  ] }),
350
357
  arcMidpoint: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", children: [
351
- /* @__PURE__ */ jsx("path", { d: "M4 17 A 9 9 0 0 1 20 17", stroke: "currentColor", strokeWidth: "1.4" }),
352
- /* @__PURE__ */ jsx("circle", { cx: "4", cy: "17", r: "1.6", fill: "currentColor" }),
353
- /* @__PURE__ */ jsx("circle", { cx: "20", cy: "17", r: "1.6", fill: "currentColor" }),
354
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "8.2", r: "2.4", fill: C_CONSTRUCT })
358
+ /* @__PURE__ */ jsx("path", { d: "M4 17 A 8.5 8.5 0 0 1 20 17", stroke: "currentColor", strokeWidth: "1.6", fill: "none" }),
359
+ /* @__PURE__ */ jsx("circle", { cx: "4", cy: "17", r: "1.8", fill: C_POINT }),
360
+ /* @__PURE__ */ jsx("circle", { cx: "20", cy: "17", r: "1.8", fill: C_POINT }),
361
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "11.4", r: "2.3", fill: C_CONSTRUCT })
355
362
  ] }),
356
363
  circleIntersection: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
357
- /* @__PURE__ */ jsx("circle", { cx: "9", cy: "12", r: "6", stroke: "currentColor", strokeWidth: "1.3" }),
358
- /* @__PURE__ */ jsx("circle", { cx: "15", cy: "12", r: "6", stroke: "currentColor", strokeWidth: "1.3" }),
359
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "7.6", r: "2", fill: C_CONSTRUCT }),
360
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "16.4", r: "2", fill: C_CONSTRUCT })
364
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "12", r: "6", stroke: "currentColor", strokeWidth: "1.4" }),
365
+ /* @__PURE__ */ jsx("circle", { cx: "15", cy: "12", r: "6", stroke: "currentColor", strokeWidth: "1.4" }),
366
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "6.8", r: "2", fill: C_CONSTRUCT }),
367
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "17.2", r: "2", fill: C_CONSTRUCT })
361
368
  ] }),
362
369
  tangentPointExt: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", children: [
363
- /* @__PURE__ */ jsx("circle", { cx: "14", cy: "12", r: "6", stroke: "currentColor", strokeWidth: "1.3" }),
364
- /* @__PURE__ */ jsx("circle", { cx: "3.5", cy: "12", r: "1.8", fill: C_POINT }),
365
- /* @__PURE__ */ jsx("line", { x1: "3.5", y1: "12", x2: "17.5", y2: "7.5", stroke: "currentColor", strokeWidth: "1.2" }),
366
- /* @__PURE__ */ jsx("line", { x1: "3.5", y1: "12", x2: "17.5", y2: "16.5", stroke: "currentColor", strokeWidth: "1.2" }),
367
- /* @__PURE__ */ jsx("circle", { cx: "17.5", cy: "7.5", r: "1.8", fill: C_CONSTRUCT }),
368
- /* @__PURE__ */ jsx("circle", { cx: "17.5", cy: "16.5", r: "1.8", fill: C_CONSTRUCT })
370
+ /* @__PURE__ */ jsx("circle", { cx: "13", cy: "12", r: "6", stroke: "currentColor", strokeWidth: "1.4" }),
371
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "11.8", y2: "18.6", stroke: "currentColor", strokeWidth: "1.3" }),
372
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "11.8", y2: "5.4", stroke: "currentColor", strokeWidth: "1.3" }),
373
+ /* @__PURE__ */ jsx("circle", { cx: "3", cy: "12", r: "2", fill: C_POINT }),
374
+ /* @__PURE__ */ jsx("circle", { cx: "9.4", cy: "16.8", r: "1.8", fill: C_CONSTRUCT }),
375
+ /* @__PURE__ */ jsx("circle", { cx: "9.4", cy: "7.2", r: "1.8", fill: C_CONSTRUCT })
369
376
  ] }),
370
377
  circleCR: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
371
378
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "7.5", stroke: "currentColor", strokeWidth: "1.3" }),
@@ -376,9 +383,11 @@ var Icon = {
376
383
  /* @__PURE__ */ jsx("path", { d: "M3 19 L12 4 L21 19 Z", stroke: "currentColor", strokeWidth: "1.3", strokeLinejoin: "round" }),
377
384
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "14", r: "4.2", fill: "none", stroke: C_CONSTRUCT, strokeWidth: "1.3" })
378
385
  ] }),
379
- excircle: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
380
- /* @__PURE__ */ jsx("path", { d: "M6 9 L14 4 L18 13 Z", stroke: "currentColor", strokeWidth: "1.2" }),
381
- /* @__PURE__ */ jsx("circle", { cx: "9", cy: "17", r: "4.6", fill: "none", stroke: C_CONSTRUCT, strokeWidth: "1.3" })
386
+ excircle: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", strokeLinejoin: "round", children: [
387
+ /* @__PURE__ */ jsx("polygon", { points: "12,3 15,15 9,15", stroke: "currentColor", strokeWidth: "1.4", fill: "none" }),
388
+ /* @__PURE__ */ jsx("line", { x1: "9", y1: "15", x2: "8", y2: "18.9", stroke: "#94a3b8", strokeWidth: "1", strokeDasharray: "1.6 1.6" }),
389
+ /* @__PURE__ */ jsx("line", { x1: "15", y1: "15", x2: "16", y2: "18.9", stroke: "#94a3b8", strokeWidth: "1", strokeDasharray: "1.6 1.6" }),
390
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "18.9", r: "3.8", stroke: C_CONSTRUCT, strokeWidth: "1.5", fill: C_CONSTRUCT, fillOpacity: "0.12" })
382
391
  ] }),
383
392
  pointOn: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", children: [
384
393
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "7.5", stroke: "currentColor", strokeWidth: "1.3" }),
@@ -2123,11 +2132,11 @@ function buildObjectSnapshot(state, id, anchorScreen) {
2123
2132
  const obj = state.objects[id];
2124
2133
  if (!obj) return null;
2125
2134
  const k = obj.kind;
2126
- if (k !== "point" && k !== "line" && k !== "circle" && k !== "segment" && k !== "ray" && k !== "vector") {
2135
+ if (k !== "point" && k !== "line" && k !== "circle" && k !== "segment" && k !== "ray" && k !== "vector" && k !== "intersection") {
2127
2136
  return null;
2128
2137
  }
2129
2138
  const a = obj.attrs;
2130
- const jKind = k === "point" ? "point" : k === "circle" ? "circle" : "line";
2139
+ const jKind = k === "point" || k === "intersection" ? "point" : k === "circle" ? "circle" : "line";
2131
2140
  return {
2132
2141
  id,
2133
2142
  kind: jKind,
@@ -2703,6 +2712,11 @@ var MiniBoard2D = forwardRef(function MiniBoard2D2({ onReady, store, selectedToo
2703
2712
  rendererRef.current = new JxgRenderer(store, board, {
2704
2713
  theme: paletteFor(isDarkRef.current)
2705
2714
  });
2715
+ if (isDefaultBbox(initialView.bbox)) {
2716
+ const el = containerRef.current;
2717
+ const aspect = el && el.clientHeight > 0 ? el.clientWidth / el.clientHeight : 1;
2718
+ safeJsx("MiniBoard.autoFit", () => autoFitBoardToContent(board, aspect));
2719
+ }
2706
2720
  if (containerRef.current) {
2707
2721
  wheelCleanup = attachJxgWheelZoom(containerRef.current, board, "MiniBoard.2d");
2708
2722
  }
@@ -3272,6 +3286,7 @@ function useAiFigure(generator) {
3272
3286
  const [prompt, setPrompt] = useState("");
3273
3287
  const [isLoading, setIsLoading] = useState(false);
3274
3288
  const [error, setError] = useState(null);
3289
+ const [notice, setNotice] = useState(null);
3275
3290
  const [tokens, setTokens] = useState(0);
3276
3291
  const abortRef = useRef(null);
3277
3292
  const requestIdRef = useRef(0);
@@ -3292,6 +3307,7 @@ function useAiFigure(generator) {
3292
3307
  abortRef.current = controller;
3293
3308
  setIsLoading(true);
3294
3309
  setError(null);
3310
+ setNotice(null);
3295
3311
  setTokens(0);
3296
3312
  try {
3297
3313
  const generated = await generator(problem, {
@@ -3305,6 +3321,7 @@ function useAiFigure(generator) {
3305
3321
  setError(generated.message);
3306
3322
  return null;
3307
3323
  }
3324
+ if (generated.partial) setNotice(generated.partial.message);
3308
3325
  return generated.state;
3309
3326
  } catch (caught) {
3310
3327
  if (controller.signal.aborted || caught instanceof DOMException && caught.name === "AbortError") {
@@ -3331,6 +3348,7 @@ function useAiFigure(generator) {
3331
3348
  setPrompt,
3332
3349
  isLoading,
3333
3350
  error,
3351
+ notice,
3334
3352
  submit,
3335
3353
  cancel,
3336
3354
  tokens
@@ -3374,6 +3392,7 @@ function AiFigurePrompt({ generator, onGenerated }) {
3374
3392
  setPrompt,
3375
3393
  isLoading,
3376
3394
  error,
3395
+ notice,
3377
3396
  submit,
3378
3397
  cancel,
3379
3398
  tokens
@@ -3387,6 +3406,10 @@ function AiFigurePrompt({ generator, onGenerated }) {
3387
3406
  const id = setInterval(() => setElapsed((s) => s + 1), 1e3);
3388
3407
  return () => clearInterval(id);
3389
3408
  }, [isLoading]);
3409
+ const [noticeDismissed, setNoticeDismissed] = useState(false);
3410
+ useEffect(() => {
3411
+ setNoticeDismissed(false);
3412
+ }, [notice]);
3390
3413
  const [image, setImage] = useState(null);
3391
3414
  const [ocrLoading, setOcrLoading] = useState(false);
3392
3415
  const [ocrError, setOcrError] = useState(null);
@@ -3602,7 +3625,30 @@ function AiFigurePrompt({ generator, onGenerated }) {
3602
3625
  }
3603
3626
  ),
3604
3627
  ocrError && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-1 px-1 text-xs text-red-600", children: ocrError }),
3605
- error && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-1 px-1 text-xs text-red-600", children: error })
3628
+ error && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-1 px-1 text-xs text-red-600", children: error }),
3629
+ notice && !noticeDismissed && /* @__PURE__ */ jsxs(
3630
+ "div",
3631
+ {
3632
+ role: "status",
3633
+ "data-testid": "geometry-ai-partial-notice",
3634
+ className: "relative mt-2 whitespace-pre-wrap rounded-lg border border-amber-200 bg-amber-50 py-2 pl-3 pr-8 text-xs leading-relaxed text-amber-800",
3635
+ children: [
3636
+ notice,
3637
+ /* @__PURE__ */ jsx(
3638
+ "button",
3639
+ {
3640
+ type: "button",
3641
+ onClick: () => setNoticeDismissed(true),
3642
+ "aria-label": "\u0110\xF3ng th\xF4ng b\xE1o",
3643
+ title: "\u0110\xF3ng th\xF4ng b\xE1o",
3644
+ "data-testid": "geometry-ai-partial-dismiss",
3645
+ className: "absolute right-1 top-1 flex h-5 w-5 items-center justify-center rounded text-amber-500 transition hover:bg-amber-100 hover:text-amber-800",
3646
+ children: "\xD7"
3647
+ }
3648
+ )
3649
+ ]
3650
+ }
3651
+ )
3606
3652
  ] });
3607
3653
  }
3608
3654
 
@@ -4111,7 +4157,8 @@ var GeometryStampHost = forwardRef(
4111
4157
  version: 1,
4112
4158
  jsonState
4113
4159
  }),
4114
- editingElementId: editingElement?.id ?? null
4160
+ editingElementId: editingElement?.id ?? null,
4161
+ preserveExistingSize: true
4115
4162
  });
4116
4163
  } catch (err) {
4117
4164
  console.error("Geometry insert failed:", err);
@@ -4199,5 +4246,5 @@ var GeometryStampHost = forwardRef(
4199
4246
  );
4200
4247
 
4201
4248
  export { GeometryStampHost };
4202
- //# sourceMappingURL=host-3UFGFMJ2.mjs.map
4203
- //# sourceMappingURL=host-3UFGFMJ2.mjs.map
4249
+ //# sourceMappingURL=host-KMWP7KBT.mjs.map
4250
+ //# sourceMappingURL=host-KMWP7KBT.mjs.map