ourui 0.3.2__tar.gz → 0.3.3__tar.gz
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.
- {ourui-0.3.2 → ourui-0.3.3}/PKG-INFO +2 -2
- {ourui-0.3.2 → ourui-0.3.3}/README.md +1 -1
- {ourui-0.3.2 → ourui-0.3.3}/ourui/analysis/__init__.py +45 -1
- {ourui-0.3.2 → ourui-0.3.3}/ourui/emit/html.py +130 -11
- {ourui-0.3.2 → ourui-0.3.3}/ourui/lowering/layout.py +6 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/lowering/presentation.py +6 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/lowering/render.py +6 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/lsp/completions.py +1 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/node.py +7 -1
- {ourui-0.3.2 → ourui-0.3.3}/ourui/pipeline.py +1 -1
- {ourui-0.3.2 → ourui-0.3.3}/ourui.egg-info/PKG-INFO +2 -2
- {ourui-0.3.2 → ourui-0.3.3}/pyproject.toml +1 -1
- {ourui-0.3.2 → ourui-0.3.3}/LICENSE +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/__init__.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/analysis/components.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/cli.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/design/__init__.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/design/resolve.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/emit/__init__.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/emit/js.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/lowering/__init__.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/lowering/intent.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/lsp/__init__.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/lsp/protocol.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/lsp/server.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/parse/__init__.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/runtime/__init__.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/runtime/hmr.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/runtime/invoke.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/runtime/session.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/serialize/__init__.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/theme.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui/ui.py +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui.egg-info/SOURCES.txt +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui.egg-info/dependency_links.txt +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui.egg-info/entry_points.txt +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/ourui.egg-info/top_level.txt +0 -0
- {ourui-0.3.2 → ourui-0.3.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ourui
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Python-first UI compiler — write intent in Python, emit HTML/CSS/JS
|
|
5
5
|
Author: OurUI contributors
|
|
6
6
|
License: MIT License
|
|
@@ -46,7 +46,7 @@ Description-Content-Type: text/markdown
|
|
|
46
46
|
License-File: LICENSE
|
|
47
47
|
Dynamic: license-file
|
|
48
48
|
|
|
49
|
-
# ourui 0.3.
|
|
49
|
+
# ourui 0.3.3
|
|
50
50
|
|
|
51
51
|
Python package for the **OurUI** compiler and runtime.
|
|
52
52
|
|
|
@@ -10,7 +10,14 @@ from ourui.analysis.components import (
|
|
|
10
10
|
component_call_name,
|
|
11
11
|
expand_component_call,
|
|
12
12
|
)
|
|
13
|
-
from ourui.node import
|
|
13
|
+
from ourui.node import (
|
|
14
|
+
FORM_CONTROL_KINDS,
|
|
15
|
+
INPUT_TYPES,
|
|
16
|
+
NAV_PLACEMENTS,
|
|
17
|
+
NAV_TONES,
|
|
18
|
+
THEME_ATTR_KEYS,
|
|
19
|
+
Node,
|
|
20
|
+
)
|
|
14
21
|
from ourui.parse import call_kind, literal_value, parse_file, span_for
|
|
15
22
|
from ourui.theme import apply_theme_overrides, default_tokens, theme_kwargs_to_overrides
|
|
16
23
|
|
|
@@ -219,6 +226,39 @@ class _GraphBuilder:
|
|
|
219
226
|
if cid:
|
|
220
227
|
child_ids.append(cid)
|
|
221
228
|
continue
|
|
229
|
+
if kind == "Nav" and kw.arg == "brand" and isinstance(kw.value, ast.Call):
|
|
230
|
+
cid = self.build_call(kw.value, parent_id=nid, expansion_trail=trail)
|
|
231
|
+
if cid:
|
|
232
|
+
attrs["brand"] = cid
|
|
233
|
+
child_ids.append(cid)
|
|
234
|
+
continue
|
|
235
|
+
if kind == "Nav" and kw.arg in {"items", "actions"}:
|
|
236
|
+
slot_ids: list[str] = []
|
|
237
|
+
val_node = kw.value
|
|
238
|
+
if isinstance(val_node, (ast.List, ast.Tuple)):
|
|
239
|
+
for elt in val_node.elts:
|
|
240
|
+
if isinstance(elt, ast.Call):
|
|
241
|
+
cid = self.build_call(elt, parent_id=nid, expansion_trail=trail)
|
|
242
|
+
if cid:
|
|
243
|
+
slot_ids.append(cid)
|
|
244
|
+
child_ids.append(cid)
|
|
245
|
+
elif isinstance(val_node, ast.Call):
|
|
246
|
+
cid = self.build_call(val_node, parent_id=nid, expansion_trail=trail)
|
|
247
|
+
if cid:
|
|
248
|
+
slot_ids.append(cid)
|
|
249
|
+
child_ids.append(cid)
|
|
250
|
+
attrs[kw.arg] = slot_ids
|
|
251
|
+
continue
|
|
252
|
+
if kind == "Nav" and kw.arg == "placement":
|
|
253
|
+
place = literal_value(kw.value)
|
|
254
|
+
if isinstance(place, str):
|
|
255
|
+
attrs["placement"] = place if place in NAV_PLACEMENTS else "sticky-top"
|
|
256
|
+
continue
|
|
257
|
+
if kind == "Nav" and kw.arg == "tone":
|
|
258
|
+
tone = literal_value(kw.value)
|
|
259
|
+
if isinstance(tone, str):
|
|
260
|
+
attrs["tone"] = tone if tone in NAV_TONES else "solid"
|
|
261
|
+
continue
|
|
222
262
|
if kw.arg == "route" and kind == "Page":
|
|
223
263
|
route_val = literal_value(kw.value)
|
|
224
264
|
if isinstance(route_val, str):
|
|
@@ -255,6 +295,10 @@ class _GraphBuilder:
|
|
|
255
295
|
continue
|
|
256
296
|
attrs[kw.arg] = literal_value(kw.value)
|
|
257
297
|
|
|
298
|
+
if kind == "Nav":
|
|
299
|
+
attrs.setdefault("placement", "sticky-top")
|
|
300
|
+
attrs.setdefault("tone", "solid")
|
|
301
|
+
|
|
258
302
|
provenance = ["parse:ui_call", "analyze:semantic_graph", *[f"expand:{n}" for n in trail]]
|
|
259
303
|
node = Node(
|
|
260
304
|
id=nid,
|
|
@@ -13,6 +13,7 @@ _ROLE_TAG: dict[str, str] = {
|
|
|
13
13
|
"hero": "header",
|
|
14
14
|
"section": "section",
|
|
15
15
|
"shell": "div",
|
|
16
|
+
"nav": "nav",
|
|
16
17
|
"card": "div",
|
|
17
18
|
"grid": "div",
|
|
18
19
|
"text": "span",
|
|
@@ -158,10 +159,84 @@ input.ourui-slider {
|
|
|
158
159
|
max-width: 24rem;
|
|
159
160
|
accent-color: var(--ourui-primary);
|
|
160
161
|
}
|
|
162
|
+
.ourui-nav {
|
|
163
|
+
display: flex;
|
|
164
|
+
align-items: center;
|
|
165
|
+
gap: var(--ourui-space-md);
|
|
166
|
+
flex-wrap: wrap;
|
|
167
|
+
width: 100%;
|
|
168
|
+
box-sizing: border-box;
|
|
169
|
+
padding: var(--ourui-space-sm) var(--ourui-space-md);
|
|
170
|
+
z-index: 40;
|
|
171
|
+
}
|
|
172
|
+
.ourui-nav-brand {
|
|
173
|
+
display: flex;
|
|
174
|
+
align-items: center;
|
|
175
|
+
gap: var(--ourui-space-sm);
|
|
176
|
+
font-weight: 600;
|
|
177
|
+
}
|
|
178
|
+
.ourui-nav-items {
|
|
179
|
+
display: flex;
|
|
180
|
+
align-items: center;
|
|
181
|
+
gap: var(--ourui-space-md);
|
|
182
|
+
flex: 1 1 auto;
|
|
183
|
+
flex-wrap: wrap;
|
|
184
|
+
}
|
|
185
|
+
.ourui-nav-actions {
|
|
186
|
+
display: flex;
|
|
187
|
+
align-items: center;
|
|
188
|
+
gap: var(--ourui-space-sm);
|
|
189
|
+
margin-inline-start: auto;
|
|
190
|
+
}
|
|
191
|
+
.ourui-nav-solid {
|
|
192
|
+
background: var(--ourui-card);
|
|
193
|
+
color: var(--ourui-card-fg);
|
|
194
|
+
border-bottom: 1px solid var(--ourui-border);
|
|
195
|
+
}
|
|
196
|
+
.ourui-nav-glass {
|
|
197
|
+
background: color-mix(in srgb, var(--ourui-card) 72%, transparent);
|
|
198
|
+
color: var(--ourui-card-fg);
|
|
199
|
+
border-bottom: 1px solid var(--ourui-border);
|
|
200
|
+
backdrop-filter: blur(10px);
|
|
201
|
+
-webkit-backdrop-filter: blur(10px);
|
|
202
|
+
}
|
|
203
|
+
.ourui-nav-sticky-top {
|
|
204
|
+
position: sticky;
|
|
205
|
+
top: 0;
|
|
206
|
+
}
|
|
207
|
+
.ourui-nav-fixed-top {
|
|
208
|
+
position: fixed;
|
|
209
|
+
inset-inline: 0;
|
|
210
|
+
top: 0;
|
|
211
|
+
}
|
|
212
|
+
.ourui-nav-fixed-bottom {
|
|
213
|
+
position: fixed;
|
|
214
|
+
inset-inline: 0;
|
|
215
|
+
bottom: 0;
|
|
216
|
+
border-bottom: none;
|
|
217
|
+
border-top: 1px solid var(--ourui-border);
|
|
218
|
+
}
|
|
219
|
+
.ourui-nav-flow {
|
|
220
|
+
position: static;
|
|
221
|
+
}
|
|
222
|
+
.ourui-nav-overlay {
|
|
223
|
+
position: absolute;
|
|
224
|
+
inset-inline: 0;
|
|
225
|
+
top: 0;
|
|
226
|
+
}
|
|
227
|
+
.ourui-nav-backdrop {
|
|
228
|
+
position: absolute;
|
|
229
|
+
inset: 0;
|
|
230
|
+
z-index: 0;
|
|
231
|
+
pointer-events: none;
|
|
232
|
+
}
|
|
233
|
+
.ourui-root:has(.ourui-nav-fixed-top) {
|
|
234
|
+
padding-top: 3.75rem;
|
|
235
|
+
}
|
|
161
236
|
"""
|
|
162
237
|
# Tone classes above use CSS vars seeded from Resolved Design (Host Contract).
|
|
163
238
|
# Per-node rules from Resolved Design override for concrete fill/fg/radius/pad.
|
|
164
|
-
# Form control chrome is host-private layout — not Design System.
|
|
239
|
+
# Form control + Nav chrome is host-private layout — not Design System.
|
|
165
240
|
|
|
166
241
|
def _as_resolved_design(resolved_design: Any) -> dict[str, Any] | None:
|
|
167
242
|
if resolved_design is None:
|
|
@@ -247,16 +322,17 @@ def _classes_for(node: dict[str, Any]) -> list[str]:
|
|
|
247
322
|
shell = attrs.get("shell_layout")
|
|
248
323
|
role = attrs.get("role", "")
|
|
249
324
|
classes: list[str] = []
|
|
250
|
-
if
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
325
|
+
if role != "nav":
|
|
326
|
+
if shell == "split-3":
|
|
327
|
+
classes.append("ourui-shell-split-3")
|
|
328
|
+
elif shell == "stack":
|
|
329
|
+
classes.append("ourui-shell-stack")
|
|
330
|
+
elif layout == "vertical":
|
|
331
|
+
classes.append("ourui-col")
|
|
332
|
+
elif layout == "horizontal":
|
|
333
|
+
classes.append("ourui-row")
|
|
334
|
+
elif layout == "grid":
|
|
335
|
+
classes.append("ourui-grid")
|
|
260
336
|
if role == "card":
|
|
261
337
|
classes.append("ourui-card")
|
|
262
338
|
if role == "link":
|
|
@@ -277,6 +353,12 @@ def _classes_for(node: dict[str, Any]) -> list[str]:
|
|
|
277
353
|
classes.append("ourui-toggle")
|
|
278
354
|
if role == "slider":
|
|
279
355
|
classes.append("ourui-slider")
|
|
356
|
+
if role == "nav":
|
|
357
|
+
classes.append("ourui-nav")
|
|
358
|
+
placement = attrs.get("placement") or "sticky-top"
|
|
359
|
+
tone = attrs.get("tone") or "solid"
|
|
360
|
+
classes.append(f"ourui-nav-{placement}")
|
|
361
|
+
classes.append(f"ourui-nav-{tone}")
|
|
280
362
|
if (
|
|
281
363
|
node["kind"] == "Leaf"
|
|
282
364
|
and "ourui-control" not in classes
|
|
@@ -285,6 +367,7 @@ def _classes_for(node: dict[str, Any]) -> list[str]:
|
|
|
285
367
|
and "ourui-select" not in classes
|
|
286
368
|
and "ourui-toggle" not in classes
|
|
287
369
|
and "ourui-slider" not in classes
|
|
370
|
+
and "ourui-nav" not in classes
|
|
288
371
|
):
|
|
289
372
|
classes.append("ourui-leaf")
|
|
290
373
|
return classes
|
|
@@ -454,6 +537,42 @@ def _render_node(nid: str, nodes: dict[str, dict[str, Any]], indent: int) -> lis
|
|
|
454
537
|
attrs = f"{class_attr}{data_role}{data_id}{field}{events}"
|
|
455
538
|
return _wrap_field(pad, node_attrs.get("label"), [f"<input{attrs} />"])
|
|
456
539
|
|
|
540
|
+
if role == "nav":
|
|
541
|
+
attrs = f"{class_attr}{data_role}{data_id}{events}"
|
|
542
|
+
brand = node_attrs.get("brand")
|
|
543
|
+
items = node_attrs.get("items") if isinstance(node_attrs.get("items"), list) else []
|
|
544
|
+
actions = node_attrs.get("actions") if isinstance(node_attrs.get("actions"), list) else []
|
|
545
|
+
slotted = set()
|
|
546
|
+
if isinstance(brand, str):
|
|
547
|
+
slotted.add(brand)
|
|
548
|
+
slotted.update(i for i in items if isinstance(i, str))
|
|
549
|
+
slotted.update(a for a in actions if isinstance(a, str))
|
|
550
|
+
|
|
551
|
+
def _slot(title: str, ids: list[str]) -> list[str]:
|
|
552
|
+
if not ids:
|
|
553
|
+
return []
|
|
554
|
+
out = [f'{pad} <div class="ourui-nav-{title}">']
|
|
555
|
+
for cid in ids:
|
|
556
|
+
if cid in nodes:
|
|
557
|
+
out.extend(_render_node(cid, nodes, indent + 2))
|
|
558
|
+
out.append(f"{pad} </div>")
|
|
559
|
+
return out
|
|
560
|
+
|
|
561
|
+
lines = [f"{pad}<nav{attrs}>"]
|
|
562
|
+
if isinstance(brand, str) and brand in nodes:
|
|
563
|
+
lines.append(f'{pad} <div class="ourui-nav-brand">')
|
|
564
|
+
lines.extend(_render_node(brand, nodes, indent + 2))
|
|
565
|
+
lines.append(f"{pad} </div>")
|
|
566
|
+
lines.extend(_slot("items", [i for i in items if isinstance(i, str)]))
|
|
567
|
+
lines.extend(_slot("actions", [a for a in actions if isinstance(a, str)]))
|
|
568
|
+
# Positional children not assigned to slots
|
|
569
|
+
for child_id in node.get("children", []):
|
|
570
|
+
if child_id in slotted or child_id not in nodes:
|
|
571
|
+
continue
|
|
572
|
+
lines.extend(_render_node(child_id, nodes, indent + 1))
|
|
573
|
+
lines.append(f"{pad}</nav>")
|
|
574
|
+
return lines
|
|
575
|
+
|
|
457
576
|
children = node.get("children", [])
|
|
458
577
|
attrs = f"{class_attr}{data_role}{data_id}{link}{events}"
|
|
459
578
|
|
|
@@ -11,6 +11,7 @@ _LAYOUT_KIND: dict[str, str] = {
|
|
|
11
11
|
"Hero": "Column",
|
|
12
12
|
"Section": "Column",
|
|
13
13
|
"Shell": "Row",
|
|
14
|
+
"Nav": "Row",
|
|
14
15
|
"Grid": "Grid",
|
|
15
16
|
"Card": "Box",
|
|
16
17
|
"Button": "Box",
|
|
@@ -56,6 +57,11 @@ _PASSTHROUGH_PROPS = (
|
|
|
56
57
|
"min",
|
|
57
58
|
"max",
|
|
58
59
|
"step",
|
|
60
|
+
"placement",
|
|
61
|
+
"tone",
|
|
62
|
+
"brand",
|
|
63
|
+
"items",
|
|
64
|
+
"actions",
|
|
59
65
|
)
|
|
60
66
|
|
|
61
67
|
|
|
@@ -12,6 +12,7 @@ _PRESENTATION_KINDS = frozenset(
|
|
|
12
12
|
"Hero",
|
|
13
13
|
"Section",
|
|
14
14
|
"Shell",
|
|
15
|
+
"Nav",
|
|
15
16
|
"Button",
|
|
16
17
|
"Text",
|
|
17
18
|
"Card",
|
|
@@ -42,6 +43,11 @@ _PASSTHROUGH = (
|
|
|
42
43
|
"min",
|
|
43
44
|
"max",
|
|
44
45
|
"step",
|
|
46
|
+
"placement",
|
|
47
|
+
"tone",
|
|
48
|
+
"brand",
|
|
49
|
+
"items",
|
|
50
|
+
"actions",
|
|
45
51
|
)
|
|
46
52
|
|
|
47
53
|
|
|
@@ -83,6 +83,11 @@ def lower_to_rtr(ltr: Any) -> RTR:
|
|
|
83
83
|
"min",
|
|
84
84
|
"max",
|
|
85
85
|
"step",
|
|
86
|
+
"placement",
|
|
87
|
+
"tone",
|
|
88
|
+
"brand",
|
|
89
|
+
"items",
|
|
90
|
+
"actions",
|
|
86
91
|
):
|
|
87
92
|
if key in attrs:
|
|
88
93
|
props[key] = attrs[key]
|
|
@@ -149,6 +154,7 @@ def _role_for(from_intent: str) -> str:
|
|
|
149
154
|
"Hero": "hero",
|
|
150
155
|
"Section": "section",
|
|
151
156
|
"Shell": "shell",
|
|
157
|
+
"Nav": "nav",
|
|
152
158
|
"Button": "button",
|
|
153
159
|
"Card": "card",
|
|
154
160
|
"Text": "text",
|
|
@@ -21,6 +21,7 @@ UI_COMPONENTS: dict[str, str] = {
|
|
|
21
21
|
"Grid": "Layout grid container.",
|
|
22
22
|
"Link": "Presentation domain navigation anchor (href).",
|
|
23
23
|
"Shell": "Intent domain layout region (layout=stack|row|split-3|grid).",
|
|
24
|
+
"Nav": "Chrome bar; placement= + tone=solid|glass; brand/items/actions slots.",
|
|
24
25
|
"Theme": "Design token overrides for --ourui-* CSS variables.",
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -60,7 +60,7 @@ class Node:
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
INTENT_KINDS = frozenset({"Page", "Hero", "Section", "Shell"})
|
|
63
|
+
INTENT_KINDS = frozenset({"Page", "Hero", "Section", "Shell", "Nav"})
|
|
64
64
|
PRESENTATION_KINDS = frozenset(
|
|
65
65
|
{"Button", "Text", "Card", "Grid", "Link", "Input", "Select", "Toggle", "Slider"}
|
|
66
66
|
)
|
|
@@ -75,4 +75,10 @@ FORM_CONTROL_KINDS = frozenset({"Input", "Select", "Toggle", "Slider"})
|
|
|
75
75
|
# Input type= enum (S2)
|
|
76
76
|
INPUT_TYPES = frozenset({"text", "email", "password", "number", "search", "url", "tel"})
|
|
77
77
|
|
|
78
|
+
# Nav chrome (S3a)
|
|
79
|
+
NAV_PLACEMENTS = frozenset(
|
|
80
|
+
{"flow", "sticky-top", "fixed-top", "fixed-bottom", "overlay", "backdrop"}
|
|
81
|
+
)
|
|
82
|
+
NAV_TONES = frozenset({"solid", "glass"})
|
|
83
|
+
|
|
78
84
|
THEME_ATTR_KEYS = frozenset({"variant", "color", "bg", "theme"})
|
|
@@ -53,7 +53,7 @@ def compile_dump(path: str | Path) -> dict[str, Any]:
|
|
|
53
53
|
path = Path(path)
|
|
54
54
|
artifacts = compile_to_rtr(path)
|
|
55
55
|
return {
|
|
56
|
-
"version":
|
|
56
|
+
"version": 15,
|
|
57
57
|
"source": artifacts["source"],
|
|
58
58
|
"semantic_graph": artifacts["semantic_graph"].to_dict(),
|
|
59
59
|
"dependency_graph": artifacts["dependency_graph"].to_dict(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ourui
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Python-first UI compiler — write intent in Python, emit HTML/CSS/JS
|
|
5
5
|
Author: OurUI contributors
|
|
6
6
|
License: MIT License
|
|
@@ -46,7 +46,7 @@ Description-Content-Type: text/markdown
|
|
|
46
46
|
License-File: LICENSE
|
|
47
47
|
Dynamic: license-file
|
|
48
48
|
|
|
49
|
-
# ourui 0.3.
|
|
49
|
+
# ourui 0.3.3
|
|
50
50
|
|
|
51
51
|
Python package for the **OurUI** compiler and runtime.
|
|
52
52
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|