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.
Files changed (76) hide show
  1. package/README.md +1 -1
  2. package/package.json +71 -71
  3. package/packages/flutter/.qwen/settings.json +7 -0
  4. package/packages/flutter/pubspec.yaml +20 -20
  5. package/packages/go/cronixui/cronixui.go +926 -926
  6. package/packages/python/README.md +142 -0
  7. package/packages/python/cronixui/__init__.py +15 -6
  8. package/packages/python/cronixui/__pycache__/__init__.cpython-314.pyc +0 -0
  9. package/packages/python/cronixui/__pycache__/accordion.cpython-314.pyc +0 -0
  10. package/packages/python/cronixui/__pycache__/alert.cpython-314.pyc +0 -0
  11. package/packages/python/cronixui/__pycache__/avatar.cpython-314.pyc +0 -0
  12. package/packages/python/cronixui/__pycache__/badge.cpython-314.pyc +0 -0
  13. package/packages/python/cronixui/__pycache__/button.cpython-314.pyc +0 -0
  14. package/packages/python/cronixui/__pycache__/card.cpython-314.pyc +0 -0
  15. package/packages/python/cronixui/__pycache__/command_palette.cpython-314.pyc +0 -0
  16. package/packages/python/cronixui/__pycache__/core.cpython-314.pyc +0 -0
  17. package/packages/python/cronixui/__pycache__/dropdown.cpython-314.pyc +0 -0
  18. package/packages/python/cronixui/__pycache__/form.cpython-314.pyc +0 -0
  19. package/packages/python/cronixui/__pycache__/layout.cpython-314.pyc +0 -0
  20. package/packages/python/cronixui/__pycache__/list.cpython-314.pyc +0 -0
  21. package/packages/python/cronixui/__pycache__/loading.cpython-314.pyc +0 -0
  22. package/packages/python/cronixui/__pycache__/modal.cpython-314.pyc +0 -0
  23. package/packages/python/cronixui/__pycache__/nav.cpython-314.pyc +0 -0
  24. package/packages/python/cronixui/__pycache__/pagination.cpython-314.pyc +0 -0
  25. package/packages/python/cronixui/__pycache__/progress.cpython-314.pyc +0 -0
  26. package/packages/python/cronixui/__pycache__/search.cpython-314.pyc +0 -0
  27. package/packages/python/cronixui/__pycache__/table.cpython-314.pyc +0 -0
  28. package/packages/python/cronixui/__pycache__/tabs.cpython-314.pyc +0 -0
  29. package/packages/python/cronixui/__pycache__/toast.cpython-314.pyc +0 -0
  30. package/packages/python/cronixui/__pycache__/toggle.cpython-314.pyc +0 -0
  31. package/packages/python/cronixui/__pycache__/tokens.cpython-314.pyc +0 -0
  32. package/packages/python/cronixui/__pycache__/tooltip.cpython-314.pyc +0 -0
  33. package/packages/python/cronixui/alert.py +119 -36
  34. package/packages/python/cronixui/avatar.py +129 -22
  35. package/packages/python/cronixui/badge.py +161 -24
  36. package/packages/python/cronixui/button.py +96 -27
  37. package/packages/python/cronixui/card.py +206 -33
  38. package/packages/python/cronixui/core.py +212 -23
  39. package/packages/python/cronixui/form.py +552 -141
  40. package/packages/python/cronixui/layout.py +358 -96
  41. package/packages/python/cronixui/list.py +140 -37
  42. package/packages/python/cronixui/loading.py +107 -17
  43. package/packages/python/cronixui/progress.py +189 -47
  44. package/packages/python/cronixui/table.py +118 -31
  45. package/packages/python/cronixui/tooltip.py +117 -15
  46. package/packages/react/src/components/Accordion.tsx +82 -82
  47. package/packages/react/src/components/Button.tsx +47 -47
  48. package/packages/react/src/components/Card.tsx +69 -69
  49. package/packages/react/src/components/CommandPalette.tsx +131 -131
  50. package/packages/react/src/components/Dropdown.tsx +88 -88
  51. package/packages/react/src/components/FileInput.tsx +86 -86
  52. package/packages/react/src/components/FormGroup.tsx +36 -36
  53. package/packages/react/src/components/List.tsx +55 -55
  54. package/packages/react/src/components/Pagination.tsx +107 -107
  55. package/packages/react/src/components/Progress.tsx +49 -49
  56. package/packages/react/src/components/Search.tsx +95 -95
  57. package/packages/react/src/components/Sidebar.tsx +64 -64
  58. package/packages/react/src/components/Stack.tsx +69 -69
  59. package/packages/react/src/components/Table.tsx +90 -90
  60. package/packages/react/src/components/Toast.tsx +134 -134
  61. package/packages/react/src/components/Typography.tsx +66 -66
  62. package/packages/react/src/index.ts +40 -40
  63. package/packages/react/src/styles.css +2039 -2039
  64. package/packages/rust/cronixui/src/components/avatar.rs +85 -85
  65. package/packages/rust/cronixui/src/components/breadcrumb.rs +58 -58
  66. package/packages/rust/cronixui/src/components/card.rs +259 -259
  67. package/packages/rust/cronixui/src/components/command_palette.rs +254 -254
  68. package/packages/rust/cronixui/src/components/dropdown.rs +179 -179
  69. package/packages/rust/cronixui/src/components/file_input.rs +74 -74
  70. package/packages/rust/cronixui/src/components/mod.rs +51 -51
  71. package/packages/rust/cronixui/src/components/search.rs +185 -185
  72. package/packages/rust/cronixui/src/components/skeleton.rs +63 -63
  73. package/packages/rust/cronixui/src/components/table.rs +56 -56
  74. package/packages/rust/cronixui/src/lib.rs +128 -128
  75. package/packages/web/dist/cronixui.css +97 -93
  76. 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
- from typing import Dict, Optional, List, Any
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
- def init() -> None:
7
- """Initialize all CronixUI components."""
8
- pass
9
+ from dataclasses import dataclass, field
10
+ from typing import Dict, List, Optional, Union
9
11
 
10
12
 
11
- def query(selector: str) -> Optional[Any]:
12
- """Query single element.
13
+ def escape_html(text: str) -> str:
14
+ """Escape HTML special characters in text.
13
15
 
14
16
  Args:
15
- selector: CSS selector
17
+ text: Raw text that may contain HTML special characters
16
18
 
17
19
  Returns:
18
- Element or None
20
+ Text with HTML special characters escaped
21
+
22
+ Example:
23
+ >>> escape_html("<script>alert('xss')</script>")
24
+ '&lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;'
25
+ """
26
+ return (
27
+ text.replace("&", "&amp;")
28
+ .replace("<", "&lt;")
29
+ .replace(">", "&gt;")
30
+ .replace('"', "&quot;")
31
+ .replace("'", "&#x27;")
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
- pass
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 query_all(selector: str) -> List[Any]:
24
- """Query all matching elements.
56
+ def attrs(**kwargs: Optional[str]) -> str:
57
+ """Build an HTML attribute string from keyword arguments.
25
58
 
26
59
  Args:
27
- selector: CSS selector
60
+ **kwargs: Attribute name-value pairs (None values are skipped)
28
61
 
29
62
  Returns:
30
- List of elements
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
- def create_el(
36
- tag: str, class_name: Optional[str] = None, attrs: Optional[Dict[str, str]] = None
37
- ) -> Any:
38
- """Create an element.
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: Optional CSS class name
43
- attrs: Optional attributes dict
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
- Created element
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
- pass
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
+ )