fh-matui 0.9.7__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.
- fh_matui/__init__.py +1 -0
- fh_matui/_modidx.py +192 -0
- fh_matui/app_pages.py +291 -0
- fh_matui/components.py +1200 -0
- fh_matui/core.py +230 -0
- fh_matui/datatable.py +870 -0
- fh_matui/foundations.py +59 -0
- fh_matui/web_pages.py +919 -0
- fh_matui-0.9.7.dist-info/METADATA +243 -0
- fh_matui-0.9.7.dist-info/RECORD +14 -0
- fh_matui-0.9.7.dist-info/WHEEL +5 -0
- fh_matui-0.9.7.dist-info/entry_points.txt +2 -0
- fh_matui-0.9.7.dist-info/licenses/LICENSE +201 -0
- fh_matui-0.9.7.dist-info/top_level.txt +1 -0
fh_matui/core.py
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"""Core components for building fh-matui Material Design apps with BeerCSS"""
|
|
2
|
+
|
|
3
|
+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_core.ipynb.
|
|
4
|
+
|
|
5
|
+
# %% auto 0
|
|
6
|
+
__all__ = ['HEADER_URLS', 'beer_hdrs', 'COLOR_NAMES', 'SIZES', 'WIDTH_HEIGHT', 'ELEVATES', 'DIRECTIONS', 'FORMS', 'MARGINS',
|
|
7
|
+
'PADDINGS', 'POSITIONS', 'RESPONSIVE', 'ALIGNMENTS', 'BLURS', 'OPACITIES', 'SHADOWS', 'SPACES', 'RIPPLES',
|
|
8
|
+
'SCROLLS', 'WAVES', 'ZOOMS', 'THEME_HELPERS', 'TYPOGRAPHY', 'TRIGGERS', 'COLOR_HELPERS', 'ALL_HELPERS',
|
|
9
|
+
'MatTheme', 'BeerCssChain']
|
|
10
|
+
|
|
11
|
+
# %% ../nbs/01_core.ipynb 2
|
|
12
|
+
from fastcore.utils import *
|
|
13
|
+
from fasthtml.common import *
|
|
14
|
+
from fasthtml.jupyter import *
|
|
15
|
+
from fastlite import *
|
|
16
|
+
from fasthtml.common import A, Button as FhButton, I, Span
|
|
17
|
+
from .foundations import normalize_tokens, dedupe_preserve_order, stringify, listify, VEnum
|
|
18
|
+
from nbdev.showdoc import show_doc
|
|
19
|
+
|
|
20
|
+
# %% ../nbs/01_core.ipynb 5
|
|
21
|
+
#| code-fold: true
|
|
22
|
+
HEADER_URLS = {
|
|
23
|
+
"beercss_css": "https://cdn.jsdelivr.net/npm/beercss@3.13.1/dist/cdn/beer.min.css",
|
|
24
|
+
"beercss_js": "https://cdn.jsdelivr.net/npm/beercss@3.13.1/dist/cdn/beer.min.js",
|
|
25
|
+
"mdc_js": "https://cdn.jsdelivr.net/npm/material-dynamic-colors@1.1.2/dist/cdn/material-dynamic-colors.min.js",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
beer_hdrs = (
|
|
29
|
+
Link(href=HEADER_URLS["beercss_css"], rel='stylesheet', type='text/css'),
|
|
30
|
+
Script(src=HEADER_URLS["beercss_js"], type='module'),
|
|
31
|
+
Script(src=HEADER_URLS["mdc_js"], type='module'),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# %% ../nbs/01_core.ipynb 8
|
|
35
|
+
#| code-fold: true
|
|
36
|
+
# All BeerCSS color names
|
|
37
|
+
COLOR_NAMES = ['amber', 'blue', 'blue_grey', 'brown', 'cyan', 'deep_orange', 'deep_purple',
|
|
38
|
+
'green', 'grey', 'indigo', 'light_blue', 'light_green', 'lime', 'orange',
|
|
39
|
+
'pink', 'purple', 'red', 'teal', 'yellow']
|
|
40
|
+
|
|
41
|
+
# All shared helpers organized by category
|
|
42
|
+
SIZES = ['tiny', 'small', 'medium', 'large', 'extra', 'wrap', 'no_wrap', 'max']
|
|
43
|
+
WIDTH_HEIGHT = ['auto_width', 'small_width', 'medium_width', 'large_width',
|
|
44
|
+
'auto_height', 'small_height', 'medium_height', 'large_height']
|
|
45
|
+
ELEVATES = ['elevate', 'no_elevate', 'small_elevate', 'medium_elevate', 'large_elevate']
|
|
46
|
+
DIRECTIONS = ['horizontal', 'vertical']
|
|
47
|
+
FORMS = ['border', 'no_border', 'circle', 'square', 'none', 'fill', 'extend', 'tabbed',
|
|
48
|
+
'round', 'no_round', 'small_round', 'medium_round', 'large_round',
|
|
49
|
+
'left_round', 'right_round', 'top_round', 'bottom_round']
|
|
50
|
+
MARGINS = ['margin', 'no_margin', 'auto_margin', 'tiny_margin', 'small_margin', 'medium_margin', 'large_margin',
|
|
51
|
+
'left_margin', 'right_margin', 'top_margin', 'bottom_margin', 'horizontal_margin', 'vertical_margin']
|
|
52
|
+
PADDINGS = ['padding', 'no_padding', 'tiny_padding', 'small_padding', 'medium_padding', 'large_padding',
|
|
53
|
+
'left_padding', 'right_padding', 'top_padding', 'bottom_padding', 'horizontal_padding', 'vertical_padding']
|
|
54
|
+
POSITIONS = ['left', 'right', 'center', 'top', 'bottom', 'middle', 'front', 'back']
|
|
55
|
+
RESPONSIVE = ['responsive', 's', 'm', 'l']
|
|
56
|
+
ALIGNMENTS = ['left_align', 'right_align', 'center_align', 'top_align', 'bottom_align', 'middle_align']
|
|
57
|
+
BLURS = ['blur', 'small_blur', 'medium_blur', 'large_blur']
|
|
58
|
+
OPACITIES = ['opacity', 'no_opacity', 'small_opacity', 'medium_opacity', 'large_opacity']
|
|
59
|
+
SHADOWS = ['shadow', 'left_shadow', 'right_shadow', 'top_shadow', 'bottom_shadow']
|
|
60
|
+
SPACES = ['space', 'no_space', 'small_space', 'medium_space', 'large_space']
|
|
61
|
+
RIPPLES = ['ripple', 'slow_ripple', 'fast_ripple']
|
|
62
|
+
SCROLLS = ['scroll', 'no_scroll']
|
|
63
|
+
WAVES = ['wave', 'no_wave']
|
|
64
|
+
ZOOMS = ['zoom', 'tiny_zoom', 'small_zoom', 'medium_zoom', 'large_zoom', 'extra_zoom']
|
|
65
|
+
THEME_HELPERS = ['light', 'dark', 'primary', 'secondary', 'tertiary', 'transparent',
|
|
66
|
+
'primary_text', 'primary_border', 'primary_container',
|
|
67
|
+
'secondary_text', 'secondary_border', 'secondary_container',
|
|
68
|
+
'tertiary_text', 'tertiary_border', 'tertiary_container',
|
|
69
|
+
'error', 'error_text', 'error_border', 'error_container',
|
|
70
|
+
'background', 'surface', 'surface_variant', 'inverse_surface',
|
|
71
|
+
'inverse_primary', 'inverse_primary_text', 'inverse_primary_border',
|
|
72
|
+
'black', 'black_text', 'black_border',
|
|
73
|
+
'white', 'white_text', 'white_border',
|
|
74
|
+
'transparent_text', 'transparent_border']
|
|
75
|
+
TYPOGRAPHY = ['italic', 'bold', 'underline', 'overline', 'upper', 'lower', 'capitalize',
|
|
76
|
+
'link', 'small_text', 'medium_text', 'large_text']
|
|
77
|
+
TRIGGERS = ['active']
|
|
78
|
+
|
|
79
|
+
# Generate color variants (color1-10, color, color-border, color-text)
|
|
80
|
+
COLOR_HELPERS = []
|
|
81
|
+
for color in COLOR_NAMES:
|
|
82
|
+
for i in range(1, 11):
|
|
83
|
+
COLOR_HELPERS.append(f'{color}{i}')
|
|
84
|
+
COLOR_HELPERS.extend([color, f'{color}_border', f'{color}_text'])
|
|
85
|
+
|
|
86
|
+
# Combine all helpers
|
|
87
|
+
ALL_HELPERS = (SIZES + WIDTH_HEIGHT + ELEVATES + DIRECTIONS + FORMS + MARGINS + PADDINGS +
|
|
88
|
+
POSITIONS + RESPONSIVE + ALIGNMENTS + BLURS + OPACITIES + SHADOWS + SPACES +
|
|
89
|
+
RIPPLES + SCROLLS + WAVES + ZOOMS + THEME_HELPERS + TYPOGRAPHY + TRIGGERS + COLOR_HELPERS)
|
|
90
|
+
|
|
91
|
+
# %% ../nbs/01_core.ipynb 11
|
|
92
|
+
#| code-fold: true
|
|
93
|
+
class _ThemeChain:
|
|
94
|
+
"""Internal class for building themed headers"""
|
|
95
|
+
def __init__(self, color=None):
|
|
96
|
+
self._color = color
|
|
97
|
+
|
|
98
|
+
def headers(self, title="App", mode="auto"):
|
|
99
|
+
"""Generate FastHTML headers with BeerCSS theming"""
|
|
100
|
+
hdrs = list(beer_hdrs)
|
|
101
|
+
if self._color:
|
|
102
|
+
color_map = {
|
|
103
|
+
'amber': '#ffc107', 'blue': '#2196f3', 'red': '#f44336', 'green': '#4caf50',
|
|
104
|
+
'purple': '#9c27b0', 'orange': '#ff9800', 'pink': '#e91e63', 'cyan': '#00bcd4',
|
|
105
|
+
'teal': '#009688', 'indigo': '#3f51b5', 'lime': '#cddc39', 'grey': '#9e9e9e',
|
|
106
|
+
'brown': '#795548', 'yellow': '#ffeb3b', 'light_blue': '#03a9f4',
|
|
107
|
+
'light_green': '#8bc34a', 'deep_orange': '#ff5722', 'deep_purple': '#673ab7',
|
|
108
|
+
'blue_grey': '#607d8b'
|
|
109
|
+
}
|
|
110
|
+
hex_color = color_map.get(self._color, '#673ab7')
|
|
111
|
+
theme_script = Script(f'''
|
|
112
|
+
window.addEventListener("load", () => {{
|
|
113
|
+
function initTheme() {{
|
|
114
|
+
if (typeof ui !== 'undefined') {{
|
|
115
|
+
try {{
|
|
116
|
+
ui("theme", "{hex_color}");
|
|
117
|
+
}} catch (e) {{ console.error("Beer CSS theme error:", e.message); }}
|
|
118
|
+
}}
|
|
119
|
+
if (typeof ui !== 'undefined' && "{mode}" !== "auto") {{
|
|
120
|
+
try {{ ui("mode", "{mode}"); }} catch (e) {{ }}
|
|
121
|
+
}}
|
|
122
|
+
}}
|
|
123
|
+
setTimeout(initTheme, 50);
|
|
124
|
+
setTimeout(initTheme, 200);
|
|
125
|
+
setTimeout(initTheme, 500);
|
|
126
|
+
}});
|
|
127
|
+
window.setTheme = function(hexColor) {{
|
|
128
|
+
if (typeof ui !== 'undefined') {{ try {{ ui("theme", hexColor); }} catch (e) {{ }} }}
|
|
129
|
+
}};
|
|
130
|
+
window.toggleMode = function() {{
|
|
131
|
+
if (typeof ui !== 'undefined') {{
|
|
132
|
+
try {{
|
|
133
|
+
const currentMode = ui("mode");
|
|
134
|
+
const newMode = currentMode === "dark" ? "light" : "dark";
|
|
135
|
+
ui("mode", newMode);
|
|
136
|
+
return newMode;
|
|
137
|
+
}} catch (e) {{ }}
|
|
138
|
+
}}
|
|
139
|
+
}};
|
|
140
|
+
window.setMode = function(mode) {{
|
|
141
|
+
if (typeof ui !== 'undefined') {{ try {{ ui("mode", mode); }} catch (e) {{ }} }}
|
|
142
|
+
}};
|
|
143
|
+
window.toggleNav = function(selector) {{
|
|
144
|
+
const nav = document.querySelector(selector);
|
|
145
|
+
if (nav) {{ nav.classList.toggle('max'); }}
|
|
146
|
+
}};
|
|
147
|
+
''')
|
|
148
|
+
hdrs.append(theme_script)
|
|
149
|
+
hdrs.append(Title(title))
|
|
150
|
+
return tuple(hdrs)
|
|
151
|
+
|
|
152
|
+
# %% ../nbs/01_core.ipynb 12
|
|
153
|
+
#| code-fold: true
|
|
154
|
+
class _ThemeNamespace:
|
|
155
|
+
"""Namespace providing color properties that return _ThemeChain instances"""
|
|
156
|
+
@property
|
|
157
|
+
def amber(self): return _ThemeChain("amber")
|
|
158
|
+
@property
|
|
159
|
+
def blue(self): return _ThemeChain("blue")
|
|
160
|
+
@property
|
|
161
|
+
def red(self): return _ThemeChain("red")
|
|
162
|
+
@property
|
|
163
|
+
def slate(self): return _ThemeChain("grey")
|
|
164
|
+
@property
|
|
165
|
+
def stone(self): return _ThemeChain("brown")
|
|
166
|
+
@property
|
|
167
|
+
def gray(self): return _ThemeChain("grey")
|
|
168
|
+
@property
|
|
169
|
+
def grey(self): return _ThemeChain("grey")
|
|
170
|
+
@property
|
|
171
|
+
def neutral(self): return _ThemeChain("grey")
|
|
172
|
+
@property
|
|
173
|
+
def rose(self): return _ThemeChain("pink")
|
|
174
|
+
@property
|
|
175
|
+
def orange(self): return _ThemeChain("orange")
|
|
176
|
+
@property
|
|
177
|
+
def green(self): return _ThemeChain("green")
|
|
178
|
+
@property
|
|
179
|
+
def yellow(self): return _ThemeChain("yellow")
|
|
180
|
+
@property
|
|
181
|
+
def violet(self): return _ThemeChain("purple")
|
|
182
|
+
@property
|
|
183
|
+
def purple(self): return _ThemeChain("purple")
|
|
184
|
+
@property
|
|
185
|
+
def zinc(self): return _ThemeChain("blue_grey")
|
|
186
|
+
@property
|
|
187
|
+
def cyan(self): return _ThemeChain("cyan")
|
|
188
|
+
@property
|
|
189
|
+
def teal(self): return _ThemeChain("teal")
|
|
190
|
+
@property
|
|
191
|
+
def indigo(self): return _ThemeChain("indigo")
|
|
192
|
+
@property
|
|
193
|
+
def pink(self): return _ThemeChain("pink")
|
|
194
|
+
@property
|
|
195
|
+
def lime(self): return _ThemeChain("lime")
|
|
196
|
+
@property
|
|
197
|
+
def light_blue(self): return _ThemeChain("light_blue")
|
|
198
|
+
@property
|
|
199
|
+
def light_green(self): return _ThemeChain("light_green")
|
|
200
|
+
@property
|
|
201
|
+
def deep_orange(self): return _ThemeChain("deep_orange")
|
|
202
|
+
@property
|
|
203
|
+
def deep_purple(self): return _ThemeChain("deep_purple")
|
|
204
|
+
@property
|
|
205
|
+
def blue_grey(self): return _ThemeChain("blue_grey")
|
|
206
|
+
@property
|
|
207
|
+
def brown(self): return _ThemeChain("brown")
|
|
208
|
+
|
|
209
|
+
MatTheme = _ThemeNamespace()
|
|
210
|
+
|
|
211
|
+
# %% ../nbs/01_core.ipynb 16
|
|
212
|
+
#| code-fold: true
|
|
213
|
+
class BeerCssChain:
|
|
214
|
+
"""Base class for chaining Beer CSS helper classes together"""
|
|
215
|
+
def __init__(self, tokens=None):
|
|
216
|
+
self._tokens = list(tokens or [])
|
|
217
|
+
|
|
218
|
+
def __iter__(self):
|
|
219
|
+
return iter(self._tokens)
|
|
220
|
+
|
|
221
|
+
def __str__(self):
|
|
222
|
+
return " ".join(self._tokens)
|
|
223
|
+
|
|
224
|
+
def __repr__(self):
|
|
225
|
+
return f"BeerCssChain({self._tokens})"
|
|
226
|
+
|
|
227
|
+
# Generate properties for all Beer CSS helpers
|
|
228
|
+
for name in ALL_HELPERS:
|
|
229
|
+
css_name = name.replace('_', '-')
|
|
230
|
+
setattr(BeerCssChain, name, property(lambda self, css=css_name: type(self)(self._tokens + [css])))
|