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.
- bootstack/__init__.py +157 -0
- bootstack/__main__.py +5 -0
- bootstack/_core/__init__.py +21 -0
- bootstack/_core/capabilities/__init__.py +45 -0
- bootstack/_core/capabilities/after.py +103 -0
- bootstack/_core/capabilities/bind.py +192 -0
- bootstack/_core/capabilities/bindtags.py +112 -0
- bootstack/_core/capabilities/busy.py +72 -0
- bootstack/_core/capabilities/clipboard.py +89 -0
- bootstack/_core/capabilities/focus.py +118 -0
- bootstack/_core/capabilities/grab.py +65 -0
- bootstack/_core/capabilities/grid.py +211 -0
- bootstack/_core/capabilities/localization.py +231 -0
- bootstack/_core/capabilities/pack.py +140 -0
- bootstack/_core/capabilities/place.py +113 -0
- bootstack/_core/capabilities/selection.py +136 -0
- bootstack/_core/capabilities/signals.py +244 -0
- bootstack/_core/capabilities/winfo.py +315 -0
- bootstack/_core/colorutils.py +234 -0
- bootstack/_core/exceptions.py +25 -0
- bootstack/_core/images.py +463 -0
- bootstack/_core/mixins/__init__.py +1 -0
- bootstack/_core/mixins/ttk_state.py +35 -0
- bootstack/_core/mixins/widget.py +132 -0
- bootstack/_core/paths.py +49 -0
- bootstack/_core/publisher.py +149 -0
- bootstack/_core/variables.py +62 -0
- bootstack/_runtime/__init__.py +3 -0
- bootstack/_runtime/app.py +930 -0
- bootstack/_runtime/base_window.py +945 -0
- bootstack/_runtime/events.py +399 -0
- bootstack/_runtime/shortcuts.py +496 -0
- bootstack/_runtime/tk_patch.py +43 -0
- bootstack/_runtime/toplevel.py +276 -0
- bootstack/_runtime/utility.py +457 -0
- bootstack/_runtime/visual_focus.py +240 -0
- bootstack/_runtime/window_utilities.py +1123 -0
- bootstack/assets/__init__.py +21 -0
- bootstack/assets/bootstack.ico +0 -0
- bootstack/assets/bootstack.png +0 -0
- bootstack/assets/elements/__init__.py +0 -0
- bootstack/assets/elements/badge-pill.png +0 -0
- bootstack/assets/elements/badge-square.png +0 -0
- bootstack/assets/elements/button-compact.png +0 -0
- bootstack/assets/elements/button-default.png +0 -0
- bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
- bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
- bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
- bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
- bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
- bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
- bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
- bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
- bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
- bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
- bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
- bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
- bootstack/assets/elements/card.png +0 -0
- bootstack/assets/elements/checkbox-checked.png +0 -0
- bootstack/assets/elements/checkbox-indeterminate.png +0 -0
- bootstack/assets/elements/checkbox-unchecked.png +0 -0
- bootstack/assets/elements/field.png +0 -0
- bootstack/assets/elements/input-addon-compact.png +0 -0
- bootstack/assets/elements/input-addon-default.png +0 -0
- bootstack/assets/elements/input-compact.png +0 -0
- bootstack/assets/elements/input-default.png +0 -0
- bootstack/assets/elements/list-item-separated.png +0 -0
- bootstack/assets/elements/list-item.png +0 -0
- bootstack/assets/elements/listrow-compact.png +0 -0
- bootstack/assets/elements/listrow-default.png +0 -0
- bootstack/assets/elements/manifest.toml +361 -0
- bootstack/assets/elements/menu-item.png +0 -0
- bootstack/assets/elements/navitem-compact.png +0 -0
- bootstack/assets/elements/navitem-default.png +0 -0
- bootstack/assets/elements/progressbar-h-compact.png +0 -0
- bootstack/assets/elements/progressbar-h-default.png +0 -0
- bootstack/assets/elements/progressbar-v-compact.png +0 -0
- bootstack/assets/elements/progressbar-v-default.png +0 -0
- bootstack/assets/elements/radiobutton.png +0 -0
- bootstack/assets/elements/scrollbar-horizontal.png +0 -0
- bootstack/assets/elements/scrollbar-vertical.png +0 -0
- bootstack/assets/elements/slider-handle.png +0 -0
- bootstack/assets/elements/slider-track-h.png +0 -0
- bootstack/assets/elements/slider-track-v.png +0 -0
- bootstack/assets/elements/switch-off.png +0 -0
- bootstack/assets/elements/switch-on.png +0 -0
- bootstack/assets/elements/tab-h.png +0 -0
- bootstack/assets/elements/tab-v.png +0 -0
- bootstack/assets/icons/bootstrap.ttf +0 -0
- bootstack/assets/icons/glyphmap.json +2080 -0
- bootstack/assets/icons/icon_metrics.json +12470 -0
- bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +878 -0
- bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +878 -0
- bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +854 -0
- bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +844 -0
- bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +917 -0
- bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +844 -0
- bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +844 -0
- bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +845 -0
- bootstack/cli/__init__.py +133 -0
- bootstack/cli/__main__.py +6 -0
- bootstack/cli/add.py +395 -0
- bootstack/cli/appicon.py +285 -0
- bootstack/cli/build.py +115 -0
- bootstack/cli/config.py +313 -0
- bootstack/cli/demo.py +564 -0
- bootstack/cli/dev.py +153 -0
- bootstack/cli/doctor.py +195 -0
- bootstack/cli/icons.py +98 -0
- bootstack/cli/promote.py +120 -0
- bootstack/cli/pyinstaller.py +268 -0
- bootstack/cli/run.py +95 -0
- bootstack/cli/start.py +117 -0
- bootstack/cli/templates/__init__.py +931 -0
- bootstack/clipboard.py +48 -0
- bootstack/constants.py +318 -0
- bootstack/data/README.md +615 -0
- bootstack/data/__init__.py +78 -0
- bootstack/data/_observable.py +276 -0
- bootstack/data/base.py +780 -0
- bootstack/data/file_source.py +367 -0
- bootstack/data/memory_source.py +450 -0
- bootstack/data/query.py +367 -0
- bootstack/data/readers.py +289 -0
- bootstack/data/sqlite_source.py +869 -0
- bootstack/data/types.py +354 -0
- bootstack/data/writers.py +232 -0
- bootstack/dev/__init__.py +36 -0
- bootstack/dev/_capture.py +141 -0
- bootstack/dev/_env.py +43 -0
- bootstack/dev/_registry.py +140 -0
- bootstack/dev/_reloader.py +351 -0
- bootstack/dev/_reset.py +50 -0
- bootstack/dev/_watcher.py +91 -0
- bootstack/dialogs/__init__.py +948 -0
- bootstack/dialogs/_impl/__init__.py +47 -0
- bootstack/dialogs/_impl/colorchooser.py +588 -0
- bootstack/dialogs/_impl/datedialog.py +450 -0
- bootstack/dialogs/_impl/dialog.py +594 -0
- bootstack/dialogs/_impl/filterdialog.py +358 -0
- bootstack/dialogs/_impl/fontdialog.py +364 -0
- bootstack/dialogs/_impl/formdialog.py +564 -0
- bootstack/dialogs/_impl/message.py +486 -0
- bootstack/dialogs/_impl/query.py +570 -0
- bootstack/errors.py +67 -0
- bootstack/events/__init__.py +111 -0
- bootstack/events/_event.py +135 -0
- bootstack/events/_payloads.py +539 -0
- bootstack/events/_subscription.py +38 -0
- bootstack/i18n/README.md +77 -0
- bootstack/i18n/__init__.py +23 -0
- bootstack/i18n/catalog.py +121 -0
- bootstack/i18n/intl_format.py +584 -0
- bootstack/i18n/msgcat.py +425 -0
- bootstack/i18n/specs.py +156 -0
- bootstack/images.py +563 -0
- bootstack/py.typed +1 -0
- bootstack/scheduling/__init__.py +11 -0
- bootstack/scheduling/_schedule.py +218 -0
- bootstack/shortcuts.py +21 -0
- bootstack/signals/README.md +98 -0
- bootstack/signals/__init__.py +10 -0
- bootstack/signals/integration.py +100 -0
- bootstack/signals/signal.py +353 -0
- bootstack/signals/types.py +6 -0
- bootstack/store.py +286 -0
- bootstack/streams/__init__.py +12 -0
- bootstack/streams/_stream.py +321 -0
- bootstack/style/__init__.py +38 -0
- bootstack/style/builders/__init__.py +51 -0
- bootstack/style/builders/badge.py +46 -0
- bootstack/style/builders/button.py +339 -0
- bootstack/style/builders/buttongroup.py +311 -0
- bootstack/style/builders/calendar.py +271 -0
- bootstack/style/builders/checkbutton.py +110 -0
- bootstack/style/builders/combobox.py +113 -0
- bootstack/style/builders/contextmenu.py +268 -0
- bootstack/style/builders/entry.py +82 -0
- bootstack/style/builders/expander.py +148 -0
- bootstack/style/builders/field.py +335 -0
- bootstack/style/builders/frame.py +50 -0
- bootstack/style/builders/label.py +28 -0
- bootstack/style/builders/labelframe.py +34 -0
- bootstack/style/builders/listview.py +369 -0
- bootstack/style/builders/menubar.py +91 -0
- bootstack/style/builders/menubutton.py +359 -0
- bootstack/style/builders/panedwindow.py +25 -0
- bootstack/style/builders/progressbar.py +67 -0
- bootstack/style/builders/radiobutton.py +99 -0
- bootstack/style/builders/scale.py +64 -0
- bootstack/style/builders/scrollbar.py +225 -0
- bootstack/style/builders/separator.py +49 -0
- bootstack/style/builders/sidenav.py +643 -0
- bootstack/style/builders/sizegrip.py +15 -0
- bootstack/style/builders/spinbox.py +119 -0
- bootstack/style/builders/switch.py +70 -0
- bootstack/style/builders/tabitem.py +204 -0
- bootstack/style/builders/togglegroup.py +294 -0
- bootstack/style/builders/toolbutton.py +275 -0
- bootstack/style/builders/tooltip.py +26 -0
- bootstack/style/builders/treeview.py +193 -0
- bootstack/style/builders/utils.py +455 -0
- bootstack/style/builders_tk/__init__.py +16 -0
- bootstack/style/builders_tk/defaults.py +229 -0
- bootstack/style/element.py +173 -0
- bootstack/style/fonts.py +123 -0
- bootstack/style/style.py +609 -0
- bootstack/style/style_builder_base.py +716 -0
- bootstack/style/style_builder_mixed.py +93 -0
- bootstack/style/style_builder_tk.py +109 -0
- bootstack/style/style_builder_ttk.py +353 -0
- bootstack/style/style_resolver.py +447 -0
- bootstack/style/theme.py +245 -0
- bootstack/style/theme_provider.py +471 -0
- bootstack/style/themes/__init__.py +128 -0
- bootstack/style/tk_patch.py +5 -0
- bootstack/style/token_maps.py +41 -0
- bootstack/style/types.py +32 -0
- bootstack/style/typography.py +523 -0
- bootstack/style/utility.py +746 -0
- bootstack/types.py +39 -0
- bootstack/validation/__init__.py +6 -0
- bootstack/validation/types.py +15 -0
- bootstack/validation/validation_result.py +17 -0
- bootstack/validation/validation_rules.py +205 -0
- bootstack/widgets/__init__.py +74 -0
- bootstack/widgets/_core/__init__.py +31 -0
- bootstack/widgets/_core/app_config.py +266 -0
- bootstack/widgets/_core/base.py +461 -0
- bootstack/widgets/_core/container.py +334 -0
- bootstack/widgets/_core/context.py +35 -0
- bootstack/widgets/_core/events.py +130 -0
- bootstack/widgets/_core/field_mixin.py +353 -0
- bootstack/widgets/_core/icon_image_props.py +72 -0
- bootstack/widgets/_core/image_binding.py +93 -0
- bootstack/widgets/_core/navmodel.py +345 -0
- bootstack/widgets/_core/options.py +210 -0
- bootstack/widgets/_core/selection_group.py +130 -0
- bootstack/widgets/_core/window_controls.py +96 -0
- bootstack/widgets/_core/window_menu.py +246 -0
- bootstack/widgets/_impl/__init__.py +1 -0
- bootstack/widgets/_impl/_internal/__init__.py +0 -0
- bootstack/widgets/_impl/_internal/wrapper_base.py +307 -0
- bootstack/widgets/_impl/_parts/__init__.py +11 -0
- bootstack/widgets/_impl/_parts/numberentry_part.py +385 -0
- bootstack/widgets/_impl/_parts/spinnerentry_part.py +434 -0
- bootstack/widgets/_impl/_parts/textentry_part.py +406 -0
- bootstack/widgets/_impl/composites/__init__.py +33 -0
- bootstack/widgets/_impl/composites/_dateutils.py +33 -0
- bootstack/widgets/_impl/composites/_image_fit.py +105 -0
- bootstack/widgets/_impl/composites/accordion.py +381 -0
- bootstack/widgets/_impl/composites/avatar.py +191 -0
- bootstack/widgets/_impl/composites/buttongroup.py +371 -0
- bootstack/widgets/_impl/composites/calendar.py +972 -0
- bootstack/widgets/_impl/composites/carousel.py +567 -0
- bootstack/widgets/_impl/composites/chart.py +882 -0
- bootstack/widgets/_impl/composites/compositeframe.py +298 -0
- bootstack/widgets/_impl/composites/contextmenu.py +1951 -0
- bootstack/widgets/_impl/composites/dateentry.py +404 -0
- bootstack/widgets/_impl/composites/dropdownbutton.py +325 -0
- bootstack/widgets/_impl/composites/expander.py +515 -0
- bootstack/widgets/_impl/composites/field.py +670 -0
- bootstack/widgets/_impl/composites/form.py +1066 -0
- bootstack/widgets/_impl/composites/gallery.py +551 -0
- bootstack/widgets/_impl/composites/list/__init__.py +15 -0
- bootstack/widgets/_impl/composites/list/listitem.py +802 -0
- bootstack/widgets/_impl/composites/list/listview.py +1433 -0
- bootstack/widgets/_impl/composites/menu/__init__.py +18 -0
- bootstack/widgets/_impl/composites/menu/model.py +358 -0
- bootstack/widgets/_impl/composites/menu/render_native.py +134 -0
- bootstack/widgets/_impl/composites/menu/render_themed.py +134 -0
- bootstack/widgets/_impl/composites/meter.py +860 -0
- bootstack/widgets/_impl/composites/numericentry.py +201 -0
- bootstack/widgets/_impl/composites/pagestack.py +395 -0
- bootstack/widgets/_impl/composites/passwordentry.py +142 -0
- bootstack/widgets/_impl/composites/pathentry.py +168 -0
- bootstack/widgets/_impl/composites/picture.py +289 -0
- bootstack/widgets/_impl/composites/radiogroup.py +511 -0
- bootstack/widgets/_impl/composites/scrolledtext.py +375 -0
- bootstack/widgets/_impl/composites/scrolledtext.pyi +186 -0
- bootstack/widgets/_impl/composites/scrollview.py +764 -0
- bootstack/widgets/_impl/composites/selectbox.py +1026 -0
- bootstack/widgets/_impl/composites/shell/__init__.py +40 -0
- bootstack/widgets/_impl/composites/shell/content_host.py +52 -0
- bootstack/widgets/_impl/composites/shell/layout.py +335 -0
- bootstack/widgets/_impl/composites/shell/nav_panel.py +345 -0
- bootstack/widgets/_impl/composites/shell/providers.py +558 -0
- bootstack/widgets/_impl/composites/shell/rail.py +117 -0
- bootstack/widgets/_impl/composites/shell/shell.py +581 -0
- bootstack/widgets/_impl/composites/shell/workspace.py +273 -0
- bootstack/widgets/_impl/composites/sidenav/__init__.py +16 -0
- bootstack/widgets/_impl/composites/sidenav/header.py +81 -0
- bootstack/widgets/_impl/composites/sidenav/separator.py +44 -0
- bootstack/widgets/_impl/composites/slider/__init__.py +7 -0
- bootstack/widgets/_impl/composites/slider/_shared.py +195 -0
- bootstack/widgets/_impl/composites/slider/rangeslider.py +982 -0
- bootstack/widgets/_impl/composites/slider/slider.py +851 -0
- bootstack/widgets/_impl/composites/spinnerentry.py +185 -0
- bootstack/widgets/_impl/composites/tableview/__init__.py +5 -0
- bootstack/widgets/_impl/composites/tableview/tableview.py +3388 -0
- bootstack/widgets/_impl/composites/tableview/types.py +169 -0
- bootstack/widgets/_impl/composites/tabs/__init__.py +23 -0
- bootstack/widgets/_impl/composites/tabs/tabitem.py +389 -0
- bootstack/widgets/_impl/composites/tabs/tabs.py +974 -0
- bootstack/widgets/_impl/composites/tabs/tabview.py +650 -0
- bootstack/widgets/_impl/composites/textarea/__init__.py +26 -0
- bootstack/widgets/_impl/composites/textarea/change.py +46 -0
- bootstack/widgets/_impl/composites/textarea/codeeditor.py +526 -0
- bootstack/widgets/_impl/composites/textarea/core.py +495 -0
- bootstack/widgets/_impl/composites/textarea/decoration.py +42 -0
- bootstack/widgets/_impl/composites/textarea/diff.py +127 -0
- bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +1 -0
- bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +138 -0
- bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +158 -0
- bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +138 -0
- bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +312 -0
- bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +177 -0
- bootstack/widgets/_impl/composites/textarea/filter.py +171 -0
- bootstack/widgets/_impl/composites/textarea/search_overlay.py +459 -0
- bootstack/widgets/_impl/composites/textarea/sidebar.py +88 -0
- bootstack/widgets/_impl/composites/textarea/style_registry.py +178 -0
- bootstack/widgets/_impl/composites/textarea/textarea.py +606 -0
- bootstack/widgets/_impl/composites/textarea/undo.py +217 -0
- bootstack/widgets/_impl/composites/textentry.py +57 -0
- bootstack/widgets/_impl/composites/timeentry.py +176 -0
- bootstack/widgets/_impl/composites/toast.py +390 -0
- bootstack/widgets/_impl/composites/toast_stack.py +156 -0
- bootstack/widgets/_impl/composites/togglegroup.py +418 -0
- bootstack/widgets/_impl/composites/toolbar.py +608 -0
- bootstack/widgets/_impl/composites/tooltip.py +491 -0
- bootstack/widgets/_impl/composites/tree/__init__.py +7 -0
- bootstack/widgets/_impl/composites/tree/source_binding.py +136 -0
- bootstack/widgets/_impl/composites/tree/treeitem.py +393 -0
- bootstack/widgets/_impl/composites/tree/treenode.py +174 -0
- bootstack/widgets/_impl/composites/tree/treeview.py +841 -0
- bootstack/widgets/_impl/mixins/__init__.py +24 -0
- bootstack/widgets/_impl/mixins/configure_mixin.py +216 -0
- bootstack/widgets/_impl/mixins/entry_mixin.py +134 -0
- bootstack/widgets/_impl/mixins/font_mixin.py +368 -0
- bootstack/widgets/_impl/mixins/icon_mixin.py +61 -0
- bootstack/widgets/_impl/mixins/localization_mixin.py +253 -0
- bootstack/widgets/_impl/mixins/signal_mixin.py +268 -0
- bootstack/widgets/_impl/mixins/validation_mixin.py +226 -0
- bootstack/widgets/_impl/primitives/__init__.py +49 -0
- bootstack/widgets/_impl/primitives/_menubutton.py +107 -0
- bootstack/widgets/_impl/primitives/badge.py +45 -0
- bootstack/widgets/_impl/primitives/button.py +76 -0
- bootstack/widgets/_impl/primitives/card.py +45 -0
- bootstack/widgets/_impl/primitives/checkbutton.py +124 -0
- bootstack/widgets/_impl/primitives/checktoggle.py +62 -0
- bootstack/widgets/_impl/primitives/combobox.py +156 -0
- bootstack/widgets/_impl/primitives/entry.py +87 -0
- bootstack/widgets/_impl/primitives/flexframe.py +448 -0
- bootstack/widgets/_impl/primitives/frame.py +185 -0
- bootstack/widgets/_impl/primitives/gridframe.py +546 -0
- bootstack/widgets/_impl/primitives/label.py +84 -0
- bootstack/widgets/_impl/primitives/labelframe.py +54 -0
- bootstack/widgets/_impl/primitives/optionmenu.py +387 -0
- bootstack/widgets/_impl/primitives/packframe.py +227 -0
- bootstack/widgets/_impl/primitives/panedwindow.py +45 -0
- bootstack/widgets/_impl/primitives/progressbar.py +83 -0
- bootstack/widgets/_impl/primitives/radiobutton.py +115 -0
- bootstack/widgets/_impl/primitives/radiotoggle.py +54 -0
- bootstack/widgets/_impl/primitives/scrollbar.py +42 -0
- bootstack/widgets/_impl/primitives/separator.py +43 -0
- bootstack/widgets/_impl/primitives/sizegrip.py +33 -0
- bootstack/widgets/_impl/primitives/spinbox.py +95 -0
- bootstack/widgets/_impl/primitives/switch.py +44 -0
- bootstack/widgets/_impl/primitives/treeview.py +69 -0
- bootstack/widgets/app.py +371 -0
- bootstack/widgets/appshell.py +1179 -0
- bootstack/widgets/avatar.py +140 -0
- bootstack/widgets/boolean_controls.py +455 -0
- bootstack/widgets/button.py +224 -0
- bootstack/widgets/buttongroup.py +239 -0
- bootstack/widgets/calendar.py +195 -0
- bootstack/widgets/card.py +159 -0
- bootstack/widgets/carousel.py +241 -0
- bootstack/widgets/chart.py +302 -0
- bootstack/widgets/codeeditor.py +675 -0
- bootstack/widgets/contextmenu.py +371 -0
- bootstack/widgets/datatable.py +688 -0
- bootstack/widgets/datefield.py +395 -0
- bootstack/widgets/divider.py +60 -0
- bootstack/widgets/expander.py +579 -0
- bootstack/widgets/form.py +200 -0
- bootstack/widgets/gallery.py +250 -0
- bootstack/widgets/gauge.py +168 -0
- bootstack/widgets/grid.py +121 -0
- bootstack/widgets/groupbox.py +162 -0
- bootstack/widgets/label.py +229 -0
- bootstack/widgets/listview.py +354 -0
- bootstack/widgets/menubutton.py +419 -0
- bootstack/widgets/numberfield.py +431 -0
- bootstack/widgets/pagestack.py +345 -0
- bootstack/widgets/passwordfield.py +383 -0
- bootstack/widgets/pathfield.py +454 -0
- bootstack/widgets/picture.py +251 -0
- bootstack/widgets/progressbar.py +106 -0
- bootstack/widgets/radio_variants.py +271 -0
- bootstack/widgets/radiogroup.py +228 -0
- bootstack/widgets/scrollbar.py +64 -0
- bootstack/widgets/scrollview.py +186 -0
- bootstack/widgets/select.py +302 -0
- bootstack/widgets/selectbutton.py +182 -0
- bootstack/widgets/sidebar_toggle.py +130 -0
- bootstack/widgets/sizegrip.py +42 -0
- bootstack/widgets/slider.py +408 -0
- bootstack/widgets/spinbox.py +147 -0
- bootstack/widgets/spinnerfield.py +413 -0
- bootstack/widgets/splash.py +367 -0
- bootstack/widgets/splitview.py +482 -0
- bootstack/widgets/stacks.py +249 -0
- bootstack/widgets/statusbar.py +189 -0
- bootstack/widgets/tabs.py +425 -0
- bootstack/widgets/textarea.py +459 -0
- bootstack/widgets/textfield.py +410 -0
- bootstack/widgets/theme_toggle.py +92 -0
- bootstack/widgets/timefield.py +340 -0
- bootstack/widgets/toast.py +314 -0
- bootstack/widgets/togglegroup.py +231 -0
- bootstack/widgets/toolbar.py +347 -0
- bootstack/widgets/tooltip.py +94 -0
- bootstack/widgets/tree.py +648 -0
- bootstack/widgets/types.py +305 -0
- bootstack/widgets/window.py +307 -0
- bootstack-0.1.0.dist-info/METADATA +301 -0
- bootstack-0.1.0.dist-info/RECORD +471 -0
- bootstack-0.1.0.dist-info/WHEEL +5 -0
- bootstack-0.1.0.dist-info/entry_points.txt +2 -0
- bootstack-0.1.0.dist-info/licenses/LICENSE +21 -0
- bootstack-0.1.0.dist-info/licenses/NOTICE +10 -0
- bootstack-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import tkinter
|
|
4
|
+
from typing import overload, Any, Callable, TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from bootstack.widgets._impl.composites.numericentry import NumericEntry as _InternalNumericEntry
|
|
7
|
+
from bootstack.widgets._core.base import PublicWidgetBase, adapt_handler
|
|
8
|
+
from bootstack.widgets._core.events import resolve_event, register_widget_events
|
|
9
|
+
from bootstack.widgets._core.field_mixin import FieldAddonMixin, ValueSignalMixin
|
|
10
|
+
from bootstack.events import ChangeEvent, InputEvent, Subscription, ValidationEvent
|
|
11
|
+
from bootstack.streams import Stream
|
|
12
|
+
from bootstack.widgets.textfield import _INNER_ENTRY_SEQUENCES
|
|
13
|
+
from bootstack.widgets.types import AccentToken, Event, Justify, WidgetDensity
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from bootstack.signals import Signal
|
|
17
|
+
|
|
18
|
+
def _as_number(raw: Any) -> int | float | None:
|
|
19
|
+
"""Coerce a field's stored value to a number, regardless of representation.
|
|
20
|
+
|
|
21
|
+
The numeric field stores its value as text in some code paths; the public
|
|
22
|
+
contract is that `value` (and the bound `signal`) is always a number.
|
|
23
|
+
"""
|
|
24
|
+
if raw is None or raw == "":
|
|
25
|
+
return None
|
|
26
|
+
if isinstance(raw, (int, float)):
|
|
27
|
+
return raw
|
|
28
|
+
try:
|
|
29
|
+
f = float(raw)
|
|
30
|
+
except (TypeError, ValueError):
|
|
31
|
+
return None
|
|
32
|
+
return int(f) if f.is_integer() else f
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
_NUMBER_FIELD_EVENTS: dict[str, str] = {
|
|
36
|
+
"input": "<<Input>>",
|
|
37
|
+
"change": "<<Change>>",
|
|
38
|
+
"valid": "<<Valid>>",
|
|
39
|
+
"invalid": "<<Invalid>>",
|
|
40
|
+
"validate": "<<Validate>>",
|
|
41
|
+
"submit": "<Return>",
|
|
42
|
+
"focus": "<FocusIn>",
|
|
43
|
+
"blur": "<FocusOut>",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class NumberField(ValueSignalMixin, FieldAddonMixin, PublicWidgetBase):
|
|
48
|
+
"""A numeric input field with optional stepper buttons.
|
|
49
|
+
|
|
50
|
+
Accepts integer or float values. Up/Down arrow keys and the mouse wheel
|
|
51
|
+
step the value by `step`. The field validates that the typed value is
|
|
52
|
+
numeric and within `min_value`/`max_value` bounds.
|
|
53
|
+
|
|
54
|
+
The initial value is the first positional argument. All options are
|
|
55
|
+
keyword-only.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
value: Initial numeric value. Defaults to `0`.
|
|
59
|
+
signal: Reactive `Signal` two-way bound to the field's numeric value.
|
|
60
|
+
Carries the parsed number (`int`/`float`), not the text. Use a
|
|
61
|
+
float-typed signal — `Signal(0.0)` — when the field accepts
|
|
62
|
+
fractional values, so they bind cleanly; an `int`-typed `Signal(0)`
|
|
63
|
+
holds whole numbers only. When given, it seeds the initial value.
|
|
64
|
+
This is the usual way to bind a number field.
|
|
65
|
+
label: Label displayed above the field.
|
|
66
|
+
message: Hint or helper text displayed below the field.
|
|
67
|
+
min_value: Minimum allowed value (inclusive). No lower bound if omitted.
|
|
68
|
+
max_value: Maximum allowed value (inclusive). No upper bound if omitted.
|
|
69
|
+
step: Amount added or subtracted per increment/decrement. Defaults to
|
|
70
|
+
`1`.
|
|
71
|
+
wrap: If `True`, stepping past `max_value` wraps to `min_value` and
|
|
72
|
+
vice versa (requires both bounds set). Defaults to `False`.
|
|
73
|
+
show_steppers: If `False`, hides the +/− stepper buttons. Defaults
|
|
74
|
+
to `True`.
|
|
75
|
+
required: If `True`, marks the field as required and prevents empty
|
|
76
|
+
submission.
|
|
77
|
+
read_only: If `True`, value is visible and selectable but not
|
|
78
|
+
editable.
|
|
79
|
+
disabled: If `True`, field is fully non-interactive and dimmed.
|
|
80
|
+
width: Width in character units.
|
|
81
|
+
justify: Text alignment inside the entry. Default `'left'`.
|
|
82
|
+
font: Semantic font token (e.g. `'body'`, `'code'`). See
|
|
83
|
+
:doc:`/reference/typography`.
|
|
84
|
+
value_format: Format applied when displaying the value — a named preset
|
|
85
|
+
(e.g. `'decimal'`, `'currency'`, `'percent'`) or a custom pattern
|
|
86
|
+
(e.g. `'#,##0.00'`). Requires localization enabled. See
|
|
87
|
+
:ref:`format specs <value-formats>`.
|
|
88
|
+
accent: Accent token applied to the focus ring.
|
|
89
|
+
density: Padding density.
|
|
90
|
+
parent: Explicit parent widget. If omitted, the current context-stack
|
|
91
|
+
container is used.
|
|
92
|
+
**kwargs: Layout placement options applied by the parent container —
|
|
93
|
+
`fill`, `expand`, `anchor`, `margin`, `row`, `column`, `sticky`.
|
|
94
|
+
See :doc:`/tasks/layout`.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
_VALIDATION_KIND = "number"
|
|
98
|
+
|
|
99
|
+
def __init__(
|
|
100
|
+
self,
|
|
101
|
+
value: int | float = 0,
|
|
102
|
+
*,
|
|
103
|
+
signal: "Signal | None" = None,
|
|
104
|
+
value_format: str | None = None,
|
|
105
|
+
label: str | None = None,
|
|
106
|
+
message: str | None = None,
|
|
107
|
+
min_value: int | float | None = None,
|
|
108
|
+
max_value: int | float | None = None,
|
|
109
|
+
step: int | float = 1,
|
|
110
|
+
wrap: bool = False,
|
|
111
|
+
show_steppers: bool = True,
|
|
112
|
+
required: bool = False,
|
|
113
|
+
read_only: bool = False,
|
|
114
|
+
disabled: bool = False,
|
|
115
|
+
width: int | None = None,
|
|
116
|
+
justify: Justify | None = None,
|
|
117
|
+
font: str | None = None,
|
|
118
|
+
accent: AccentToken | str | None = None,
|
|
119
|
+
density: WidgetDensity | None = None,
|
|
120
|
+
parent: Any = None,
|
|
121
|
+
**kwargs: Any,
|
|
122
|
+
) -> None:
|
|
123
|
+
self._parent = self._resolve_parent(parent)
|
|
124
|
+
layout_kw = self._split_layout_kwargs(kwargs)
|
|
125
|
+
if "textsignal" in kwargs:
|
|
126
|
+
raise TypeError(
|
|
127
|
+
"NumberField does not accept 'textsignal=' — a number field binds "
|
|
128
|
+
"its numeric value. Use signal= with a number-typed Signal "
|
|
129
|
+
"(e.g. Signal(0) or Signal(0.0))."
|
|
130
|
+
)
|
|
131
|
+
tk_master = self._parent._child_master() if self._parent else None
|
|
132
|
+
|
|
133
|
+
internal_kwargs: dict[str, Any] = {
|
|
134
|
+
"value": value,
|
|
135
|
+
"increment": step,
|
|
136
|
+
"show_spin_buttons": show_steppers,
|
|
137
|
+
}
|
|
138
|
+
if wrap:
|
|
139
|
+
internal_kwargs["wrap"] = True
|
|
140
|
+
if value_format is not None:
|
|
141
|
+
internal_kwargs["value_format"] = value_format
|
|
142
|
+
if label is not None:
|
|
143
|
+
internal_kwargs["label"] = label
|
|
144
|
+
if message is not None:
|
|
145
|
+
internal_kwargs["message"] = message
|
|
146
|
+
if min_value is not None:
|
|
147
|
+
internal_kwargs["minvalue"] = min_value
|
|
148
|
+
if max_value is not None:
|
|
149
|
+
internal_kwargs["maxvalue"] = max_value
|
|
150
|
+
if required:
|
|
151
|
+
internal_kwargs["required"] = True
|
|
152
|
+
if disabled:
|
|
153
|
+
internal_kwargs["state"] = "disabled"
|
|
154
|
+
elif read_only:
|
|
155
|
+
internal_kwargs["state"] = "readonly"
|
|
156
|
+
if width is not None:
|
|
157
|
+
internal_kwargs["width"] = width
|
|
158
|
+
if justify is not None:
|
|
159
|
+
internal_kwargs["justify"] = justify
|
|
160
|
+
if font is not None:
|
|
161
|
+
internal_kwargs["font"] = font
|
|
162
|
+
if accent is not None:
|
|
163
|
+
internal_kwargs["accent"] = accent
|
|
164
|
+
if density is not None:
|
|
165
|
+
internal_kwargs["density"] = density
|
|
166
|
+
|
|
167
|
+
self._internal = _InternalNumericEntry(tk_master, **internal_kwargs)
|
|
168
|
+
self._attach_to_parent(layout_kw)
|
|
169
|
+
|
|
170
|
+
if signal is not None:
|
|
171
|
+
self._bind_value_signal(signal)
|
|
172
|
+
|
|
173
|
+
# ----- Event routing -----
|
|
174
|
+
|
|
175
|
+
def _entry_widget(self) -> tkinter.Misc:
|
|
176
|
+
return self._internal._entry
|
|
177
|
+
|
|
178
|
+
@overload
|
|
179
|
+
def on(self, event: str) -> Stream: ...
|
|
180
|
+
@overload
|
|
181
|
+
def on(self, event: str, handler: Callable[[Event], Any]) -> Subscription: ...
|
|
182
|
+
def on(self, event: str, handler: Callable[[Event], Any] | None = None) -> Stream | Subscription:
|
|
183
|
+
"""Register a callback for an event by name.
|
|
184
|
+
|
|
185
|
+
A generic, string-keyed escape hatch — prefer the typed `on_*`
|
|
186
|
+
shorthands (e.g. `on_change`), which carry the precise payload type.
|
|
187
|
+
Called with no handler, returns a composable `Stream`; with a handler,
|
|
188
|
+
binds it and returns a `Subscription`.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
event: Event name (for example `'change'` or `'focus'`).
|
|
192
|
+
handler: Called with the event payload. Omit to get a composable
|
|
193
|
+
:class:`~bootstack.streams.Stream` instead.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
A cancellable :class:`~bootstack.events.Subscription` when a handler
|
|
197
|
+
is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
198
|
+
"""
|
|
199
|
+
sequence = resolve_event(self, str(event))
|
|
200
|
+
target = self._entry_widget() if sequence in _INNER_ENTRY_SEQUENCES else self._internal
|
|
201
|
+
if handler is None:
|
|
202
|
+
def _source(h):
|
|
203
|
+
t = self._entry_widget() if sequence in _INNER_ENTRY_SEQUENCES else self._internal
|
|
204
|
+
bid = t.bind(sequence, adapt_handler(h), add="+")
|
|
205
|
+
return Subscription(t, sequence, bid)
|
|
206
|
+
return Stream(self._internal, _source=_source)
|
|
207
|
+
bid = target.bind(sequence, adapt_handler(handler), add="+")
|
|
208
|
+
return Subscription(target, sequence, bid)
|
|
209
|
+
|
|
210
|
+
# ----- Properties -----
|
|
211
|
+
|
|
212
|
+
@property
|
|
213
|
+
def value(self) -> int | float | None:
|
|
214
|
+
"""The current numeric value, or `None` if the field is empty."""
|
|
215
|
+
return _as_number(self._internal.value)
|
|
216
|
+
|
|
217
|
+
@value.setter
|
|
218
|
+
def value(self, v: int | float) -> None:
|
|
219
|
+
self._internal.value = v
|
|
220
|
+
self._sync_value_set(v)
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def read_only(self) -> bool:
|
|
224
|
+
"""Whether the field is visible but not editable."""
|
|
225
|
+
return str(self._entry_widget().cget("state")) == "readonly"
|
|
226
|
+
|
|
227
|
+
@read_only.setter
|
|
228
|
+
def read_only(self, v: bool) -> None:
|
|
229
|
+
self._internal.configure(state="readonly" if v else "normal")
|
|
230
|
+
|
|
231
|
+
@property
|
|
232
|
+
def disabled(self) -> bool:
|
|
233
|
+
"""Whether the field is fully non-interactive."""
|
|
234
|
+
return str(self._entry_widget().cget("state")) == "disabled"
|
|
235
|
+
|
|
236
|
+
@disabled.setter
|
|
237
|
+
def disabled(self, v: bool) -> None:
|
|
238
|
+
self._internal.configure(state="disabled" if v else "normal")
|
|
239
|
+
|
|
240
|
+
# ----- Methods -----
|
|
241
|
+
|
|
242
|
+
def increment(self, steps: int = 1) -> None:
|
|
243
|
+
"""Increment the value by `steps` × step size.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
steps: Number of steps to increment. Defaults to `1`.
|
|
247
|
+
"""
|
|
248
|
+
self._internal.step(steps)
|
|
249
|
+
|
|
250
|
+
def decrement(self, steps: int = 1) -> None:
|
|
251
|
+
"""Decrement the value by `steps` × step size.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
steps: Number of steps to decrement. Defaults to `1`.
|
|
255
|
+
"""
|
|
256
|
+
self._internal.step(-steps)
|
|
257
|
+
|
|
258
|
+
def validate(self) -> bool:
|
|
259
|
+
"""Run validation rules against the current value.
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
`True` if all rules pass, `False` otherwise.
|
|
263
|
+
"""
|
|
264
|
+
entry = self._internal._entry
|
|
265
|
+
return entry.validate(entry._get_validation_value(), trigger="manual")
|
|
266
|
+
|
|
267
|
+
def focus(self) -> None:
|
|
268
|
+
"""Give keyboard focus to this field."""
|
|
269
|
+
self._entry_widget().focus_set()
|
|
270
|
+
|
|
271
|
+
def clear(self) -> None:
|
|
272
|
+
"""Clear the field, leaving it empty.
|
|
273
|
+
|
|
274
|
+
The value becomes `None` (an empty field), not `0` — so a cleared
|
|
275
|
+
required field still reads as blank.
|
|
276
|
+
"""
|
|
277
|
+
self._internal.value = ""
|
|
278
|
+
|
|
279
|
+
def select_all(self) -> None:
|
|
280
|
+
"""Select all text in the field."""
|
|
281
|
+
self._entry_widget().selection_range(0, "end")
|
|
282
|
+
|
|
283
|
+
def select_range(self, start: int, end: int) -> None:
|
|
284
|
+
"""Select text between `start` and `end` character positions.
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
start: Start index (0-based, inclusive).
|
|
288
|
+
end: End index (exclusive).
|
|
289
|
+
"""
|
|
290
|
+
self._entry_widget().selection_range(start, end)
|
|
291
|
+
|
|
292
|
+
# ----- Event shorthands -----
|
|
293
|
+
|
|
294
|
+
@overload
|
|
295
|
+
def on_input(self) -> Stream: ...
|
|
296
|
+
@overload
|
|
297
|
+
def on_input(self, handler: Callable[[InputEvent], Any]) -> Subscription: ...
|
|
298
|
+
def on_input(self, handler: Callable[[InputEvent], Any] | None = None) -> Stream | Subscription:
|
|
299
|
+
"""Register a callback fired on every keystroke.
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
handler: Called with an :class:`~bootstack.events.InputEvent`. Omit to
|
|
303
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
304
|
+
|
|
305
|
+
Returns:
|
|
306
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
307
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
308
|
+
"""
|
|
309
|
+
return self.on("input", handler)
|
|
310
|
+
|
|
311
|
+
@overload
|
|
312
|
+
def on_change(self) -> Stream: ...
|
|
313
|
+
@overload
|
|
314
|
+
def on_change(self, handler: Callable[[ChangeEvent], Any]) -> Subscription: ...
|
|
315
|
+
def on_change(self, handler: Callable[[ChangeEvent], Any] | None = None) -> Stream | Subscription:
|
|
316
|
+
"""Register a callback fired when the value is committed.
|
|
317
|
+
|
|
318
|
+
Args:
|
|
319
|
+
handler: Called with a :class:`~bootstack.events.ChangeEvent`. Omit to
|
|
320
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
321
|
+
|
|
322
|
+
Returns:
|
|
323
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
324
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
325
|
+
"""
|
|
326
|
+
return self.on("change", handler)
|
|
327
|
+
|
|
328
|
+
@overload
|
|
329
|
+
def on_submit(self) -> Stream: ...
|
|
330
|
+
@overload
|
|
331
|
+
def on_submit(self, handler: Callable[[Event], Any]) -> Subscription: ...
|
|
332
|
+
def on_submit(self, handler: Callable[[Event], Any] | None = None) -> Stream | Subscription:
|
|
333
|
+
"""Register a callback fired when the user presses Enter.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
handler: Called with an :class:`~bootstack.events.Event`. Omit to
|
|
337
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
341
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
342
|
+
"""
|
|
343
|
+
return self.on("submit", handler)
|
|
344
|
+
|
|
345
|
+
@overload
|
|
346
|
+
def on_focus(self) -> Stream: ...
|
|
347
|
+
@overload
|
|
348
|
+
def on_focus(self, handler: Callable[[Event], Any]) -> Subscription: ...
|
|
349
|
+
def on_focus(self, handler: Callable[[Event], Any] | None = None) -> Stream | Subscription:
|
|
350
|
+
"""Register a callback fired when the field gains focus.
|
|
351
|
+
|
|
352
|
+
Args:
|
|
353
|
+
handler: Called with an :class:`~bootstack.events.Event`. Omit to
|
|
354
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
355
|
+
|
|
356
|
+
Returns:
|
|
357
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
358
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
359
|
+
"""
|
|
360
|
+
return self.on("focus", handler)
|
|
361
|
+
|
|
362
|
+
@overload
|
|
363
|
+
def on_blur(self) -> Stream: ...
|
|
364
|
+
@overload
|
|
365
|
+
def on_blur(self, handler: Callable[[Event], Any]) -> Subscription: ...
|
|
366
|
+
def on_blur(self, handler: Callable[[Event], Any] | None = None) -> Stream | Subscription:
|
|
367
|
+
"""Register a callback fired when the field loses focus.
|
|
368
|
+
|
|
369
|
+
Args:
|
|
370
|
+
handler: Called with an :class:`~bootstack.events.Event`. Omit to
|
|
371
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
372
|
+
|
|
373
|
+
Returns:
|
|
374
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
375
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
376
|
+
"""
|
|
377
|
+
return self.on("blur", handler)
|
|
378
|
+
|
|
379
|
+
@overload
|
|
380
|
+
def on_valid(self) -> Stream: ...
|
|
381
|
+
@overload
|
|
382
|
+
def on_valid(self, handler: Callable[[ValidationEvent], Any]) -> Subscription: ...
|
|
383
|
+
def on_valid(self, handler: Callable[[ValidationEvent], Any] | None = None) -> Stream | Subscription:
|
|
384
|
+
"""Register a callback fired when validation passes.
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
handler: Called with a :class:`~bootstack.events.ValidationEvent`. Omit to
|
|
388
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
389
|
+
|
|
390
|
+
Returns:
|
|
391
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
392
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
393
|
+
"""
|
|
394
|
+
return self.on("valid", handler)
|
|
395
|
+
|
|
396
|
+
@overload
|
|
397
|
+
def on_invalid(self) -> Stream: ...
|
|
398
|
+
@overload
|
|
399
|
+
def on_invalid(self, handler: Callable[[ValidationEvent], Any]) -> Subscription: ...
|
|
400
|
+
def on_invalid(self, handler: Callable[[ValidationEvent], Any] | None = None) -> Stream | Subscription:
|
|
401
|
+
"""Register a callback fired when validation fails.
|
|
402
|
+
|
|
403
|
+
Args:
|
|
404
|
+
handler: Called with a :class:`~bootstack.events.ValidationEvent`. Omit to
|
|
405
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
406
|
+
|
|
407
|
+
Returns:
|
|
408
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
409
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
410
|
+
"""
|
|
411
|
+
return self.on("invalid", handler)
|
|
412
|
+
|
|
413
|
+
@overload
|
|
414
|
+
def on_validate(self) -> Stream: ...
|
|
415
|
+
@overload
|
|
416
|
+
def on_validate(self, handler: Callable[[ValidationEvent], Any]) -> Subscription: ...
|
|
417
|
+
def on_validate(self, handler: Callable[[ValidationEvent], Any] | None = None) -> Stream | Subscription:
|
|
418
|
+
"""Register a callback fired after any validation run.
|
|
419
|
+
|
|
420
|
+
Args:
|
|
421
|
+
handler: Called with a :class:`~bootstack.events.ValidationEvent`. Omit to
|
|
422
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
423
|
+
|
|
424
|
+
Returns:
|
|
425
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
426
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
427
|
+
"""
|
|
428
|
+
return self.on("validate", handler)
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
register_widget_events(NumberField, _NUMBER_FIELD_EVENTS)
|