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,121 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from bootstack.widgets._impl.primitives.gridframe import GridFrame
6
+ from bootstack.widgets._core.container import (
7
+ PublicContainer, GRID_KEYS, grid_sticky, _reject_legacy_child_kwargs,
8
+ )
9
+ from bootstack.widgets.types import (
10
+ AccentToken, SurfaceToken, HAlign, VAlign, Padding, AutoFlow,
11
+ )
12
+
13
+
14
+ class Grid(PublicContainer):
15
+ """A container that arranges children in rows and columns.
16
+
17
+ Children are auto-placed left-to-right, top-to-bottom by default. Column and
18
+ row sizes are set with weighted `columns=` / `rows=`; in-cell alignment is
19
+ controlled with `horizontal_items` and `vertical_items`, overridable per
20
+ child with `horizontal` / `vertical`.
21
+
22
+ Args:
23
+ columns: Column definitions. An integer creates that many
24
+ equal-weight columns. A list sets per-column weights or
25
+ sizes — integers are relative weights, `'auto'` sizes to
26
+ content, `'Npx'` sets a fixed pixel width (e.g. `'120px'`).
27
+ Defaults to `None` (single column, sized to content).
28
+ rows: Row definitions, same format as `columns`. Defaults to
29
+ `None` (rows added automatically as children are placed).
30
+ gap: Space in pixels between cells. An integer applies to both
31
+ axes; a 2-tuple `(col_gap, row_gap)` sets them
32
+ independently. Defaults to `0`.
33
+ horizontal_items: Horizontal in-cell alignment of every child —
34
+ `'stretch'` (fill the cell width), `'left'`, `'center'`, or
35
+ `'right'`. Override per child with `horizontal`. Defaults to
36
+ `'stretch'`.
37
+ vertical_items: Vertical in-cell alignment of every child —
38
+ `'stretch'` (fill the cell height), `'top'`, `'center'`, or
39
+ `'bottom'`. Override per child with `vertical`. Defaults to
40
+ `'stretch'`.
41
+ auto_flow: Auto-placement direction. Defaults to `'row'`.
42
+ padding: Space in pixels between the grid border and its
43
+ content. Defaults to `None` (no padding).
44
+ surface: Background token. Accepts a surface token, an accent
45
+ token, or any token with modifiers (e.g. `'primary[subtle]'`).
46
+ Defaults to `None` (inherits from parent surface).
47
+ show_border: When `True`, draws a 1 px border around the
48
+ grid. Use at least `padding=1` to give the border visual
49
+ clearance. Defaults to `False`.
50
+ width: Fixed width in pixels. Disables frame propagation —
51
+ see the note in :class:`Row` for sizing behavior.
52
+ Defaults to `None`.
53
+ height: Fixed height in pixels. Disables frame propagation —
54
+ see the note in :class:`Column` for sizing behavior.
55
+ Defaults to `None`.
56
+ parent: Override the context-stack parent widget.
57
+ **kwargs: Per-child placement options — `row`, `column`,
58
+ `rowspan`, `columnspan`, `horizontal`, `vertical`,
59
+ `margin`. See :doc:`/tasks/layout`.
60
+ """
61
+
62
+ def __init__(
63
+ self,
64
+ *,
65
+ parent: Any = None,
66
+ columns: int | list[int | str] | None = None,
67
+ rows: int | list[int | str] | None = None,
68
+ gap: int | tuple[int, int] = 0,
69
+ horizontal_items: HAlign = "stretch",
70
+ vertical_items: VAlign = "stretch",
71
+ auto_flow: AutoFlow = "row",
72
+ padding: Padding | None = None,
73
+ surface: SurfaceToken | AccentToken | str | None = None,
74
+ show_border: bool = False,
75
+ width: int | None = None,
76
+ height: int | None = None,
77
+ **kwargs: Any,
78
+ ) -> None:
79
+ self._parent = self._resolve_parent(parent)
80
+ layout_kw = self._split_layout_kwargs(kwargs)
81
+
82
+ frame_kwargs: dict[str, Any] = {
83
+ "rows": rows,
84
+ "columns": columns,
85
+ "gap": gap,
86
+ "auto_flow": auto_flow,
87
+ }
88
+ for k, v in {
89
+ "padding": padding,
90
+ "surface": surface,
91
+ }.items():
92
+ if v is not None:
93
+ frame_kwargs[k] = v
94
+ if show_border:
95
+ frame_kwargs["show_border"] = True
96
+ if width is not None:
97
+ frame_kwargs["width"] = width
98
+ if height is not None:
99
+ frame_kwargs["height"] = height
100
+ if width is not None or height is not None:
101
+ frame_kwargs["propagate"] = False
102
+
103
+ self._horizontal_items = horizontal_items
104
+ self._vertical_items = vertical_items
105
+
106
+ tk_master = self._parent._child_master() if self._parent else None
107
+ self._internal = GridFrame(tk_master, **frame_kwargs)
108
+ self._attach_to_parent(layout_kw)
109
+
110
+ def _default_layout_method(self) -> str:
111
+ return "grid"
112
+
113
+ def _merge_layout_options(self, child: Any, layout_kw: dict) -> tuple[str, dict]:
114
+ _reject_legacy_child_kwargs(layout_kw, "Grid")
115
+ options = {k: v for k, v in layout_kw.items() if k in GRID_KEYS}
116
+ # Derive the cell sticky from per-child horizontal/vertical, each falling
117
+ # back to the container default for its axis.
118
+ h = layout_kw.get("horizontal") or self._horizontal_items
119
+ v = layout_kw.get("vertical") or self._vertical_items
120
+ options["sticky"] = grid_sticky(h, v)
121
+ return ("grid", options)
@@ -0,0 +1,162 @@
1
+ from __future__ import annotations
2
+
3
+ import tkinter
4
+ from typing import Any
5
+
6
+ from bootstack.widgets._impl.primitives.labelframe import LabelFrame as _LabelFrame
7
+ from bootstack.widgets._impl.primitives.flexframe import FlexFrame
8
+ from bootstack.widgets._impl.primitives.gridframe import GridFrame
9
+ from bootstack.widgets._core.container import (
10
+ PublicContainer, GRID_KEYS, place_flex_child, grid_sticky,
11
+ _reject_legacy_child_kwargs,
12
+ )
13
+ from bootstack.widgets.types import (
14
+ AccentToken, Padding, LayoutKind, AutoFlow, LocalizeMode,
15
+ )
16
+
17
+
18
+ class GroupBox(PublicContainer):
19
+ """A labeled container that groups related content inside a bordered frame.
20
+
21
+ The title is embedded in the top border line, giving the classic fieldset
22
+ look. Children are laid out according to `layout`.
23
+
24
+ Args:
25
+ title: Text label embedded in the top border line. Defaults to an
26
+ empty string (border only, no label).
27
+ layout: Internal layout manager. Defaults to `'column'`.
28
+ padding: Space in pixels between the border and the content. A single
29
+ value applies to all sides; `(x, y)` sets the horizontal and
30
+ vertical amounts. Defaults to `16`.
31
+ accent: Color intent token applied to the border and title label.
32
+ When omitted, the border uses the theme's default foreground color.
33
+ gap: Space in pixels between child widgets. Defaults to `0`.
34
+ horizontal_items: How children sit on the horizontal axis — edge values
35
+ `'left'`/`'center'`/`'right'`/`'stretch'`, plus the `'space-*'` modes
36
+ when horizontal is the stacking axis (`'row'`). Override per child
37
+ with `horizontal`. Defaults to `'stretch'` in grid mode, `'center'` in a column
38
+ and `'left'` in a row.
39
+ vertical_items: How children sit on the vertical axis — edge values
40
+ `'top'`/`'center'`/`'bottom'`/`'stretch'`, plus the `'space-*'` modes
41
+ when vertical is the stacking axis (`'column'`). Override per child
42
+ with `vertical`. Defaults to `'stretch'` in grid mode, `'center'` in a row and `'top'` in a column.
43
+ grow_items: For `'column'`/`'row'` layout, when `True` every child
44
+ grows equally to share the main axis. Defaults to `False`.
45
+ columns: Column definitions for `'grid'` layout. An integer sets
46
+ the number of equal-weight columns; a list sets per-column
47
+ weights or sizes — integers are relative weights, `'auto'`
48
+ sizes to content, `'Npx'` sets a fixed pixel width (e.g.
49
+ `[1, 2, 'auto', '120px']`).
50
+ rows: Row definitions for `'grid'` layout, same format as `columns`.
51
+ auto_flow: Grid auto-placement direction. Defaults to `'row'`.
52
+ localize: Whether the title is translated through the catalog — `True`,
53
+ `False`, or `'auto'`. Defaults to the app's `localize_mode`.
54
+ parent: Override the context-stack parent widget.
55
+ **kwargs: Layout placement options applied by the parent container —
56
+ `fill`, `expand`, `anchor`, `margin`, `row`, `column`, `sticky`.
57
+ See :doc:`/tasks/layout`.
58
+ """
59
+
60
+ def __init__(
61
+ self,
62
+ title: str = "",
63
+ *,
64
+ layout: LayoutKind = "column",
65
+ padding: Padding | None = 16,
66
+ accent: AccentToken | str | None = None,
67
+ gap: int = 0,
68
+ horizontal_items: str | None = None,
69
+ vertical_items: str | None = None,
70
+ grow_items: bool = False,
71
+ columns: int | list[int | str] | None = None,
72
+ rows: int | list[int | str] | None = None,
73
+ auto_flow: AutoFlow = "row",
74
+ localize: LocalizeMode | None = None,
75
+ parent: Any = None,
76
+ **kwargs: Any,
77
+ ) -> None:
78
+ self._parent = self._resolve_parent(parent)
79
+ self._layout = layout
80
+ layout_kw = self._split_layout_kwargs(kwargs)
81
+
82
+ # One horizontal_items/vertical_items pair serves both modes; the sensible
83
+ # default differs — grid cells fill (stretch), stacked children sit at the
84
+ # leading edge (left/top).
85
+ if horizontal_items is None:
86
+ horizontal_items = (
87
+ "stretch" if layout == "grid"
88
+ else "center" if layout == "column" else "left"
89
+ )
90
+ if vertical_items is None:
91
+ vertical_items = (
92
+ "stretch" if layout == "grid"
93
+ else "center" if layout == "row" else "top"
94
+ )
95
+
96
+ tk_master = self._parent._child_master() if self._parent else None
97
+
98
+ lf_kwargs: dict[str, Any] = {"text": title, "padding": padding}
99
+ if accent is not None:
100
+ lf_kwargs["accent"] = accent
101
+ if localize is not None:
102
+ lf_kwargs["localize"] = localize
103
+
104
+ self._internal = _LabelFrame(tk_master, **lf_kwargs)
105
+
106
+ if layout in ("column", "row"):
107
+ self._layout_frame = FlexFrame(
108
+ self._internal,
109
+ direction="vertical" if layout == "column" else "horizontal",
110
+ gap=gap,
111
+ horizontal_items=horizontal_items,
112
+ vertical_items=vertical_items,
113
+ grow_items=grow_items,
114
+ )
115
+ elif layout == "grid":
116
+ self._layout_frame = GridFrame(
117
+ self._internal,
118
+ columns=columns,
119
+ rows=rows,
120
+ gap=gap,
121
+ auto_flow=auto_flow,
122
+ )
123
+ else:
124
+ raise ValueError(
125
+ f"GroupBox layout must be 'column', 'row', or 'grid', got {layout!r}"
126
+ )
127
+
128
+ self._horizontal_items = horizontal_items
129
+ self._vertical_items = vertical_items
130
+ self._layout_frame.pack(fill="both", expand=True)
131
+ self._attach_to_parent(layout_kw)
132
+
133
+ def _child_master(self) -> tkinter.Misc:
134
+ return self._layout_frame
135
+
136
+ def _default_layout_method(self) -> str:
137
+ return "grid" if self._layout == "grid" else "flex"
138
+
139
+ def guide_layout(self, child: Any, **layout_kw: Any) -> None:
140
+ if self._layout == "grid":
141
+ return super().guide_layout(child, **layout_kw)
142
+ place_flex_child(self._layout_frame, child, layout_kw, "GroupBox")
143
+
144
+ def _merge_layout_options(self, child: Any, layout_kw: dict) -> tuple[str, dict]:
145
+ # Only reached for grid layout (column/row use the flex path above).
146
+ _reject_legacy_child_kwargs(layout_kw, "GroupBox")
147
+ options = {k: v for k, v in layout_kw.items() if k in GRID_KEYS}
148
+ h = layout_kw.get("horizontal") or self._horizontal_items
149
+ v = layout_kw.get("vertical") or self._vertical_items
150
+ options["sticky"] = grid_sticky(h, v)
151
+ return ("grid", options)
152
+
153
+ # ----- Properties -----
154
+
155
+ @property
156
+ def title(self) -> str:
157
+ """The text embedded in the border."""
158
+ return self._internal.cget("text")
159
+
160
+ @title.setter
161
+ def title(self, value: str) -> None:
162
+ self._internal.configure(text=value)
@@ -0,0 +1,229 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import overload, Any, Callable, Literal, TYPE_CHECKING
4
+
5
+ from bootstack.widgets._impl.primitives.label import Label as _InternalLabel
6
+ from bootstack.widgets._impl.primitives.badge import Badge as _InternalBadge
7
+ from bootstack.widgets._core.base import PublicWidgetBase
8
+ from bootstack.widgets._core.events import register_widget_events
9
+ from bootstack.widgets._core.icon_image_props import IconProperty, ImageProperty
10
+ from bootstack.events import Event, Subscription
11
+ from bootstack.streams import Stream
12
+ from bootstack.widgets.types import (
13
+ AccentToken, SurfaceToken,
14
+ Anchor, Justify, Relief, CompoundMode, Padding, IconPosition, IconSpec,
15
+ )
16
+
17
+ if TYPE_CHECKING:
18
+ from bootstack.signals import Signal
19
+
20
+
21
+ class Label(IconProperty, ImageProperty, PublicWidgetBase):
22
+ """Static text display with optional icon, semantic styling, and font tokens.
23
+
24
+ The display text is the first positional argument. All options are
25
+ keyword-only.
26
+
27
+ Args:
28
+ text: Text to display.
29
+ textsignal: Reactive `Signal` bound to the display text. Updates
30
+ automatically when the signal changes. Combine with
31
+ `value_format=` to format numeric or date values.
32
+ value_format: Format applied to the `textsignal` value before display —
33
+ a named preset (e.g. `'decimal'`, `'currency'`, `'shortDate'`) or a
34
+ custom pattern (e.g. `'#,##0'`). Requires `textsignal=` and
35
+ localization enabled. See :ref:`format specs <value-formats>`.
36
+ image: An `Image` handle (from `bootstack.images`) to display, for custom
37
+ artwork rather than a Bootstrap Icon name. Also accepts a `get_icon`
38
+ result. Use `icon_position=` to control placement relative to text.
39
+ icon: Bootstrap Icons name (e.g. `'house'`, `'gear'`) — see the full
40
+ catalog at https://icons.getbootstrap.com — or an `IconSpec` mapping
41
+ (`{'name', 'size', 'color'}`) for control over size and color.
42
+ icon_only: If `True`, show only the icon. Auto-detected when
43
+ `text` is empty and `icon` is provided.
44
+ icon_position: Position of the icon or image relative to the text.
45
+ Only relevant when an icon or image is shown alongside text.
46
+ Default `'left'`.
47
+ anchor: Content alignment within the label area. Default `'center'`.
48
+ justify: Multi-line text alignment.
49
+ padding: Inner spacing around the text content.
50
+ width: Width in character units.
51
+ wrap_width: Maximum pixel width before text wraps. Set to enable
52
+ multi-line wrapping.
53
+ font: Semantic font token. Examples: `'body'`, `'heading-lg'`,
54
+ `'heading-md[bold]'`, `'caption'`, `'code'`, `'body+2[italic]'`.
55
+ accent: Semantic color applied to the text.
56
+ surface: Background surface context.
57
+ localize: Whether the text is translated through the catalog — `True`,
58
+ `False`, or `'auto'` (translate when a translation is registered,
59
+ otherwise show the literal). Defaults to the app's `localize_mode`.
60
+ Set `False` to keep a proper noun or identifier untranslated.
61
+ parent: Explicit parent widget. If omitted, the current context-stack
62
+ container is used.
63
+ """
64
+
65
+ _internal_class = _InternalLabel
66
+
67
+ def __init__(
68
+ self,
69
+ text: str = "",
70
+ *,
71
+ textsignal: "Signal | None" = None,
72
+ value_format: str | None = None,
73
+ image: Any = None,
74
+ icon: str | IconSpec | None = None,
75
+ icon_only: bool = False,
76
+ icon_position: IconPosition = "left",
77
+ anchor: Anchor | None = None,
78
+ justify: Justify | None = None,
79
+ padding: Padding | None = None,
80
+ width: int | None = None,
81
+ wrap_width: int | None = None,
82
+ font: str | None = None,
83
+ accent: AccentToken | Literal['muted'] | str | None = None,
84
+ surface: SurfaceToken | str | None = None,
85
+ localize: bool | Literal['auto'] | None = None,
86
+ parent: Any = None,
87
+ **kwargs: Any,
88
+ ) -> None:
89
+ # `variant` is not a public Label option (Label has only the implicit
90
+ # 'default'); it rides in via kwargs as the conduit for the Badge
91
+ # subclass, which sets its own 'square'/'pill' on a Badge ttk class.
92
+ variant = kwargs.pop("variant", None)
93
+ self._reject_signal_text(text)
94
+ self._parent = self._resolve_parent(parent)
95
+ layout_kw = self._split_layout_kwargs(kwargs)
96
+ tk_master = self._parent._child_master() if self._parent else None
97
+
98
+ internal_kwargs: dict[str, Any] = {}
99
+ if text:
100
+ internal_kwargs["text"] = text
101
+ if textsignal is not None:
102
+ internal_kwargs["textsignal"] = textsignal
103
+ if value_format is not None:
104
+ internal_kwargs["value_format"] = value_format
105
+ deferred_image = None
106
+ if image is not None:
107
+ from bootstack.images import Image as _ImageHandle
108
+
109
+ if isinstance(image, _ImageHandle):
110
+ deferred_image = image
111
+ has_text = bool(text) or textsignal is not None
112
+ if not has_text or icon_only:
113
+ internal_kwargs["icon_only"] = True
114
+ internal_kwargs["compound"] = "image"
115
+ else:
116
+ internal_kwargs["compound"] = icon_position
117
+ else:
118
+ internal_kwargs["image"] = image
119
+ if icon is not None:
120
+ internal_kwargs["icon"] = icon
121
+ has_text = bool(text) or textsignal is not None
122
+ if not has_text or icon_only:
123
+ internal_kwargs["icon_only"] = True
124
+ internal_kwargs["compound"] = "image"
125
+ else:
126
+ internal_kwargs["compound"] = icon_position
127
+ elif icon_only:
128
+ internal_kwargs["icon_only"] = True
129
+ if anchor is not None:
130
+ internal_kwargs["anchor"] = anchor
131
+ if justify is not None:
132
+ internal_kwargs["justify"] = justify
133
+ if padding is not None:
134
+ internal_kwargs["padding"] = padding
135
+ if width is not None:
136
+ internal_kwargs["width"] = width
137
+ if wrap_width is not None:
138
+ internal_kwargs["wraplength"] = wrap_width
139
+ if font is not None:
140
+ internal_kwargs["font"] = font
141
+ if accent is not None:
142
+ internal_kwargs["accent"] = accent
143
+ if variant is not None:
144
+ internal_kwargs["variant"] = variant
145
+ if surface is not None:
146
+ internal_kwargs["surface"] = surface
147
+ if localize is not None:
148
+ internal_kwargs["localize"] = localize
149
+
150
+ self._internal = self._internal_class(tk_master, **internal_kwargs)
151
+ if deferred_image is not None:
152
+ from bootstack.widgets._core.image_binding import bind_image
153
+
154
+ bind_image(self, self._internal, deferred_image)
155
+ self._attach_to_parent(layout_kw)
156
+
157
+ # ----- Properties -----
158
+
159
+ @property
160
+ def text(self) -> str:
161
+ """The displayed text."""
162
+ return str(self._internal.cget("text"))
163
+
164
+ @text.setter
165
+ def text(self, value: str) -> None:
166
+ # When a textsignal/textvariable owns the text, ttk ignores the `text`
167
+ # option — write through the variable instead (which also keeps the
168
+ # bound signal in sync). Falls back to the option when unbound.
169
+ textvar = getattr(self._internal, "_textvariable", None)
170
+ if textvar is not None:
171
+ textvar.set(value)
172
+ else:
173
+ self._internal.configure(text=value)
174
+
175
+ # ----- Events -----
176
+
177
+ @overload
178
+ def on_click(self) -> Stream: ...
179
+ @overload
180
+ def on_click(self, handler: Callable[[Event], Any]) -> Subscription: ...
181
+ def on_click(self, handler: Callable[[Event], Any] | None = None) -> Stream | Subscription:
182
+ """Register a callback for click events on this label.
183
+
184
+ Called with no handler, returns a composable `Stream`. Called with
185
+ a handler, binds it immediately and returns a `Subscription`. The
186
+ handler receives the curated `Event` (pointer position, modifier keys).
187
+
188
+ Args:
189
+ handler: Called with the click `Event` when the label is clicked.
190
+
191
+ Returns:
192
+ `Subscription` (with handler) or `Stream` (without handler).
193
+ """
194
+ return self.on("click", handler)
195
+
196
+
197
+ register_widget_events(Label, {})
198
+
199
+
200
+ class Badge(Label):
201
+ """Compact styled chip for status indicators, counts, and tags.
202
+
203
+ A `Badge` is a styled `Label` with a fixed visual shape. It accepts the
204
+ same kwargs as `Label`, but the icon and image elements are not rendered.
205
+
206
+ Args:
207
+ text: Text to display inside the badge.
208
+ accent: Color intent token for the badge. Defaults to `'primary'`.
209
+ variant: Shape variant — `'square'` is a rounded rectangle, `'pill'` is
210
+ fully rounded. Default `'square'`.
211
+ **kwargs: Other `Label` options (e.g. `font`, `padding`, `width`) plus
212
+ layout placement options applied by the parent container. See
213
+ :doc:`/tasks/layout`.
214
+ """
215
+
216
+ _internal_class = _InternalBadge
217
+
218
+ def __init__(
219
+ self,
220
+ text: str = "",
221
+ *,
222
+ accent: AccentToken | str = "primary",
223
+ variant: Literal["square", "pill"] = "square",
224
+ **kwargs: Any,
225
+ ) -> None:
226
+ super().__init__(text, accent=accent, variant=variant, **kwargs)
227
+
228
+
229
+ register_widget_events(Badge, {})