bootstack 0.1.0a5__tar.gz → 0.1.0a7__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 (432) hide show
  1. {bootstack-0.1.0a5/src/bootstack.egg-info → bootstack-0.1.0a7}/PKG-INFO +2 -2
  2. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/README.md +1 -1
  3. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/pyproject.toml +2 -2
  4. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/__init__.py +9 -4
  5. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/api/__init__.py +2 -1
  6. bootstack-0.1.0a7/src/bootstack/api/menu.py +7 -0
  7. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/api/style.py +4 -1
  8. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/api/widgets.py +3 -0
  9. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/__init__.py +4 -1
  10. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/add.py +2 -2
  11. bootstack-0.1.0a7/src/bootstack/cli/icons.py +28 -0
  12. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/localization/intl_format.py +4 -4
  13. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/datasource/sqlite_source.py +60 -53
  14. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/dialogs/datedialog.py +38 -12
  15. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/dialogs/dialog.py +9 -9
  16. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/dialogs/filterdialog.py +12 -12
  17. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/runtime/menu.py +89 -136
  18. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/field.py +14 -8
  19. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/typography.py +6 -6
  20. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/appshell.py +47 -16
  21. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/calendar.py +1 -1
  22. bootstack-0.1.0a7/src/bootstack/widgets/composites/dateentry.py +434 -0
  23. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/dropdownbutton.py +1 -3
  24. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/field.py +43 -17
  25. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/form.py +1 -2
  26. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/scrollview.py +19 -10
  27. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/selectbox.py +11 -4
  28. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/sidenav/view.py +6 -15
  29. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/tableview/tableview.py +21 -21
  30. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/textentry.py +5 -8
  31. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/timeentry.py +8 -1
  32. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/toolbar.py +1 -1
  33. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/parts/textentry_part.py +2 -0
  34. {bootstack-0.1.0a5 → bootstack-0.1.0a7/src/bootstack.egg-info}/PKG-INFO +2 -2
  35. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack.egg-info/SOURCES.txt +1 -0
  36. bootstack-0.1.0a5/src/bootstack/api/menu.py +0 -7
  37. bootstack-0.1.0a5/src/bootstack/widgets/composites/dateentry.py +0 -261
  38. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/LICENSE +0 -0
  39. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/MANIFEST.in +0 -0
  40. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/NOTICE +0 -0
  41. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/setup.cfg +0 -0
  42. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/__main__.py +0 -0
  43. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/api/app.py +0 -0
  44. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/api/constants.py +0 -0
  45. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/api/data.py +0 -0
  46. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/api/dialogs.py +0 -0
  47. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/api/i18n.py +0 -0
  48. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/api/localization.py +0 -0
  49. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/api/utils.py +0 -0
  50. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/__init__.py +0 -0
  51. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/bootstack-dark.ico +0 -0
  52. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/bootstack-light.ico +0 -0
  53. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/bootstack-transparent.png +0 -0
  54. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/bootstack.ico +0 -0
  55. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/bootstack.png +0 -0
  56. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/__init__.py +0 -0
  57. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/badge-pill.png +0 -0
  58. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/badge-square.png +0 -0
  59. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/border.png +0 -0
  60. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-compact.png +0 -0
  61. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-default.png +0 -0
  62. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-horizontal-after-compact.png +0 -0
  63. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-horizontal-after-default.png +0 -0
  64. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-horizontal-before-compact.png +0 -0
  65. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-horizontal-before-default.png +0 -0
  66. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-horizontal-center-compact.png +0 -0
  67. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-horizontal-center-default.png +0 -0
  68. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-vertical-after-compact.png +0 -0
  69. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-vertical-after-default.png +0 -0
  70. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-vertical-before-compact.png +0 -0
  71. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-vertical-before-default.png +0 -0
  72. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-vertical-center-compact.png +0 -0
  73. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/button-group-vertical-center-default.png +0 -0
  74. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/checkbox-checked.png +0 -0
  75. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/checkbox-indeterminate.png +0 -0
  76. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/checkbox-unchecked.png +0 -0
  77. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/field.png +0 -0
  78. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/input-after-compact.png +0 -0
  79. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/input-after-default.png +0 -0
  80. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/input-before-compact.png +0 -0
  81. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/input-before-default.png +0 -0
  82. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/input-compact.png +0 -0
  83. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/input-default.png +0 -0
  84. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/list-item-separated.png +0 -0
  85. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/list-item.png +0 -0
  86. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/manifest.toml +0 -0
  87. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/menu-item.png +0 -0
  88. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/nav-button-compact.png +0 -0
  89. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/nav-button-default.png +0 -0
  90. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/nav-icon-button-compact.png +0 -0
  91. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/nav-icon-button-default.png +0 -0
  92. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/notebook-client-border.png +0 -0
  93. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/notebook-tab-active.png +0 -0
  94. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/notebook-tab-bar.png +0 -0
  95. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/notebook-tab-normal.png +0 -0
  96. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/notebook-tab-pill.png +0 -0
  97. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/progress-bar-horizontal-striped.png +0 -0
  98. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/progress-bar-solid.png +0 -0
  99. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/progress-bar-thin.png +0 -0
  100. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/progress-bar-vertical-striped.png +0 -0
  101. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/radio-selected.png +0 -0
  102. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/radio-unselected.png +0 -0
  103. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/scrollbar-horizontal.png +0 -0
  104. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/scrollbar-vertical.png +0 -0
  105. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/slider-handle-focus.png +0 -0
  106. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/slider-handle.png +0 -0
  107. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/slider-track-horizontal.png +0 -0
  108. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/slider-track-vertical.png +0 -0
  109. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/switch-off.png +0 -0
  110. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/switch-on.png +0 -0
  111. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/tabs-bar-horizontal.png +0 -0
  112. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/tabs-bar-vertical.png +0 -0
  113. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/elements/tabs-pill.png +0 -0
  114. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
  115. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +0 -0
  116. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +0 -0
  117. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
  118. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +0 -0
  119. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
  120. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +0 -0
  121. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
  122. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +0 -0
  123. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
  124. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +0 -0
  125. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
  126. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +0 -0
  127. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
  128. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +0 -0
  129. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
  130. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +0 -0
  131. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
  132. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +0 -0
  133. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
  134. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +0 -0
  135. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
  136. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +0 -0
  137. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
  138. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +0 -0
  139. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
  140. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +0 -0
  141. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
  142. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +0 -0
  143. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
  144. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +0 -0
  145. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
  146. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +0 -0
  147. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
  148. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +0 -0
  149. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
  150. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +0 -0
  151. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
  152. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +0 -0
  153. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
  154. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +0 -0
  155. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
  156. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +0 -0
  157. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
  158. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +0 -0
  159. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/__init__.py +0 -0
  160. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/amber-dark.json +0 -0
  161. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/amber-light.json +0 -0
  162. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/aurora-dark.json +0 -0
  163. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/aurora-light.json +0 -0
  164. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/bootstrap-dark.json +0 -0
  165. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/bootstrap-light.json +0 -0
  166. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/classic-dark.json +0 -0
  167. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/classic-light.json +0 -0
  168. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/docs-dark.json +0 -0
  169. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/docs-light.json +0 -0
  170. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/forest-dark.json +0 -0
  171. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/forest-light.json +0 -0
  172. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/ocean-dark.json +0 -0
  173. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/ocean-light.json +0 -0
  174. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/rose-dark.json +0 -0
  175. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/themes/rose-light.json +0 -0
  176. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/__init__.py +0 -0
  177. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/badge-default.png +0 -0
  178. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/badge-pill.png +0 -0
  179. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/border.png +0 -0
  180. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/button-group-horizontal-after.png +0 -0
  181. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/button-group-horizontal-before.png +0 -0
  182. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/button-group-horizontal-center.png +0 -0
  183. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/button-group-vertical-after.png +0 -0
  184. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/button-group-vertical-before.png +0 -0
  185. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/button-group-vertical-center.png +0 -0
  186. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/button.png +0 -0
  187. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/checkbox-checked.png +0 -0
  188. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/checkbox-indeterminate.png +0 -0
  189. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/checkbox-unchecked.png +0 -0
  190. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/field.png +0 -0
  191. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/icon-button.png +0 -0
  192. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/input-inner.png +0 -0
  193. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/input-prefix.png +0 -0
  194. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/input-suffix.png +0 -0
  195. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/input.png +0 -0
  196. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/list-item-focus.png +0 -0
  197. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/list-item-separated.png +0 -0
  198. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/menu-item-separated.png +0 -0
  199. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/notebook-client-border.png +0 -0
  200. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/notebook-pill-active.png +0 -0
  201. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/notebook-pill-inactive.png +0 -0
  202. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/notebook-tab-active.png +0 -0
  203. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/notebook-tab-border.png +0 -0
  204. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/notebook-tab-normal.png +0 -0
  205. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/notebook-underline.png +0 -0
  206. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/progress-bar-horizontal-default.png +0 -0
  207. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/progress-bar-horizontal-striped.png +0 -0
  208. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/progress-bar-vertical-default.png +0 -0
  209. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/progress-bar-vertical-striped.png +0 -0
  210. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/progress-trough-horizontal.png +0 -0
  211. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/progress-trough-vertical.png +0 -0
  212. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/radio-selected.png +0 -0
  213. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/radio-unselected.png +0 -0
  214. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/scrollbar-horizontal-rounded.png +0 -0
  215. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/scrollbar-vertical-rounded.png +0 -0
  216. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/separator-horizontal.png +0 -0
  217. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/separator-vertical.png +0 -0
  218. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/slider-handle-focus.png +0 -0
  219. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/slider-handle.png +0 -0
  220. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/slider-track-horizontal.png +0 -0
  221. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/slider-track-vertical.png +0 -0
  222. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/switch-off.png +0 -0
  223. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/switch-on.png +0 -0
  224. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/tabs-bar-horizontal.png +0 -0
  225. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/tabs-bar-vertical.png +0 -0
  226. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/assets/widgets/tabs-pill.png +0 -0
  227. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/__main__.py +0 -0
  228. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/build.py +0 -0
  229. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/config.py +0 -0
  230. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/demo.py +0 -0
  231. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/doctor.py +0 -0
  232. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/list_cmd.py +0 -0
  233. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/promote.py +0 -0
  234. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/pyinstaller.py +0 -0
  235. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/run.py +0 -0
  236. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/start.py +0 -0
  237. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/cli/templates/__init__.py +0 -0
  238. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/constants.py +0 -0
  239. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/__init__.py +0 -0
  240. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/__init__.py +0 -0
  241. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/after.py +0 -0
  242. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/bind.py +0 -0
  243. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/bindtags.py +0 -0
  244. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/busy.py +0 -0
  245. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/clipboard.py +0 -0
  246. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/focus.py +0 -0
  247. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/grab.py +0 -0
  248. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/grid.py +0 -0
  249. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/localization.py +0 -0
  250. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/pack.py +0 -0
  251. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/place.py +0 -0
  252. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/selection.py +0 -0
  253. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/signals.py +0 -0
  254. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/capabilities/winfo.py +0 -0
  255. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/colorutils.py +0 -0
  256. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/exceptions.py +0 -0
  257. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/images.py +0 -0
  258. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/localization/README.md +0 -0
  259. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/localization/__init__.py +0 -0
  260. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/localization/msgcat.py +0 -0
  261. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/localization/specs.py +0 -0
  262. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/mixins/__init__.py +0 -0
  263. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/mixins/ttk_state.py +0 -0
  264. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/mixins/widget.py +0 -0
  265. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/publisher.py +0 -0
  266. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/signals/README.md +0 -0
  267. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/signals/__init__.py +0 -0
  268. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/signals/integration.py +0 -0
  269. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/signals/signal.py +0 -0
  270. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/signals/types.py +0 -0
  271. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/validation/__init__.py +0 -0
  272. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/validation/types.py +0 -0
  273. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/validation/validation_result.py +0 -0
  274. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/validation/validation_rules.py +0 -0
  275. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/core/variables.py +0 -0
  276. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/datasource/README.md +0 -0
  277. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/datasource/__init__.py +0 -0
  278. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/datasource/base.py +0 -0
  279. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/datasource/file_source.py +0 -0
  280. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/datasource/memory_source.py +0 -0
  281. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/datasource/types.py +0 -0
  282. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/dialogs/__init__.py +0 -0
  283. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/dialogs/colorchooser.py +0 -0
  284. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/dialogs/colordropper.py +0 -0
  285. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/dialogs/fontdialog.py +0 -0
  286. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/dialogs/formdialog.py +0 -0
  287. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/dialogs/message.py +0 -0
  288. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/dialogs/query.py +0 -0
  289. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/py.typed +0 -0
  290. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/runtime/__init__.py +0 -0
  291. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/runtime/app.py +0 -0
  292. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/runtime/base_window.py +0 -0
  293. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/runtime/events.py +0 -0
  294. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/runtime/shortcuts.py +0 -0
  295. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/runtime/tk_patch.py +0 -0
  296. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/runtime/toplevel.py +0 -0
  297. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/runtime/utility.py +0 -0
  298. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/runtime/visual_focus.py +0 -0
  299. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/runtime/window_utilities.py +0 -0
  300. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/__init__.py +0 -0
  301. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/bootstyle.py +0 -0
  302. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/bootstyle_builder_base.py +0 -0
  303. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/bootstyle_builder_mixed.py +0 -0
  304. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/bootstyle_builder_tk.py +0 -0
  305. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/bootstyle_builder_ttk.py +0 -0
  306. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/__init__.py +0 -0
  307. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/badge.py +0 -0
  308. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/button.py +0 -0
  309. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/buttongroup.py +0 -0
  310. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/calendar.py +0 -0
  311. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/checkbutton.py +0 -0
  312. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/combobox.py +0 -0
  313. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/contextmenu.py +0 -0
  314. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/entry.py +0 -0
  315. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/expander.py +0 -0
  316. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/frame.py +0 -0
  317. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/label.py +0 -0
  318. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/labelframe.py +0 -0
  319. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/listview.py +0 -0
  320. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/menubar.py +0 -0
  321. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/menubutton.py +0 -0
  322. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/notebook.py +0 -0
  323. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/panedwindow.py +0 -0
  324. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/progressbar.py +0 -0
  325. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/radiobutton.py +0 -0
  326. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/scale.py +0 -0
  327. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/scrollbar.py +0 -0
  328. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/separator.py +0 -0
  329. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/sidenav.py +0 -0
  330. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/sizegrip.py +0 -0
  331. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/spinbox.py +0 -0
  332. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/switch.py +0 -0
  333. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/tabitem.py +0 -0
  334. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/toolbutton.py +0 -0
  335. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/tooltip.py +0 -0
  336. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/treeview.py +0 -0
  337. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders/utils.py +0 -0
  338. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders_tk/__init__.py +0 -0
  339. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/builders_tk/defaults.py +0 -0
  340. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/element.py +0 -0
  341. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/style.py +0 -0
  342. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/theme_provider.py +0 -0
  343. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/tk_patch.py +0 -0
  344. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/token_maps.py +0 -0
  345. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/types.py +0 -0
  346. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/style/utility.py +0 -0
  347. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/themes/__init__.py +0 -0
  348. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/themes/standard.py +0 -0
  349. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/themes/user.py +0 -0
  350. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/__init__.py +0 -0
  351. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/__init__.py +0 -0
  352. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/accordion.py +0 -0
  353. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/buttongroup.py +0 -0
  354. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/compositeframe.py +0 -0
  355. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/contextmenu.py +0 -0
  356. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/expander.py +0 -0
  357. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/floodgauge.py +0 -0
  358. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/labeledscale.py +0 -0
  359. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/list/__init__.py +0 -0
  360. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/list/listitem.py +0 -0
  361. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/list/listview.py +0 -0
  362. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/menubar.py +0 -0
  363. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/meter.py +0 -0
  364. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/numericentry.py +0 -0
  365. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/pagestack.py +0 -0
  366. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/passwordentry.py +0 -0
  367. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/pathentry.py +0 -0
  368. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/radiogroup.py +0 -0
  369. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/scrolledtext.py +0 -0
  370. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/scrolledtext.pyi +0 -0
  371. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/sidenav/__init__.py +0 -0
  372. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/sidenav/group.py +0 -0
  373. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/sidenav/header.py +0 -0
  374. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/sidenav/item.py +0 -0
  375. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/sidenav/separator.py +0 -0
  376. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/spinnerentry.py +0 -0
  377. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/tableview/__init__.py +0 -0
  378. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/tableview/types.py +0 -0
  379. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/tabs/__init__.py +0 -0
  380. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/tabs/tabitem.py +0 -0
  381. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/tabs/tabs.py +0 -0
  382. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/tabs/tabview.py +0 -0
  383. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/toast.py +0 -0
  384. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/togglegroup.py +0 -0
  385. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/composites/tooltip.py +0 -0
  386. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/internal/__init__.py +0 -0
  387. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/internal/wrapper_base.py +0 -0
  388. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/mixins/__init__.py +0 -0
  389. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/mixins/configure_mixin.py +0 -0
  390. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/mixins/entry_mixin.py +0 -0
  391. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/mixins/font_mixin.py +0 -0
  392. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/mixins/icon_mixin.py +0 -0
  393. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/mixins/localization_mixin.py +0 -0
  394. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/mixins/signal_mixin.py +0 -0
  395. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/mixins/validation_mixin.py +0 -0
  396. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/parts/__init__.py +0 -0
  397. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/parts/numberentry_part.py +0 -0
  398. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/parts/spinnerentry_part.py +0 -0
  399. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/__init__.py +0 -0
  400. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/badge.py +0 -0
  401. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/button.py +0 -0
  402. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/card.py +0 -0
  403. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/checkbutton.py +0 -0
  404. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/checktoggle.py +0 -0
  405. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/combobox.py +0 -0
  406. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/entry.py +0 -0
  407. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/frame.py +0 -0
  408. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/gridframe.py +0 -0
  409. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/label.py +0 -0
  410. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/labelframe.py +0 -0
  411. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/menubutton.py +0 -0
  412. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/notebook.py +0 -0
  413. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/optionmenu.py +0 -0
  414. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/packframe.py +0 -0
  415. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/panedwindow.py +0 -0
  416. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/progressbar.py +0 -0
  417. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/radiobutton.py +0 -0
  418. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/radiotoggle.py +0 -0
  419. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/scale.py +0 -0
  420. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/scrollbar.py +0 -0
  421. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/separator.py +0 -0
  422. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/sizegrip.py +0 -0
  423. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/spinbox.py +0 -0
  424. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/switch.py +0 -0
  425. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/primitives/treeview.py +0 -0
  426. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack/widgets/types.py +0 -0
  427. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack.egg-info/dependency_links.txt +0 -0
  428. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack.egg-info/entry_points.txt +0 -0
  429. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack.egg-info/requires.txt +0 -0
  430. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/src/bootstack.egg-info/top_level.txt +0 -0
  431. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/tests/test_togglegroup.py +0 -0
  432. {bootstack-0.1.0a5 → bootstack-0.1.0a7}/tests/test_variables.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bootstack
