bootstack 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (471) hide show
  1. bootstack/__init__.py +157 -0
  2. bootstack/__main__.py +5 -0
  3. bootstack/_core/__init__.py +21 -0
  4. bootstack/_core/capabilities/__init__.py +45 -0
  5. bootstack/_core/capabilities/after.py +103 -0
  6. bootstack/_core/capabilities/bind.py +192 -0
  7. bootstack/_core/capabilities/bindtags.py +112 -0
  8. bootstack/_core/capabilities/busy.py +72 -0
  9. bootstack/_core/capabilities/clipboard.py +89 -0
  10. bootstack/_core/capabilities/focus.py +118 -0
  11. bootstack/_core/capabilities/grab.py +65 -0
  12. bootstack/_core/capabilities/grid.py +211 -0
  13. bootstack/_core/capabilities/localization.py +231 -0
  14. bootstack/_core/capabilities/pack.py +140 -0
  15. bootstack/_core/capabilities/place.py +113 -0
  16. bootstack/_core/capabilities/selection.py +136 -0
  17. bootstack/_core/capabilities/signals.py +244 -0
  18. bootstack/_core/capabilities/winfo.py +315 -0
  19. bootstack/_core/colorutils.py +234 -0
  20. bootstack/_core/exceptions.py +25 -0
  21. bootstack/_core/images.py +463 -0
  22. bootstack/_core/mixins/__init__.py +1 -0
  23. bootstack/_core/mixins/ttk_state.py +35 -0
  24. bootstack/_core/mixins/widget.py +132 -0
  25. bootstack/_core/paths.py +49 -0
  26. bootstack/_core/publisher.py +149 -0
  27. bootstack/_core/variables.py +62 -0
  28. bootstack/_runtime/__init__.py +3 -0
  29. bootstack/_runtime/app.py +930 -0
  30. bootstack/_runtime/base_window.py +945 -0
  31. bootstack/_runtime/events.py +399 -0
  32. bootstack/_runtime/shortcuts.py +496 -0
  33. bootstack/_runtime/tk_patch.py +43 -0
  34. bootstack/_runtime/toplevel.py +276 -0
  35. bootstack/_runtime/utility.py +457 -0
  36. bootstack/_runtime/visual_focus.py +240 -0
  37. bootstack/_runtime/window_utilities.py +1123 -0
  38. bootstack/assets/__init__.py +21 -0
  39. bootstack/assets/bootstack.ico +0 -0
  40. bootstack/assets/bootstack.png +0 -0
  41. bootstack/assets/elements/__init__.py +0 -0
  42. bootstack/assets/elements/badge-pill.png +0 -0
  43. bootstack/assets/elements/badge-square.png +0 -0
  44. bootstack/assets/elements/button-compact.png +0 -0
  45. bootstack/assets/elements/button-default.png +0 -0
  46. bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
  47. bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
  48. bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
  49. bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
  50. bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
  51. bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
  52. bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
  53. bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
  54. bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
  55. bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
  56. bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
  57. bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
  58. bootstack/assets/elements/card.png +0 -0
  59. bootstack/assets/elements/checkbox-checked.png +0 -0
  60. bootstack/assets/elements/checkbox-indeterminate.png +0 -0
  61. bootstack/assets/elements/checkbox-unchecked.png +0 -0
  62. bootstack/assets/elements/field.png +0 -0
  63. bootstack/assets/elements/input-addon-compact.png +0 -0
  64. bootstack/assets/elements/input-addon-default.png +0 -0
  65. bootstack/assets/elements/input-compact.png +0 -0
  66. bootstack/assets/elements/input-default.png +0 -0
  67. bootstack/assets/elements/list-item-separated.png +0 -0
  68. bootstack/assets/elements/list-item.png +0 -0
  69. bootstack/assets/elements/listrow-compact.png +0 -0
  70. bootstack/assets/elements/listrow-default.png +0 -0
  71. bootstack/assets/elements/manifest.toml +361 -0
  72. bootstack/assets/elements/menu-item.png +0 -0
  73. bootstack/assets/elements/navitem-compact.png +0 -0
  74. bootstack/assets/elements/navitem-default.png +0 -0
  75. bootstack/assets/elements/progressbar-h-compact.png +0 -0
  76. bootstack/assets/elements/progressbar-h-default.png +0 -0
  77. bootstack/assets/elements/progressbar-v-compact.png +0 -0
  78. bootstack/assets/elements/progressbar-v-default.png +0 -0
  79. bootstack/assets/elements/radiobutton.png +0 -0
  80. bootstack/assets/elements/scrollbar-horizontal.png +0 -0
  81. bootstack/assets/elements/scrollbar-vertical.png +0 -0
  82. bootstack/assets/elements/slider-handle.png +0 -0
  83. bootstack/assets/elements/slider-track-h.png +0 -0
  84. bootstack/assets/elements/slider-track-v.png +0 -0
  85. bootstack/assets/elements/switch-off.png +0 -0
  86. bootstack/assets/elements/switch-on.png +0 -0
  87. bootstack/assets/elements/tab-h.png +0 -0
  88. bootstack/assets/elements/tab-v.png +0 -0
  89. bootstack/assets/icons/bootstrap.ttf +0 -0
  90. bootstack/assets/icons/glyphmap.json +2080 -0
  91. bootstack/assets/icons/icon_metrics.json +12470 -0
  92. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
  93. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +856 -0
  94. bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
  95. bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +878 -0
  96. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
  97. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +856 -0
  98. bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
  99. bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +856 -0
  100. bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
  101. bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +856 -0
  102. bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
  103. bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +878 -0
  104. bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
  105. bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +856 -0
  106. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
  107. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +856 -0
  108. bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
  109. bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +854 -0
  110. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
  111. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +845 -0
  112. bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
  113. bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +844 -0
  114. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
  115. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +917 -0
  116. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
  117. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +845 -0
  118. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
  119. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +844 -0
  120. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
  121. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +844 -0
  122. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
  123. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +845 -0
  124. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
  125. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +845 -0
  126. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
  127. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +845 -0
  128. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
  129. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +845 -0
  130. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
  131. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +845 -0
  132. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
  133. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +845 -0
  134. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
  135. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +845 -0
  136. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
  137. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +845 -0
  138. bootstack/cli/__init__.py +133 -0
  139. bootstack/cli/__main__.py +6 -0
  140. bootstack/cli/add.py +395 -0
  141. bootstack/cli/appicon.py +285 -0
  142. bootstack/cli/build.py +115 -0
  143. bootstack/cli/config.py +313 -0
  144. bootstack/cli/demo.py +564 -0
  145. bootstack/cli/dev.py +153 -0
  146. bootstack/cli/doctor.py +195 -0
  147. bootstack/cli/icons.py +98 -0
  148. bootstack/cli/promote.py +120 -0
  149. bootstack/cli/pyinstaller.py +268 -0
  150. bootstack/cli/run.py +95 -0
  151. bootstack/cli/start.py +117 -0
  152. bootstack/cli/templates/__init__.py +931 -0
  153. bootstack/clipboard.py +48 -0
  154. bootstack/constants.py +318 -0
  155. bootstack/data/README.md +615 -0
  156. bootstack/data/__init__.py +78 -0
  157. bootstack/data/_observable.py +276 -0
  158. bootstack/data/base.py +780 -0
  159. bootstack/data/file_source.py +367 -0
  160. bootstack/data/memory_source.py +450 -0
  161. bootstack/data/query.py +367 -0
  162. bootstack/data/readers.py +289 -0
  163. bootstack/data/sqlite_source.py +869 -0
  164. bootstack/data/types.py +354 -0
  165. bootstack/data/writers.py +232 -0
  166. bootstack/dev/__init__.py +36 -0
  167. bootstack/dev/_capture.py +141 -0
  168. bootstack/dev/_env.py +43 -0
  169. bootstack/dev/_registry.py +140 -0
  170. bootstack/dev/_reloader.py +351 -0
  171. bootstack/dev/_reset.py +50 -0
  172. bootstack/dev/_watcher.py +91 -0
  173. bootstack/dialogs/__init__.py +948 -0
  174. bootstack/dialogs/_impl/__init__.py +47 -0
  175. bootstack/dialogs/_impl/colorchooser.py +588 -0
  176. bootstack/dialogs/_impl/datedialog.py +450 -0
  177. bootstack/dialogs/_impl/dialog.py +594 -0
  178. bootstack/dialogs/_impl/filterdialog.py +358 -0
  179. bootstack/dialogs/_impl/fontdialog.py +364 -0
  180. bootstack/dialogs/_impl/formdialog.py +564 -0
  181. bootstack/dialogs/_impl/message.py +486 -0
  182. bootstack/dialogs/_impl/query.py +570 -0
  183. bootstack/errors.py +67 -0
  184. bootstack/events/__init__.py +111 -0
  185. bootstack/events/_event.py +135 -0
  186. bootstack/events/_payloads.py +539 -0
  187. bootstack/events/_subscription.py +38 -0
  188. bootstack/i18n/README.md +77 -0
  189. bootstack/i18n/__init__.py +23 -0
  190. bootstack/i18n/catalog.py +121 -0
  191. bootstack/i18n/intl_format.py +584 -0
  192. bootstack/i18n/msgcat.py +425 -0
  193. bootstack/i18n/specs.py +156 -0
  194. bootstack/images.py +563 -0
  195. bootstack/py.typed +1 -0
  196. bootstack/scheduling/__init__.py +11 -0
  197. bootstack/scheduling/_schedule.py +218 -0
  198. bootstack/shortcuts.py +21 -0
  199. bootstack/signals/README.md +98 -0
  200. bootstack/signals/__init__.py +10 -0
  201. bootstack/signals/integration.py +100 -0
  202. bootstack/signals/signal.py +353 -0
  203. bootstack/signals/types.py +6 -0
  204. bootstack/store.py +286 -0
  205. bootstack/streams/__init__.py +12 -0
  206. bootstack/streams/_stream.py +321 -0
  207. bootstack/style/__init__.py +38 -0
  208. bootstack/style/builders/__init__.py +51 -0
  209. bootstack/style/builders/badge.py +46 -0
  210. bootstack/style/builders/button.py +339 -0
  211. bootstack/style/builders/buttongroup.py +311 -0
  212. bootstack/style/builders/calendar.py +271 -0
  213. bootstack/style/builders/checkbutton.py +110 -0
  214. bootstack/style/builders/combobox.py +113 -0
  215. bootstack/style/builders/contextmenu.py +268 -0
  216. bootstack/style/builders/entry.py +82 -0
  217. bootstack/style/builders/expander.py +148 -0
  218. bootstack/style/builders/field.py +335 -0
  219. bootstack/style/builders/frame.py +50 -0
  220. bootstack/style/builders/label.py +28 -0
  221. bootstack/style/builders/labelframe.py +34 -0
  222. bootstack/style/builders/listview.py +369 -0
  223. bootstack/style/builders/menubar.py +91 -0
  224. bootstack/style/builders/menubutton.py +359 -0
  225. bootstack/style/builders/panedwindow.py +25 -0
  226. bootstack/style/builders/progressbar.py +67 -0
  227. bootstack/style/builders/radiobutton.py +99 -0
  228. bootstack/style/builders/scale.py +64 -0
  229. bootstack/style/builders/scrollbar.py +225 -0
  230. bootstack/style/builders/separator.py +49 -0
  231. bootstack/style/builders/sidenav.py +643 -0
  232. bootstack/style/builders/sizegrip.py +15 -0
  233. bootstack/style/builders/spinbox.py +119 -0
  234. bootstack/style/builders/switch.py +70 -0
  235. bootstack/style/builders/tabitem.py +204 -0
  236. bootstack/style/builders/togglegroup.py +294 -0
  237. bootstack/style/builders/toolbutton.py +275 -0
  238. bootstack/style/builders/tooltip.py +26 -0
  239. bootstack/style/builders/treeview.py +193 -0
  240. bootstack/style/builders/utils.py +455 -0
  241. bootstack/style/builders_tk/__init__.py +16 -0
  242. bootstack/style/builders_tk/defaults.py +229 -0
  243. bootstack/style/element.py +173 -0
  244. bootstack/style/fonts.py +123 -0
  245. bootstack/style/style.py +609 -0
  246. bootstack/style/style_builder_base.py +716 -0
  247. bootstack/style/style_builder_mixed.py +93 -0
  248. bootstack/style/style_builder_tk.py +109 -0
  249. bootstack/style/style_builder_ttk.py +353 -0
  250. bootstack/style/style_resolver.py +447 -0
  251. bootstack/style/theme.py +245 -0
  252. bootstack/style/theme_provider.py +471 -0
  253. bootstack/style/themes/__init__.py +128 -0
  254. bootstack/style/tk_patch.py +5 -0
  255. bootstack/style/token_maps.py +41 -0
  256. bootstack/style/types.py +32 -0
  257. bootstack/style/typography.py +523 -0
  258. bootstack/style/utility.py +746 -0
  259. bootstack/types.py +39 -0
  260. bootstack/validation/__init__.py +6 -0
  261. bootstack/validation/types.py +15 -0
  262. bootstack/validation/validation_result.py +17 -0
  263. bootstack/validation/validation_rules.py +205 -0
  264. bootstack/widgets/__init__.py +74 -0
  265. bootstack/widgets/_core/__init__.py +31 -0
  266. bootstack/widgets/_core/app_config.py +266 -0
  267. bootstack/widgets/_core/base.py +461 -0
  268. bootstack/widgets/_core/container.py +334 -0
  269. bootstack/widgets/_core/context.py +35 -0
  270. bootstack/widgets/_core/events.py +130 -0
  271. bootstack/widgets/_core/field_mixin.py +353 -0
  272. bootstack/widgets/_core/icon_image_props.py +72 -0
  273. bootstack/widgets/_core/image_binding.py +93 -0
  274. bootstack/widgets/_core/navmodel.py +345 -0
  275. bootstack/widgets/_core/options.py +210 -0
  276. bootstack/widgets/_core/selection_group.py +130 -0
  277. bootstack/widgets/_core/window_controls.py +96 -0
  278. bootstack/widgets/_core/window_menu.py +246 -0
  279. bootstack/widgets/_impl/__init__.py +1 -0
  280. bootstack/widgets/_impl/_internal/__init__.py +0 -0
  281. bootstack/widgets/_impl/_internal/wrapper_base.py +307 -0
  282. bootstack/widgets/_impl/_parts/__init__.py +11 -0
  283. bootstack/widgets/_impl/_parts/numberentry_part.py +385 -0
  284. bootstack/widgets/_impl/_parts/spinnerentry_part.py +434 -0
  285. bootstack/widgets/_impl/_parts/textentry_part.py +406 -0
  286. bootstack/widgets/_impl/composites/__init__.py +33 -0
  287. bootstack/widgets/_impl/composites/_dateutils.py +33 -0
  288. bootstack/widgets/_impl/composites/_image_fit.py +105 -0
  289. bootstack/widgets/_impl/composites/accordion.py +381 -0
  290. bootstack/widgets/_impl/composites/avatar.py +191 -0
  291. bootstack/widgets/_impl/composites/buttongroup.py +371 -0
  292. bootstack/widgets/_impl/composites/calendar.py +972 -0
  293. bootstack/widgets/_impl/composites/carousel.py +567 -0
  294. bootstack/widgets/_impl/composites/chart.py +882 -0
  295. bootstack/widgets/_impl/composites/compositeframe.py +298 -0
  296. bootstack/widgets/_impl/composites/contextmenu.py +1951 -0
  297. bootstack/widgets/_impl/composites/dateentry.py +404 -0
  298. bootstack/widgets/_impl/composites/dropdownbutton.py +325 -0
  299. bootstack/widgets/_impl/composites/expander.py +515 -0
  300. bootstack/widgets/_impl/composites/field.py +670 -0
  301. bootstack/widgets/_impl/composites/form.py +1066 -0
  302. bootstack/widgets/_impl/composites/gallery.py +551 -0
  303. bootstack/widgets/_impl/composites/list/__init__.py +15 -0
  304. bootstack/widgets/_impl/composites/list/listitem.py +802 -0
  305. bootstack/widgets/_impl/composites/list/listview.py +1433 -0
  306. bootstack/widgets/_impl/composites/menu/__init__.py +18 -0
  307. bootstack/widgets/_impl/composites/menu/model.py +358 -0
  308. bootstack/widgets/_impl/composites/menu/render_native.py +134 -0
  309. bootstack/widgets/_impl/composites/menu/render_themed.py +134 -0
  310. bootstack/widgets/_impl/composites/meter.py +860 -0
  311. bootstack/widgets/_impl/composites/numericentry.py +201 -0
  312. bootstack/widgets/_impl/composites/pagestack.py +395 -0
  313. bootstack/widgets/_impl/composites/passwordentry.py +142 -0
  314. bootstack/widgets/_impl/composites/pathentry.py +168 -0
  315. bootstack/widgets/_impl/composites/picture.py +289 -0
  316. bootstack/widgets/_impl/composites/radiogroup.py +511 -0
  317. bootstack/widgets/_impl/composites/scrolledtext.py +375 -0
  318. bootstack/widgets/_impl/composites/scrolledtext.pyi +186 -0
  319. bootstack/widgets/_impl/composites/scrollview.py +764 -0
  320. bootstack/widgets/_impl/composites/selectbox.py +1026 -0
  321. bootstack/widgets/_impl/composites/shell/__init__.py +40 -0
  322. bootstack/widgets/_impl/composites/shell/content_host.py +52 -0
  323. bootstack/widgets/_impl/composites/shell/layout.py +335 -0
  324. bootstack/widgets/_impl/composites/shell/nav_panel.py +345 -0
  325. bootstack/widgets/_impl/composites/shell/providers.py +558 -0
  326. bootstack/widgets/_impl/composites/shell/rail.py +117 -0
  327. bootstack/widgets/_impl/composites/shell/shell.py +581 -0
  328. bootstack/widgets/_impl/composites/shell/workspace.py +273 -0
  329. bootstack/widgets/_impl/composites/sidenav/__init__.py +16 -0
  330. bootstack/widgets/_impl/composites/sidenav/header.py +81 -0
  331. bootstack/widgets/_impl/composites/sidenav/separator.py +44 -0
  332. bootstack/widgets/_impl/composites/slider/__init__.py +7 -0
  333. bootstack/widgets/_impl/composites/slider/_shared.py +195 -0
  334. bootstack/widgets/_impl/composites/slider/rangeslider.py +982 -0
  335. bootstack/widgets/_impl/composites/slider/slider.py +851 -0
  336. bootstack/widgets/_impl/composites/spinnerentry.py +185 -0
  337. bootstack/widgets/_impl/composites/tableview/__init__.py +5 -0
  338. bootstack/widgets/_impl/composites/tableview/tableview.py +3388 -0
  339. bootstack/widgets/_impl/composites/tableview/types.py +169 -0
  340. bootstack/widgets/_impl/composites/tabs/__init__.py +23 -0
  341. bootstack/widgets/_impl/composites/tabs/tabitem.py +389 -0
  342. bootstack/widgets/_impl/composites/tabs/tabs.py +974 -0
  343. bootstack/widgets/_impl/composites/tabs/tabview.py +650 -0
  344. bootstack/widgets/_impl/composites/textarea/__init__.py +26 -0
  345. bootstack/widgets/_impl/composites/textarea/change.py +46 -0
  346. bootstack/widgets/_impl/composites/textarea/codeeditor.py +526 -0
  347. bootstack/widgets/_impl/composites/textarea/core.py +495 -0
  348. bootstack/widgets/_impl/composites/textarea/decoration.py +42 -0
  349. bootstack/widgets/_impl/composites/textarea/diff.py +127 -0
  350. bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +1 -0
  351. bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +138 -0
  352. bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +158 -0
  353. bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +138 -0
  354. bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +312 -0
  355. bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +177 -0
  356. bootstack/widgets/_impl/composites/textarea/filter.py +171 -0
  357. bootstack/widgets/_impl/composites/textarea/search_overlay.py +459 -0
  358. bootstack/widgets/_impl/composites/textarea/sidebar.py +88 -0
  359. bootstack/widgets/_impl/composites/textarea/style_registry.py +178 -0
  360. bootstack/widgets/_impl/composites/textarea/textarea.py +606 -0
  361. bootstack/widgets/_impl/composites/textarea/undo.py +217 -0
  362. bootstack/widgets/_impl/composites/textentry.py +57 -0
  363. bootstack/widgets/_impl/composites/timeentry.py +176 -0
  364. bootstack/widgets/_impl/composites/toast.py +390 -0
  365. bootstack/widgets/_impl/composites/toast_stack.py +156 -0
  366. bootstack/widgets/_impl/composites/togglegroup.py +418 -0
  367. bootstack/widgets/_impl/composites/toolbar.py +608 -0
  368. bootstack/widgets/_impl/composites/tooltip.py +491 -0
  369. bootstack/widgets/_impl/composites/tree/__init__.py +7 -0
  370. bootstack/widgets/_impl/composites/tree/source_binding.py +136 -0
  371. bootstack/widgets/_impl/composites/tree/treeitem.py +393 -0
  372. bootstack/widgets/_impl/composites/tree/treenode.py +174 -0
  373. bootstack/widgets/_impl/composites/tree/treeview.py +841 -0
  374. bootstack/widgets/_impl/mixins/__init__.py +24 -0
  375. bootstack/widgets/_impl/mixins/configure_mixin.py +216 -0
  376. bootstack/widgets/_impl/mixins/entry_mixin.py +134 -0
  377. bootstack/widgets/_impl/mixins/font_mixin.py +368 -0
  378. bootstack/widgets/_impl/mixins/icon_mixin.py +61 -0
  379. bootstack/widgets/_impl/mixins/localization_mixin.py +253 -0
  380. bootstack/widgets/_impl/mixins/signal_mixin.py +268 -0
  381. bootstack/widgets/_impl/mixins/validation_mixin.py +226 -0
  382. bootstack/widgets/_impl/primitives/__init__.py +49 -0
  383. bootstack/widgets/_impl/primitives/_menubutton.py +107 -0
  384. bootstack/widgets/_impl/primitives/badge.py +45 -0
  385. bootstack/widgets/_impl/primitives/button.py +76 -0
  386. bootstack/widgets/_impl/primitives/card.py +45 -0
  387. bootstack/widgets/_impl/primitives/checkbutton.py +124 -0
  388. bootstack/widgets/_impl/primitives/checktoggle.py +62 -0
  389. bootstack/widgets/_impl/primitives/combobox.py +156 -0
  390. bootstack/widgets/_impl/primitives/entry.py +87 -0
  391. bootstack/widgets/_impl/primitives/flexframe.py +448 -0
  392. bootstack/widgets/_impl/primitives/frame.py +185 -0
  393. bootstack/widgets/_impl/primitives/gridframe.py +546 -0
  394. bootstack/widgets/_impl/primitives/label.py +84 -0
  395. bootstack/widgets/_impl/primitives/labelframe.py +54 -0
  396. bootstack/widgets/_impl/primitives/optionmenu.py +387 -0
  397. bootstack/widgets/_impl/primitives/packframe.py +227 -0
  398. bootstack/widgets/_impl/primitives/panedwindow.py +45 -0
  399. bootstack/widgets/_impl/primitives/progressbar.py +83 -0
  400. bootstack/widgets/_impl/primitives/radiobutton.py +115 -0
  401. bootstack/widgets/_impl/primitives/radiotoggle.py +54 -0
  402. bootstack/widgets/_impl/primitives/scrollbar.py +42 -0
  403. bootstack/widgets/_impl/primitives/separator.py +43 -0
  404. bootstack/widgets/_impl/primitives/sizegrip.py +33 -0
  405. bootstack/widgets/_impl/primitives/spinbox.py +95 -0
  406. bootstack/widgets/_impl/primitives/switch.py +44 -0
  407. bootstack/widgets/_impl/primitives/treeview.py +69 -0
  408. bootstack/widgets/app.py +371 -0
  409. bootstack/widgets/appshell.py +1179 -0
  410. bootstack/widgets/avatar.py +140 -0
  411. bootstack/widgets/boolean_controls.py +455 -0
  412. bootstack/widgets/button.py +224 -0
  413. bootstack/widgets/buttongroup.py +239 -0
  414. bootstack/widgets/calendar.py +195 -0
  415. bootstack/widgets/card.py +159 -0
  416. bootstack/widgets/carousel.py +241 -0
  417. bootstack/widgets/chart.py +302 -0
  418. bootstack/widgets/codeeditor.py +675 -0
  419. bootstack/widgets/contextmenu.py +371 -0
  420. bootstack/widgets/datatable.py +688 -0
  421. bootstack/widgets/datefield.py +395 -0
  422. bootstack/widgets/divider.py +60 -0
  423. bootstack/widgets/expander.py +579 -0
  424. bootstack/widgets/form.py +200 -0
  425. bootstack/widgets/gallery.py +250 -0
  426. bootstack/widgets/gauge.py +168 -0
  427. bootstack/widgets/grid.py +121 -0
  428. bootstack/widgets/groupbox.py +162 -0
  429. bootstack/widgets/label.py +229 -0
  430. bootstack/widgets/listview.py +354 -0
  431. bootstack/widgets/menubutton.py +419 -0
  432. bootstack/widgets/numberfield.py +431 -0
  433. bootstack/widgets/pagestack.py +345 -0
  434. bootstack/widgets/passwordfield.py +383 -0
  435. bootstack/widgets/pathfield.py +454 -0
  436. bootstack/widgets/picture.py +251 -0
  437. bootstack/widgets/progressbar.py +106 -0
  438. bootstack/widgets/radio_variants.py +271 -0
  439. bootstack/widgets/radiogroup.py +228 -0
  440. bootstack/widgets/scrollbar.py +64 -0
  441. bootstack/widgets/scrollview.py +186 -0
  442. bootstack/widgets/select.py +302 -0
  443. bootstack/widgets/selectbutton.py +182 -0
  444. bootstack/widgets/sidebar_toggle.py +130 -0
  445. bootstack/widgets/sizegrip.py +42 -0
  446. bootstack/widgets/slider.py +408 -0
  447. bootstack/widgets/spinbox.py +147 -0
  448. bootstack/widgets/spinnerfield.py +413 -0
  449. bootstack/widgets/splash.py +367 -0
  450. bootstack/widgets/splitview.py +482 -0
  451. bootstack/widgets/stacks.py +249 -0
  452. bootstack/widgets/statusbar.py +189 -0
  453. bootstack/widgets/tabs.py +425 -0
  454. bootstack/widgets/textarea.py +459 -0
  455. bootstack/widgets/textfield.py +410 -0
  456. bootstack/widgets/theme_toggle.py +92 -0
  457. bootstack/widgets/timefield.py +340 -0
  458. bootstack/widgets/toast.py +314 -0
  459. bootstack/widgets/togglegroup.py +231 -0
  460. bootstack/widgets/toolbar.py +347 -0
  461. bootstack/widgets/tooltip.py +94 -0
  462. bootstack/widgets/tree.py +648 -0
  463. bootstack/widgets/types.py +305 -0
  464. bootstack/widgets/window.py +307 -0
  465. bootstack-0.1.0.dist-info/METADATA +301 -0
  466. bootstack-0.1.0.dist-info/RECORD +471 -0
  467. bootstack-0.1.0.dist-info/WHEEL +5 -0
  468. bootstack-0.1.0.dist-info/entry_points.txt +2 -0
  469. bootstack-0.1.0.dist-info/licenses/LICENSE +21 -0
  470. bootstack-0.1.0.dist-info/licenses/NOTICE +10 -0
  471. bootstack-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,40 @@
