bootstack 0.1.0a13__tar.gz → 0.1.0a15__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 (478) hide show
  1. {bootstack-0.1.0a13/src/bootstack.egg-info → bootstack-0.1.0a15}/PKG-INFO +1 -1
  2. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/pyproject.toml +2 -2
  3. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/__init__.py +5 -3
  4. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_runtime/app.py +2 -0
  5. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/pyinstaller.py +2 -1
  6. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/events/__init__.py +6 -0
  7. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/events/_payloads.py +32 -0
  8. bootstack-0.1.0a15/src/bootstack/signals/README.md +98 -0
  9. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/signals/signal.py +110 -102
  10. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/carousel.py +13 -8
  11. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/scrollview.py +30 -0
  12. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tableview/tableview.py +110 -58
  13. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/codeeditor.py +145 -2
  14. bootstack-0.1.0a15/src/bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +177 -0
  15. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/textarea.py +11 -2
  16. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/toolbar.py +17 -14
  17. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/button.py +10 -1
  18. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/codeeditor.py +163 -21
  19. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/datatable.py +14 -0
  20. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/menubutton.py +23 -0
  21. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/scrollview.py +52 -2
  22. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/spinnerfield.py +1 -1
  23. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/splitview.py +61 -3
  24. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/textarea.py +20 -0
  25. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/timefield.py +2 -2
  26. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/toolbar.py +41 -18
  27. {bootstack-0.1.0a13 → bootstack-0.1.0a15/src/bootstack.egg-info}/PKG-INFO +1 -1
  28. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/tests/test_public_surface.py +16 -0
  29. bootstack-0.1.0a13/src/bootstack/signals/README.md +0 -112
  30. bootstack-0.1.0a13/src/bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +0 -87
  31. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/LICENSE +0 -0
  32. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/MANIFEST.in +0 -0
  33. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/NOTICE +0 -0
  34. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/README.md +0 -0
  35. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/setup.cfg +0 -0
  36. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/__main__.py +0 -0
  37. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/__init__.py +0 -0
  38. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/__init__.py +0 -0
  39. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/after.py +0 -0
  40. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/bind.py +0 -0
  41. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/bindtags.py +0 -0
  42. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/busy.py +0 -0
  43. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/clipboard.py +0 -0
  44. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/focus.py +0 -0
  45. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/grab.py +0 -0
  46. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/grid.py +0 -0
  47. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/localization.py +0 -0
  48. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/pack.py +0 -0
  49. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/place.py +0 -0
  50. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/selection.py +0 -0
  51. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/signals.py +0 -0
  52. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/capabilities/winfo.py +0 -0
  53. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/colorutils.py +0 -0
  54. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/exceptions.py +0 -0
  55. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/images.py +0 -0
  56. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/mixins/__init__.py +0 -0
  57. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/mixins/ttk_state.py +0 -0
  58. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/mixins/widget.py +0 -0
  59. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/paths.py +0 -0
  60. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/publisher.py +0 -0
  61. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_core/variables.py +0 -0
  62. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_runtime/__init__.py +0 -0
  63. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_runtime/base_window.py +0 -0
  64. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_runtime/events.py +0 -0
  65. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_runtime/shortcuts.py +0 -0
  66. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_runtime/tk_patch.py +0 -0
  67. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_runtime/toplevel.py +0 -0
  68. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_runtime/utility.py +0 -0
  69. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_runtime/visual_focus.py +0 -0
  70. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/_runtime/window_utilities.py +0 -0
  71. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/__init__.py +0 -0
  72. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/bootstack.ico +0 -0
  73. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/bootstack.png +0 -0
  74. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/__init__.py +0 -0
  75. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/badge-pill.png +0 -0
  76. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/badge-square.png +0 -0
  77. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/button-compact.png +0 -0
  78. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/button-default.png +0 -0
  79. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
  80. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
  81. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
  82. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
  83. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
  84. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
  85. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
  86. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
  87. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
  88. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
  89. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
  90. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
  91. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/card.png +0 -0
  92. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/checkbox-checked.png +0 -0
  93. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/checkbox-indeterminate.png +0 -0
  94. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/checkbox-unchecked.png +0 -0
  95. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/field.png +0 -0
  96. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/input-addon-compact.png +0 -0
  97. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/input-addon-default.png +0 -0
  98. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/input-compact.png +0 -0
  99. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/input-default.png +0 -0
  100. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/list-item-separated.png +0 -0
  101. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/list-item.png +0 -0
  102. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/listrow-compact.png +0 -0
  103. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/listrow-default.png +0 -0
  104. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/manifest.toml +0 -0
  105. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/menu-item.png +0 -0
  106. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/navitem-compact.png +0 -0
  107. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/navitem-default.png +0 -0
  108. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/progressbar-h-compact.png +0 -0
  109. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/progressbar-h-default.png +0 -0
  110. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/progressbar-v-compact.png +0 -0
  111. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/progressbar-v-default.png +0 -0
  112. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/radiobutton.png +0 -0
  113. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/scrollbar-horizontal.png +0 -0
  114. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/scrollbar-vertical.png +0 -0
  115. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/slider-handle.png +0 -0
  116. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/slider-track-h.png +0 -0
  117. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/slider-track-v.png +0 -0
  118. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/switch-off.png +0 -0
  119. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/switch-on.png +0 -0
  120. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/tab-h.png +0 -0
  121. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/elements/tab-v.png +0 -0
  122. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/icons/bootstrap.ttf +0 -0
  123. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/icons/glyphmap.json +0 -0
  124. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/icons/icon_metrics.json +0 -0
  125. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
  126. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +0 -0
  127. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
  128. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +0 -0
  129. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
  130. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +0 -0
  131. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
  132. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +0 -0
  133. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
  134. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +0 -0
  135. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
  136. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +0 -0
  137. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
  138. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +0 -0
  139. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
  140. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +0 -0
  141. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
  142. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +0 -0
  143. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
  144. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +0 -0
  145. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
  146. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +0 -0
  147. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
  148. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +0 -0
  149. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
  150. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +0 -0
  151. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
  152. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +0 -0
  153. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
  154. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +0 -0
  155. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
  156. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +0 -0
  157. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
  158. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +0 -0
  159. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
  160. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +0 -0
  161. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
  162. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +0 -0
  163. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
  164. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +0 -0
  165. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
  166. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +0 -0
  167. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
  168. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +0 -0
  169. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
  170. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +0 -0
  171. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/__init__.py +0 -0
  172. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/__main__.py +0 -0
  173. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/add.py +0 -0
  174. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/appicon.py +0 -0
  175. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/build.py +0 -0
  176. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/config.py +0 -0
  177. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/demo.py +0 -0
  178. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/doctor.py +0 -0
  179. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/icons.py +0 -0
  180. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/promote.py +0 -0
  181. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/run.py +0 -0
  182. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/start.py +0 -0
  183. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/cli/templates/__init__.py +0 -0
  184. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/clipboard.py +0 -0
  185. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/constants.py +0 -0
  186. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/data/README.md +0 -0
  187. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/data/__init__.py +0 -0
  188. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/data/_observable.py +0 -0
  189. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/data/base.py +0 -0
  190. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/data/file_source.py +0 -0
  191. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/data/memory_source.py +0 -0
  192. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/data/query.py +0 -0
  193. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/data/readers.py +0 -0
  194. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/data/sqlite_source.py +0 -0
  195. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/data/types.py +0 -0
  196. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/data/writers.py +0 -0
  197. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/dialogs/__init__.py +0 -0
  198. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/dialogs/_impl/__init__.py +0 -0
  199. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/dialogs/_impl/colorchooser.py +0 -0
  200. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/dialogs/_impl/datedialog.py +0 -0
  201. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/dialogs/_impl/dialog.py +0 -0
  202. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/dialogs/_impl/filterdialog.py +0 -0
  203. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/dialogs/_impl/fontdialog.py +0 -0
  204. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/dialogs/_impl/formdialog.py +0 -0
  205. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/dialogs/_impl/message.py +0 -0
  206. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/dialogs/_impl/query.py +0 -0
  207. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/errors.py +0 -0
  208. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/events/_event.py +0 -0
  209. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/events/_subscription.py +0 -0
  210. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/i18n/README.md +0 -0
  211. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/i18n/__init__.py +0 -0
  212. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/i18n/catalog.py +0 -0
  213. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/i18n/intl_format.py +0 -0
  214. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/i18n/msgcat.py +0 -0
  215. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/i18n/specs.py +0 -0
  216. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/images.py +0 -0
  217. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/py.typed +0 -0
  218. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/scheduling/__init__.py +0 -0
  219. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/scheduling/_schedule.py +0 -0
  220. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/shortcuts.py +0 -0
  221. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/signals/__init__.py +0 -0
  222. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/signals/integration.py +0 -0
  223. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/signals/types.py +0 -0
  224. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/store.py +0 -0
  225. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/streams/__init__.py +0 -0
  226. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/streams/_stream.py +0 -0
  227. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/__init__.py +0 -0
  228. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/__init__.py +0 -0
  229. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/badge.py +0 -0
  230. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/button.py +0 -0
  231. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/buttongroup.py +0 -0
  232. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/calendar.py +0 -0
  233. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/checkbutton.py +0 -0
  234. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/combobox.py +0 -0
  235. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/contextmenu.py +0 -0
  236. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/entry.py +0 -0
  237. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/expander.py +0 -0
  238. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/field.py +0 -0
  239. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/frame.py +0 -0
  240. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/label.py +0 -0
  241. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/labelframe.py +0 -0
  242. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/listview.py +0 -0
  243. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/menubar.py +0 -0
  244. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/menubutton.py +0 -0
  245. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/panedwindow.py +0 -0
  246. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/progressbar.py +0 -0
  247. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/radiobutton.py +0 -0
  248. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/scale.py +0 -0
  249. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/scrollbar.py +0 -0
  250. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/separator.py +0 -0
  251. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/sidenav.py +0 -0
  252. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/sizegrip.py +0 -0
  253. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/spinbox.py +0 -0
  254. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/switch.py +0 -0
  255. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/tabitem.py +0 -0
  256. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/togglegroup.py +0 -0
  257. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/toolbutton.py +0 -0
  258. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/tooltip.py +0 -0
  259. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/treeview.py +0 -0
  260. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders/utils.py +0 -0
  261. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders_tk/__init__.py +0 -0
  262. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/builders_tk/defaults.py +0 -0
  263. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/element.py +0 -0
  264. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/fonts.py +0 -0
  265. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/style.py +0 -0
  266. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/style_builder_base.py +0 -0
  267. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/style_builder_mixed.py +0 -0
  268. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/style_builder_tk.py +0 -0
  269. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/style_builder_ttk.py +0 -0
  270. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/style_resolver.py +0 -0
  271. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/theme.py +0 -0
  272. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/theme_provider.py +0 -0
  273. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/themes/__init__.py +0 -0
  274. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/tk_patch.py +0 -0
  275. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/token_maps.py +0 -0
  276. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/types.py +0 -0
  277. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/typography.py +0 -0
  278. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/style/utility.py +0 -0
  279. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/types.py +0 -0
  280. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/validation/__init__.py +0 -0
  281. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/validation/types.py +0 -0
  282. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/validation/validation_result.py +0 -0
  283. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/validation/validation_rules.py +0 -0
  284. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/__init__.py +0 -0
  285. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/__init__.py +0 -0
  286. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/app_config.py +0 -0
  287. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/base.py +0 -0
  288. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/container.py +0 -0
  289. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/context.py +0 -0
  290. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/events.py +0 -0
  291. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/field_mixin.py +0 -0
  292. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/icon_image_props.py +0 -0
  293. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/image_binding.py +0 -0
  294. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/navmodel.py +0 -0
  295. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/options.py +0 -0
  296. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/selection_group.py +0 -0
  297. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/window_controls.py +0 -0
  298. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_core/window_menu.py +0 -0
  299. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/__init__.py +0 -0
  300. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/_internal/__init__.py +0 -0
  301. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/_internal/wrapper_base.py +0 -0
  302. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/_parts/__init__.py +0 -0
  303. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/_parts/numberentry_part.py +0 -0
  304. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/_parts/spinnerentry_part.py +0 -0
  305. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/_parts/textentry_part.py +0 -0
  306. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/__init__.py +0 -0
  307. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/_dateutils.py +0 -0
  308. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/_image_fit.py +0 -0
  309. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/accordion.py +0 -0
  310. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/avatar.py +0 -0
  311. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/buttongroup.py +0 -0
  312. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/calendar.py +0 -0
  313. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/chart.py +0 -0
  314. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/compositeframe.py +0 -0
  315. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/contextmenu.py +0 -0
  316. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/dateentry.py +0 -0
  317. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/dropdownbutton.py +0 -0
  318. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/expander.py +0 -0
  319. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/field.py +0 -0
  320. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/form.py +0 -0
  321. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/gallery.py +0 -0
  322. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/list/__init__.py +0 -0
  323. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/list/listitem.py +0 -0
  324. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/list/listview.py +0 -0
  325. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/menu/__init__.py +0 -0
  326. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/menu/model.py +0 -0
  327. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/menu/render_native.py +0 -0
  328. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/menu/render_themed.py +0 -0
  329. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/meter.py +0 -0
  330. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/numericentry.py +0 -0
  331. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/pagestack.py +0 -0
  332. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/passwordentry.py +0 -0
  333. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/pathentry.py +0 -0
  334. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/picture.py +0 -0
  335. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/radiogroup.py +0 -0
  336. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/scrolledtext.py +0 -0
  337. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/scrolledtext.pyi +0 -0
  338. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/selectbox.py +0 -0
  339. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/shell/__init__.py +0 -0
  340. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/shell/content_host.py +0 -0
  341. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/shell/layout.py +0 -0
  342. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/shell/nav_panel.py +0 -0
  343. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/shell/providers.py +0 -0
  344. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/shell/rail.py +0 -0
  345. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/shell/shell.py +0 -0
  346. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/shell/workspace.py +0 -0
  347. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/sidenav/__init__.py +0 -0
  348. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/sidenav/header.py +0 -0
  349. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/sidenav/separator.py +0 -0
  350. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/slider/__init__.py +0 -0
  351. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/slider/_shared.py +0 -0
  352. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/slider/rangeslider.py +0 -0
  353. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/slider/slider.py +0 -0
  354. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/spinnerentry.py +0 -0
  355. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tableview/__init__.py +0 -0
  356. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tableview/types.py +0 -0
  357. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tabs/__init__.py +0 -0
  358. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tabs/tabitem.py +0 -0
  359. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tabs/tabs.py +0 -0
  360. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tabs/tabview.py +0 -0
  361. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/__init__.py +0 -0
  362. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/change.py +0 -0
  363. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/core.py +0 -0
  364. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/decoration.py +0 -0
  365. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/diff.py +0 -0
  366. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +0 -0
  367. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +0 -0
  368. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +0 -0
  369. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +0 -0
  370. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +0 -0
  371. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/filter.py +0 -0
  372. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/search_overlay.py +0 -0
  373. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/sidebar.py +0 -0
  374. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/style_registry.py +0 -0
  375. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textarea/undo.py +0 -0
  376. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/textentry.py +0 -0
  377. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/timeentry.py +0 -0
  378. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/toast.py +0 -0
  379. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/toast_stack.py +0 -0
  380. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/togglegroup.py +0 -0
  381. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tooltip.py +0 -0
  382. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tree/__init__.py +0 -0
  383. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tree/source_binding.py +0 -0
  384. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tree/treeitem.py +0 -0
  385. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tree/treenode.py +0 -0
  386. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/composites/tree/treeview.py +0 -0
  387. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/mixins/__init__.py +0 -0
  388. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/mixins/configure_mixin.py +0 -0
  389. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/mixins/entry_mixin.py +0 -0
  390. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/mixins/font_mixin.py +0 -0
  391. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/mixins/icon_mixin.py +0 -0
  392. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/mixins/localization_mixin.py +0 -0
  393. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/mixins/signal_mixin.py +0 -0
  394. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/mixins/validation_mixin.py +0 -0
  395. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/__init__.py +0 -0
  396. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/_menubutton.py +0 -0
  397. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/badge.py +0 -0
  398. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/button.py +0 -0
  399. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/card.py +0 -0
  400. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/checkbutton.py +0 -0
  401. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/checktoggle.py +0 -0
  402. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/combobox.py +0 -0
  403. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/entry.py +0 -0
  404. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/flexframe.py +0 -0
  405. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/frame.py +0 -0
  406. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/gridframe.py +0 -0
  407. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/label.py +0 -0
  408. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/labelframe.py +0 -0
  409. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/optionmenu.py +0 -0
  410. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/packframe.py +0 -0
  411. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/panedwindow.py +0 -0
  412. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/progressbar.py +0 -0
  413. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/radiobutton.py +0 -0
  414. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/radiotoggle.py +0 -0
  415. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/scrollbar.py +0 -0
  416. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/separator.py +0 -0
  417. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/sizegrip.py +0 -0
  418. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/spinbox.py +0 -0
  419. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/switch.py +0 -0
  420. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/_impl/primitives/treeview.py +0 -0
  421. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/app.py +0 -0
  422. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/appshell.py +0 -0
  423. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/avatar.py +0 -0
  424. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/boolean_controls.py +0 -0
  425. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/buttongroup.py +0 -0
  426. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/calendar.py +0 -0
  427. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/card.py +0 -0
  428. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/carousel.py +0 -0
  429. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/chart.py +0 -0
  430. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/contextmenu.py +0 -0
  431. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/datefield.py +0 -0
  432. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/divider.py +0 -0
  433. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/expander.py +0 -0
  434. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/form.py +0 -0
  435. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/gallery.py +0 -0
  436. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/gauge.py +0 -0
  437. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/grid.py +0 -0
  438. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/groupbox.py +0 -0
  439. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/label.py +0 -0
  440. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/listview.py +0 -0
  441. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/numberfield.py +0 -0
  442. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/pagestack.py +0 -0
  443. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/passwordfield.py +0 -0
  444. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/pathfield.py +0 -0
  445. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/picture.py +0 -0
  446. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/progressbar.py +0 -0
  447. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/radio_variants.py +0 -0
  448. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/radiogroup.py +0 -0
  449. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/scrollbar.py +0 -0
  450. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/select.py +0 -0
  451. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/selectbutton.py +0 -0
  452. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/sidebar_toggle.py +0 -0
  453. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/sizegrip.py +0 -0
  454. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/slider.py +0 -0
  455. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/spinbox.py +0 -0
  456. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/stacks.py +0 -0
  457. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/statusbar.py +0 -0
  458. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/tabs.py +0 -0
  459. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/textfield.py +0 -0
  460. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/theme_toggle.py +0 -0
  461. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/toast.py +0 -0
  462. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/togglegroup.py +0 -0
  463. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/tooltip.py +0 -0
  464. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/tree.py +0 -0
  465. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/types.py +0 -0
  466. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack/widgets/window.py +0 -0
  467. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack.egg-info/SOURCES.txt +0 -0
  468. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack.egg-info/dependency_links.txt +0 -0
  469. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack.egg-info/entry_points.txt +0 -0
  470. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack.egg-info/requires.txt +0 -0
  471. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/src/bootstack.egg-info/top_level.txt +0 -0
  472. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/tests/test_images.py +0 -0
  473. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/tests/test_images_gui.py +0 -0
  474. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/tests/test_intl_format.py +0 -0
  475. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/tests/test_navmodel.py +0 -0
  476. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/tests/test_store.py +0 -0
  477. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/tests/test_theme_from_existing.py +0 -0
  478. {bootstack-0.1.0a13 → bootstack-0.1.0a15}/tests/test_validation_rules.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bootstack
