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,579 @@
1
+ from __future__ import annotations
2
+
3
+ import tkinter
4
+ from typing import overload, Any, Callable, Literal
5
+
6
+ from bootstack.widgets._impl.composites.expander import Expander as _InternalExpander
7
+ from bootstack.widgets._impl.composites.accordion import Accordion as _InternalAccordion
8
+ from bootstack.widgets._impl.primitives.flexframe import FlexFrame
9
+ from bootstack.widgets._impl.primitives.gridframe import GridFrame
10
+ from bootstack.widgets._core.container import (
11
+ PublicContainer, GRID_KEYS, grid_sticky, place_flex_child,
12
+ _reject_legacy_child_kwargs, _expand_margin,
13
+ )
14
+ from bootstack.widgets._core.base import PublicWidgetBase
15
+ from bootstack.widgets._core.context import push_container, pop_container
16
+ from bootstack.widgets._core.events import register_widget_events
17
+ from bootstack.events import AccordionChangeEvent, Subscription, ToggleEvent
18
+ from bootstack.streams import Stream
19
+ from bootstack.widgets.types import (
20
+ Event, AccentToken, Padding, LayoutKind, AutoFlow, AccordionVariant,
21
+ )
22
+
23
+ _EXPANDER_EVENTS: dict[str, str] = {
24
+ "expand": "<<Toggle>>",
25
+ "collapse": "<<Toggle>>",
26
+ "toggle": "<<Toggle>>",
27
+ }
28
+
29
+ _ACCORDION_EVENTS: dict[str, str] = {
30
+ "change": "<<AccordionChange>>",
31
+ }
32
+
33
+
34
+ class Expander(PublicContainer):
35
+ """A collapsible container with a clickable header.
36
+
37
+ Children placed inside the context block go into the expandable body,
38
+ laid out according to `layout`.
39
+
40
+ Args:
41
+ title: Header text shown in the clickable header bar.
42
+ layout: Internal layout for the body. One of `'column'` (default),
43
+ `'row'`, or `'grid'`.
44
+ padding: Space between the expander border and its body content, in
45
+ pixels. Accepts a single int or a `(x, y)` tuple.
46
+ gap: Space between body children in pixels. Default `0`.
47
+ horizontal_items: How body children sit on the horizontal axis — edge
48
+ values `'left'`/`'center'`/`'right'`/`'stretch'`, plus
49
+ `'space-*'` when horizontal is the stacking axis. Default
50
+ `'stretch'` for `'grid'`, else `'left'`.
51
+ vertical_items: How body children sit on the vertical axis — edge values
52
+ `'top'`/`'center'`/`'bottom'`/`'stretch'`, plus `'space-*'`
53
+ when vertical is the stacking axis. Default `'stretch'` for
54
+ `'grid'`, else `'top'`.
55
+ grow_items: For `'column'`/`'row'`, when `True` every body
56
+ child grows equally to share the main axis. Default `False`.
57
+ columns: Column size definitions for `'grid'` layout. An integer
58
+ creates that many equal-weight columns; a list of ints sets
59
+ per-column weights. Default `None`.
60
+ rows: Row size definitions for `'grid'` layout. Same format as
61
+ `columns`. Default `None`.
62
+ auto_flow: Grid placement direction — `'row'` (default) or
63
+ `'column'`.
64
+ expanded: If `True` (default), the body is visible on creation.
65
+ collapsible: If `True` (default), clicking the header toggles the
66
+ body. If `False`, the chevron is hidden and the body stays open.
67
+ show_border: If `True`, draws a border around the entire widget.
68
+ Default `False`.
69
+ variant: Header style. Defaults to `None` (the default header reads
70
+ as a ghost/transparent bar).
71
+ icon: Icon name or spec displayed to the left of the title.
72
+ icon_position: Side on which the collapse chevron appears —
73
+ `'after'` (default, right of title) or `'before'` (left).
74
+ highlight: If `True`, the header shows a selected visual state while
75
+ the body is expanded. Default `False`.
76
+ accent: Color intent token for the header. Defaults to `None`
77
+ (theme default).
78
+ parent: Explicit parent container. Omit to use the current context.
79
+ """
80
+
81
+ def __init__(
82
+ self,
83
+ title: str = "",
84
+ *,
85
+ layout: LayoutKind = "column",
86
+ padding: Padding | None = None,
87
+ gap: int = 0,
88
+ horizontal_items: str | None = None,
89
+ vertical_items: str | None = None,
90
+ grow_items: bool = False,
91
+ columns: int | list[int | str] | None = None,
92
+ rows: int | list[int | str] | None = None,
93
+ auto_flow: AutoFlow = "row",
94
+ expanded: bool = True,
95
+ collapsible: bool = True,
96
+ show_border: bool = False,
97
+ variant: AccordionVariant | None = None,
98
+ icon: str | None = None,
99
+ icon_position: Literal["before", "after"] = "after",
100
+ highlight: bool = False,
101
+ accent: AccentToken | str | None = None,
102
+ parent: Any = None,
103
+ **kwargs: Any,
104
+ ) -> None:
105
+ self._parent = self._resolve_parent(parent)
106
+ self._layout = layout
107
+ layout_kw = self._split_layout_kwargs(kwargs)
108
+ layout_kw.setdefault("horizontal", "stretch")
109
+
110
+ if horizontal_items is None:
111
+ horizontal_items = (
112
+ "stretch" if layout == "grid"
113
+ else "center" if layout == "column" else "left"
114
+ )
115
+ if vertical_items is None:
116
+ vertical_items = (
117
+ "stretch" if layout == "grid"
118
+ else "center" if layout == "row" else "top"
119
+ )
120
+
121
+ tk_master = self._parent._child_master() if self._parent else None
122
+
123
+ internal_kwargs: dict[str, Any] = {
124
+ "title": title,
125
+ "expanded": expanded,
126
+ "collapsible": collapsible,
127
+ "icon_position": icon_position,
128
+ "highlight": highlight,
129
+ }
130
+ if show_border:
131
+ internal_kwargs["show_border"] = True
132
+ if variant is not None:
133
+ internal_kwargs["variant"] = variant
134
+ if icon is not None:
135
+ internal_kwargs["icon"] = icon
136
+ if accent is not None:
137
+ internal_kwargs["accent"] = accent
138
+
139
+ self._internal = _InternalExpander(tk_master, **internal_kwargs)
140
+
141
+ content = self._internal._content_frame
142
+ if layout in ("column", "row"):
143
+ self._layout_frame = FlexFrame(
144
+ content,
145
+ direction="vertical" if layout == "column" else "horizontal",
146
+ padding=padding,
147
+ gap=gap,
148
+ horizontal_items=horizontal_items,
149
+ vertical_items=vertical_items,
150
+ grow_items=grow_items,
151
+ )
152
+ elif layout == "grid":
153
+ self._layout_frame = GridFrame(
154
+ content,
155
+ columns=columns,
156
+ rows=rows,
157
+ padding=padding,
158
+ gap=gap,
159
+ auto_flow=auto_flow,
160
+ )
161
+ else:
162
+ raise ValueError(
163
+ f"Expander layout must be 'column', 'row', or 'grid', got {layout!r}"
164
+ )
165
+
166
+ self._horizontal_items = horizontal_items
167
+ self._vertical_items = vertical_items
168
+ self._layout_frame.pack(fill="both", expand=True)
169
+ self._attach_to_parent(layout_kw)
170
+
171
+ def _child_master(self) -> tkinter.Misc:
172
+ return self._layout_frame
173
+
174
+ def guide_layout(self, child: PublicWidgetBase, **layout_kw: Any) -> None:
175
+ if self._layout == "grid":
176
+ _reject_legacy_child_kwargs(layout_kw, "Expander")
177
+ _expand_margin(layout_kw)
178
+ options = {k: v for k, v in layout_kw.items() if k in GRID_KEYS}
179
+ h = layout_kw.get("horizontal") or self._horizontal_items
180
+ v = layout_kw.get("vertical") or self._vertical_items
181
+ options["sticky"] = grid_sticky(h, v)
182
+ child._internal.grid(in_=self._child_master(), **options)
183
+ return
184
+ place_flex_child(self._layout_frame, child, layout_kw, "Expander")
185
+
186
+ # ----- Properties -----
187
+
188
+ @property
189
+ def expanded(self) -> bool:
190
+ return self._internal._expanded
191
+
192
+ # ----- Methods -----
193
+
194
+ def expand(self) -> None:
195
+ """Expand the body."""
196
+ self._internal.expand()
197
+
198
+ def collapse(self) -> None:
199
+ """Collapse the body."""
200
+ self._internal.collapse()
201
+
202
+ def toggle(self) -> None:
203
+ """Toggle between expanded and collapsed."""
204
+ self._internal.toggle()
205
+
206
+ # ----- Event shorthands -----
207
+
208
+ @overload
209
+ def on_toggle(self) -> Stream: ...
210
+ @overload
211
+ def on_toggle(self, handler: Callable[[ToggleEvent], Any]) -> Subscription: ...
212
+ def on_toggle(self, handler: Callable[[ToggleEvent], Any] | None = None) -> Stream | Subscription:
213
+ """Register a callback fired when the expander is expanded or collapsed.
214
+
215
+ Returns:
216
+ Subscription — call `.cancel()` to unsubscribe.
217
+ """
218
+ return self.on("toggle", handler)
219
+
220
+
221
+ register_widget_events(Expander, _EXPANDER_EVENTS)
222
+
223
+
224
+ class AccordionSection:
225
+ """A handle for one accordion section — both a layout context and a live controller.
226
+
227
+ Returned by `Accordion.add()` and by `Accordion.item()` / `items()`. Use it
228
+ as a `with` block to place child widgets inside the section, and read or call
229
+ `key` / `title` / `expanded` / `expand()` / `collapse()` / `toggle()` to
230
+ inspect or drive the section afterward.
231
+
232
+ As a context manager it accepts the same layout kwargs as the standalone
233
+ layout containers — `layout=`, `gap=`, `horizontal_items=`, `vertical_items=`,
234
+ `grow_items=`, `columns=`, `rows=`, `auto_flow=`.
235
+ """
236
+
237
+ def __init__(
238
+ self,
239
+ internal_expander: _InternalExpander,
240
+ *,
241
+ key: str,
242
+ layout: LayoutKind = "column",
243
+ padding: Padding | None = None,
244
+ gap: int = 0,
245
+ horizontal_items: str | None = None,
246
+ vertical_items: str | None = None,
247
+ grow_items: bool = False,
248
+ columns: int | list[int | str] | None = None,
249
+ rows: int | list[int | str] | None = None,
250
+ auto_flow: AutoFlow = "row",
251
+ ) -> None:
252
+ self._expander = internal_expander
253
+ self._key = key
254
+ self._layout = layout
255
+
256
+ if horizontal_items is None:
257
+ horizontal_items = (
258
+ "stretch" if layout == "grid"
259
+ else "center" if layout == "column" else "left"
260
+ )
261
+ if vertical_items is None:
262
+ vertical_items = (
263
+ "stretch" if layout == "grid"
264
+ else "center" if layout == "row" else "top"
265
+ )
266
+
267
+ content = internal_expander._content_frame
268
+ if layout in ("column", "row"):
269
+ self._layout_frame = FlexFrame(
270
+ content,
271
+ direction="vertical" if layout == "column" else "horizontal",
272
+ padding=padding,
273
+ gap=gap,
274
+ horizontal_items=horizontal_items,
275
+ vertical_items=vertical_items,
276
+ grow_items=grow_items,
277
+ )
278
+ elif layout == "grid":
279
+ self._layout_frame = GridFrame(
280
+ content,
281
+ columns=columns,
282
+ rows=rows,
283
+ padding=padding,
284
+ gap=gap,
285
+ auto_flow=auto_flow,
286
+ )
287
+ else:
288
+ raise ValueError(
289
+ f"AccordionSection layout must be 'column', 'row', or 'grid', got {layout!r}"
290
+ )
291
+
292
+ self._horizontal_items = horizontal_items
293
+ self._vertical_items = vertical_items
294
+ self._layout_frame.pack(fill="both", expand=True)
295
+
296
+ def _child_master(self) -> tkinter.Misc:
297
+ return self._layout_frame
298
+
299
+ def guide_layout(self, child: PublicWidgetBase, **layout_kw: Any) -> None:
300
+ if self._layout == "grid":
301
+ _reject_legacy_child_kwargs(layout_kw, "AccordionSection")
302
+ _expand_margin(layout_kw)
303
+ options = {k: v for k, v in layout_kw.items() if k in GRID_KEYS}
304
+ h = layout_kw.get("horizontal") or self._horizontal_items
305
+ v = layout_kw.get("vertical") or self._vertical_items
306
+ options["sticky"] = grid_sticky(h, v)
307
+ child._internal.grid(in_=self._child_master(), **options)
308
+ return
309
+ place_flex_child(self._layout_frame, child, layout_kw, "AccordionSection")
310
+
311
+ # ----- Section identity, state, and control -----
312
+
313
+ @property
314
+ def key(self) -> str:
315
+ """The section's unique key, used with `Accordion.item()`/`remove()`."""
316
+ return self._key
317
+
318
+ @property
319
+ def title(self) -> str:
320
+ """The section header text. Assigning a new value relabels the header."""
321
+ return self._expander._title
322
+
323
+ @title.setter
324
+ def title(self, value: str) -> None:
325
+ self._expander.configure(title=value)
326
+
327
+ @property
328
+ def expanded(self) -> bool:
329
+ """Whether the section is currently expanded."""
330
+ return self._expander._expanded
331
+
332
+ def expand(self) -> None:
333
+ """Expand this section."""
334
+ self._expander.expand()
335
+
336
+ def collapse(self) -> None:
337
+ """Collapse this section."""
338
+ self._expander.collapse()
339
+
340
+ def toggle(self) -> None:
341
+ """Toggle this section between expanded and collapsed."""
342
+ self._expander.toggle()
343
+
344
+ def __enter__(self) -> "AccordionSection":
345
+ push_container(self)
346
+ return self
347
+
348
+ def __exit__(self, exc_type, exc, tb) -> None:
349
+ pop_container(self)
350
+
351
+
352
+ class Accordion(PublicWidgetBase):
353
+ """A list of collapsible sections, optionally limited to one open at a time.
354
+
355
+ Each section is added with `add()`, which returns an `AccordionSection`
356
+ context manager for placing child widgets inside that section.
357
+
358
+ Args:
359
+ allow_multiple: If `True`, multiple sections can be expanded at
360
+ once. Defaults to `False` (only one section open at a time).
361
+ allow_collapse_all: If `True` (default), every section can be
362
+ collapsed. If `False`, at least one section stays open.
363
+ show_separators: If `True`, draws a separator line between sections.
364
+ Defaults to `True`.
365
+ show_border: If `True`, wraps the accordion in a bordered frame.
366
+ Defaults to `True`.
367
+ variant: Style variant applied to each section header. Defaults to
368
+ `None` (the default header reads as a ghost/transparent bar).
369
+ accent: Color intent token applied to all section headers. Defaults
370
+ to `None` (theme default).
371
+ padding: Space between the outer border and the sections, in pixels.
372
+ Defaults to `None`.
373
+ parent: Explicit parent container. Omit to use the current context.
374
+ **kwargs: Layout placement options applied by the parent container —
375
+ `fill`, `expand`, `anchor`, `margin`, `row`, `column`, `sticky`.
376
+ See :doc:`/tasks/layout`.
377
+ """
378
+
379
+ def __init__(
380
+ self,
381
+ *,
382
+ allow_multiple: bool = False,
383
+ allow_collapse_all: bool = True,
384
+ show_separators: bool = True,
385
+ show_border: bool = True,
386
+ variant: AccordionVariant | None = None,
387
+ accent: AccentToken | str | None = None,
388
+ padding: Padding | None = None,
389
+ parent: Any = None,
390
+ **kwargs: Any,
391
+ ) -> None:
392
+ self._parent = self._resolve_parent(parent)
393
+ layout_kw = self._split_layout_kwargs(kwargs)
394
+ layout_kw.setdefault("horizontal", "stretch")
395
+
396
+ tk_master = self._parent._child_master() if self._parent else None
397
+
398
+ internal_kwargs: dict[str, Any] = {
399
+ "allow_multiple": allow_multiple,
400
+ "allow_collapse_all": allow_collapse_all,
401
+ "show_separators": show_separators,
402
+ }
403
+ if show_border:
404
+ internal_kwargs["show_border"] = True
405
+ if variant is not None:
406
+ internal_kwargs["variant"] = variant
407
+ if accent is not None:
408
+ internal_kwargs["accent"] = accent
409
+ if padding is not None:
410
+ internal_kwargs["padding"] = padding
411
+
412
+ self._sections: dict[str, AccordionSection] = {}
413
+ self._internal = _InternalAccordion(tk_master, **internal_kwargs)
414
+ self._attach_to_parent(layout_kw)
415
+
416
+ # ----- Section management -----
417
+
418
+ def remove(self, key: str) -> None:
419
+ """Remove a section by key.
420
+
421
+ Args:
422
+ key: The key assigned when the section was added.
423
+ """
424
+ self._internal.remove(key)
425
+ self._sections.pop(key, None)
426
+
427
+ def item(self, key: str) -> AccordionSection:
428
+ """Return the section handle for `key`.
429
+
430
+ Args:
431
+ key: Section key.
432
+
433
+ Returns:
434
+ The `AccordionSection` for that key — read `expanded`/`title` or call
435
+ `expand()`/`collapse()`/`toggle()` to drive it.
436
+ """
437
+ return self._sections[key]
438
+
439
+ def items(self, expanded: bool | None = None) -> tuple[AccordionSection, ...]:
440
+ """Return all section handles in insertion order, optionally filtered.
441
+
442
+ Args:
443
+ expanded: If `True`, return only expanded sections. If `False`,
444
+ only collapsed. If `None` (default), return all.
445
+
446
+ Returns:
447
+ A tuple of `AccordionSection` handles.
448
+ """
449
+ sections = (self._sections[k] for k in self._internal.keys())
450
+ if expanded is None:
451
+ return tuple(sections)
452
+ return tuple(s for s in sections if s.expanded == expanded)
453
+
454
+ def keys(self) -> tuple[str, ...]:
455
+ """Return all section keys in insertion order."""
456
+ return self._internal.keys()
457
+
458
+ def expand(self, key: str) -> None:
459
+ """Expand the section identified by `key`.
460
+
461
+ Args:
462
+ key: Section key.
463
+ """
464
+ self._internal.expand(key)
465
+
466
+ def collapse(self, key: str) -> None:
467
+ """Collapse the section identified by `key`.
468
+
469
+ Args:
470
+ key: Section key.
471
+ """
472
+ self._internal.collapse(key)
473
+
474
+ def expand_all(self) -> None:
475
+ """Expand all sections."""
476
+ self._internal.expand_all()
477
+
478
+ def collapse_all(self) -> None:
479
+ """Collapse all sections."""
480
+ self._internal.collapse_all()
481
+
482
+ # ----- Events -----
483
+
484
+ @overload
485
+ def on_change(self) -> Stream: ...
486
+ @overload
487
+ def on_change(self, handler: Callable[[AccordionChangeEvent], Any]) -> Subscription: ...
488
+ def on_change(self, handler: Callable[[AccordionChangeEvent], Any] | None = None) -> Stream | Subscription:
489
+ """Register a callback fired when any section expands or collapses.
490
+
491
+ The handler receives an `AccordionChangeEvent`; `e.expanded` is the
492
+ tuple of currently expanded sections.
493
+
494
+ Returns:
495
+ `Subscription` (with handler) or `Stream` (without handler).
496
+ """
497
+ return self.on("change", handler)
498
+
499
+ def add(
500
+ self,
501
+ title: str,
502
+ *,
503
+ key: str | None = None,
504
+ layout: LayoutKind = "column",
505
+ padding: Padding | None = 16,
506
+ gap: int = 0,
507
+ horizontal_items: str | None = None,
508
+ vertical_items: str | None = None,
509
+ grow_items: bool = False,
510
+ columns: int | list[int | str] | None = None,
511
+ rows: int | list[int | str] | None = None,
512
+ auto_flow: AutoFlow = "row",
513
+ expanded: bool | None = None,
514
+ icon: str | None = None,
515
+ ) -> AccordionSection:
516
+ """Add a section and return a context manager for placing its children.
517
+
518
+ Args:
519
+ title: Section header text.
520
+ key: Unique identifier used with `item()`, `expand()`, `collapse()`,
521
+ and `remove()`. Auto-generated if omitted.
522
+ layout: Body layout. Defaults to `'column'`.
523
+ padding: Space between the section border and its body, in pixels.
524
+ Defaults to `16`.
525
+ gap: Space between body children in pixels. Defaults to `0`.
526
+ horizontal_items: How body children sit on the horizontal axis — edge
527
+ values `'left'`/`'center'`/`'right'`/`'stretch'`, plus `'space-*'`
528
+ when horizontal is the stacking axis. Defaults to `'stretch'` in grid mode,
529
+ `'center'` in a column and `'left'` in a row.
530
+ vertical_items: How body children sit on the vertical axis — edge
531
+ values `'top'`/`'center'`/`'bottom'`/`'stretch'`, plus `'space-*'`
532
+ when vertical is the stacking axis. Defaults to `'stretch'` in grid mode,
533
+ `'center'` in a row and `'top'` in a column.
534
+ grow_items: For `'column'`/`'row'`, when `True` every body child
535
+ grows equally to share the main axis. Defaults to `False`.
536
+ columns: Column definitions for `'grid'` layout. An integer sets
537
+ the number of equal-weight columns; a list sets per-column
538
+ weights or sizes (e.g. `[1, 2, 'auto', '120px']`).
539
+ Defaults to `None`.
540
+ rows: Row definitions for `'grid'` layout. Defaults to `None`.
541
+ auto_flow: Grid placement direction. Defaults to `'row'`.
542
+ expanded: Whether the section starts expanded. Defaults to the
543
+ accordion's own default (collapsed when `allow_multiple=False`).
544
+ icon: Icon name or spec displayed in the section header.
545
+
546
+ Returns:
547
+ `AccordionSection` — use as a context manager to place children.
548
+ """
549
+ exp_kwargs: dict[str, Any] = {}
550
+ if key is not None:
551
+ exp_kwargs["key"] = key
552
+ if expanded is not None:
553
+ exp_kwargs["expanded"] = expanded
554
+ if icon is not None:
555
+ exp_kwargs["icon"] = icon
556
+ internal_exp = self._internal.add(title=title, **exp_kwargs)
557
+ # The internal accordion auto-generates a key when one is not supplied;
558
+ # recover the resolved key so the section handle can be looked up later.
559
+ resolved_key = next(
560
+ k for k, v in self._internal._expanders.items() if v is internal_exp
561
+ )
562
+ section = AccordionSection(
563
+ internal_exp,
564
+ key=resolved_key,
565
+ layout=layout,
566
+ padding=padding,
567
+ gap=gap,
568
+ horizontal_items=horizontal_items,
569
+ vertical_items=vertical_items,
570
+ grow_items=grow_items,
571
+ columns=columns,
572
+ rows=rows,
573
+ auto_flow=auto_flow,
574
+ )
575
+ self._sections[resolved_key] = section
576
+ return section
577
+
578
+
579
+ register_widget_events(Accordion, _ACCORDION_EVENTS)