pgwidgets-js 0.4.0__tar.gz → 0.4.2__tar.gz

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 (211) hide show
  1. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/.github/workflows/tests.yml +3 -3
  2. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/PKG-INFO +3 -3
  3. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/WhatsNew.rst +87 -0
  4. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/widgets/display.rst +56 -17
  5. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/widgets/text.rst +23 -1
  6. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/package.json +1 -1
  7. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/defs.py +7 -1
  8. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/TextArea.js +51 -0
  9. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/TextSource.js +28 -4
  10. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/TreeView.js +82 -27
  11. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js.egg-info/PKG-INFO +3 -3
  12. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js.egg-info/SOURCES.txt +5 -1
  13. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js.egg-info/scm_file_list.json +5 -1
  14. pgwidgets_js-0.4.2/pgwidgets_js.egg-info/scm_version.json +8 -0
  15. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pyproject.toml +4 -3
  16. pgwidgets_js-0.4.2/tests/test_treeview_resize.py +34 -0
  17. pgwidgets_js-0.4.2/tests/test_treeview_select.py +32 -0
  18. pgwidgets_js-0.4.2/tests/treeview_resize.mjs +199 -0
  19. pgwidgets_js-0.4.2/tests/treeview_select.mjs +92 -0
  20. pgwidgets_js-0.4.0/pgwidgets_js.egg-info/scm_version.json +0 -8
  21. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/.flake8 +0 -0
  22. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/.gitignore +0 -0
  23. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/.readthedocs.yaml +0 -0
  24. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/LICENSE.md +0 -0
  25. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/MANIFEST.in +0 -0
  26. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/README.md +0 -0
  27. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/Widgets.css +0 -0
  28. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/Widgets.js +0 -0
  29. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/Makefile +0 -0
  30. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/callbacks.rst +0 -0
  31. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/conf.py +0 -0
  32. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/electron.rst +0 -0
  33. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/external-widgets.rst +0 -0
  34. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/for-developers.rst +0 -0
  35. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/frameworks.rst +0 -0
  36. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/getting-started.rst +0 -0
  37. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/index.rst +0 -0
  38. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/pyodide.rst +0 -0
  39. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/remote.rst +0 -0
  40. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/styling.rst +0 -0
  41. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/widgets/controls.rst +0 -0
  42. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/widgets/dialogs.rst +0 -0
  43. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/widgets/index.rst +0 -0
  44. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/widgets/layout.rst +0 -0
  45. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/widgets/menus.rst +0 -0
  46. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/docs/widgets/nonvisual.rst +0 -0
  47. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/all_widgets.html +0 -0
  48. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/all_widgets_pyodide.html +0 -0
  49. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/all_widgets_pyodide.py +0 -0
  50. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/all_widgets_pyscript.html +0 -0
  51. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/all_widgets_pyscript.py +0 -0
  52. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/box.html +0 -0
  53. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/button.html +0 -0
  54. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/canvas.html +0 -0
  55. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/checkbox.html +0 -0
  56. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/colordialog.html +0 -0
  57. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/combobox.html +0 -0
  58. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/debug_spinbox.html +0 -0
  59. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/dial.html +0 -0
  60. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/dialog.html +0 -0
  61. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/electron/.gitignore +0 -0
  62. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/electron/.npmrc +0 -0
  63. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/electron/index.html +0 -0
  64. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/electron/main.js +0 -0
  65. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/electron/package.json +0 -0
  66. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/expander.html +0 -0
  67. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/external_widgets.html +0 -0
  68. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/fixedlayout.html +0 -0
  69. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/frame.html +0 -0
  70. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/gridbox.html +0 -0
  71. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/htmlview.html +0 -0
  72. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/image.html +0 -0
  73. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/label.html +0 -0
  74. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/mdi_widget.html +0 -0
  75. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/menu.html +0 -0
  76. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/progressbar.html +0 -0
  77. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/pyodide_demo.html +0 -0
  78. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/pyscript.toml +0 -0
  79. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/radiobutton.html +0 -0
  80. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/remote.html +0 -0
  81. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/remote_demo.py +0 -0
  82. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/remote_demo_async.py +0 -0
  83. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/scroll_area.html +0 -0
  84. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/scrollable.html +0 -0
  85. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/scrollbar.html +0 -0
  86. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/slider.html +0 -0
  87. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/spinbox.html +0 -0
  88. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/splitter.html +0 -0
  89. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/tab_widget.html +0 -0
  90. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/tableview.html +0 -0
  91. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/text_entry.html +0 -0
  92. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/textarea.html +0 -0
  93. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/textentryset.html +0 -0
  94. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/textsource.html +0 -0
  95. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/togglebutton.html +0 -0
  96. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/toolbar.html +0 -0
  97. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/treeview.html +0 -0
  98. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/examples/videowidget.html +0 -0
  99. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/__init__.py +0 -0
  100. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/pyodide/__init__.py +0 -0
  101. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/pyodide/log.py +0 -0
  102. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/pyodide/widget.py +0 -0
  103. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/Widgets.css +0 -0
  104. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/Widgets.js +0 -0
  105. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/AbstractScrollArea.css +0 -0
  106. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Box.css +0 -0
  107. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Button.css +0 -0
  108. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/CheckBox.css +0 -0
  109. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/ColorDialog.css +0 -0
  110. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/ComboBox.css +0 -0
  111. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Dial.css +0 -0
  112. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Dialog.css +0 -0
  113. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Expander.css +0 -0
  114. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/ExternalWidget.css +0 -0
  115. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/FixedLayout.css +0 -0
  116. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Frame.css +0 -0
  117. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/GridBox.css +0 -0
  118. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/HtmlView.css +0 -0
  119. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Image.css +0 -0
  120. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Label.css +0 -0
  121. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/MDIWidget.css +0 -0
  122. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Menu.css +0 -0
  123. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/ProgressBar.css +0 -0
  124. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/RadioButton.css +0 -0
  125. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/ScrollArea.css +0 -0
  126. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/ScrollBar.css +0 -0
  127. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Slider.css +0 -0
  128. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/SpinBox.css +0 -0
  129. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Splitter.css +0 -0
  130. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/StatusBar.css +0 -0
  131. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/TabWidget.css +0 -0
  132. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Text.css +0 -0
  133. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/TextArea.css +0 -0
  134. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/TextEntrySet.css +0 -0
  135. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/TextSource.css +0 -0
  136. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/ToggleButton.css +0 -0
  137. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/ToolBar.css +0 -0
  138. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/TopLevel.css +0 -0
  139. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/TreeView.css +0 -0
  140. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/VideoWidget.css +0 -0
  141. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/Widget.css +0 -0
  142. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/css/WindowMenu.css +0 -0
  143. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/icons/file.svg +0 -0
  144. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/icons/folder.svg +0 -0
  145. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/icons/hdots.svg +0 -0
  146. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/icons/pgicon.svg +0 -0
  147. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/icons/pgwidgets-logo.png +0 -0
  148. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/icons/pgwidgets-logo.svg +0 -0
  149. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/icons/vdots.svg +0 -0
  150. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/AbstractScrollArea.js +0 -0
  151. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Box.js +0 -0
  152. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Button.js +0 -0
  153. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Callback.js +0 -0
  154. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Canvas.js +0 -0
  155. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/CheckBox.js +0 -0
  156. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/ColorDialog.js +0 -0
  157. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/ColorWidget.js +0 -0
  158. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/ComboBox.js +0 -0
  159. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/ComboBoxNative.js +0 -0
  160. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Dial.js +0 -0
  161. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Dialog.js +0 -0
  162. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Expander.js +0 -0
  163. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/ExternalWidget.js +0 -0
  164. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/FileDialog.js +0 -0
  165. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/FixedLayout.js +0 -0
  166. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Frame.js +0 -0
  167. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/GridBox.js +0 -0
  168. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/HtmlView.js +0 -0
  169. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Image.js +0 -0
  170. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Label.js +0 -0
  171. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/MDIWidget.js +0 -0
  172. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Menu.js +0 -0
  173. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/MenuAction.js +0 -0
  174. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/MenuBar.js +0 -0
  175. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Page.js +0 -0
  176. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/ProgressBar.js +0 -0
  177. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/RadioButton.js +0 -0
  178. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/RemoteInterface.js +0 -0
  179. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/ScrollArea.js +0 -0
  180. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/ScrollBar.js +0 -0
  181. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Separator.js +0 -0
  182. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Slider.js +0 -0
  183. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/SpinBox.js +0 -0
  184. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Splitter.js +0 -0
  185. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/StatusBar.js +0 -0
  186. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/TabWidget.js +0 -0
  187. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/TableView.js +0 -0
  188. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/TextEntry.js +0 -0
  189. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/TextEntrySet.js +0 -0
  190. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/TextWidget.js +0 -0
  191. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Timer.js +0 -0
  192. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/ToggleButton.js +0 -0
  193. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/ToolBar.js +0 -0
  194. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/ToolBarAction.js +0 -0
  195. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/TopLevel.js +0 -0
  196. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/VideoWidget.js +0 -0
  197. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/Widget.js +0 -0
  198. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/modules/WindowMenu.js +0 -0
  199. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js/static/remote.html +0 -0
  200. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js.egg-info/dependency_links.txt +0 -0
  201. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js.egg-info/requires.txt +0 -0
  202. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/pgwidgets_js.egg-info/top_level.txt +0 -0
  203. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/setup.cfg +0 -0
  204. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/setup.py +0 -0
  205. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/tests/__init__.py +0 -0
  206. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/tests/test_consistency.py +0 -0
  207. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/tests/test_defs.py +0 -0
  208. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/tests/test_recent_additions.py +0 -0
  209. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/tests/test_static_assets.py +0 -0
  210. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/tests/test_treeview_diff.py +0 -0
  211. {pgwidgets_js-0.4.0 → pgwidgets_js-0.4.2}/tests/treeview_diff.mjs +0 -0
