@pinkpixel/marzipan 1.0.9 → 1.1.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 (251) hide show
  1. package/README.md +23 -1
  2. package/dist/{_basePickBy-7myk7wY6.js → _basePickBy-CBhXlrs3.js} +3 -3
  3. package/dist/{_basePickBy-7myk7wY6.js.map → _basePickBy-CBhXlrs3.js.map} +1 -1
  4. package/dist/{_baseUniq-DVSvs9C9.js → _baseUniq-BnlNEqx5.js} +2 -2
  5. package/dist/{_baseUniq-DVSvs9C9.js.map → _baseUniq-BnlNEqx5.js.map} +1 -1
  6. package/dist/actions/core/formats.d.ts.map +1 -1
  7. package/dist/actions/core/formats.js +5 -0
  8. package/dist/actions/core/formats.js.map +1 -1
  9. package/dist/actions/index.d.ts +4 -0
  10. package/dist/actions/index.d.ts.map +1 -1
  11. package/dist/actions/index.js +20 -0
  12. package/dist/actions/index.js.map +1 -1
  13. package/dist/{arc-CfMWIGxd.js → arc-DKfQKN_X.js} +2 -2
  14. package/dist/{arc-CfMWIGxd.js.map → arc-DKfQKN_X.js.map} +1 -1
  15. package/dist/{architectureDiagram-VXUJARFQ-BUbrFcAV.js → architectureDiagram-VXUJARFQ-DyTB8Kgd.js} +5 -5
  16. package/dist/{architectureDiagram-VXUJARFQ-BUbrFcAV.js.map → architectureDiagram-VXUJARFQ-DyTB8Kgd.js.map} +1 -1
  17. package/dist/{blockDiagram-VD42YOAC-jy_Bz7_a.js → blockDiagram-VD42YOAC-BCYA47jf.js} +7 -12
  18. package/dist/{blockDiagram-VD42YOAC-jy_Bz7_a.js.map → blockDiagram-VD42YOAC-BCYA47jf.js.map} +1 -1
  19. package/dist/{c4Diagram-YG6GDRKO-D-ENeA7h.js → c4Diagram-YG6GDRKO-ChtfMRpM.js} +3 -3
  20. package/dist/{c4Diagram-YG6GDRKO-D-ENeA7h.js.map → c4Diagram-YG6GDRKO-ChtfMRpM.js.map} +1 -1
  21. package/dist/channel-XZzkxuXg.js +6 -0
  22. package/dist/{channel-BCTxewZI.js.map → channel-XZzkxuXg.js.map} +1 -1
  23. package/dist/{chunk-4BX2VUAB-BPOEnnJc.js → chunk-4BX2VUAB-Cx8HPvOf.js} +2 -2
  24. package/dist/{chunk-4BX2VUAB-BPOEnnJc.js.map → chunk-4BX2VUAB-Cx8HPvOf.js.map} +1 -1
  25. package/dist/{chunk-55IACEB6-CvbNm4Ij.js → chunk-55IACEB6-DGQSbiTY.js} +2 -2
  26. package/dist/{chunk-55IACEB6-CvbNm4Ij.js.map → chunk-55IACEB6-DGQSbiTY.js.map} +1 -1
  27. package/dist/{chunk-B4BG7PRW-C_qWbbk6.js → chunk-B4BG7PRW-CY260R4Q.js} +5 -5
  28. package/dist/{chunk-B4BG7PRW-C_qWbbk6.js.map → chunk-B4BG7PRW-CY260R4Q.js.map} +1 -1
  29. package/dist/{chunk-DI55MBZ5-BiWs6KMl.js → chunk-DI55MBZ5-B4h9UrCS.js} +4 -4
  30. package/dist/{chunk-DI55MBZ5-BiWs6KMl.js.map → chunk-DI55MBZ5-B4h9UrCS.js.map} +1 -1
  31. package/dist/{chunk-FMBD7UC4-B9NJjOBf.js → chunk-FMBD7UC4-BrVGjj-q.js} +2 -2
  32. package/dist/{chunk-FMBD7UC4-B9NJjOBf.js.map → chunk-FMBD7UC4-BrVGjj-q.js.map} +1 -1
  33. package/dist/{chunk-QN33PNHL-0k4tnBW4.js → chunk-QN33PNHL-DZm-2bJu.js} +2 -2
  34. package/dist/{chunk-QN33PNHL-0k4tnBW4.js.map → chunk-QN33PNHL-DZm-2bJu.js.map} +1 -1
  35. package/dist/{chunk-QZHKN3VN-Cqlx-pCX.js → chunk-QZHKN3VN-Hi_p5q2K.js} +2 -2
  36. package/dist/{chunk-QZHKN3VN-Cqlx-pCX.js.map → chunk-QZHKN3VN-Hi_p5q2K.js.map} +1 -1
  37. package/dist/{chunk-TZMSLE5B-CIL9qnEM.js → chunk-TZMSLE5B-CIZlLW3r.js} +2 -2
  38. package/dist/{chunk-TZMSLE5B-CIL9qnEM.js.map → chunk-TZMSLE5B-CIZlLW3r.js.map} +1 -1
  39. package/dist/{classDiagram-2ON5EDUG-Cg641kit.js → classDiagram-2ON5EDUG-QSrTDjZ0.js} +3 -3
  40. package/dist/{classDiagram-2ON5EDUG-Cg641kit.js.map → classDiagram-2ON5EDUG-QSrTDjZ0.js.map} +1 -1
  41. package/dist/{classDiagram-2ON5EDUG-DvfCZ1-0.js → classDiagram-v2-WZHVMYZB-QSrTDjZ0.js} +3 -3
  42. package/dist/{classDiagram-v2-WZHVMYZB-Cg641kit.js.map → classDiagram-v2-WZHVMYZB-QSrTDjZ0.js.map} +1 -1
  43. package/dist/clone-B6rhP1DC.js +9 -0
  44. package/dist/{clone-BZ5Rkhbx.js.map → clone-B6rhP1DC.js.map} +1 -1
  45. package/dist/{cose-bilkent-S5V4N54A-DIb5rck_.js → cose-bilkent-S5V4N54A-Cz05oWQ-.js} +3 -3
  46. package/dist/{cose-bilkent-S5V4N54A-DIb5rck_.js.map → cose-bilkent-S5V4N54A-Cz05oWQ-.js.map} +1 -1
  47. package/dist/{cytoscape.esm-DfdJODL8.js → cytoscape.esm-Cvf3sx9F.js} +16 -47
  48. package/dist/{cytoscape.esm-DfdJODL8.js.map → cytoscape.esm-Cvf3sx9F.js.map} +1 -1
  49. package/dist/{dagre-6UL2VRFP-BFkZcVkL.js → dagre-6UL2VRFP-24cZIDCv.js} +7 -7
  50. package/dist/{dagre-6UL2VRFP-BFkZcVkL.js.map → dagre-6UL2VRFP-24cZIDCv.js.map} +1 -1
  51. package/dist/defaultLocale-BgPVtth8.js +172 -0
  52. package/dist/defaultLocale-BgPVtth8.js.map +1 -0
  53. package/dist/{diagram-PSM6KHXK-DyiwV-ia.js → diagram-PSM6KHXK-hMkwALkg.js} +7 -7
  54. package/dist/{diagram-PSM6KHXK-DyiwV-ia.js.map → diagram-PSM6KHXK-hMkwALkg.js.map} +1 -1
  55. package/dist/{diagram-QEK2KX5R-DxjNZqZ_.js → diagram-QEK2KX5R-DN407_qN.js} +4 -4
  56. package/dist/{diagram-QEK2KX5R-DxjNZqZ_.js.map → diagram-QEK2KX5R-DN407_qN.js.map} +1 -1
  57. package/dist/{diagram-S2PKOQOG-CCX3j4vi.js → diagram-S2PKOQOG-DYfbxKMk.js} +4 -4
  58. package/dist/{diagram-S2PKOQOG-BOO6_G9V.js.map → diagram-S2PKOQOG-DYfbxKMk.js.map} +1 -1
  59. package/dist/{erDiagram-Q2GNP2WA-Bm9LxMmY.js → erDiagram-Q2GNP2WA-CyzD1x2b.js} +5 -5
  60. package/dist/{erDiagram-Q2GNP2WA-Bm9LxMmY.js.map → erDiagram-Q2GNP2WA-CyzD1x2b.js.map} +1 -1
  61. package/dist/{flowDiagram-NV44I4VS-CDsRBuXA.js → flowDiagram-NV44I4VS-BHrJSYHv.js} +6 -6
  62. package/dist/{flowDiagram-NV44I4VS-CDsRBuXA.js.map → flowDiagram-NV44I4VS-BHrJSYHv.js.map} +1 -1
  63. package/dist/ganttDiagram-JELNMOA3-DibD3FLu.js +2671 -0
  64. package/dist/ganttDiagram-JELNMOA3-DibD3FLu.js.map +1 -0
  65. package/dist/{gitGraphDiagram-NY62KEGX-BgmbSTgN.js → gitGraphDiagram-V2S2FVAM-BlXeU9uI.js} +5 -5
  66. package/dist/gitGraphDiagram-V2S2FVAM-BlXeU9uI.js.map +1 -0
  67. package/dist/{graph-CSVEP8oS.js → graph-BN01VVM9.js} +3 -3
  68. package/dist/{graph-CSVEP8oS.js.map → graph-BN01VVM9.js.map} +1 -1
  69. package/dist/index-DjXgvYA3.js +36 -0
  70. package/dist/index-DjXgvYA3.js.map +1 -0
  71. package/dist/index.d.ts +60 -0
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +357 -303
  74. package/dist/index.js.map +1 -1
  75. package/dist/{infoDiagram-F6ZHWCRC-BIKrEuHs.js → infoDiagram-HS3SLOUP-Dqf1wtMF.js} +3 -3
  76. package/dist/{infoDiagram-F6ZHWCRC-BIKrEuHs.js.map → infoDiagram-HS3SLOUP-Dqf1wtMF.js.map} +1 -1
  77. package/dist/{journeyDiagram-XKPGCS4Q-B5P7hkT-.js → journeyDiagram-XKPGCS4Q-DCJl6fPA.js} +5 -5
  78. package/dist/{journeyDiagram-XKPGCS4Q-B5P7hkT-.js.map → journeyDiagram-XKPGCS4Q-DCJl6fPA.js.map} +1 -1
  79. package/dist/{kanban-definition-3W4ZIXB7-DJzoU3Tr.js → kanban-definition-3W4ZIXB7-C4uKwcnd.js} +3 -3
  80. package/dist/{kanban-definition-3W4ZIXB7-CLtnd0xR.js.map → kanban-definition-3W4ZIXB7-C4uKwcnd.js.map} +1 -1
  81. package/dist/{layout-CdTiJocX.js → layout-DPZm-_SA.js} +33 -22
  82. package/dist/layout-DPZm-_SA.js.map +1 -0
  83. package/dist/{linear-Cr_O1Zei.js → linear-DgKHAz_i.js} +3 -3
  84. package/dist/{linear-BhblBDrV.js.map → linear-DgKHAz_i.js.map} +1 -1
  85. package/dist/marzipan.d.ts.map +1 -1
  86. package/dist/marzipan.js +9 -5
  87. package/dist/marzipan.js.map +1 -1
  88. package/dist/{mermaid.core-DENutRS8.js → mermaid.core-KR6iXUBd.js} +430 -415
  89. package/dist/{mermaid.core-BwjwqwU6.js.map → mermaid.core-KR6iXUBd.js.map} +1 -1
  90. package/dist/{mindmap-definition-VGOIOE7T-BNBUkXyU.js → mindmap-definition-VGOIOE7T-DDKBtjHc.js} +4 -4
  91. package/dist/{mindmap-definition-VGOIOE7T-BNBUkXyU.js.map → mindmap-definition-VGOIOE7T-DDKBtjHc.js.map} +1 -1
  92. package/dist/{ordinal-DfAQgscy.js → ordinal-B6-f3MAq.js} +2 -2
  93. package/dist/{ordinal-DfAQgscy.js.map → ordinal-B6-f3MAq.js.map} +1 -1
  94. package/dist/parser.d.ts.map +1 -1
  95. package/dist/parser.js +0 -4
  96. package/dist/parser.js.map +1 -1
  97. package/dist/{pieDiagram-ADFJNKIX-BND3UUQ-.js → pieDiagram-ADFJNKIX-hp1Z1x8W.js} +6 -6
  98. package/dist/{pieDiagram-ADFJNKIX-BND3UUQ-.js.map → pieDiagram-ADFJNKIX-hp1Z1x8W.js.map} +1 -1
  99. package/dist/plugins/accentSwatchPlugin.d.ts.map +1 -1
  100. package/dist/plugins/accentSwatchPlugin.js +33 -33
  101. package/dist/plugins/accentSwatchPlugin.js.map +1 -1
  102. package/dist/plugins/block-handles.d.ts +24 -9
  103. package/dist/plugins/block-handles.d.ts.map +1 -1
  104. package/dist/plugins/block-handles.js +102 -78
  105. package/dist/plugins/block-handles.js.map +1 -1
  106. package/dist/plugins/imageManagerPlugin.js.map +1 -1
  107. package/dist/plugins/index.d.ts +16 -0
  108. package/dist/plugins/index.d.ts.map +1 -1
  109. package/dist/plugins/index.js +29 -2
  110. package/dist/plugins/index.js.map +1 -1
  111. package/dist/plugins/mermaidPlugin.js +1 -1
  112. package/dist/plugins/tableGridPlugin.d.ts.map +1 -1
  113. package/dist/plugins/tableGridPlugin.js +23 -23
  114. package/dist/plugins/tableGridPlugin.js.map +1 -1
  115. package/dist/{quadrantDiagram-AYHSOK5B-iCwbSiz2.js → quadrantDiagram-AYHSOK5B-B9wjnoWH.js} +3 -3
  116. package/dist/{quadrantDiagram-AYHSOK5B-CnLHbrEF.js.map → quadrantDiagram-AYHSOK5B-B9wjnoWH.js.map} +1 -1
  117. package/dist/{requirementDiagram-UZGBJVZJ-CH1vdgr6.js → requirementDiagram-UZGBJVZJ-CAYg9pNG.js} +4 -4
  118. package/dist/{requirementDiagram-UZGBJVZJ-CH1vdgr6.js.map → requirementDiagram-UZGBJVZJ-CAYg9pNG.js.map} +1 -1
  119. package/dist/{sankeyDiagram-TZEHDZUN-CV5-bwv8.js → sankeyDiagram-TZEHDZUN-Dbi0-ImG.js} +3 -3
  120. package/dist/{sankeyDiagram-TZEHDZUN-CV5-bwv8.js.map → sankeyDiagram-TZEHDZUN-Dbi0-ImG.js.map} +1 -1
  121. package/dist/{sequenceDiagram-WL72ISMW-Cq1otbHU.js → sequenceDiagram-WL72ISMW-CgnGVPN0.js} +4 -4
  122. package/dist/{sequenceDiagram-WL72ISMW-BG1sXWAR.js.map → sequenceDiagram-WL72ISMW-CgnGVPN0.js.map} +1 -1
  123. package/dist/{stateDiagram-FKZM4ZOC-BJ5UwskL.js → stateDiagram-FKZM4ZOC-BnrHMBt-.js} +5 -5
  124. package/dist/{stateDiagram-FKZM4ZOC-BJ5UwskL.js.map → stateDiagram-FKZM4ZOC-BnrHMBt-.js.map} +1 -1
  125. package/dist/{stateDiagram-v2-4FDKWEC3-BbM9NXKp.js → stateDiagram-v2-4FDKWEC3-CvQCssRZ.js} +3 -3
  126. package/dist/{stateDiagram-v2-4FDKWEC3-BbM9NXKp.js.map → stateDiagram-v2-4FDKWEC3-CvQCssRZ.js.map} +1 -1
  127. package/dist/styles.d.ts.map +1 -1
  128. package/dist/styles.js +25 -21
  129. package/dist/styles.js.map +1 -1
  130. package/dist/themes.d.ts +6 -0
  131. package/dist/themes.d.ts.map +1 -1
  132. package/dist/themes.js +2 -0
  133. package/dist/themes.js.map +1 -1
  134. package/dist/{timeline-definition-IT6M3QCI-B4lGoGS8.js → timeline-definition-IT6M3QCI-C9po0EuD.js} +3 -3
  135. package/dist/{timeline-definition-IT6M3QCI-CqPEUsh4.js.map → timeline-definition-IT6M3QCI-C9po0EuD.js.map} +1 -1
  136. package/dist/treemap-GDKQZRPO-DUJ_UgsM.js +17929 -0
  137. package/dist/treemap-GDKQZRPO-DUJ_UgsM.js.map +1 -0
  138. package/dist/{xychartDiagram-PRI3JC2R-C3_IO4Rm.js → xychartDiagram-PRI3JC2R-Daz1URdd.js} +4 -4
  139. package/dist/{xychartDiagram-PRI3JC2R-C3_IO4Rm.js.map → xychartDiagram-PRI3JC2R-Daz1URdd.js.map} +1 -1
  140. package/docs/.vitepress/config.ts +77 -0
  141. package/docs/README.md +3 -1
  142. package/docs/TABLE_OF_CONTENTS.md +1 -0
  143. package/docs/api.md +42 -2
  144. package/docs/{block-handles.README.md → block-handles.md} +2 -6
  145. package/docs/index.md +95 -0
  146. package/docs/plugins.md +24 -0
  147. package/docs/public/favicon.png +0 -0
  148. package/docs/public/logo.png +0 -0
  149. package/docs/types.d.ts +1 -1
  150. package/docs/types.md +150 -0
  151. package/package.json +11 -4
  152. package/dist/_basePickBy-BXyyc71p.js +0 -152
  153. package/dist/_basePickBy-BXyyc71p.js.map +0 -1
  154. package/dist/_baseUniq-Dde5pUWM.js +0 -615
  155. package/dist/_baseUniq-Dde5pUWM.js.map +0 -1
  156. package/dist/arc-wOVD9GAB.js +0 -84
  157. package/dist/arc-wOVD9GAB.js.map +0 -1
  158. package/dist/architectureDiagram-VXUJARFQ-Bb4i7x-6.js +0 -4663
  159. package/dist/architectureDiagram-VXUJARFQ-Bb4i7x-6.js.map +0 -1
  160. package/dist/blockDiagram-VD42YOAC-ldSoJhgA.js +0 -2262
  161. package/dist/blockDiagram-VD42YOAC-ldSoJhgA.js.map +0 -1
  162. package/dist/c4Diagram-YG6GDRKO-zzDx0s1r.js +0 -1581
  163. package/dist/c4Diagram-YG6GDRKO-zzDx0s1r.js.map +0 -1
  164. package/dist/channel-BCTxewZI.js +0 -6
  165. package/dist/channel-CwQyz_h8.js +0 -6
  166. package/dist/channel-CwQyz_h8.js.map +0 -1
  167. package/dist/chunk-4BX2VUAB-Cfh_4i4X.js +0 -9
  168. package/dist/chunk-4BX2VUAB-Cfh_4i4X.js.map +0 -1
  169. package/dist/chunk-55IACEB6-DNOIVRvW.js +0 -9
  170. package/dist/chunk-55IACEB6-DNOIVRvW.js.map +0 -1
  171. package/dist/chunk-B4BG7PRW-DeY8sefa.js +0 -1376
  172. package/dist/chunk-B4BG7PRW-DeY8sefa.js.map +0 -1
  173. package/dist/chunk-DI55MBZ5-D_yXJA03.js +0 -1371
  174. package/dist/chunk-DI55MBZ5-D_yXJA03.js.map +0 -1
  175. package/dist/chunk-FMBD7UC4-DFfhN2XA.js +0 -20
  176. package/dist/chunk-FMBD7UC4-DFfhN2XA.js.map +0 -1
  177. package/dist/chunk-QN33PNHL-CVrLUVsI.js +0 -20
  178. package/dist/chunk-QN33PNHL-CVrLUVsI.js.map +0 -1
  179. package/dist/chunk-QZHKN3VN-FvAf_VJR.js +0 -16
  180. package/dist/chunk-QZHKN3VN-FvAf_VJR.js.map +0 -1
  181. package/dist/chunk-TZMSLE5B-DxYTPD3t.js +0 -65
  182. package/dist/chunk-TZMSLE5B-DxYTPD3t.js.map +0 -1
  183. package/dist/classDiagram-2ON5EDUG-DvfCZ1-0.js.map +0 -1
  184. package/dist/classDiagram-v2-WZHVMYZB-Cg641kit.js +0 -17
  185. package/dist/classDiagram-v2-WZHVMYZB-DvfCZ1-0.js +0 -17
  186. package/dist/classDiagram-v2-WZHVMYZB-DvfCZ1-0.js.map +0 -1
  187. package/dist/clone-BZ5Rkhbx.js +0 -9
  188. package/dist/clone-D062_nJ-.js +0 -9
  189. package/dist/clone-D062_nJ-.js.map +0 -1
  190. package/dist/cose-bilkent-S5V4N54A-Doh7yBTX.js +0 -2609
  191. package/dist/cose-bilkent-S5V4N54A-Doh7yBTX.js.map +0 -1
  192. package/dist/dagre-6UL2VRFP-CZKadRq9.js +0 -445
  193. package/dist/dagre-6UL2VRFP-CZKadRq9.js.map +0 -1
  194. package/dist/defaultLocale-D7EN2tov.js +0 -172
  195. package/dist/defaultLocale-D7EN2tov.js.map +0 -1
  196. package/dist/diagram-PSM6KHXK-VDtnZynV.js +0 -532
  197. package/dist/diagram-PSM6KHXK-VDtnZynV.js.map +0 -1
  198. package/dist/diagram-QEK2KX5R-Dczirmo7.js +0 -218
  199. package/dist/diagram-QEK2KX5R-Dczirmo7.js.map +0 -1
  200. package/dist/diagram-S2PKOQOG-BOO6_G9V.js +0 -143
  201. package/dist/diagram-S2PKOQOG-CCX3j4vi.js.map +0 -1
  202. package/dist/erDiagram-Q2GNP2WA-nwmrf6lJ.js +0 -842
  203. package/dist/erDiagram-Q2GNP2WA-nwmrf6lJ.js.map +0 -1
  204. package/dist/flowDiagram-NV44I4VS-DQEdMlRX.js +0 -1621
  205. package/dist/flowDiagram-NV44I4VS-DQEdMlRX.js.map +0 -1
  206. package/dist/ganttDiagram-LVOFAZNH-BHG15mHm.js +0 -2506
  207. package/dist/ganttDiagram-LVOFAZNH-BHG15mHm.js.map +0 -1
  208. package/dist/ganttDiagram-LVOFAZNH-WMiy-Gep.js +0 -2506
  209. package/dist/ganttDiagram-LVOFAZNH-WMiy-Gep.js.map +0 -1
  210. package/dist/gitGraphDiagram-NY62KEGX-BgmbSTgN.js.map +0 -1
  211. package/dist/gitGraphDiagram-NY62KEGX-D_Oe_z5q.js +0 -700
  212. package/dist/gitGraphDiagram-NY62KEGX-D_Oe_z5q.js.map +0 -1
  213. package/dist/graph-DnSw707R.js +0 -248
  214. package/dist/graph-DnSw707R.js.map +0 -1
  215. package/dist/infoDiagram-F6ZHWCRC-BzTgHHGF.js +0 -25
  216. package/dist/infoDiagram-F6ZHWCRC-BzTgHHGF.js.map +0 -1
  217. package/dist/journeyDiagram-XKPGCS4Q-Cwx0rvbI.js +0 -835
  218. package/dist/journeyDiagram-XKPGCS4Q-Cwx0rvbI.js.map +0 -1
  219. package/dist/kanban-definition-3W4ZIXB7-CLtnd0xR.js +0 -720
  220. package/dist/kanban-definition-3W4ZIXB7-DJzoU3Tr.js.map +0 -1
  221. package/dist/layout-CdTiJocX.js.map +0 -1
  222. package/dist/layout-mDCCYMKB.js +0 -1325
  223. package/dist/layout-mDCCYMKB.js.map +0 -1
  224. package/dist/linear-BhblBDrV.js +0 -260
  225. package/dist/linear-Cr_O1Zei.js.map +0 -1
  226. package/dist/mermaid.core-BwjwqwU6.js +0 -15249
  227. package/dist/mermaid.core-DENutRS8.js.map +0 -1
  228. package/dist/mindmap-definition-VGOIOE7T-BXBE9eta.js +0 -785
  229. package/dist/mindmap-definition-VGOIOE7T-BXBE9eta.js.map +0 -1
  230. package/dist/pieDiagram-ADFJNKIX-DgEtM4kB.js +0 -162
  231. package/dist/pieDiagram-ADFJNKIX-DgEtM4kB.js.map +0 -1
  232. package/dist/quadrantDiagram-AYHSOK5B-CnLHbrEF.js +0 -1023
  233. package/dist/quadrantDiagram-AYHSOK5B-iCwbSiz2.js.map +0 -1
  234. package/dist/requirementDiagram-UZGBJVZJ-caC7K17a.js +0 -851
  235. package/dist/requirementDiagram-UZGBJVZJ-caC7K17a.js.map +0 -1
  236. package/dist/sankeyDiagram-TZEHDZUN-Gl503N-l.js +0 -811
  237. package/dist/sankeyDiagram-TZEHDZUN-Gl503N-l.js.map +0 -1
  238. package/dist/sequenceDiagram-WL72ISMW-BG1sXWAR.js +0 -2512
  239. package/dist/sequenceDiagram-WL72ISMW-Cq1otbHU.js.map +0 -1
  240. package/dist/stateDiagram-FKZM4ZOC-DZEKan9V.js +0 -264
  241. package/dist/stateDiagram-FKZM4ZOC-DZEKan9V.js.map +0 -1
  242. package/dist/stateDiagram-v2-4FDKWEC3-H1gqsSsO.js +0 -17
  243. package/dist/stateDiagram-v2-4FDKWEC3-H1gqsSsO.js.map +0 -1
  244. package/dist/timeline-definition-IT6M3QCI-B4lGoGS8.js.map +0 -1
  245. package/dist/timeline-definition-IT6M3QCI-CqPEUsh4.js +0 -796
  246. package/dist/treemap-75Q7IDZK-Cx8WKL-4.js +0 -12988
  247. package/dist/treemap-75Q7IDZK-Cx8WKL-4.js.map +0 -1
  248. package/dist/treemap-75Q7IDZK-DmPg5GN7.js +0 -12988
  249. package/dist/treemap-75Q7IDZK-DmPg5GN7.js.map +0 -1
  250. package/dist/xychartDiagram-PRI3JC2R-DnhFwjWO.js +0 -1341
  251. package/dist/xychartDiagram-PRI3JC2R-DnhFwjWO.js.map +0 -1
