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/tags.py CHANGED
@@ -1,29 +1,16 @@
1
- from typing import Optional, Literal, Any, Union
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
- # Define exports for this module
7
- __all__ = [
8
- # Custom EidosUI components
9
- 'Button', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Body',
10
- # Semantic components with styling
11
- 'Strong', 'I', 'Small', 'Del', 'Abbr', 'Var', 'Mark', 'Time',
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
- def H1(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
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
- def H2(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
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
- def H3(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
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
- def H4(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
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
- def H5(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
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
- def H6(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
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
- def Body(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
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 I(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
104
- return air.I(*content, class_=stringify(styles.semantic.i, class_), **kwargs)
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_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
110
- return air.Del(*content, class_=stringify(styles.semantic.del_, class_), **kwargs)
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
- def Abbr(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
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.semantic.abbr, class_), **kwargs)
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 Var(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
128
- return air.Var(*content, class_=stringify(styles.semantic.var, class_), **kwargs)
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 Time(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
134
- return air.Time(*content, class_=stringify(styles.semantic.time, class_), **kwargs)
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 Pre(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
140
- return air.Pre(*content, class_=stringify(styles.semantic.pre, class_), **kwargs)
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 Samp(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
146
- return air.Samp(*content, class_=stringify(styles.semantic.samp, class_), **kwargs)
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 Cite(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
152
- return air.Cite(*content, class_=stringify(styles.semantic.cite, class_), **kwargs)
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 Hr(class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
158
- return air.Hr(class_=stringify(styles.semantic.hr, class_), **kwargs)
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 Summary(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
164
- return air.Summary(*content, class_=stringify(styles.semantic.summary, class_), **kwargs)
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 Dt(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
170
- return air.Dt(*content, class_=stringify(styles.semantic.dt, class_), **kwargs)
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 Figure(*content: Any, class_: Optional[Union[str, list[str]]] = None, **kwargs: Any) -> air.Tag:
176
- return air.Figure(*content, class_=stringify(styles.semantic.figure, class_), **kwargs)
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 typing import Optional, Union, List
4
- import os
5
- import sys
3
+ from pathlib import Path
6
4
 
7
5
 
8
- def stringify(*classes: Optional[Union[str, List[str]]]) -> str:
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 get_eidos_static_directory() -> str:
40
+ def get_eidos_static_files(markdown: bool = False) -> dict:
43
41
  """
44
- Get the path to eidos static files for mounting in FastAPI/Air apps.
45
-
46
- This function returns the directory containing the eidos package files,
47
- which includes the CSS directory. Use this when mounting static files
48
- in your application.
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
- The absolute path to the eidos package directory
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 get_eidos_static_directory
56
- >>> app.mount("/eidos", StaticFiles(directory=get_eidos_static_directory()), name="eidos")
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
- try:
59
- from importlib.resources import files
60
- import pathlib
61
- # Convert MultiplexedPath to actual filesystem path
62
- eidos_path = files('eidos')
63
- if hasattr(eidos_path, '_paths'):
64
- # MultiplexedPath - get the first valid path
65
- for path in eidos_path._paths:
66
- if isinstance(path, pathlib.Path) and path.exists():
67
- return str(path)
68
- # Try to get the path directly
69
- return str(eidos_path)
70
- except (ImportError, AttributeError):
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,,