@@ -11,13 +11,13 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  strategy:
13
13
  matrix:
14
- python-version: ["3.12", "3.13"]
14
+ python-version: ["3.12", "3.13", "3.14"]
15
15
 
16
16
  steps:
17
- - uses: actions/checkout@v4
17
+ - uses: actions/checkout@v7
18
18
 
19
19
  - name: Set up Python ${{ matrix.python-version }}
20
- uses: actions/setup-python@v5
20
+ uses: actions/setup-python@v6
21
21
  with:
22
22
  python-version: ${{ matrix.python-version }}
23
23
 
@@ -1,19 +1,19 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pgwidgets-js
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: pgwidgets JavaScript widget library — static assets for use with Python servers
5
5
  Author: PGWidgets Developers
6
- License: BSD-3-Clause
6
+ License-Expression: BSD-3-Clause
7
7
  Project-URL: Homepage, https://github.com/naojsoft/pgwidgets-js
8
8
  Project-URL: Repository, https://github.com/naojsoft/pgwidgets-js
9
9
  Keywords: widgets,ui,gui,javascript,websocket
10
10
  Classifier: Development Status :: 3 - Alpha
11
11
  Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: BSD License
13
12
  Classifier: Programming Language :: JavaScript
14
13
  Classifier: Programming Language :: Python :: 3
