SaaS-FrameWork 0.1.2__tar.gz → 0.1.3__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.
Files changed (91) hide show
  1. {saas_framework-0.1.2 → saas_framework-0.1.3}/MANIFEST.in +1 -1
  2. {saas_framework-0.1.2 → saas_framework-0.1.3}/PKG-INFO +18 -10
  3. {saas_framework-0.1.2 → saas_framework-0.1.3}/README.md +15 -9
  4. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/data/DEx_DataTable.py +20 -4
  5. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/feedback/DEx_AlertDialog.py +8 -2
  6. saas_framework-0.1.3/components/inputs/DEx_Dropdown.py +41 -0
  7. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_TextField.py +18 -2
  8. saas_framework-0.1.3/components/layout/DEx_AppShell.py +137 -0
  9. saas_framework-0.1.3/components/layout/DEx_Header.py +80 -0
  10. saas_framework-0.1.3/components/layout/DEx_Sidebar.py +177 -0
  11. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/metadata.py +9 -9
  12. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/project.py +23 -19
  13. {saas_framework-0.1.2 → saas_framework-0.1.3}/pyproject.toml +5 -2
  14. saas_framework-0.1.2/components/inputs/DEx_Dropdown.py +0 -25
  15. saas_framework-0.1.2/components/layout/DEx_AppShell.py +0 -80
  16. saas_framework-0.1.2/components/layout/DEx_Header.py +0 -57
  17. saas_framework-0.1.2/components/layout/DEx_Sidebar.py +0 -131
  18. {saas_framework-0.1.2 → saas_framework-0.1.3}/SaaS_FrameWork.egg-info/SOURCES.txt +0 -0
  19. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/__init__.py +0 -0
  20. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/buttons/DEx_BtnFAB.py +0 -0
  21. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/buttons/DEx_BtnFilled.py +0 -0
  22. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/buttons/DEx_BtnGhost.py +0 -0
  23. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/buttons/DEx_BtnIcon.py +0 -0
  24. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/buttons/DEx_BtnPrimary.py +0 -0
  25. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/buttons/DEx_BtnSegmented.py +0 -0
  26. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/buttons/DEx_BtnText.py +0 -0
  27. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/buttons/DEx_BtnTonal.py +0 -0
  28. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/buttons/DEx_MenuBar.py +0 -0
  29. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/buttons/DEx_PopupMenu.py +0 -0
  30. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/buttons/__init__.py +0 -0
  31. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/cards/DEx_Card.py +0 -0
  32. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/cards/DEx_ContactCard.py +0 -0
  33. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/cards/DEx_MetricCard.py +0 -0
  34. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/cards/__init__.py +0 -0
  35. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/data/DEx_ExpansionPanel.py +0 -0
  36. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/data/DEx_ExpansionTile.py +0 -0
  37. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/data/DEx_GridView.py +0 -0
  38. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/data/DEx_ListTile.py +0 -0
  39. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/data/DEx_ListView.py +0 -0
  40. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/data/DEx_PipelineColumn.py +0 -0
  41. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/data/DEx_TreeView.py +0 -0
  42. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/data/__init__.py +0 -0
  43. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/feedback/DEx_Banner.py +0 -0
  44. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/feedback/DEx_BottomSheet.py +0 -0
  45. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/feedback/DEx_Notify.py +0 -0
  46. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/feedback/DEx_ProgressBar.py +0 -0
  47. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/feedback/DEx_ProgressRing.py +0 -0
  48. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/feedback/DEx_Shimmer.py +0 -0
  49. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/feedback/DEx_Tooltip.py +0 -0
  50. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/feedback/__init__.py +0 -0
  51. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_AutoComplete.py +0 -0
  52. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_Checkbox.py +0 -0
  53. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_Chip.py +0 -0
  54. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_DatePicker.py +0 -0
  55. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_FilePicker.py +0 -0
  56. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_Radio.py +0 -0
  57. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_SearchBar.py +0 -0
  58. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_SearchField.py +0 -0
  59. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_Slider.py +0 -0
  60. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_Switch.py +0 -0
  61. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_TagInput.py +0 -0
  62. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/DEx_TimePicker.py +0 -0
  63. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/inputs/__init__.py +0 -0
  64. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_AnimatedSwitcher.py +0 -0
  65. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_AppBar.py +0 -0
  66. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_Draggable.py +0 -0
  67. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_GestureDetector.py +0 -0
  68. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_Marquee.py +0 -0
  69. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_NavItem.py +0 -0
  70. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_NavigationBar.py +0 -0
  71. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_NavigationDrawer.py +0 -0
  72. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_NavigationRail.py +0 -0
  73. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_ResponsiveRow.py +0 -0
  74. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_Splitter.py +0 -0
  75. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_Stack.py +0 -0
  76. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/DEx_Tabs.py +0 -0
  77. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/layout/__init__.py +0 -0
  78. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/primitives/DEx_Avatar.py +0 -0
  79. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/primitives/DEx_Badge.py +0 -0
  80. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/primitives/DEx_Divider.py +0 -0
  81. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/primitives/DEx_Icon.py +0 -0
  82. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/primitives/DEx_Image.py +0 -0
  83. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/primitives/DEx_Markdown.py +0 -0
  84. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/primitives/DEx_SectionEyebrow.py +0 -0
  85. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/primitives/DEx_StatusDot.py +0 -0
  86. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/primitives/__init__.py +0 -0
  87. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/theme/DEx_ColorThemes.py +0 -0
  88. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/theme/DEx_Theme.py +0 -0
  89. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/theme/__init__.py +0 -0
  90. {saas_framework-0.1.2 → saas_framework-0.1.3}/components/versioning.py +0 -0
  91. {saas_framework-0.1.2 → saas_framework-0.1.3}/setup.cfg +0 -0