3
- Version: 0.1.0a5
3
+ Version: 0.1.0a7
4
4
  Summary: A full UI framework for Python desktop apps built on tkinter — rich widgets, theming, and application structure out of the box.
5
5
  Author-email: Israel Dryer <israel.dryer@gmail.com>
6
6
  License-Expression: MIT
@@ -150,7 +150,7 @@ bs.Button(app, text="+1", command=lambda: counter.set(counter.get() + 1))
150
150
 
151
151
  ## Features
152
152
 
153
- - **Application scaffolding** — `App` for blank windows, `AppShell` for toolbar + sidebar + page-stack apps, frameless windows with custom chrome
153
+ - **Application scaffolding** — `App` for blank windows, `AppShell` for toolbar + sidebar + page-stack apps, undecorated windows with custom chrome
154
154
  - **60+ themed widgets** — ttk-derived primitives plus higher-level composites (TableView, Calendar, DateEntry, Form, FloodGauge, Meter, ToggleGroup, PageStack, Toast, Tooltip, and more)
155
155
  - **9 dialogs** — Message, Query, ColorChooser, ColorDropper, DateDialog, FontDialog, FilterDialog, FormDialog, plus a `Dialog` base
156
156
  - **Layout containers** — `PackFrame` and `GridFrame` for declarative layouts; `ScrollView`, `PanedWindow`, `Accordion`, `Card`, `Expander`