@@ -1,16 +1,16 @@
1
1
  class r {
2
- constructor(e, t, i = {}) {
2
+ constructor(e, t, n = {}) {
3
3
  this.editor = e, this.preview = t, this.config = {
4
- enabled: i.enabled ?? !0,
5
- showOnHover: i.showOnHover ?? !0,
6
- handleOffset: i.handleOffset ?? -30,
7
- handleSize: i.handleSize ?? 20,
4
+ enabled: n.enabled ?? !0,
5
+ showOnHover: n.showOnHover ?? !0,
6
+ handleOffset: n.handleOffset ?? 4,
7
+ handleSize: n.handleSize ?? 20,
8
8
  colors: {
9
- hover: i.colors?.hover ?? "rgba(59, 130, 246, 0.1)",
10
- selected: i.colors?.selected ?? "rgba(59, 130, 246, 0.2)",
11
- handle: i.colors?.handle ?? "rgba(59, 130, 246, 0.8)"
9
+ hover: n.colors?.hover ?? "rgba(59, 130, 246, 0.1)",
10
+ selected: n.colors?.selected ?? "rgba(59, 130, 246, 0.2)",
11
+ handle: n.colors?.handle ?? "rgba(59, 130, 246, 0.8)"
12
12
  }
13
- }, this.blocks = /* @__PURE__ */ new Map(), this.selectedBlockId = null, this.handleContainer = null, this.initialize();
13
+ }, this.blocks = /* @__PURE__ */ new Map(), this.selectedBlockId = null, this.handleContainer = null, this._boundMouseMove = this.handleMouseMove.bind(this), this._boundMouseLeave = this.handleMouseLeave.bind(this), this._boundClick = this.handleClick.bind(this), this._boundKeyDown = this.handleKeyDown.bind(this), this.initialize();
14
14
  }
15
15
  /**
16
16
  * Initialize the plugin
@@ -19,7 +19,9 @@ class r {
19
19
  this.config.enabled && (this.createHandleContainer(), this.setupEventListeners(), this.scanBlocks());
20
20
  }
21
21
  /**
22
- * Create the container for block handles
22
+ * Create the container for block handles.
23
+ * Appended to the wrapper (parent of preview) so it sits above the textarea
24
+ * and is not subject to the preview's pointer-events: none rule.
23
25
  */
24
26
  createHandleContainer() {
25
27
  this.handleContainer = document.createElement("div"), this.handleContainer.className = "mz-block-handles", this.handleContainer.style.cssText = `
@@ -29,14 +31,18 @@ class r {
29
31
  width: 100%;
30
32
  height: 100%;
31
33
  pointer-events: none;
32
- z-index: 10;
33
- `, this.preview.style.position = "relative", this.preview.appendChild(this.handleContainer);
34
+ z-index: 2;
35
+ `;
36
+ const e = this.preview.parentElement;
37
+ e && e.appendChild(this.handleContainer);
34
38
  }
35
39
  /**
36
- * Set up event listeners for block interactions
40
+ * Set up event listeners for block interactions.
41
+ * We listen on both the textarea (normal mode) and the preview (preview mode),
42
+ * since in preview mode the textarea is display:none and the preview has pointer-events:auto.
37
43
  */
38
44
  setupEventListeners() {
39
- this.preview.addEventListener("mousemove", this.handleMouseMove.bind(this)), this.preview.addEventListener("mouseleave", this.handleMouseLeave.bind(this)), this.preview.addEventListener("click", this.handleClick.bind(this)), document.addEventListener("keydown", this.handleKeyDown.bind(this));
45
+ this.editor.addEventListener("mousemove", this._boundMouseMove), this.editor.addEventListener("mouseleave", this._boundMouseLeave), this.editor.addEventListener("click", this._boundClick), this.preview.addEventListener("mousemove", this._boundMouseMove), this.preview.addEventListener("mouseleave", this._boundMouseLeave), this.preview.addEventListener("click", this._boundClick), document.addEventListener("keydown", this._boundKeyDown);
40
46
  }
41
47
  /**
42
48
  * Scan the preview for blocks and create handles
@@ -44,25 +50,25 @@ class r {
44
50
  scanBlocks() {
45
51
  if (this.blocks.clear(), !this.handleContainer) return;
46
52
  this.handleContainer.innerHTML = "", this.preview.querySelectorAll("[data-block-id]").forEach((t) => {
47
- const i = t.getAttribute("data-block-id"), s = t.getAttribute("data-block-type"), n = parseInt(t.getAttribute("data-line-start") || "0", 10), c = parseInt(t.getAttribute("data-line-end") || "0", 10);
53
+ const n = t, i = n.getAttribute("data-block-id"), s = n.getAttribute("data-block-type"), c = parseInt(n.getAttribute("data-line-start") || "0", 10), l = parseInt(n.getAttribute("data-line-end") || "0", 10);
48
54
  if (!i) return;
49
- const l = this.createHandle(i, s || "paragraph", t);
55
+ const a = this.createHandle(i, s || "paragraph");
50
56
  this.blocks.set(i, {
51
57
  id: i,
52
58
  type: s || "paragraph",
53
- lineStart: n,
54
- lineEnd: c,
55
- element: t,
56
- handleElement: l
59
+ lineStart: c,
60
+ lineEnd: l,
61
+ element: n,
62
+ handleElement: a
57
63
  });
58
64
  });
59
65
  }
60
66
  /**
61
67
  * Create a handle element for a block
62
68
  */
63
- createHandle(e, t, i) {
64
- const s = document.createElement("div");
65
- return s.className = `mz-block-handle mz-block-handle-${t}`, s.setAttribute("data-block-id", e), s.style.cssText = `
69
+ createHandle(e, t) {
70
+ const n = document.createElement("div");
71
+ return n.className = `mz-block-handle mz-block-handle-${t}`, n.setAttribute("data-block-id", e), n.style.cssText = `
66
72
  position: absolute;
67
73
  width: ${this.config.handleSize}px;
68
74
  height: ${this.config.handleSize}px;
@@ -72,18 +78,18 @@ class r {
72
78
  cursor: pointer;
73
79
  opacity: 0;
74
80
  transition: opacity 0.2s ease;
75
- pointer-events: auto;
81
+ pointer-events: none;
76
82
  display: flex;
77
83
  align-items: center;
78
84
  justify-content: center;
79
85
  color: white;
80
86
  font-size: 12px;
81
87
  user-select: none;
82
- `, s.innerHTML = this.getHandleIcon(t), s.addEventListener("click", (n) => {
83
- n.stopPropagation(), this.selectBlock(e);
84
- }), s.addEventListener("contextmenu", (n) => {
85
- n.preventDefault(), n.stopPropagation(), this.showContextMenu(e, n);
86
- }), this.handleContainer?.appendChild(s), this.updateHandlePosition(e), s;
88
+ `, n.innerHTML = this.getHandleIcon(t), n.addEventListener("click", (i) => {
89
+ i.stopPropagation(), this.selectBlock(e);
90
+ }), n.addEventListener("contextmenu", (i) => {
91
+ i.preventDefault(), i.stopPropagation(), this.showContextMenu(e, i);
92
+ }), this.handleContainer?.appendChild(n), this.updateHandlePosition(e), n;
87
93
  }
88
94
  /**
89
95
  * Get icon for handle based on block type
@@ -102,13 +108,14 @@ class r {
102
108
  }[e] || "○";
103
109
  }
104
110
  /**
105
- * Update handle position based on block element position
111
+ * Update handle position based on block element position.
112
+ * Uses viewport-relative coordinates so scrolling is automatically accounted for.
106
113
  */
107
114
  updateHandlePosition(e) {
108
115
  const t = this.blocks.get(e);
109
116
  if (!t || !t.handleElement) return;
110
- const i = t.element.getBoundingClientRect(), s = this.preview.getBoundingClientRect(), n = i.top - s.top + this.preview.scrollTop;
111
- t.handleElement.style.top = `${n}px`;
117
+ const n = t.element.getBoundingClientRect(), i = this.preview.getBoundingClientRect(), s = n.top - i.top;
118
+ t.handleElement.style.top = `${s}px`;
112
119
  }
113
120
  /**
114
121
  * Update all handle positions (call on scroll/resize)
@@ -119,16 +126,33 @@ class r {
119
126
  });
120
127
  }
121
128
  /**
122
- * Handle mouse move for hover effects
129
+ * Find the preview block element at a given viewport position.
130
+ * Extends the hit rect to the left by handleOffset + handleSize so the
131
+ * mouse can reach the handle without triggering a hide.
132
+ */
133
+ findBlockAtPoint(e, t) {
134
+ const n = this.config.handleOffset + this.config.handleSize;
135
+ for (const i of this.blocks.values()) {
136
+ const s = i.element.getBoundingClientRect();
137
+ if (e >= s.left - n && e <= s.right && t >= s.top && t <= s.bottom)
138
+ return i.element;
139
+ }
140
+ return null;
141
+ }
142
+ /**
143
+ * Handle mouse move for hover effects.
144
+ * Listens on both the textarea (normal mode) and the preview (preview mode).
123
145
  */
124
146
  handleMouseMove(e) {
125
147
  if (!this.config.showOnHover) return;
126
- const t = e.target, i = this.findBlockElement(t);
127
- if (i) {
128
- const s = i.getAttribute("data-block-id");
129
- s && (this.showHandle(s), this.highlightBlock(s, !1));
148
+ const t = document.elementFromPoint(e.clientX, e.clientY);
149
+ if (t && t.closest?.(".mz-block-handle")) return;
150
+ const n = this.findBlockAtPoint(e.clientX, e.clientY);
151
+ if (n) {
152
+ const i = n.getAttribute("data-block-id");
153
+ i && (this.showHandle(i), i !== this.selectedBlockId && this.highlightBlock(i, !1));
130
154
  } else
131
- this.hideAllHandles(), this.unhighlightAll();
155
+ this.hideAllHandles(), this.unhighlightAll(!0);
132
156
  }
133
157
  /**
134
158
  * Handle mouse leave event
@@ -137,14 +161,20 @@ class r {
137
161
  this.hideAllHandles(), this.unhighlightAll(!0);
138
162
  }
139
163
  /**
140
- * Handle click events for block selection
164
+ * Handle click events for block selection.
165
+ * Clicks anywhere in the left handle-zone (the padding area left of block text)
166
+ * select the block — no shift key required. Shift+click anywhere on the block
167
+ * also selects it. Clicking in normal text area deselects.
141
168
  */
142
169
  handleClick(e) {
143
- const t = e.target, i = this.findBlockElement(t);
144
- if (i) {
145
- const s = i.getAttribute("data-block-id");
146
- s && e.shiftKey && (e.preventDefault(), this.selectBlock(s));
147
- } else t.closest(".mz-block-handle") || this.deselectBlock();
170
+ const t = this.findBlockAtPoint(e.clientX, e.clientY);
171
+ if (t) {
172
+ const n = t.getAttribute("data-block-id");
173
+ if (n) {
174
+ const i = t.getBoundingClientRect();
175
+ e.clientX < i.left || e.shiftKey ? (e.preventDefault(), this.selectBlock(n)) : this.selectedBlockId && this.deselectBlock();
176
+ }
177
+ } else e.target.closest?.(".mz-block-handle") || this.deselectBlock();
148
178
  }
149
179
  /**
150
180
  * Handle keyboard shortcuts
@@ -152,35 +182,29 @@ class r {
152
182
  handleKeyDown(e) {
153
183
  this.selectedBlockId && ((e.ctrlKey || e.metaKey) && e.key === "c" && !this.editor.selectionStart && (e.preventDefault(), this.copyBlock(this.selectedBlockId)), (e.key === "Delete" || e.key === "Backspace") && !this.editor.selectionStart && (e.preventDefault(), this.deleteBlock(this.selectedBlockId)), e.key === "Escape" && this.deselectBlock());
154
184
  }
155
- /**
156
- * Find the block element from any child element
157
- */
158
- findBlockElement(e) {
159
- return e ? e.hasAttribute("data-block-id") ? e : e.closest("[data-block-id]") : null;
160
- }
161
185
  /**
162
186
  * Show a specific handle
163
187
  */
164
188
  showHandle(e) {
165
189
  const t = this.blocks.get(e);
166
- t?.handleElement && (t.handleElement.style.opacity = "1");
190
+ t?.handleElement && (t.handleElement.style.opacity = "1", t.handleElement.style.pointerEvents = "auto");
167
191
  }
168
192
  /**
169
193
  * Hide all handles except selected
170
194
  */
171
195
  hideAllHandles() {
172
196
  this.blocks.forEach((e) => {
173
- e.handleElement && e.id !== this.selectedBlockId && (e.handleElement.style.opacity = "0");
197
+ e.handleElement && e.id !== this.selectedBlockId && (e.handleElement.style.opacity = "0", e.handleElement.style.pointerEvents = "none");
174
198
  });
175
199
  }
176
200
  /**
177
201
  * Highlight a block
178
202
  */
179
203
  highlightBlock(e, t) {
180
- const i = this.blocks.get(e);
181
- if (!i) return;
182
- const s = t ? this.config.colors.selected : this.config.colors.hover;
183
- i.element.style.backgroundColor = s;
204
+ const n = this.blocks.get(e);
205
+ if (!n) return;
206
+ const i = t ? this.config.colors.selected : this.config.colors.hover;
207
+ n.element.style.backgroundColor = i ?? "";
184
208
  }
185
209
  /**
186
210
  * Remove highlight from all blocks
@@ -197,7 +221,7 @@ class r {
197
221
  if (this.selectedBlockId) {
198
222
  this.unhighlightAll();
199
223
  const t = this.blocks.get(this.selectedBlockId);
200
- t?.handleElement && (t.handleElement.style.opacity = "0");
224
+ t?.handleElement && (t.handleElement.style.opacity = "0", t.handleElement.style.pointerEvents = "none");
201
225
  }
202
226
  this.selectedBlockId = e, this.highlightBlock(e, !0), this.showHandle(e), this.preview.dispatchEvent(new CustomEvent("blockSelected", {
203
227
  detail: { blockId: e, block: this.blocks.get(e) }
@@ -219,11 +243,11 @@ class r {
219
243
  async copyBlock(e) {
220
244
  const t = this.blocks.get(e);
221
245
  if (!t) return;
222
- const i = this.getBlockContent(t);
246
+ const n = this.getBlockContent(t);
223
247
  try {
224
- await navigator.clipboard.writeText(i), this.showToast("Block copied to clipboard");
225
- } catch (s) {
226
- console.error("Failed to copy block:", s), this.showToast("Failed to copy block", "error");
248
+ await navigator.clipboard.writeText(n), this.showToast("Block copied to clipboard");
249
+ } catch (i) {
250
+ console.error("Failed to copy block:", i), this.showToast("Failed to copy block", "error");
227
251
  }
228
252
  }
229
253
  /**
@@ -232,9 +256,9 @@ class r {
232
256
  deleteBlock(e) {
233
257
  const t = this.blocks.get(e);
234
258
  if (!t) return;
235
- const s = this.editor.value.split(`
259
+ const i = this.editor.value.split(`
236
260
  `);
237
- s.splice(t.lineStart, t.lineEnd - t.lineStart + 1), this.editor.value = s.join(`
261
+ i.splice(t.lineStart, t.lineEnd - t.lineStart + 1), this.editor.value = i.join(`
238
262
  `), this.editor.dispatchEvent(new Event("input", { bubbles: !0 })), this.deselectBlock(), this.showToast("Block deleted");
239
263
  }
240
264
  /**
@@ -249,10 +273,10 @@ class r {
249
273
  * Show context menu for block actions
250
274
  */
251
275
  showContextMenu(e, t) {
252
- const i = document.querySelector(".mz-block-context-menu");
253
- i && i.remove();
254
- const s = document.createElement("div");
255
- s.className = "mz-block-context-menu", s.style.cssText = `
276
+ const n = document.querySelector(".mz-block-context-menu");
277
+ n && n.remove();
278
+ const i = document.createElement("div");
279
+ i.className = "mz-block-context-menu", i.style.cssText = `
256
280
  position: fixed;
257
281
  top: ${t.clientY}px;
258
282
  left: ${t.clientX}px;
@@ -280,11 +304,11 @@ class r {
280
304
  }), o.addEventListener("mouseleave", () => {
281
305
  o.style.backgroundColor = "";
282
306
  }), o.addEventListener("click", () => {
283
- a(), s.remove();
284
- }), s.appendChild(o);
285
- }), document.body.appendChild(s);
307
+ a(), i.remove();
308
+ }), i.appendChild(o);
309
+ }), document.body.appendChild(i);
286
310
  const c = (l) => {
287
- s.contains(l.target) || (s.remove(), document.removeEventListener("click", c));
311
+ i.contains(l.target) || (i.remove(), document.removeEventListener("click", c));
288
312
  };
289
313
  setTimeout(() => {
290
314
  document.addEventListener("click", c);
@@ -294,8 +318,8 @@ class r {
294
318
  * Show a toast notification
295
319
  */
296
320
  showToast(e, t = "success") {
297
- const i = document.createElement("div");
298
- i.className = "mz-toast", i.textContent = e, i.style.cssText = `
321
+ const n = document.createElement("div");
322
+ n.className = "mz-toast", n.textContent = e, n.style.cssText = `
299
323
  position: fixed;
300
324
  bottom: 20px;
301
325
  right: 20px;
@@ -308,21 +332,21 @@ class r {
308
332
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
309
333
  font-size: 14px;
310
334
  animation: slideIn 0.3s ease;
311
- `, document.body.appendChild(i), setTimeout(() => {
312
- i.style.animation = "slideOut 0.3s ease", setTimeout(() => i.remove(), 300);
335
+ `, document.body.appendChild(n), setTimeout(() => {
336
+ n.style.animation = "slideOut 0.3s ease", setTimeout(() => n.remove(), 300);
313
337
  }, 2e3);
314
338
  }
315
339
  /**
316
340
  * Enable the plugin
317
341
  */
318
342
  enable() {
319
- this.config.enabled = !0, this.initialize();
343
+ this.config.enabled || (this.config.enabled = !0, this.initialize());
320
344
  }
321
345
  /**
322
346
  * Disable the plugin
323
347
  */
324
348
  disable() {
325
- this.config.enabled = !1, this.handleContainer?.remove(), this.handleContainer = null, this.blocks.clear(), this.selectedBlockId = null;
349
+ this.config.enabled = !1, this.handleContainer?.remove(), this.handleContainer = null, this.blocks.clear(), this.selectedBlockId = null, this.editor.removeEventListener("mousemove", this._boundMouseMove), this.editor.removeEventListener("mouseleave", this._boundMouseLeave), this.editor.removeEventListener("click", this._boundClick), this.preview.removeEventListener("mousemove", this._boundMouseMove), this.preview.removeEventListener("mouseleave", this._boundMouseLeave), this.preview.removeEventListener("click", this._boundClick), document.removeEventListener("keydown", this._boundKeyDown);
326
350
  }
327
351
  /**
328
352
  * Refresh the plugin (rescan blocks and update positions)
@@ -346,7 +370,7 @@ class r {
346
370
  * Clean up and remove the plugin
347
371
  */
348
372
  destroy() {
349
- this.disable(), this.preview.removeEventListener("mousemove", this.handleMouseMove.bind(this)), this.preview.removeEventListener("mouseleave", this.handleMouseLeave.bind(this)), this.preview.removeEventListener("click", this.handleClick.bind(this)), document.removeEventListener("keydown", this.handleKeyDown.bind(this));
373
+ this.disable();
350
374
  }
351
375
  }
352
376
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"block-handles.js","sources":["../../src/plugins/block-handles.ts"],"sourcesContent":["// @ts-nocheck\n/**\n * Block Handles Plugin\n * \n * Provides interactive handles on the left side of markdown blocks in the preview overlay.\n * Handles appear on hover and provide quick actions for block manipulation.\n * \n * Features:\n * - Hover to show handles\n * - Click to select blocks\n * - Copy block content\n * - Delete blocks\n * - Visual feedback for selected blocks\n */\n\nexport interface BlockHandle {\n id: string;\n type: string;\n lineStart: number;\n lineEnd: number;\n element: HTMLElement;\n handleElement: HTMLElement | null;\n}\n\nexport interface BlockHandlesConfig {\n enabled?: boolean;\n showOnHover?: boolean;\n handleOffset?: number;\n handleSize?: number;\n colors?: {\n hover?: string;\n selected?: string;\n handle?: string;\n };\n}\n\nexport class BlockHandlesPlugin {\n private editor: HTMLTextAreaElement;\n private preview: HTMLElement;\n private config: Required<BlockHandlesConfig>;\n private blocks: Map<string, BlockHandle>;\n private selectedBlockId: string | null;\n private handleContainer: HTMLElement | null;\n\n constructor(editor: HTMLTextAreaElement, preview: HTMLElement, config: BlockHandlesConfig = {}) {\n this.editor = editor;\n this.preview = preview;\n this.config = {\n enabled: config.enabled ?? true,\n showOnHover: config.showOnHover ?? true,\n handleOffset: config.handleOffset ?? -30,\n handleSize: config.handleSize ?? 20,\n colors: {\n hover: config.colors?.hover ?? 'rgba(59, 130, 246, 0.1)',\n selected: config.colors?.selected ?? 'rgba(59, 130, 246, 0.2)',\n handle: config.colors?.handle ?? 'rgba(59, 130, 246, 0.8)',\n },\n };\n this.blocks = new Map();\n this.selectedBlockId = null;\n this.handleContainer = null;\n\n this.initialize();\n }\n\n /**\n * Initialize the plugin\n */\n private initialize(): void {\n if (!this.config.enabled) return;\n\n // Create handle container\n this.createHandleContainer();\n\n // Set up event listeners\n this.setupEventListeners();\n\n // Initial scan for blocks\n this.scanBlocks();\n }\n\n /**\n * Create the container for block handles\n */\n private createHandleContainer(): void {\n this.handleContainer = document.createElement('div');\n this.handleContainer.className = 'mz-block-handles';\n this.handleContainer.style.cssText = `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 10;\n `;\n this.preview.style.position = 'relative';\n this.preview.appendChild(this.handleContainer);\n }\n\n /**\n * Set up event listeners for block interactions\n */\n private setupEventListeners(): void {\n // Mouse move for hover effects\n this.preview.addEventListener('mousemove', this.handleMouseMove.bind(this));\n this.preview.addEventListener('mouseleave', this.handleMouseLeave.bind(this));\n\n // Click for selection\n this.preview.addEventListener('click', this.handleClick.bind(this));\n\n // Keyboard shortcuts\n document.addEventListener('keydown', this.handleKeyDown.bind(this));\n }\n\n /**\n * Scan the preview for blocks and create handles\n */\n public scanBlocks(): void {\n this.blocks.clear();\n \n if (!this.handleContainer) return;\n\n // Clear existing handles\n this.handleContainer.innerHTML = '';\n\n // Find all elements with block metadata\n const blockElements = this.preview.querySelectorAll('[data-block-id]');\n \n blockElements.forEach((element: HTMLElement) => {\n const blockId = element.getAttribute('data-block-id');\n const blockType = element.getAttribute('data-block-type');\n const lineStart = parseInt(element.getAttribute('data-line-start') || '0', 10);\n const lineEnd = parseInt(element.getAttribute('data-line-end') || '0', 10);\n\n if (!blockId) return;\n\n // Create handle for this block\n const handle = this.createHandle(blockId, blockType || 'paragraph', element);\n\n this.blocks.set(blockId, {\n id: blockId,\n type: blockType || 'paragraph',\n lineStart,\n lineEnd,\n element,\n handleElement: handle,\n });\n });\n }\n\n /**\n * Create a handle element for a block\n */\n private createHandle(blockId: string, blockType: string, blockElement: HTMLElement): HTMLElement {\n const handle = document.createElement('div');\n handle.className = `mz-block-handle mz-block-handle-${blockType}`;\n handle.setAttribute('data-block-id', blockId);\n handle.style.cssText = `\n position: absolute;\n width: ${this.config.handleSize}px;\n height: ${this.config.handleSize}px;\n left: ${this.config.handleOffset}px;\n background: ${this.config.colors.handle};\n border-radius: 4px;\n cursor: pointer;\n opacity: 0;\n transition: opacity 0.2s ease;\n pointer-events: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 12px;\n user-select: none;\n `;\n\n // Add icon based on block type\n handle.innerHTML = this.getHandleIcon(blockType);\n\n // Handle click events\n handle.addEventListener('click', (e) => {\n e.stopPropagation();\n this.selectBlock(blockId);\n });\n\n // Show context menu on right click\n handle.addEventListener('contextmenu', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this.showContextMenu(blockId, e);\n });\n\n this.handleContainer?.appendChild(handle);\n this.updateHandlePosition(blockId);\n\n return handle;\n }\n\n /**\n * Get icon for handle based on block type\n */\n private getHandleIcon(blockType: string): string {\n const icons: Record<string, string> = {\n heading: '⚡',\n paragraph: '¶',\n 'list-item': '•',\n quote: '\"',\n 'code-fence': '{',\n 'code-content': '{}',\n hr: '―',\n 'table-row': '⊞',\n 'table-separator': '═',\n };\n return icons[blockType] || '○';\n }\n\n /**\n * Update handle position based on block element position\n */\n private updateHandlePosition(blockId: string): void {\n const block = this.blocks.get(blockId);\n if (!block || !block.handleElement) return;\n\n const blockRect = block.element.getBoundingClientRect();\n const previewRect = this.preview.getBoundingClientRect();\n\n const top = blockRect.top - previewRect.top + this.preview.scrollTop;\n \n block.handleElement.style.top = `${top}px`;\n }\n\n /**\n * Update all handle positions (call on scroll/resize)\n */\n public updateAllHandlePositions(): void {\n this.blocks.forEach((block, blockId) => {\n this.updateHandlePosition(blockId);\n });\n }\n\n /**\n * Handle mouse move for hover effects\n */\n private handleMouseMove(e: MouseEvent): void {\n if (!this.config.showOnHover) return;\n\n const target = e.target as HTMLElement;\n const blockElement = this.findBlockElement(target);\n\n if (blockElement) {\n const blockId = blockElement.getAttribute('data-block-id');\n if (blockId) {\n this.showHandle(blockId);\n this.highlightBlock(blockId, false);\n }\n } else {\n this.hideAllHandles();\n this.unhighlightAll();\n }\n }\n\n /**\n * Handle mouse leave event\n */\n private handleMouseLeave(): void {\n this.hideAllHandles();\n this.unhighlightAll(true);\n }\n\n /**\n * Handle click events for block selection\n */\n private handleClick(e: MouseEvent): void {\n const target = e.target as HTMLElement;\n const blockElement = this.findBlockElement(target);\n\n if (blockElement) {\n const blockId = blockElement.getAttribute('data-block-id');\n if (blockId && e.shiftKey) {\n e.preventDefault();\n this.selectBlock(blockId);\n }\n } else if (!target.closest('.mz-block-handle')) {\n // Click outside blocks and handles - deselect\n this.deselectBlock();\n }\n }\n\n /**\n * Handle keyboard shortcuts\n */\n private handleKeyDown(e: KeyboardEvent): void {\n if (!this.selectedBlockId) return;\n\n // Copy block (Ctrl/Cmd + C when block is selected)\n if ((e.ctrlKey || e.metaKey) && e.key === 'c' && !this.editor.selectionStart) {\n e.preventDefault();\n this.copyBlock(this.selectedBlockId);\n }\n\n // Delete block (Delete or Backspace when block is selected)\n if ((e.key === 'Delete' || e.key === 'Backspace') && !this.editor.selectionStart) {\n e.preventDefault();\n this.deleteBlock(this.selectedBlockId);\n }\n\n // Escape to deselect\n if (e.key === 'Escape') {\n this.deselectBlock();\n }\n }\n\n /**\n * Find the block element from any child element\n */\n private findBlockElement(element: HTMLElement | null): HTMLElement | null {\n if (!element) return null;\n \n // Check if element itself is a block\n if (element.hasAttribute('data-block-id')) {\n return element;\n }\n\n // Look up the tree for a block element\n return element.closest('[data-block-id]') as HTMLElement | null;\n }\n\n /**\n * Show a specific handle\n */\n private showHandle(blockId: string): void {\n const block = this.blocks.get(blockId);\n if (block?.handleElement) {\n block.handleElement.style.opacity = '1';\n }\n }\n\n /**\n * Hide all handles except selected\n */\n private hideAllHandles(): void {\n this.blocks.forEach((block) => {\n if (block.handleElement && block.id !== this.selectedBlockId) {\n block.handleElement.style.opacity = '0';\n }\n });\n }\n\n /**\n * Highlight a block\n */\n private highlightBlock(blockId: string, selected: boolean): void {\n const block = this.blocks.get(blockId);\n if (!block) return;\n\n const color = selected ? this.config.colors.selected : this.config.colors.hover;\n block.element.style.backgroundColor = color;\n }\n\n /**\n * Remove highlight from all blocks\n */\n private unhighlightAll(keepSelected: boolean = false): void {\n this.blocks.forEach((block) => {\n if (!keepSelected || block.id !== this.selectedBlockId) {\n block.element.style.backgroundColor = '';\n }\n });\n }\n\n /**\n * Select a block\n */\n private selectBlock(blockId: string): void {\n // Deselect previous block\n if (this.selectedBlockId) {\n this.unhighlightAll();\n const prevBlock = this.blocks.get(this.selectedBlockId);\n if (prevBlock?.handleElement) {\n prevBlock.handleElement.style.opacity = '0';\n }\n }\n\n // Select new block\n this.selectedBlockId = blockId;\n this.highlightBlock(blockId, true);\n this.showHandle(blockId);\n\n // Dispatch selection event\n this.preview.dispatchEvent(new CustomEvent('blockSelected', {\n detail: { blockId, block: this.blocks.get(blockId) },\n }));\n }\n\n /**\n * Deselect current block\n */\n private deselectBlock(): void {\n if (!this.selectedBlockId) return;\n\n const blockId = this.selectedBlockId;\n this.selectedBlockId = null;\n this.unhighlightAll();\n this.hideAllHandles();\n\n // Dispatch deselection event\n this.preview.dispatchEvent(new CustomEvent('blockDeselected', {\n detail: { blockId },\n }));\n }\n\n /**\n * Copy block content to clipboard\n */\n private async copyBlock(blockId: string): Promise<void> {\n const block = this.blocks.get(blockId);\n if (!block) return;\n\n const content = this.getBlockContent(block);\n \n try {\n await navigator.clipboard.writeText(content);\n this.showToast('Block copied to clipboard');\n } catch (err) {\n console.error('Failed to copy block:', err);\n this.showToast('Failed to copy block', 'error');\n }\n }\n\n /**\n * Delete a block from the editor\n */\n private deleteBlock(blockId: string): void {\n const block = this.blocks.get(blockId);\n if (!block) return;\n\n const content = this.editor.value;\n const lines = content.split('\\n');\n\n // Remove lines for this block\n lines.splice(block.lineStart, block.lineEnd - block.lineStart + 1);\n\n // Update editor\n this.editor.value = lines.join('\\n');\n \n // Trigger input event to update preview\n this.editor.dispatchEvent(new Event('input', { bubbles: true }));\n\n // Deselect and rescan\n this.deselectBlock();\n this.showToast('Block deleted');\n }\n\n /**\n * Get the text content of a block from the editor\n */\n private getBlockContent(block: BlockHandle): string {\n const content = this.editor.value;\n const lines = content.split('\\n');\n \n return lines\n .slice(block.lineStart, block.lineEnd + 1)\n .join('\\n');\n }\n\n /**\n * Show context menu for block actions\n */\n private showContextMenu(blockId: string, e: MouseEvent): void {\n // Remove existing context menu if any\n const existingMenu = document.querySelector('.mz-block-context-menu');\n if (existingMenu) {\n existingMenu.remove();\n }\n\n const menu = document.createElement('div');\n menu.className = 'mz-block-context-menu';\n menu.style.cssText = `\n position: fixed;\n top: ${e.clientY}px;\n left: ${e.clientX}px;\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n min-width: 150px;\n padding: 4px 0;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n `;\n\n const actions = [\n { label: 'Copy', action: () => this.copyBlock(blockId), icon: '📋' },\n { label: 'Delete', action: () => this.deleteBlock(blockId), icon: '🗑️' },\n { label: 'Select', action: () => this.selectBlock(blockId), icon: '✓' },\n ];\n\n actions.forEach(({ label, action, icon }) => {\n const item = document.createElement('div');\n item.className = 'mz-context-menu-item';\n item.textContent = `${icon} ${label}`;\n item.style.cssText = `\n padding: 8px 16px;\n cursor: pointer;\n user-select: none;\n `;\n\n item.addEventListener('mouseenter', () => {\n item.style.backgroundColor = '#f5f5f5';\n });\n\n item.addEventListener('mouseleave', () => {\n item.style.backgroundColor = '';\n });\n\n item.addEventListener('click', () => {\n action();\n menu.remove();\n });\n\n menu.appendChild(item);\n });\n\n document.body.appendChild(menu);\n\n // Close menu on click outside\n const closeMenu = (e: MouseEvent) => {\n if (!menu.contains(e.target as Node)) {\n menu.remove();\n document.removeEventListener('click', closeMenu);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', closeMenu);\n }, 0);\n }\n\n /**\n * Show a toast notification\n */\n private showToast(message: string, type: 'success' | 'error' = 'success'): void {\n const toast = document.createElement('div');\n toast.className = 'mz-toast';\n toast.textContent = message;\n toast.style.cssText = `\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: ${type === 'success' ? '#10b981' : '#ef4444'};\n color: white;\n padding: 12px 20px;\n border-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n animation: slideIn 0.3s ease;\n `;\n\n document.body.appendChild(toast);\n\n setTimeout(() => {\n toast.style.animation = 'slideOut 0.3s ease';\n setTimeout(() => toast.remove(), 300);\n }, 2000);\n }\n\n /**\n * Enable the plugin\n */\n public enable(): void {\n this.config.enabled = true;\n this.initialize();\n }\n\n /**\n * Disable the plugin\n */\n public disable(): void {\n this.config.enabled = false;\n this.handleContainer?.remove();\n this.handleContainer = null;\n this.blocks.clear();\n this.selectedBlockId = null;\n }\n\n /**\n * Refresh the plugin (rescan blocks and update positions)\n */\n public refresh(): void {\n this.scanBlocks();\n }\n\n /**\n * Get the currently selected block\n */\n public getSelectedBlock(): BlockHandle | null {\n return this.selectedBlockId ? this.blocks.get(this.selectedBlockId) || null : null;\n }\n\n /**\n * Get all blocks\n */\n public getAllBlocks(): BlockHandle[] {\n return Array.from(this.blocks.values());\n }\n\n /**\n * Clean up and remove the plugin\n */\n public destroy(): void {\n this.disable();\n this.preview.removeEventListener('mousemove', this.handleMouseMove.bind(this));\n this.preview.removeEventListener('mouseleave', this.handleMouseLeave.bind(this));\n this.preview.removeEventListener('click', this.handleClick.bind(this));\n document.removeEventListener('keydown', this.handleKeyDown.bind(this));\n }\n}\n"],"names":["BlockHandlesPlugin","editor","preview","config","element","blockId","blockType","lineStart","lineEnd","handle","blockElement","e","block","blockRect","previewRect","top","target","selected","color","keepSelected","prevBlock","content","err","lines","existingMenu","menu","label","action","icon","item","closeMenu","message","type","toast"],"mappings":"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"}
1
+ {"version":3,"file":"block-handles.js","sources":["../../src/plugins/block-handles.ts"],"sourcesContent":["/**\n * Block Handles Plugin\n * \n * Provides interactive handles on the left side of markdown blocks in the preview overlay.\n * Handles appear on hover and provide quick actions for block manipulation.\n * \n * Features:\n * - Hover to show handles\n * - Click to select blocks\n * - Copy block content\n * - Delete blocks\n * - Visual feedback for selected blocks\n */\n\nexport interface BlockHandle {\n id: string;\n type: string;\n lineStart: number;\n lineEnd: number;\n element: HTMLElement;\n handleElement: HTMLElement | null;\n}\n\nexport interface BlockHandlesConfig {\n enabled?: boolean;\n showOnHover?: boolean;\n handleOffset?: number;\n handleSize?: number;\n colors?: {\n hover?: string;\n selected?: string;\n handle?: string;\n };\n}\n\nexport class BlockHandlesPlugin {\n private editor: HTMLTextAreaElement;\n private preview: HTMLElement;\n private config: Required<BlockHandlesConfig>;\n private blocks: Map<string, BlockHandle>;\n private selectedBlockId: string | null;\n private handleContainer: HTMLElement | null;\n\n // Stored bound handlers for proper cleanup\n private _boundMouseMove: (e: MouseEvent) => void;\n private _boundMouseLeave: () => void;\n private _boundClick: (e: MouseEvent) => void;\n private _boundKeyDown: (e: KeyboardEvent) => void;\n\n constructor(editor: HTMLTextAreaElement, preview: HTMLElement, config: BlockHandlesConfig = {}) {\n this.editor = editor;\n this.preview = preview;\n this.config = {\n enabled: config.enabled ?? true,\n showOnHover: config.showOnHover ?? true,\n handleOffset: config.handleOffset ?? 4,\n handleSize: config.handleSize ?? 20,\n colors: {\n hover: config.colors?.hover ?? 'rgba(59, 130, 246, 0.1)',\n selected: config.colors?.selected ?? 'rgba(59, 130, 246, 0.2)',\n handle: config.colors?.handle ?? 'rgba(59, 130, 246, 0.8)',\n },\n };\n this.blocks = new Map();\n this.selectedBlockId = null;\n this.handleContainer = null;\n\n // Bind handlers once for consistent add/remove\n this._boundMouseMove = this.handleMouseMove.bind(this);\n this._boundMouseLeave = this.handleMouseLeave.bind(this);\n this._boundClick = this.handleClick.bind(this);\n this._boundKeyDown = this.handleKeyDown.bind(this);\n\n this.initialize();\n }\n\n /**\n * Initialize the plugin\n */\n private initialize(): void {\n if (!this.config.enabled) return;\n\n // Create handle container\n this.createHandleContainer();\n\n // Set up event listeners\n this.setupEventListeners();\n\n // Initial scan for blocks\n this.scanBlocks();\n }\n\n /**\n * Create the container for block handles.\n * Appended to the wrapper (parent of preview) so it sits above the textarea\n * and is not subject to the preview's pointer-events: none rule.\n */\n private createHandleContainer(): void {\n this.handleContainer = document.createElement('div');\n this.handleContainer.className = 'mz-block-handles';\n this.handleContainer.style.cssText = `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 2;\n `;\n // Attach to the wrapper (preview's parent), not the preview itself.\n // The preview has pointer-events: none which would prevent any interaction.\n const wrapper = this.preview.parentElement;\n if (wrapper) {\n wrapper.appendChild(this.handleContainer);\n }\n }\n\n /**\n * Set up event listeners for block interactions.\n * We listen on both the textarea (normal mode) and the preview (preview mode),\n * since in preview mode the textarea is display:none and the preview has pointer-events:auto.\n */\n private setupEventListeners(): void {\n // Normal overlay mode: textarea receives pointer events\n this.editor.addEventListener('mousemove', this._boundMouseMove);\n this.editor.addEventListener('mouseleave', this._boundMouseLeave);\n this.editor.addEventListener('click', this._boundClick);\n\n // Preview mode: preview has pointer-events:auto, textarea is display:none\n this.preview.addEventListener('mousemove', this._boundMouseMove);\n this.preview.addEventListener('mouseleave', this._boundMouseLeave);\n this.preview.addEventListener('click', this._boundClick);\n\n // Keyboard shortcuts\n document.addEventListener('keydown', this._boundKeyDown);\n }\n\n /**\n * Scan the preview for blocks and create handles\n */\n public scanBlocks(): void {\n this.blocks.clear();\n \n if (!this.handleContainer) return;\n\n // Clear existing handles\n this.handleContainer.innerHTML = '';\n\n // Find all elements with block metadata\n const blockElements = this.preview.querySelectorAll('[data-block-id]');\n \n blockElements.forEach((element) => {\n const el = element as HTMLElement;\n const blockId = el.getAttribute('data-block-id');\n const blockType = el.getAttribute('data-block-type');\n const lineStart = parseInt(el.getAttribute('data-line-start') || '0', 10);\n const lineEnd = parseInt(el.getAttribute('data-line-end') || '0', 10);\n\n if (!blockId) return;\n\n // Create handle for this block\n const handle = this.createHandle(blockId, blockType || 'paragraph');\n\n this.blocks.set(blockId, {\n id: blockId,\n type: blockType || 'paragraph',\n lineStart,\n lineEnd,\n element: el,\n handleElement: handle,\n });\n });\n }\n\n /**\n * Create a handle element for a block\n */\n private createHandle(blockId: string, blockType: string): HTMLElement {\n const handle = document.createElement('div');\n handle.className = `mz-block-handle mz-block-handle-${blockType}`;\n handle.setAttribute('data-block-id', blockId);\n handle.style.cssText = `\n position: absolute;\n width: ${this.config.handleSize}px;\n height: ${this.config.handleSize}px;\n left: ${this.config.handleOffset}px;\n background: ${this.config.colors.handle};\n border-radius: 4px;\n cursor: pointer;\n opacity: 0;\n transition: opacity 0.2s ease;\n pointer-events: none;\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 12px;\n user-select: none;\n `;\n\n // Add icon based on block type\n handle.innerHTML = this.getHandleIcon(blockType);\n\n // Handle click events\n handle.addEventListener('click', (e) => {\n e.stopPropagation();\n this.selectBlock(blockId);\n });\n\n // Show context menu on right click\n handle.addEventListener('contextmenu', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this.showContextMenu(blockId, e);\n });\n\n this.handleContainer?.appendChild(handle);\n this.updateHandlePosition(blockId);\n\n return handle;\n }\n\n /**\n * Get icon for handle based on block type\n */\n private getHandleIcon(blockType: string): string {\n const icons: Record<string, string> = {\n heading: '⚡',\n paragraph: '¶',\n 'list-item': '•',\n quote: '\"',\n 'code-fence': '{',\n 'code-content': '{}',\n hr: '―',\n 'table-row': '⊞',\n 'table-separator': '═',\n };\n return icons[blockType] || '○';\n }\n\n /**\n * Update handle position based on block element position.\n * Uses viewport-relative coordinates so scrolling is automatically accounted for.\n */\n private updateHandlePosition(blockId: string): void {\n const block = this.blocks.get(blockId);\n if (!block || !block.handleElement) return;\n\n const blockRect = block.element.getBoundingClientRect();\n const previewRect = this.preview.getBoundingClientRect();\n\n // blockRect.top and previewRect.top are both viewport-relative,\n // so their difference gives the offset within the visible preview area.\n const top = blockRect.top - previewRect.top;\n\n block.handleElement.style.top = `${top}px`;\n }\n\n /**\n * Update all handle positions (call on scroll/resize)\n */\n public updateAllHandlePositions(): void {\n this.blocks.forEach((_block, blockId) => {\n this.updateHandlePosition(blockId);\n });\n }\n\n /**\n * Find the preview block element at a given viewport position.\n * Extends the hit rect to the left by handleOffset + handleSize so the\n * mouse can reach the handle without triggering a hide.\n */\n private findBlockAtPoint(clientX: number, clientY: number): HTMLElement | null {\n const handleReach = this.config.handleOffset + this.config.handleSize;\n for (const block of this.blocks.values()) {\n const rect = block.element.getBoundingClientRect();\n if (clientX >= rect.left - handleReach && clientX <= rect.right &&\n clientY >= rect.top && clientY <= rect.bottom) {\n return block.element;\n }\n }\n return null;\n }\n\n /**\n * Handle mouse move for hover effects.\n * Listens on both the textarea (normal mode) and the preview (preview mode).\n */\n private handleMouseMove(e: MouseEvent): void {\n if (!this.config.showOnHover) return;\n\n // If the element actually under the cursor is a handle, keep it visible\n const elementUnder = document.elementFromPoint(e.clientX, e.clientY);\n if (elementUnder && (elementUnder as HTMLElement).closest?.('.mz-block-handle')) return;\n\n const blockElement = this.findBlockAtPoint(e.clientX, e.clientY);\n\n if (blockElement) {\n const blockId = blockElement.getAttribute('data-block-id');\n if (blockId) {\n this.showHandle(blockId);\n // Don't replace selected-color with hover-color on the selected block\n if (blockId !== this.selectedBlockId) {\n this.highlightBlock(blockId, false);\n }\n }\n } else {\n this.hideAllHandles();\n this.unhighlightAll(true); // keep selected block highlighted\n }\n }\n\n /**\n * Handle mouse leave event\n */\n private handleMouseLeave(): void {\n this.hideAllHandles();\n this.unhighlightAll(true);\n }\n\n /**\n * Handle click events for block selection.\n * Clicks anywhere in the left handle-zone (the padding area left of block text)\n * select the block — no shift key required. Shift+click anywhere on the block\n * also selects it. Clicking in normal text area deselects.\n */\n private handleClick(e: MouseEvent): void {\n const blockElement = this.findBlockAtPoint(e.clientX, e.clientY);\n\n if (blockElement) {\n const blockId = blockElement.getAttribute('data-block-id');\n if (blockId) {\n const blockRect = blockElement.getBoundingClientRect();\n // A click in the handle zone (left of where text starts) or shift+click selects\n const inHandleZone = e.clientX < blockRect.left;\n if (inHandleZone || e.shiftKey) {\n e.preventDefault();\n this.selectBlock(blockId);\n } else {\n // Normal click inside block text — deselect if something was selected\n if (this.selectedBlockId) this.deselectBlock();\n }\n }\n } else if (!(e.target as HTMLElement).closest?.('.mz-block-handle')) {\n // Click outside all blocks — deselect\n this.deselectBlock();\n }\n }\n\n /**\n * Handle keyboard shortcuts\n */\n private handleKeyDown(e: KeyboardEvent): void {\n if (!this.selectedBlockId) return;\n\n // Copy block (Ctrl/Cmd + C when block is selected)\n if ((e.ctrlKey || e.metaKey) && e.key === 'c' && !this.editor.selectionStart) {\n e.preventDefault();\n this.copyBlock(this.selectedBlockId);\n }\n\n // Delete block (Delete or Backspace when block is selected)\n if ((e.key === 'Delete' || e.key === 'Backspace') && !this.editor.selectionStart) {\n e.preventDefault();\n this.deleteBlock(this.selectedBlockId);\n }\n\n // Escape to deselect\n if (e.key === 'Escape') {\n this.deselectBlock();\n }\n }\n\n /**\n * Show a specific handle\n */\n private showHandle(blockId: string): void {\n const block = this.blocks.get(blockId);\n if (block?.handleElement) {\n block.handleElement.style.opacity = '1';\n block.handleElement.style.pointerEvents = 'auto';\n }\n }\n\n /**\n * Hide all handles except selected\n */\n private hideAllHandles(): void {\n this.blocks.forEach((block) => {\n if (block.handleElement && block.id !== this.selectedBlockId) {\n block.handleElement.style.opacity = '0';\n block.handleElement.style.pointerEvents = 'none';\n }\n });\n }\n\n /**\n * Highlight a block\n */\n private highlightBlock(blockId: string, selected: boolean): void {\n const block = this.blocks.get(blockId);\n if (!block) return;\n\n const color = selected ? this.config.colors.selected : this.config.colors.hover;\n block.element.style.backgroundColor = color ?? '';\n }\n\n /**\n * Remove highlight from all blocks\n */\n private unhighlightAll(keepSelected: boolean = false): void {\n this.blocks.forEach((block) => {\n if (!keepSelected || block.id !== this.selectedBlockId) {\n block.element.style.backgroundColor = '';\n }\n });\n }\n\n /**\n * Select a block\n */\n private selectBlock(blockId: string): void {\n // Deselect previous block\n if (this.selectedBlockId) {\n this.unhighlightAll();\n const prevBlock = this.blocks.get(this.selectedBlockId);\n if (prevBlock?.handleElement) {\n prevBlock.handleElement.style.opacity = '0';\n prevBlock.handleElement.style.pointerEvents = 'none';\n }\n }\n\n // Select new block\n this.selectedBlockId = blockId;\n this.highlightBlock(blockId, true);\n this.showHandle(blockId);\n\n // Dispatch selection event\n this.preview.dispatchEvent(new CustomEvent('blockSelected', {\n detail: { blockId, block: this.blocks.get(blockId) },\n }));\n }\n\n /**\n * Deselect current block\n */\n private deselectBlock(): void {\n if (!this.selectedBlockId) return;\n\n const blockId = this.selectedBlockId;\n this.selectedBlockId = null;\n this.unhighlightAll();\n this.hideAllHandles();\n\n // Dispatch deselection event\n this.preview.dispatchEvent(new CustomEvent('blockDeselected', {\n detail: { blockId },\n }));\n }\n\n /**\n * Copy block content to clipboard\n */\n private async copyBlock(blockId: string): Promise<void> {\n const block = this.blocks.get(blockId);\n if (!block) return;\n\n const content = this.getBlockContent(block);\n \n try {\n await navigator.clipboard.writeText(content);\n this.showToast('Block copied to clipboard');\n } catch (err) {\n console.error('Failed to copy block:', err);\n this.showToast('Failed to copy block', 'error');\n }\n }\n\n /**\n * Delete a block from the editor\n */\n private deleteBlock(blockId: string): void {\n const block = this.blocks.get(blockId);\n if (!block) return;\n\n const content = this.editor.value;\n const lines = content.split('\\n');\n\n // Remove lines for this block\n lines.splice(block.lineStart, block.lineEnd - block.lineStart + 1);\n\n // Update editor\n this.editor.value = lines.join('\\n');\n \n // Trigger input event to update preview\n this.editor.dispatchEvent(new Event('input', { bubbles: true }));\n\n // Deselect and rescan\n this.deselectBlock();\n this.showToast('Block deleted');\n }\n\n /**\n * Get the text content of a block from the editor\n */\n private getBlockContent(block: BlockHandle): string {\n const content = this.editor.value;\n const lines = content.split('\\n');\n \n return lines\n .slice(block.lineStart, block.lineEnd + 1)\n .join('\\n');\n }\n\n /**\n * Show context menu for block actions\n */\n private showContextMenu(blockId: string, e: MouseEvent): void {\n // Remove existing context menu if any\n const existingMenu = document.querySelector('.mz-block-context-menu');\n if (existingMenu) {\n existingMenu.remove();\n }\n\n const menu = document.createElement('div');\n menu.className = 'mz-block-context-menu';\n menu.style.cssText = `\n position: fixed;\n top: ${e.clientY}px;\n left: ${e.clientX}px;\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n min-width: 150px;\n padding: 4px 0;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n `;\n\n const actions = [\n { label: 'Copy', action: () => this.copyBlock(blockId), icon: '📋' },\n { label: 'Delete', action: () => this.deleteBlock(blockId), icon: '🗑️' },\n { label: 'Select', action: () => this.selectBlock(blockId), icon: '✓' },\n ];\n\n actions.forEach(({ label, action, icon }) => {\n const item = document.createElement('div');\n item.className = 'mz-context-menu-item';\n item.textContent = `${icon} ${label}`;\n item.style.cssText = `\n padding: 8px 16px;\n cursor: pointer;\n user-select: none;\n `;\n\n item.addEventListener('mouseenter', () => {\n item.style.backgroundColor = '#f5f5f5';\n });\n\n item.addEventListener('mouseleave', () => {\n item.style.backgroundColor = '';\n });\n\n item.addEventListener('click', () => {\n action();\n menu.remove();\n });\n\n menu.appendChild(item);\n });\n\n document.body.appendChild(menu);\n\n // Close menu on click outside\n const closeMenu = (e: MouseEvent) => {\n if (!menu.contains(e.target as Node)) {\n menu.remove();\n document.removeEventListener('click', closeMenu);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', closeMenu);\n }, 0);\n }\n\n /**\n * Show a toast notification\n */\n private showToast(message: string, type: 'success' | 'error' = 'success'): void {\n const toast = document.createElement('div');\n toast.className = 'mz-toast';\n toast.textContent = message;\n toast.style.cssText = `\n position: fixed;\n bottom: 20px;\n right: 20px;\n background: ${type === 'success' ? '#10b981' : '#ef4444'};\n color: white;\n padding: 12px 20px;\n border-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n animation: slideIn 0.3s ease;\n `;\n\n document.body.appendChild(toast);\n\n setTimeout(() => {\n toast.style.animation = 'slideOut 0.3s ease';\n setTimeout(() => toast.remove(), 300);\n }, 2000);\n }\n\n /**\n * Enable the plugin\n */\n public enable(): void {\n if (this.config.enabled) return; // Already enabled\n this.config.enabled = true;\n this.initialize();\n }\n\n /**\n * Disable the plugin\n */\n public disable(): void {\n this.config.enabled = false;\n this.handleContainer?.remove();\n this.handleContainer = null;\n this.blocks.clear();\n this.selectedBlockId = null;\n // Remove event listeners from both textarea and preview\n this.editor.removeEventListener('mousemove', this._boundMouseMove);\n this.editor.removeEventListener('mouseleave', this._boundMouseLeave);\n this.editor.removeEventListener('click', this._boundClick);\n this.preview.removeEventListener('mousemove', this._boundMouseMove);\n this.preview.removeEventListener('mouseleave', this._boundMouseLeave);\n this.preview.removeEventListener('click', this._boundClick);\n document.removeEventListener('keydown', this._boundKeyDown);\n }\n\n /**\n * Refresh the plugin (rescan blocks and update positions)\n */\n public refresh(): void {\n this.scanBlocks();\n }\n\n /**\n * Get the currently selected block\n */\n public getSelectedBlock(): BlockHandle | null {\n return this.selectedBlockId ? this.blocks.get(this.selectedBlockId) || null : null;\n }\n\n /**\n * Get all blocks\n */\n public getAllBlocks(): BlockHandle[] {\n return Array.from(this.blocks.values());\n }\n\n /**\n * Clean up and remove the plugin\n */\n public destroy(): void {\n this.disable();\n }\n}\n"],"names":["BlockHandlesPlugin","editor","preview","config","wrapper","element","el","blockId","blockType","lineStart","lineEnd","handle","e","block","blockRect","previewRect","top","_block","clientX","clientY","handleReach","rect","elementUnder","blockElement","selected","color","keepSelected","prevBlock","content","err","lines","existingMenu","menu","label","action","icon","item","closeMenu","message","type","toast"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"imageManagerPlugin.js","sources":["../../src/plugins/imageManagerPlugin.ts"],"sourcesContent":["// plugins/imageManagerPlugin.ts` — recents, upload, URL add, drag-drop, paste\n// =====================================================\n// Persists “recents” in `localStorage` (data-URLs for small files ≤ default 1 MB).\n// Optional `uploader(file) => Promise<string>` to store remotely and return a URL.\n// Drag files onto the editor, or paste images from clipboard—instant preview and insert.\n// Tiny panel with thumbnails; click to insert; remove/clear as needed.\n\ntype MzEditor = {\n container: HTMLElement;\n textarea: HTMLTextAreaElement;\n updatePreview: () => void;\n};\n\ntype RecentImage = { url: string; name: string; createdAt: number; persistent: boolean };\n\nconst LS_KEY = 'marzipan.images';\n\nfunction insertAtCursor(editor: MzEditor, text: string) {\n const ta = editor.textarea;\n const s = ta.selectionStart ?? 0, e = ta.selectionEnd ?? 0;\n ta.setRangeText(text, s, e, 'end');\n editor.updatePreview();\n ta.focus();\n}\n\nfunction loadRecents(): RecentImage[] {\n try { return JSON.parse(localStorage.getItem(LS_KEY) || '[]'); }\n catch { return []; }\n}\nfunction saveRecents(list: RecentImage[]) {\n try { localStorage.setItem(LS_KEY, JSON.stringify(list.slice(0, 50))); } catch {}\n}\n\nasync function fileToDataURL(file: File): Promise<string> {\n const fr = new FileReader();\n return new Promise((res, rej) => {\n fr.onerror = () => rej(fr.error);\n fr.onload = () => res(String(fr.result));\n fr.readAsDataURL(file);\n });\n}\n\nexport function imageManagerPlugin(opts?: {\n label?: string; // toolbar label\n title?: string; // tooltip\n maxRecent?: number; // default 24\n persistThresholdBytes?: number; // default 1 MiB\n uploader?: (file: File) => Promise<string>; // optional remote upload\n onInsert?: (url: string) => string; // transform URL before insert\n}) {\n const label = opts?.label ?? '🗂️';\n const title = opts?.title ?? 'Images';\n const maxRecent = Math.max(1, opts?.maxRecent ?? 24);\n const threshold = opts?.persistThresholdBytes ?? (1 * 1024 * 1024);\n\n return (editor: MzEditor) => {\n const bar = editor.container.querySelector('.marzipan-toolbar') as HTMLElement ?? editor.container;\n\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'mz-btn mz-btn-imagemgr';\n btn.title = title;\n btn.textContent = label;\n\n let panel: HTMLElement | null = null;\n let recents: RecentImage[] = loadRecents();\n\n function closePanel() {\n panel?.remove(); panel = null;\n document.removeEventListener('click', outsideClose, true);\n window.removeEventListener('resize', closePanel);\n window.removeEventListener('scroll', closePanel, true);\n }\n function outsideClose(e: MouseEvent) {\n if (!panel) return;\n if (e.target instanceof Node && (panel.contains(e.target) || btn.contains(e.target))) return;\n closePanel();\n }\n\n function renderGrid(root: HTMLElement) {\n const grid = root.querySelector('.mz-im-grid') as HTMLElement;\n grid.innerHTML = '';\n recents.slice(0, maxRecent).forEach((img, idx) => {\n const card = document.createElement('div');\n card.className = 'mz-im-card';\n\n const image = document.createElement('img');\n image.decoding = 'async';\n image.loading = 'lazy';\n image.src = img.url;\n image.alt = img.name;\n\n const row = document.createElement('div');\n row.className = 'mz-im-actions';\n\n const insertBtn = document.createElement('button');\n insertBtn.type = 'button';\n insertBtn.textContent = 'Insert';\n insertBtn.onclick = () => {\n const url = opts?.onInsert ? opts.onInsert(img.url) : img.url;\n insertAtCursor(editor, `![${img.name}](${url})`);\n closePanel();\n };\n\n const delBtn = document.createElement('button');\n delBtn.type = 'button';\n delBtn.textContent = '✕';\n delBtn.title = 'Remove from recents';\n delBtn.onclick = () => {\n recents.splice(idx, 1);\n saveRecents(recents);\n renderGrid(root);\n };\n\n row.append(insertBtn, delBtn);\n card.append(image, row);\n grid.appendChild(card);\n });\n }\n\n async function addFromFile(file: File) {\n try {\n let url: string;\n if (opts?.uploader) {\n url = await opts.uploader(file);\n } else if (file.size <= threshold) {\n url = await fileToDataURL(file); // persist across reload\n } else {\n url = URL.createObjectURL(file); // session-only\n }\n const item: RecentImage = { url, name: file.name, createdAt: Date.now(), persistent: !url.startsWith('blob:') };\n recents = [item, ...recents.filter(r => r.url !== url)];\n saveRecents(recents);\n if (panel) renderGrid(panel);\n const finalUrl = opts?.onInsert ? opts.onInsert(url) : url;\n insertAtCursor(editor, `![${file.name}](${finalUrl})`);\n } catch (e) {\n console.error('Image add failed:', e);\n alert('Could not add image.');\n }\n }\n\n async function addFromUrl(url: string, name = 'image') {\n const item: RecentImage = { url, name, createdAt: Date.now(), persistent: true };\n recents = [item, ...recents.filter(r => r.url !== url)];\n saveRecents(recents);\n if (panel) renderGrid(panel);\n const finalUrl = opts?.onInsert ? opts.onInsert(url) : url;\n insertAtCursor(editor, `![${name}](${finalUrl})`);\n }\n\n function openPanel() {\n if (panel) { closePanel(); return; }\n\n panel = document.createElement('div');\n panel.className = 'mz-pop mz-im-panel';\n panel.innerHTML = `\n <div class=\"mz-im-row\">\n <input class=\"mz-im-url\" type=\"url\" placeholder=\"https://example.com/image.png\" />\n <button class=\"mz-im-addurl\" type=\"button\">Add URL</button>\n <input class=\"mz-im-file\" type=\"file\" accept=\"image/*\" hidden />\n <button class=\"mz-im-upload\" type=\"button\">Upload</button>\n <button class=\"mz-im-clear\" type=\"button\" title=\"Clear recents\">Clear</button>\n </div>\n <div class=\"mz-im-drop\">Drop images here, or paste into the editor.</div>\n <div class=\"mz-im-grid\"></div>\n `;\n document.body.appendChild(panel);\n\n // position panel\n const br = btn.getBoundingClientRect();\n panel.style.left = `${Math.round(window.scrollX + br.left)}px`;\n panel.style.top = `${Math.round(window.scrollY + br.bottom + 6)}px`;\n\n // Wire buttons\n const urlIn = panel.querySelector('.mz-im-url') as HTMLInputElement;\n const addUrl = panel.querySelector('.mz-im-addurl') as HTMLButtonElement;\n const fileIn = panel.querySelector('.mz-im-file') as HTMLInputElement;\n const upBtn = panel.querySelector('.mz-im-upload') as HTMLButtonElement;\n const clrBtn = panel.querySelector('.mz-im-clear') as HTMLButtonElement;\n const drop = panel.querySelector('.mz-im-drop') as HTMLElement;\n\n addUrl.onclick = () => {\n const val = urlIn.value.trim();\n if (!val) return;\n addFromUrl(val);\n urlIn.value = '';\n };\n\n upBtn.onclick = () => fileIn.click();\n fileIn.onchange = () => { const f = fileIn.files?.[0]; if (f) addFromFile(f); };\n\n clrBtn.onclick = () => {\n if (confirm('Clear recent images?')) {\n recents = [];\n saveRecents(recents);\n renderGrid(panel!);\n }\n };\n\n // Drag & drop\n ;['dragenter','dragover'].forEach(ev =>\n drop.addEventListener(ev, e => { e.preventDefault(); drop.classList.add('on'); })\n );\n ;['dragleave','drop'].forEach(ev =>\n drop.addEventListener(ev, e => { e.preventDefault(); drop.classList.remove('on'); })\n );\n drop.addEventListener('drop', (e: DragEvent) => {\n const files = e.dataTransfer?.files;\n if (!files || !files.length) return;\n Array.from(files).forEach(addFromFile);\n });\n\n // Render\n renderGrid(panel);\n\n // Close management\n setTimeout(() => {\n document.addEventListener('click', outsideClose, true);\n window.addEventListener('resize', closePanel);\n window.addEventListener('scroll', closePanel, true);\n }, 0);\n }\n\n // Paste support (into the editor textarea)\n editor.textarea.addEventListener('paste', (e: ClipboardEvent) => {\n const item = e.clipboardData?.items && Array.from(e.clipboardData.items)\n .find(i => i.kind === 'file' && i.type.startsWith('image/'));\n if (!item) return;\n const file = item.getAsFile();\n if (file) {\n e.preventDefault();\n addFromFile(file);\n }\n });\n\n // Drag & drop onto the editor container\n editor.container.addEventListener('dragover', e => {\n if (Array.from(e.dataTransfer?.items || []).some(i => i.kind === 'file')) e.preventDefault();\n });\n editor.container.addEventListener('drop', (e: DragEvent) => {\n const files = e.dataTransfer?.files;\n if (!files || !files.length) return;\n e.preventDefault();\n Array.from(files).forEach(addFromFile);\n });\n\n btn.onclick = openPanel;\n bar.appendChild(btn);\n };\n}\n\n// Minimal styles (inject once in your app)\nexport const imageManagerStyles = `\n.mz-im-panel { width: 440px; max-width: calc(100vw - 24px); }\n.mz-im-row { display: grid; grid-template-columns: 1fr auto auto auto; gap: 6px; margin-bottom: 8px; }\n.mz-im-row input[type=\"url\"] {\n background: var(--mz-ip-bg, #0f1216); color: var(--mz-ip-fg, #e7e7e7);\n border: 1px solid var(--mz-ip-bd, #2b2f36); border-radius: 8px; padding: 6px 8px;\n}\n.mz-im-row button {\n padding: 6px 10px; border-radius: 8px; border: 1px solid var(--mz-bd, #2b2f36);\n background: var(--mz-btn-bg, #1a1e24); color: var(--mz-btn-fg, #e7e7e7); cursor: pointer;\n}\n.mz-im-drop {\n border: 1px dashed var(--mz-drop-bd, #3b4350); border-radius: 8px;\n padding: 10px; text-align: center; font-size: 12px; margin-bottom: 8px;\n background: var(--mz-drop-bg, #0e1116);\n}\n.mz-im-drop.on { background: var(--mz-drop-on, #172033); }\n.mz-im-grid {\n display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));\n gap: 8px; max-height: 320px; overflow: auto; padding: 2px;\n}\n.mz-im-card { border: 1px solid var(--mz-card-bd, #2b2f36); border-radius: 8px; overflow: hidden;\n background: var(--mz-card-bg, #12151a); display: flex; flex-direction: column; }\n.mz-im-card img { width: 100%; height: 82px; object-fit: cover; display: block; }\n.mz-im-actions { display: flex; gap: 6px; padding: 6px; justify-content: space-between; }\n.mz-im-actions button {\n flex: 1; padding: 4px 6px; border-radius: 6px; border: 1px solid var(--mz-bd, #2b2f36);\n background: var(--mz-btn2-bg, #1b2027); color: var(--mz-btn2-fg, #e7e7e7); cursor: pointer; font-size: 12px;\n}\n`;"],"names":["LS_KEY","insertAtCursor","editor","text","ta","s","e","loadRecents","saveRecents","list","fileToDataURL","file","fr","res","rej","imageManagerPlugin","opts","label","title","maxRecent","threshold","bar","btn","panel","recents","closePanel","outsideClose","renderGrid","root","grid","img","idx","card","image","row","insertBtn","url","delBtn","addFromFile","r","finalUrl","addFromUrl","name","openPanel","br","urlIn","addUrl","fileIn","upBtn","clrBtn","drop","val","f","ev","files","item","i","imageManagerStyles"],"mappings":"AAeA,MAAMA,IAAS;AAEf,SAASC,EAAeC,GAAkBC,GAAc;AACtD,QAAMC,IAAKF,EAAO,UACZG,IAAID,EAAG,kBAAkB,GAAGE,IAAIF,EAAG,gBAAgB;AACzD,EAAAA,EAAG,aAAaD,GAAME,GAAGC,GAAG,KAAK,GACjCJ,EAAO,cAAA,GACPE,EAAG,MAAA;AACL;AAEA,SAASG,IAA6B;AACpC,MAAI;AAAE,WAAO,KAAK,MAAM,aAAa,QAAQP,CAAM,KAAK,IAAI;AAAA,EAAG,QACzD;AAAE,WAAO,CAAA;AAAA,EAAI;AACrB;AACA,SAASQ,EAAYC,GAAqB;AACxC,MAAI;AAAE,iBAAa,QAAQT,GAAQ,KAAK,UAAUS,EAAK,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,EAAG,QAAQ;AAAA,EAAC;AAClF;AAEA,eAAeC,EAAcC,GAA6B;AACxD,QAAMC,IAAK,IAAI,WAAA;AACf,SAAO,IAAI,QAAQ,CAACC,GAAKC,MAAQ;AAC/B,IAAAF,EAAG,UAAU,MAAME,EAAIF,EAAG,KAAK,GAC/BA,EAAG,SAAS,MAAMC,EAAI,OAAOD,EAAG,MAAM,CAAC,GACvCA,EAAG,cAAcD,CAAI;AAAA,EACvB,CAAC;AACH;AAEO,SAASI,EAAmBC,GAOhC;AACD,QAAMC,IAAQD,GAAM,SAAS,OACvBE,IAAQF,GAAM,SAAS,UACvBG,IAAY,KAAK,IAAI,GAAGH,GAAM,aAAa,EAAE,GAC7CI,IAAYJ,GAAM,yBAA0B,IAAI,OAAO;AAE7D,SAAO,CAACd,MAAqB;AAC3B,UAAMmB,IAAMnB,EAAO,UAAU,cAAc,mBAAmB,KAAoBA,EAAO,WAEnFoB,IAAM,SAAS,cAAc,QAAQ;AAC3C,IAAAA,EAAI,OAAO,UACXA,EAAI,YAAY,0BAChBA,EAAI,QAAQJ,GACZI,EAAI,cAAcL;AAElB,QAAIM,IAA4B,MAC5BC,IAAyBjB,EAAA;AAE7B,aAASkB,IAAa;AACpB,MAAAF,GAAO,OAAA,GAAUA,IAAQ,MACzB,SAAS,oBAAoB,SAASG,GAAc,EAAI,GACxD,OAAO,oBAAoB,UAAUD,CAAU,GAC/C,OAAO,oBAAoB,UAAUA,GAAY,EAAI;AAAA,IACvD;AACA,aAASC,EAAa,GAAe;AACnC,MAAKH,MACD,EAAE,kBAAkB,SAASA,EAAM,SAAS,EAAE,MAAM,KAAKD,EAAI,SAAS,EAAE,MAAM,MAClFG,EAAA;AAAA,IACF;AAEA,aAASE,EAAWC,GAAmB;AACrC,YAAMC,IAAOD,EAAK,cAAc,aAAa;AAC7C,MAAAC,EAAK,YAAY,IACjBL,EAAQ,MAAM,GAAGL,CAAS,EAAE,QAAQ,CAACW,GAAKC,MAAQ;AAChD,cAAMC,IAAO,SAAS,cAAc,KAAK;AACzC,QAAAA,EAAK,YAAY;AAEjB,cAAMC,IAAQ,SAAS,cAAc,KAAK;AAC1C,QAAAA,EAAM,WAAW,SACjBA,EAAM,UAAU,QAChBA,EAAM,MAAMH,EAAI,KAChBG,EAAM,MAAMH,EAAI;AAEhB,cAAMI,IAAM,SAAS,cAAc,KAAK;AACxC,QAAAA,EAAI,YAAY;AAEhB,cAAMC,IAAY,SAAS,cAAc,QAAQ;AACjD,QAAAA,EAAU,OAAO,UACjBA,EAAU,cAAc,UACxBA,EAAU,UAAU,MAAM;AACxB,gBAAMC,IAAMpB,GAAM,WAAWA,EAAK,SAASc,EAAI,GAAG,IAAIA,EAAI;AAC1D,UAAA7B,EAAeC,GAAQ,KAAK4B,EAAI,IAAI,KAAKM,CAAG,GAAG,GAC/CX,EAAA;AAAA,QACF;AAEA,cAAMY,IAAS,SAAS,cAAc,QAAQ;AAC9C,QAAAA,EAAO,OAAO,UACdA,EAAO,cAAc,KACrBA,EAAO,QAAQ,uBACfA,EAAO,UAAU,MAAM;AACrB,UAAAb,EAAQ,OAAOO,GAAK,CAAC,GACrBvB,EAAYgB,CAAO,GACnBG,EAAWC,CAAI;AAAA,QACjB,GAEAM,EAAI,OAAOC,GAAWE,CAAM,GAC5BL,EAAK,OAAOC,GAAOC,CAAG,GACtBL,EAAK,YAAYG,CAAI;AAAA,MACvB,CAAC;AAAA,IACH;AAEA,mBAAeM,EAAY3B,GAAY;AACrC,UAAI;AACF,YAAIyB;AACJ,QAAIpB,GAAM,WACRoB,IAAM,MAAMpB,EAAK,SAASL,CAAI,IACrBA,EAAK,QAAQS,IACtBgB,IAAM,MAAM1B,EAAcC,CAAI,IAE9ByB,IAAM,IAAI,gBAAgBzB,CAAI,GAGhCa,IAAU,CADgB,EAAE,KAAAY,GAAK,MAAMzB,EAAK,MAAM,WAAW,KAAK,IAAA,GAAO,YAAY,CAACyB,EAAI,WAAW,OAAO,EAAA,GAC3F,GAAGZ,EAAQ,OAAO,CAAAe,MAAKA,EAAE,QAAQH,CAAG,CAAC,GACtD5B,EAAYgB,CAAO,GACfD,OAAkBA,CAAK;AAC3B,cAAMiB,IAAWxB,GAAM,WAAWA,EAAK,SAASoB,CAAG,IAAIA;AACvD,QAAAnC,EAAeC,GAAQ,KAAKS,EAAK,IAAI,KAAK6B,CAAQ,GAAG;AAAA,MACvD,SAASlC,GAAG;AACV,gBAAQ,MAAM,qBAAqBA,CAAC,GACpC,MAAM,sBAAsB;AAAA,MAC9B;AAAA,IACF;AAEA,mBAAemC,EAAWL,GAAaM,IAAO,SAAS;AAErD,MAAAlB,IAAU,CADgB,EAAE,KAAAY,GAAK,MAAAM,GAAM,WAAW,KAAK,IAAA,GAAO,YAAY,GAAA,GACzD,GAAGlB,EAAQ,OAAO,CAAAe,MAAKA,EAAE,QAAQH,CAAG,CAAC,GACtD5B,EAAYgB,CAAO,GACfD,OAAkBA,CAAK;AAC3B,YAAMiB,IAAWxB,GAAM,WAAWA,EAAK,SAASoB,CAAG,IAAIA;AACvD,MAAAnC,EAAeC,GAAQ,KAAKwC,CAAI,KAAKF,CAAQ,GAAG;AAAA,IAClD;AAEA,aAASG,IAAY;AACnB,UAAIpB,GAAO;AAAE,QAAAE,EAAA;AAAc;AAAA,MAAQ;AAEnC,MAAAF,IAAQ,SAAS,cAAc,KAAK,GACpCA,EAAM,YAAY,sBAClBA,EAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAWlB,SAAS,KAAK,YAAYA,CAAK;AAG/B,YAAMqB,IAAKtB,EAAI,sBAAA;AACf,MAAAC,EAAM,MAAM,OAAO,GAAG,KAAK,MAAM,OAAO,UAAUqB,EAAG,IAAI,CAAC,MAC1DrB,EAAM,MAAM,MAAO,GAAG,KAAK,MAAM,OAAO,UAAUqB,EAAG,SAAS,CAAC,CAAC;AAGhE,YAAMC,IAAStB,EAAM,cAAc,YAAY,GACzCuB,IAASvB,EAAM,cAAc,eAAe,GAC5CwB,IAASxB,EAAM,cAAc,aAAa,GAC1CyB,IAASzB,EAAM,cAAc,eAAe,GAC5C0B,IAAS1B,EAAM,cAAc,cAAc,GAC3C2B,IAAS3B,EAAM,cAAc,aAAa;AAEhD,MAAAuB,EAAO,UAAU,MAAM;AACrB,cAAMK,IAAMN,EAAM,MAAM,KAAA;AACxB,QAAKM,MACLV,EAAWU,CAAG,GACdN,EAAM,QAAQ;AAAA,MAChB,GAEAG,EAAM,UAAU,MAAMD,EAAO,MAAA,GAC7BA,EAAO,WAAW,MAAM;AAAE,cAAMK,IAAIL,EAAO,QAAQ,CAAC;AAAG,QAAIK,OAAeA,CAAC;AAAA,MAAG,GAE9EH,EAAO,UAAU,MAAM;AACrB,QAAI,QAAQ,sBAAsB,MAChCzB,IAAU,CAAA,GACVhB,EAAYgB,CAAO,GACnBG,EAAWJ,CAAM;AAAA,MAErB,GAGC,CAAC,aAAY,UAAU,EAAE;AAAA,QAAQ,CAAA8B,MAChCH,EAAK,iBAAiBG,GAAI,CAAA/C,MAAK;AAAE,UAAAA,EAAE,eAAA,GAAkB4C,EAAK,UAAU,IAAI,IAAI;AAAA,QAAG,CAAC;AAAA,MAAA,GAEjF,CAAC,aAAY,MAAM,EAAE;AAAA,QAAQ,CAAAG,MAC5BH,EAAK,iBAAiBG,GAAI,CAAA/C,MAAK;AAAE,UAAAA,EAAE,eAAA,GAAkB4C,EAAK,UAAU,OAAO,IAAI;AAAA,QAAG,CAAC;AAAA,MAAA,GAErFA,EAAK,iBAAiB,QAAQ,CAAC5C,MAAiB;AAC9C,cAAMgD,IAAQhD,EAAE,cAAc;AAC9B,QAAI,CAACgD,KAAS,CAACA,EAAM,UACrB,MAAM,KAAKA,CAAK,EAAE,QAAQhB,CAAW;AAAA,MACvC,CAAC,GAGDX,EAAWJ,CAAK,GAGhB,WAAW,MAAM;AACf,iBAAS,iBAAiB,SAASG,GAAc,EAAI,GACrD,OAAO,iBAAiB,UAAUD,CAAU,GAC5C,OAAO,iBAAiB,UAAUA,GAAY,EAAI;AAAA,MACpD,GAAG,CAAC;AAAA,IACN;AAGA,IAAAvB,EAAO,SAAS,iBAAiB,SAAS,CAAC,MAAsB;AAC/D,YAAMqD,IAAO,EAAE,eAAe,SAAS,MAAM,KAAK,EAAE,cAAc,KAAK,EACpE,KAAK,CAAAC,MAAKA,EAAE,SAAS,UAAUA,EAAE,KAAK,WAAW,QAAQ,CAAC;AAC7D,UAAI,CAACD,EAAM;AACX,YAAM5C,IAAO4C,EAAK,UAAA;AAClB,MAAI5C,MACF,EAAE,eAAA,GACF2B,EAAY3B,CAAI;AAAA,IAEpB,CAAC,GAGDT,EAAO,UAAU,iBAAiB,YAAY,CAAA,MAAK;AACjD,MAAI,MAAM,KAAK,EAAE,cAAc,SAAS,CAAA,CAAE,EAAE,KAAK,OAAKsD,EAAE,SAAS,MAAM,OAAK,eAAA;AAAA,IAC9E,CAAC,GACDtD,EAAO,UAAU,iBAAiB,QAAQ,CAAC,MAAiB;AAC1D,YAAMoD,IAAQ,EAAE,cAAc;AAC9B,MAAI,CAACA,KAAS,CAACA,EAAM,WACrB,EAAE,eAAA,GACF,MAAM,KAAKA,CAAK,EAAE,QAAQhB,CAAW;AAAA,IACvC,CAAC,GAEDhB,EAAI,UAAUqB,GACdtB,EAAI,YAAYC,CAAG;AAAA,EACrB;AACF;AAGO,MAAMmC,IAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;"}
1
+ {"version":3,"file":"imageManagerPlugin.js","sources":["../../src/plugins/imageManagerPlugin.ts"],"sourcesContent":["// plugins/imageManagerPlugin.ts` — recents, upload, URL add, drag-drop, paste\n// =====================================================\n// Persists “recents” in `localStorage` (data-URLs for small files ≤ default 1 MB).\n// Optional `uploader(file) => Promise<string>` to store remotely and return a URL.\n// Drag files onto the editor, or paste images from clipboard—instant preview and insert.\n// Tiny panel with thumbnails; click to insert; remove/clear as needed.\n\ntype MzEditor = {\n container: HTMLElement;\n textarea: HTMLTextAreaElement;\n updatePreview: () => void;\n};\n\ntype RecentImage = { url: string; name: string; createdAt: number; persistent: boolean };\n\nconst LS_KEY = 'marzipan.images';\n\nfunction insertAtCursor(editor: MzEditor, text: string) {\n const ta = editor.textarea;\n const s = ta.selectionStart ?? 0, e = ta.selectionEnd ?? 0;\n ta.setRangeText(text, s, e, 'end');\n editor.updatePreview();\n ta.focus();\n}\n\nfunction loadRecents(): RecentImage[] {\n try { return JSON.parse(localStorage.getItem(LS_KEY) || '[]'); }\n catch { return []; }\n}\nfunction saveRecents(list: RecentImage[]) {\n try { localStorage.setItem(LS_KEY, JSON.stringify(list.slice(0, 50))); } catch { /* localStorage not available */ }\n}\n\nasync function fileToDataURL(file: File): Promise<string> {\n const fr = new FileReader();\n return new Promise((res, rej) => {\n fr.onerror = () => rej(fr.error);\n fr.onload = () => res(String(fr.result));\n fr.readAsDataURL(file);\n });\n}\n\nexport function imageManagerPlugin(opts?: {\n label?: string; // toolbar label\n title?: string; // tooltip\n maxRecent?: number; // default 24\n persistThresholdBytes?: number; // default 1 MiB\n uploader?: (file: File) => Promise<string>; // optional remote upload\n onInsert?: (url: string) => string; // transform URL before insert\n}) {\n const label = opts?.label ?? '🗂️';\n const title = opts?.title ?? 'Images';\n const maxRecent = Math.max(1, opts?.maxRecent ?? 24);\n const threshold = opts?.persistThresholdBytes ?? (1 * 1024 * 1024);\n\n return (editor: MzEditor) => {\n const bar = editor.container.querySelector('.marzipan-toolbar') as HTMLElement ?? editor.container;\n\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'mz-btn mz-btn-imagemgr';\n btn.title = title;\n btn.textContent = label;\n\n let panel: HTMLElement | null = null;\n let recents: RecentImage[] = loadRecents();\n\n function closePanel() {\n panel?.remove(); panel = null;\n document.removeEventListener('click', outsideClose, true);\n window.removeEventListener('resize', closePanel);\n window.removeEventListener('scroll', closePanel, true);\n }\n function outsideClose(e: MouseEvent) {\n if (!panel) return;\n if (e.target instanceof Node && (panel.contains(e.target) || btn.contains(e.target))) return;\n closePanel();\n }\n\n function renderGrid(root: HTMLElement) {\n const grid = root.querySelector('.mz-im-grid') as HTMLElement;\n grid.innerHTML = '';\n recents.slice(0, maxRecent).forEach((img, idx) => {\n const card = document.createElement('div');\n card.className = 'mz-im-card';\n\n const image = document.createElement('img');\n image.decoding = 'async';\n image.loading = 'lazy';\n image.src = img.url;\n image.alt = img.name;\n\n const row = document.createElement('div');\n row.className = 'mz-im-actions';\n\n const insertBtn = document.createElement('button');\n insertBtn.type = 'button';\n insertBtn.textContent = 'Insert';\n insertBtn.onclick = () => {\n const url = opts?.onInsert ? opts.onInsert(img.url) : img.url;\n insertAtCursor(editor, `![${img.name}](${url})`);\n closePanel();\n };\n\n const delBtn = document.createElement('button');\n delBtn.type = 'button';\n delBtn.textContent = '✕';\n delBtn.title = 'Remove from recents';\n delBtn.onclick = () => {\n recents.splice(idx, 1);\n saveRecents(recents);\n renderGrid(root);\n };\n\n row.append(insertBtn, delBtn);\n card.append(image, row);\n grid.appendChild(card);\n });\n }\n\n async function addFromFile(file: File) {\n try {\n let url: string;\n if (opts?.uploader) {\n url = await opts.uploader(file);\n } else if (file.size <= threshold) {\n url = await fileToDataURL(file); // persist across reload\n } else {\n url = URL.createObjectURL(file); // session-only\n }\n const item: RecentImage = { url, name: file.name, createdAt: Date.now(), persistent: !url.startsWith('blob:') };\n recents = [item, ...recents.filter(r => r.url !== url)];\n saveRecents(recents);\n if (panel) renderGrid(panel);\n const finalUrl = opts?.onInsert ? opts.onInsert(url) : url;\n insertAtCursor(editor, `![${file.name}](${finalUrl})`);\n } catch (e) {\n console.error('Image add failed:', e);\n alert('Could not add image.');\n }\n }\n\n async function addFromUrl(url: string, name = 'image') {\n const item: RecentImage = { url, name, createdAt: Date.now(), persistent: true };\n recents = [item, ...recents.filter(r => r.url !== url)];\n saveRecents(recents);\n if (panel) renderGrid(panel);\n const finalUrl = opts?.onInsert ? opts.onInsert(url) : url;\n insertAtCursor(editor, `![${name}](${finalUrl})`);\n }\n\n function openPanel() {\n if (panel) { closePanel(); return; }\n\n panel = document.createElement('div');\n panel.className = 'mz-pop mz-im-panel';\n panel.innerHTML = `\n <div class=\"mz-im-row\">\n <input class=\"mz-im-url\" type=\"url\" placeholder=\"https://example.com/image.png\" />\n <button class=\"mz-im-addurl\" type=\"button\">Add URL</button>\n <input class=\"mz-im-file\" type=\"file\" accept=\"image/*\" hidden />\n <button class=\"mz-im-upload\" type=\"button\">Upload</button>\n <button class=\"mz-im-clear\" type=\"button\" title=\"Clear recents\">Clear</button>\n </div>\n <div class=\"mz-im-drop\">Drop images here, or paste into the editor.</div>\n <div class=\"mz-im-grid\"></div>\n `;\n document.body.appendChild(panel);\n\n // position panel\n const br = btn.getBoundingClientRect();\n panel.style.left = `${Math.round(window.scrollX + br.left)}px`;\n panel.style.top = `${Math.round(window.scrollY + br.bottom + 6)}px`;\n\n // Wire buttons\n const urlIn = panel.querySelector('.mz-im-url') as HTMLInputElement;\n const addUrl = panel.querySelector('.mz-im-addurl') as HTMLButtonElement;\n const fileIn = panel.querySelector('.mz-im-file') as HTMLInputElement;\n const upBtn = panel.querySelector('.mz-im-upload') as HTMLButtonElement;\n const clrBtn = panel.querySelector('.mz-im-clear') as HTMLButtonElement;\n const drop = panel.querySelector('.mz-im-drop') as HTMLElement;\n\n addUrl.onclick = () => {\n const val = urlIn.value.trim();\n if (!val) return;\n addFromUrl(val);\n urlIn.value = '';\n };\n\n upBtn.onclick = () => fileIn.click();\n fileIn.onchange = () => { const f = fileIn.files?.[0]; if (f) addFromFile(f); };\n\n clrBtn.onclick = () => {\n if (confirm('Clear recent images?')) {\n recents = [];\n saveRecents(recents);\n renderGrid(panel!);\n }\n };\n\n // Drag & drop\n ;['dragenter','dragover'].forEach(ev =>\n drop.addEventListener(ev, e => { e.preventDefault(); drop.classList.add('on'); })\n );\n ;['dragleave','drop'].forEach(ev =>\n drop.addEventListener(ev, e => { e.preventDefault(); drop.classList.remove('on'); })\n );\n drop.addEventListener('drop', (e: DragEvent) => {\n const files = e.dataTransfer?.files;\n if (!files || !files.length) return;\n Array.from(files).forEach(addFromFile);\n });\n\n // Render\n renderGrid(panel);\n\n // Close management\n setTimeout(() => {\n document.addEventListener('click', outsideClose, true);\n window.addEventListener('resize', closePanel);\n window.addEventListener('scroll', closePanel, true);\n }, 0);\n }\n\n // Paste support (into the editor textarea)\n editor.textarea.addEventListener('paste', (e: ClipboardEvent) => {\n const item = e.clipboardData?.items && Array.from(e.clipboardData.items)\n .find(i => i.kind === 'file' && i.type.startsWith('image/'));\n if (!item) return;\n const file = item.getAsFile();\n if (file) {\n e.preventDefault();\n addFromFile(file);\n }\n });\n\n // Drag & drop onto the editor container\n editor.container.addEventListener('dragover', e => {\n if (Array.from(e.dataTransfer?.items || []).some(i => i.kind === 'file')) e.preventDefault();\n });\n editor.container.addEventListener('drop', (e: DragEvent) => {\n const files = e.dataTransfer?.files;\n if (!files || !files.length) return;\n e.preventDefault();\n Array.from(files).forEach(addFromFile);\n });\n\n btn.onclick = openPanel;\n bar.appendChild(btn);\n };\n}\n\n// Minimal styles (inject once in your app)\nexport const imageManagerStyles = `\n.mz-im-panel { width: 440px; max-width: calc(100vw - 24px); }\n.mz-im-row { display: grid; grid-template-columns: 1fr auto auto auto; gap: 6px; margin-bottom: 8px; }\n.mz-im-row input[type=\"url\"] {\n background: var(--mz-ip-bg, #0f1216); color: var(--mz-ip-fg, #e7e7e7);\n border: 1px solid var(--mz-ip-bd, #2b2f36); border-radius: 8px; padding: 6px 8px;\n}\n.mz-im-row button {\n padding: 6px 10px; border-radius: 8px; border: 1px solid var(--mz-bd, #2b2f36);\n background: var(--mz-btn-bg, #1a1e24); color: var(--mz-btn-fg, #e7e7e7); cursor: pointer;\n}\n.mz-im-drop {\n border: 1px dashed var(--mz-drop-bd, #3b4350); border-radius: 8px;\n padding: 10px; text-align: center; font-size: 12px; margin-bottom: 8px;\n background: var(--mz-drop-bg, #0e1116);\n}\n.mz-im-drop.on { background: var(--mz-drop-on, #172033); }\n.mz-im-grid {\n display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));\n gap: 8px; max-height: 320px; overflow: auto; padding: 2px;\n}\n.mz-im-card { border: 1px solid var(--mz-card-bd, #2b2f36); border-radius: 8px; overflow: hidden;\n background: var(--mz-card-bg, #12151a); display: flex; flex-direction: column; }\n.mz-im-card img { width: 100%; height: 82px; object-fit: cover; display: block; }\n.mz-im-actions { display: flex; gap: 6px; padding: 6px; justify-content: space-between; }\n.mz-im-actions button {\n flex: 1; padding: 4px 6px; border-radius: 6px; border: 1px solid var(--mz-bd, #2b2f36);\n background: var(--mz-btn2-bg, #1b2027); color: var(--mz-btn2-fg, #e7e7e7); cursor: pointer; font-size: 12px;\n}\n`;"],"names":["LS_KEY","insertAtCursor","editor","text","ta","s","e","loadRecents","saveRecents","list","fileToDataURL","file","fr","res","rej","imageManagerPlugin","opts","label","title","maxRecent","threshold","bar","btn","panel","recents","closePanel","outsideClose","renderGrid","root","grid","img","idx","card","image","row","insertBtn","url","delBtn","addFromFile","r","finalUrl","addFromUrl","name","openPanel","br","urlIn","addUrl","fileIn","upBtn","clrBtn","drop","val","f","ev","files","item","i","imageManagerStyles"],"mappings":"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"}
@@ -5,4 +5,20 @@
5
5
  */
6
6
  export { BlockHandlesPlugin } from './block-handles';
7
7
  export type { BlockHandle, BlockHandlesConfig } from './block-handles';
8
+ export { accentSwatchPlugin, accentSwatchStyles } from './accentSwatchPlugin';
9
+ export { imageManagerPlugin, imageManagerStyles } from './imageManagerPlugin';
10
+ export { imagePickerPlugin } from './imagePickerPlugin';
11
+ export type { ImagePickerOptions } from './imagePicker';
12
+ export { mermaidPlugin } from './mermaidPlugin';
13
+ export { mermaidExternalPlugin } from './mermaidExternal';
14
+ export { tablePlugin } from './tablePlugin';
15
+ export type { TablePluginOptions } from './tablePlugin';
16
+ export { tableGridPlugin, tableGridStyles } from './tableGridPlugin';
17
+ export type { TableGridPluginOptions } from './tableGridPlugin';
18
+ export { tableGeneratorPlugin } from './tableGenerator';
19
+ export { tinyHighlightPlugin, tinyHighlightStyles } from './tinyHighlight';
20
+ export type { MarzipanLike } from './tinyHighlight';
21
+ export { buildTableMarkdown, resolvePositiveInteger } from './utils/table';
22
+ export { imagePickerPlugin as coreImagePickerPlugin } from './imagePicker';
23
+ export type { ImagePickerOptions as CoreImagePickerOptions } from './imagePicker';
8
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AACA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AACA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAGvE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG9E,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACrE,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGxD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC3E,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGpD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAG3E,OAAO,EAAE,iBAAiB,IAAI,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC3E,YAAY,EAAE,kBAAkB,IAAI,sBAAsB,EAAE,MAAM,eAAe,CAAC"}