cronixui 1.1.2 → 1.1.3
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.
- package/README.md +1 -1
- package/package.json +71 -71
- package/packages/flutter/.qwen/settings.json +7 -0
- package/packages/flutter/pubspec.yaml +20 -20
- package/packages/go/cronixui/cronixui.go +926 -926
- package/packages/python/README.md +142 -0
- package/packages/python/cronixui/__init__.py +15 -6
- package/packages/python/cronixui/__pycache__/__init__.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/accordion.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/alert.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/avatar.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/badge.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/button.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/card.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/command_palette.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/core.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/dropdown.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/form.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/layout.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/list.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/loading.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/modal.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/nav.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/pagination.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/progress.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/search.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/table.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/tabs.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/toast.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/toggle.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/tokens.cpython-314.pyc +0 -0
- package/packages/python/cronixui/__pycache__/tooltip.cpython-314.pyc +0 -0
- package/packages/python/cronixui/alert.py +119 -36
- package/packages/python/cronixui/avatar.py +129 -22
- package/packages/python/cronixui/badge.py +161 -24
- package/packages/python/cronixui/button.py +96 -27
- package/packages/python/cronixui/card.py +206 -33
- package/packages/python/cronixui/core.py +212 -23
- package/packages/python/cronixui/form.py +552 -141
- package/packages/python/cronixui/layout.py +358 -96
- package/packages/python/cronixui/list.py +140 -37
- package/packages/python/cronixui/loading.py +107 -17
- package/packages/python/cronixui/progress.py +189 -47
- package/packages/python/cronixui/table.py +118 -31
- package/packages/python/cronixui/tooltip.py +117 -15
- package/packages/react/src/components/Accordion.tsx +82 -82
- package/packages/react/src/components/Button.tsx +47 -47
- package/packages/react/src/components/Card.tsx +69 -69
- package/packages/react/src/components/CommandPalette.tsx +131 -131
- package/packages/react/src/components/Dropdown.tsx +88 -88
- package/packages/react/src/components/FileInput.tsx +86 -86
- package/packages/react/src/components/FormGroup.tsx +36 -36
- package/packages/react/src/components/List.tsx +55 -55
- package/packages/react/src/components/Pagination.tsx +107 -107
- package/packages/react/src/components/Progress.tsx +49 -49
- package/packages/react/src/components/Search.tsx +95 -95
- package/packages/react/src/components/Sidebar.tsx +64 -64
- package/packages/react/src/components/Stack.tsx +69 -69
- package/packages/react/src/components/Table.tsx +90 -90
- package/packages/react/src/components/Toast.tsx +134 -134
- package/packages/react/src/components/Typography.tsx +66 -66
- package/packages/react/src/index.ts +40 -40
- package/packages/react/src/styles.css +2039 -2039
- package/packages/rust/cronixui/src/components/avatar.rs +85 -85
- package/packages/rust/cronixui/src/components/breadcrumb.rs +58 -58
- package/packages/rust/cronixui/src/components/card.rs +259 -259
- package/packages/rust/cronixui/src/components/command_palette.rs +254 -254
- package/packages/rust/cronixui/src/components/dropdown.rs +179 -179
- package/packages/rust/cronixui/src/components/file_input.rs +74 -74
- package/packages/rust/cronixui/src/components/mod.rs +51 -51
- package/packages/rust/cronixui/src/components/search.rs +185 -185
- package/packages/rust/cronixui/src/components/skeleton.rs +63 -63
- package/packages/rust/cronixui/src/components/table.rs +56 -56
- package/packages/rust/cronixui/src/lib.rs +128 -128
- package/packages/web/dist/cronixui.css +97 -93
- package/packages/web/dist/cronixui.min.css +1 -1
|
@@ -1,48 +1,237 @@
|
|
|
1
|
-
"""Core CronixUI functions.
|
|
1
|
+
"""Core CronixUI functions - HTML string generation utilities.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This module provides helper functions and dataclasses for generating HTML
|
|
4
|
+
as strings or structured data. It does NOT use browser DOM APIs.
|
|
5
|
+
"""
|
|
4
6
|
|
|
7
|
+
from __future__ import annotations
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
pass
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from typing import Dict, List, Optional, Union
|
|
9
11
|
|
|
10
12
|
|
|
11
|
-
def
|
|
12
|
-
"""
|
|
13
|
+
def escape_html(text: str) -> str:
|
|
14
|
+
"""Escape HTML special characters in text.
|
|
13
15
|
|
|
14
16
|
Args:
|
|
15
|
-
|
|
17
|
+
text: Raw text that may contain HTML special characters
|
|
16
18
|
|
|
17
19
|
Returns:
|
|
18
|
-
|
|
20
|
+
Text with HTML special characters escaped
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
>>> escape_html("<script>alert('xss')</script>")
|
|
24
|
+
'<script>alert('xss')</script>'
|
|
25
|
+
"""
|
|
26
|
+
return (
|
|
27
|
+
text.replace("&", "&")
|
|
28
|
+
.replace("<", "<")
|
|
29
|
+
.replace(">", ">")
|
|
30
|
+
.replace('"', """)
|
|
31
|
+
.replace("'", "'")
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def classes(*names: Optional[str], **flags: bool) -> str:
|
|
36
|
+
"""Build a CSS class string from names and conditional flags.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
*names: Always-included class names (None values are skipped)
|
|
40
|
+
**flags: Conditional class names (key is class suffix, value is boolean)
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Space-separated class string
|
|
44
|
+
|
|
45
|
+
Example:
|
|
46
|
+
>>> classes("cn-btn", "cn-btn-primary", active=True, disabled=False)
|
|
47
|
+
'cn-btn cn-btn-primary cn-btn-active'
|
|
48
|
+
>>> classes("cn-btn", size="lg") # size is truthy string, adds nothing
|
|
49
|
+
'cn-btn'
|
|
19
50
|
"""
|
|
20
|
-
|
|
51
|
+
parts = [n for n in names if n]
|
|
52
|
+
parts.extend(f"cn-{k}" for k, v in flags.items() if v)
|
|
53
|
+
return " ".join(parts)
|
|
21
54
|
|
|
22
55
|
|
|
23
|
-
def
|
|
24
|
-
"""
|
|
56
|
+
def attrs(**kwargs: Optional[str]) -> str:
|
|
57
|
+
"""Build an HTML attribute string from keyword arguments.
|
|
25
58
|
|
|
26
59
|
Args:
|
|
27
|
-
|
|
60
|
+
**kwargs: Attribute name-value pairs (None values are skipped)
|
|
28
61
|
|
|
29
62
|
Returns:
|
|
30
|
-
|
|
63
|
+
Space-separated attribute string, each as name="value"
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
>>> attrs(type="text", placeholder="Enter name", disabled="")
|
|
67
|
+
'type="text" placeholder="Enter name" disabled=""'
|
|
68
|
+
"""
|
|
69
|
+
parts = []
|
|
70
|
+
for name, value in kwargs.items():
|
|
71
|
+
if value is not None:
|
|
72
|
+
attr_name = name.replace("_", "-")
|
|
73
|
+
parts.append(f'{attr_name}="{value}"')
|
|
74
|
+
result = " ".join(parts)
|
|
75
|
+
return f" {result}" if result else ""
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass
|
|
79
|
+
class HtmlElement:
|
|
80
|
+
"""Represents a rendered HTML element as a data structure.
|
|
81
|
+
|
|
82
|
+
This is the core building block for component rendering. Components
|
|
83
|
+
return HtmlElement instances from their render() method.
|
|
84
|
+
|
|
85
|
+
Attributes:
|
|
86
|
+
tag: HTML tag name (e.g. "div", "span", "button")
|
|
87
|
+
classes: List of CSS class names
|
|
88
|
+
attributes: Dictionary of HTML attributes
|
|
89
|
+
text: Text content (escaped automatically in render_html)
|
|
90
|
+
inner_html: Raw HTML content (NOT escaped, use carefully)
|
|
91
|
+
children: Nested child HtmlElement instances
|
|
92
|
+
|
|
93
|
+
Example:
|
|
94
|
+
>>> el = HtmlElement(
|
|
95
|
+
... tag="div",
|
|
96
|
+
... classes=["cn-card"],
|
|
97
|
+
... attributes={"data-id": "123"},
|
|
98
|
+
... text="Hello"
|
|
99
|
+
... )
|
|
100
|
+
>>> print(el.render_html())
|
|
101
|
+
<div class="cn-card" data-id="123">Hello</div>
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
tag: str
|
|
105
|
+
classes: List[str] = field(default_factory=list)
|
|
106
|
+
attributes: Dict[str, str] = field(default_factory=dict)
|
|
107
|
+
text: str = ""
|
|
108
|
+
inner_html: str = ""
|
|
109
|
+
children: List["HtmlElement"] = field(default_factory=list)
|
|
110
|
+
|
|
111
|
+
def render_html(self) -> str:
|
|
112
|
+
"""Render this element and all children as an HTML string.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Complete HTML string for this element tree
|
|
116
|
+
"""
|
|
117
|
+
class_str = " ".join(self.classes)
|
|
118
|
+
class_attr = f' class="{class_str}"' if class_str else ""
|
|
119
|
+
attrs_str = "".join(
|
|
120
|
+
f' {k}="{v}"' for k, v in self.attributes.items()
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
if self.inner_html:
|
|
124
|
+
content = self.inner_html
|
|
125
|
+
elif self.text:
|
|
126
|
+
content = escape_html(self.text)
|
|
127
|
+
elif self.children:
|
|
128
|
+
content = "".join(child.render_html() for child in self.children)
|
|
129
|
+
else:
|
|
130
|
+
return f"<{self.tag}{class_attr}{attrs_str} />"
|
|
131
|
+
|
|
132
|
+
return f"<{self.tag}{class_attr}{attrs_str}>{content}</{self.tag}>"
|
|
133
|
+
|
|
134
|
+
def render(self) -> "HtmlElement":
|
|
135
|
+
"""Return self (for API compatibility with components).
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
This HtmlElement instance
|
|
139
|
+
"""
|
|
140
|
+
return self
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@dataclass
|
|
144
|
+
class ComponentGroup:
|
|
145
|
+
"""Represents a group of components wrapped in a container.
|
|
146
|
+
|
|
147
|
+
Useful for rendering multiple components together.
|
|
148
|
+
|
|
149
|
+
Attributes:
|
|
150
|
+
tag: Container tag name (default: "div")
|
|
151
|
+
classes: CSS classes for the container
|
|
152
|
+
children: List of components or HtmlElements
|
|
153
|
+
|
|
154
|
+
Example:
|
|
155
|
+
>>> group = ComponentGroup(
|
|
156
|
+
... classes="cn-stack",
|
|
157
|
+
... children=[Button("A"), Button("B")]
|
|
158
|
+
... )
|
|
159
|
+
>>> print(group.render_html())
|
|
31
160
|
"""
|
|
32
|
-
return []
|
|
33
161
|
|
|
162
|
+
tag: str = "div"
|
|
163
|
+
classes: List[str] = field(default_factory=list)
|
|
164
|
+
attributes: Dict[str, str] = field(default_factory=dict)
|
|
165
|
+
children: List[Union[HtmlElement, "ComponentGroup"]] = field(
|
|
166
|
+
default_factory=list
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
def render_html(self) -> str:
|
|
170
|
+
"""Render all children as HTML inside the container.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
HTML string with container wrapping all children
|
|
174
|
+
"""
|
|
175
|
+
class_str = " ".join(self.classes)
|
|
176
|
+
class_attr = f' class="{class_str}"' if class_str else ""
|
|
177
|
+
attrs_str = "".join(
|
|
178
|
+
f' {k}="{v}"' for k, v in self.attributes.items()
|
|
179
|
+
)
|
|
180
|
+
children_html = "".join(
|
|
181
|
+
child.render_html()
|
|
182
|
+
if hasattr(child, "render_html")
|
|
183
|
+
else str(child)
|
|
184
|
+
for child in self.children
|
|
185
|
+
)
|
|
186
|
+
return f"<{self.tag}{class_attr}{attrs_str}>{children_html}</{self.tag}>"
|
|
187
|
+
|
|
188
|
+
def render(self) -> "ComponentGroup":
|
|
189
|
+
"""Return self (for API compatibility).
|
|
34
190
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
191
|
+
Returns:
|
|
192
|
+
This ComponentGroup instance
|
|
193
|
+
"""
|
|
194
|
+
return self
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def el(
|
|
198
|
+
tag: str,
|
|
199
|
+
class_name: Optional[str] = None,
|
|
200
|
+
attrs: Optional[Dict[str, str]] = None,
|
|
201
|
+
text: str = "",
|
|
202
|
+
inner_html: str = "",
|
|
203
|
+
children: Optional[List[HtmlElement]] = None,
|
|
204
|
+
) -> HtmlElement:
|
|
205
|
+
"""Create an HtmlElement with a convenient builder API.
|
|
206
|
+
|
|
207
|
+
This is the primary replacement for the old create_el() function.
|
|
208
|
+
Instead of returning DOM-like objects, it returns data structures
|
|
209
|
+
that can generate HTML strings.
|
|
39
210
|
|
|
40
211
|
Args:
|
|
41
212
|
tag: HTML tag name
|
|
42
|
-
class_name:
|
|
43
|
-
attrs:
|
|
213
|
+
class_name: Space-separated CSS class string (auto-split)
|
|
214
|
+
attrs: HTML attributes dictionary
|
|
215
|
+
text: Text content (will be escaped)
|
|
216
|
+
inner_html: Raw HTML content (not escaped)
|
|
217
|
+
children: List of child HtmlElement instances
|
|
44
218
|
|
|
45
219
|
Returns:
|
|
46
|
-
|
|
220
|
+
HtmlElement instance
|
|
221
|
+
|
|
222
|
+
Example:
|
|
223
|
+
>>> card = el("div", "cn-card", {"data-id": "1"})
|
|
224
|
+
>>> title = el("h3", "cn-card-title", text="My Card")
|
|
225
|
+
>>> card.children.append(title)
|
|
226
|
+
>>> print(card.render_html())
|
|
227
|
+
<div class="cn-card" data-id="1"><h3 class="cn-card-title">My Card</h3></div>
|
|
47
228
|
"""
|
|
48
|
-
|
|
229
|
+
classes_list = class_name.split() if class_name else []
|
|
230
|
+
return HtmlElement(
|
|
231
|
+
tag=tag,
|
|
232
|
+
classes=classes_list,
|
|
233
|
+
attributes=attrs or {},
|
|
234
|
+
text=text,
|
|
235
|
+
inner_html=inner_html,
|
|
236
|
+
children=children or [],
|
|
237
|
+
)
|