15
14
  Classifier: Programming Language :: Python :: 3.12
16
15
  Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
17
  Classifier: Topic :: Software Development :: User Interfaces
18
18
  Requires-Python: >=3.12
19
19
  Description-Content-Type: text/markdown
@@ -1,6 +1,93 @@
1
1
  What's New
2
2
  ==========
3
3
 
4
+ Recent changes — since ``v0.4.0``
5
+ ---------------------------------
6
+
7
+ TreeView: a header drag resizes one column, qt-style
8
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9
+
10
+ Dragging a header divider now resizes the column to its left and
11
+ nothing else. The columns after it keep their widths and slide along,
12
+ and the table grows past the viewport into the horizontal scrollbar --
13
+ what a qt ``QHeaderView`` does in its default Interactive mode. A drag
14
+ first pins every column to the width it is rendering at, so a column
15
+ still on ``"1fr"`` stops re-dividing the leftover space and drifting
16
+ while an unrelated boundary is dragged.
17
+
18
+ Previously a drag behaved like a splitter: every pixel the column
19
+ gained came out of the next one, so widening a column ate its
20
+ neighbour down to the 5 px floor before anything to the right would
21
+ move. For the same reason the last column had no divider -- it has no
22
+ neighbour to take width from. It has one now.
23
+
24
+ TreeView: ``select_path()`` and friends default ``state`` to true
25
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26
+
27
+ ``select_path(path, state = true)``, ``select_paths()`` and
28
+ ``select_all()`` now default ``state``, matching ``select_cell()`` /
29
+ ``select_cells()`` and the Python API, where a caller writes
30
+ ``select_path(path)`` to select a row.
31
+
32
+ A bridge that forwards only the arguments it was given -- as the Python
33
+ proxy does, being generated from the ``defs.py`` parameter lists --
34
+ passed ``undefined`` otherwise, and the call quietly did nothing.
35
+ ``select_all()`` was worse than a no-op: it took the ``else`` branch
36
+ and cleared the selection instead of filling it.
37
+
38
+ TreeView / TableView: selecting from code no longer fires ``selected``
39
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40
+
41
+ ``clear_selection()``, ``set_selected()``, ``select_path()``,
42
+ ``select_paths()`` and ``select_all()`` now change the selection
43
+ silently: selecting from code is not the user selecting something. The
44
+ caller already knows what it did, and two views that clear each other's
45
+ selection would otherwise ping-pong. Only pointer and keyboard
46
+ interaction reports a selection.
47
+
48
+ This is a behaviour change -- ``clear_selection()`` previously
49
+ documented that it fires ``selected`` with an empty list -- and it
50
+ brings these widgets in line with what the desktop toolkits already
51
+ did. A caller that leaned on the callback to update itself should now
52
+ call its handler directly after selecting. ``TableView`` inherits all
53
+ of these from ``TreeView``; it also declares ``clear_selection`` in
54
+ ``defs.py`` now, which only ``TreeView`` had.
55
+
56
+ ``cell_action`` names the clicked row by path as well as by value
57
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
58
+
59
+ A button cell fired ``cell_action(row_values, col_key)``, which is what
60
+ a table wants but not what a tree does -- a tree names a row by its
61
+ path. The callback now sends both, as
62
+ ``cell_action(path, row_values, col_key)``, and the consumer keeps
63
+ whichever suits the widget it is presenting. Existing handlers take one
64
+ more leading argument.
65
+
66
+ TreeView / TableView: ``get_column_widths()``
67
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
68
+
69
+ Returns the width of every column, left to right. The widths are
70
+ measured from the rendered header cells, so an auto-sized (``1fr``)
71
+ column reports a real number rather than nothing; when the view is not
72
+ on screen yet it falls back to the widths that were set.
73
+
74
+ Text widgets: scroll alignment, and a styleable ``TextSource`` caret
75
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
76
+
77
+ ``TextArea`` gains ``scroll_to_lineno(lineno, align)`` and
78
+ ``scroll_to_end()``. A ``<textarea>`` has no per-line elements, so the
79
+ line's position is computed from the line height -- approximate when
80
+ wrapping is on.
81
+
82
+ ``TextSource.scroll_to_ref()`` takes the same ``align`` -- ``'nearest'``
83
+ (the default, as before), ``'center'`` or ``'top'`` -- mapped onto
84
+ ``scrollIntoView``'s ``block`` value, so a search that scrolls to its
85
+ match can put the match in the middle of the view instead of merely
86
+ bringing it into sight. ``set_cursor_style(style, color)`` styles the
87
+ caret through CSS ``caret-color`` / ``caret-shape``: it is the browser's
88
+ own caret, so it is drawn only while the editor has the focus, and the
89
+ ``'block'`` shape needs a browser that supports ``caret-shape``.
90
+
4
91
  Recent changes — since ``v0.3.6``