3
- Version: 0.1.0a13
3
+ Version: 0.1.0a15
4
4
  Summary: From idea to a shipped desktop app, fast — a declarative, reactive, batteries-included Python UI framework with 60+ widgets, semantic theming, and built-in packaging.
5
5
  Author-email: Israel Dryer <israel.dryer@gmail.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "bootstack"
7
- version = "0.1.0a13"
7
+ version = "0.1.0a15"
8
8
  description = "From idea to a shipped desktop app, fast — a declarative, reactive, batteries-included Python UI framework with 60+ widgets, semantic theming, and built-in packaging."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -109,7 +109,7 @@ where = ["src"]
109
109
  ]
110
110
 
111
111
  [tool.bumpversion]
112
- current_version = "0.1.0a13"
112
+ current_version = "0.1.0a15"
113
113
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)((?P<pre>a|b|rc)(?P<pre_n>\\d+))?"
114
114
  serialize = [
115
115
  "{major}.{minor}.{patch}{pre}{pre_n}",
@@ -27,9 +27,11 @@ submodules — for example::
27
27
 
28
28
  See the "API overview" in the documentation for the full map.
29
29
  """
30
- from importlib.metadata import version as _pkg_version
31
-
32
- __version__ = _pkg_version("bootstack")
30
+ try:
31
+ from importlib.metadata import version as _pkg_version
32
+ __version__ = _pkg_version("bootstack")
33
+ except Exception:
34
+ __version__ = "unknown"
33
35
 
34
36
  # ── Runtime patches — must run before widgets are created ─────────────────────
35
37
  from bootstack._runtime.tk_patch import install_tk_autostyle as _install_autostyle
@@ -694,10 +694,12 @@ class App(BaseWindow, WidgetCapabilitiesMixin, tkinter.Tk):
694
694
  from bootstack.style.typography import Typography
695
695
  from bootstack._core.images import _ImageService
696
696
  from bootstack._runtime.visual_focus import reset_visual_focus_root
697
+ from bootstack.signals.signal import reset_realized_signals
697
698
  reset_style()
698
699
  Typography.reset()
699
700
  _ImageService.clear_cache()
700
701
  reset_visual_focus_root()
702
+ reset_realized_signals()
701
703
  gc.collect()
702
704
  except Exception:
703
705
  pass
@@ -128,11 +128,12 @@ if config.build and config.build.datas.include:
128
128
  # Collect package data (themes, fonts, icon glyphmaps, locales, etc.)
129
129
  # =============================================================================
130
130
 
131
- from PyInstaller.utils.hooks import collect_data_files
131
+ from PyInstaller.utils.hooks import collect_data_files, copy_metadata
132
132
 
133
133
  for _pkg in ("bootstack",):
134
134
  try:
135
135
  datas += collect_data_files(_pkg)
136
+ datas += copy_metadata(_pkg)
136
137
  except Exception as _e: # pragma: no cover
137
138
  print(f"Warning: Could not collect data files from {{_pkg}}: {{_e}}")
138
139
 
@@ -32,6 +32,8 @@ from bootstack.events._payloads import (
32
32
  RangeSliderEvent,
33
33
  RowEvent,
34
34
  RowsEvent,
35
+ SashMoveEvent,
36
+ ScrollEvent,
35
37
  SelectionEvent,
36
38
  SliderCommitEvent,
37
39
  SliderEvent,
@@ -97,4 +99,8 @@ __all__ = [
97
99
  # Payloads — data source
98
100
  "DataChangeEvent",
99
101
  "ChangeKind",
102
+ # Payloads — split view
103
+ "SashMoveEvent",
104
+ # Payloads — scroll view
105
+ "ScrollEvent",
100
106
  ]
@@ -487,3 +487,35 @@ class DataChangeEvent:
487
487
  record: Mapping[str, Any] | None = None
488
488
  """The affected record (or the applied updates) where cheaply available on
489
489
  `insert`/`update`; `None` otherwise."""
490
+
491
+
492
+ # ---------------------------------------------------------------------------
493
+ # SplitView
494
+ # ---------------------------------------------------------------------------
495
+
496
+
497
+ @dataclass(frozen=True, slots=True)
498
+ class SashMoveEvent:
499
+ """Fires when a `SplitView` sash is released after being dragged."""
500
+
501
+ index: int = 0
502
+ """Zero-based index of the sash that moved."""
503
+
504
+ position: int = 0
505
+ """New pixel position of the sash in pixels from the leading edge."""
506
+
507
+
508
+ # ---------------------------------------------------------------------------
509
+ # ScrollView
510
+ # ---------------------------------------------------------------------------
511
+
512
+
513
+ @dataclass(frozen=True, slots=True)
514
+ class ScrollEvent:
515
+ """Fires when a `ScrollView`'s viewport position changes."""
516
+
517
+ y: float = 0.0
518
+ """Vertical scroll position — 0.0 (top) to 1.0 (bottom)."""
519
+
520
+ x: float = 0.0
521
+ """Horizontal scroll position — 0.0 (left) to 1.0 (right)."""
@@ -0,0 +1,98 @@
1
+ Signals for bootstack
2
+ =====================
3
+
4
+ Lightweight reactive state. A ``Signal[T]`` holds a value, notifies subscribers
5
+ when it changes, and can be bound two-way to widgets. It is backed by a Tk
6
+ variable, but that variable is created lazily, so the Tk surface never leaks
7
+ into the public API.
8
+
9
+ > The user-facing guide is ``docs/reference/signals.rst`` (teaching) and the
10
+ > API Reference page for ``bootstack.signals`` (lookup). This README covers the
11
+ > package internals; keep it in sync with ``signal.py``.
12
+
13
+ Architecture
14
+ - ``Signal[T]`` (public): the reactive cell — ``signal()`` to read, ``set()`` to
15
+ write, ``subscribe()`` to observe, ``map()`` to derive.
16
+ - Lazy Tk-var realization: ``Signal(...)`` creates **no** Tk variable at
17
+ construction, so a signal can be created at module level (before any ``App``).
18
+ The backing variable is realized on first bind/escape-hatch access against the
19
+ running interpreter, and re-realized cleanly across ``App`` lifecycles.
20
+ - Object mode: values that are not Tk-native (anything other than
21
+ ``bool``/``int``/``float``/``str``/``set`` — e.g. a ``date`` or a dataclass)
22
+ are held as the authoritative Python object; the Tk variable is used only as a
23
+ change-notification bus. Native values are stored in the Tk variable directly.
24
+ - ``_SignalTrace`` (internal): manages the Tcl variable trace
25
+ (``trace_add``/``trace_remove``).
26
+
27
+ Key behaviors
28
+ - Read / write: ``signal()`` returns the current value; ``signal.set(v)`` updates
29
+ it. A ``set()`` to an equal value is a no-op (no notification).
30
+ - Subscriptions: ``subscribe(callback, *, immediate=False)`` returns a
31
+ ``streams.Handle``; call ``handle.cancel()`` to unsubscribe. ``immediate=True``
32
+ fires the callback once with the current value at subscribe time.
33
+ - Derived signals: ``map(transform)`` returns a new signal that follows this one.
34
+ A weak reference keeps the parent from holding the derived signal alive.
35
+ - Robustness: the last value is cached and returned even if the backing variable
36
+ has been dropped (e.g. between ``App`` lifecycles).
37
+ - Escape hatch: ``Signal.from_variable(tk_var)`` wraps an existing Tk variable,
38
+ and ``signal.var`` exposes the backing variable. These are the only Tk-aware
39
+ paths; everything else stays Tk-free.
40
+
41
+ Usage
42
+ 1) Quick start (works at module level — no ``App`` required)
43
+ ```python
44
+ from bootstack.signals import Signal
45
+
46
+ count = Signal(0)
47
+ print(count()) # -> 0
48
+ count.set(1)
49
+ print(count()) # -> 1
50
+ ```
51
+
52
+ 2) Two-way binding to a widget
53
+ ```python
54
+ import bootstack as bs
55
+
56
+ with bs.App() as app:
57
+ name = bs.Signal("")
58
+ bs.TextField(textsignal=name) # edits flow into the signal
59
+ bs.Label(textsignal=name.map(lambda v: f"Hello, {v}!")) # derived display
60
+ app.run()
61
+ ```
62
+
63
+ 3) Subscribing and unsubscribing
64
+ ```python
65
+ import bootstack as bs
66
+
67
+ with bs.App() as app:
68
+ flag = bs.Signal(False)
69
+
70
+ def on_flag(value):
71
+ print("flag:", value)
72
+
73
+ handle = flag.subscribe(on_flag, immediate=True) # prints: flag: False
74
+ flag.set(True) # prints: flag: True
75
+ handle.cancel() # stop observing
76
+ app.run()
77
+ ```
78
+
79
+ 4) Typed (object-mode) values
80
+ ```python
81
+ from datetime import date
82
+ import bootstack as bs
83
+
84
+ with bs.App():
85
+ due = bs.Signal(date.today())
86
+ bs.DateField(signal=due) # binds the typed value
87
+ print(type(due())) # -> <class 'datetime.date'> (not str)
88
+ ```
89
+
90
+ Import path
91
+ - ``import bootstack as bs; bs.Signal``
92
+ - ``from bootstack.signals import Signal``
93
+
94
+ Notes
95
+ - The UI toolkit is not thread-safe. Marshal cross-thread updates onto the UI
96
+ via the framework's scheduling, not by touching the signal from a worker
97
+ thread.
98
+ - Keep subscriber callbacks fast; offload long-running work.
@@ -10,43 +10,43 @@ from bootstack.streams import Handle
10
10
  T = TypeVar("T")