@@ -10,7 +10,7 @@ prune build
10
10
  prune catalog
11
11
  prune *.egg-info
12
12
  prune dist
13
- prune docs
13
+ prune Diretrizes
14
14
  prune tests
15
15
  prune use_cases
16
16
  exclude files.zip
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SaaS-FrameWork
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: SaaS-FrameWork - sistema de componentes reutilizaveis para apps SaaS construido com Python e Flet
5
5
  Author-email: Almir Duarte <almir.jg@gmail.com>
6
6
  License-Expression: MIT
@@ -13,6 +13,8 @@ Classifier: Topic :: Software Development :: User Interfaces
13
13
  Requires-Python: >=3.13
14
14
  Description-Content-Type: text/markdown
15
15
  Requires-Dist: flet==0.84.0
16
+ Provides-Extra: web
17
+ Requires-Dist: flet-web==0.84.0; extra == "web"
16
18
  Provides-Extra: dev
17
19
  Requires-Dist: flet==0.84.0; extra == "dev"
18
20
  Requires-Dist: pytest<10,>=9.1; extra == "dev"
@@ -86,7 +88,7 @@ The following folders are repository assets and are intentionally excluded from
86
88
 
87
89
  - `catalog/`: local visual catalog and inspection tool.
88
90
  - `use_cases/`: executable examples for development and documentation.
89
- - `docs/`: component documentation and generated structure images.
91
+ - `Diretrizes/`: project guidelines — prompts, design/component documentation, management artifacts, and QA evidence.
90
92
  - `_base/`: preserved reference material.
91
93
 
92
94
  This separation is enforced in `pyproject.toml` through `tool.setuptools.packages.find`.
@@ -98,8 +100,8 @@ Adding a public component requires all of the following:
98
100
  - entry in `components/metadata.py`
99
101
  - public export in `components/__init__.py`
100
102
  - use case `use_cases/UC_<Name>_01.py`
101
- - documentation `docs/components/Documentação/DEx_<Name>.md`
102
- - four structure images in `docs/components/images/`
103
+ - documentation `Diretrizes/design/components/Documentação/DEx_<Name>.md`
104
+ - four structure images in `Diretrizes/design/components/images/`
103
105
 
104
106
  The repository governance tests fail when this contract is broken.
105
107
 
@@ -126,8 +128,14 @@ SaaS-Framework/
126
128
  | |-- UC_TreeView_01.py