@@ -116,7 +116,7 @@ bs.Button(app, text="+1", command=lambda: counter.set(counter.get() + 1))
116
116
 
117
117
  ## Features
118
118
 
119
- - **Application scaffolding** — `App` for blank windows, `AppShell` for toolbar + sidebar + page-stack apps, frameless windows with custom chrome
119
+ - **Application scaffolding** — `App` for blank windows, `AppShell` for toolbar + sidebar + page-stack apps, undecorated windows with custom chrome
120
120
  - **60+ themed widgets** — ttk-derived primitives plus higher-level composites (TableView, Calendar, DateEntry, Form, FloodGauge, Meter, ToggleGroup, PageStack, Toast, Tooltip, and more)
121
121
  - **9 dialogs** — Message, Query, ColorChooser, ColorDropper, DateDialog, FontDialog, FilterDialog, FormDialog, plus a `Dialog` base
122
122
  - **Layout containers** — `PackFrame` and `GridFrame` for declarative layouts; `ScrollView`, `PanedWindow`, `Accordion`, `Card`, `Expander`
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "bootstack"
7
- version = "0.1.0a5"
7
+ version = "0.1.0a7"
8
8
  description = "A full UI framework for Python desktop apps built on tkinter — rich widgets, theming, and application structure out of the box."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -82,7 +82,7 @@ where = ["src"]