11
11
  U = TypeVar("U")
12
12
 
13
+ # Weak registry of all realized signals. Cleared on App.destroy() (when no
14
+ # other App is live) so module-level signals can be re-realized against the
15
+ # next App's interpreter without dangling against a dead one.
16
+ _realized: "weakref.WeakSet[Signal]" = weakref.WeakSet()
13
17
 
14
- class _SignalTrace:
15
- """
16
- Internal helper to manage Tcl variable traces using tkinter's Variable API.
17
- This class encapsulates low-level `trace_add` and `trace_remove` logic.
18
+ # Global subscriber ID counter — unique across all Signal instances so that
19
+ # Handle cancellation never accidentally removes the wrong entry.
20
+ _sub_counter = count(1)
21
+
22
+
23
+ def reset_realized_signals() -> None:
24
+ """Drop the Tk var from every realized signal.
25
+
26
+ Called on App.destroy() when no other App is live. Module-level signals
27
+ return to pending (unrealized) state and re-realize transparently the next
28
+ time a widget inside a new App binds them via .var / .name / .tk.
18
29
  """
30
+ for sig in list(_realized):
31
+ try:
32
+ sig._drop_var()
33
+ except Exception:
34
+ pass
19
35
 
20
- def __init__(self, tk_var: tk.Variable):
21
- """
22
- Initialize a trace manager for a tkinter variable.
23
36
 