127
129
  | `-- UC_ColorThemes_01.py
128
130
  |-- catalog/
129
- | `-- main.py
130
- |-- docs/
131
+ | `-- catalog.py
132
+ |-- Diretrizes/
133
+ | |-- Dados/ data artifacts (DDL, DML, scripts)
134
+ | |-- Prompt/ prompt files
135
+ | |-- design/ design references and component docs/images
136
+ | | `-- components/
137
+ | |-- gestao/ roadmap, policies, and management reports
138
+ | `-- qa/ QA evidence
131
139
  |-- AGENTS.md
132
140
  |-- pyproject.toml
133
141
  `-- README.md
@@ -153,14 +161,14 @@ Run the catalog as desktop app:
153
161
 
154
162
  ```cmd
155
163
  call C:\Python\venv\.venv_313_FW\Scripts\activate.bat
156
- flet run catalog/main.py
164
+ flet run catalog/catalog.py
157
165
  ```
158
166
 
159
167
  Run as web catalog only when browser validation is required:
160
168
 
161
169
  ```cmd
162
170
  call C:\Python\venv\.venv_313_FW\Scripts\activate.bat
163
- flet run --web --port 8550 catalog/main.py
171
+ flet run --web --port 8550 catalog/catalog.py
164
172
  ```
165
173
 
166
174
  Run a use case:
@@ -219,12 +227,12 @@ The script builds the package, checks the artifacts, and uploads to TestPyPI or
219
227
  With the documented Flet environment:
220
228
 
221
229
  ```cmd
222
- C:\Python\venv\.venv_313_FW\Scripts\python.exe -c "import catalog.main as c; print(c.PROJECT_VERSION)"
230
+ C:\Python\venv\.venv_313_FW\Scripts\python.exe -c "import catalog.constants as c; print(c.PROJECT_VERSION)"
223
231
  ```
224
232
 
225
233
  ## Catalog
226
234
 
227
- The catalog entry point is `catalog/main.py`.
235
+ The catalog entry point is `catalog/catalog.py`.
228
236
 
229
237
  It follows the project window structure:
230
238
 
@@ -63,7 +63,7 @@ The following folders are repository assets and are intentionally excluded from
63
63
 
64
64
  - `catalog/`: local visual catalog and inspection tool.
65
65
  - `use_cases/`: executable examples for development and documentation.
66
- - `docs/`: component documentation and generated structure images.
66
+ - `Diretrizes/`: project guidelines — prompts, design/component documentation, management artifacts, and QA evidence.
67
67
  - `_base/`: preserved reference material.
68
68
 
69
69
  This separation is enforced in `pyproject.toml` through `tool.setuptools.packages.find`.
@@ -75,8 +75,8 @@ Adding a public component requires all of the following:
75
75
  - entry in `components/metadata.py`
76
76
  - public export in `components/__init__.py`
77
77
  - use case `use_cases/UC_<Name>_01.py`
78
- - documentation `docs/components/Documentação/DEx_<Name>.md`
79
- - four structure images in `docs/components/images/`
78
+ - documentation `Diretrizes/design/components/Documentação/DEx_<Name>.md`
79
+ - four structure images in `Diretrizes/design/components/images/`
80
80
 
81
81
  The repository governance tests fail when this contract is broken.
82
82
 
@@ -103,8 +103,14 @@ SaaS-Framework/
103
103
  | |-- UC_TreeView_01.py
104
104
  | `-- UC_ColorThemes_01.py
105
105
  |-- catalog/
106
- | `-- main.py
107
- |-- docs/
106
+ | `-- catalog.py
107
+ |-- Diretrizes/
108
+ | |-- Dados/ data artifacts (DDL, DML, scripts)
109
+ | |-- Prompt/ prompt files
110
+ | |-- design/ design references and component docs/images
111
+ | | `-- components/
112
+ | |-- gestao/ roadmap, policies, and management reports
113
+ | `-- qa/ QA evidence
108
114
  |-- AGENTS.md
109
115
  |-- pyproject.toml
110
116
  `-- README.md
@@ -130,14 +136,14 @@ Run the catalog as desktop app:
130
136
 
131
137
  ```cmd
132
138
  call C:\Python\venv\.venv_313_FW\Scripts\activate.bat
133
- flet run catalog/main.py
139
+ flet run catalog/catalog.py
134
140
  ```
135
141
 