1
+ """Internal composites for the clean-slate application shell.
2
+
3
+ Layered per `docs/_dev/appshell-navigation-spec.md`:
4
+
5
+ - `layout.ShellLayout` — Layer 1, the dumb region/slot band layout.
6
+ - `nav_panel.NavPanel` — the static single-select nav list (sidebar).
7
+ - `content_host.ContentHost` — context container for rendering detail bodies.
8
+ - `providers.NavProvider` / `StaticProvider` / `ListNavProvider` — Layer 3.
9
+ - `shell.Shell` — wires `NavModel` to the regions (single-tier path).
10
+
11
+ Later layers (rail, tree provider, collapse) build on top of these.
12
+ """
13
+
14
+ from bootstack.widgets._impl.composites.shell.content_host import ContentHost
15
+ from bootstack.widgets._impl.composites.shell.layout import ShellLayout
16
+ from bootstack.widgets._impl.composites.shell.nav_panel import NavPanel
17
+ from bootstack.widgets._impl.composites.shell.rail import Rail
18
+ from bootstack.widgets._impl.composites.shell.providers import (
19
+ CustomProvider,
20
+ ListNavProvider,
21
+ NavProvider,
22
+ StaticProvider,
23
+ TreeNavProvider,
24
+ )
25
+ from bootstack.widgets._impl.composites.shell.shell import Shell
26
+ from bootstack.widgets._impl.composites.shell.workspace import Workspace
27
+
28
+ __all__ = [
29
+ "ShellLayout",
30
+ "NavPanel",
31
+ "Rail",
32
+ "ContentHost",
33
+ "NavProvider",
34
+ "StaticProvider",
35
+ "ListNavProvider",
36
+ "TreeNavProvider",
37
+ "CustomProvider",
38
+ "Workspace",
39
+ "Shell",
40
+ ]
@@ -0,0 +1,52 @@
1
+ """Context container for rendering a provider's content into a region frame.
2
+
3
+ A data-bound provider's `@detail` body is authored with public widgets
4
+ (`with bs.VStack(...): ...`), which parent to whatever container is on top of
5
+ the context stack. `ContentHost` wraps a plain region frame as such a container,
6
+ so the framework can push it, call the detail builder, and pop it — landing the
7
+ built widgets inside the content region.
8
+
9
+ Mirrors the public `_PageFrame` container protocol (`_child_master` /
10
+ `guide_layout`).
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from typing import Any
16
+
17
+ from bootstack.widgets._core.container import PACK_KEYS, normalize_fill
18
+ from bootstack.widgets._core.context import push_container, pop_container
19
+
20
+
21
+ class ContentHost:
22
+ """A context-stack container that parents public widgets into `frame`."""
23
+
24
+ def __init__(self, frame: Any) -> None:
25
+ self._internal = frame
26
+
27
+ def _child_master(self) -> Any:
28
+ return self._internal
29
+
30
+ def guide_layout(self, child: Any, **layout_kw: Any) -> None:
31
+ # A content/sidebar region's top-level child should fill it — otherwise a
32
+ # detail builder's container shrinks to its content and centers (looking
33
+ # like huge padding). The flex placement kwargs (`grow` / `horizontal`)
34
+ # don't apply to a plain region frame, so default to fill="both"/expand
35
+ # and let any explicit pack option override.
36
+ options: dict[str, Any] = {"fill": "both", "expand": True}
37
+ if "fill" in layout_kw:
38
+ options["fill"] = normalize_fill(layout_kw["fill"])
39
+ options.update({k: v for k, v in layout_kw.items() if k in PACK_KEYS and k != "fill"})
40
+ child._internal.pack(in_=self._internal, **options)
41
+
42
+ def __enter__(self) -> "ContentHost":
43
+ push_container(self)
44
+ return self
45
+
46
+ def __exit__(self, *exc: Any) -> None:
47
+ pop_container(self)
48
+
49
+ def clear(self) -> None:
50
+ """Destroy all children currently in the frame."""
51
+ for child in self._internal.winfo_children():
52
+ child.destroy()
@@ -0,0 +1,335 @@
1
+ """Layer 1 — the region/slot band layout for the application shell.
2
+
3
+ `ShellLayout` owns the window (it subclasses the internal `App`) and arranges
4
+ the shell's bands as independently toggleable slots:
5
+
6
+ +-------------------------------------------------+
7
+ | chrome (top, full width) |
8
+ +----+--------------+------------------+----------+
9
+ | r | sidebar | content | dock |
10
+ | a | | | (resv'd) |
11
+ | i | | | |
12
+ | l | | | |
13
+ +----+--------------+------------------+----------+
14
+ | statusbar (full width) |
15
+ +-------------------------------------------------+
16
+
17
+ This layer is deliberately **dumb about navigation** — it exposes region frames
18
+ and show/hide/size operations only. Wiring the regions to `NavModel` (which
19
+ workspace/page is active, the rail gesture, etc.) happens in a higher layer.
20
+
21
+ The top (`chrome`) and bottom (`statusbar`) bands span the full window width;
22
+ only the body row knows whether the rail/sidebar/dock exist. That invariant lets
23
+ "sidebar + chrome", "chrome only", and "sidebar only" be the same layout with
24
+ slots toggled rather than separate code paths.
25
+
26
+ Note: the resizable sidebar/content sash (a `PanedWindow`) is deferred to the
27
+ collapse step — for now the body uses fixed-width pack slots. See the build order
28
+ in `docs/_dev/appshell-navigation-spec.md`.
29
+ """
30
+
31
+ from __future__ import annotations
32
+
33
+ import sys
34
+ from typing import Any
35
+
36
+ from bootstack._runtime.app import App
37
+ from bootstack.widgets._impl.composites.toolbar import Toolbar
38
+ from bootstack.widgets._impl.primitives.frame import Frame
39
+ from bootstack.widgets._impl.primitives.packframe import PackFrame
40
+ from bootstack.widgets._impl.primitives.separator import Separator
41
+
42
+
43
+ # Default region sizing (pixels). Rail and compact sidebar share a width so a
44
+ # collapsed single sidebar matches the two-tier rail (the seam rule).
45
+ DEFAULT_RAIL_WIDTH = 52
46
+ DEFAULT_SIDEBAR_WIDTH = 240
47
+ DEFAULT_DOCK_WIDTH = 280
48
+
49
+ # Region surfaces — the single source of truth. Nav items blend their selection
50
+ # tint (and round their corners) against the SAME surface they render on, so the
51
+ # color can never mismatch the background; callers thread these down rather than
52
+ # hardcoding a surface token independently.
53
+ #
54
+ # Elevation tiers: the rail is the chrome tier; the sidebar (and dock) sit on a
55
+ # SUBTLE `raised` elevation (half the `card` step) — gentle, not a big ramp, and
56
+ # reinforced by the dividers. Selection is neutral, so a subtle elevation no
57
+ # longer washes it out. content < raised < chrome.
58
+ RAIL_SURFACE = "chrome"
59
+ SIDEBAR_SURFACE = "raised"
60
+ DOCK_SURFACE = "raised"
61
+ STATUSBAR_SURFACE = "chrome"
62
+
63
+ # Divider stroke softness. The default separator border blends 16% toward the
64
+ # surface's on-color (text), which reads strong on the near-black dark surfaces;
65
+ # the shell's region dividers blend less (closer to the surface) for a quieter
66
+ # hairline. Higher = quieter.
67
+ DIVIDER_BORDER_STRENGTH = 0.90
68
+
69
+
70
+ class ShellLayout(App):
71
+ """The shell's band layout — a window of toggleable region slots.
72
+
73
+ Args:
74
+ title: Window title.
75
+ theme: Theme name, or None for the default.
76
+ size: Initial window size as `(width, height)`.
77
+ undecorated: Remove OS chrome and draw a custom border (ignored on
78
+ macOS). The public `AppShell` injects a default title bar (window
79
+ controls + drag) for a borderless shell unless the author adds their
80
+ own `add_toolbar(show_window_controls=True)`; this layer itself adds
81
+ no chrome.
82
+ rail_width: Width of the workspace rail (and compact sidebar) in pixels.
83
+ sidebar_width: Width of the expanded sidebar in pixels.
84
+ dock_width: Width of the detail/inspector dock in pixels.
85
+ **kwargs: Forwarded to `App` (position, minsize, locale, etc.).
86
+ """
87
+
88
+ def __init__(
89
+ self,
90
+ *,
91
+ title: str = "",
92
+ theme: str | None = None,
93
+ size: tuple[int, int] | None = None,
94
+ undecorated: bool = False,
95
+ rail_width: int = DEFAULT_RAIL_WIDTH,
96
+ sidebar_width: int = DEFAULT_SIDEBAR_WIDTH,
97
+ dock_width: int = DEFAULT_DOCK_WIDTH,
98
+ rail_surface: str = RAIL_SURFACE,
99
+ sidebar_surface: str = SIDEBAR_SURFACE,
100
+ statusbar_surface: str = STATUSBAR_SURFACE,
101
+ **kwargs: Any,
102
+ ) -> None:
103
+ # overrideredirect has no effect on macOS — disable undecorated there.
104
+ if sys.platform == "darwin":
105
+ undecorated = False
106
+
107
+ self._rail_surface = rail_surface
108
+ self._sidebar_surface = sidebar_surface
109
+ self._statusbar_surface = statusbar_surface
110
+ app_kwargs: dict[str, Any] = {"title": title, "override_redirect": undecorated}
111
+ if theme is not None:
112
+ app_kwargs["theme"] = theme
113
+ if size is not None:
114
+ app_kwargs["size"] = size
115
+ app_kwargs.update(kwargs)
116
+ super().__init__(**app_kwargs)
117
+
118
+ self._undecorated = undecorated
119
+ self._rail_width = rail_width
120
+ self._sidebar_width = sidebar_width
121
+ self._dock_width = dock_width
122
+
123
+ # Visibility flags. Content is always shown; the rest are slots. The
124
+ # window's top chrome is the `toolbar_stack` region (filled by
125
+ # `add_toolbar()`); a custom title bar in undecorated mode is just an
126
+ # `add_toolbar(show_window_controls=True)`.
127
+ self._show_statusbar = False
128
+ self._show_rail = False
129
+ self._show_sidebar = True
130
+ self._show_dock = False
131
+
132
+ self._build_regions()
133
+ self._relayout_window()
134
+ self._relayout_body()
135
+
136
+ # ----- Construction -----
137
+
138
+ def _build_regions(self) -> None:
139
+ # In undecorated mode the OS border is gone; a bordered frame substitutes
140
+ # it (padding is required or the border is obscured by children).
141
+ if self._undecorated:
142
+ root = Frame(self, show_border=True, padding=1)
143
+ root.pack(fill="both", expand=True)
144
+ else:
145
+ root = self
146
+ # NB: do not name this `self._root` — tkinter's `Misc._root()` is a
147
+ # method; shadowing it with an attribute breaks event dispatch.
148
+ self._region_root = root
149
+
150
+ # Full-width top and bottom bands. The window's top chrome is the
151
+ # stacked-toolbar region (the `add_toolbar()` host) at the very top,
152
+ # spanning the whole width above the rail + sidebar + content body.
153
+ # Chrome-surfaced so any gap (e.g. a divider margin) reads chrome, not the
154
+ # content surface. The status band + its hairline span the full width too.
155
+ self._toolbar_stack = PackFrame(root, direction="vertical", surface="chrome")
156
+ self._statusbar = Toolbar(root, surface=self._statusbar_surface, draggable=False)
157
+ self._status_sep = Separator(root, orient="horizontal", border_strength=DIVIDER_BORDER_STRENGTH)
158
+ # A persistent hairline at the top edge of the body (above the rail +
159
+ # sidebar + content), derived against the content surface. This is the
160
+ # always-on boundary between the window's top chrome and the workspace,
161
+ # regardless of whether any toolbar is present. Stacked toolbars can still
162
+ # add their own dividers (`add_toolbar(divider=True)`) to separate bars.
163
+ self._body_sep = Separator(root, orient="horizontal", border_strength=DIVIDER_BORDER_STRENGTH)
164
+
165
+ # Body row + its slots.
166
+ self._body = Frame(root)
167
+ self._rail = Frame(self._body, surface=self._rail_surface)
168
+ # A thin divider between the rail and the sidebar reinforces the tier
169
+ # boundary (shown only when the rail renders). Each divider takes the
170
+ # surface of the region it edges so its stroke is derived against that
171
+ # surface, not the default content surface.
172
+ self._rail_sep = Separator(self._body, orient="vertical", surface=self._rail_surface,
173
+ border_strength=DIVIDER_BORDER_STRENGTH)
174
+ self._sidebar = Frame(self._body, surface=self._sidebar_surface)
175
+ # A matching divider on the sidebar's right edge defines the sidebar/
176
+ # content boundary (shown only when the sidebar is visible).
177
+ self._sidebar_sep = Separator(self._body, orient="vertical", surface=self._sidebar_surface,
178
+ border_strength=DIVIDER_BORDER_STRENGTH)
179
+ self._content = Frame(self._body)
180
+ self._dock = Frame(self._body, surface=DOCK_SURFACE)
181
+
182
+ # Fixed-width slots keep their requested width instead of shrinking to
183
+ # fit their children.
184
+ for frame, width in (
185
+ (self._rail, self._rail_width),
186
+ (self._sidebar, self._sidebar_width),
187
+ (self._dock, self._dock_width),
188
+ ):
189
+ frame.configure(width=width)
190
+ frame.pack_propagate(False)
191
+
192
+ # ----- Layout (re-pack in canonical order on every visibility change) -----
193
+
194
+ def _relayout_window(self) -> None:
195
+ """Re-pack the full-width toolbar / status bands and the body."""
196
+ for child in (self._toolbar_stack, self._body_sep, self._status_sep,
197
+ self._statusbar, self._body):
198
+ child.pack_forget()
199
+ # The stacked-toolbar region — full width, at the very top, above the body.
200
+ self._toolbar_stack.pack(side="top", fill="x")
201
+ # Persistent boundary between the top chrome and the workspace below it.
202
+ self._body_sep.pack(side="top", fill="x")
203
+ if self._show_statusbar:
204
+ # Band at the very bottom; its hairline just above it (both full width).
205
+ self._statusbar.pack(side="bottom", fill="x")
206
+ self._status_sep.pack(side="bottom", fill="x")
207
+ # Body fills whatever the bands leave; packed last so it claims the middle.
208
+ self._body.pack(side="top", fill="both", expand=True)
209
+
210
+ def _relayout_body(self) -> None:
211
+ """Re-pack the rail / sidebar / content / dock slots left-to-right."""
212
+ for child in (self._rail, self._rail_sep, self._sidebar, self._sidebar_sep,
213
+ self._content, self._dock):
214
+ child.pack_forget()
215
+ if self._show_rail:
216
+ self._rail.pack(side="left", fill="y")
217
+ self._rail_sep.pack(side="left", fill="y")
218
+ if self._show_sidebar:
219
+ self._sidebar.pack(side="left", fill="y")
220
+ self._sidebar_sep.pack(side="left", fill="y")
221
+ self._content.pack(side="left", fill="both", expand=True)
222
+ if self._show_dock:
223
+ self._dock.pack(side="right", fill="y")
224
+
225
+ # ----- Region visibility -----
226
+
227
+ def set_statusbar_visible(self, visible: bool) -> None:
228
+ """Show or hide the bottom status band (and its full-width hairline)."""
229
+ if self._show_statusbar != visible:
230
+ self._show_statusbar = visible
231
+ self._relayout_window()
232
+
233
+ def set_rail_visible(self, visible: bool) -> None:
234
+ """Show or hide the workspace rail."""
235
+ if self._show_rail != visible:
236
+ self._show_rail = visible
237
+ self._relayout_body()
238
+
239
+ def set_sidebar_visible(self, visible: bool) -> None:
240
+ """Show or hide the sidebar slot."""
241
+ if self._show_sidebar != visible:
242
+ self._show_sidebar = visible
243
+ self._relayout_body()
244
+
245
+ def set_dock_visible(self, visible: bool) -> None:
246
+ """Show or hide the detail/inspector dock."""
247
+ if self._show_dock != visible:
248
+ self._show_dock = visible
249
+ self._relayout_body()
250
+
251
+ # ----- Region sizing -----
252
+
253
+ def set_rail_width(self, width: int) -> None:
254
+ """Set the rail width in pixels."""
255
+ self._rail_width = width
256
+ self._rail.configure(width=width)
257
+
258
+ def set_sidebar_width(self, width: int) -> None:
259
+ """Set the expanded-sidebar width in pixels."""
260
+ self._sidebar_width = width
261
+ self._sidebar.configure(width=width)
262
+
263
+ def set_dock_width(self, width: int) -> None:
264
+ """Set the dock width in pixels."""
265
+ self._dock_width = width
266
+ self._dock.configure(width=width)
267
+
268
+ # ----- Region accessors -----
269
+
270
+ @property
271
+ def toolbar_stack(self) -> PackFrame:
272
+ """The vertical region hosting `add_toolbar()` toolbars (top of window)."""
273
+ return self._toolbar_stack
274
+
275
+ @property
276
+ def statusbar(self) -> Toolbar:
277
+ """The bottom status band (a command-bar strip; passive content)."""
278
+ return self._statusbar
279
+
280
+ @property
281
+ def rail(self) -> Frame:
282
+ """The workspace rail slot."""
283
+ return self._rail
284
+
285
+ @property
286
+ def sidebar(self) -> Frame:
287
+ """The sidebar slot (the active workspace's panel)."""
288
+ return self._sidebar
289
+
290
+ @property
291
+ def content(self) -> Frame:
292
+ """The content slot (the active page)."""
293
+ return self._content
294
+
295
+ @property
296
+ def sidebar_surface(self) -> str:
297
+ """Surface token the sidebar region renders on (for matched nav tints)."""
298
+ return self._sidebar_surface
299
+
300
+ @property
301
+ def rail_surface(self) -> str:
302
+ """Surface token the rail region renders on."""
303
+ return self._rail_surface
304
+
305
+ @property
306
+ def statusbar_surface(self) -> str:
307
+ """Surface token the status band renders on."""
308
+ return self._statusbar_surface
309
+
310
+ @property
311
+ def dock(self) -> Frame:
312
+ """The detail/inspector dock slot (reserved)."""
313
+ return self._dock
314
+
315
+ # ----- Visibility state (read-only) -----
316
+
317
+ @property
318
+ def statusbar_visible(self) -> bool:
319
+ """Whether the status band is shown."""
320
+ return self._show_statusbar
321
+
322
+ @property
323
+ def rail_visible(self) -> bool:
324
+ """Whether the rail is shown."""
325
+ return self._show_rail
326
+
327
+ @property
328
+ def sidebar_visible(self) -> bool:
329
+ """Whether the sidebar slot is shown."""
330
+ return self._show_sidebar
331
+
332
+ @property
333
+ def dock_visible(self) -> bool:
334
+ """Whether the dock slot is shown."""
335
+ return self._show_dock