scitex 2.10.2__py3-none-any.whl → 2.11.0__py3-none-any.whl

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 (363) hide show
  1. scitex/__init__.py +1 -4
  2. scitex/__version__.py +1 -1
  3. scitex/_install_guide.py +14 -2
  4. scitex/bridge/_figrecipe.py +1 -1
  5. scitex/bridge/_helpers.py +1 -1
  6. scitex/bridge/_plt_vis.py +1 -1
  7. scitex/bridge/_stats_plt.py +1 -1
  8. scitex/bridge/_stats_vis.py +2 -2
  9. scitex/{fig → canvas}/__init__.py +84 -96
  10. scitex/{fig → canvas}/backend/_parser.py +1 -1
  11. scitex/{fig → canvas}/canvas.py +13 -14
  12. scitex/{fts/_fig/_editor → canvas/editor}/_defaults.py +2 -2
  13. scitex/{fig → canvas}/editor/edit/__init__.py +11 -14
  14. scitex/{fig → canvas}/editor/edit/bundle_resolver.py +56 -48
  15. scitex/{fig → canvas}/editor/edit/editor_launcher.py +79 -26
  16. scitex/{fts/_fig/_editor/_cui/_panel_loader.py → canvas/editor/edit/panel_loader.py} +8 -8
  17. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_bbox.py +2 -1
  18. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_core.py +84 -84
  19. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_renderer.py +7 -6
  20. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/static/css/features/canvas.css +2 -2
  21. scitex/{fig → canvas}/editor/flask_editor/static/css/features/panel-grid.css +1 -1
  22. scitex/{fig → canvas}/editor/flask_editor/static/js/core/api.js +3 -4
  23. scitex/{fig → canvas}/editor/flask_editor/static/js/editor/preview.js +5 -5
  24. scitex/{fig → canvas}/editor/flask_editor/templates/_html.py +3 -3
  25. scitex/{fig → canvas}/editor/flask_editor/templates/_scripts.py +10 -10
  26. scitex/{fig → canvas}/editor/flask_editor/templates/_styles.py +3 -3
  27. scitex/{fig → canvas}/io/__init__.py +32 -38
  28. scitex/{fig → canvas}/io/_bundle.py +217 -154
  29. scitex/{fig → canvas}/io/_canvas.py +1 -1
  30. scitex/{fig → canvas}/io/_data.py +1 -1
  31. scitex/{fig → canvas}/io/_export.py +1 -1
  32. scitex/{fig → canvas}/io/_load.py +1 -1
  33. scitex/{fig → canvas}/io/_panel.py +1 -1
  34. scitex/{fig → canvas}/io/_save.py +1 -1
  35. scitex/{fig → canvas}/model/__init__.py +1 -1
  36. scitex/{fig → canvas}/model/_annotations.py +1 -1
  37. scitex/{fig → canvas}/model/_axes.py +1 -1
  38. scitex/{fig → canvas}/model/_figure.py +1 -1
  39. scitex/{fig → canvas}/model/_guides.py +1 -1
  40. scitex/{fig → canvas}/model/_plot.py +1 -1
  41. scitex/{fig → canvas}/model/_styles.py +1 -1
  42. scitex/{fig → canvas}/utils/__init__.py +1 -1
  43. scitex/cli/convert.py +10 -6
  44. scitex/diagram/README.md +7 -7
  45. scitex/io/__init__.py +7 -19
  46. scitex/io/_load.py +15 -19
  47. scitex/io/_load_modules/_canvas.py +2 -2
  48. scitex/io/_load_modules/_con.py +5 -5
  49. scitex/io/_load_modules/_eeg.py +16 -12
  50. scitex/io/_save.py +11 -16
  51. scitex/io/_save_modules/__init__.py +6 -10
  52. scitex/io/_save_modules/_canvas.py +3 -3
  53. scitex/io/_save_modules/_plot_bundle.py +112 -0
  54. scitex/io/_save_modules/{_pltz_stx.py → _plot_scitex.py} +7 -7
  55. scitex/io/_save_modules/_stx_bundle.py +16 -16
  56. scitex/io/bundle/README.md +89 -80
  57. scitex/{fts/_bundle/_FTS.py → io/bundle/_Bundle.py} +197 -95
  58. scitex/io/bundle/__init__.py +67 -35
  59. scitex/{fts/_bundle → io/bundle}/_children.py +32 -40
  60. scitex/io/bundle/_core.py +184 -97
  61. scitex/{fts/_bundle/_dataclasses/_Node.py → io/bundle/_dataclasses/_Spec.py} +29 -23
  62. scitex/{fts/_bundle/_dataclasses/_NodeRefs.py → io/bundle/_dataclasses/_SpecRefs.py} +6 -6
  63. scitex/{fts/_bundle → io/bundle}/_dataclasses/__init__.py +4 -4
  64. scitex/{fts/_bundle → io/bundle}/_loader.py +19 -19
  65. scitex/io/bundle/_manifest.py +99 -0
  66. scitex/{fts/_bundle → io/bundle}/_mpl_helpers.py +119 -28
  67. scitex/io/bundle/_nested.py +113 -100
  68. scitex/{fts/_bundle → io/bundle}/_saver.py +13 -14
  69. scitex/{fts/_bundle → io/bundle}/_storage.py +3 -3
  70. scitex/io/bundle/_types.py +41 -16
  71. scitex/{fts/_bundle → io/bundle}/_validation.py +20 -18
  72. scitex/io/bundle/_zip.py +21 -31
  73. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_backend/_parser.py +1 -1
  74. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Annotations.py +1 -1
  75. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Axes.py +1 -1
  76. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Figure.py +1 -1
  77. scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Guides.py +1 -1
  78. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Plot.py +1 -1
  79. scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Styles.py +1 -1
  80. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_utils/_plot_layout.py +1 -1
  81. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/__init__.py +1 -1
  82. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/_app.py +1 -1
  83. scitex/{fts/_tables → io/bundle/kinds/_table}/_latex/_export.py +1 -1
  84. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_figure_exporter.py +1 -1
  85. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_table_exporter.py +1 -1
  86. scitex/io/bundle/schemas/__init__.py +30 -0
  87. scitex/parallel/_run.py +5 -4
  88. scitex/path/_find.py +60 -83
  89. scitex/path/_get_module_path.py +23 -21
  90. scitex/path/_get_spath.py +6 -27
  91. scitex/path/_getsize.py +23 -9
  92. scitex/path/_increment_version.py +31 -38
  93. scitex/path/_mk_spath.py +26 -29
  94. scitex/path/_path.py +5 -12
  95. scitex/path/_split.py +27 -15
  96. scitex/path/_this_path.py +23 -9
  97. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +2 -1
  98. scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +2 -2
  99. scitex/plt/gallery/_generate.py +76 -50
  100. scitex/plt/io/__init__.py +17 -19
  101. scitex/plt/io/_bundle.py +99 -52
  102. scitex/plt/io/_layered_bundle.py +303 -168
  103. scitex/plt/utils/_csv_column_naming.py +250 -118
  104. scitex/schema/__init__.py +69 -73
  105. scitex/schema/_canvas.py +1 -1
  106. scitex/schema/_stats.py +2 -2
  107. scitex/stats/__init__.py +30 -33
  108. scitex/stats/_schema.py +1 -1
  109. scitex/stats/io/__init__.py +10 -11
  110. scitex/stats/io/_bundle.py +16 -16
  111. {scitex-2.10.2.dist-info → scitex-2.11.0.dist-info}/METADATA +191 -72
  112. {scitex-2.10.2.dist-info → scitex-2.11.0.dist-info}/RECORD +237 -360
  113. scitex/fig/editor/_defaults.py +0 -300
  114. scitex/fig/editor/edit/panel_loader.py +0 -232
  115. scitex/fig/editor/flask_editor/_bbox.py +0 -1299
  116. scitex/fig/editor/flask_editor/_core.py +0 -1429
  117. scitex/fig/editor/flask_editor/_renderer.py +0 -813
  118. scitex/fig/editor/flask_editor/static/css/features/canvas.css +0 -176
  119. scitex/fts/README.md +0 -262
  120. scitex/fts/TODO.md +0 -66
  121. scitex/fts/__init__.py +0 -90
  122. scitex/fts/_bundle/README_IN_BUNDLE.md +0 -102
  123. scitex/fts/_bundle/__init__.py +0 -38
  124. scitex/fts/_bundle/_utils/__init__.py +0 -55
  125. scitex/fts/_bundle/_utils/_const.py +0 -26
  126. scitex/fts/_bundle/_utils/_errors.py +0 -73
  127. scitex/fts/_bundle/_utils/_generate.py +0 -21
  128. scitex/fts/_bundle/_utils/_types.py +0 -76
  129. scitex/fts/_bundle/_zipbundle.py +0 -165
  130. scitex/fts/_fig/__init__.py +0 -22
  131. scitex/fts/_fig/_backend/_parser.py +0 -188
  132. scitex/fts/_fig/_editor/__init__.py +0 -14
  133. scitex/fts/_fig/_editor/_cui/__init__.py +0 -33
  134. scitex/fts/_fig/_editor/_cui/_backend_detector.py +0 -39
  135. scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +0 -366
  136. scitex/fts/_fig/_editor/_cui/_editor_launcher.py +0 -175
  137. scitex/fts/_fig/_editor/_cui/_manual_handler.py +0 -52
  138. scitex/fts/_fig/_editor/_cui/_path_resolver.py +0 -66
  139. scitex/fts/_fig/_editor/_gui/__init__.py +0 -11
  140. scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +0 -20
  141. scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +0 -664
  142. scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +0 -79
  143. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +0 -41
  144. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +0 -16
  145. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +0 -85
  146. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +0 -217
  147. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +0 -93
  148. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +0 -57
  149. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +0 -112
  150. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +0 -59
  151. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +0 -212
  152. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +0 -190
  153. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +0 -59
  154. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +0 -45
  155. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +0 -95
  156. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +0 -101
  157. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +0 -138
  158. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +0 -31
  159. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +0 -7
  160. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +0 -56
  161. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +0 -78
  162. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +0 -314
  163. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +0 -107
  164. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +0 -54
  165. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +0 -172
  166. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +0 -258
  167. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +0 -48
  168. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +0 -71
  169. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +0 -288
  170. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +0 -143
  171. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +0 -245
  172. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +0 -992
  173. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +0 -339
  174. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +0 -286
  175. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +0 -371
  176. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +0 -293
  177. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +0 -426
  178. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +0 -152
  179. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +0 -265
  180. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +0 -184
  181. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +0 -57
  182. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +0 -100
  183. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +0 -34
  184. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +0 -124
  185. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +0 -851
  186. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +0 -4932
  187. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +0 -1657
  188. scitex/fts/_fig/_editor/_gui/_flask_editor.py +0 -36
  189. scitex/fts/_fig/_models/_Annotations.py +0 -115
  190. scitex/fts/_fig/_models/_Axes.py +0 -152
  191. scitex/fts/_fig/_models/_Figure.py +0 -138
  192. scitex/fts/_fig/_models/_Plot.py +0 -123
  193. scitex/fts/_fig/_utils/_plot_layout.py +0 -397
  194. scitex/fts/_kinds/_figure/_composite.py +0 -345
  195. scitex/fts/_kinds/_plot/_backend/__init__.py +0 -53
  196. scitex/fts/_kinds/_plot/_backend/_export.py +0 -165
  197. scitex/fts/_kinds/_plot/_backend/_render.py +0 -538
  198. scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +0 -46
  199. scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +0 -82
  200. scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +0 -441
  201. scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +0 -52
  202. scitex/fts/_kinds/_plot/_dataclasses/__init__.py +0 -47
  203. scitex/fts/_kinds/_plot/_models/_Guides.py +0 -104
  204. scitex/fts/_kinds/_plot/_models/_Styles.py +0 -245
  205. scitex/fts/_kinds/_plot/_models/__init__.py +0 -80
  206. scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +0 -156
  207. scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +0 -43
  208. scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +0 -38
  209. scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +0 -36
  210. scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +0 -60
  211. scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +0 -30
  212. scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +0 -61
  213. scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +0 -57
  214. scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +0 -30
  215. scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +0 -121
  216. scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +0 -36
  217. scitex/fts/_kinds/_plot/_utils/__init__.py +0 -129
  218. scitex/fts/_kinds/_plot/_utils/_auto_layout.py +0 -127
  219. scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +0 -111
  220. scitex/fts/_kinds/_plot/_utils/_const_sizes.py +0 -48
  221. scitex/fts/_kinds/_plot/_utils/_convert_coords.py +0 -77
  222. scitex/fts/_kinds/_plot/_utils/_get_template.py +0 -178
  223. scitex/fts/_kinds/_plot/_utils/_normalize.py +0 -73
  224. scitex/fts/_kinds/_plot/_utils/_validate.py +0 -197
  225. scitex/fts/_kinds/_table/_latex/_export.py +0 -279
  226. scitex/fts/_stats/__init__.py +0 -48
  227. scitex/fts/_stats/_dataclasses/_Stats.py +0 -423
  228. scitex/fts/_stats/_dataclasses/__init__.py +0 -48
  229. scitex/fts/_tables/__init__.py +0 -65
  230. scitex/fts/_tables/_latex/__init__.py +0 -93
  231. scitex/fts/_tables/_latex/_editor/__init__.py +0 -11
  232. scitex/fts/_tables/_latex/_editor/_app.py +0 -725
  233. scitex/fts/_tables/_latex/_figure_exporter.py +0 -153
  234. scitex/fts/_tables/_latex/_stats_formatter.py +0 -274
  235. scitex/fts/_tables/_latex/_table_exporter.py +0 -362
  236. scitex/fts/_tables/_latex/_utils.py +0 -369
  237. scitex/fts/_tables/_latex/_validator.py +0 -445
  238. scitex/io/_save_modules/_pltz_bundle.py +0 -356
  239. /scitex/{fig → canvas}/README.md +0 -0
  240. /scitex/{fig → canvas}/backend/__init__.py +0 -0
  241. /scitex/{fig → canvas}/backend/_export.py +0 -0
  242. /scitex/{fig → canvas}/backend/_render.py +0 -0
  243. /scitex/{fig → canvas}/docs/CANVAS_ARCHITECTURE.md +0 -0
  244. /scitex/{fig → canvas}/editor/__init__.py +0 -0
  245. /scitex/{fig → canvas}/editor/_dearpygui_editor.py +0 -0
  246. /scitex/{fig → canvas}/editor/_flask_editor.py +0 -0
  247. /scitex/{fig → canvas}/editor/_mpl_editor.py +0 -0
  248. /scitex/{fig → canvas}/editor/_qt_editor.py +0 -0
  249. /scitex/{fig → canvas}/editor/_tkinter_editor.py +0 -0
  250. /scitex/{fig → canvas}/editor/edit/backend_detector.py +0 -0
  251. /scitex/{fig → canvas}/editor/edit/manual_handler.py +0 -0
  252. /scitex/{fig → canvas}/editor/edit/path_resolver.py +0 -0
  253. /scitex/{fig → canvas}/editor/flask_editor/__init__.py +0 -0
  254. /scitex/{fig → canvas}/editor/flask_editor/_plotter.py +0 -0
  255. /scitex/{fig → canvas}/editor/flask_editor/_utils.py +0 -0
  256. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/reset.css +0 -0
  257. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/typography.css +0 -0
  258. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/variables.css +0 -0
  259. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/buttons.css +0 -0
  260. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/context-menu.css +0 -0
  261. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/dropdown.css +0 -0
  262. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/forms.css +0 -0
  263. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/modal.css +0 -0
  264. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/sections.css +0 -0
  265. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/element-inspector.css +0 -0
  266. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/loading.css +0 -0
  267. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/overlay.css +0 -0
  268. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/selection.css +0 -0
  269. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/statistics.css +0 -0
  270. /scitex/{fig → canvas}/editor/flask_editor/static/css/index.css +0 -0
  271. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/container.css +0 -0
  272. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/controls.css +0 -0
  273. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/preview.css +0 -0
  274. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/axis.js +0 -0
  275. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/basic.js +0 -0
  276. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/distribute.js +0 -0
  277. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/canvas.js +0 -0
  278. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/dragging.js +0 -0
  279. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/resize.js +0 -0
  280. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/selection.js +0 -0
  281. /scitex/{fig → canvas}/editor/flask_editor/static/js/core/state.js +0 -0
  282. /scitex/{fig → canvas}/editor/flask_editor/static/js/core/utils.js +0 -0
  283. /scitex/{fig → canvas}/editor/flask_editor/static/js/dev/element-inspector.js +0 -0
  284. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/bbox.js +0 -0
  285. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/element-drag.js +0 -0
  286. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/overlay.js +0 -0
  287. /scitex/{fig → canvas}/editor/flask_editor/static/js/main.js +0 -0
  288. /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/context-menu.js +0 -0
  289. /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/keyboard.js +0 -0
  290. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/controls.js +0 -0
  291. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/download.js +0 -0
  292. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/help.js +0 -0
  293. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/theme.js +0 -0
  294. /scitex/{fig → canvas}/editor/flask_editor/templates/__init__.py +0 -0
  295. /scitex/{fig → canvas}/io/_directory.py +0 -0
  296. /scitex/{fig → canvas}/model/_plot_types.py +0 -0
  297. /scitex/{fig → canvas}/utils/_defaults.py +0 -0
  298. /scitex/{fig → canvas}/utils/_validate.py +0 -0
  299. /scitex/{fts/_bundle → io/bundle}/_conversion/__init__.py +0 -0
  300. /scitex/{fts/_bundle → io/bundle}/_conversion/_bundle2dict.py +0 -0
  301. /scitex/{fts/_bundle → io/bundle}/_conversion/_dict2bundle.py +0 -0
  302. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_Axes.py +0 -0
  303. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_BBox.py +0 -0
  304. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_ColumnDef.py +0 -0
  305. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataFormat.py +0 -0
  306. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataInfo.py +0 -0
  307. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataSource.py +0 -0
  308. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_SizeMM.py +0 -0
  309. /scitex/{fts/_bundle → io/bundle}/_extractors/__init__.py +0 -0
  310. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_bar.py +0 -0
  311. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_line.py +0 -0
  312. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_scatter.py +0 -0
  313. /scitex/{fts/_kinds → io/bundle/kinds}/__init__.py +0 -0
  314. /scitex/{fts/_kinds → io/bundle/kinds}/_figure/__init__.py +0 -0
  315. /scitex/{fts/_fig → io/bundle/kinds/_figure}/_composite.py +0 -0
  316. /scitex/{fts/_kinds → io/bundle/kinds}/_plot/__init__.py +0 -0
  317. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/__init__.py +0 -0
  318. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_export.py +0 -0
  319. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_render.py +0 -0
  320. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_ChannelEncoding.py +0 -0
  321. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Encoding.py +0 -0
  322. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Theme.py +0 -0
  323. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_TraceEncoding.py +0 -0
  324. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/__init__.py +0 -0
  325. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/__init__.py +0 -0
  326. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/__init__.py +0 -0
  327. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_bar.py +0 -0
  328. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_box.py +0 -0
  329. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_distribution.py +0 -0
  330. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_errorbar.py +0 -0
  331. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_histogram.py +0 -0
  332. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_image.py +0 -0
  333. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_line.py +0 -0
  334. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_scatter.py +0 -0
  335. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_seaborn.py +0 -0
  336. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_violin.py +0 -0
  337. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/__init__.py +0 -0
  338. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_auto_layout.py +0 -0
  339. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_calc_bounds.py +0 -0
  340. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_const_sizes.py +0 -0
  341. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_convert_coords.py +0 -0
  342. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_get_template.py +0 -0
  343. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_normalize.py +0 -0
  344. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_validate.py +0 -0
  345. /scitex/{fts/_kinds → io/bundle/kinds}/_shape/__init__.py +0 -0
  346. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/__init__.py +0 -0
  347. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/_Stats.py +0 -0
  348. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/__init__.py +0 -0
  349. /scitex/{fts/_kinds → io/bundle/kinds}/_table/__init__.py +0 -0
  350. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/__init__.py +0 -0
  351. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_stats_formatter.py +0 -0
  352. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_utils.py +0 -0
  353. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_validator.py +0 -0
  354. /scitex/{fts/_kinds → io/bundle/kinds}/_text/__init__.py +0 -0
  355. /scitex/{fts/_schemas → io/bundle/schemas}/data_info.schema.json +0 -0
  356. /scitex/{fts/_schemas → io/bundle/schemas}/encoding.schema.json +0 -0
  357. /scitex/{fts/_schemas → io/bundle/schemas}/node.schema.json +0 -0
  358. /scitex/{fts/_schemas → io/bundle/schemas}/render_manifest.schema.json +0 -0
  359. /scitex/{fts/_schemas → io/bundle/schemas}/stats.schema.json +0 -0
  360. /scitex/{fts/_schemas → io/bundle/schemas}/theme.schema.json +0 -0
  361. {scitex-2.10.2.dist-info → scitex-2.11.0.dist-info}/WHEEL +0 -0
  362. {scitex-2.10.2.dist-info → scitex-2.11.0.dist-info}/entry_points.txt +0 -0
  363. {scitex-2.10.2.dist-info → scitex-2.11.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,371 +0,0 @@
1
- /**
2
- * Overlay Rendering
3
- * Handles SVG overlay for element highlighting and debug visualization
4
- */
5
-
6
- // ============================================================================
7
- // Main Overlay Update
8
- // ============================================================================
9
- function updateOverlay() {
10
- const overlay = document.getElementById('hover-overlay');
11
- // Find the visible preview element (SVG wrapper or img)
12
- const svgWrapper = document.getElementById('preview-svg-wrapper');
13
- const imgEl = document.getElementById('preview');
14
-
15
- let targetEl = null;
16
- if (svgWrapper) {
17
- targetEl = svgWrapper.querySelector('svg') || svgWrapper;
18
- } else if (imgEl && imgEl.offsetWidth > 0) {
19
- targetEl = imgEl;
20
- }
21
-
22
- if (!targetEl) return;
23
-
24
- const rect = targetEl.getBoundingClientRect();
25
- if (rect.width === 0 || rect.height === 0) return;
26
-
27
- // Guard against zero imgSize (can cause Infinity scale)
28
- if (!imgSize || !imgSize.width || !imgSize.height || imgSize.width === 0 || imgSize.height === 0) {
29
- return;
30
- }
31
-
32
- overlay.setAttribute('width', rect.width);
33
- overlay.setAttribute('height', rect.height);
34
- overlay.style.width = rect.width + 'px';
35
- overlay.style.height = rect.height + 'px';
36
-
37
- // Position overlay over the target element
38
- const containerRect = document.getElementById('preview-container').getBoundingClientRect();
39
- overlay.style.left = (rect.left - containerRect.left) + 'px';
40
- overlay.style.top = (rect.top - containerRect.top) + 'px';
41
-
42
- const scaleX = rect.width / imgSize.width;
43
- const scaleY = rect.height / imgSize.height;
44
-
45
- let svg = '';
46
-
47
- // Debug mode: draw ALL bboxes
48
- if (debugMode) {
49
- svg += drawDebugBboxes(scaleX, scaleY);
50
- }
51
-
52
- function drawElement(elementName, type) {
53
- const bbox = elementBboxes[elementName];
54
- if (!bbox) return '';
55
-
56
- const elementType = bbox.element_type || '';
57
- const hasPoints = bbox.points && bbox.points.length > 0;
58
-
59
- // Lines - draw as path
60
- if ((elementType === 'line' || elementName.includes('trace_')) && hasPoints) {
61
- return drawTracePath(bbox, scaleX, scaleY, type);
62
- }
63
- // Scatter - draw as circles
64
- else if (elementType === 'scatter' && hasPoints) {
65
- return drawScatterPoints(bbox, scaleX, scaleY, type);
66
- }
67
- // Default - draw bbox rectangle
68
- else {
69
- const rectClass = type === 'hover' ? 'hover-rect' : 'selected-rect';
70
- const labelClass = type === 'hover' ? 'hover-label' : 'selected-label';
71
- const x = bbox.x0 * scaleX - 2;
72
- const y = bbox.y0 * scaleY - 2;
73
- const w = (bbox.x1 - bbox.x0) * scaleX + 4;
74
- const h = (bbox.y1 - bbox.y0) * scaleY + 4;
75
- return `<rect class="${rectClass}" x="${x}" y="${y}" width="${w}" height="${h}" rx="2"/>` +
76
- `<text class="${labelClass}" x="${x}" y="${y - 4}">${bbox.label || elementName}</text>`;
77
- }
78
- }
79
-
80
- if (hoveredElement && hoveredElement !== selectedElement) {
81
- svg += drawElement(hoveredElement, 'hover');
82
- }
83
-
84
- if (selectedElement) {
85
- svg += drawElement(selectedElement, 'selected');
86
- }
87
-
88
- overlay.innerHTML = svg;
89
- }
90
-
91
- // ============================================================================
92
- // Draw Path/Line Elements
93
- // ============================================================================
94
- function drawTracePath(bbox, scaleX, scaleY, type) {
95
- if (!Array.isArray(bbox.points) || bbox.points.length < 2) return '';
96
-
97
- const points = bbox.points.filter(pt => Array.isArray(pt) && pt.length >= 2);
98
- if (points.length < 2) return '';
99
-
100
- let pathD = `M ${points[0][0] * scaleX} ${points[0][1] * scaleY}`;
101
- for (let i = 1; i < points.length; i++) {
102
- pathD += ` L ${points[i][0] * scaleX} ${points[i][1] * scaleY}`;
103
- }
104
-
105
- const className = type === 'hover' ? 'hover-path' : 'selected-path';
106
- const labelX = points[0][0] * scaleX;
107
- const labelY = points[0][1] * scaleY - 8;
108
- const labelClass = type === 'hover' ? 'hover-label' : 'selected-label';
109
-
110
- return `<path class="${className}" d="${pathD}"/>` +
111
- `<text class="${labelClass}" x="${labelX}" y="${labelY}">${bbox.label || ''}</text>`;
112
- }
113
-
114
- // ============================================================================
115
- // Draw Scatter Points
116
- // ============================================================================
117
- function drawScatterPoints(bbox, scaleX, scaleY, type) {
118
- // Draw scatter points as circles
119
- if (!Array.isArray(bbox.points) || bbox.points.length === 0) return '';
120
-
121
- const className = type === 'hover' ? 'hover-scatter' : 'selected-scatter';
122
- const labelClass = type === 'hover' ? 'hover-label' : 'selected-label';
123
- const radius = 4;
124
-
125
- let svg = '';
126
- for (const pt of bbox.points) {
127
- if (!Array.isArray(pt) || pt.length < 2) continue;
128
- const [x, y] = pt;
129
- svg += `<circle class="${className}" cx="${x * scaleX}" cy="${y * scaleY}" r="${radius}"/>`;
130
- }
131
-
132
- // Add label near first point
133
- const validPoints = bbox.points.filter(pt => Array.isArray(pt) && pt.length >= 2);
134
- if (validPoints.length > 0) {
135
- const labelX = validPoints[0][0] * scaleX;
136
- const labelY = validPoints[0][1] * scaleY - 10;
137
- svg += `<text class="${labelClass}" x="${labelX}" y="${labelY}">${bbox.label || ''}</text>`;
138
- }
139
-
140
- return svg;
141
- }
142
-
143
- // ============================================================================
144
- // Debug Visualization
145
- // ============================================================================
146
- function drawDebugBboxes(scaleX, scaleY) {
147
- let svg = '';
148
- let count = 0;
149
-
150
- for (const [name, bbox] of Object.entries(elementBboxes)) {
151
- if (name === '_meta') continue;
152
-
153
- count++;
154
- const hasPoints = bbox.points && bbox.points.length > 0;
155
- const elementType = bbox.element_type || '';
156
-
157
- // Choose color based on element type
158
- let rectClass = 'debug-rect';
159
- if (name.includes('trace_') || elementType === 'line') {
160
- rectClass = 'debug-rect-trace';
161
- } else if (name.includes('legend')) {
162
- rectClass = 'debug-rect-legend';
163
- }
164
-
165
- // Draw bbox rectangle
166
- const x = bbox.x0 * scaleX;
167
- const y = bbox.y0 * scaleY;
168
- const w = (bbox.x1 - bbox.x0) * scaleX;
169
- const h = (bbox.y1 - bbox.y0) * scaleY;
170
-
171
- svg += `<rect class="${rectClass}" x="${x}" y="${y}" width="${w}" height="${h}"/>`;
172
- svg += `<text class="debug-label" x="${x + 2}" y="${y + 10}">${name}</text>`;
173
-
174
- // Draw path points if available
175
- if (hasPoints && bbox.points.length > 1) {
176
- let pathD = `M ${bbox.points[0][0] * scaleX} ${bbox.points[0][1] * scaleY}`;
177
- for (let i = 1; i < bbox.points.length; i++) {
178
- const pt = bbox.points[i];
179
- if (pt && pt.length >= 2) {
180
- pathD += ` L ${pt[0] * scaleX} ${pt[1] * scaleY}`;
181
- }
182
- }
183
- svg += `<path class="debug-path" d="${pathD}"/>`;
184
- }
185
- }
186
-
187
- return svg;
188
- }
189
-
190
- function toggleDebugMode() {
191
- debugMode = !debugMode;
192
- const btn = document.getElementById('debug-toggle-btn');
193
- if (btn) {
194
- btn.classList.toggle('active', debugMode);
195
- btn.textContent = debugMode ? 'Hide Hit Areas' : 'Show Hit Areas';
196
- }
197
- updateOverlay();
198
- }
199
-
200
- // ============================================================================
201
- // Panel Overlay Update (for multi-panel canvas)
202
- // ============================================================================
203
- function updatePanelOverlay(overlay, bboxes, imgSizePanel, displayWidth, displayHeight, hovered, selected, img) {
204
- if (!overlay) return;
205
-
206
- overlay.innerHTML = '';
207
-
208
- // Calculate actual rendered dimensions accounting for object-fit: contain
209
- let scaleX, scaleY, offsetX = 0, offsetY = 0;
210
-
211
- if (img && img.naturalWidth && img.naturalHeight) {
212
- const dims = getObjectFitContainDimensions(img);
213
- scaleX = dims.displayWidth / imgSizePanel.width;
214
- scaleY = dims.displayHeight / imgSizePanel.height;
215
- offsetX = dims.offsetX;
216
- offsetY = dims.offsetY;
217
-
218
- // Use container dimensions for the overlay size
219
- overlay.setAttribute('width', img.clientWidth);
220
- overlay.setAttribute('height', img.clientHeight);
221
- } else {
222
- // Fallback for backward compatibility
223
- scaleX = displayWidth / imgSizePanel.width;
224
- scaleY = displayHeight / imgSizePanel.height;
225
- overlay.setAttribute('width', displayWidth);
226
- overlay.setAttribute('height', displayHeight);
227
- }
228
-
229
- let svg = '';
230
-
231
- // Debug mode: draw all bboxes (with offset for object-fit:contain letterboxing)
232
- if (panelDebugMode) {
233
- svg += drawPanelDebugBboxes(bboxes, scaleX, scaleY, offsetX, offsetY);
234
- }
235
-
236
- function drawPanelElement(elementName, type) {
237
- const bbox = bboxes[elementName];
238
- if (!bbox) return '';
239
-
240
- const elementType = bbox.element_type || '';
241
- const hasPoints = bbox.points && bbox.points.length > 0;
242
-
243
- // Lines - draw as path (with offset)
244
- if ((elementType === 'line' || elementName.includes('trace_')) && hasPoints) {
245
- const points = bbox.points.filter(pt => Array.isArray(pt) && pt.length >= 2);
246
- if (points.length < 2) return '';
247
-
248
- let pathD = `M ${points[0][0] * scaleX + offsetX} ${points[0][1] * scaleY + offsetY}`;
249
- for (let i = 1; i < points.length; i++) {
250
- pathD += ` L ${points[i][0] * scaleX + offsetX} ${points[i][1] * scaleY + offsetY}`;
251
- }
252
-
253
- const className = type === 'hover' ? 'hover-path' : 'selected-path';
254
- return `<path class="${className}" d="${pathD}"/>`;
255
- }
256
- // Scatter - draw as circles (with offset)
257
- else if (elementType === 'scatter' && hasPoints) {
258
- const className = type === 'hover' ? 'hover-scatter' : 'selected-scatter';
259
- let circles = '';
260
- for (const pt of bbox.points) {
261
- if (!Array.isArray(pt) || pt.length < 2) continue;
262
- const [x, y] = pt;
263
- circles += `<circle class="${className}" cx="${x * scaleX + offsetX}" cy="${y * scaleY + offsetY}" r="3"/>`;
264
- }
265
- return circles;
266
- }
267
- // Default - draw bbox rectangle (with offset)
268
- else {
269
- const rectClass = type === 'hover' ? 'hover-rect' : 'selected-rect';
270
- const x = bbox.x0 * scaleX + offsetX;
271
- const y = bbox.y0 * scaleY + offsetY;
272
- const w = (bbox.x1 - bbox.x0) * scaleX;
273
- const h = (bbox.y1 - bbox.y0) * scaleY;
274
- return `<rect class="${rectClass}" x="${x}" y="${y}" width="${w}" height="${h}" rx="1"/>`;
275
- }
276
- }
277
-
278
- if (hovered && hovered !== selected) {
279
- svg += drawPanelElement(hovered, 'hover');
280
- }
281
-
282
- if (selected) {
283
- svg += drawPanelElement(selected, 'selected');
284
- }
285
-
286
- overlay.innerHTML = svg;
287
- }
288
-
289
- function drawPanelDebugBboxes(bboxes, scaleX, scaleY, offsetX, offsetY) {
290
- let svg = '';
291
-
292
- // Default offset to 0 if not provided
293
- offsetX = offsetX || 0;
294
- offsetY = offsetY || 0;
295
-
296
- for (const [name, bbox] of Object.entries(bboxes)) {
297
- if (name === '_meta') continue;
298
-
299
- const hasPoints = bbox.points && bbox.points.length > 0;
300
- const elementType = bbox.element_type || '';
301
-
302
- // Choose color based on element type
303
- let rectClass = 'debug-rect';
304
- if (name.includes('trace_') || elementType === 'line') {
305
- rectClass = 'debug-rect-trace';
306
- } else if (name.includes('legend')) {
307
- rectClass = 'debug-rect-legend';
308
- }
309
-
310
- // Draw bbox rectangle (with offset for object-fit:contain letterboxing)
311
- const x = bbox.x0 * scaleX + offsetX;
312
- const y = bbox.y0 * scaleY + offsetY;
313
- const w = (bbox.x1 - bbox.x0) * scaleX;
314
- const h = (bbox.y1 - bbox.y0) * scaleY;
315
-
316
- svg += `<rect class="${rectClass}" x="${x}" y="${y}" width="${w}" height="${h}"/>`;
317
-
318
- // Draw short label (truncated for small panels)
319
- const shortName = name.length > 15 ? name.substring(0, 12) + '...' : name;
320
- svg += `<text class="debug-label" x="${x + 2}" y="${y + 8}" font-size="8">${shortName}</text>`;
321
-
322
- // Draw path points if available (with offset)
323
- if (hasPoints && bbox.points.length > 1) {
324
- let pathD = `M ${bbox.points[0][0] * scaleX + offsetX} ${bbox.points[0][1] * scaleY + offsetY}`;
325
- for (let i = 1; i < bbox.points.length; i++) {
326
- const pt = bbox.points[i];
327
- if (pt && pt.length >= 2) {
328
- pathD += ` L ${pt[0] * scaleX + offsetX} ${pt[1] * scaleY + offsetY}`;
329
- }
330
- }
331
- svg += `<path class="debug-path" d="${pathD}" stroke-width="0.5"/>`;
332
- }
333
- }
334
-
335
- return svg;
336
- }
337
-
338
- function togglePanelDebugMode() {
339
- panelDebugMode = !panelDebugMode;
340
- const btn = document.getElementById('panel-debug-toggle-btn');
341
- if (btn) {
342
- btn.classList.toggle('active', panelDebugMode);
343
- btn.textContent = panelDebugMode ? 'Hide Panel Hit Areas' : 'Show Panel Hit Areas';
344
- }
345
-
346
- // Redraw all panel overlays
347
- redrawAllPanelOverlays();
348
- }
349
-
350
- function redrawAllPanelOverlays() {
351
- document.querySelectorAll('.panel-canvas-item').forEach((item, idx) => {
352
- const panelName = item.dataset.panelName;
353
- const overlay = item.querySelector('.panel-card-overlay');
354
- const img = item.querySelector('img');
355
- const panelCache = panelBboxesCache[panelName];
356
-
357
- if (overlay && img && panelCache) {
358
- const rect = img.getBoundingClientRect();
359
- updatePanelOverlay(
360
- overlay,
361
- panelCache.bboxes,
362
- panelCache.imgSize,
363
- rect.width,
364
- rect.height,
365
- panelHoveredElement,
366
- selectedElement,
367
- img
368
- );
369
- }
370
- });
371
- }
@@ -1,293 +0,0 @@
1
- /**
2
- * Preview Management
3
- * Handles preview loading, panel navigation, and grid view
4
- */
5
-
6
- // ============================================================================
7
- // Initial Preview Loading
8
- // ============================================================================
9
- async function loadInitialPreview() {
10
- setStatus('Loading preview...', false);
11
- try {
12
- const resp = await fetch('/preview');
13
- const data = await resp.json();
14
-
15
- console.log('=== PREVIEW DATA RECEIVED ===');
16
- console.log('format:', data.format);
17
- console.log('img_size:', data.img_size);
18
- console.log('bboxes keys:', Object.keys(data.bboxes || {}));
19
-
20
- const previewContainer = document.getElementById('preview-container');
21
- const img = document.getElementById('preview');
22
-
23
- if (data.format === 'svg' && data.svg) {
24
- // Handle SVG: replace img with inline SVG
25
- const svgWrapper = document.createElement('div');
26
- svgWrapper.id = 'preview-svg-wrapper';
27
- svgWrapper.innerHTML = data.svg;
28
- svgWrapper.style.width = '100%';
29
- svgWrapper.style.maxHeight = '70vh';
30
-
31
- // Find the SVG element and set styles
32
- const svgEl = svgWrapper.querySelector('svg');
33
- if (svgEl) {
34
- svgEl.style.width = '100%';
35
- svgEl.style.height = 'auto';
36
- svgEl.style.maxHeight = '70vh';
37
- svgEl.id = 'preview'; // Keep same ID for event handlers
38
- }
39
-
40
- img.style.display = 'none';
41
- const existingWrapper = document.getElementById('preview-svg-wrapper');
42
- if (existingWrapper) existingWrapper.remove();
43
- previewContainer.appendChild(svgWrapper);
44
- } else if (data.image) {
45
- // Handle PNG: show as base64 image
46
- img.src = 'data:image/png;base64,' + data.image;
47
- img.style.display = 'block';
48
- const existingWrapper = document.getElementById('preview-svg-wrapper');
49
- if (existingWrapper) existingWrapper.remove();
50
- }
51
-
52
- if (data.bboxes) {
53
- elementBboxes = data.bboxes;
54
- originalBboxes = JSON.parse(JSON.stringify(data.bboxes)); // Deep copy
55
- if (data.bboxes._meta) {
56
- schemaMeta = data.bboxes._meta;
57
- }
58
- }
59
- if (data.img_size) {
60
- imgSize = data.img_size;
61
- originalImgSize = {...data.img_size}; // Copy
62
- }
63
-
64
- isShowingOriginalPreview = true;
65
- updateOverlay();
66
- setStatus('Preview loaded', false);
67
-
68
- // Initialize hover system for the SVG if needed
69
- if (data.format === 'svg') {
70
- const svgWrapper = document.getElementById('preview-svg-wrapper');
71
- if (svgWrapper) {
72
- initHoverSystemForElement(svgWrapper.querySelector('svg'));
73
- }
74
- }
75
-
76
- // Draw debug bboxes if debug mode is on
77
- if (debugMode) {
78
- updateOverlay();
79
- }
80
-
81
- // Handle multi-panel figz bundles
82
- if (data.panel_info && data.panel_info.panels) {
83
- panelData = data.panel_info;
84
- currentPanelIndex = data.panel_info.current_index || 0;
85
- console.log('Multi-panel figz detected:', panelData.panels.length, 'panels');
86
- loadPanelGrid();
87
- }
88
-
89
- // Start auto-update AFTER initial preview is loaded
90
- setAutoUpdateInterval();
91
- } catch (e) {
92
- setStatus('Error loading preview: ' + e.message, true);
93
- console.error('Preview load error:', e);
94
- // Start auto-update even on error so the editor works
95
- setAutoUpdateInterval();
96
- }
97
- }
98
-
99
- // ============================================================================
100
- // Multi-Panel Grid Loading
101
- // ============================================================================
102
- async function loadPanelGrid() {
103
- if (!panelData || panelData.panels.length <= 1) {
104
- // Not a multi-panel bundle or only one panel
105
- document.getElementById('panel-grid-section').style.display = 'none';
106
- document.getElementById('preview-header').style.display = 'none';
107
- return;
108
- }
109
-
110
- console.log('Loading panel canvas for', panelData.panels.length, 'panels');
111
-
112
- // Hide single-panel preview completely for multi-panel bundles (unified canvas only)
113
- document.getElementById('preview-header').style.display = 'none';
114
- const previewWrapper = document.querySelector('.preview-wrapper');
115
- if (previewWrapper) {
116
- previewWrapper.style.display = 'none';
117
- }
118
-
119
- // Fetch all panel images with bboxes
120
- try {
121
- const resp = await fetch('/panels');
122
- const data = await resp.json();
123
-
124
- if (data.error) {
125
- console.error('Panel canvas error:', data.error);
126
- return;
127
- }
128
-
129
- const canvasEl = document.getElementById('panel-canvas');
130
- canvasEl.innerHTML = '';
131
-
132
- // Use figz layout to position panels as unified canvas (matching export)
133
- const hasLayout = data.layout && Object.keys(data.layout).length > 0;
134
-
135
- // Calculate scale factor: convert mm to pixels
136
- // Find total figure dimensions from layout
137
- let maxX = 0, maxY = 0;
138
- if (hasLayout) {
139
- Object.values(data.layout).forEach(l => {
140
- const right = (l.position?.x_mm || 0) + (l.size?.width_mm || 80);
141
- const bottom = (l.position?.y_mm || 0) + (l.size?.height_mm || 50);
142
- maxX = Math.max(maxX, right);
143
- maxY = Math.max(maxY, bottom);
144
- });
145
- }
146
-
147
- // Scale to fit canvas (max width ~700px for good display)
148
- const canvasMaxWidth = 700;
149
- const scale = hasLayout && maxX > 0 ? canvasMaxWidth / maxX : 3; // ~3px per mm fallback
150
- canvasScale = scale; // Store globally for drag conversions
151
-
152
- // Reset layout tracking
153
- panelLayoutMm = {};
154
- layoutModified = false;
155
-
156
- data.panels.forEach((panel, idx) => {
157
- // Store bboxes and imgSize in cache for interactive hover/click
158
- if (panel.bboxes && panel.img_size) {
159
- panelBboxesCache[panel.name] = {
160
- bboxes: panel.bboxes,
161
- imgSize: panel.img_size
162
- };
163
- }
164
-
165
- // Use figz layout for positioning (unified canvas like export)
166
- let pos, posMm;
167
- if (panel.layout && panel.layout.position && panel.layout.size) {
168
- const x_mm = panel.layout.position.x_mm || 0;
169
- const y_mm = panel.layout.position.y_mm || 0;
170
- const width_mm = panel.layout.size.width_mm || 80;
171
- const height_mm = panel.layout.size.height_mm || 50;
172
- pos = {
173
- x: x_mm * scale,
174
- y: y_mm * scale,
175
- width: width_mm * scale,
176
- height: height_mm * scale,
177
- };
178
- posMm = { x_mm, y_mm, width_mm, height_mm };
179
- } else {
180
- // Fallback grid layout if no figz layout
181
- const cols = Math.ceil(Math.sqrt(data.panels.length));
182
- const baseWidth = 220, baseHeight = 180, padding = 15;
183
- const col = idx % cols;
184
- const row = Math.floor(idx / cols);
185
- pos = {
186
- x: padding + col * (baseWidth + padding),
187
- y: padding + row * (baseHeight + padding),
188
- width: baseWidth,
189
- height: baseHeight,
190
- };
191
- // Convert to mm for fallback
192
- posMm = {
193
- x_mm: pos.x / scale,
194
- y_mm: pos.y / scale,
195
- width_mm: pos.width / scale,
196
- height_mm: pos.height / scale,
197
- };
198
- }
199
- panelPositions[panel.name] = pos;
200
- panelLayoutMm[panel.name] = posMm;
201
-
202
- const item = document.createElement('div');
203
- item.className = 'panel-canvas-item' + (idx === currentPanelIndex ? ' active' : '');
204
- item.dataset.panelIndex = idx;
205
- item.dataset.panelName = panel.name;
206
- item.style.left = pos.x + 'px';
207
- item.style.top = pos.y + 'px';
208
- item.style.width = pos.width + 'px';
209
- item.style.height = pos.height + 'px';
210
-
211
- if (panel.image) {
212
- item.innerHTML = `
213
- <span class="panel-canvas-label">${panel.name}</span>
214
- <span class="panel-position-indicator" id="pos-${panel.name}"></span>
215
- <div class="panel-drag-handle" title="Drag to move panel">⋮⋮</div>
216
- <div class="panel-card-container">
217
- <img src="data:image/png;base64,${panel.image}" alt="Panel ${panel.name}">
218
- <svg class="panel-card-overlay" id="panel-overlay-${idx}"></svg>
219
- </div>
220
- `;
221
- } else {
222
- item.innerHTML = `
223
- <span class="panel-canvas-label">${panel.name}</span>
224
- <span class="panel-position-indicator" id="pos-${panel.name}"></span>
225
- <div class="panel-drag-handle" title="Drag to move panel">⋮⋮</div>
226
- <div style="padding: 20px; color: var(--text-muted);">No preview</div>
227
- `;
228
- }
229
-
230
- // Add interactive event handlers (hover, click for element selection)
231
- // Note: initCanvasItemInteraction already calls initPanelDrag internally
232
- initCanvasItemInteraction(item, idx, panel.name);
233
-
234
- canvasEl.appendChild(item);
235
- });
236
-
237
- // Update canvas size to fit all panels (unified canvas)
238
- const canvasHeight = Math.max(...Object.values(panelPositions).map(p => p.y + p.height)) + 10;
239
- const canvasWidth = Math.max(...Object.values(panelPositions).map(p => p.x + p.width)) + 10;
240
- canvasEl.style.minHeight = Math.max(400, canvasHeight) + 'px';
241
- canvasEl.style.minWidth = canvasWidth + 'px';
242
-
243
- // Update panel indicator
244
- updatePanelIndicator();
245
-
246
- // Show unified canvas for multi-panel figures
247
- showingPanelGrid = true;
248
- document.getElementById('panel-grid-section').style.display = 'block';
249
- } catch (e) {
250
- console.error('Error loading panels:', e);
251
- }
252
- }
253
-
254
- // ============================================================================
255
- // Panel Navigation
256
- // ============================================================================
257
- function togglePanelGrid() {
258
- showingPanelGrid = !showingPanelGrid;
259
- if (showingPanelGrid) {
260
- loadPanelGrid();
261
- } else {
262
- document.getElementById('panel-grid-section').style.display = 'none';
263
- }
264
- }
265
-
266
- function prevPanel() {
267
- if (currentPanelIndex > 0) {
268
- loadPanelForEditing(panelData.panels[currentPanelIndex - 1].name);
269
- }
270
- }
271
-
272
- function nextPanel() {
273
- if (currentPanelIndex < panelData.panels.length - 1) {
274
- loadPanelForEditing(panelData.panels[currentPanelIndex + 1].name);
275
- }
276
- }
277
-
278
- function updatePanelIndicator() {
279
- if (!panelData) return;
280
-
281
- const indicator = document.getElementById('panel-indicator');
282
- const prevBtn = document.getElementById('btn-prev-panel');
283
- const nextBtn = document.getElementById('btn-next-panel');
284
-
285
- // Update indicator text (if elements exist)
286
- if (indicator) {
287
- indicator.textContent = `${currentPanelIndex + 1} / ${panelData.panels.length}`;
288
- }
289
-
290
- // Update button states
291
- if (prevBtn) prevBtn.disabled = currentPanelIndex === 0;
292
- if (nextBtn) nextBtn.disabled = currentPanelIndex === panelData.panels.length - 1;
293
- }