136
142
  Run as web catalog only when browser validation is required:
137
143
 
138
144
  ```cmd
139
145
  call C:\Python\venv\.venv_313_FW\Scripts\activate.bat
140
- flet run --web --port 8550 catalog/main.py
146
+ flet run --web --port 8550 catalog/catalog.py
141
147
  ```
142
148
 
143
149
  Run a use case:
@@ -196,12 +202,12 @@ The script builds the package, checks the artifacts, and uploads to TestPyPI or
196
202
  With the documented Flet environment:
197
203
 
198
204
  ```cmd
199
- C:\Python\venv\.venv_313_FW\Scripts\python.exe -c "import catalog.main as c; print(c.PROJECT_VERSION)"
205
+ C:\Python\venv\.venv_313_FW\Scripts\python.exe -c "import catalog.constants as c; print(c.PROJECT_VERSION)"
200
206
  ```
201
207
 
202
208
  ## Catalog
203
209
 
204
- The catalog entry point is `catalog/main.py`.
210
+ The catalog entry point is `catalog/catalog.py`.
205
211
 
206
212
  It follows the project window structure:
207
213
 
@@ -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.1"
4
+ COMPONENT_VERSION = "0.1.0"
5
5
 
6
6
 
7
7
  def _state_placeholder(state: str, empty_message: str, error_message: str) -> ft.Control:
@@ -44,10 +44,26 @@ def DEx_DataTable(
44
44
  state: str | None = None,
45
45
  empty_message: str = "Nenhum registro encontrado.",
46
46
  error_message: str = "Erro ao carregar os dados.",
47
+ row_payloads: list | None = None,
47
48
  ) -> ft.Control:
48
- """Create the versioned data table with DEx headers, borders, and rows."""
49
+ """Create the versioned data table with DEx headers, borders, and rows.
50
+
51
+ row_payloads (BL13 do AutoFlow): um payload por linha; quando presente,
52
+ on_row_click recebe (evento, payload) — os produtos deixavam de religar
53
+ o clique linha a linha sobre o ft.DataTable retornado. Sem payloads, o
54
+ comportamento antigo (on_row_click(evento)) e preservado.
55
+ """
49
56
  if state in ("loading", "empty", "error"):
50
57
  return _state_placeholder(state, empty_message, error_message)