5
92
  ---------------------------------
6
93
 
@@ -385,14 +385,16 @@ supplies no value for it, so most interiors need no
385
385
  - Expand or collapse a single node by key path.
386
386
  * - ``get_selected()`` / ``set_selected(paths)``
387
387
  - Get or set selection. ``set_selected`` accepts a single
388
- path or an array of paths.
388
+ path or an array of paths. Setting is silent -- see
389
+ "Selecting from code" below.
389
390
  * - ``clear_selection()``
390
- - Drop all selection. Fires the ``selected`` callback with
391
- an empty list.
392
- * - ``select_path(path, state)`` / ``select_paths(paths, state)``
393
- - Select or deselect by key path(s).
394
- * - ``select_all(state)``
395
- - Select or deselect all nodes.
391
+ - Drop all selection. Silent, like the other selection
392
+ setters.
393
+ * - ``select_path(path, state=true)`` / ``select_paths(paths, state=true)``
394
+ - Select or deselect by key path(s). ``state`` defaults to
395
+ true, so ``select_path(path)`` selects.
396
+ * - ``select_all(state=true)``
397
+ - Select or deselect all nodes. ``state`` defaults to true.
396
398
  * - ``get_subtree(status='all')``
397
399
  - Return a dict-tree containing a subset. ``status`` is
398
400
  ``"all"``, ``"selected"``, ``"expanded"``, or ``"collapsed"``.
@@ -415,8 +417,13 @@ supplies no value for it, so most interiors need no
415
417
  - Column manipulation. ``before`` is a column key.
416
418
  * - ``set_column_width(col_key, width)``
417
419
  - Set column width.
420
+ * - ``get_column_widths()``
421
+ - The width of every column, left to right, in pixels.
422
+ Measured from the rendered header cells, so an auto-sized
423
+ (``"1fr"``) column reports a real number; falls back to the
424
+ widths that were set when the view is not on screen yet.
418
425
  * - ``set_optimal_column_widths()``
419
- - Auto-size all columns.
426
+ - Auto-size all columns to their header and cell content.
420
427
  * - ``set_row_spacing(px)`` / ``set_column_spacing(px)``
421
428
  - Set the vertical (row) / horizontal (column) cell padding in
422
429
  pixels. ``set_row_spacing(0)`` also relaxes the row min-height
@@ -467,15 +474,20 @@ across the row.
467
474
  col_key)``; fires on row double-click or Enter. ``col_key``
468
475
  is the column the click landed on (``null`` for
469
476
  keyboard-triggered activation).
470
- - ``selected`` -- selection changed; handler receives an array of
471
- ``{path, values}`` objects.
477
+ - ``selected`` -- the user changed the selection; handler
478
+ receives an array of ``{path, values}`` objects. Selecting
479
+ from code does not fire it -- see "Selecting from code" below.
472
480
  - ``expanded`` / ``collapsed`` -- handler ``(widget, values, path)``.
473
481
  - ``cell_edited`` -- ``(widget, path, col_key, oldValue, newValue)``.
474
- - ``cell_selected`` -- cell-mode selection changed; handler
475
- receives ``(widget, cells)`` where each cell is
476
- ``{path, col_key, value}``.
477
- - ``cell_action`` -- ``(widget, row_values, col_key)``; fires
478
- when the user clicks a ``widget: "button"`` cell.
482
+ - ``cell_selected`` -- the user changed the cell-mode selection;
483
+ handler receives ``(widget, cells)`` where each cell is
484
+ ``{path, col_key, value}``. Like ``selected``, it does not
485
+ fire for selection made from code.
486
+ - ``cell_action`` -- ``(widget, path, row_values, col_key)``;
487
+ fires when the user clicks a ``widget: "button"`` cell. Both
488
+ names for the row are sent: a table normally wants
489
+ ``row_values``, a tree its ``path``. (Before v0.4.1 the
490
+ ``path`` argument was not there.)
479
491
  - ``copy`` / ``cut`` / ``paste`` -- ``(widget, tsv)``; fire from
480
492
  Ctrl/Cmd+C/X/V and from the programmatic helpers.
481
493
  - ``sorted`` -- ``(widget, col_key, ascending)``.
@@ -499,6 +511,30 @@ gate the per-row widget. An empty row value of ``null`` /
499
511
  ``false`` on a button column suppresses that row's button if
500
512
  ``visible_key`` is also unset.
501
513
 
514
+ **Resizing columns.** Every header cell carries a divider on its right
515
+ edge, the last column included. Dragging one resizes *that* column and
516
+ leaves the rest alone: the columns after it keep their widths and slide
517
+ along, and the table grows past the viewport into the horizontal
518
+ scrollbar. This is what a qt ``QHeaderView`` does in its default
519
+ Interactive mode. A drag pins every column to the width it is
520
+ rendering at, so a column still on ``"1fr"`` stops re-dividing the
521
+ leftover space and drifting. (Before v0.4.2 a drag behaved like a
522
+ splitter, taking the width it gained out of the next column, and the
523
+ last column had no divider at all because it has no neighbour to take
524
+ from.)
525
+
526
+ **Selecting from code.** ``set_selected``, ``select_path``,
527
+ ``select_paths``, ``select_all``, ``clear_selection`` and their
528
+ cell-mode counterparts ``select_cell`` / ``select_cells`` /
529
+ ``clear_cell_selection`` all change the selection *silently*:
530
+ ``selected`` and ``cell_selected`` report pointer and keyboard
531
+ interaction only. The caller already knows what it selected, and
532
+ two views that clear each other's selection would otherwise
533
+ ping-pong. Call your own handler after selecting if it needs to
534
+ run. (Before v0.4.1, ``clear_selection`` fired ``selected`` with
535
+ an empty list, and the desktop toolkits ginga wraps disagreed
536
+ among themselves on the rest.)
537
+
502
538
  **Colour overrides.** Each of the four ``set_*_color`` methods
