eidosui 0.4.0__py3-none-any.whl → 0.6.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.
- eidos/__init__.py +270 -0
- eidos/components/__init__.py +11 -0
- eidos/components/headers.py +16 -14
- eidos/components/navigation.py +44 -35
- eidos/components/table.py +84 -0
- eidos/components/tabs.py +140 -0
- eidos/css/styles.css +155 -0
- eidos/plugins/__init__.py +1 -1
- eidos/plugins/markdown/__init__.py +3 -3
- eidos/plugins/markdown/components.py +10 -22
- eidos/plugins/markdown/extensions/__init__.py +1 -1
- eidos/plugins/markdown/extensions/alerts.py +68 -78
- eidos/plugins/markdown/renderer.py +19 -24
- eidos/styles.py +58 -11
- eidos/tags.py +144 -86
- eidos/utils.py +42 -38
- eidosui-0.6.0.dist-info/METADATA +113 -0
- eidosui-0.6.0.dist-info/RECORD +25 -0
- eidosui-0.4.0.dist-info/METADATA +0 -127
- eidosui-0.4.0.dist-info/RECORD +0 -22
- {eidosui-0.4.0.dist-info → eidosui-0.6.0.dist-info}/WHEEL +0 -0
- {eidosui-0.4.0.dist-info → eidosui-0.6.0.dist-info}/licenses/LICENSE +0 -0
eidos/tags.py
CHANGED
@@ -1,29 +1,16 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import Any
|
2
|
+
|
2
3
|
import air
|
4
|
+
|
3
5
|
from . import styles
|
4
6
|
from .utils import stringify
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
'Code', 'Pre', 'Kbd', 'Samp', 'Blockquote', 'Cite', 'Address',
|
13
|
-
'Hr', 'Details', 'Summary', 'Dl', 'Dt', 'Dd', 'Figure', 'Figcaption',
|
14
|
-
# Pass-through HTML tags from air.tags
|
15
|
-
'A', 'Area', 'Article', 'Aside', 'Audio', 'B', 'Base', 'Bdi', 'Bdo', 'Br',
|
16
|
-
'Canvas', 'Caption', 'Col', 'Colgroup', 'Data', 'Datalist', 'Dfn', 'Dialog', 'Div',
|
17
|
-
'Em', 'Embed', 'Fieldset', 'Footer', 'Form', 'Head', 'Header', 'Hgroup', 'Html',
|
18
|
-
'Iframe', 'Img', 'Input', 'Ins', 'Label', 'Legend', 'Li', 'Link',
|
19
|
-
'Main', 'Map', 'Menu', 'Meta', 'Meter', 'Nav', 'Noscript', 'Object', 'Ol', 'Optgroup', 'Option', 'Output',
|
20
|
-
'P', 'Param', 'Picture', 'Progress', 'Q', 'Rp', 'Rt', 'Ruby',
|
21
|
-
'S', 'Script', 'Search', 'Section', 'Select', 'Source', 'Span', 'Style', 'Sub', 'Sup',
|
22
|
-
'Table', 'Tbody', 'Td', 'Template', 'Textarea', 'Tfoot', 'Th', 'Thead', 'Title', 'Tr', 'Track',
|
23
|
-
'U', 'Ul', 'Video', 'Wbr'
|
24
|
-
]
|
25
|
-
|
26
|
-
def Button(*content: Any, class_: Optional[Union[str, list[str]]] = styles.buttons.primary, **kwargs: Any) -> air.Tag:
|
8
|
+
|
9
|
+
def Button(
|
10
|
+
*content: Any,
|
11
|
+
class_: str | list[str] | None = styles.buttons.primary,
|
12
|
+
**kwargs: Any,
|
13
|
+
) -> air.Tag:
|
27
14
|
"""
|
28
15
|
Args:
|
29
16
|
content: The content of the button.
|
@@ -38,7 +25,8 @@ def Button(*content: Any, class_: Optional[Union[str, list[str]]] = styles.butto
|
|
38
25
|
"""
|
39
26
|
return air.Button(*content, class_=stringify(styles.buttons.base, class_), **kwargs)
|
40
27
|
|
41
|
-
|
28
|
+
|
29
|
+
def H1(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
42
30
|
"""
|
43
31
|
Args:
|
44
32
|
content: The content of the h1 tag.
|
@@ -53,7 +41,8 @@ def H1(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs:
|
|
53
41
|
"""
|
54
42
|
return air.H1(*content, class_=stringify(styles.typography.h1, class_), **kwargs)
|
55
43
|
|
56
|
-
|
44
|
+
|
45
|
+
def H2(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
57
46
|
"""
|
58
47
|
Args:
|
59
48
|
content: The content of the h2 tag.
|
@@ -68,7 +57,8 @@ def H2(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs:
|
|
68
57
|
"""
|
69
58
|
return air.H2(*content, class_=stringify(styles.typography.h2, class_), **kwargs)
|
70
59
|
|
71
|
-
|
60
|
+
|
61
|
+
def H3(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
72
62
|
"""
|
73
63
|
Args:
|
74
64
|
content: The content of the h3 tag.
|
@@ -83,33 +73,43 @@ def H3(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs:
|
|
83
73
|
"""
|
84
74
|
return air.H3(*content, class_=stringify(styles.typography.h3, class_), **kwargs)
|
85
75
|
|
86
|
-
|
76
|
+
|
77
|
+
def H4(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
87
78
|
return air.H4(*content, class_=stringify(styles.typography.h4, class_), **kwargs)
|
88
79
|
|
89
|
-
|
80
|
+
|
81
|
+
def H5(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
90
82
|
return air.H5(*content, class_=stringify(styles.typography.h5, class_), **kwargs)
|
91
83
|
|
92
|
-
|
84
|
+
|
85
|
+
def H6(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
93
86
|
return air.H6(*content, class_=stringify(styles.typography.h6, class_), **kwargs)
|
94
87
|
|
95
|
-
|
88
|
+
|
89
|
+
def Body(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
96
90
|
return air.Body(*content, class_=stringify(styles.Theme.body, class_), **kwargs)
|
97
91
|
|
92
|
+
|
98
93
|
# Semantic HTML Elements
|
99
94
|
|
100
|
-
def Strong(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
|
101
|
-
return air.Strong(*content, class_=stringify(styles.semantic.strong, class_), **kwargs)
|
102
95
|
|
103
|
-
def
|
104
|
-
return air.
|
96
|
+
def Strong(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
97
|
+
return air.Strong(*content, class_=stringify(styles.typography.strong, class_), **kwargs)
|
98
|
+
|
99
|
+
|
100
|
+
def I(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
101
|
+
return air.I(*content, class_=stringify(styles.typography.i, class_), **kwargs)
|
102
|
+
|
103
|
+
|
104
|
+
def Small(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
105
|
+
return air.Small(*content, class_=stringify(styles.typography.small, class_), **kwargs)
|
105
106
|
|
106
|
-
def Small(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
|
107
|
-
return air.Small(*content, class_=stringify(styles.semantic.small, class_), **kwargs)
|
108
107
|
|
109
|
-
def Del(*content: Any, class_:
|
110
|
-
return air.Del(*content, class_=stringify(styles.
|
108
|
+
def Del(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
109
|
+
return air.Del(*content, class_=stringify(styles.typography.del_, class_), **kwargs)
|
111
110
|
|
112
|
-
|
111
|
+
|
112
|
+
def Abbr(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
113
113
|
"""
|
114
114
|
Args:
|
115
115
|
content: The content of the abbr tag.
|
@@ -122,73 +122,131 @@ def Abbr(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs
|
|
122
122
|
Example:
|
123
123
|
Abbr("HTML", title="Hyper Text Markup Language")
|
124
124
|
"""
|
125
|
-
return air.Abbr(*content, class_=stringify(styles.
|
125
|
+
return air.Abbr(*content, class_=stringify(styles.typography.abbr, class_), **kwargs)
|
126
|
+
|
127
|
+
|
128
|
+
def Var(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
129
|
+
return air.Var(*content, class_=stringify(styles.typography.var, class_), **kwargs)
|
130
|
+
|
131
|
+
|
132
|
+
def Mark(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
133
|
+
return air.Mark(*content, class_=stringify(styles.typography.mark, class_), **kwargs)
|
134
|
+
|
135
|
+
|
136
|
+
def Time(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
137
|
+
return air.Time(*content, class_=stringify(styles.typography.time, class_), **kwargs)
|
138
|
+
|
139
|
+
|
140
|
+
def Code(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
141
|
+
return air.Code(*content, class_=stringify(styles.typography.code, class_), **kwargs)
|
142
|
+
|
143
|
+
|
144
|
+
def Pre(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
145
|
+
return air.Pre(*content, class_=stringify(styles.typography.pre, class_), **kwargs)
|
146
|
+
|
147
|
+
|
148
|
+
def Kbd(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
149
|
+
return air.Kbd(*content, class_=stringify(styles.typography.kbd, class_), **kwargs)
|
150
|
+
|
151
|
+
|
152
|
+
def Samp(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
153
|
+
return air.Samp(*content, class_=stringify(styles.typography.samp, class_), **kwargs)
|
154
|
+
|
155
|
+
|
156
|
+
def Blockquote(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
157
|
+
return air.Blockquote(*content, class_=stringify(styles.typography.blockquote, class_), **kwargs)
|
158
|
+
|
159
|
+
|
160
|
+
def Cite(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
161
|
+
return air.Cite(*content, class_=stringify(styles.typography.cite, class_), **kwargs)
|
162
|
+
|
163
|
+
|
164
|
+
def Address(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
165
|
+
return air.Address(*content, class_=stringify(styles.typography.address, class_), **kwargs)
|
166
|
+
|
167
|
+
|
168
|
+
def Hr(class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
169
|
+
return air.Hr(class_=stringify(styles.typography.hr, class_), **kwargs)
|
170
|
+
|
171
|
+
|
172
|
+
def Details(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
173
|
+
return air.Details(*content, class_=stringify(styles.typography.details, class_), **kwargs)
|
174
|
+
|
175
|
+
|
176
|
+
def Summary(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
177
|
+
return air.Summary(*content, class_=stringify(styles.typography.summary, class_), **kwargs)
|
178
|
+
|
179
|
+
|
180
|
+
def Dl(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
181
|
+
return air.Dl(*content, class_=stringify(styles.typography.dl, class_), **kwargs)
|
182
|
+
|
183
|
+
|
184
|
+
def Dt(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
185
|
+
return air.Dt(*content, class_=stringify(styles.typography.dt, class_), **kwargs)
|
186
|
+
|
187
|
+
|
188
|
+
def Dd(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
189
|
+
return air.Dd(*content, class_=stringify(styles.typography.dd, class_), **kwargs)
|
190
|
+
|
191
|
+
|
192
|
+
def Figure(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
193
|
+
return air.Figure(*content, class_=stringify(styles.typography.figure, class_), **kwargs)
|
194
|
+
|
195
|
+
|
196
|
+
def Figcaption(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
197
|
+
return air.Figcaption(*content, class_=stringify(styles.typography.figcaption, class_), **kwargs)
|
198
|
+
|
199
|
+
|
200
|
+
# Table elements with styling
|
201
|
+
|
202
|
+
|
203
|
+
def Table(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
204
|
+
"""Styled table element."""
|
205
|
+
return air.Table(*content, class_=stringify(styles.tables.table, class_), **kwargs)
|
206
|
+
|
126
207
|
|
127
|
-
def
|
128
|
-
|
208
|
+
def Thead(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
209
|
+
"""Styled table head element."""
|
210
|
+
return air.Thead(*content, class_=stringify(styles.tables.thead, class_), **kwargs)
|
129
211
|
|
130
|
-
def Mark(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
|
131
|
-
return air.Mark(*content, class_=stringify(styles.semantic.mark, class_), **kwargs)
|
132
212
|
|
133
|
-
def
|
134
|
-
|
213
|
+
def Tbody(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
214
|
+
"""Styled table body element."""
|
215
|
+
return air.Tbody(*content, class_=stringify(styles.tables.tbody, class_), **kwargs)
|
135
216
|
|
136
|
-
def Code(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
|
137
|
-
return air.Code(*content, class_=stringify(styles.semantic.code, class_), **kwargs)
|
138
217
|
|
139
|
-
def
|
140
|
-
|
218
|
+
def Tfoot(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
219
|
+
"""Styled table footer element."""
|
220
|
+
return air.Tfoot(*content, class_=stringify(styles.tables.tfoot, class_), **kwargs)
|
141
221
|
|
142
|
-
def Kbd(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
|
143
|
-
return air.Kbd(*content, class_=stringify(styles.semantic.kbd, class_), **kwargs)
|
144
222
|
|
145
|
-
def
|
146
|
-
|
223
|
+
def Tr(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
224
|
+
"""Styled table row element."""
|
225
|
+
return air.Tr(*content, class_=stringify(styles.tables.tr, class_), **kwargs)
|
147
226
|
|
148
|
-
def Blockquote(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
|
149
|
-
return air.Blockquote(*content, class_=stringify(styles.semantic.blockquote, class_), **kwargs)
|
150
227
|
|
151
|
-
def
|
152
|
-
|
228
|
+
def Th(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
229
|
+
"""Styled table header cell element."""
|
230
|
+
return air.Th(*content, class_=stringify(styles.tables.th, class_), **kwargs)
|
153
231
|
|
154
|
-
def Address(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
|
155
|
-
return air.Address(*content, class_=stringify(styles.semantic.address, class_), **kwargs)
|
156
232
|
|
157
|
-
def
|
158
|
-
|
233
|
+
def Td(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
234
|
+
"""Styled table data cell element."""
|
235
|
+
return air.Td(*content, class_=stringify(styles.tables.td, class_), **kwargs)
|
159
236
|
|
160
|
-
def Details(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
|
161
|
-
return air.Details(*content, class_=stringify(styles.semantic.details, class_), **kwargs)
|
162
237
|
|
163
|
-
def
|
164
|
-
return air.
|
238
|
+
def Ul(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
239
|
+
return air.Ul(*content, class_=stringify(styles.lists.ul, class_), **kwargs)
|
165
240
|
|
166
|
-
def Dl(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
|
167
|
-
return air.Dl(*content, class_=stringify(styles.semantic.dl, class_), **kwargs)
|
168
241
|
|
169
|
-
def
|
170
|
-
return air.
|
242
|
+
def Ol(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
243
|
+
return air.Ol(*content, class_=stringify(styles.lists.ol, class_), **kwargs)
|
171
244
|
|
172
|
-
def Dd(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
|
173
|
-
return air.Dd(*content, class_=stringify(styles.semantic.dd, class_), **kwargs)
|
174
245
|
|
175
|
-
def
|
176
|
-
return air.
|
246
|
+
def Li(*content: Any, class_: str | list[str] | None = None, **kwargs: Any) -> air.Tag:
|
247
|
+
return air.Li(*content, class_=stringify(styles.lists.li, class_), **kwargs)
|
177
248
|
|
178
|
-
def Figcaption(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
|
179
|
-
return air.Figcaption(*content, class_=stringify(styles.semantic.figcaption, class_), **kwargs)
|
180
249
|
|
181
250
|
|
182
251
|
# Pass-through tags from air.tags
|
183
252
|
# Import all standard HTML tags that don't have custom styling
|
184
|
-
from air.tags import (
|
185
|
-
A, Area, Article, Aside, Audio, B, Base, Bdi, Bdo, Br,
|
186
|
-
Canvas, Caption, Col, Colgroup, Data, Datalist, Dfn, Dialog, Div,
|
187
|
-
Em, Embed, Fieldset, Footer, Form, Head, Header, Hgroup, Html,
|
188
|
-
Iframe, Img, Input, Ins, Label, Legend, Li, Link,
|
189
|
-
Main, Map, Menu, Meta, Meter, Nav, Noscript, Object, Ol, Optgroup, Option, Output,
|
190
|
-
P, Param, Picture, Progress, Q, Rp, Rt, Ruby,
|
191
|
-
S, Script, Search, Section, Select, Source, Span, Style, Sub, Sup,
|
192
|
-
Table, Tbody, Td, Template, Textarea, Tfoot, Th, Thead, Title, Tr, Track,
|
193
|
-
U, Ul, Video, Wbr
|
194
|
-
)
|
eidos/utils.py
CHANGED
@@ -1,32 +1,30 @@
|
|
1
1
|
"""Core utility functions for EidosUI."""
|
2
2
|
|
3
|
-
from
|
4
|
-
import os
|
5
|
-
import sys
|
3
|
+
from pathlib import Path
|
6
4
|
|
7
5
|
|
8
|
-
def stringify(*classes:
|
6
|
+
def stringify(*classes: str | list[str] | None) -> str:
|
9
7
|
"""
|
10
8
|
Concatenate CSS classes, filtering out None values and flattening lists.
|
11
|
-
|
9
|
+
|
12
10
|
Args:
|
13
11
|
*classes: Variable number of class strings, lists of strings, or None values
|
14
|
-
|
12
|
+
|
15
13
|
Returns:
|
16
14
|
A single space-separated string of CSS classes
|
17
|
-
|
15
|
+
|
18
16
|
Examples:
|
19
17
|
>>> stringify("btn", "btn-primary")
|
20
18
|
"btn btn-primary"
|
21
|
-
|
19
|
+
|
22
20
|
>>> stringify("btn", None, "btn-lg")
|
23
21
|
"btn btn-lg"
|
24
|
-
|
22
|
+
|
25
23
|
>>> stringify(["btn", "btn-primary"], "mt-4")
|
26
24
|
"btn btn-primary mt-4"
|
27
25
|
"""
|
28
|
-
result = []
|
29
|
-
|
26
|
+
result: list[str] = []
|
27
|
+
|
30
28
|
for class_ in classes:
|
31
29
|
if class_ is None:
|
32
30
|
continue
|
@@ -35,38 +33,44 @@ def stringify(*classes: Optional[Union[str, List[str]]]) -> str:
|
|
35
33
|
result.extend(c for c in class_ if c)
|
36
34
|
elif isinstance(class_, str) and class_.strip():
|
37
35
|
result.append(class_.strip())
|
38
|
-
|
36
|
+
|
39
37
|
return " ".join(result)
|
40
38
|
|
41
39
|
|
42
|
-
def
|
40
|
+
def get_eidos_static_files(markdown: bool = False) -> dict:
|
43
41
|
"""
|
44
|
-
Get
|
45
|
-
|
46
|
-
This
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
Get a dictionary mapping URL paths to static file directories.
|
43
|
+
|
44
|
+
This provides a safe way to mount only specific static assets
|
45
|
+
without exposing Python source files.
|
46
|
+
|
47
|
+
Args:
|
48
|
+
markdown: Whether to include markdown plugin CSS (default: False)
|
49
|
+
|
50
50
|
Returns:
|
51
|
-
|
52
|
-
|
51
|
+
Dict mapping mount paths to directory paths
|
52
|
+
|
53
53
|
Example:
|
54
54
|
>>> from fastapi.staticfiles import StaticFiles
|
55
|
-
>>> from eidos.utils import
|
56
|
-
>>>
|
55
|
+
>>> from eidos.utils import get_eidos_static_files
|
56
|
+
>>> # Basic usage - just core CSS and JS
|
57
|
+
>>> for mount_path, directory in get_eidos_static_files().items():
|
58
|
+
... app.mount(mount_path, StaticFiles(directory=directory), name=mount_path.strip('/'))
|
59
|
+
>>>
|
60
|
+
>>> # Include markdown CSS
|
61
|
+
>>> for mount_path, directory in get_eidos_static_files(markdown=True).items():
|
62
|
+
... app.mount(mount_path, StaticFiles(directory=directory), name=mount_path.strip('/'))
|
57
63
|
"""
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
# Fallback for development or if importlib.resources fails
|
72
|
-
return os.path.dirname(os.path.abspath(__file__))
|
64
|
+
# Use pathlib for cleaner path handling
|
65
|
+
base_path = Path(__file__).parent.absolute()
|
66
|
+
|
67
|
+
static_files = {
|
68
|
+
"/eidos/css": str(base_path / "css"),
|
69
|
+
"/eidos/js": str(base_path / "js"),
|
70
|
+
}
|
71
|
+
|
72
|
+
# Only include markdown CSS if requested
|
73
|
+
if markdown:
|
74
|
+
static_files["/eidos/plugins/markdown/css"] = str(base_path / "plugins" / "markdown" / "css")
|
75
|
+
|
76
|
+
return static_files
|
@@ -0,0 +1,113 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: eidosui
|
3
|
+
Version: 0.6.0
|
4
|
+
Summary: A modern, Tailwind CSS-based UI library for air development
|
5
|
+
Project-URL: Homepage, https://github.com/isaac-flath/EidosUI
|
6
|
+
Project-URL: Repository, https://github.com/isaac-flath/EidosUI
|
7
|
+
Project-URL: Issues, https://github.com/isaac-flath/EidosUI/issues
|
8
|
+
Project-URL: Documentation, https://github.com/isaac-flath/EidosUI#readme
|
9
|
+
Author: Isaac Flath
|
10
|
+
License-Expression: MIT
|
11
|
+
License-File: LICENSE
|
12
|
+
Keywords: air,components,css,fastapi,tailwind,ui,web
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
14
|
+
Classifier: Intended Audience :: Developers
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
21
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
23
|
+
Requires-Python: >=3.10
|
24
|
+
Requires-Dist: air>=0.12
|
25
|
+
Requires-Dist: fastapi[standard]
|
26
|
+
Requires-Dist: uvicorn
|
27
|
+
Provides-Extra: dev
|
28
|
+
Requires-Dist: black; extra == 'dev'
|
29
|
+
Requires-Dist: isort; extra == 'dev'
|
30
|
+
Requires-Dist: mypy; extra == 'dev'
|
31
|
+
Requires-Dist: pytest; extra == 'dev'
|
32
|
+
Requires-Dist: ruff; extra == 'dev'
|
33
|
+
Provides-Extra: markdown
|
34
|
+
Requires-Dist: markdown>=3.4; extra == 'markdown'
|
35
|
+
Description-Content-Type: text/markdown
|
36
|
+
|
37
|
+
# EidosUI
|
38
|
+
|
39
|
+
Modern UI library for Python web frameworks. Built on Air and Tailwind CSS.
|
40
|
+
|
41
|
+
> [!CAUTION]
|
42
|
+
> This library is in alpha, and may have semi-frequent breaking changes. I'd love for you to try it an contribute feedback or PRs!
|
43
|
+
|
44
|
+
## Installation
|
45
|
+
|
46
|
+
```bash
|
47
|
+
pip install eidosui
|
48
|
+
```
|
49
|
+
|
50
|
+
## Quick Start
|
51
|
+
|
52
|
+
```python
|
53
|
+
from eidos import *
|
54
|
+
import air
|
55
|
+
|
56
|
+
app = air.Air()
|
57
|
+
|
58
|
+
@app.get("/")
|
59
|
+
def home():
|
60
|
+
return Html(
|
61
|
+
Head(
|
62
|
+
Title("My App"),
|
63
|
+
*EidosHeaders() # Required CSS/JS
|
64
|
+
),
|
65
|
+
Body(
|
66
|
+
H1("Welcome"),
|
67
|
+
P("Build modern web apps with Python."),
|
68
|
+
DataTable.from_lists(
|
69
|
+
[["Alice", "30"], ["Bob", "25"]],
|
70
|
+
headers=["Name", "Age"]
|
71
|
+
)
|
72
|
+
)
|
73
|
+
)
|
74
|
+
|
75
|
+
app.run()
|
76
|
+
```
|
77
|
+
|
78
|
+
## Features
|
79
|
+
|
80
|
+
- **Styled HTML tags** - Pre-styled versions of all HTML elements
|
81
|
+
- **Components** - DataTable, NavBar, and more
|
82
|
+
- **Themes** - Light/dark themes via CSS variables
|
83
|
+
- **Type hints** - Full type annotations
|
84
|
+
- **Air integration** - Works seamlessly with Air framework
|
85
|
+
|
86
|
+
## Plugins
|
87
|
+
|
88
|
+
### Markdown
|
89
|
+
|
90
|
+
```bash
|
91
|
+
pip install "eidosui[markdown]"
|
92
|
+
```
|
93
|
+
|
94
|
+
```python
|
95
|
+
from eidos.plugins.markdown import Markdown, MarkdownCSS
|
96
|
+
|
97
|
+
Head(
|
98
|
+
*EidosHeaders(),
|
99
|
+
MarkdownCSS() # Add markdown styles
|
100
|
+
)
|
101
|
+
|
102
|
+
Body(
|
103
|
+
Markdown("# Hello\n\nSupports **GitHub Flavored Markdown**")
|
104
|
+
)
|
105
|
+
```
|
106
|
+
|
107
|
+
## Documentation
|
108
|
+
|
109
|
+
Full documentation: https://eidosui.readthedocs.io
|
110
|
+
|
111
|
+
## License
|
112
|
+
|
113
|
+
MIT
|
@@ -0,0 +1,25 @@
|
|
1
|
+
eidos/__init__.py,sha256=zXRgrBv7PD1Om8AIV77-fUMkxFXlD3z5KWd-OyBoIZo,3538
|
2
|
+
eidos/styles.py,sha256=771gD4y0ORvOPoF5yy9sPvDaVKpcH9WoovEeY1-0638,3308
|
3
|
+
eidos/tags.py,sha256=N0a01Q_Iatkq3KL75lk88gZjuCWrnRQjQOxftR099o8,9309
|
4
|
+
eidos/utils.py,sha256=9hRZUL7DzyO3apo_lwpmTOEIPf2fCv-xTdVmh1u_0i8,2375
|
5
|
+
eidos/components/__init__.py,sha256=AUpvyy_PdNxleiNPBwtjDZhs8SArFvaqmUn2x7b0E28,339
|
6
|
+
eidos/components/headers.py,sha256=jWsQxXHxATL4kVAZiYb4IkfvLYN6zPCCAyj-JQ_yBCg,1949
|
7
|
+
eidos/components/navigation.py,sha256=gMIwvM75tVK2We1MNhVKMFvBD7H3gM6qDeVEX5XNUt0,2481
|
8
|
+
eidos/components/table.py,sha256=nmtVXh0fRunJ0Uhwq4CXDzKdFbhbY09NafXQRJZyoSc,2538
|
9
|
+
eidos/components/tabs.py,sha256=Xiph2HgP0Eph80E2UvYriPvQtfSY7CsdDOIcD1NJVnA,3535
|
10
|
+
eidos/css/styles.css,sha256=Th7e3z3UF8hdVjOelwos2zqzUM9C8tGi-hVaGfX4tjU,13056
|
11
|
+
eidos/css/themes/dark.css,sha256=yUDNz7iLEJ_Q63MrKXlrhYcpojm1L2eNUOthzhYc3Vs,4170
|
12
|
+
eidos/css/themes/eidos-variables.css,sha256=s4_CUivnqvndE4c7T1stp59orEHL_0C9tmN0rxai7bU,5686
|
13
|
+
eidos/css/themes/light.css,sha256=kESbN5Z4ovCn-Q3fxilQcjafgMCIyyJiocU9kMC5sIM,2674
|
14
|
+
eidos/js/eidos.js,sha256=ag6aoyWIE234ZoMiXJV-KVgBTsPR-fZd5Qhuo4rEeh0,5048
|
15
|
+
eidos/plugins/__init__.py,sha256=8PQKKy0bFlhoWwJhQ_Oo8oR0lVuZGaqm6-TwcaIq-YU,26
|
16
|
+
eidos/plugins/markdown/__init__.py,sha256=_6M4vQ7yfrgGFFVgJ1IBpJvbWG_qNJ5v9QVzZixlYB8,548
|
17
|
+
eidos/plugins/markdown/components.py,sha256=XrBhpA49gmqFzdlggv69sxm5OT5l5dC5AiFZmIRYGss,1123
|
18
|
+
eidos/plugins/markdown/renderer.py,sha256=pBO-iTfcfXDICKIhu5tS3YsAgSV7A6OOG9N_xRTkYN4,1651
|
19
|
+
eidos/plugins/markdown/css/markdown.css,sha256=RxNx7aJDmJMx3zuydX10uAMaPFtl9r6zOFDni9Idsdk,6226
|
20
|
+
eidos/plugins/markdown/extensions/__init__.py,sha256=hRe8Pk_5ahmZjf68sJCbBGTj9B1KONLlv-nhOg7kudk,29
|
21
|
+
eidos/plugins/markdown/extensions/alerts.py,sha256=xY0NCNxUshhdKOe43fkGOV4ibcmQ4QzR0e_kQ1oq0kc,4002
|
22
|
+
eidosui-0.6.0.dist-info/METADATA,sha256=8PwVcturBKmYvCwhr3r2-4mWqfN89uNMQE51YM6Mw98,2878
|
23
|
+
eidosui-0.6.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
24
|
+
eidosui-0.6.0.dist-info/licenses/LICENSE,sha256=evjPJs6lg9eka9CYtC6ErQrZ71IovVbdvZqqz3ax8E8,1064
|
25
|
+
eidosui-0.6.0.dist-info/RECORD,,
|