58
+
59
+ def _handler(indice: int):
60
+ if on_row_click is None:
61
+ return None
62
+ if row_payloads is None:
63
+ return on_row_click
64
+ payload = row_payloads[indice] if indice < len(row_payloads) else None
65
+ return lambda e, p=payload: on_row_click(e, p)
66
+
51
67
  return ft.DataTable(
52
68
  columns=[
53
69
  ft.DataColumn(
@@ -67,9 +83,9 @@ def DEx_DataTable(
67
83
  ft.DataCell(ft.Text(cell, size=13, color=Colors.TEXT_PRIMARY))
68
84
  for cell in row
69
85
  ],
70
- on_select_change=on_row_click,
86
+ on_select_change=_handler(i),
71
87
  )
72
- for row in rows
88
+ for i, row in enumerate(rows)
73
89
  ],
74
90
  border=ft.Border.all(1, Colors.BORDER),
75
91
  border_radius=Spacing.CARD_BORDER_RADIUS,
@@ -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.1"
4
+ COMPONENT_VERSION = "0.1.0"
5
5
 
6
6
 
7
7
  def DEx_AlertDialog(
@@ -9,8 +9,13 @@ def DEx_AlertDialog(
9
9
  content: ft.Control | str | None = None,
10
10
  actions: list[ft.Control] | None = None,
11
11
  on_dismiss=None,
12
+ modal: bool = False,
12
13
  ) -> ft.AlertDialog:
13
- """Modal dialog for confirmations, alerts and short forms."""
14
+ """Modal dialog for confirmations, alerts and short forms.
15
+
16
+ modal (BL13 do AutoFlow): bloqueia o fechamento por clique fora — os
17
+ produtos ajustavam o atributo publico pos-construcao.
18
+ """
14
19
  body = (
15
20
  ft.Text(content, size=13, color=Colors.TEXT_SECONDARY)
16
21
  if isinstance(content, str)
@@ -21,6 +26,7 @@ def DEx_AlertDialog(
21
26
  content=body,
22
27
  actions=actions or [],
23
28
  on_dismiss=on_dismiss,
29
+ modal=modal,
24
30
  bgcolor=Colors.BG_ELEVATED,
25
31
  shape=ft.RoundedRectangleBorder(radius=Spacing.CARD_BORDER_RADIUS),
26
32
  )
@@ -0,0 +1,41 @@
1
+ import flet as ft
2
+ from components.theme.DEx_Theme import Colors, Spacing
3
+
4
+ COMPONENT_VERSION = "0.1.0"
5
+
6
+
7
+ def _option(item) -> ft.dropdown.Option:
8
+ """Aceita opcao como str (key=text) ou par (key, text) — BL13."""
9
+ if isinstance(item, (tuple, list)) and len(item) == 2:
10
+ key, text = item
11
+ return ft.dropdown.Option(key=str(key), text=str(text))
12
+ return ft.dropdown.Option(str(item))
13
+
14
+
15
+ def DEx_Dropdown(
16
+ label: str,
17
+ options: list,
18
+ on_change=None,
19
+ value: str | None = None,
20
+ width: int | None = None,
21
+ ) -> ft.Dropdown:
22
+ """Create the versioned styled dropdown selector.
23
+
24
+ options aceita list[str] (compat) ou list[(key, text)]; value/width
25
+ (BL13 do AutoFlow) evitam o ajuste pos-construcao nos produtos.
26
+ """
27
+ dd = ft.Dropdown(
28
+ label=label,
29
+ options=[_option(o) for o in options],
30
+ value=value,
31
+ width=width,
32
+ border_color=Colors.BORDER,
33
+ focused_border_color=Colors.ACCENT,
34
+ label_style=ft.TextStyle(color=Colors.TEXT_SECONDARY, size=12),
35
+ text_style=ft.TextStyle(color=Colors.TEXT_PRIMARY, size=14),
36
+ bgcolor=Colors.BG_SURFACE,
37
+ border_radius=Spacing.BUTTON_BORDER_RADIUS,
38
+ )
39
+ if on_change is not None:
40
+ dd.on_change = on_change
41
+ return dd
@@ -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.1"
4
+ COMPONENT_VERSION = "0.1.0"
5
5
 
6
6
 
7
7
  def DEx_TextField(
@@ -10,8 +10,18 @@ def DEx_TextField(
10
10
  icon=None,
11
11
  password: bool = False,
12
12
  on_change=None,
13
+ value: str = "",
14
+ width: int | None = None,
15
+ visible: bool = True,
16
+ multiline: bool = False,
17
+ min_lines: int | None = None,
18
+ max_lines: int | None = None,
13
19
  ) -> ft.TextField:
14
- """Create the versioned DEx text field for forms and filters."""
20
+ """Create the versioned DEx text field for forms and filters.
21
+
22
+ value/width/visible/multiline (BL13 do AutoFlow): os produtos ajustavam
23
+ esses atributos publicos pos-construcao; agora a fabrica os expoe.
24
+ """
15
25
  return ft.TextField(
16
26
  label=label,
17
27
  hint_text=hint,
@@ -19,6 +29,12 @@ def DEx_TextField(
19
29
  password=password,
20
30
  can_reveal_password=password,
21
31
  on_change=on_change,
32
+ value=value,
33
+ width=width,
34
+ visible=visible,
35
+ multiline=multiline,
36
+ min_lines=min_lines,
37
+ max_lines=max_lines,
22
38
  border_color=Colors.BORDER,
23
39
  focused_border_color=Colors.ACCENT,
24
40
  label_style=ft.TextStyle(color=Colors.TEXT_SECONDARY, size=12),
@@ -0,0 +1,137 @@
1
+ import flet as ft
2
+ from components.theme.DEx_Theme import Colors, Spacing
3
+ from components.layout.DEx_Sidebar import DEx_Sidebar
4
+ from components.layout.DEx_Header import DEx_Header
5
+
6
+ COMPONENT_VERSION = "0.1.0"
7
+
8
+
9
+ class DEx_AppShell(ft.Row):
10
+ """Versioned application shell with sidebar, header, and content host.
11
+
12
+ BL12 (demanda AutoFlow): o shell repassa a identidade e a navegacao do
13
+ produto para o DEx_Sidebar (nav_items, logo, secao, settings, usuario,
14
+ on_logout) e as opcoes do DEx_Header (busca/sino/ajuda). Defaults
15
+ reproduzem a vitrine do catalogo — retrocompativel.
16
+ """
17
+
18
+ def __init__(
19
+ self,
20
+ page: ft.Page,
21
+ title: str = "",
22
+ subtitle: str = "",
23
+ header_actions: list[ft.Control] | None = None,
24
+ nav_items: list[tuple] | None = None,
25
+ initial_route: str = "/dashboard",
26
+ logo_letter: str = "D",
27
+ logo_title: str = "DEx",
28
+ logo_subtitle: str = "Framework v4",
29
+ section_label: str = "NAVEGACAO",
30
+ settings_route: str | None = "/settings",
31
+ user_name: str | None = "Almir Duarte",
32
+ user_role: str | None = "Admin",
33
+ on_logout=None,
34
+ on_navigate=None,
35
+ show_search: bool = True,
36
+ on_search=None,
37
+ show_notifications: bool = True,
38
+ show_help: bool = True,
39
+ ):
40
+ self._page_ref = page
41
+ self.title = title
42
+ self.subtitle = subtitle
43
+ self.header_actions = header_actions or []
44
+ self.nav_items = nav_items
45
+ self.logo_letter = logo_letter
46
+ self.logo_title = logo_title
47
+ self.logo_subtitle = logo_subtitle
48
+ self.section_label = section_label
49
+ self.settings_route = settings_route
50
+ self.user_name = user_name
51
+ self.user_role = user_role
52
+ self.on_logout = on_logout
53
+ self.on_navigate_produto = on_navigate
54
+ self.show_search = show_search
55
+ self.on_search = on_search
56
+ self.show_notifications = show_notifications
57
+ self.show_help = show_help
58
+ self._content = ft.Container(expand=True)
59
+ self._route = initial_route
60
+
61
+ page.bgcolor = Colors.BG_DEEP
62
+ page.padding = 0
63
+ page.spacing = 0
64
+
65
+ super().__init__(
66
+ controls=self._build_controls(),
67
+ spacing=0,
68
+ expand=True,
69
+ )
70
+
71
+ def set_content(self, control: ft.Control, title: str = None, subtitle: str = None):
72
+ if title:
73
+ self.title = title
74
+ if subtitle:
75
+ self.subtitle = subtitle
76
+ self._content = ft.Container(
77
+ content=ft.Column(
78
+ [ft.Container(content=control, padding=ft.Padding.all(Spacing.LG))],
79
+ spacing=0,
80
+ expand=True,
81
+ horizontal_alignment=ft.CrossAxisAlignment.START,
82
+ ),
83
+ expand=True,
84
+ bgcolor=Colors.BG_DEEP,
85
+ )
86
+ self.controls = self._build_controls()
87
+ try:
88
+ self.update()
89
+ except RuntimeError:
90
+ pass
91
+
92
+ def _on_navigate(self, route: str):
93
+ self._route = route
94
+ if self.on_navigate_produto:
95
+ self.on_navigate_produto(route)
96
+ self.controls = self._build_controls()
97
+ self.update()
98
+
99
+ def _build_controls(self) -> list[ft.Control]:
100
+ sidebar = DEx_Sidebar(
101
+ current_route=self._route,
102
+ on_navigate=self._on_navigate,
103
+ nav_items=self.nav_items,
104
+ logo_letter=self.logo_letter,
105
+ logo_title=self.logo_title,
106
+ logo_subtitle=self.logo_subtitle,
107
+ section_label=self.section_label,
108
+ settings_route=self.settings_route,
109
+ user_name=self.user_name,
110
+ user_role=self.user_role,
111
+ on_logout=self.on_logout,
112
+ )
113
+ header = DEx_Header(
114
+ self.title,
115
+ self.subtitle,
116
+ actions=self.header_actions,
117
+ show_search=self.show_search,
118
+ on_search=self.on_search,
119
+ show_notifications=self.show_notifications,
120
+ show_help=self.show_help,
121
+ )
122
+
123
+ main_area = ft.Column(
124
+ [
125
+ ft.Row([header], spacing=0, expand=True),
126
+ ft.Container(
127
+ content=self._content,
128
+ expand=True,
129
+ clip_behavior=ft.ClipBehavior.HARD_EDGE,
130
+ ),
131
+ ],
132
+ spacing=0,
133
+ expand=True,
134
+ alignment=ft.MainAxisAlignment.START,
135
+ )
136
+
137
+ return [sidebar, main_area]
@@ -0,0 +1,80 @@
1
+ import flet as ft
2
+ from components.theme.DEx_Theme import Colors, Spacing
3
+
4
+ COMPONENT_VERSION = "0.1.0"
5
+
6
+
7
+ class DEx_Header(ft.Container):
8
+ """Versioned page header with title, subtitle, search, and actions.
9
+
10
+ BL12 (demanda AutoFlow): busca, sino e ajuda agora sao opcionais e a
11
+ busca aceita on_search (on_change) — defaults reproduzem a vitrine.
12
+ """
13
+
14
+ def __init__(
15
+ self,
16
+ title: str,
17
+ subtitle: str = "",
18
+ actions: list[ft.Control] | None = None,
19
+ show_search: bool = True,
20
+ on_search=None,
21
+ show_notifications: bool = True,
22
+ show_help: bool = True,
23
+ ):
24
+ self.title = title
25
+ self.subtitle = subtitle
26
+ self.actions = actions or []
27
+ self.show_search = show_search
28
+ self.on_search = on_search
29
+ self.show_notifications = show_notifications
30
+ self.show_help = show_help
31
+ super().__init__(
32
+ content=self._build_content(),
33
+ height=Spacing.HEADER_HEIGHT,
34
+ bgcolor=Colors.BG_DEEP,
35
+ border=ft.Border.only(bottom=ft.BorderSide(1, Colors.BORDER)),
36
+ padding=ft.Padding.symmetric(horizontal=Spacing.LG),
37
+ )
38
+
39
+ def _build_content(self) -> ft.Row:
40
+ title_block = ft.Column(
41
+ [
42
+ ft.Text(self.title, size=20, weight=ft.FontWeight.W_700, color=Colors.TEXT_PRIMARY),
43
+ ft.Text(self.subtitle, size=12, color=Colors.TEXT_SECONDARY) if self.subtitle else ft.Container(),
44
+ ],
45
+ spacing=2, tight=True,
46
+ )
47
+
48
+ partes: list[ft.Control] = [title_block, ft.Container(expand=True)]
49
+
50
+ if self.show_search:
51
+ partes.append(
52
+ ft.TextField(
53
+ hint_text="Buscar...",
54
+ prefix_icon=ft.Icons.SEARCH,
55
+ on_change=self.on_search,
56
+ border_color=Colors.BORDER,
57
+ focused_border_color=Colors.ACCENT,
58
+ text_style=ft.TextStyle(color=Colors.TEXT_PRIMARY, size=13),
59
+ hint_style=ft.TextStyle(color=Colors.TEXT_MUTED, size=13),
60
+ bgcolor=Colors.BG_ELEVATED,
61
+ border_radius=8,
62
+ height=40,
63
+ content_padding=ft.Padding.symmetric(horizontal=12, vertical=8),
64
+ width=280,
65
+ )
66
+ )
67
+
68
+ icones: list[ft.Control] = []
69
+ if self.show_notifications:
70
+ icones.append(
71
+ ft.IconButton(ft.Icons.NOTIFICATIONS_NONE_ROUNDED, icon_color=Colors.TEXT_SECONDARY, icon_size=20)
72
+ )
73
+ icones.extend(self.actions)
74
+ if self.show_help:
75
+ icones.append(
76
+ ft.IconButton(ft.Icons.HELP_OUTLINE_ROUNDED, icon_color=Colors.TEXT_SECONDARY, icon_size=20)
77
+ )
78
+ partes.append(ft.Row(icones, spacing=0))
79
+
80
+ return ft.Row(partes, vertical_alignment=ft.CrossAxisAlignment.CENTER)