503
539
  takes ``fg`` (text), ``bg`` (background), and ``bold``. All
504
540
  three are optional; passing all-null clears that layer's
@@ -572,11 +608,14 @@ dicts (preferred) or a list of positional arrays:
572
608
  table.append_row({NAME: "Carol", DEPT: "Sales", SALARY: 71000});
573
609
  table.sort_by_column("SALARY", false); // descending
574
610
 
575
- **Callbacks:** identical to TreeView, including the new
611
+ **Callbacks:** identical to TreeView, including the
576
612
  ``activated`` 4-arg signature with ``col_key``, the
577
613
  ``cell_selected`` / ``cell_action`` / ``copy`` / ``cut`` /
578
614
  ``paste`` callbacks, and the per-cell ``cell_edited``
579
- signature.
615
+ signature. ``cell_action`` carries the clicked row's ``path``
616
+ ahead of its values here too, even though a flat table normally
617
+ reads the values; the path is a single-element array of the
618
+ row's key. Selecting from code is silent, as on a TreeView.
580
619
 
581
620
  TableView ``set_columns`` accepts the same column descriptor
582
621
  fields as TreeView, including ``widget`` / ``choices`` /
@@ -164,6 +164,15 @@ Multi-line text editor.
164
164
  - Set word-wrap mode.
165
165
  * - ``set_limit(numlines)``
166
166
  - Limit visible lines (scrollback).
167
+ * - ``scroll_to_lineno(lineno, align="nearest")``
168
+ - Scroll so line *lineno* (0-based, clamped to the text) is in
169
+ view. ``align`` is ``"nearest"`` (scroll the least amount
170
+ that brings the line into view), ``"center"`` or ``"top"``.
171
+ A ``<textarea>`` has no per-line elements, so the line's
172
+ position is computed from the line height -- approximate when
173
+ ``wrap`` is on.
174
+ * - ``scroll_to_end()``
175
+ - Scroll to the last line.
167
176
 
168
177
  **Callbacks:** None.
169
178
 
@@ -325,10 +334,23 @@ position-returning method on the public API uses refs.
325
334
  - Find all non-overlapping matches; returns an array of ref pairs.
326
335
  * - ``replace(query, replacement, {all, start_ref, case_insensitive})``
327
336
  - Find and replace; returns the number of replacements.
328
- * - ``scroll_to_ref(ref)``
337
+ * - ``scroll_to_ref(ref, align="nearest")``
329
338
  - Scroll the view so the line containing *ref* is visible.
339
+ ``align`` is ``"nearest"`` (the default), ``"center"`` or
340
+ ``"top"``, mapped onto ``scrollIntoView``'s ``block`` value,
341
+ so a search can put its match in the middle of the view
342
+ rather than merely bringing it into sight.
343
+ To scroll to a line number, mint a ref for it first with
344
+ ``get_ref_line_start(lineno)``.
330
345
  * - ``scroll_to_cursor()``
331
346
  - Scroll to cursor position.
347
+ * - ``set_cursor_style(style="line", color=null)``
348
+ - Style the caret: ``style`` is ``"line"`` or ``"block"``,
349
+ ``color`` any CSS colour (``null`` restores the browser's).
350
+ This styles the browser's own caret through ``caret-color``
351
+ / ``caret-shape``, so it is drawn only while the editor has
352
+ the focus, and ``"block"`` needs a browser that supports
353
+ ``caret-shape``.
332
354
 
333
355
  **Callbacks:**
334
356
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgwidgets",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "A native JavaScript widget library with Qt/GTK-style layout and controls",
5
5
  "type": "module",
6
6
  "main": "Widgets.js",
@@ -537,6 +537,8 @@ WIDGETS = {
537
537
  "set_limit": ["numlines"],
538
538
  "set_scroll_position": ["h_pct", "v_pct"],
539
539
  "get_scroll_position": [],
540
+ "scroll_to_lineno": ["lineno", "align"],
541
+ "scroll_to_end": [],
540
542
  },
541
543
  "callbacks": ["scrolled"],
542
544
  },