24
- Args:
25
- tk_var: A tkinter.Variable instance (e.g., StringVar, IntVar).
26
- """
37
+ class _SignalTrace:
38
+ """Manages the single bridge Tk trace on a realized Signal."""
39
+
40
+ def __init__(self, tk_var: tk.Variable):
27
41
  self._var = tk_var
28
- # Map trace id -> (operation, callback)
29
42
  self._traces: dict[str, tuple[TraceOperation, Callable[..., Any]]] = {}
30
43
 
31
- def callbacks(self) -> tuple[str, ...]:
32
- """
33
- Return all currently active trace IDs.
34
-
35
- Returns:
36
- A tuple of trace ID strings.
37
- """
38
- return tuple(self._traces.keys())
39
-
40
44
  def add(
41
45
  self,
42
46
  operation: TraceOperation,
43
47
  callback: Callable[[T], Any],
44
48
  get_value: Callable[[], T],
45
49
  ) -> str:
46
- """
47
- Add a new trace that calls a callback when the variable is written.
48
- """
49
-
50
50
  def traced_callback(name: str, index: str, mode: str) -> None:
51
51
  callback(get_value())
52
52
 
@@ -58,9 +58,6 @@ class _SignalTrace:
58
58
  return fid
59
59
 
60
60
  def remove(self, fid: str) -> None:
61
- """
62
- Remove a trace by ID. Safe if already removed or variable destroyed.
63
- """
64
61
  op_cb = self._traces.pop(fid, None)
65
62
  if op_cb is None:
66
63
  return
@@ -68,7 +65,6 @@ class _SignalTrace:
68
65
  try:
69
66
  self._var.trace_remove(operation, fid)
70
67
  except tk.TclError:
71
- # Variable may be unset/destroyed; ignore
72
68
  pass
73
69
 
74
70
 
@@ -82,6 +78,11 @@ class Signal(Generic[T]):
82
78
 
83
79
  Bind a signal to a widget by passing it as `textsignal=` for text-bearing
84
80
  widgets, or `signal=` for boolean and numeric widgets.
81
+
82
+ Signals may be constructed at module level (before `bs.App()` exists). The
83
+ backing Tk variable is created lazily on the first widget binding and torn
84
+ down when the App is destroyed, so the same signal can be reused across
85
+ successive App lifecycles.
85
86
  """
