creo 0.0.4-dev → 0.2.0

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 (71) hide show
  1. package/README.md +276 -1
  2. package/dist/functional/assert.d.ts +1 -0
  3. package/dist/functional/key.d.ts +2 -0
  4. package/dist/functional/lis.d.ts +11 -0
  5. package/dist/functional/maybe.d.ts +8 -0
  6. package/dist/functional/maybe_promise.d.ts +1 -0
  7. package/dist/functional/shallow_equal.d.ts +2 -0
  8. package/dist/index.d.ts +20 -0
  9. package/dist/index.js +1357 -0
  10. package/dist/index.js.map +25 -0
  11. package/dist/internal/engine.d.ts +24 -0
  12. package/dist/internal/internal_view.d.ts +29 -0
  13. package/dist/internal/orchestrator.d.ts +16 -0
  14. package/dist/public/app.d.ts +19 -0
  15. package/dist/public/event_handle.d.ts +32 -0
  16. package/dist/public/primitive.d.ts +20 -0
  17. package/dist/public/primitives/primitives.d.ts +318 -0
  18. package/dist/public/state.d.ts +37 -0
  19. package/dist/public/store.d.ts +35 -0
  20. package/dist/public/view.d.ts +33 -0
  21. package/dist/render/canvas_render.d.ts +1 -0
  22. package/dist/render/html_render.d.ts +22 -0
  23. package/dist/render/json_render.d.ts +19 -0
  24. package/dist/render/render_interface.d.ts +9 -0
  25. package/dist/render/stream_render.d.ts +1 -0
  26. package/dist/render/string_render.d.ts +22 -0
  27. package/dist/structures/indexed_list.d.ts +46 -0
  28. package/dist/structures/list.d.ts +68 -0
  29. package/package.json +23 -11
  30. package/.env.development +0 -1
  31. package/.github/workflows/main.yml +0 -24
  32. package/TODOS.md +0 -2
  33. package/index.html +0 -13
  34. package/index.ts +0 -1
  35. package/src/DOM/Context.ts +0 -36
  36. package/src/DOM/DomEngine.ts +0 -106
  37. package/src/DOM/IRenderCycle.ts +0 -9
  38. package/src/DOM/Key.ts +0 -1
  39. package/src/DOM/Node.ts +0 -472
  40. package/src/DOM/Registry.ts +0 -53
  41. package/src/creo.ts +0 -134
  42. package/src/data-structures/assert/assert.ts +0 -12
  43. package/src/data-structures/indexed-map/IndexedMap.ts +0 -281
  44. package/src/data-structures/linked-map/LinkedMap.spec.ts +0 -67
  45. package/src/data-structures/linked-map/LinkedMap.ts +0 -198
  46. package/src/data-structures/list/List.spec.ts +0 -181
  47. package/src/data-structures/list/List.ts +0 -195
  48. package/src/data-structures/maybe/Maybe.ts +0 -25
  49. package/src/data-structures/null/null.ts +0 -3
  50. package/src/data-structures/record/IsRecordLike.spec.ts +0 -29
  51. package/src/data-structures/record/IsRecordLike.ts +0 -3
  52. package/src/data-structures/record/Record.spec.ts +0 -240
  53. package/src/data-structures/record/Record.ts +0 -145
  54. package/src/data-structures/shalllowEqual/shallowEqual.ts +0 -26
  55. package/src/data-structures/simpleKey/simpleKey.ts +0 -8
  56. package/src/examples/SimpleTodoList/SimpleTodoList.ts +0 -53
  57. package/src/examples/simple.ts +0 -0
  58. package/src/globals.d.ts +0 -1
  59. package/src/main.ts +0 -24
  60. package/src/style.css +0 -41
  61. package/src/ui/html/Block.ts +0 -10
  62. package/src/ui/html/Button.ts +0 -12
  63. package/src/ui/html/HStack.ts +0 -10
  64. package/src/ui/html/Inline.ts +0 -12
  65. package/src/ui/html/List.ts +0 -10
  66. package/src/ui/html/Text.ts +0 -9
  67. package/src/ui/html/VStack.ts +0 -11
  68. package/src/vite-env.d.ts +0 -1
  69. package/tsconfig.json +0 -23
  70. package/vite.config.js +0 -10
  71. /package/{src/data-structures/wildcard/wildcard.ts → dist/internal/wildcard.d.ts} +0 -0
package/README.md CHANGED
@@ -1 +1,276 @@
1
- Work in progress, stay tuned
1
+ # Creo
2
+
3
+ > _"There is a point of no return"_
4
+
5
+ - A "streaming" UI framework.
6
+ - No JSX, no templates, no compiler — views are function calls that flow top-down, rendered as they execute.
7
+ - Simplicity over tons of features
8
+
9
+ ## Philosophy
10
+
11
+ ### Streaming the UI
12
+
13
+ Most frameworks build a tree and diff it. Creo streams it. When `render()` runs, each `div()`, `text()`, `span()` call immediately registers a child in sequence — there is no intermediate representation between your code and the virtual DOM. The render function IS the tree, read top to bottom. What you call is what you get, in the order you call it.
14
+
15
+ ```ts
16
+ render() {
17
+ h1({}, () => text("Title")); // first child
18
+ p({}, () => text("Paragraph")); // second child
19
+ ul({}, () => { // third child, with its own children streamed inside
20
+ li({}, () => text("One"));
21
+ li({}, () => text("Two"));
22
+ });
23
+ }
24
+ ```
25
+
26
+ ### Native control flow
27
+
28
+ No `v-if`, no `{condition && <X/>}`, no `.map()` wrappers. Creo renders imperatively — use `if`, `for`, `while`, `switch`, or any JavaScript you want. The language IS the template language.
29
+
30
+ ```ts
31
+ render() {
32
+ if (loading.get()) {
33
+ Spinner();
34
+ } else if (error.get()) {
35
+ ErrorBanner({ message: error.get() });
36
+ } else {
37
+ for (const item of items.get()) {
38
+ ListItem({ key: item.id, data: item });
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ Say _NO_ to:
45
+
46
+ - special syntax to learn.
47
+ - framework-specific iteration helpers.
48
+ - ternary gymnastics.
49
+
50
+ ### Minimal model
51
+
52
+ The entire reactivity model is three concepts:
53
+
54
+ - **`use(value)`** — local state. Call `.get()`, `.set()`, `.update()`. That's it.
55
+ - **`store.new(value)`** — global state. Same interface. Any view can subscribe with `use(store)`.
56
+ - **`props()`** — read-only, passed by parent. A function call, not a magic object.
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`.
66
+
67
+ One of major ideas under the framework "if user can do it with same efficiency, let it outside framework zone"
68
+
69
+ ### Pluggable renderers
70
+
71
+ Creo allows any renderer overrides.
72
+
73
+ - **`HtmlRender`** — DOM output for browsers
74
+ - **`JsonRender`** — JSON AST for testing and serialization
75
+ - **`StringRender`** — HTML strings for SSR
76
+
77
+ ```ts
78
+ // Browser
79
+ createApp(() => App(), new HtmlRender(document.getElementById("app")!)).mount();
80
+
81
+ // Server
82
+ const renderer = new StringRender();
83
+ const engine = new Engine(renderer);
84
+ engine.createRoot(() => App(), {});
85
+ engine.render();
86
+ return renderer.renderToString();
87
+ ```
88
+
89
+ ## Quick Start
90
+
91
+ ```ts
92
+ import { createApp, view, div, text, button } from "creo";
93
+ import { HtmlRender } from "creo";
94
+
95
+ const Counter = view<{ initial: number }>(({ props, use }) => {
96
+ const count = use(props().initial);
97
+ const increment = () => count.update((n) => n + 1);
98
+
99
+ return {
100
+ render() {
101
+ button({ onClick: increment }, () => {
102
+ text(count.get());
103
+ });
104
+ },
105
+ };
106
+ });
107
+
108
+ createApp(
109
+ () => Counter({ initial: 0 }),
110
+ new HtmlRender(document.getElementById("app")!),
111
+ ).mount();
112
+ ```
113
+
114
+ ## Core Concepts
115
+
116
+ ### Views
117
+
118
+ Views are components. Define them with `view<Props>()`, which takes a setup function called once per lifecycle. The setup returns a `ViewBody` with a `render()` function called on every update.
119
+
120
+ ```ts
121
+ const Greeting = view<{ name: string }>(({ props }) => ({
122
+ render() {
123
+ div({ class: "greeting" }, () => {
124
+ text(`Hello, ${props().name}!`);
125
+ });
126
+ },
127
+ }));
128
+
129
+ // Usage in another view's render:
130
+ Greeting({ name: "world" });
131
+ ```
132
+
133
+ ### State
134
+
135
+ Local reactive state via `use()`. Called once in the setup function, read via `.get()` in render.
136
+
137
+ ```ts
138
+ const Toggle = view(({ use }) => {
139
+ const on = use(false);
140
+ const toggle = () => on.update((v) => !v);
141
+
142
+ return {
143
+ render() {
144
+ button({ onClick: toggle }, () => {
145
+ text(on.get() ? "ON" : "OFF");
146
+ });
147
+ },
148
+ };
149
+ });
150
+ ```
151
+
152
+ ### Store
153
+
154
+ Global shared state. Create outside views, subscribe inside with `use(store)`.
155
+
156
+ ```ts
157
+ import { store } from "creo";
158
+
159
+ const ThemeStore = store.new<"light" | "dark">("light");
160
+
161
+ // Any view can subscribe:
162
+ const ThemeDisplay = view(({ use }) => {
163
+ const theme = use(ThemeStore);
164
+ return {
165
+ render() {
166
+ text(`Theme: ${theme.get()}`);
167
+ },
168
+ };
169
+ });
170
+
171
+ // Update from anywhere:
172
+ ThemeStore.set("dark");
173
+ ```
174
+
175
+ ### Slots (Children)
176
+
177
+ Pass children via a slot callback — the second argument to any view or primitive.
178
+
179
+ ```ts
180
+ const Card = view<{ title: string }>(({ props, slot }) => ({
181
+ render() {
182
+ div({ class: "card" }, () => {
183
+ h1({}, () => text(props().title));
184
+ div({ class: "card-body" }, slot);
185
+ });
186
+ },
187
+ }));
188
+
189
+ // Usage:
190
+ Card({ title: "Hello" }, () => {
191
+ p({}, () => text("Card content here."));
192
+ });
193
+ ```
194
+
195
+ ### Lifecycle Hooks
196
+
197
+ ```ts
198
+ const MyView = view<{ value: number }>(({ props }) => ({
199
+ onMount() {
200
+ /* after first render */
201
+ },
202
+ onUpdateBefore() {
203
+ /* before re-render */
204
+ },
205
+ onUpdateAfter() {
206
+ /* after re-render */
207
+ },
208
+ shouldUpdate(nextProps) {
209
+ return nextProps.value !== props().value;
210
+ },
211
+ render() {
212
+ text(props().value);
213
+ },
214
+ }));
215
+ ```
216
+
217
+ ### Keyed Lists
218
+
219
+ Use `key` in props for efficient list reconciliation:
220
+
221
+ ```ts
222
+ for (const item of items.get()) {
223
+ TodoItem({ key: item.id, text: item.text, done: item.done });
224
+ }
225
+ ```
226
+
227
+ ### Conditional Rendering
228
+
229
+ Standard JavaScript control flow — no special syntax:
230
+
231
+ ```ts
232
+ render() {
233
+ if (editing.get()) {
234
+ Editor({ key: id, value });
235
+ } else {
236
+ Display({ key: id, value });
237
+ }
238
+ }
239
+ ```
240
+
241
+ ## Router
242
+
243
+ Hash-based router available as `creo-router` (separate package):
244
+
245
+ ```ts
246
+ import { createRouter } from "creo-router";
247
+
248
+ const { routeStore, navigate, RouterView, Link } = createRouter({
249
+ routes: [
250
+ { path: "/", view: () => HomePage() },
251
+ { path: "/users/:id", view: () => UserPage() },
252
+ ],
253
+ fallback: () => NotFoundPage(),
254
+ });
255
+
256
+ // Navigation:
257
+ Link({ href: "/users/42" }, () => text("User 42"));
258
+ navigate("/users/42"); // programmatic
259
+
260
+ // Read params:
261
+ const route = use(routeStore);
262
+ route.get().params.id; // "42"
263
+ ```
264
+
265
+ ## Development
266
+
267
+ ```bash
268
+ bun install
269
+ bun test src/ # Run tests
270
+ bun tsc # Type-check
271
+ bun run build # Build to dist/
272
+
273
+ # Run examples:
274
+ cd examples/todo && bun install && bun run dev
275
+ cd examples/router && bun install && bun run dev
276
+ ```
@@ -0,0 +1 @@
1
+ export declare function assertNever(x: never): never;
@@ -0,0 +1,2 @@
1
+ export type Key = number | string;
2
+ export declare function generateNextKey(): string;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Longest Increasing Subsequence — O(n log n).
3
+ *
4
+ * Given an array of numbers, returns the Set of *indices* into that array
5
+ * whose elements form the longest strictly increasing subsequence.
6
+ * Entries equal to -1 are skipped (treated as "not present").
7
+ *
8
+ * Used by the keyed reconciler to identify the maximal set of children
9
+ * that are already in correct relative order and don't need DOM moves.
10
+ */
11
+ export declare function lis(arr: number[]): Set<number>;
@@ -0,0 +1,8 @@
1
+ export type None = null | undefined;
2
+ export type Just<T> = T;
3
+ export type Maybe<T> = Just<T> | None;
4
+ export declare function just<T>(maybe: Maybe<T>, errorMessage?: string): asserts maybe is Just<T>;
5
+ export declare function isJust<T>(maybe: Maybe<T>): maybe is Just<T>;
6
+ export declare function isNone<T>(maybe: Maybe<T>): maybe is None;
7
+ export declare function withDefault<T, K>(v: Maybe<T>, alternative: K): K | NonNullable<T>;
8
+ export declare const _: undefined;
@@ -0,0 +1 @@
1
+ export type MaybePromise<T> = T | Promise<T>;
@@ -0,0 +1,2 @@
1
+ import type { Wildcard } from "../internal/wildcard";
2
+ export declare function shallowEqual(a: Wildcard, b: Wildcard): boolean;
@@ -0,0 +1,20 @@
1
+ export { createApp } from "./public/app";
2
+ export { view } from "./public/view";
3
+ export type { ViewBody, ViewFn, Slot, PublicView } from "./public/view";
4
+ export type { Reactive, Use } from "./public/state";
5
+ export { State } from "./public/state";
6
+ export { Store, store, isStore } from "./public/store";
7
+ export { $primitive } from "./public/primitive";
8
+ export type { PrimitiveProps, EventHandlerProps } from "./public/primitive";
9
+ export { html, text, div, span, section, article, aside, nav, header, footer, main, address, hgroup, search, p, h1, h2, h3, h4, h5, h6, pre, code, em, strong, small, br, hr, a, blockquote, label, abbr, b, bdi, bdo, cite, data, dfn, i, kbd, mark, q, rp, rt, ruby, s, samp, sub, sup, time, u, varEl, wbr, del, ins, ul, ol, li, dl, dt, dd, table, thead, tbody, tfoot, tr, th, td, caption, colgroup, col, form, button, input, textarea, select, option, fieldset, legend, datalist, optgroup, output, progress, meter, img, video, audio, canvas, source, track, map, area, picture, iframe, embed, object, portal, svg, details, summary, dialog, menu, figure, figcaption, script, noscript, template, slot, } from "./public/primitives/primitives";
10
+ export type { BaseEventData, PointerEventData, KeyEventData, InputEventData, FocusEventData, ContainerEvents, FormEvents, HtmlAttrs, } from "./public/primitives/primitives";
11
+ export type { IRender } from "./render/render_interface";
12
+ export { HtmlRender } from "./render/html_render";
13
+ export { JsonRender } from "./render/json_render";
14
+ export type { JsonNode } from "./render/json_render";
15
+ export { HtmlStringRender, StringRender } from "./render/string_render";
16
+ export { Engine, type Scheduler } from "./internal/engine";
17
+ export { type Maybe, type None, type Just, just, withDefault, _ } from "./functional/maybe";
18
+ export type { Key } from "./functional/key";
19
+ export { shallowEqual } from "./functional/shallow_equal";
20
+ export { assertNever } from "./functional/assert";