@@ -566,6 +568,7 @@ WIDGETS = {
566
568
  "set_icon": ["ref", "icon_url"],
567
569
  "get_cursor": [],
568
570
  "set_cursor": ["ref"],
571
+ "set_cursor_style": ["style", "color"],
569
572
  "get_selection_range": [],
570
573
  "has_selection": [],
571
574
  "get_selection_bounds": [],
@@ -608,7 +611,7 @@ WIDGETS = {
608
611
  "find_all": ["query", "opts"],
609
612
  "replace": ["query", "replacement", "opts"],
610
613
  # Scrolling
611
- "scroll_to_ref": ["ref"],
614
+ "scroll_to_ref": ["ref", "align"],
612
615
  "scroll_to_cursor": [],
613
616
  "set_scroll_position": ["h_pct", "v_pct"],
614
617
  "get_scroll_position": [],
@@ -795,6 +798,7 @@ WIDGETS = {
795
798
  "select_paths": ["paths", "state"],
796
799
  "select_all": ["state"],
797
800
  "set_column_width": ["col_key", "width"],
801
+ "get_column_widths": [],
798
802
  "set_optimal_column_widths": [],
799
803
  "sort_by_column": ["col_key", "ascending"],
800
804
  "scroll_to_path": ["path"],
@@ -854,10 +858,12 @@ WIDGETS = {
854
858
  "clear": [],
855
859
  "get_selected": [],
856
860
  "set_selected": ["items"],
861
+ "clear_selection": [],
857
862
  "select_path": ["path", "state"],
858
863
  "select_paths": ["paths", "state"],
859
864
  "select_all": ["state"],
860
865
  "set_column_width": ["col_index", "width"],
866
+ "get_column_widths": [],
861
867
  "set_optimal_column_widths": [],
862
868
  "set_row_spacing": ["px"],
863
869
  "set_column_spacing": ["px"],
@@ -182,6 +182,57 @@ class TextArea extends Widget {
182
182
  this._scrollSilent = false;
183
183
  }
184
184
 
185
+ /**
186
+ * Scrolls so that line *lineno* (0-based) is visible.
187
+ *
188
+ * NOTE: a <textarea> has no per-line elements to measure, so the
189
+ * line's position is derived from the computed line height. With
190
+ * wrapping on, a long logical line occupies more than one visual
191
+ * line and the result is approximate.
192
+ *
193
+ * @param {number} lineno - Line to scroll to (0-based).
194
+ * @param {string} [align='nearest'] - Where the line should end up:
195
+ * 'nearest' scrolls the least amount that brings it into view,
196
+ * 'center' puts it in the middle and 'top' at the top.
197
+ */
198
+ scroll_to_lineno(lineno, align = 'nearest') {
199
+ let ta = this._textarea;
200
+ let style = window.getComputedStyle(ta);
201
+ let lineHeight = parseFloat(style.lineHeight);
202
+ if (! isFinite(lineHeight)) {
203
+ // 'normal' -- approximate it from the font size
204
+ lineHeight = parseFloat(style.fontSize) * 1.2;
205
+ }
206
+ let padTop = parseFloat(style.paddingTop) || 0;
207
+ let top = padTop + Math.max(0, lineno) * lineHeight;
208
+ let view = ta.clientHeight;
209
+ let pos = ta.scrollTop;
210
+ let target;
211
+ if (align === 'center') {
212
+ target = top - (view - lineHeight) / 2;
213
+ } else if (align === 'top') {
214
+ target = top;
215
+ } else {
216
+ if (top < pos) target = top;
217
+ else if (top + lineHeight > pos + view) target = top + lineHeight - view;
218
+ else target = pos;
219
+ }
220
+ let maxY = ta.scrollHeight - view;
221
+ ta.scrollTop = Math.max(0, Math.min(target, maxY));
222
+ this._scrollSilent = true;
223
+ this._syncFromScroll();
224
+ this._scrollSilent = false;
225
+ }
226
+
227
+ /** Scrolls to the end of the buffer. */
228
+ scroll_to_end() {
229
+ let ta = this._textarea;
230
+ ta.scrollTop = Math.max(0, ta.scrollHeight - ta.clientHeight);
231
+ this._scrollSilent = true;
232
+ this._syncFromScroll();
233
+ this._scrollSilent = false;
234
+ }
235
+
185
236
  /**
186
237
  * Returns the current scroll position as [h_pct, v_pct] (0–1).
187
238
  * @returns {number[]}
@@ -1996,9 +1996,10 @@ class TextSource extends Widget {
1996
1996
  /**
1997
1997
  * Scroll the view so that the line containing *ref* is visible.
1998
1998
  * @param {TextBufferRef} ref
1999
+ * @param {string} [align='nearest'] - 'nearest', 'center' or 'top'.
1999
2000
  */
2000
- scroll_to_ref(ref) {
2001
- this._scrollToOffset(this._offsetOf(ref));
2001
+ scroll_to_ref(ref, align = 'nearest') {
2002
+ this._scrollToOffset(this._offsetOf(ref), align);
2002
2003
  }
2003
2004
 
2004
2005
  /**
@@ -2007,16 +2008,39 @@ class TextSource extends Widget {
2007
2008
  * ref over the wire (the Python side owns the ref and passes its offset).
2008
2009
  * @private
2009
2010
  * @param {number} offset
2011
+ * @param {string} [align='nearest'] - 'nearest' scrolls the least
2012
+ * amount that brings the line into view, 'center' puts it in the
2013
+ * middle of the view and 'top' at the top.
2010
2014
  */
2011
- _scrollToOffset(offset) {
2015
+ _scrollToOffset(offset, align = 'nearest') {
2012
2016
  let line = this._lineOfOffset(this._clampOffset(offset));
2013
2017
  let lineDiv = this._edit.children[line];
2014
2018
  if (lineDiv && lineDiv.scrollIntoView) {
2015
- lineDiv.scrollIntoView({ block: 'nearest' });
2019
+ let block = { center: 'center', top: 'start' }[align] || 'nearest';
2020
+ lineDiv.scrollIntoView({ block: block });
2016
2021
  this._syncFromScroll();
2017
2022
  }
2018
2023
  }
2019
2024
 
2025
+ /**
2026
+ * Set the appearance of the text caret.
2027
+ *
2028
+ * NOTE: this styles the browser's own caret, which means it is only
2029
+ * drawn while the editor has the keyboard focus, and that the block
2030
+ * shape needs a browser supporting the CSS 'caret-shape' property
2031
+ * (elsewhere the caret keeps its color but stays a thin bar).
2032
+ *
2033
+ * @param {string} [style='line'] - 'line' or 'block'.
2034
+ * @param {?string} [color=null] - Any CSS color, or null for the
2035
+ * browser default.
2036
+ */
2037
+ set_cursor_style(style = 'line', color = null) {
2038
+ this._cursorStyle = style;
2039
+ this._cursorColor = color;
2040
+ this._edit.style.caretColor = (color === null) ? '' : color;
2041
+ this._edit.style.caretShape = (style === 'block') ? 'block' : '';
2042
+ }
2043
+
2020
2044
  /** Scroll so the cursor is visible. */
2021
2045
  scroll_to_cursor() {
2022
2046
  let line = this._lineOfOffset(this._cursor);
@@ -676,12 +676,16 @@ class TreeView extends Widget {
676
676
  this._onHeaderClick(this._columns[i].key);
677
677
  });
678
678
 
679
- if (i < this._columns.length - 1) {
680
- let handle = document.createElement('div');
681
- handle.className = 'treeview-resize-handle';
682
- cell.appendChild(handle);
683
- this._setupColumnResize(handle, i);
684
- }
679
+ // Every column gets a divider, the last one included -- qt
680
+ // lets you drag the final section's right edge too. (The
681
+ // last one used to be skipped because resizing worked like a
682
+ // splitter, and the last column has no neighbour to take the
683
+ // width from; now that a drag only resizes its own column,
684
+ // there is nothing special about it.)
685
+ let handle = document.createElement('div');
686
+ handle.className = 'treeview-resize-handle';
687
+ cell.appendChild(handle);
688
+ this._setupColumnResize(handle, i);
685
689
 
686
690
  this._header.appendChild(cell);
687
691
  }
@@ -714,8 +718,22 @@ class TreeView extends Widget {
714
718
  }
715
719
  }
716
720
 
721
+ /**
722
+ * Wire up one header divider.
723
+ *
724
+ * Dragging resizes only the column to the divider's left: the
725
+ * columns after it keep their widths and slide along, the table
726
+ * grows past the viewport and the horizontal scrollbar takes up the
727
+ * difference. That is what a qt ``QHeaderView`` does in its default
728
+ * Interactive mode, and what makes a too-narrow column widenable
729
+ * without robbing its neighbour.
730
+ *
731
+ * (It used to behave like a splitter -- every pixel the dragged
732
+ * column gained came out of the next one, so widening a column ate
733
+ * the one beside it down to the 5 px floor before anything moved.)
734
+ */
717
735
  _setupColumnResize(handle, colIndex) {
718
- let startX, startWidthA, startWidthB;
736
+ let startX, startWidth;
719
737
  const onMouseMove = (e) => {
720
738
  let dx = e.clientX - startX;
721
739
  // 5 px floor matches the width of ``.treeview-resize-handle``
@@ -726,11 +744,11 @@ class TreeView extends Widget {
726
744
  // *inflate* any column whose declared ``colwidth`` was
727
745
  // below 30 the moment a drag started, making columns
728
746
  // like a 10 px Mute / checkbox column un-resizable.
729
- let newA = Math.max(5, startWidthA + dx);
730
- let newB = Math.max(5, startWidthB - dx);
731
- this._colWidths[colIndex] = newA + 'px';
732
- this._colWidths[colIndex + 1] = newB + 'px';
747
+ this._colWidths[colIndex] = Math.max(5, startWidth + dx) + 'px';
733
748
  this._applyGridTemplate();
749
+ // the table's total width changes now (it did not when this
750
+ // stole from the neighbour), so the scrollbar has to follow
751
+ this._syncScrollbars();
734
752
  };
735
753
  const onMouseUp = () => {
736
754
  document.removeEventListener('mousemove', onMouseMove);
@@ -741,8 +759,18 @@ class TreeView extends Widget {
741
759
  e.stopPropagation();
742
760
  startX = e.clientX;
743
761
  let cells = this._header.querySelectorAll('.treeview-header-cell');
744
- startWidthA = cells[colIndex].getBoundingClientRect().width;
745
- startWidthB = cells[colIndex + 1].getBoundingClientRect().width;
762
+ // Pin every column to the width it is rendering at before
763
+ // the drag starts. Any track still on an ``fr`` unit would
764
+ // otherwise re-divide the leftover space on each move, so
765
+ // columns the user never touched would drift as a side
766
+ // effect of dragging one boundary.
767
+ for (let i = 0; i < this._colWidths.length; i++) {
768
+ if (cells[i]) {
769
+ this._colWidths[i] =
770
+ cells[i].getBoundingClientRect().width + 'px';
771
+ }
772
+ }
773
+ startWidth = parseFloat(this._colWidths[colIndex]);
746
774
  document.addEventListener('mousemove', onMouseMove);
747
775
  document.addEventListener('mouseup', onMouseUp);
748
776
  });
@@ -1395,13 +1423,25 @@ class TreeView extends Widget {
1395
1423
  }
1396
1424
 
1397
1425
  /**
1398
- * Clear all selection. Fires the 'selected' callback with an
1399
- * empty list.
1426
+ * Clear all selection.
1427
+ *
1428
+ * NOTE: this and the other selection setters below do NOT fire the
1429
+ * 'selected' callback -- selecting from code is not the user
1430
+ * selecting something. The caller already knows what it just did,
1431
+ * and a pair of views that clear each other's selection would
1432
+ * otherwise ping-pong. Only pointer and keyboard interaction
1433
+ * reports a selection.
1434
+ *
1435
+ * NOTE: the ``state`` argument of the select_* methods defaults to
1436
+ * true, matching select_cell()/select_cells() and the Python side
1437
+ * (whose callers write ``select_path(path)`` to select a row). A
1438
+ * bridge that forwards only the arguments it was given would
1439
+ * otherwise pass ``undefined`` here, and the call would silently do
1440
+ * nothing -- or, for select_all(), clear the selection instead.
1400
1441
  */
1401
1442
  clear_selection() {
1402
1443
  this._selection = [];
1403
1444
  this._updateSelectionDisplay();
1404
- this.make_callback('selected', this.get_selected());
1405
1445
  }
1406
1446
 
1407
1447
  set_selected(paths) {
@@ -1423,10 +1463,9 @@ class TreeView extends Widget {
1423
1463
  }
1424
1464
  }
1425
1465
  this._updateSelectionDisplay();
1426
- this.make_callback('selected', this.get_selected());
1427
1466
  }
1428
1467
 
1429
- select_path(path, state) {
1468
+ select_path(path, state = true) {
1430
1469
  let node = this._nodeAtPath(path);
1431
1470
  if (!node) return;
1432
1471
  let idx = this._selection.indexOf(node);
@@ -1436,10 +1475,9 @@ class TreeView extends Widget {
1436
1475
  this._selection.splice(idx, 1);
1437
1476
  }
1438
1477
  this._updateSelectionDisplay();
1439
- this.make_callback('selected', this.get_selected());
1440
1478
  }
1441
1479
 
1442
- select_paths(paths, state) {
1480
+ select_paths(paths, state = true) {
1443
1481
  for (let path of paths) {
1444
1482
  let node = this._nodeAtPath(path);
1445
1483
  if (!node) continue;
@@ -1451,10 +1489,9 @@ class TreeView extends Widget {
1451
1489
  }
1452
1490
  }
1453
1491
  this._updateSelectionDisplay();
1454
- this.make_callback('selected', this.get_selected());
1455
1492
  }
1456
1493
 
1457
- select_all(state) {
1494
+ select_all(state = true) {
1458
1495
  if (state) {
1459
1496
  this._selection = [];
1460
1497
  this._walkNodes(this._root, (n) => this._selection.push(n));
@@ -1462,7 +1499,6 @@ class TreeView extends Widget {
1462
1499
  this._selection = [];
1463
1500
  }
1464
1501
  this._updateSelectionDisplay();
1465
- this.make_callback('selected', this.get_selected());
1466
1502
  }
1467
1503
 
1468
1504
  /**
@@ -1477,6 +1513,23 @@ class TreeView extends Widget {
1477
1513
  this._applyGridTemplate();
1478
1514
  }
1479
1515
 
1516
+ /**
1517
+ * The current width of every column, in pixels, left to right.
1518
+ *
1519
+ * Measured from the rendered header cells so that auto-sized
1520
+ * columns ('1fr') report a real number too; falls back to the
1521
+ * widths that were set when the view is not on screen yet, and to
1522
+ * 0 for a column whose width was never set.
1523
+ * @returns {number[]}
1524
+ */
1525
+ get_column_widths() {
1526
+ return this._columns.map((col, i) => {
1527
+ let cell = this._headerCells ? this._headerCells[i] : null;
1528
+ if (cell && cell.offsetWidth) return cell.offsetWidth;
1529
+ return parseFloat(this._colWidths[i]) || 0;
1530
+ });
1531
+ }
1532
+
1480
1533
  set_optimal_column_widths() {
1481
1534
  if (!this.element.isConnected) {
1482
1535
  requestAnimationFrame(() => this.set_optimal_column_widths());
@@ -2870,8 +2923,10 @@ class TreeView extends Widget {
2870
2923
  * Change fires ``cell_edited`` with the new option string.
2871
2924
  * - ``progress``: <progress max=col.max value=val>. Read-only.
2872
2925
  * - ``button``: <button>. Click fires
2873
- * ``cell_action(row_values, col_key)``. The button label is
2874
- * the per-row value when non-null, else ``col.text`` if set.
2926
+ * ``cell_action(path, row_values, col_key)`` -- both ways of
2927
+ * naming the row, since a tree wants the path and a table wants
2928
+ * the values. The button label is the per-row value when
2929
+ * non-null, else ``col.text`` if set.
2875
2930
  */
2876
2931
  _buildCellWidget(node, colDef, val) {
2877
2932
  let colKey = colDef.key;
@@ -2936,8 +2991,8 @@ class TreeView extends Widget {
2936
2991
  : (colDef.text || ''));
2937
2992
  el.addEventListener('click', (e) => {
2938
2993
  e.stopPropagation();
2939
- this.make_callback('cell_action', node.values || {},
2940
- colKey);
2994
+ this.make_callback('cell_action', path,
2995
+ node.values || {}, colKey);
2941
2996
  });
2942
2997
  return el;
2943
2998
  }