86
87
 
87
88
  _cnt = count(1)
@@ -90,29 +91,22 @@ class Signal(Generic[T]):
90
91
  self._name = name or f"SIG{next(self._cnt)}"
91
92
  self._type: Type[T] = type(value)
92
93
  self._master: tk.Misc | None = master
93
- # An object-typed signal (e.g. a date/time, or any custom object) has no
94
- # native Tk variable that round-trips it — a StringVar would hand back the
95
- # string form. In that case the cached Python value is the source of truth
96
- # and the backing variable serves only as the write-trace notification bus.
97
94
  self._object_mode = not self._is_tk_native(value)
98
- self._var = self._create_variable(value)
99
- self._trace = _SignalTrace(self._var)
100
- # Map fid -> callback to allow multiple subscriptions of same function
101
- self._subscribers: dict[str, Callable[[T], Any]] = {}
102
- # Reverse index: callback -> set of fids
103
- self._callback_index: dict[Callable[[T], Any], set[str]] = {}
104
- # Cache last known value for robustness when Tcl variable is torn down
95
+ # _last is always the authoritative Python value — before realization it
96
+ # is the only store; after realization it stays in sync via the bridge.
105
97
  self._last: T = value
98
+ # Tk var and bridge trace — None until the first widget binding.
99
+ self._var: tk.Variable | None = None
100
+ self._trace: _SignalTrace | None = None
101
+ self._bridge_fid: str | None = None
102
+ # Python-owned subscriber list (int id → callback). The bridge trace fans
103
+ # these out when a widget writes the Tk var; set() notifies them directly
104
+ # while unrealized. Replaces the old one-Tk-trace-per-subscriber model.
105
+ self._subscribers: dict[int, Callable[[T], Any]] = {}
106
106
 