82
82
  ]
83
83
 
84
84
  [tool.bumpversion]
85
- current_version = "0.1.0a5"
85
+ current_version = "0.1.0a7"
86
86
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)((?P<pre>a|b|rc)(?P<pre_n>\\d+))?"
87
87
  serialize = [
88
88
  "{major}.{minor}.{patch}{pre}{pre_n}",
@@ -45,11 +45,12 @@ from ttkbootstrap_icons_bs import BootstrapIcon # noqa: E402
45
45
  # (see constants.py which re-exports from core.constants)
46
46
 
47
47
  if TYPE_CHECKING:
48
- from bootstack.api.menu import MenuManager, create_menu
48
+ from bootstack.api.menu import MenuManager, create_menu, create_menu_items
49
49
  from bootstack.api.app import App, AppShell, App as Window, Toplevel, AppSettings, get_app_settings, get_current_app, Shortcuts, Shortcut, get_shortcuts
50
50
  from bootstack.api.style import (
51
51
  Font,
52
52
  Style,
53
+ Typography,
53
54
  get_style,
54
55
  get_style_builder,
55
56
  get_theme,
@@ -58,6 +59,7 @@ if TYPE_CHECKING:
58
59
  toggle_theme,
59
60
  get_theme_color,
60
61
  get_themes,
62
+ register_user_theme,
61
63
  )
62
64
  from bootstack.api.widgets import (
63
65
  Button,
@@ -80,6 +82,8 @@ if TYPE_CHECKING:
80
82
  Label,
81
83
  LabelFrame,
82
84
  LabeledScale,
85
+ ListItem,
86
+ ListView,
83
87
  MenuBar,
84
88
  MenuButton,
85
89
  Meter,
@@ -153,15 +157,16 @@ _MODULE_EXPORTS = {
153
157
  # Application & Windows (includes menu and shortcuts)
154
158
  "bootstack.api.app": [
155
159
  "App", "AppShell", "Toplevel", "Window", "AppSettings", "get_app_settings", "get_current_app",
156
- "MenuManager", "create_menu",
160
+ "MenuManager", "create_menu", "create_menu_items",
157
161
  "Shortcuts", "Shortcut", "get_shortcuts",
158
162
  ],
159
163
  # Style & Theming
160
164
  "bootstack.api.style": [
161
- "BootstrapIcon", "Font", "Style",
165
+ "BootstrapIcon", "Font", "Style", "Typography",
162
166
  "get_style", "get_style_builder", "get_theme",
163
167
  "get_theme_provider", "set_theme", "get_theme_color",
164
168
  "toggle_theme", "get_themes",
169
+ "register_user_theme",
165
170
  ],
166
171
  # Widgets
167
172
  "bootstack.api.widgets": [
@@ -173,7 +178,7 @@ _MODULE_EXPORTS = {
173
178
  "RadioToggle",
174
179
  "Calendar", "ContextMenu", "ContextMenuItem", "DateEntry",
175
180
  "Accordion", "DropdownButton", "Expander", "Field", "FieldOptions", "FloodGauge", "Form",
176
- "GridFrame", "LabeledScale", "MenuBar", "Meter",
181
+ "GridFrame", "LabeledScale", "ListItem", "ListView", "MenuBar", "Meter",
177
182
  "SideNav", "SideNavItem", "SideNavGroup",
178
183
  "SideNavHeader", "SideNavSeparator",
179
184
  "NumericEntry", "PackFrame", "PageStack",
@@ -64,7 +64,7 @@ from bootstack.api.widgets import (
64
64
  )
65
65
  from bootstack.runtime.app import App, App as Window
66
66
  from bootstack.runtime.toplevel import Toplevel
67
- from bootstack.runtime.menu import MenuManager, create_menu
67
+ from bootstack.runtime.menu import MenuManager, create_menu, create_menu_items
68
68
 
69
69
  __all__ = [
70
70
  "BootstrapIcon",
@@ -122,6 +122,7 @@ __all__ = [
122
122
  "get_theme_provider",
123
123
  "get_theme_color",
124
124
  "create_menu",
125
+ "create_menu_items",
125
126
  "TK_WIDGETS",
126
127
  "TTK_WIDGETS",
127
128
  ]
@@ -0,0 +1,7 @@
1
+ """Public menu-related API surface."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from bootstack.runtime.menu import MenuManager, create_menu, create_menu_items
6
+
7
+ __all__ = ["MenuManager", "create_menu", "create_menu_items"]
@@ -6,12 +6,14 @@ from ttkbootstrap_icons_bs import BootstrapIcon
6
6
 
7
7
  from bootstack.style.style import (Style, get_style, get_style_builder, get_theme, get_theme_color,
8
8
  get_theme_provider, set_theme, toggle_theme, get_themes)
9
- from bootstack.style.typography import Font
9
+ from bootstack.style.theme_provider import register_user_theme
10
+ from bootstack.style.typography import Font, Typography
10
11
 
11
12
  __all__ = [
12
13
  "BootstrapIcon",
13
14
  "Font",
14
15
  "Style",
16
+ "Typography",
15
17
  "get_style",
16
18
  "get_style_builder",
17
19
  "get_theme",
@@ -20,4 +22,5 @@ __all__ = [
20
22
  "get_theme_provider",
21
23
  "get_theme_color",
22
24
  "get_themes",
25
+ "register_user_theme",
23
26
  ]
@@ -35,6 +35,7 @@ from bootstack.widgets.primitives.gridframe import GridFrame
35
35
  from bootstack.widgets.primitives.label import Label
36
36
  from bootstack.widgets.primitives.labelframe import LabelFrame
37
37
  from bootstack.widgets.composites.labeledscale import LabeledScale
38
+ from bootstack.widgets.composites.list import ListItem, ListView
38
39
  from bootstack.widgets.composites.menubar import MenuBar
39
40
  from bootstack.widgets.primitives.menubutton import MenuButton
40
41
  from bootstack.widgets.composites.meter import Meter
@@ -93,6 +94,8 @@ __all__ = [
93
94
  "Label",
94
95
  "LabelFrame",
95
96
  "LabeledScale",
97
+ "ListItem",
98
+ "ListView",
96
99
  "MenuBar",
97
100
  "SideNav",
98
101
  "SideNavItem",
@@ -20,6 +20,7 @@ Usage:
20
20
  bootstack list themes List available themes
21
21
  bootstack doctor Diagnose project and environment health
22
22
  bootstack gallery Launch the widget gallery
23
+ bootstack icons Browse Bootstrap Icons
23
24
  """
24
25
 
25
26
  from __future__ import annotations
@@ -28,7 +29,7 @@ import argparse
28
29
  import sys
29
30
  from typing import Sequence
30
31
 
31
- from bootstack.cli import add, build, doctor, list_cmd, promote, run, start
32
+ from bootstack.cli import add, build, doctor, icons, list_cmd, promote, run, start
32
33
  from bootstack.cli.demo import run_demo
33
34
 
34
35
 
@@ -50,6 +51,7 @@ Examples:
50
51
  bootstack list themes List available themes
51
52
  bootstack doctor Diagnose project and environment health
52
53
  bootstack gallery Launch the widget gallery
54
+ bootstack icons Browse Bootstrap Icons
53
55
 
54
56
  For more information on a command:
55
57
  bootstack <command> --help
@@ -82,6 +84,7 @@ For more information on a command:
82
84
  add.add_parser(subparsers)
83
85
  list_cmd.add_parser(subparsers)
84
86
  doctor.add_parser(subparsers)
87
+ icons.add_parser(subparsers)
85
88
 
86
89
  # Gallery command
87
90
  gallery_parser = subparsers.add_parser(
@@ -305,7 +305,7 @@ def run_add_theme(args: argparse.Namespace) -> None:
305
305
  print()
306
306
  print(" from bootstack.style.theme_provider import register_user_theme")
307
307
  print(f' register_user_theme("{theme_name}", "themes/{theme_name}.json")')
308
- print(f' app = ttk.App(theme="{theme_name}")')
308
+ print(f' app = bs.App(theme="{theme_name}")')
309
309
 
310
310
 
311
311
  def run_add_i18n(args: argparse.Namespace) -> None:
@@ -340,7 +340,7 @@ def run_add_i18n(args: argparse.Namespace) -> None:
340
340
  print("Next steps:")
341
341
  print(" 1. Add translatable strings to your .po files")
342
342
  print(" 2. Compile with: msgfmt locales/<lang>/LC_MESSAGES/messages.po -o locales/<lang>/LC_MESSAGES/messages.mo")
343
- print(" 3. Use translations in code: ttk.mc('Hello')")
343
+ print(" 3. Use translations in code: bs.L('Hello')")
344
344
 
345
345
 
346
346
  _BASE_SHADES = {
@@ -0,0 +1,28 @@
1
+ """Icons command — delegates to the ttkbootstrap-icons browser."""
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import subprocess
6
+ import sys
7
+ from pathlib import Path
8
+
9
+
10
+ def add_parser(subparsers: argparse._SubParsersAction) -> None:
11
+ parser = subparsers.add_parser(
12
+ "icons",
13
+ help="Browse Bootstrap Icons available in bootstack",
14
+ description=(
15
+ "Launch the Bootstrap Icons browser.\n\n"
16
+ "Delegates to the ttkbootstrap-icons tool bundled with the "
17
+ "ttkbootstrap_icons_bs package. Any icon name shown there can "
18
+ "be used as the icon= parameter on any bootstack widget."
19
+ ),
20
+ )
21
+ parser.set_defaults(func=lambda args: run_icons())
22
+
23
+
24
+ def run_icons() -> None:
25
+ scripts = Path(sys.executable).parent
26
+ name = "ttkbootstrap-icons.exe" if sys.platform == "win32" else "ttkbootstrap-icons"
27
+ result = subprocess.run([str(scripts / name)])
28
+ sys.exit(result.returncode)
@@ -429,8 +429,8 @@ class IntlFormatter:
429
429
  opt = self._normalize_date_spec(spec)
430
430
  typ = opt["type"]
431
431
  if typ == "custom": return format_time(t, format=opt["pattern"], locale=self.locale)
432
- if typ == "longTime": return format_time(t, "long", self.locale)
433
- if typ == "shortTime": return format_time(t, "short", self.locale)
432
+ if typ == "longTime": return format_time(t, "long", locale=self.locale)
433
+ if typ == "shortTime": return format_time(t, "short", locale=self.locale)
434
434
  if typ == "hour": return format_time(t, "H", self.locale)
435
435
  if typ == "minute": return format_time(t, "m", self.locale)
436
436
  if typ == "second": return format_time(t, "s", self.locale)
@@ -451,8 +451,8 @@ class IntlFormatter:
451
451
  if typ == "shortDateShortTime": return format_datetime(dt, "short", self.locale)
452
452
  if typ == "longDate": return format_date(dt.date(), "long", self.locale)
453
453
  if typ == "shortDate": return format_date(dt.date(), "short", self.locale)
454
- if typ == "longTime": return format_time(dt.time(), "long", self.locale)
455
- if typ == "shortTime": return format_time(dt.time(), "short", self.locale)
454
+ if typ == "longTime": return format_time(dt.time(), "long", locale=self.locale)
455
+ if typ == "shortTime": return format_time(dt.time(), "short", locale=self.locale)
456
456
  if typ == "monthAndDay": return format_date(dt.date(), "MMMM d", self.locale)
457
457
  if typ == "monthAndYear": return format_date(dt.date(), "MMMM y", self.locale)
458
458
  if typ == "quarterAndYear": return format_date(dt.date(), "QQQ y", self.locale)
@@ -34,6 +34,10 @@ from typing import Any, Dict, List, Optional, Union, Sequence
34
34
  from bootstack.datasource.base import BaseDataSource
35
35
  from bootstack.datasource.types import Primitive, Record
36
36
 
37
+ # Internal column names — reserved by SqliteDataSource, never exposed to user data.
38
+ _ROW_ID = "_bs_row_id"
39
+ _ROW_SEL = "_bs_selected"
40
+
37
41
 
38
42
  class SqliteDataSource(BaseDataSource):
39
43
  """SQLite-backed data manager with pagination, filtering, sorting, and CRUD operations.
@@ -61,8 +65,9 @@ class SqliteDataSource(BaseDataSource):
61
65
  - The database connection persists for the lifetime of the object
62
66
  - Close the connection explicitly with conn.close() if needed
63
67
  - Schema is inferred from first record's data types
64
- - 'id' field is automatically set as PRIMARY KEY
65
- - 'selected' field is added automatically for selection tracking
68
+ - An internal row-identity column (_bs_row_id) is added automatically as PRIMARY KEY
69
+ - An internal selection column (_bs_selected) is added automatically for selection tracking
70
+ - These internal columns are filtered out of the display column list automatically
66
71
  """
67
72
 
68
73
  def __init__(self, name: str = ":memory:", page_size: int = 10):
@@ -121,12 +126,12 @@ class SqliteDataSource(BaseDataSource):
121
126
  using_dicts = True
122
127
 
123
128
  if using_dicts:
124
- # Ensure helper columns
129
+ # Ensure internal helper columns
125
130
  for i, record in enumerate(records):
126
- if "id" not in record:
127
- record["id"] = i
128
- if "selected" not in record:
129
- record["selected"] = 0
131
+ if _ROW_ID not in record:
132
+ record[_ROW_ID] = i
133
+ if _ROW_SEL not in record:
134
+ record[_ROW_SEL] = 0
130
135
 
131
136
  self._columns = list(records[0].keys())
132
137
  col_types = {col: self._infer_type(records[0][col]) for col in self._columns}
@@ -136,25 +141,25 @@ class SqliteDataSource(BaseDataSource):
136
141
  keys = list(column_keys or [])
137
142
  if not keys:
138
143
  keys = [str(i) for i in range(len(first))]
139
- need_id = "id" not in keys
140
- need_selected = "selected" not in keys
144
+ need_id = _ROW_ID not in keys
145
+ need_sel = _ROW_SEL not in keys
141
146
  if need_id:
142
- keys.append("id")
143
- if need_selected:
144
- keys.append("selected")
147
+ keys.append(_ROW_ID)
148
+ if need_sel:
149
+ keys.append(_ROW_SEL)
145
150
  self._columns = keys
146
151
 
147
152
  # Infer types from first row (pad to keys length)
148
153
  padded_first = list(first) + [None] * (len(keys) - len(first))
149
- if need_id and "id" in keys:
150
- padded_first[keys.index("id")] = 0
151
- if need_selected and "selected" in keys:
152
- padded_first[keys.index("selected")] = 0
154
+ if need_id and _ROW_ID in keys:
155
+ padded_first[keys.index(_ROW_ID)] = 0
156
+ if need_sel and _ROW_SEL in keys:
157
+ padded_first[keys.index(_ROW_SEL)] = 0
153
158
  col_types = {col: self._infer_type(padded_first[idx]) for idx, col in enumerate(keys)}
154
159
 
155
160
  rows_to_insert = []
156
- id_idx = keys.index("id") if "id" in keys else None
157
- sel_idx = keys.index("selected") if "selected" in keys else None
161
+ id_idx = keys.index(_ROW_ID) if _ROW_ID in keys else None
162
+ sel_idx = keys.index(_ROW_SEL) if _ROW_SEL in keys else None
158
163
  value_len = len(keys)
159
164
  for i, row in enumerate(records):
160
165
  base_values = list(row[: value_len]) + [""] * (value_len - len(row))
@@ -165,7 +170,7 @@ class SqliteDataSource(BaseDataSource):
165
170
  rows_to_insert.append(tuple(base_values))
166
171
 
167
172
  col_definitions = ", ".join(
168
- f"{self._quote_identifier(col)} {col_types[col]}" + (" PRIMARY KEY" if col == "id" else "")
173
+ f"{self._quote_identifier(col)} {col_types[col]}" + (" PRIMARY KEY" if col == _ROW_ID else "")
169
174
  for col in self._columns
170
175
  )
171
176
  placeholders = ", ".join("?" for _ in self._columns)
@@ -241,11 +246,11 @@ class SqliteDataSource(BaseDataSource):
241
246
 
242
247
  def create_record(self, record: Dict[str, Any]) -> int:
243
248
  """Create new record and return its ID."""
244
- if "id" not in record:
245
- record["id"] = self._generate_new_id()
249
+ if _ROW_ID not in record:
250
+ record[_ROW_ID] = self._generate_new_id()
246
251
 
247
- if "selected" not in record:
248
- record["selected"] = 0
252
+ if _ROW_SEL not in record:
253
+ record[_ROW_SEL] = 0
249
254
 
250
255
  # Ensure table exists (handles empty datasources)
251
256
  self._ensure_table_for_record(record)
@@ -257,11 +262,11 @@ class SqliteDataSource(BaseDataSource):
257
262
 
258
263
  with self.conn:
259
264
  self.conn.execute(f"INSERT INTO {self._table} ({cols}) VALUES ({placeholders})", values)
260
- return record["id"]
265
+ return record[_ROW_ID]
261
266
 
262
267
  def read_record(self, record_id: Any) -> Optional[Dict[str, Any]]:
263
268
  """Retrieve single record by ID."""
264
- cursor = self.conn.execute(f"SELECT * FROM {self._table} WHERE id = ?", (record_id,))
269
+ cursor = self.conn.execute(f"SELECT * FROM {self._table} WHERE {_ROW_ID} = ?", (record_id,))
265
270
  row = cursor.fetchone()
266
271
  return dict(row) if row else None
267
272
 
@@ -272,19 +277,19 @@ class SqliteDataSource(BaseDataSource):
272
277
  set_clause = ", ".join(f"{self._quote_identifier(k)} = ?" for k in updates)
273
278
  values = tuple(updates.values()) + (record_id,)
274
279
  with self.conn:
275
- cur = self.conn.execute(f"UPDATE {self._table} SET {set_clause} WHERE id = ?", values)
280
+ cur = self.conn.execute(f"UPDATE {self._table} SET {set_clause} WHERE {_ROW_ID} = ?", values)
276
281
  return cur.rowcount > 0
277
282
 
278
283
  def delete_record(self, record_id: Any) -> bool:
279
284
  """Delete record by ID."""
280
285
  with self.conn:
281
- cur = self.conn.execute(f"DELETE FROM {self._table} WHERE id = ?", (record_id,))
286
+ cur = self.conn.execute(f"DELETE FROM {self._table} WHERE {_ROW_ID} = ?", (record_id,))
282
287
  return cur.rowcount > 0
283
288
 
284
289
  def _generate_new_id(self) -> int:
285
290
  """Generate next available integer ID."""
286
291
  try:
287
- cursor = self.conn.execute(f"SELECT MAX(id) FROM {self._table}")
292
+ cursor = self.conn.execute(f"SELECT MAX({_ROW_ID}) FROM {self._table}")
288
293
  max_id = cursor.fetchone()[0]
289
294
  except Exception:
290
295
  max_id = 0
@@ -301,23 +306,23 @@ class SqliteDataSource(BaseDataSource):
301
306
  pass
302
307
 
303
308
  cols = list(self._columns) if self._columns else list(record.keys())
304
- if "id" not in cols:
305
- cols.append("id")
306
- if "selected" not in cols:
307
- cols.append("selected")
309
+ if _ROW_ID not in cols:
310
+ cols.append(_ROW_ID)
311
+ if _ROW_SEL not in cols:
312
+ cols.append(_ROW_SEL)
308
313
  self._columns = cols
309
314
 
310
315
  col_types = {}
311
316
  for c in cols:
312
- if c == "id":
317
+ if c == _ROW_ID:
313
318
  col_types[c] = "INTEGER"
314
- elif c == "selected":
319
+ elif c == _ROW_SEL:
315
320
  col_types[c] = "INTEGER"
316
321
  else:
317
322
  col_types[c] = self._infer_type(record.get(c))
318
323
 
319
324
  col_definitions = ", ".join(
320
- f"{self._quote_identifier(col)} {col_types[col]}" + (" PRIMARY KEY" if col == "id" else "")
325
+ f"{self._quote_identifier(col)} {col_types[col]}" + (" PRIMARY KEY" if col == _ROW_ID else "")
321
326
  for col in cols
322
327
  )
323
328
  with self.conn:
@@ -337,40 +342,40 @@ class SqliteDataSource(BaseDataSource):
337
342
  """Select all records (optionally only current page)."""
338
343
  self._ensure_selected_column()
339
344
  if current_page_only:
340
- ids = [row["id"] for row in self.get_page()]
345
+ ids = [row[_ROW_ID] for row in self.get_page()]
341
346
  if not ids:
342
347
  return 0
343
348
  placeholders = ", ".join("?" for _ in ids)
344
- query = f"UPDATE {self._table} SET selected = 1 WHERE id IN ({placeholders})"
349
+ query = f"UPDATE {self._table} SET {_ROW_SEL} = 1 WHERE {_ROW_ID} IN ({placeholders})"
345
350
  with self.conn:
346
351
  cur = self.conn.execute(query, ids)
347
352
  return cur.rowcount
348
353
  else:
349
354
  with self.conn:
350
- cur = self.conn.execute(f"UPDATE {self._table} SET selected = 1")
355
+ cur = self.conn.execute(f"UPDATE {self._table} SET {_ROW_SEL} = 1")
351
356
  return cur.rowcount
352
357
 
353
358
  def unselect_all(self, current_page_only: bool = False) -> int:
354
359
  """Unselect all records (optionally only current page)."""
355
360
  self._ensure_selected_column()
356
361
  if current_page_only:
357
- ids = [row["id"] for row in self.get_page()]
362
+ ids = [row[_ROW_ID] for row in self.get_page()]
358
363
  if not ids:
359
364
  return 0
360
365
  placeholders = ", ".join("?" for _ in ids)
361
- query = f"UPDATE {self._table} SET selected = 0 WHERE id IN ({placeholders})"
366
+ query = f"UPDATE {self._table} SET {_ROW_SEL} = 0 WHERE {_ROW_ID} IN ({placeholders})"
362
367
  with self.conn:
363
368
  cur = self.conn.execute(query, ids)
364
369
  return cur.rowcount
365
370
  else:
366
371
  with self.conn:
367
- cur = self.conn.execute(f"UPDATE {self._table} SET selected = 0")
372
+ cur = self.conn.execute(f"UPDATE {self._table} SET {_ROW_SEL} = 0")
368
373
  return cur.rowcount
369
374
 
370
375
  def get_selected(self, page: Optional[int] = None) -> List[Dict[str, Any]]:
371
376
  """Get selected records, optionally paginated."""
372
377
  self._ensure_selected_column()
373
- query = f"SELECT * FROM {self._table} WHERE selected = 1"
378
+ query = f"SELECT * FROM {self._table} WHERE {_ROW_SEL} = 1"
374
379
 
375
380
  if page is not None:
376
381
  offset = page * self.page_size
@@ -380,28 +385,30 @@ class SqliteDataSource(BaseDataSource):
380
385
  return [dict(row) for row in cursor.fetchall()]
381
386
 
382
387
  def _ensure_selected_column(self):
383
- """Add 'selected' column to table if it doesn't exist."""
384
- if "selected" not in self._columns:
388
+ """Add selection column to table if it doesn't exist."""
389
+ if _ROW_SEL not in self._columns:
385
390
  with self.conn:
386
- self.conn.execute(f"ALTER TABLE {self._table} ADD COLUMN selected INTEGER DEFAULT 0")
387
- self._columns.append("selected")
391
+ self.conn.execute(f"ALTER TABLE {self._table} ADD COLUMN {_ROW_SEL} INTEGER DEFAULT 0")
392
+ self._columns.append(_ROW_SEL)
388
393
 
389
394
  def selected_count(self) -> int:
390
395
  """Get total number of selected records."""
391
396
  self._ensure_selected_column()
392
- query = f"SELECT COUNT(*) FROM {self._table} WHERE selected = 1"
397
+ query = f"SELECT COUNT(*) FROM {self._table} WHERE {_ROW_SEL} = 1"
393
398
  return self.conn.execute(query).fetchone()[0]
394
399
 
395
400
  def _set_selected_flag(self, record_id: Any, flag: int) -> bool:
396
401
  """Set selection flag for record by ID."""
397
- if "selected" not in self._columns:
398
- # Add selected column if it doesn't exist
402
+ if _ROW_SEL not in self._columns:
399
403
  with self.conn:
400
- self.conn.execute(f"ALTER TABLE {self._table} ADD COLUMN selected INTEGER DEFAULT 0")
401
- self._columns.append("selected")
404
+ self.conn.execute(f"ALTER TABLE {self._table} ADD COLUMN {_ROW_SEL} INTEGER DEFAULT 0")
405
+ self._columns.append(_ROW_SEL)
402
406
 
403
407
  with self.conn:
404
- cur = self.conn.execute(f"UPDATE {self._table} SET selected = ? WHERE id = ?", (flag, record_id))
408
+ cur = self.conn.execute(
409
+ f"UPDATE {self._table} SET {_ROW_SEL} = ? WHERE {_ROW_ID} = ?",
410
+ (flag, record_id),
411
+ )
405
412
  return cur.rowcount > 0
406
413
 
407
414
  # === DATA EXPORT ===
@@ -411,7 +418,7 @@ class SqliteDataSource(BaseDataSource):
411
418
  self._ensure_selected_column()
412
419
  query = f"SELECT * FROM {self._table}"
413
420
  if not include_all:
414
- query += " WHERE selected = 1"
421
+ query += f" WHERE {_ROW_SEL} = 1"
415
422
 
416
423
  cursor = self.conn.execute(query)
417
424
  rows = cursor.fetchall()
@@ -202,13 +202,16 @@ class DateDialog:
202
202
  show_week_numbers: bool = False,
203
203
  hide_window_chrome: bool = False,
204
204
  close_on_click_outside: bool = False,
205
+ selection_mode: Literal["single", "range"] = "single",
206
+ start_date: Optional[date | datetime | str] = None,
207
+ end_date: Optional[date | datetime | str] = None,
205
208
  ) -> None:
206
209
  """Create a date selection dialog.
207
210
 
208
211
  Args:
209
212
  master: Parent widget; positions dialog relative to it when set.
210
213
  title: Dialog window title text.
211
- initial_date: Initial date shown; defaults to `date.today()`.
214
+ initial_date: Initial date shown in single mode; defaults to `date.today()`.
212
215
  first_weekday: First weekday index (0=Monday, 6=Sunday).
213
216
  accent: Calendar accent token (e.g., `primary`, `secondary`).
214
217
  disabled_dates: Iterable of dates to disable selection.
@@ -221,6 +224,11 @@ class DateDialog:
221
224
  decorations using override-redirect.
222
225
  close_on_click_outside: When True, closes the dialog when focus
223
226
  moves outside (popover mode).
227
+ selection_mode: `'single'` for a single date (default) or `'range'`
228
+ for a start/end date range. In range mode `result` is a
229
+ `tuple[date, date]` rather than a `date`.
230
+ start_date: Initial range start date (range mode only).
231
+ end_date: Initial range end date (range mode only).
224
232
  """
225
233
  self._master = master
226
234
  self._first_weekday = first_weekday
@@ -233,6 +241,9 @@ class DateDialog:
233
241
  self._show_week_numbers = show_week_numbers
234
242
  self._hide_window_chrome = hide_window_chrome
235
243
  self._close_on_click_outside = close_on_click_outside
244
+ self._selection_mode = selection_mode
245
+ self._start_date = start_date
246
+ self._end_date = end_date
236
247
 
237
248
  self._picker: Optional[_DialogCalendar] = None
238
249
 
@@ -253,7 +264,9 @@ class DateDialog:
253
264
 
254
265
  self._picker = _DialogCalendar(
255
266
  master=container,
256
- start_date=self._initial_date,
267
+ selection_mode=self._selection_mode,
268
+ start_date=self._start_date if self._selection_mode == "range" else self._initial_date,
269
+ end_date=self._end_date if self._selection_mode == "range" else None,
257
270
  first_weekday=self._first_weekday,
258
271
  accent=self._accent,
259
272
  disabled_dates=self._disabled_dates,
@@ -275,16 +288,29 @@ class DateDialog:
275
288
  return
276
289
 
277
290
  payload = getattr(event, "data", None)
278
- selected = None
279
- if isinstance(payload, dict):
280
- selected = payload.get("date") or payload.get("result")
281
291
 
282
- selected = selected or self._picker.get()
283
- if selected is None:
284
- return
292
+ if self._selection_mode == "range":
293
+ range_data = None
294
+ if isinstance(payload, dict):
295
+ range_data = payload.get("range")
296
+ if range_data is None:
297
+ range_data = self._picker.get_range()
298
+ start, end = range_data if range_data else (None, None)
299
+ # Wait for both dates before confirming
300
+ if start is None or end is None:
301
+ return
302
+ result: date | Tuple[date, date] = (start, end)
303
+ else:
304
+ selected = None
305
+ if isinstance(payload, dict):
306
+ selected = payload.get("date") or payload.get("result")
307
+ selected = selected or self._picker.get()
308
+ if selected is None:
309
+ return
310
+ result = selected
285
311
 
286
- self._dialog.result = selected
287
- self._emit_result(selected, confirmed=True)
312
+ self._dialog.result = result
313
+ self._emit_result(result, confirmed=True)
288
314
  if self._dialog.toplevel:
289
315
  top = self._dialog.toplevel
290
316
  try:
@@ -354,8 +380,8 @@ class DateDialog:
354
380
  )
355
381
 
356
382
  @property
357
- def result(self) -> Optional[date]:
358
- """The selected date, or None if cancelled."""
383
+ def result(self) -> Optional[Union[date, Tuple[date, date]]]:
384
+ """The selected date (single mode) or ``(start, end)`` tuple (range mode), or None if cancelled."""
359
385
  return self._dialog.result
360
386
 
361
387
  def on_result(self, callback: Callable[[date], None]) -> Optional[str]: