SaaS-FrameWork 0.1.2__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {saas_framework-0.1.2 → saas_framework-0.1.4}/MANIFEST.in +1 -1
- saas_framework-0.1.4/PKG-INFO +116 -0
- saas_framework-0.1.4/README.md +90 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/SaaS_FrameWork.egg-info/SOURCES.txt +6 -1
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/__init__.py +6 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/buttons/DEx_BtnFAB.py +5 -3
- saas_framework-0.1.4/components/buttons/DEx_BtnFilled.py +34 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/buttons/DEx_BtnGhost.py +13 -2
- saas_framework-0.1.4/components/buttons/DEx_BtnPrimary.py +41 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/buttons/DEx_BtnSegmented.py +4 -2
- saas_framework-0.1.4/components/buttons/DEx_BtnText.py +36 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/buttons/DEx_BtnTonal.py +6 -3
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/cards/DEx_ContactCard.py +15 -5
- saas_framework-0.1.4/components/charts/DEx_BarChart.py +101 -0
- saas_framework-0.1.4/components/charts/DEx_LineChart.py +130 -0
- saas_framework-0.1.4/components/charts/DEx_PieChart.py +124 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/data/DEx_DataTable.py +20 -4
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/data/DEx_ListTile.py +4 -2
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/data/DEx_TreeView.py +7 -3
- saas_framework-0.1.4/components/feedback/DEx_AlertDialog.py +141 -0
- saas_framework-0.1.4/components/feedback/DEx_Notify.py +24 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_Checkbox.py +14 -2
- saas_framework-0.1.4/components/inputs/DEx_Dropdown.py +41 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_Slider.py +5 -2
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_Switch.py +5 -2
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_TagInput.py +5 -2
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_TextField.py +22 -3
- saas_framework-0.1.4/components/layout/DEx_AppShell.py +137 -0
- saas_framework-0.1.4/components/layout/DEx_Header.py +80 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_NavItem.py +4 -3
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_NavigationDrawer.py +9 -5
- saas_framework-0.1.4/components/layout/DEx_Sidebar.py +178 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_Stack.py +6 -3
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_Tabs.py +4 -2
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/metadata.py +35 -30
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/primitives/DEx_Avatar.py +5 -2
- saas_framework-0.1.4/components/primitives/__init__.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/project.py +23 -19
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/theme/DEx_ColorThemes.py +112 -14
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/theme/DEx_Theme.py +21 -7
- saas_framework-0.1.4/components/theme/platform_variant.py +72 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/pyproject.toml +9 -2
- saas_framework-0.1.2/PKG-INFO +0 -450
- saas_framework-0.1.2/README.md +0 -427
- saas_framework-0.1.2/components/buttons/DEx_BtnFilled.py +0 -20
- saas_framework-0.1.2/components/buttons/DEx_BtnPrimary.py +0 -21
- saas_framework-0.1.2/components/buttons/DEx_BtnText.py +0 -22
- saas_framework-0.1.2/components/feedback/DEx_AlertDialog.py +0 -26
- saas_framework-0.1.2/components/feedback/DEx_Notify.py +0 -17
- saas_framework-0.1.2/components/inputs/DEx_Dropdown.py +0 -25
- saas_framework-0.1.2/components/layout/DEx_AppShell.py +0 -80
- saas_framework-0.1.2/components/layout/DEx_Header.py +0 -57
- saas_framework-0.1.2/components/layout/DEx_Sidebar.py +0 -131
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/buttons/DEx_BtnIcon.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/buttons/DEx_MenuBar.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/buttons/DEx_PopupMenu.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/buttons/__init__.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/cards/DEx_Card.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/cards/DEx_MetricCard.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/cards/__init__.py +0 -0
- {saas_framework-0.1.2/components/data → saas_framework-0.1.4/components/charts}/__init__.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/data/DEx_ExpansionPanel.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/data/DEx_ExpansionTile.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/data/DEx_GridView.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/data/DEx_ListView.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/data/DEx_PipelineColumn.py +0 -0
- {saas_framework-0.1.2/components/feedback → saas_framework-0.1.4/components/data}/__init__.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/feedback/DEx_Banner.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/feedback/DEx_BottomSheet.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/feedback/DEx_ProgressBar.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/feedback/DEx_ProgressRing.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/feedback/DEx_Shimmer.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/feedback/DEx_Tooltip.py +0 -0
- {saas_framework-0.1.2/components/inputs → saas_framework-0.1.4/components/feedback}/__init__.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_AutoComplete.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_Chip.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_DatePicker.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_FilePicker.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_Radio.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_SearchBar.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_SearchField.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/inputs/DEx_TimePicker.py +0 -0
- {saas_framework-0.1.2/components/layout → saas_framework-0.1.4/components/inputs}/__init__.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_AnimatedSwitcher.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_AppBar.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_Draggable.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_GestureDetector.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_Marquee.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_NavigationBar.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_NavigationRail.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_ResponsiveRow.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/layout/DEx_Splitter.py +0 -0
- {saas_framework-0.1.2/components/primitives → saas_framework-0.1.4/components/layout}/__init__.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/primitives/DEx_Badge.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/primitives/DEx_Divider.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/primitives/DEx_Icon.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/primitives/DEx_Image.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/primitives/DEx_Markdown.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/primitives/DEx_SectionEyebrow.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/primitives/DEx_StatusDot.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/theme/__init__.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/components/versioning.py +0 -0
- {saas_framework-0.1.2 → saas_framework-0.1.4}/setup.cfg +0 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: SaaS-FrameWork
|
|
3
|
+
Version: 0.1.4
|
|
4
|
+
Summary: SaaS-FrameWork - sistema de componentes reutilizaveis para apps SaaS construido com Python e Flet
|
|
5
|
+
Author-email: Almir Duarte <almir.jg@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/DEx-SaaS/FrameWork
|
|
8
|
+
Keywords: flet,saas,framework,ui,components,design-system
|
|
9
|
+
Classifier: Development Status :: 1 - Planning
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
13
|
+
Requires-Python: >=3.13
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
Requires-Dist: flet==0.84.0
|
|
16
|
+
Requires-Dist: flet-charts==0.84.0
|
|
17
|
+
Provides-Extra: web
|
|
18
|
+
Requires-Dist: flet-web==0.84.0; extra == "web"
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: flet==0.84.0; extra == "dev"
|
|
21
|
+
Requires-Dist: pytest<10,>=9.1; extra == "dev"
|
|
22
|
+
Requires-Dist: build<2,>=1.3; extra == "dev"
|
|
23
|
+
Requires-Dist: twine<7,>=6.2; extra == "dev"
|
|
24
|
+
Provides-Extra: visual
|
|
25
|
+
Requires-Dist: playwright<2,>=1.40; extra == "visual"
|
|
26
|
+
|
|
27
|
+
# SaaS-FrameWork
|
|
28
|
+
|
|
29
|
+
Reusable SaaS UI components for [Flet](https://flet.dev): a versioned design system with
|
|
30
|
+
**70 catalogued components** — buttons, inputs, navigation, data tables and tree views,
|
|
31
|
+
overlays and dialogs, feedback, media and responsive layout — plus accessible color themes
|
|
32
|
+
and a navigable component catalog.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install SaaS-FrameWork
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
For web deployments, install the web extra:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install "SaaS-FrameWork[web]"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quickstart
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import flet as ft
|
|
50
|
+
from components import DEx_BtnPrimary, DEx_MetricCard, DEx_Notify, DEx_TextField
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def main(page: ft.Page) -> None:
|
|
54
|
+
page.title = "Hello SaaS-FrameWork"
|
|
55
|
+
name = DEx_TextField(label="Your name", hint="Type and press the button")
|
|
56
|
+
page.add(
|
|
57
|
+
DEx_MetricCard(label="Active users", value="1,024", delta="+12%"),
|
|
58
|
+
name,
|
|
59
|
+
DEx_BtnPrimary("Greet", on_click=lambda e: DEx_Notify(page, f"Hello, {name.value}!")),
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
ft.app(main)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Save as `hello.py` and run:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
python hello.py
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Every public component is importable straight from `components`
|
|
73
|
+
(`from components import DEx_DataTable, DEx_AppShell, ...`).
|
|
74
|
+
|
|
75
|
+
## Compatibility
|
|
76
|
+
|
|
77
|
+
| Requirement | Version |
|
|
78
|
+
|---|---|
|
|
79
|
+
| Python | `>= 3.13` |
|
|
80
|
+
| Flet | `== 0.84.0` (pinned) |
|
|
81
|
+
|
|
82
|
+
The Flet dependency is intentionally **pinned**: Flet's API still moves between releases, so
|
|
83
|
+
upgrades only land here after the project's upgrade policy revalidates all 70 use cases
|
|
84
|
+
against the candidate version. Installing this package therefore also pins your app's Flet
|
|
85
|
+
version.
|
|
86
|
+
|
|
87
|
+
## Component catalog
|
|
88
|
+
|
|
89
|
+
Browse every component, its use case, parameters and source in the live catalog:
|
|
90
|
+
|
|
91
|
+
- **Online:** https://saas-framework-catalog.onrender.com
|
|
92
|
+
- **Local (from the repository):** `flet run catalog/catalog.py`
|
|
93
|
+
|
|
94
|
+
The catalog has global search, maturity filters and a responsive layout, and is audited for
|
|
95
|
+
accessibility (WCAG AA contrast, keyboard navigation).
|
|
96
|
+
|
|
97
|
+
## Versioning and maturity
|
|
98
|
+
|
|
99
|
+
The project is **pre-1.0**: APIs may still change between minor releases. Each component
|
|
100
|
+
declares its own `COMPONENT_VERSION` and the catalog groups them into maturity bands —
|
|
101
|
+
Experimental (`0.0.x`), Evolving (`0.1.x+`) and Stable (`1.x+`). Every component change is
|
|
102
|
+
required (and CI-enforced) to bump the component version. Release history lives in
|
|
103
|
+
[CHANGELOG.md](CHANGELOG.md).
|
|
104
|
+
|
|
105
|
+
## Feedback
|
|
106
|
+
|
|
107
|
+
Bug reports, questions and suggestions: https://github.com/DEx-SaaS/FrameWork/issues
|
|
108
|
+
|
|
109
|
+
## Development
|
|
110
|
+
|
|
111
|
+
Contributor documentation — folder structure, naming conventions, versioning rules, test
|
|
112
|
+
suite and the component contract — lives in [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# SaaS-FrameWork
|
|
2
|
+
|
|
3
|
+
Reusable SaaS UI components for [Flet](https://flet.dev): a versioned design system with
|
|
4
|
+
**70 catalogued components** — buttons, inputs, navigation, data tables and tree views,
|
|
5
|
+
overlays and dialogs, feedback, media and responsive layout — plus accessible color themes
|
|
6
|
+
and a navigable component catalog.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install SaaS-FrameWork
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
For web deployments, install the web extra:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install "SaaS-FrameWork[web]"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quickstart
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
import flet as ft
|
|
24
|
+
from components import DEx_BtnPrimary, DEx_MetricCard, DEx_Notify, DEx_TextField
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def main(page: ft.Page) -> None:
|
|
28
|
+
page.title = "Hello SaaS-FrameWork"
|
|
29
|
+
name = DEx_TextField(label="Your name", hint="Type and press the button")
|
|
30
|
+
page.add(
|
|
31
|
+
DEx_MetricCard(label="Active users", value="1,024", delta="+12%"),
|
|
32
|
+
name,
|
|
33
|
+
DEx_BtnPrimary("Greet", on_click=lambda e: DEx_Notify(page, f"Hello, {name.value}!")),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
ft.app(main)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Save as `hello.py` and run:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
python hello.py
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Every public component is importable straight from `components`
|
|
47
|
+
(`from components import DEx_DataTable, DEx_AppShell, ...`).
|
|
48
|
+
|
|
49
|
+
## Compatibility
|
|
50
|
+
|
|
51
|
+
| Requirement | Version |
|
|
52
|
+
|---|---|
|
|
53
|
+
| Python | `>= 3.13` |
|
|
54
|
+
| Flet | `== 0.84.0` (pinned) |
|
|
55
|
+
|
|
56
|
+
The Flet dependency is intentionally **pinned**: Flet's API still moves between releases, so
|
|
57
|
+
upgrades only land here after the project's upgrade policy revalidates all 70 use cases
|
|
58
|
+
against the candidate version. Installing this package therefore also pins your app's Flet
|
|
59
|
+
version.
|
|
60
|
+
|
|
61
|
+
## Component catalog
|
|
62
|
+
|
|
63
|
+
Browse every component, its use case, parameters and source in the live catalog:
|
|
64
|
+
|
|
65
|
+
- **Online:** https://saas-framework-catalog.onrender.com
|
|
66
|
+
- **Local (from the repository):** `flet run catalog/catalog.py`
|
|
67
|
+
|
|
68
|
+
The catalog has global search, maturity filters and a responsive layout, and is audited for
|
|
69
|
+
accessibility (WCAG AA contrast, keyboard navigation).
|
|
70
|
+
|
|
71
|
+
## Versioning and maturity
|
|
72
|
+
|
|
73
|
+
The project is **pre-1.0**: APIs may still change between minor releases. Each component
|
|
74
|
+
declares its own `COMPONENT_VERSION` and the catalog groups them into maturity bands —
|
|
75
|
+
Experimental (`0.0.x`), Evolving (`0.1.x+`) and Stable (`1.x+`). Every component change is
|
|
76
|
+
required (and CI-enforced) to bump the component version. Release history lives in
|
|
77
|
+
[CHANGELOG.md](CHANGELOG.md).
|
|
78
|
+
|
|
79
|
+
## Feedback
|
|
80
|
+
|
|
81
|
+
Bug reports, questions and suggestions: https://github.com/DEx-SaaS/FrameWork/issues
|
|
82
|
+
|
|
83
|
+
## Development
|
|
84
|
+
|
|
85
|
+
Contributor documentation — folder structure, naming conventions, versioning rules, test
|
|
86
|
+
suite and the component contract — lives in [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT.
|
|
@@ -20,6 +20,10 @@ components/cards/DEx_Card.py
|
|
|
20
20
|
components/cards/DEx_ContactCard.py
|
|
21
21
|
components/cards/DEx_MetricCard.py
|
|
22
22
|
components/cards/__init__.py
|
|
23
|
+
components/charts/DEx_BarChart.py
|
|
24
|
+
components/charts/DEx_LineChart.py
|
|
25
|
+
components/charts/DEx_PieChart.py
|
|
26
|
+
components/charts/__init__.py
|
|
23
27
|
components/data/DEx_DataTable.py
|
|
24
28
|
components/data/DEx_ExpansionPanel.py
|
|
25
29
|
components/data/DEx_ExpansionTile.py
|
|
@@ -81,4 +85,5 @@ components/primitives/DEx_StatusDot.py
|
|
|
81
85
|
components/primitives/__init__.py
|
|
82
86
|
components/theme/DEx_ColorThemes.py
|
|
83
87
|
components/theme/DEx_Theme.py
|
|
84
|
-
components/theme/__init__.py
|
|
88
|
+
components/theme/__init__.py
|
|
89
|
+
components/theme/platform_variant.py
|
|
@@ -77,6 +77,10 @@ from components.feedback.DEx_ProgressBar import DEx_ProgressBar
|
|
|
77
77
|
from components.feedback.DEx_ProgressRing import DEx_ProgressRing
|
|
78
78
|
from components.feedback.DEx_Shimmer import DEx_ShimmerCard, DEx_ShimmerListItem, DEx_ShimmerList
|
|
79
79
|
|
|
80
|
+
from components.charts.DEx_LineChart import DEx_LineChart
|
|
81
|
+
from components.charts.DEx_BarChart import DEx_BarChart
|
|
82
|
+
from components.charts.DEx_PieChart import DEx_PieChart
|
|
83
|
+
|
|
80
84
|
__version__ = "0.1.1"
|
|
81
85
|
|
|
82
86
|
__all__ = [
|
|
@@ -120,6 +124,8 @@ __all__ = [
|
|
|
120
124
|
"DEx_Notify", "DEx_AlertDialog", "DEx_BottomSheet", "DEx_Banner",
|
|
121
125
|
"DEx_Tooltip", "DEx_ProgressBar", "DEx_ProgressRing",
|
|
122
126
|
"DEx_ShimmerCard", "DEx_ShimmerListItem", "DEx_ShimmerList",
|
|
127
|
+
# charts
|
|
128
|
+
"DEx_LineChart", "DEx_BarChart", "DEx_PieChart",
|
|
123
129
|
# meta
|
|
124
130
|
"__version__",
|
|
125
131
|
]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import flet as ft
|
|
2
2
|
from components.theme.DEx_Theme import Colors, Spacing
|
|
3
3
|
|
|
4
|
-
COMPONENT_VERSION = "0.0.
|
|
4
|
+
COMPONENT_VERSION = "0.0.2"
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def DEx_BtnFAB(
|
|
@@ -13,11 +13,13 @@ def DEx_BtnFAB(
|
|
|
13
13
|
"""Floating action button for the primary creation or positive action on a screen.
|
|
14
14
|
|
|
15
15
|
Pass label for extended FAB; omit for compact circular form.
|
|
16
|
+
Rótulo e ícone em ``ACCENT_ON`` (token semântico "sobre ACCENT") —
|
|
17
|
+
débito técnico 12, S12/atv11.
|
|
16
18
|
"""
|
|
17
19
|
if label:
|
|
18
20
|
return ft.FloatingActionButton(
|
|
19
21
|
content=ft.Row(
|
|
20
|
-
[ft.Icon(icon, size=18, color=Colors.
|
|
22
|
+
[ft.Icon(icon, size=18, color=Colors.ACCENT_ON), ft.Text(label, size=14, color=Colors.ACCENT_ON)],
|
|
21
23
|
spacing=8,
|
|
22
24
|
tight=True,
|
|
23
25
|
),
|
|
@@ -31,7 +33,7 @@ def DEx_BtnFAB(
|
|
|
31
33
|
on_click=on_click,
|
|
32
34
|
mini=mini,
|
|
33
35
|
bgcolor=Colors.ACCENT,
|
|
34
|
-
foreground_color=Colors.
|
|
36
|
+
foreground_color=Colors.ACCENT_ON,
|
|
35
37
|
hover_color=Colors.ACCENT_DARK,
|
|
36
38
|
shape=ft.RoundedRectangleBorder(radius=28),
|
|
37
39
|
)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import flet as ft
|
|
2
|
+
from components.theme.platform_variant import adaptive_kwargs, is_cupertino
|
|
3
|
+
from components.theme.DEx_Theme import Colors, Spacing
|
|
4
|
+
|
|
5
|
+
COMPONENT_VERSION = "0.1.0"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def DEx_BtnFilled(label: str, on_click=None, icon=None, platform: str | None = None):
|
|
9
|
+
"""Primary filled button — highest emphasis action in a view.
|
|
10
|
+
|
|
11
|
+
Rótulo em ``ACCENT_ON`` (token semântico "sobre ACCENT"), mesma higiene
|
|
12
|
+
do DEx_BtnPrimary — débito técnico 12, S12/atv11."""
|
|
13
|
+
if is_cupertino(platform):
|
|
14
|
+
return ft.CupertinoFilledButton(
|
|
15
|
+
content=label,
|
|
16
|
+
icon=icon,
|
|
17
|
+
on_click=on_click,
|
|
18
|
+
bgcolor=Colors.ACCENT,
|
|
19
|
+
color=Colors.ACCENT_ON,
|
|
20
|
+
border_radius=Spacing.BUTTON_BORDER_RADIUS,
|
|
21
|
+
)
|
|
22
|
+
return ft.FilledButton(
|
|
23
|
+
**adaptive_kwargs(platform),
|
|
24
|
+
content=label,
|
|
25
|
+
icon=icon,
|
|
26
|
+
on_click=on_click,
|
|
27
|
+
style=ft.ButtonStyle(
|
|
28
|
+
bgcolor=Colors.ACCENT,
|
|
29
|
+
color=Colors.ACCENT_ON,
|
|
30
|
+
overlay_color=Colors.ACCENT_DARK,
|
|
31
|
+
shape=ft.RoundedRectangleBorder(radius=Spacing.BUTTON_BORDER_RADIUS),
|
|
32
|
+
padding=ft.Padding.symmetric(horizontal=Spacing.MD, vertical=Spacing.SM + 2),
|
|
33
|
+
),
|
|
34
|
+
)
|
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import flet as ft
|
|
2
|
+
from components.theme.platform_variant import adaptive_kwargs, is_cupertino
|
|
2
3
|
from components.theme.DEx_Theme import Colors, Spacing
|
|
3
4
|
|
|
4
|
-
COMPONENT_VERSION = "0.
|
|
5
|
+
COMPONENT_VERSION = "0.2.0"
|
|
5
6
|
|
|
6
7
|
|
|
7
|
-
def DEx_BtnGhost(label: str, on_click=None, icon=None
|
|
8
|
+
def DEx_BtnGhost(label: str, on_click=None, icon=None, platform: str | None = None):
|
|
8
9
|
"""Create the versioned secondary outlined button for lower-emphasis actions."""
|
|
10
|
+
if is_cupertino(platform):
|
|
11
|
+
return ft.CupertinoButton(
|
|
12
|
+
content=label,
|
|
13
|
+
icon=icon,
|
|
14
|
+
on_click=on_click,
|
|
15
|
+
bgcolor="transparent",
|
|
16
|
+
color=Colors.TEXT_PRIMARY,
|
|
17
|
+
border_radius=Spacing.BUTTON_BORDER_RADIUS,
|
|
18
|
+
)
|
|
9
19
|
return ft.Button(
|
|
20
|
+
**adaptive_kwargs(platform),
|
|
10
21
|
content=label,
|
|
11
22
|
icon=icon,
|
|
12
23
|
on_click=on_click,
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import flet as ft
|
|
2
|
+
from components.theme.platform_variant import adaptive_kwargs, is_cupertino
|
|
3
|
+
from components.theme.DEx_Theme import Colors, Spacing
|
|
4
|
+
|
|
5
|
+
COMPONENT_VERSION = "0.2.0"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def DEx_BtnPrimary(label: str, on_click=None, icon=None, platform: str | None = None):
|
|
9
|
+
"""Create the versioned primary action button for main user commands.
|
|
10
|
+
|
|
11
|
+
Rótulo em ``ACCENT_ON`` — o token semântico "sobre ACCENT" (5.17:1 no
|
|
12
|
+
tema default e AA por construção nos presets, que trocam o rótulo para
|
|
13
|
+
escuro quando o accent do preset é claro). ``TEXT_PRIMARY`` passava no
|
|
14
|
+
tema default mas não acompanha os presets (débito técnico 12, S12/atv11).
|
|
15
|
+
|
|
16
|
+
``platform`` aceita ``"material"`` (padrão), ``"ios"`` (contraparte
|
|
17
|
+
Cupertino) e ``"auto"`` (o Flet escolhe em runtime) — ver
|
|
18
|
+
``components/theme/platform_variant.py``."""
|
|
19
|
+
if is_cupertino(platform):
|
|
20
|
+
return ft.CupertinoFilledButton(
|
|
21
|
+
content=label,
|
|
22
|
+
icon=icon,
|
|
23
|
+
on_click=on_click,
|
|
24
|
+
bgcolor=Colors.ACCENT,
|
|
25
|
+
color=Colors.ACCENT_ON,
|
|
26
|
+
border_radius=Spacing.BUTTON_BORDER_RADIUS,
|
|
27
|
+
)
|
|
28
|
+
return ft.Button(
|
|
29
|
+
**adaptive_kwargs(platform),
|
|
30
|
+
content=label,
|
|
31
|
+
icon=icon,
|
|
32
|
+
on_click=on_click,
|
|
33
|
+
bgcolor=Colors.ACCENT,
|
|
34
|
+
color=Colors.ACCENT_ON,
|
|
35
|
+
elevation=1,
|
|
36
|
+
style=ft.ButtonStyle(
|
|
37
|
+
overlay_color=Colors.ACCENT_DARK,
|
|
38
|
+
shape=ft.RoundedRectangleBorder(radius=Spacing.BUTTON_BORDER_RADIUS),
|
|
39
|
+
padding=ft.Padding.symmetric(horizontal=Spacing.MD, vertical=Spacing.SM + 2),
|
|
40
|
+
),
|
|
41
|
+
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import flet as ft
|
|
2
2
|
from components.theme.DEx_Theme import Colors, Spacing
|
|
3
3
|
|
|
4
|
-
COMPONENT_VERSION = "0.0.
|
|
4
|
+
COMPONENT_VERSION = "0.0.2"
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def DEx_BtnSegmented(
|
|
@@ -14,6 +14,8 @@ def DEx_BtnSegmented(
|
|
|
14
14
|
"""Multi-option toggle control for mutually exclusive or multi-select choices.
|
|
15
15
|
|
|
16
16
|
Each entry in segments: {"value": str, "label": str, "icon": str | None}
|
|
17
|
+
Rótulo do segmento selecionado em ``ACCENT_ON`` (token semântico
|
|
18
|
+
"sobre ACCENT") — débito técnico 12, S12/atv11.
|
|
17
19
|
"""
|
|
18
20
|
_selected = list(selected) if selected else [segments[0]["value"]]
|
|
19
21
|
return ft.SegmentedButton(
|
|
@@ -35,7 +37,7 @@ def DEx_BtnSegmented(
|
|
|
35
37
|
ft.ControlState.DEFAULT: Colors.BG_ELEVATED,
|
|
36
38
|
},
|
|
37
39
|
color={
|
|
38
|
-
ft.ControlState.SELECTED: Colors.
|
|
40
|
+
ft.ControlState.SELECTED: Colors.ACCENT_ON,
|
|
39
41
|
ft.ControlState.DEFAULT: Colors.TEXT_SECONDARY,
|
|
40
42
|
},
|
|
41
43
|
side=ft.BorderSide(1, Colors.BORDER),
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import flet as ft
|
|
2
|
+
from components.theme.platform_variant import adaptive_kwargs, is_cupertino
|
|
3
|
+
from components.theme.DEx_Theme import Colors, Spacing
|
|
4
|
+
|
|
5
|
+
COMPONENT_VERSION = "0.2.0"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def DEx_BtnText(label: str, on_click=None, icon=None, platform: str | None = None):
|
|
9
|
+
"""Lowest-emphasis action button: no border and no background fill.
|
|
10
|
+
|
|
11
|
+
Rótulo em ``ACCENT_TEXT`` (violeta AA para texto pequeno, >= 4.5:1 nos
|
|
12
|
+
três fundos) — ``ACCENT`` é token de UI e media 3.44:1 como texto
|
|
13
|
+
(débito técnico 12, S12/atv11)."""
|
|
14
|
+
if is_cupertino(platform):
|
|
15
|
+
return ft.CupertinoButton(
|
|
16
|
+
content=label,
|
|
17
|
+
icon=icon,
|
|
18
|
+
on_click=on_click,
|
|
19
|
+
bgcolor="transparent",
|
|
20
|
+
color=Colors.ACCENT_TEXT,
|
|
21
|
+
)
|
|
22
|
+
return ft.Button(
|
|
23
|
+
**adaptive_kwargs(platform),
|
|
24
|
+
content=label,
|
|
25
|
+
icon=icon,
|
|
26
|
+
on_click=on_click,
|
|
27
|
+
bgcolor="transparent",
|
|
28
|
+
color=Colors.ACCENT_TEXT,
|
|
29
|
+
elevation=0,
|
|
30
|
+
style=ft.ButtonStyle(
|
|
31
|
+
color=Colors.ACCENT_TEXT,
|
|
32
|
+
overlay_color=Colors.BG_ELEVATED,
|
|
33
|
+
shape=ft.RoundedRectangleBorder(radius=Spacing.BUTTON_BORDER_RADIUS),
|
|
34
|
+
padding=ft.Padding.symmetric(horizontal=Spacing.SM, vertical=Spacing.SM + 2),
|
|
35
|
+
),
|
|
36
|
+
)
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import flet as ft
|
|
2
2
|
from components.theme.DEx_Theme import Colors, Spacing
|
|
3
3
|
|
|
4
|
-
COMPONENT_VERSION = "0.0.
|
|
4
|
+
COMPONENT_VERSION = "0.0.2"
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def DEx_BtnTonal(label: str, on_click=None, icon=None) -> ft.FilledTonalButton:
|
|
8
|
-
"""Secondary filled button with muted emphasis — between outlined and filled.
|
|
8
|
+
"""Secondary filled button with muted emphasis — between outlined and filled.
|
|
9
|
+
|
|
10
|
+
Rótulo em ``ACCENT_TEXT`` (>= 4.76:1 sobre BG_ELEVATED) — ``ACCENT``
|
|
11
|
+
media 3.13:1 sobre o fundo elevado (débito técnico 12, S12/atv11)."""
|
|
9
12
|
return ft.FilledTonalButton(
|
|
10
13
|
content=label,
|
|
11
14
|
icon=icon,
|
|
12
15
|
on_click=on_click,
|
|
13
16
|
style=ft.ButtonStyle(
|
|
14
17
|
bgcolor=Colors.BG_ELEVATED,
|
|
15
|
-
color=Colors.
|
|
18
|
+
color=Colors.ACCENT_TEXT,
|
|
16
19
|
overlay_color=Colors.ACCENT_DARK,
|
|
17
20
|
shape=ft.RoundedRectangleBorder(radius=Spacing.BUTTON_BORDER_RADIUS),
|
|
18
21
|
padding=ft.Padding.symmetric(horizontal=Spacing.MD, vertical=Spacing.SM + 2),
|
|
@@ -4,7 +4,7 @@ from components.cards.DEx_Card import DEx_Card
|
|
|
4
4
|
from components.primitives.DEx_Badge import DEx_Badge
|
|
5
5
|
from components.primitives.DEx_Divider import DEx_Divider
|
|
6
6
|
|
|
7
|
-
COMPONENT_VERSION = "0.0.
|
|
7
|
+
COMPONENT_VERSION = "0.0.2"
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def DEx_ContactCard(
|
|
@@ -15,13 +15,19 @@ def DEx_ContactCard(
|
|
|
15
15
|
tag: str = None,
|
|
16
16
|
value: str = None,
|
|
17
17
|
) -> ft.Container:
|
|
18
|
-
"""Create the versioned contact/entity card with avatar and optional footer.
|
|
18
|
+
"""Create the versioned contact/entity card with avatar and optional footer.
|
|
19
|
+
|
|
20
|
+
S12/atv11: iniciais e tag em ``ACCENT_TEXT`` (>= 4.69:1 sobre o fill
|
|
21
|
+
translúcido composto com o fundo do card, débito técnico 12); os fills
|
|
22
|
+
com sufixo hex ``22``/``33`` viravam AARRGGBB no Flutter e pintavam
|
|
23
|
+
esverdeados (BUG5) — agora usam ``ft.Colors.with_opacity``.
|
|
24
|
+
"""
|
|
19
25
|
initials = "".join(p[0].upper() for p in name.split()[:2])
|
|
20
26
|
|
|
21
27
|
avatar = ft.Container(
|
|
22
|
-
content=ft.Text(initials, size=14, weight=ft.FontWeight.W_700, color=Colors.
|
|
28
|
+
content=ft.Text(initials, size=14, weight=ft.FontWeight.W_700, color=Colors.ACCENT_TEXT),
|
|
23
29
|
width=42, height=42,
|
|
24
|
-
bgcolor=
|
|
30
|
+
bgcolor=ft.Colors.with_opacity(0.13, Colors.ACCENT),
|
|
25
31
|
border_radius=21,
|
|
26
32
|
alignment=ft.Alignment(0, 0),
|
|
27
33
|
)
|
|
@@ -35,7 +41,11 @@ def DEx_ContactCard(
|
|
|
35
41
|
footer_controls = []
|
|
36
42
|
if tag:
|
|
37
43
|
footer_controls.append(
|
|
38
|
-
DEx_Badge(
|
|
44
|
+
DEx_Badge(
|
|
45
|
+
tag,
|
|
46
|
+
color=ft.Colors.with_opacity(0.13, Colors.ACCENT),
|
|
47
|
+
text_color=Colors.ACCENT_TEXT,
|
|
48
|
+
)
|
|
39
49
|
)
|
|
40
50
|
if value:
|
|
41
51
|
footer_controls.append(
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""DEx_BarChart — comparação por categoria, com os tokens do tema.
|
|
2
|
+
|
|
3
|
+
Construído sobre ``flet_charts`` (decisão D5). Aceita uma série (barras
|
|
4
|
+
simples) ou várias (barras agrupadas por categoria), com legenda opcional.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import flet as ft
|
|
9
|
+
import flet_charts as fc
|
|
10
|
+
|
|
11
|
+
from components.charts.DEx_LineChart import series_color
|
|
12
|
+
from components.theme.DEx_Theme import Colors, Spacing
|
|
13
|
+
|
|
14
|
+
COMPONENT_VERSION = "0.0.1"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _legenda(nomes: list[str]) -> ft.Row:
|
|
18
|
+
itens: list[ft.Control] = []
|
|
19
|
+
for i, nome in enumerate(nomes):
|
|
20
|
+
itens.append(
|
|
21
|
+
ft.Row(
|
|
22
|
+
[
|
|
23
|
+
ft.Container(width=10, height=10, bgcolor=series_color(i), border_radius=2),
|
|
24
|
+
ft.Text(nome, size=11, color=Colors.TEXT_SECONDARY),
|
|
25
|
+
],
|
|
26
|
+
spacing=6,
|
|
27
|
+
tight=True,
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
return ft.Row(itens, spacing=Spacing.MD, wrap=True)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def DEx_BarChart(
|
|
34
|
+
categories: list[str],
|
|
35
|
+
series: list[dict],
|
|
36
|
+
height: int = 260,
|
|
37
|
+
show_legend: bool = True,
|
|
38
|
+
show_grid: bool = True,
|
|
39
|
+
bar_width: int = 16,
|
|
40
|
+
horizontal: bool = False,
|
|
41
|
+
) -> ft.Column:
|
|
42
|
+
"""Gráfico de barras agrupadas por categoria.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
categories: rótulos do eixo de categorias (uma entrada por grupo).
|
|
46
|
+
series: lista de séries. Cada série é um dicionário com ``name`` (str)
|
|
47
|
+
e ``values`` (lista de números, alinhada a ``categories``). Aceita
|
|
48
|
+
``color`` para fixar a cor.
|
|
49
|
+
height: altura do gráfico em pixels.
|
|
50
|
+
show_legend: exibe a legenda de séries abaixo do gráfico.
|
|
51
|
+
show_grid: exibe a grade horizontal.
|
|
52
|
+
bar_width: largura de cada barra em pixels.
|
|
53
|
+
horizontal: ainda não suportado pelo backend; mantido para
|
|
54
|
+
compatibilidade futura de assinatura e ignorado hoje.
|
|
55
|
+
"""
|
|
56
|
+
nomes = [s.get("name", f"Série {i + 1}") for i, s in enumerate(series)]
|
|
57
|
+
|
|
58
|
+
grupos: list[fc.BarChartGroup] = []
|
|
59
|
+
for indice_categoria in range(len(categories)):
|
|
60
|
+
barras: list[fc.BarChartRod] = []
|
|
61
|
+
for i, serie in enumerate(series):
|
|
62
|
+
valores = serie.get("values", [])
|
|
63
|
+
if indice_categoria >= len(valores):
|
|
64
|
+
continue
|
|
65
|
+
barras.append(
|
|
66
|
+
fc.BarChartRod(
|
|
67
|
+
to_y=valores[indice_categoria],
|
|
68
|
+
width=bar_width,
|
|
69
|
+
color=serie.get("color") or series_color(i),
|
|
70
|
+
border_radius=4,
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
grupos.append(fc.BarChartGroup(x=indice_categoria, rods=barras))
|
|
74
|
+
|
|
75
|
+
eixo_x = fc.ChartAxis(
|
|
76
|
+
labels=[
|
|
77
|
+
fc.ChartAxisLabel(
|
|
78
|
+
value=i,
|
|
79
|
+
label=ft.Text(rotulo, size=10, color=Colors.TEXT_SECONDARY),
|
|
80
|
+
)
|
|
81
|
+
for i, rotulo in enumerate(categories)
|
|
82
|
+
],
|
|
83
|
+
label_size=28,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
grafico = fc.BarChart(
|
|
87
|
+
groups=grupos,
|
|
88
|
+
bottom_axis=eixo_x,
|
|
89
|
+
left_axis=fc.ChartAxis(label_size=40),
|
|
90
|
+
border=ft.Border.all(1, Colors.BORDER),
|
|
91
|
+
horizontal_grid_lines=(
|
|
92
|
+
fc.ChartGridLines(color=Colors.BORDER, width=1) if show_grid else None
|
|
93
|
+
),
|
|
94
|
+
tooltip=fc.BarChartTooltip(bgcolor=Colors.BG_ELEVATED),
|
|
95
|
+
expand=True,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
conteudo: list[ft.Control] = [ft.Container(content=grafico, height=height)]
|
|
99
|
+
if show_legend and nomes:
|
|
100
|
+
conteudo.append(_legenda(nomes))
|
|
101
|
+
return ft.Column(conteudo, spacing=Spacing.SM, tight=True)
|