@llui/dom 0.0.1 → 0.0.2

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 (2) hide show
  1. package/README.md +111 -3
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,14 +1,122 @@
1
1
  # @llui/dom
2
2
 
3
- Runtime for the [LLui](https://github.com/fponticelli/llui) web framework.
3
+ Runtime for the [LLui](https://github.com/fponticelli/llui) web framework — The Elm Architecture with compile-time bitmask optimization.
4
4
 
5
- Component model, mount, scope tree, reactive bindings, structural primitives (`show`, `branch`, `each`), element helpers, and the `View<S, M>` helper bundle.
5
+ No virtual DOM. `view()` runs once at mount, building real DOM nodes with reactive bindings that update surgically when state changes.
6
+
7
+ ## Install
6
8
 
7
9
  ```bash
8
10
  pnpm add @llui/dom
9
11
  ```
10
12
 
11
- See the [main README](../../README.md) for getting started.
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { component, mountApp, div, button } from '@llui/dom'
17
+
18
+ type State = { count: number }
19
+ type Msg = { type: 'inc' } | { type: 'dec' }
20
+
21
+ const Counter = component<State, Msg, never>({
22
+ name: 'Counter',
23
+ init: () => [{ count: 0 }, []],
24
+ update: (state, msg) => {
25
+ switch (msg.type) {
26
+ case 'inc': return [{ ...state, count: state.count + 1 }, []]
27
+ case 'dec': return [{ ...state, count: state.count - 1 }, []]
28
+ }
29
+ },
30
+ view: ({ send, text }) => [
31
+ button({ onClick: () => send({ type: 'dec' }) }, [text('-')]),
32
+ text(s => String(s.count)),
33
+ button({ onClick: () => send({ type: 'inc' }) }, [text('+')]),
34
+ ],
35
+ })
36
+
37
+ mountApp(document.getElementById('app')!, Counter)
38
+ ```
39
+
40
+ ## View<S, M> — the helper bundle
41
+
42
+ `view` receives a single `View<S, M>` bag. Destructure what you need — `send` plus any state-bound helpers. TypeScript infers `S` from the component definition, so no per-call generics:
43
+
44
+ ```typescript
45
+ view: ({ send, text, show, each, branch, memo }) => [
46
+ text(s => s.label), // s is State — inferred
47
+ ...show({ when: s => s.visible, render: () => [...] }),
48
+ ...each({ items: s => s.items, key: i => i.id, render: ({ item }) => [...] }),
49
+ ]
50
+ ```
51
+
52
+ Element helpers (`div`, `button`, `span`, etc.) stay as imports — they're stateless and don't need the `S` binding.
53
+
54
+ ## API
55
+
56
+ ### Core
57
+
58
+ | Export | Purpose |
59
+ |---|---|
60
+ | `component(def)` | Create a component definition |
61
+ | `mountApp(el, def)` | Mount a component to a DOM element |
62
+ | `hydrateApp(el, def)` | Hydrate server-rendered HTML |
63
+ | `flush()` | Synchronously flush all pending updates |
64
+ | `createView(send)` | Create a full View bundle (for tests/dynamic use) |
65
+
66
+ ### View Primitives
67
+
68
+ | Primitive | Purpose |
69
+ |---|---|
70
+ | `text(accessor)` | Reactive text node |
71
+ | `show({ when, render })` | Conditional rendering |
72
+ | `branch({ on, cases })` | Multi-case switching |
73
+ | `each({ items, key, render })` | Keyed list rendering |
74
+ | `portal({ target, render })` | Render into a different DOM location |
75
+ | `child({ def, key, props })` | Full component boundary (Level 2 composition) |
76
+ | `memo(accessor)` | Memoized derived value |
77
+ | `selector(field)` | O(1) one-of-N selection binding |
78
+ | `onMount(callback)` | Lifecycle hook (runs once after mount) |
79
+ | `errorBoundary(opts)` | Catch render errors |
80
+ | `foreign({ create, update })` | Integrate non-LLui libraries |
81
+ | `slice(h, selector)` | View over a sub-slice of state |
82
+
83
+ ### Composition
84
+
85
+ | Export | Purpose |
86
+ |---|---|
87
+ | `mergeHandlers(...handlers)` | Combine multiple update handlers |
88
+ | `sliceHandler({ get, set, narrow, sub })` | Route messages to a state slice |
89
+
90
+ ### Context
91
+
92
+ | Export | Purpose |
93
+ |---|---|
94
+ | `createContext(defaultValue)` | Create a context |
95
+ | `provide(ctx, accessor, children)` | Provide value to subtree |
96
+ | `useContext(ctx)` | Read context value |
97
+
98
+ ### Element Helpers
99
+
100
+ 50+ typed element constructors: `div`, `span`, `button`, `input`, `a`, `h1`-`h6`, `table`, `tr`, `td`, `ul`, `li`, `img`, `form`, `label`, `select`, `textarea`, `canvas`, `video`, `nav`, `header`, `footer`, `section`, `article`, `p`, `pre`, `code`, and more.
101
+
102
+ ### SSR
103
+
104
+ | Export | Purpose |
105
+ |---|---|
106
+ | `renderToString(def)` | Render component to HTML string |
107
+ | `initSsrDom()` | Initialize jsdom for SSR (from `@llui/dom/ssr`) |
108
+
109
+ ## Sub-path Exports
110
+
111
+ ```typescript
112
+ import { installDevTools } from '@llui/dom/devtools' // dev-only, tree-shaken
113
+ import { initSsrDom } from '@llui/dom/ssr' // server-only
114
+ import { replaceComponent } from '@llui/dom/hmr' // HMR support
115
+ ```
116
+
117
+ ## Performance
118
+
119
+ Competitive with Solid and Svelte on [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark). 5.8 KB gzipped.
12
120
 
13
121
  ## License
14
122
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llui/dom",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {