creo 0.2.0 → 0.2.1
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/LICENSE +21 -0
- package/README.md +114 -40
- package/dist/index.d.ts +1 -1
- package/dist/index.js +340 -317
- package/dist/index.js.map +8 -8
- package/dist/internal/engine.d.ts +4 -4
- package/dist/internal/internal_view.d.ts +3 -3
- package/dist/public/primitives/primitives.d.ts +2 -1
- package/dist/public/view.d.ts +10 -3
- package/package.json +3 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nik Mostovoy (xnim.me)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,31 +1,48 @@
|
|
|
1
|
-
# Creo
|
|
1
|
+
# Creo: Lightweight UI framework
|
|
2
2
|
|
|
3
|
-
> _"There
|
|
3
|
+
> _"There are many UI framework but this one is mine!"_
|
|
4
4
|
|
|
5
|
-
-
|
|
6
|
-
- No JSX
|
|
5
|
+
- Lightweight, "Streaming" UI framework.
|
|
6
|
+
- No JSX / templates / compiler
|
|
7
7
|
- Simplicity over tons of features
|
|
8
|
+
- Easy to start, easy to work with
|
|
9
|
+
- Extendability by defining renderers
|
|
8
10
|
|
|
9
11
|
## Philosophy
|
|
10
12
|
|
|
11
13
|
### Streaming the UI
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
> _"There is a point of no return"_
|
|
16
|
+
|
|
17
|
+
Most frameworks are based on "returning" the data. Creo started back in (early 2025)[https://x.com/xnimorz/status/1876212381568905348] with the idea, that "return" is not the point. We can intersect the components during rendering cycle to handle it.
|
|
18
|
+
|
|
19
|
+
It comes with some limitations, yes, like using VirtualDOM, instead of compiling it all and putting just renderer instructions but I believe VDOM is not the weakest point of modern software engineering.
|
|
20
|
+
|
|
21
|
+
The weakest point is complexity. Every time I looked at "framework A/B/C" I always find myself struggling with remembering all "you should do X/Y/Z in order to make it work".
|
|
22
|
+
|
|
23
|
+
And look.. I get it, it's important to follow the rules (e.g. I remember early svelte they experience problems with props, where incorrect usage de-optimised perfromance a lot). But after getting to the point where "a little bit too much" of the rules, I experience mental overload.
|
|
24
|
+
|
|
25
|
+
This is why I want to have a framework which I enjoy using on daily basis. And one major thing I don't like is "too many DSLs" to remember.
|
|
26
|
+
|
|
27
|
+
So... Why not just to use JAVASCRIPT?
|
|
14
28
|
|
|
15
29
|
```ts
|
|
16
30
|
render() {
|
|
17
|
-
h1(
|
|
18
|
-
p(
|
|
19
|
-
ul(
|
|
20
|
-
li(
|
|
21
|
-
li(
|
|
31
|
+
h1(_, "Title"); // first child
|
|
32
|
+
p(_, "Paragraph"); // second child
|
|
33
|
+
ul(_, () => { // third child, with its own children streamed inside
|
|
34
|
+
li(_, "One");
|
|
35
|
+
li(_, "Two");
|
|
22
36
|
});
|
|
23
37
|
}
|
|
24
38
|
```
|
|
25
39
|
|
|
26
40
|
### Native control flow
|
|
27
41
|
|
|
28
|
-
No `v-if`, no `{condition && <X/>}`, no `.map()` wrappers.
|
|
42
|
+
No `v-if`, no `{condition && <X/>}`, no `.map()` wrappers.
|
|
43
|
+
Creo renders imperatively: use `if`, `for`, `while`, `switch`, or any JavaScript you want.
|
|
44
|
+
|
|
45
|
+
**The language is the template language on its own**:
|
|
29
46
|
|
|
30
47
|
```ts
|
|
31
48
|
render() {
|
|
@@ -41,30 +58,21 @@ render() {
|
|
|
41
58
|
}
|
|
42
59
|
```
|
|
43
60
|
|
|
44
|
-
|
|
61
|
+
It reduces mental load. We don't require people to learn:
|
|
45
62
|
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
63
|
+
- Any specific templating syntax
|
|
64
|
+
- Framework-specific iteration helpers.
|
|
65
|
+
- Ternary gymnastics.
|
|
49
66
|
|
|
50
67
|
### Minimal model
|
|
51
68
|
|
|
52
69
|
The entire reactivity model is three concepts:
|
|
53
70
|
|
|
54
|
-
- **`use(value)
|
|
55
|
-
- **`store.new(value)
|
|
56
|
-
- **`props()
|
|
57
|
-
|
|
58
|
-
No:
|
|
59
|
-
|
|
60
|
-
- Computed properties
|
|
61
|
-
- Watchers
|
|
62
|
-
- Dependency arrays
|
|
63
|
-
- Selectors
|
|
64
|
-
|
|
65
|
-
State is explicit: you set it, you read it, you control when things update via `shouldUpdate`.
|
|
71
|
+
- **`use(value)`**: local state. Call `.get()`, `.set()`, `.update()`;
|
|
72
|
+
- **`store.new(value)`**: global store. Same interface. Any view can subscribe with `use(store)`, same to state mechanics. Library takes a shot to manage subscriptions;
|
|
73
|
+
- **`props()`**: read-only, passed by parent;
|
|
66
74
|
|
|
67
|
-
One of major ideas under the framework "if user can do it with same efficiency, let it outside framework zone"
|
|
75
|
+
One of major ideas under the framework "if user can do it with same efficiency, let it outside framework zone". I want to keep the framework efficient, but with super limited API blast radius.
|
|
68
76
|
|
|
69
77
|
### Pluggable renderers
|
|
70
78
|
|
|
@@ -72,7 +80,7 @@ Creo allows any renderer overrides.
|
|
|
72
80
|
|
|
73
81
|
- **`HtmlRender`** — DOM output for browsers
|
|
74
82
|
- **`JsonRender`** — JSON AST for testing and serialization
|
|
75
|
-
- **`
|
|
83
|
+
- **`HtmlStringRenderer`** — HTML strings for SSR
|
|
76
84
|
|
|
77
85
|
```ts
|
|
78
86
|
// Browser
|
|
@@ -89,7 +97,7 @@ return renderer.renderToString();
|
|
|
89
97
|
## Quick Start
|
|
90
98
|
|
|
91
99
|
```ts
|
|
92
|
-
import { createApp, view, div, text, button } from "creo";
|
|
100
|
+
import { createApp, view, div, text, button, _ } from "creo";
|
|
93
101
|
import { HtmlRender } from "creo";
|
|
94
102
|
|
|
95
103
|
const Counter = view<{ initial: number }>(({ props, use }) => {
|
|
@@ -120,9 +128,7 @@ Views are components. Define them with `view<Props>()`, which takes a setup func
|
|
|
120
128
|
```ts
|
|
121
129
|
const Greeting = view<{ name: string }>(({ props }) => ({
|
|
122
130
|
render() {
|
|
123
|
-
div({ class: "greeting" }, ()
|
|
124
|
-
text(`Hello, ${props().name}!`);
|
|
125
|
-
});
|
|
131
|
+
div({ class: "greeting" }, `Hello, ${props().name}!`);
|
|
126
132
|
},
|
|
127
133
|
}));
|
|
128
134
|
|
|
@@ -180,7 +186,7 @@ Pass children via a slot callback — the second argument to any view or primiti
|
|
|
180
186
|
const Card = view<{ title: string }>(({ props, slot }) => ({
|
|
181
187
|
render() {
|
|
182
188
|
div({ class: "card" }, () => {
|
|
183
|
-
h1(
|
|
189
|
+
h1(_, () => text(props().title));
|
|
184
190
|
div({ class: "card-body" }, slot);
|
|
185
191
|
});
|
|
186
192
|
},
|
|
@@ -188,7 +194,7 @@ const Card = view<{ title: string }>(({ props, slot }) => ({
|
|
|
188
194
|
|
|
189
195
|
// Usage:
|
|
190
196
|
Card({ title: "Hello" }, () => {
|
|
191
|
-
p(
|
|
197
|
+
p(_, "Card content here.");
|
|
192
198
|
});
|
|
193
199
|
```
|
|
194
200
|
|
|
@@ -238,6 +244,66 @@ render() {
|
|
|
238
244
|
}
|
|
239
245
|
```
|
|
240
246
|
|
|
247
|
+
## Conventions
|
|
248
|
+
|
|
249
|
+
### `_` for Empty Props
|
|
250
|
+
|
|
251
|
+
Use `_` (exported from `creo`) instead of `{}` when no props are needed:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
h1(_, "Title"); // not h1({}, "Title")
|
|
255
|
+
div(_, () => { ... }); // not div({}, () => { ... })
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Inline Strings
|
|
259
|
+
|
|
260
|
+
Pass strings directly as slots instead of wrapping in `() => text(...)`:
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
button({ onClick: handler }, "Click me"); // not () => text("Click me")
|
|
264
|
+
li(_, "Item text"); // not () => text("Item text")
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Use `text()` only for dynamic values or when mixing text with other elements in a function slot.
|
|
268
|
+
|
|
269
|
+
## Create App
|
|
270
|
+
|
|
271
|
+
Scaffold a new Creo project with one command:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
bunx creo-create-app my-app
|
|
275
|
+
cd my-app
|
|
276
|
+
bun install
|
|
277
|
+
bun run dev
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
The CLI prompts whether to include a **Hono server**. When enabled, the generated project includes:
|
|
281
|
+
|
|
282
|
+
- A Hono backend (`src/server.ts`) serving static files from `dist/` by default
|
|
283
|
+
- Vite dev server with `/api` proxy to Hono
|
|
284
|
+
- Scripts for both dev (`dev:server` + `dev`) and production (`build` + `start`)
|
|
285
|
+
|
|
286
|
+
Without a server, you get a pure client-side Vite + Creo setup.
|
|
287
|
+
|
|
288
|
+
See [`packages/creo-create-app/`](./packages/creo-create-app/) for full details.
|
|
289
|
+
|
|
290
|
+
## Create Tauri App
|
|
291
|
+
|
|
292
|
+
Build cross-platform desktop and mobile apps with Creo + Tauri v2:
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
bunx creo-create-tauri-app my-app
|
|
296
|
+
cd my-app
|
|
297
|
+
bun install
|
|
298
|
+
bun run tauri:dev
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
The CLI lets you select target platforms: **macOS**, **Windows**, **Linux**, **iOS**, **Android**, and **Web**. Desktop targets work immediately; mobile targets require a one-time `tauri ios init` / `tauri android init` after scaffolding.
|
|
302
|
+
|
|
303
|
+
The generated project includes a full Tauri v2 setup (`src-tauri/`) with Rust backend, Vite frontend, and a sample Tauri command.
|
|
304
|
+
|
|
305
|
+
See [`packages/creo-create-tauri-app/`](./packages/creo-create-tauri-app/) for full details.
|
|
306
|
+
|
|
241
307
|
## Router
|
|
242
308
|
|
|
243
309
|
Hash-based router available as `creo-router` (separate package):
|
|
@@ -254,7 +320,7 @@ const { routeStore, navigate, RouterView, Link } = createRouter({
|
|
|
254
320
|
});
|
|
255
321
|
|
|
256
322
|
// Navigation:
|
|
257
|
-
Link({ href: "/users/42" },
|
|
323
|
+
Link({ href: "/users/42" }, "User 42");
|
|
258
324
|
navigate("/users/42"); // programmatic
|
|
259
325
|
|
|
260
326
|
// Read params:
|
|
@@ -266,11 +332,19 @@ route.get().params.id; // "42"
|
|
|
266
332
|
|
|
267
333
|
```bash
|
|
268
334
|
bun install
|
|
269
|
-
bun test src/
|
|
270
|
-
bun
|
|
271
|
-
bun run
|
|
335
|
+
bun test packages/creo/src/ # Run tests
|
|
336
|
+
bun run build # Build all packages
|
|
337
|
+
bun run typecheck # Type-check
|
|
272
338
|
|
|
273
339
|
# Run examples:
|
|
274
340
|
cd examples/todo && bun install && bun run dev
|
|
275
341
|
cd examples/router && bun install && bun run dev
|
|
276
|
-
|
|
342
|
+
|
|
343
|
+
# Version management:
|
|
344
|
+
bun run version:patch # Bump patch version across all packages
|
|
345
|
+
bun run version:minor # Bump minor version
|
|
346
|
+
bun run version:major # Bump major version
|
|
347
|
+
|
|
348
|
+
# Publishing:
|
|
349
|
+
bun run publish:all # Dry-run publish (pass --no-dry-run to publish for real)
|
|
350
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createApp } from "./public/app";
|
|
2
2
|
export { view } from "./public/view";
|
|
3
|
-
export type { ViewBody, ViewFn, Slot, PublicView } from "./public/view";
|
|
3
|
+
export type { ViewBody, ViewFn, Slot, SlotContent, PublicView } from "./public/view";
|
|
4
4
|
export type { Reactive, Use } from "./public/state";
|
|
5
5
|
export { State } from "./public/state";
|
|
6
6
|
export { Store, store, isStore } from "./public/store";
|