107
107
  @staticmethod
108
108
  def _is_tk_native(value: Any) -> bool:
109
- """Whether a value maps to a Tk variable that round-trips it losslessly.
110
-
111
- Booleans, ints, floats, strings, and sets each have a backing Tk
112
- variable that returns the same Python type on read. Any other value
113
- (a `date`, `time`, or arbitrary object) does not, so it is held as a
114
- Python object instead.
115
- """
109
+ """Whether a value maps to a Tk variable that round-trips it losslessly."""
116
110
  return isinstance(value, (bool, int, float, str, set))
117
111
 
118
112
  def _create_variable(self, value: T) -> tk.Variable:
@@ -127,23 +121,44 @@ class Signal(Generic[T]):
127
121
  else:
128
122
  return tk.StringVar(master=self._master, name=self._name, value=value)
129
123
 
130
- def __call__(self) -> T:
131
- """
132
- Get the current value of the signal.
124
+ def _realize(self) -> None:
125
+ """Create the backing Tk variable and wire the single bridge trace.
133
126
 
134
- Returns:
135
- The current typed value.
127
+ Idempotent — safe to call multiple times. Only runs inside an App
128
+ context (widget bindings are always inside one), so a live interpreter
129
+ is guaranteed.
136
130
  """
137
- if self._object_mode:
138
- # The Python object is authoritative; the backing var only holds a
139
- # string rendering used to drive write traces.
131
+ if self._var is not None:
132
+ return
133
+ self._var = self._create_variable(self._last)
134
+ self._trace = _SignalTrace(self._var)
135
+
136
+ def _bridge(value: T) -> None:
137
+ if not self._object_mode:
138
+ self._last = value
139
+ for cb in list(self._subscribers.values()):
140
+ cb(self._last)
141
+
142
+ self._bridge_fid = self._trace.add("write", _bridge, self)
143
+ _realized.add(self)
144
+
145
+ def _drop_var(self) -> None:
146
+ """Release the Tk var and bridge trace (called by reset_realized_signals)."""
147
+ if self._trace is not None and self._bridge_fid is not None:
148
+ self._trace.remove(self._bridge_fid)
149
+ self._var = None
150
+ self._trace = None
151
+ self._bridge_fid = None
152
+
153
+ def __call__(self) -> T:
154
+ """Get the current value of the signal."""
155
+ if self._var is None or self._object_mode:
140
156
  return self._last
141
157
  try:
142
158
  value = self._var.get()
143
- self._last = value # cache last good value
159
+ self._last = value
144
160
  return value
145
161
  except tk.TclError:
146
- # Return last known value when underlying var is destroyed/unset
147
162
  return self._last
148
163
 
149
164
  @classmethod
@@ -166,7 +181,6 @@ class Signal(Generic[T]):
166
181
  Returns:
167
182
  A Signal bound to the provided tk_var.
168
183
  """
