figrecipe 0.6.0__py3-none-any.whl → 0.9.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 (269) hide show
  1. figrecipe/__init__.py +161 -1030
  2. figrecipe/__main__.py +12 -0
  3. figrecipe/_api/__init__.py +48 -0
  4. figrecipe/_api/_extract.py +108 -0
  5. figrecipe/_api/_notebook.py +61 -0
  6. figrecipe/_api/_panel.py +113 -0
  7. figrecipe/_api/_save.py +287 -0
  8. figrecipe/_api/_seaborn_proxy.py +34 -0
  9. figrecipe/_api/_style_manager.py +153 -0
  10. figrecipe/_api/_subplots.py +333 -0
  11. figrecipe/_api/_validate.py +82 -0
  12. figrecipe/_cli/__init__.py +7 -0
  13. figrecipe/_cli/_compose.py +87 -0
  14. figrecipe/_cli/_convert.py +117 -0
  15. figrecipe/_cli/_crop.py +82 -0
  16. figrecipe/_cli/_edit.py +70 -0
  17. figrecipe/_cli/_extract.py +128 -0
  18. figrecipe/_cli/_fonts.py +47 -0
  19. figrecipe/_cli/_info.py +67 -0
  20. figrecipe/_cli/_main.py +58 -0
  21. figrecipe/_cli/_reproduce.py +79 -0
  22. figrecipe/_cli/_style.py +77 -0
  23. figrecipe/_cli/_validate.py +66 -0
  24. figrecipe/_cli/_version.py +50 -0
  25. figrecipe/_composition/__init__.py +32 -0
  26. figrecipe/_composition/_alignment.py +452 -0
  27. figrecipe/_composition/_compose.py +179 -0
  28. figrecipe/_composition/_import_axes.py +127 -0
  29. figrecipe/_composition/_visibility.py +125 -0
  30. figrecipe/_dev/__init__.py +4 -93
  31. figrecipe/_dev/_plotters.py +76 -0
  32. figrecipe/_dev/_run_demos.py +56 -0
  33. figrecipe/_dev/browser/__init__.py +69 -0
  34. figrecipe/_dev/browser/_audio.py +240 -0
  35. figrecipe/_dev/browser/_caption.py +356 -0
  36. figrecipe/_dev/browser/_click_effect.py +146 -0
  37. figrecipe/_dev/browser/_cursor.py +196 -0
  38. figrecipe/_dev/browser/_highlight.py +105 -0
  39. figrecipe/_dev/browser/_narration.py +237 -0
  40. figrecipe/_dev/browser/_recorder.py +446 -0
  41. figrecipe/_dev/browser/_utils.py +178 -0
  42. figrecipe/_dev/browser/_video_trim/__init__.py +152 -0
  43. figrecipe/_dev/browser/_video_trim/_detection.py +223 -0
  44. figrecipe/_dev/browser/_video_trim/_markers.py +140 -0
  45. figrecipe/_dev/demo_plotters/__init__.py +35 -166
  46. figrecipe/_dev/demo_plotters/_categories.py +81 -0
  47. figrecipe/_dev/demo_plotters/_figure_creators.py +119 -0
  48. figrecipe/_dev/demo_plotters/_helpers.py +31 -0
  49. figrecipe/_dev/demo_plotters/_registry.py +50 -0
  50. figrecipe/_dev/demo_plotters/bar_categorical/__init__.py +4 -0
  51. figrecipe/_dev/demo_plotters/contour_surface/__init__.py +4 -0
  52. figrecipe/_dev/demo_plotters/distribution/__init__.py +4 -0
  53. figrecipe/_dev/demo_plotters/image_matrix/__init__.py +4 -0
  54. figrecipe/_dev/demo_plotters/line_curve/__init__.py +4 -0
  55. figrecipe/_dev/demo_plotters/{plot_plot.py → line_curve/plot_plot.py} +3 -2
  56. figrecipe/_dev/demo_plotters/scatter_points/__init__.py +4 -0
  57. figrecipe/_dev/demo_plotters/special/__init__.py +4 -0
  58. figrecipe/_dev/demo_plotters/{plot_pie.py → special/plot_pie.py} +5 -1
  59. figrecipe/_dev/demo_plotters/spectral_signal/__init__.py +4 -0
  60. figrecipe/_dev/demo_plotters/vector_flow/__init__.py +4 -0
  61. figrecipe/_editor/__init__.py +61 -13
  62. figrecipe/_editor/_bbox/__init__.py +43 -0
  63. figrecipe/_editor/_bbox/_collections.py +177 -0
  64. figrecipe/_editor/_bbox/_elements.py +159 -0
  65. figrecipe/_editor/_bbox/_extract.py +402 -0
  66. figrecipe/_editor/_bbox/_extract_axes.py +370 -0
  67. figrecipe/_editor/_bbox/_extract_text.py +466 -0
  68. figrecipe/_editor/_bbox/_lines.py +173 -0
  69. figrecipe/_editor/_bbox/_transforms.py +146 -0
  70. figrecipe/_editor/_call_overrides.py +183 -0
  71. figrecipe/_editor/_datatable_plot_handlers.py +249 -0
  72. figrecipe/_editor/_figure_layout.py +211 -0
  73. figrecipe/_editor/_flask_app.py +200 -1030
  74. figrecipe/_editor/_helpers.py +251 -0
  75. figrecipe/_editor/_hitmap/__init__.py +76 -0
  76. figrecipe/_editor/_hitmap/_artists/__init__.py +21 -0
  77. figrecipe/_editor/_hitmap/_artists/_collections.py +345 -0
  78. figrecipe/_editor/_hitmap/_artists/_images.py +68 -0
  79. figrecipe/_editor/_hitmap/_artists/_lines.py +107 -0
  80. figrecipe/_editor/_hitmap/_artists/_patches.py +163 -0
  81. figrecipe/_editor/_hitmap/_artists/_text.py +190 -0
  82. figrecipe/_editor/_hitmap/_colors.py +181 -0
  83. figrecipe/_editor/_hitmap/_detect.py +194 -0
  84. figrecipe/_editor/_hitmap/_restore.py +154 -0
  85. figrecipe/_editor/_hitmap_main.py +182 -0
  86. figrecipe/_editor/_overrides.py +4 -1
  87. figrecipe/_editor/_plot_types_registry.py +190 -0
  88. figrecipe/_editor/_preferences.py +135 -0
  89. figrecipe/_editor/_render_overrides.py +507 -0
  90. figrecipe/_editor/_renderer.py +81 -186
  91. figrecipe/_editor/_routes_annotation.py +114 -0
  92. figrecipe/_editor/_routes_axis.py +482 -0
  93. figrecipe/_editor/_routes_captions.py +130 -0
  94. figrecipe/_editor/_routes_composition.py +270 -0
  95. figrecipe/_editor/_routes_core.py +126 -0
  96. figrecipe/_editor/_routes_datatable.py +364 -0
  97. figrecipe/_editor/_routes_element.py +335 -0
  98. figrecipe/_editor/_routes_files.py +443 -0
  99. figrecipe/_editor/_routes_image.py +200 -0
  100. figrecipe/_editor/_routes_snapshot.py +94 -0
  101. figrecipe/_editor/_routes_style.py +243 -0
  102. figrecipe/_editor/_templates/__init__.py +116 -1
  103. figrecipe/_editor/_templates/_html.py +154 -64
  104. figrecipe/_editor/_templates/_html_components/__init__.py +13 -0
  105. figrecipe/_editor/_templates/_html_components/_composition_toolbar.py +79 -0
  106. figrecipe/_editor/_templates/_html_components/_file_browser.py +41 -0
  107. figrecipe/_editor/_templates/_html_datatable.py +92 -0
  108. figrecipe/_editor/_templates/_scripts/__init__.py +178 -0
  109. figrecipe/_editor/_templates/_scripts/_accordion.py +328 -0
  110. figrecipe/_editor/_templates/_scripts/_annotation_drag.py +504 -0
  111. figrecipe/_editor/_templates/_scripts/_api.py +228 -0
  112. figrecipe/_editor/_templates/_scripts/_canvas_context_menu.py +182 -0
  113. figrecipe/_editor/_templates/_scripts/_captions.py +231 -0
  114. figrecipe/_editor/_templates/_scripts/_colors.py +485 -0
  115. figrecipe/_editor/_templates/_scripts/_composition.py +283 -0
  116. figrecipe/_editor/_templates/_scripts/_core.py +493 -0
  117. figrecipe/_editor/_templates/_scripts/_datatable/__init__.py +59 -0
  118. figrecipe/_editor/_templates/_scripts/_datatable/_cell_edit.py +97 -0
  119. figrecipe/_editor/_templates/_scripts/_datatable/_clipboard.py +164 -0
  120. figrecipe/_editor/_templates/_scripts/_datatable/_context_menu.py +221 -0
  121. figrecipe/_editor/_templates/_scripts/_datatable/_core.py +150 -0
  122. figrecipe/_editor/_templates/_scripts/_datatable/_editable.py +511 -0
  123. figrecipe/_editor/_templates/_scripts/_datatable/_import.py +161 -0
  124. figrecipe/_editor/_templates/_scripts/_datatable/_plot.py +261 -0
  125. figrecipe/_editor/_templates/_scripts/_datatable/_selection.py +438 -0
  126. figrecipe/_editor/_templates/_scripts/_datatable/_table.py +256 -0
  127. figrecipe/_editor/_templates/_scripts/_datatable/_tabs.py +354 -0
  128. figrecipe/_editor/_templates/_scripts/_debug_snapshot.py +186 -0
  129. figrecipe/_editor/_templates/_scripts/_element_editor.py +325 -0
  130. figrecipe/_editor/_templates/_scripts/_files.py +429 -0
  131. figrecipe/_editor/_templates/_scripts/_files_context_menu.py +240 -0
  132. figrecipe/_editor/_templates/_scripts/_hitmap.py +512 -0
  133. figrecipe/_editor/_templates/_scripts/_image_drop.py +428 -0
  134. figrecipe/_editor/_templates/_scripts/_inspector.py +315 -0
  135. figrecipe/_editor/_templates/_scripts/_labels.py +464 -0
  136. figrecipe/_editor/_templates/_scripts/_legend_drag.py +270 -0
  137. figrecipe/_editor/_templates/_scripts/_modals.py +226 -0
  138. figrecipe/_editor/_templates/_scripts/_multi_select.py +198 -0
  139. figrecipe/_editor/_templates/_scripts/_overlays.py +292 -0
  140. figrecipe/_editor/_templates/_scripts/_panel_drag.py +505 -0
  141. figrecipe/_editor/_templates/_scripts/_panel_drag_snapshot.py +33 -0
  142. figrecipe/_editor/_templates/_scripts/_panel_position.py +463 -0
  143. figrecipe/_editor/_templates/_scripts/_panel_resize.py +230 -0
  144. figrecipe/_editor/_templates/_scripts/_panel_snap.py +307 -0
  145. figrecipe/_editor/_templates/_scripts/_region_select.py +255 -0
  146. figrecipe/_editor/_templates/_scripts/_selection.py +244 -0
  147. figrecipe/_editor/_templates/_scripts/_sync.py +242 -0
  148. figrecipe/_editor/_templates/_scripts/_tabs.py +89 -0
  149. figrecipe/_editor/_templates/_scripts/_undo_redo.py +348 -0
  150. figrecipe/_editor/_templates/_scripts/_view_mode.py +107 -0
  151. figrecipe/_editor/_templates/_scripts/_zoom.py +212 -0
  152. figrecipe/_editor/_templates/_styles/__init__.py +78 -0
  153. figrecipe/_editor/_templates/_styles/_base.py +111 -0
  154. figrecipe/_editor/_templates/_styles/_buttons.py +327 -0
  155. figrecipe/_editor/_templates/_styles/_color_input.py +123 -0
  156. figrecipe/_editor/_templates/_styles/_composition.py +87 -0
  157. figrecipe/_editor/_templates/_styles/_controls.py +430 -0
  158. figrecipe/_editor/_templates/_styles/_datatable/__init__.py +40 -0
  159. figrecipe/_editor/_templates/_styles/_datatable/_editable.py +203 -0
  160. figrecipe/_editor/_templates/_styles/_datatable/_panel.py +268 -0
  161. figrecipe/_editor/_templates/_styles/_datatable/_table.py +479 -0
  162. figrecipe/_editor/_templates/_styles/_datatable/_toolbar.py +384 -0
  163. figrecipe/_editor/_templates/_styles/_datatable/_vars.py +123 -0
  164. figrecipe/_editor/_templates/_styles/_dynamic_props.py +144 -0
  165. figrecipe/_editor/_templates/_styles/_file_browser.py +466 -0
  166. figrecipe/_editor/_templates/_styles/_forms.py +224 -0
  167. figrecipe/_editor/_templates/_styles/_hitmap.py +191 -0
  168. figrecipe/_editor/_templates/_styles/_inspector.py +90 -0
  169. figrecipe/_editor/_templates/_styles/_labels.py +118 -0
  170. figrecipe/_editor/_templates/_styles/_modals.py +127 -0
  171. figrecipe/_editor/_templates/_styles/_overlays.py +130 -0
  172. figrecipe/_editor/_templates/_styles/_preview.py +430 -0
  173. figrecipe/_editor/_templates/_styles/_selection.py +73 -0
  174. figrecipe/_editor/_templates/_styles/_spinner.py +117 -0
  175. figrecipe/_editor/static/audio/click.mp3 +0 -0
  176. figrecipe/_editor/static/click.mp3 +0 -0
  177. figrecipe/_editor/static/icons/favicon.ico +0 -0
  178. figrecipe/_integrations/__init__.py +17 -0
  179. figrecipe/_integrations/_scitex_stats.py +298 -0
  180. figrecipe/_params/_DECORATION_METHODS.py +8 -0
  181. figrecipe/_recorder.py +63 -109
  182. figrecipe/_recorder_utils.py +124 -0
  183. figrecipe/_reproducer/__init__.py +18 -0
  184. figrecipe/_reproducer/_core.py +509 -0
  185. figrecipe/_reproducer/_custom_plots.py +279 -0
  186. figrecipe/_reproducer/_seaborn.py +100 -0
  187. figrecipe/_reproducer/_violin.py +186 -0
  188. figrecipe/_signatures/_kwargs.py +273 -0
  189. figrecipe/_signatures/_loader.py +21 -423
  190. figrecipe/_signatures/_parsing.py +147 -0
  191. figrecipe/_utils/__init__.py +3 -0
  192. figrecipe/_utils/_bundle.py +205 -0
  193. figrecipe/_wrappers/_axes.py +252 -895
  194. figrecipe/_wrappers/_axes_helpers.py +136 -0
  195. figrecipe/_wrappers/_axes_plots.py +418 -0
  196. figrecipe/_wrappers/_axes_seaborn.py +157 -0
  197. figrecipe/_wrappers/_caption_generator.py +218 -0
  198. figrecipe/_wrappers/_figure.py +188 -1
  199. figrecipe/_wrappers/_panel_labels.py +127 -0
  200. figrecipe/_wrappers/_plot_helpers.py +143 -0
  201. figrecipe/_wrappers/_stat_annotation.py +274 -0
  202. figrecipe/_wrappers/_violin_helpers.py +180 -0
  203. figrecipe/styles/__init__.py +8 -6
  204. figrecipe/styles/_dotdict.py +72 -0
  205. figrecipe/styles/_finalize.py +134 -0
  206. figrecipe/styles/_fonts.py +77 -0
  207. figrecipe/styles/_kwargs_converter.py +178 -0
  208. figrecipe/styles/_plot_styles.py +209 -0
  209. figrecipe/styles/_style_applier.py +42 -480
  210. figrecipe/styles/_style_loader.py +16 -192
  211. figrecipe/styles/_themes.py +151 -0
  212. figrecipe/styles/presets/MATPLOTLIB.yaml +2 -1
  213. figrecipe/styles/presets/SCITEX.yaml +40 -28
  214. figrecipe-0.9.0.dist-info/METADATA +427 -0
  215. figrecipe-0.9.0.dist-info/RECORD +277 -0
  216. figrecipe-0.9.0.dist-info/entry_points.txt +2 -0
  217. figrecipe/_editor/_bbox.py +0 -978
  218. figrecipe/_editor/_hitmap.py +0 -937
  219. figrecipe/_editor/_templates/_scripts.py +0 -2778
  220. figrecipe/_editor/_templates/_styles.py +0 -1326
  221. figrecipe/_reproducer.py +0 -975
  222. figrecipe-0.6.0.dist-info/METADATA +0 -394
  223. figrecipe-0.6.0.dist-info/RECORD +0 -90
  224. /figrecipe/_dev/demo_plotters/{plot_bar.py → bar_categorical/plot_bar.py} +0 -0
  225. /figrecipe/_dev/demo_plotters/{plot_barh.py → bar_categorical/plot_barh.py} +0 -0
  226. /figrecipe/_dev/demo_plotters/{plot_contour.py → contour_surface/plot_contour.py} +0 -0
  227. /figrecipe/_dev/demo_plotters/{plot_contourf.py → contour_surface/plot_contourf.py} +0 -0
  228. /figrecipe/_dev/demo_plotters/{plot_tricontour.py → contour_surface/plot_tricontour.py} +0 -0
  229. /figrecipe/_dev/demo_plotters/{plot_tricontourf.py → contour_surface/plot_tricontourf.py} +0 -0
  230. /figrecipe/_dev/demo_plotters/{plot_tripcolor.py → contour_surface/plot_tripcolor.py} +0 -0
  231. /figrecipe/_dev/demo_plotters/{plot_triplot.py → contour_surface/plot_triplot.py} +0 -0
  232. /figrecipe/_dev/demo_plotters/{plot_boxplot.py → distribution/plot_boxplot.py} +0 -0
  233. /figrecipe/_dev/demo_plotters/{plot_ecdf.py → distribution/plot_ecdf.py} +0 -0
  234. /figrecipe/_dev/demo_plotters/{plot_hist.py → distribution/plot_hist.py} +0 -0
  235. /figrecipe/_dev/demo_plotters/{plot_hist2d.py → distribution/plot_hist2d.py} +0 -0
  236. /figrecipe/_dev/demo_plotters/{plot_violinplot.py → distribution/plot_violinplot.py} +0 -0
  237. /figrecipe/_dev/demo_plotters/{plot_hexbin.py → image_matrix/plot_hexbin.py} +0 -0
  238. /figrecipe/_dev/demo_plotters/{plot_imshow.py → image_matrix/plot_imshow.py} +0 -0
  239. /figrecipe/_dev/demo_plotters/{plot_matshow.py → image_matrix/plot_matshow.py} +0 -0
  240. /figrecipe/_dev/demo_plotters/{plot_pcolor.py → image_matrix/plot_pcolor.py} +0 -0
  241. /figrecipe/_dev/demo_plotters/{plot_pcolormesh.py → image_matrix/plot_pcolormesh.py} +0 -0
  242. /figrecipe/_dev/demo_plotters/{plot_spy.py → image_matrix/plot_spy.py} +0 -0
  243. /figrecipe/_dev/demo_plotters/{plot_errorbar.py → line_curve/plot_errorbar.py} +0 -0
  244. /figrecipe/_dev/demo_plotters/{plot_fill.py → line_curve/plot_fill.py} +0 -0
  245. /figrecipe/_dev/demo_plotters/{plot_fill_between.py → line_curve/plot_fill_between.py} +0 -0
  246. /figrecipe/_dev/demo_plotters/{plot_fill_betweenx.py → line_curve/plot_fill_betweenx.py} +0 -0
  247. /figrecipe/_dev/demo_plotters/{plot_stackplot.py → line_curve/plot_stackplot.py} +0 -0
  248. /figrecipe/_dev/demo_plotters/{plot_stairs.py → line_curve/plot_stairs.py} +0 -0
  249. /figrecipe/_dev/demo_plotters/{plot_step.py → line_curve/plot_step.py} +0 -0
  250. /figrecipe/_dev/demo_plotters/{plot_scatter.py → scatter_points/plot_scatter.py} +0 -0
  251. /figrecipe/_dev/demo_plotters/{plot_eventplot.py → special/plot_eventplot.py} +0 -0
  252. /figrecipe/_dev/demo_plotters/{plot_loglog.py → special/plot_loglog.py} +0 -0
  253. /figrecipe/_dev/demo_plotters/{plot_semilogx.py → special/plot_semilogx.py} +0 -0
  254. /figrecipe/_dev/demo_plotters/{plot_semilogy.py → special/plot_semilogy.py} +0 -0
  255. /figrecipe/_dev/demo_plotters/{plot_stem.py → special/plot_stem.py} +0 -0
  256. /figrecipe/_dev/demo_plotters/{plot_acorr.py → spectral_signal/plot_acorr.py} +0 -0
  257. /figrecipe/_dev/demo_plotters/{plot_angle_spectrum.py → spectral_signal/plot_angle_spectrum.py} +0 -0
  258. /figrecipe/_dev/demo_plotters/{plot_cohere.py → spectral_signal/plot_cohere.py} +0 -0
  259. /figrecipe/_dev/demo_plotters/{plot_csd.py → spectral_signal/plot_csd.py} +0 -0
  260. /figrecipe/_dev/demo_plotters/{plot_magnitude_spectrum.py → spectral_signal/plot_magnitude_spectrum.py} +0 -0
  261. /figrecipe/_dev/demo_plotters/{plot_phase_spectrum.py → spectral_signal/plot_phase_spectrum.py} +0 -0
  262. /figrecipe/_dev/demo_plotters/{plot_psd.py → spectral_signal/plot_psd.py} +0 -0
  263. /figrecipe/_dev/demo_plotters/{plot_specgram.py → spectral_signal/plot_specgram.py} +0 -0
  264. /figrecipe/_dev/demo_plotters/{plot_xcorr.py → spectral_signal/plot_xcorr.py} +0 -0
  265. /figrecipe/_dev/demo_plotters/{plot_barbs.py → vector_flow/plot_barbs.py} +0 -0
  266. /figrecipe/_dev/demo_plotters/{plot_quiver.py → vector_flow/plot_quiver.py} +0 -0
  267. /figrecipe/_dev/demo_plotters/{plot_streamplot.py → vector_flow/plot_streamplot.py} +0 -0
  268. {figrecipe-0.6.0.dist-info → figrecipe-0.9.0.dist-info}/WHEEL +0 -0
  269. {figrecipe-0.6.0.dist-info → figrecipe-0.9.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """JavaScript modules for the figure editor.
4
+
5
+ This package contains modular JavaScript organized by functionality:
6
+ - _accordion.py: Panel collapse/expand with state persistence
7
+ - _api.py: API calls (save, load, update, download)
8
+ - _colors.py: Color presets and conversion utilities
9
+ - _core.py: State variables and initialization
10
+ - _debug_snapshot.py: Screenshot + console log capture (Ctrl+Alt+I)
11
+ - _element_editor.py: Dynamic form fields and call properties
12
+ - _files.py: File switching functionality
13
+ - _hitmap.py: Hitmap loading and hit region drawing
14
+ - _inspector.py: Element inspector debugging
15
+ - _labels.py: Label inputs and axis/legend controls
16
+ - _modals.py: Theme and shortcuts modals
17
+ - _panel_snap.py: Panel snapping (grid, edge, center alignment)
18
+ - _panel_drag.py: Panel drag-to-move (click+drag on empty panel area)
19
+ - _panel_resize.py: Panel divider drag-to-resize
20
+ - _legend_drag.py: Legend drag-to-move (click+drag on legend)
21
+ - _panel_position.py: Panel position editing (left, bottom, width, height)
22
+ - _multi_select.py: Multi-selection with Ctrl+Click
23
+ - _overlays.py: Measurement overlays (ruler, grid, columns)
24
+ - _region_select.py: Region/marquee selection by dragging rectangle
25
+ - _selection.py: Selection drawing and property sync
26
+ - _tabs.py: Tab navigation (Figure/Axis/Element)
27
+ - _view_mode.py: View mode management (all/selected)
28
+ - _zoom.py: Zoom/pan functionality
29
+ - _undo_redo.py: Undo/redo history (Ctrl+Z, Ctrl+Shift+Z)
30
+ """
31
+
32
+ from ._accordion import SCRIPTS_ACCORDION
33
+ from ._annotation_drag import SCRIPTS_ANNOTATION_DRAG
34
+ from ._api import SCRIPTS_API
35
+ from ._canvas_context_menu import JS_CANVAS_CONTEXT_MENU
36
+ from ._captions import SCRIPTS_CAPTIONS
37
+ from ._colors import SCRIPTS_COLORS
38
+ from ._core import SCRIPTS_CORE
39
+ from ._datatable import SCRIPTS_DATATABLE
40
+ from ._debug_snapshot import SCRIPTS_DEBUG_SNAPSHOT
41
+ from ._element_editor import SCRIPTS_ELEMENT_EDITOR
42
+ from ._files import SCRIPTS_FILES
43
+ from ._files_context_menu import JS_FILES_CONTEXT_MENU
44
+ from ._hitmap import SCRIPTS_HITMAP
45
+ from ._image_drop import SCRIPTS_IMAGE_DROP
46
+ from ._inspector import SCRIPTS_INSPECTOR
47
+ from ._labels import SCRIPTS_LABELS
48
+ from ._legend_drag import SCRIPTS_LEGEND_DRAG
49
+ from ._modals import SCRIPTS_MODALS
50
+ from ._multi_select import SCRIPTS_MULTI_SELECT
51
+ from ._overlays import SCRIPTS_OVERLAYS
52
+ from ._panel_drag import SCRIPTS_PANEL_DRAG
53
+ from ._panel_drag_snapshot import SCRIPTS_PANEL_DRAG_SNAPSHOT
54
+ from ._panel_position import SCRIPTS_PANEL_POSITION
55
+ from ._panel_resize import SCRIPTS_PANEL_RESIZE
56
+ from ._panel_snap import SCRIPTS_PANEL_SNAP
57
+ from ._region_select import SCRIPTS_REGION_SELECT
58
+ from ._selection import SCRIPTS_SELECTION
59
+ from ._sync import SCRIPTS_SYNC
60
+ from ._tabs import SCRIPTS_TABS
61
+ from ._undo_redo import SCRIPTS_UNDO_REDO
62
+ from ._view_mode import SCRIPTS_VIEW_MODE
63
+ from ._zoom import SCRIPTS_ZOOM
64
+
65
+ # Combined SCRIPTS constant for backward compatibility
66
+ # Order matters: debug snapshot first (for console interception), then core/state, then features
67
+ SCRIPTS = (
68
+ SCRIPTS_DEBUG_SNAPSHOT
69
+ + SCRIPTS_CORE
70
+ + SCRIPTS_TABS
71
+ + SCRIPTS_VIEW_MODE
72
+ + SCRIPTS_COLORS
73
+ + SCRIPTS_HITMAP
74
+ + SCRIPTS_SELECTION
75
+ + SCRIPTS_MULTI_SELECT
76
+ + SCRIPTS_REGION_SELECT
77
+ + SCRIPTS_ELEMENT_EDITOR
78
+ + SCRIPTS_LABELS
79
+ + SCRIPTS_CAPTIONS
80
+ + SCRIPTS_API
81
+ + SCRIPTS_MODALS
82
+ + SCRIPTS_ZOOM
83
+ + SCRIPTS_OVERLAYS
84
+ + SCRIPTS_INSPECTOR
85
+ + SCRIPTS_FILES
86
+ + SCRIPTS_PANEL_POSITION
87
+ + SCRIPTS_PANEL_SNAP
88
+ + SCRIPTS_PANEL_DRAG_SNAPSHOT
89
+ + SCRIPTS_PANEL_DRAG
90
+ + SCRIPTS_PANEL_RESIZE
91
+ + SCRIPTS_ACCORDION
92
+ + SCRIPTS_LEGEND_DRAG
93
+ + SCRIPTS_ANNOTATION_DRAG
94
+ + SCRIPTS_IMAGE_DROP
95
+ + SCRIPTS_UNDO_REDO
96
+ + SCRIPTS_DATATABLE
97
+ + SCRIPTS_SYNC
98
+ + JS_CANVAS_CONTEXT_MENU
99
+ + JS_FILES_CONTEXT_MENU
100
+ )
101
+
102
+
103
+ def get_all_scripts():
104
+ """Return all scripts as a dictionary for testing.
105
+
106
+ Returns
107
+ -------
108
+ dict
109
+ Mapping of script name to script content.
110
+ """
111
+ return {
112
+ "accordion": SCRIPTS_ACCORDION,
113
+ "annotation_drag": SCRIPTS_ANNOTATION_DRAG,
114
+ "api": SCRIPTS_API,
115
+ "captions": SCRIPTS_CAPTIONS,
116
+ "colors": SCRIPTS_COLORS,
117
+ "core": SCRIPTS_CORE,
118
+ "datatable": SCRIPTS_DATATABLE,
119
+ "debug_snapshot": SCRIPTS_DEBUG_SNAPSHOT,
120
+ "element_editor": SCRIPTS_ELEMENT_EDITOR,
121
+ "files": SCRIPTS_FILES,
122
+ "hitmap": SCRIPTS_HITMAP,
123
+ "image_drop": SCRIPTS_IMAGE_DROP,
124
+ "inspector": SCRIPTS_INSPECTOR,
125
+ "labels": SCRIPTS_LABELS,
126
+ "legend_drag": SCRIPTS_LEGEND_DRAG,
127
+ "modals": SCRIPTS_MODALS,
128
+ "overlays": SCRIPTS_OVERLAYS,
129
+ "multi_select": SCRIPTS_MULTI_SELECT,
130
+ "panel_drag": SCRIPTS_PANEL_DRAG,
131
+ "panel_drag_snapshot": SCRIPTS_PANEL_DRAG_SNAPSHOT,
132
+ "panel_position": SCRIPTS_PANEL_POSITION,
133
+ "panel_resize": SCRIPTS_PANEL_RESIZE,
134
+ "panel_snap": SCRIPTS_PANEL_SNAP,
135
+ "region_select": SCRIPTS_REGION_SELECT,
136
+ "selection": SCRIPTS_SELECTION,
137
+ "sync": SCRIPTS_SYNC,
138
+ "tabs": SCRIPTS_TABS,
139
+ "undo_redo": SCRIPTS_UNDO_REDO,
140
+ "view_mode": SCRIPTS_VIEW_MODE,
141
+ "zoom": SCRIPTS_ZOOM,
142
+ }
143
+
144
+
145
+ __all__ = [
146
+ "SCRIPTS",
147
+ "SCRIPTS_ACCORDION",
148
+ "SCRIPTS_ANNOTATION_DRAG",
149
+ "SCRIPTS_API",
150
+ "SCRIPTS_CAPTIONS",
151
+ "SCRIPTS_COLORS",
152
+ "SCRIPTS_CORE",
153
+ "SCRIPTS_DATATABLE",
154
+ "SCRIPTS_DEBUG_SNAPSHOT",
155
+ "SCRIPTS_ELEMENT_EDITOR",
156
+ "SCRIPTS_FILES",
157
+ "SCRIPTS_HITMAP",
158
+ "SCRIPTS_IMAGE_DROP",
159
+ "SCRIPTS_INSPECTOR",
160
+ "SCRIPTS_LABELS",
161
+ "SCRIPTS_LEGEND_DRAG",
162
+ "SCRIPTS_MODALS",
163
+ "SCRIPTS_MULTI_SELECT",
164
+ "SCRIPTS_OVERLAYS",
165
+ "SCRIPTS_PANEL_DRAG",
166
+ "SCRIPTS_PANEL_DRAG_SNAPSHOT",
167
+ "SCRIPTS_PANEL_POSITION",
168
+ "SCRIPTS_PANEL_RESIZE",
169
+ "SCRIPTS_PANEL_SNAP",
170
+ "SCRIPTS_REGION_SELECT",
171
+ "SCRIPTS_SELECTION",
172
+ "SCRIPTS_SYNC",
173
+ "SCRIPTS_TABS",
174
+ "SCRIPTS_UNDO_REDO",
175
+ "SCRIPTS_VIEW_MODE",
176
+ "SCRIPTS_ZOOM",
177
+ "get_all_scripts",
178
+ ]
@@ -0,0 +1,328 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Panel accordion JavaScript for the figure editor.
4
+
5
+ This module handles collapsing/expanding of panels:
6
+ - File browser panel (left)
7
+ - Data panel (second from left)
8
+ - Properties panel (right)
9
+ - State persistence in localStorage
10
+ """
11
+
12
+ SCRIPTS_ACCORDION = """
13
+ // ==================== PANEL ACCORDION ====================
14
+ // Enables collapsing/expanding panels with state persistence
15
+
16
+ let propertiesPanelCollapsed = false;
17
+ let dataPanelCollapsed = false;
18
+ let previewPanelCollapsed = false;
19
+ // Note: fileBrowserCollapsed is declared in _files.py
20
+
21
+ // Smart expansion: when a panel collapses, expand collapsed neighbors to fill space
22
+ function checkSmartExpansion(collapsedPanelId) {
23
+ // Panel order: Files | Data | Canvas | Properties
24
+ // When one collapses, adjacent collapsed panels should expand
25
+
26
+ const filePanel = document.getElementById('file-browser-panel');
27
+ const dataPanel = document.getElementById('datatable-panel');
28
+ const previewPanel = document.getElementById('preview-panel');
29
+ const propsPanel = document.getElementById('controls-panel');
30
+
31
+ const isFileCollapsed = filePanel?.classList.contains('collapsed');
32
+ const isDataCollapsed = dataPanel?.classList.contains('collapsed');
33
+ const isPreviewCollapsed = previewPanel?.classList.contains('collapsed');
34
+ const isPropsCollapsed = propsPanel?.classList.contains('collapsed');
35
+
36
+ console.log('[SmartExpansion] Checking after', collapsedPanelId, 'collapsed');
37
+ console.log('[SmartExpansion] States - Files:', isFileCollapsed, 'Data:', isDataCollapsed,
38
+ 'Preview:', isPreviewCollapsed, 'Props:', isPropsCollapsed);
39
+
40
+ // When Canvas collapses -> expand Data if collapsed
41
+ if (collapsedPanelId === 'preview-panel' && isDataCollapsed) {
42
+ console.log('[SmartExpansion] Canvas collapsed, expanding Data panel');
43
+ expandDataPanel();
44
+ }
45
+
46
+ // When Data collapses -> expand Canvas if collapsed (prioritize canvas for viewing)
47
+ if (collapsedPanelId === 'datatable-panel' && isPreviewCollapsed) {
48
+ console.log('[SmartExpansion] Data collapsed, expanding Canvas panel');
49
+ expandPreviewPanel();
50
+ }
51
+
52
+ // When Properties collapses -> expand Canvas if collapsed
53
+ if (collapsedPanelId === 'controls-panel' && isPreviewCollapsed) {
54
+ console.log('[SmartExpansion] Properties collapsed, expanding Canvas panel');
55
+ expandPreviewPanel();
56
+ }
57
+
58
+ // When Files collapses -> expand Data if collapsed
59
+ if (collapsedPanelId === 'file-browser-panel' && isDataCollapsed) {
60
+ console.log('[SmartExpansion] Files collapsed, expanding Data panel');
61
+ expandDataPanel();
62
+ }
63
+ }
64
+
65
+ // Helper functions to expand without toggling
66
+ function expandDataPanel() {
67
+ const panel = document.getElementById('datatable-panel');
68
+ const collapseBtn = document.getElementById('btn-collapse-datatable');
69
+ if (!panel || !panel.classList.contains('collapsed')) return;
70
+
71
+ dataPanelCollapsed = false;
72
+ panel.classList.remove('collapsed');
73
+ if (collapseBtn) collapseBtn.title = 'Collapse panel';
74
+ localStorage.setItem('figrecipe_data_collapsed', 'false');
75
+ console.log('[PanelAccordion] Data panel auto-expanded');
76
+ }
77
+
78
+ function expandPreviewPanel() {
79
+ const panel = document.getElementById('preview-panel');
80
+ const collapseBtn = document.getElementById('btn-collapse-preview');
81
+ if (!panel || !panel.classList.contains('collapsed')) return;
82
+
83
+ previewPanelCollapsed = false;
84
+ panel.classList.remove('collapsed');
85
+ if (collapseBtn) collapseBtn.title = 'Collapse canvas';
86
+ localStorage.setItem('figrecipe_preview_collapsed', 'false');
87
+ console.log('[PanelAccordion] Preview panel auto-expanded');
88
+ }
89
+
90
+ function expandPropertiesPanel() {
91
+ const panel = document.getElementById('controls-panel');
92
+ const collapseBtn = document.getElementById('btn-collapse-properties');
93
+ if (!panel || !panel.classList.contains('collapsed')) return;
94
+
95
+ propertiesPanelCollapsed = false;
96
+ panel.classList.remove('collapsed');
97
+ if (collapseBtn) collapseBtn.title = 'Collapse panel';
98
+ localStorage.setItem('figrecipe_properties_collapsed', 'false');
99
+ console.log('[PanelAccordion] Properties panel auto-expanded');
100
+ }
101
+
102
+ function expandFileBrowserPanel() {
103
+ const panel = document.getElementById('file-browser-panel');
104
+ const collapseBtn = document.getElementById('btn-collapse-browser');
105
+ if (!panel || !panel.classList.contains('collapsed')) return;
106
+
107
+ // fileBrowserCollapsed is defined in _files.py
108
+ if (typeof fileBrowserCollapsed !== 'undefined') fileBrowserCollapsed = false;
109
+ panel.classList.remove('collapsed');
110
+ if (collapseBtn) {
111
+ collapseBtn.innerHTML = '❮';
112
+ collapseBtn.title = 'Collapse panel';
113
+ }
114
+ localStorage.setItem('figrecipe_filebrowser_collapsed', 'false');
115
+ console.log('[PanelAccordion] File browser auto-expanded');
116
+ }
117
+
118
+ function initPanelAccordion() {
119
+ // Properties panel collapse button
120
+ const propertiesCollapseBtn = document.getElementById('btn-collapse-properties');
121
+ const propertiesPanel = document.getElementById('controls-panel');
122
+
123
+ if (propertiesCollapseBtn && propertiesPanel) {
124
+ propertiesCollapseBtn.addEventListener('click', togglePropertiesPanel);
125
+
126
+ // Restore collapsed state from localStorage
127
+ const wasCollapsed = localStorage.getItem('figrecipe_properties_collapsed');
128
+ if (wasCollapsed === 'true') {
129
+ propertiesPanelCollapsed = true;
130
+ propertiesPanel.classList.add('collapsed');
131
+ propertiesCollapseBtn.title = 'Expand panel';
132
+ }
133
+ }
134
+
135
+ // Data panel collapse button
136
+ const dataCollapseBtn = document.getElementById('btn-collapse-datatable');
137
+ const dataPanel = document.getElementById('datatable-panel');
138
+
139
+ if (dataCollapseBtn && dataPanel) {
140
+ dataCollapseBtn.addEventListener('click', toggleDataPanel);
141
+
142
+ // Restore collapsed state from localStorage
143
+ const wasDataCollapsed = localStorage.getItem('figrecipe_data_collapsed');
144
+ if (wasDataCollapsed === 'true') {
145
+ dataPanelCollapsed = true;
146
+ dataPanel.classList.add('collapsed');
147
+ dataCollapseBtn.title = 'Expand panel';
148
+ }
149
+ }
150
+
151
+ // File browser accordion - add localStorage persistence
152
+ const fileBrowserPanel = document.getElementById('file-browser-panel');
153
+ if (fileBrowserPanel) {
154
+ const wasFileBrowserCollapsed = localStorage.getItem('figrecipe_filebrowser_collapsed');
155
+ if (wasFileBrowserCollapsed === 'true') {
156
+ fileBrowserPanel.classList.add('collapsed');
157
+ const collapseBtn = document.getElementById('btn-collapse-browser');
158
+ if (collapseBtn) {
159
+ collapseBtn.innerHTML = '❯';
160
+ collapseBtn.title = 'Expand panel';
161
+ }
162
+ }
163
+ }
164
+
165
+ // Preview/canvas panel collapse button
166
+ const previewCollapseBtn = document.getElementById('btn-collapse-preview');
167
+ const previewPanel = document.getElementById('preview-panel');
168
+
169
+ if (previewCollapseBtn && previewPanel) {
170
+ previewCollapseBtn.addEventListener('click', togglePreviewPanel);
171
+
172
+ // Restore collapsed state from localStorage
173
+ const wasPreviewCollapsed = localStorage.getItem('figrecipe_preview_collapsed');
174
+ if (wasPreviewCollapsed === 'true') {
175
+ previewPanelCollapsed = true;
176
+ previewPanel.classList.add('collapsed');
177
+ previewCollapseBtn.title = 'Expand canvas';
178
+ }
179
+ }
180
+
181
+ // Add keyboard shortcuts for toggling panels
182
+ document.addEventListener('keydown', (e) => {
183
+ // Alt+1: Toggle file browser
184
+ if (e.altKey && e.key === '1') {
185
+ e.preventDefault();
186
+ if (typeof toggleFileBrowser === 'function') {
187
+ toggleFileBrowser();
188
+ saveFileBrowserState();
189
+ }
190
+ }
191
+ // Alt+2: Toggle data panel
192
+ if (e.altKey && e.key === '2') {
193
+ e.preventDefault();
194
+ toggleDataPanel();
195
+ }
196
+ // Alt+3: Toggle canvas/preview panel
197
+ if (e.altKey && e.key === '3') {
198
+ e.preventDefault();
199
+ togglePreviewPanel();
200
+ }
201
+ // Alt+4: Toggle properties panel
202
+ if (e.altKey && e.key === '4') {
203
+ e.preventDefault();
204
+ togglePropertiesPanel();
205
+ }
206
+ });
207
+
208
+ console.log('[PanelAccordion] Initialized');
209
+ }
210
+
211
+ function toggleDataPanel() {
212
+ const panel = document.getElementById('datatable-panel');
213
+ const collapseBtn = document.getElementById('btn-collapse-datatable');
214
+ if (!panel) return;
215
+
216
+ dataPanelCollapsed = !dataPanelCollapsed;
217
+ panel.classList.toggle('collapsed', dataPanelCollapsed);
218
+
219
+ if (collapseBtn) {
220
+ collapseBtn.title = dataPanelCollapsed ? 'Expand panel' : 'Collapse panel';
221
+ }
222
+
223
+ // Persist state
224
+ localStorage.setItem('figrecipe_data_collapsed', dataPanelCollapsed);
225
+
226
+ console.log('[PanelAccordion] Data panel', dataPanelCollapsed ? 'collapsed' : 'expanded');
227
+
228
+ // Smart expansion: if collapsing, check if neighbors should expand
229
+ if (dataPanelCollapsed) {
230
+ checkSmartExpansion('datatable-panel');
231
+ }
232
+ }
233
+
234
+ function togglePropertiesPanel() {
235
+ const panel = document.getElementById('controls-panel');
236
+ const collapseBtn = document.getElementById('btn-collapse-properties');
237
+ if (!panel) return;
238
+
239
+ propertiesPanelCollapsed = !propertiesPanelCollapsed;
240
+ panel.classList.toggle('collapsed', propertiesPanelCollapsed);
241
+
242
+ if (collapseBtn) {
243
+ collapseBtn.title = propertiesPanelCollapsed ? 'Expand panel' : 'Collapse panel';
244
+ }
245
+
246
+ // Persist state
247
+ localStorage.setItem('figrecipe_properties_collapsed', propertiesPanelCollapsed);
248
+
249
+ console.log('[PanelAccordion] Properties panel', propertiesPanelCollapsed ? 'collapsed' : 'expanded');
250
+
251
+ // Smart expansion: if collapsing, check if neighbors should expand
252
+ if (propertiesPanelCollapsed) {
253
+ checkSmartExpansion('controls-panel');
254
+ }
255
+ }
256
+
257
+ function togglePreviewPanel() {
258
+ const panel = document.getElementById('preview-panel');
259
+ const collapseBtn = document.getElementById('btn-collapse-preview');
260
+ if (!panel) return;
261
+
262
+ previewPanelCollapsed = !previewPanelCollapsed;
263
+ panel.classList.toggle('collapsed', previewPanelCollapsed);
264
+
265
+ if (collapseBtn) {
266
+ collapseBtn.title = previewPanelCollapsed ? 'Expand canvas' : 'Collapse canvas';
267
+ }
268
+
269
+ // Persist state
270
+ localStorage.setItem('figrecipe_preview_collapsed', previewPanelCollapsed);
271
+
272
+ console.log('[PanelAccordion] Preview panel', previewPanelCollapsed ? 'collapsed' : 'expanded');
273
+
274
+ // Smart expansion: if collapsing, check if neighbors should expand
275
+ if (previewPanelCollapsed) {
276
+ checkSmartExpansion('preview-panel');
277
+ }
278
+ }
279
+
280
+ function saveFileBrowserState() {
281
+ const panel = document.getElementById('file-browser-panel');
282
+ if (panel) {
283
+ const isCollapsed = panel.classList.contains('collapsed');
284
+ localStorage.setItem('figrecipe_filebrowser_collapsed', isCollapsed);
285
+ }
286
+ }
287
+
288
+ // Hook into existing toggleFileBrowser to save state
289
+ const originalToggleFileBrowser = typeof window.toggleFileBrowser === 'function'
290
+ ? window.toggleFileBrowser
291
+ : null;
292
+
293
+ window.toggleFileBrowser = function() {
294
+ if (originalToggleFileBrowser) {
295
+ originalToggleFileBrowser();
296
+ } else {
297
+ // Fallback implementation
298
+ const panel = document.getElementById('file-browser-panel');
299
+ const collapseBtn = document.getElementById('btn-collapse-browser');
300
+ if (!panel) return;
301
+
302
+ panel.classList.toggle('collapsed');
303
+ if (collapseBtn) {
304
+ const isCollapsed = panel.classList.contains('collapsed');
305
+ collapseBtn.innerHTML = isCollapsed ? '❯' : '❮';
306
+ collapseBtn.title = isCollapsed ? 'Expand panel' : 'Collapse panel';
307
+ }
308
+ }
309
+ saveFileBrowserState();
310
+
311
+ // Smart expansion: if collapsing, check if neighbors should expand
312
+ const panel = document.getElementById('file-browser-panel');
313
+ if (panel && panel.classList.contains('collapsed')) {
314
+ checkSmartExpansion('file-browser-panel');
315
+ }
316
+ };
317
+
318
+ // Initialize on DOM ready
319
+ if (document.readyState === 'loading') {
320
+ document.addEventListener('DOMContentLoaded', initPanelAccordion);
321
+ } else {
322
+ initPanelAccordion();
323
+ }
324
+ """
325
+
326
+ __all__ = ["SCRIPTS_ACCORDION"]
327
+
328
+ # EOF