169
- # Infer Python type from the tk variable if not explicitly provided
170
184
  if coerce is None:
171
185
  if isinstance(tk_var, tk.BooleanVar):
172
186
  py_type: Type[Any] = bool
@@ -181,23 +195,15 @@ class Signal(Generic[T]):
181
195
  else:
182
196
  py_type = coerce
183
197
 
184
- # Construct without creating a new tk.Variable
185
- self = cls.__new__(cls) # bypass __init__
198
+ self = cls.__new__(cls)
186
199
  self._name = name or getattr(tk_var, "_name", str(tk_var))
187
200
  self._type = py_type # type: ignore[assignment]
188
- # Wrapping an existing Tk variable: it always round-trips its own native
189
- # type, so object mode never applies here.
190
201
  self._object_mode = False
191
- self._var = tk_var
192
- self._trace = _SignalTrace(self._var)
193
- self._subscribers = {}
194
- self._callback_index = {}
195
- # Best-effort capture of master/interpreter for reference
196
202
  self._master = getattr(tk_var, "_master", None)
203
+ self._subscribers = {}
197
204
  try:
198
205
  current = tk_var.get() # type: ignore[assignment]
199
206
  except tk.TclError:
200
- # Fallback default per inferred type
201
207
  if py_type is float: # type: ignore[comparison-overlap]
202
208
  current = 0.0
203
209
  elif py_type is int: # type: ignore[comparison-overlap]
@@ -209,6 +215,18 @@ class Signal(Generic[T]):
209
215
  else:
210
216
  current = ""
211
217
  self._last = current # type: ignore[assignment]
218
+
219
+ # from_variable is immediately realized — the var already exists.
220
+ self._var = tk_var
221
+ self._trace = _SignalTrace(self._var)
222
+
223
+ def _bridge(value: T) -> None:
224
+ self._last = value
225
+ for cb in list(self._subscribers.values()):
226
+ cb(self._last)
227
+
228
+ self._bridge_fid = self._trace.add("write", _bridge, self)
229
+ _realized.add(self)
212
230
  return self
213
231
 
214
232
  def set(self, value: T) -> None:
@@ -223,9 +241,6 @@ class Signal(Generic[T]):
223
241
  TypeError: If the value type does not match the signal's type (and is
224
242
  not an `int` widened to a `float`).
225
243
  """
226
- # Enforce the type to avoid surprises (e.g. a bool accepted for an int),
227
- # but widen an int into a float-typed signal — a Slider seeded at 0 and
228
- # later set to 0.5 is the common case. `type(value) is int` excludes bool.
229
244
  if type(value) is not self._type:
230
245
  if self._type is float and type(value) is int:
231
246
  value = float(value) # type: ignore[assignment]
@@ -233,10 +248,17 @@ class Signal(Generic[T]):
233
248
  raise TypeError(
234
249
  f"Expected {self._type.__name__}, got {type(value).__name__}"
235
250
  )
251
+
252
+ if self._var is None:
253
+ # Unrealized — notify Python subscribers directly.
254
+ if self._last == value:
255
+ return
256
+ self._last = value
257
+ for cb in list(self._subscribers.values()):
258
+ cb(self._last)
259
+ return
260
+
236
261
  if self._object_mode:
237
- # Reduce redundant updates by comparing the Python objects, not the
238
- # var's string form. Writing the string form fires write traces, so
239
- # subscribers are notified with the real object via `__call__`.
240
262
  if self._last == value:
241
263
  return
242
264
  self._last = value
@@ -244,14 +266,14 @@ class Signal(Generic[T]):
244
266
  self._var.set(str(value))
245
267
  except tk.TclError:
246
268
  pass
269
+ # Bridge trace fires from var.set() → notifies subscribers.
247
270
  return
248
- # Reduce redundant updates if value unchanged
271
+
272
+ # Native-type, realized — let the Tk var fire the bridge trace.
249
273
  try:
250
- current = self._var.get()
251
- if current == value:
274
+ if self._var.get() == value:
252
275
  return
253
276
  except tk.TclError:
254
- # If var is gone, proceed to set and let Tcl recreate path if possible
255
277
  pass
256
278
  self._var.set(value)
257
279
  self._last = value
@@ -271,14 +293,11 @@ class Signal(Generic[T]):
271
293
  A new read-only signal that stays updated with the transformed value.
272
294
  """
273
295
  derived = Signal(transform(self()))
274
-
275
- # Use weakref to avoid keeping derived alive solely via subscription
276
296
  weak_derived = weakref.ref(derived)
277
297
 
278
298
  def update(value: T) -> None:
279
299
  d = weak_derived()
280
300
  if d is None:
281
- # Auto-detach if derived is GC'd
282
301
  return
283
302
  d.set(transform(value))
284
303
 
@@ -298,48 +317,37 @@ class Signal(Generic[T]):
298
317
  A cancellable `Handle` — call `.cancel()` to stop listening, or use
299
318
  it as a context manager to unsubscribe on exit.
300
319
  """
301
- fid = self._trace.add("write", callback, self)
320
+ fid = next(_sub_counter)
302
321
  self._subscribers[fid] = callback
303
- self._callback_index.setdefault(callback, set()).add(fid)
304
322
  if immediate:
305
- # Call synchronously at subscription time; let any error surface to
306
- # the caller rather than swallowing a real bug in the callback.
307
323
  callback(self())
308
- return Handle(lambda: self._unsubscribe(fid))
309
-
310
- def _unsubscribe(self, funcid: str) -> None:
311
- """Remove a previously registered subscriber by its trace id."""
312
- self._subscribers.pop(funcid, None)
313
- self._trace.remove(funcid)
324
+ return Handle(lambda: self._subscribers.pop(fid, None))
314
325
 
315
326
  @property
316
327
  def name(self) -> str:
317
- """
318
- The internal name of the signal, used when binding it to a widget.
319
- """
328
+ """The internal Tcl variable name. Accessing this realizes the signal."""
329
+ self._realize()
320
330
  return self._name
321
331
 
322
332
  @property
323
333
  def type(self) -> Type[T]:
324
- """
325
- The original type of the signal value.
326
-
327
- Returns:
328
- A Python type (e.g., int, str).
329
- """
334
+ """The original type of the signal value."""
330
335
  return self._type
331
336
 
332
337
  @property
333
338
  def var(self) -> tk.Variable:
334
- return self._var
339
+ """The backing `tk.Variable`. Accessing this realizes the signal."""
340
+ self._realize()
341
+ return self._var # type: ignore[return-value]
335
342
 
336
343
  @property
337
344
  def tk(self) -> tk.Variable:
338
345
  """Underlying `tk.Variable`. UNSUPPORTED — escape-hatch use only."""
339
- return self._var
346
+ self._realize()
347
+ return self._var # type: ignore[return-value]
340
348
 
341
349
  def __str__(self) -> str:
342
350
  return self._name
343
351
 
344
352
  def __repr__(self) -> str:
345
- return self._name
353
+ return self._name
@@ -351,8 +351,10 @@ class Carousel(Frame):
351
351
  self._stage.tag_lower(next_id)
352
352
  if cur_id is not None:
353
353
  self._stage.tag_lower(cur_id)
354
- steps = 12
355
- dx = -d * w / steps
354
+ steps = 8
355
+
356
+ def _ease(t: float) -> float:
357
+ return 2 * t * t if t < 0.5 else 1 - (-2 * t + 2) ** 2 / 2
356
358
 
357
359
  def step(i: int) -> None:
358
360
  if i >= steps:
@@ -366,9 +368,10 @@ class Carousel(Frame):
366
368
  self._transitioning = False
367
369
  self._after_change()
368
370
  return
369
- self._stage.move(next_id, dx, 0)
371
+ t = _ease(i / steps)
372
+ self._stage.coords(next_id, round(d * w * (1 - t)), 0)
370
373
  if cur_id is not None:
371
- self._stage.move(cur_id, dx, 0)
374
+ self._stage.coords(cur_id, round(-d * w * t), 0)
372
375
  self._schedule.delay(_FRAME_MS, lambda: step(i + 1))
373
376
 
374
377
  step(1)
@@ -381,19 +384,21 @@ class Carousel(Frame):
381
384
  return
382
385
  self._transitioning = True
383
386
  steps = 10
387
+ # Pre-compute all frames up front so PhotoImage allocation doesn't happen
388
+ # inside the after() loop where it blocks the canvas refresh.
389
+ frames = [PhotoImage(PILImage.blend(cur, next_pil, i / steps)) for i in range(1, steps + 1)]
384
390
 
385
391
  def step(i: int) -> None:
386
- if i > steps:
392
+ if i >= len(frames):
387
393
  self._set_current(next_pil)
388
394
  self._transitioning = False
389
395
  self._after_change()
390
396
  return
391
- blended = PILImage.blend(cur, next_pil, i / steps)
392
- self._fade_photo = PhotoImage(blended)
397
+ self._fade_photo = frames[i]
393
398
  self._stage.itemconfigure(self._img_id, image=self._fade_photo)
394
399
  self._schedule.delay(_FRAME_MS + 6, lambda: step(i + 1))
395
400
 
396
- step(1)
401
+ step(0)
397
402
 
398
403
  def _after_change(self) -> None:
399
404
  bw, bh = self._box