literaljs 8.0.3 → 8.0.5
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/README.md +295 -137
- package/build/index.js +1 -1
- package/build/index.m.js +1 -1
- package/build/index.modern.mjs +1 -1
- package/build/index.umd.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,49 +1,55 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="literalJS.png" alt="LiteralJS Logo">
|
|
2
|
+
<img src="literalJS.png" alt="LiteralJS Logo" width="400">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
### A small, fast JavaScript library for building reactive user interfaces.
|
|
5
|
+
<p align="center">
|
|
6
|
+
<strong>A small, fast JavaScript library for building reactive user interfaces.</strong><br>
|
|
7
|
+
Zero dependencies. 4.5 kB gzipped. Modern browsers.
|
|
8
|
+
</p>
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
<p align="center">
|
|
11
|
+
<a href="#quick-start">Quick Start</a> · <a href="#component-api">Components</a> · <a href="#state-management">State</a> · <a href="#architecture">Architecture</a> · <a href="https://literaljs.com">Website</a>
|
|
12
|
+
</p>
|
|
12
13
|
|
|
13
14
|
---
|
|
14
15
|
|
|
15
16
|
## Quick Start
|
|
16
17
|
|
|
17
|
-
###
|
|
18
|
+
### Install
|
|
18
19
|
|
|
19
20
|
```bash
|
|
20
21
|
npm install literaljs
|
|
21
22
|
```
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
### Hello World
|
|
25
|
+
|
|
26
|
+
```jsx
|
|
24
27
|
/** @jsx h */
|
|
25
28
|
import { h, component, App } from 'literaljs';
|
|
26
29
|
|
|
27
|
-
const
|
|
28
|
-
name: '
|
|
30
|
+
const Counter = component({
|
|
31
|
+
name: 'Counter',
|
|
29
32
|
state: { count: 0 },
|
|
33
|
+
methods() {
|
|
34
|
+
return {
|
|
35
|
+
increment() {
|
|
36
|
+
this.setState({ count: this.getState().count + 1 });
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
},
|
|
30
40
|
render() {
|
|
31
|
-
const { count } = this.getState();
|
|
32
41
|
return (
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Increment
|
|
37
|
-
</button>
|
|
38
|
-
</div>
|
|
42
|
+
<button events={{ click: () => this.increment() }}>
|
|
43
|
+
Count: {this.getState().count}
|
|
44
|
+
</button>
|
|
39
45
|
);
|
|
40
46
|
}
|
|
41
47
|
});
|
|
42
48
|
|
|
43
|
-
new App(
|
|
49
|
+
new App(Counter, {}).mount('app');
|
|
44
50
|
```
|
|
45
51
|
|
|
46
|
-
> **JSX setup**: Configure your build tool to use `h` as the
|
|
52
|
+
> **JSX setup**: Configure your build tool to use `h` as the pragma:
|
|
47
53
|
> ```json
|
|
48
54
|
> { "plugins": [["@babel/plugin-transform-react-jsx", { "pragma": "h" }]] }
|
|
49
55
|
> ```
|
|
@@ -51,10 +57,10 @@ new App(Hello, {}).mount('app');
|
|
|
51
57
|
### CDN (UMD)
|
|
52
58
|
|
|
53
59
|
```html
|
|
54
|
-
<script src="https://unpkg.com/literaljs/build/index.umd.js"></script>
|
|
60
|
+
<script src="https://unpkg.com/literaljs@8/build/index.umd.js"></script>
|
|
55
61
|
<script>
|
|
56
62
|
const { h, component, App } = LiteralJS;
|
|
57
|
-
//
|
|
63
|
+
// same as above
|
|
58
64
|
</script>
|
|
59
65
|
```
|
|
60
66
|
|
|
@@ -64,188 +70,340 @@ new App(Hello, {}).mount('app');
|
|
|
64
70
|
|
|
65
71
|
| Export | Purpose |
|
|
66
72
|
|--------|---------|
|
|
67
|
-
| `h(tag, attrs, ...children)` | Create VNode (
|
|
68
|
-
| `component(config)` | Define a component with state, methods, lifecycle |
|
|
69
|
-
| `new App(rootComponent, initialStore)` | Create an app instance |
|
|
70
|
-
| `app.mount(domId)` | Mount to a DOM element |
|
|
71
|
-
| `app.unmount()` | Remove from DOM
|
|
72
|
-
| `app.
|
|
73
|
+
| `h(tag, attrs, ...children)` | Create a VNode (use as JSX pragma, Hyperscript, or plain object) |
|
|
74
|
+
| `component(config)` | Define a component with state, methods, and lifecycle |
|
|
75
|
+
| `new App(rootComponent, initialStore)` | Create an isolated app instance |
|
|
76
|
+
| `app.mount(domId)` | Mount to a DOM element by ID |
|
|
77
|
+
| `app.unmount()` | Remove from DOM, clean up events and state |
|
|
78
|
+
| `app.update()` | Force a re-render |
|
|
79
|
+
| `app.setStore(updater)` | Update the global store |
|
|
80
|
+
| `app.getStore()` | Read the global store |
|
|
73
81
|
| `render(rootComponent, domId, store)` | Legacy one-liner (backward-compatible) |
|
|
82
|
+
| `StateManager` | Standalone state manager (for testing) |
|
|
83
|
+
| `generateUUID` | UUID generator |
|
|
84
|
+
| `advanceRenderCycle` | Advance the render cycle counter (testing) |
|
|
74
85
|
|
|
75
86
|
---
|
|
76
87
|
|
|
77
|
-
##
|
|
88
|
+
## Component API
|
|
78
89
|
|
|
79
|
-
|
|
90
|
+
```jsx
|
|
91
|
+
const MyComponent = component({
|
|
92
|
+
name: 'MyComponent', // Component name (for debugging and state keys)
|
|
93
|
+
state: { count: 0 }, // Initial component state
|
|
94
|
+
methods() { // Bound methods available as this.methodName
|
|
95
|
+
return {
|
|
96
|
+
increment() {
|
|
97
|
+
this.setState({ count: this.getState().count + 1 });
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
mounted() { // Called after first render
|
|
102
|
+
console.log('Mounted!');
|
|
103
|
+
},
|
|
104
|
+
updated() { // Called after re-render
|
|
105
|
+
console.log('Updated!');
|
|
106
|
+
},
|
|
107
|
+
unmounted() { // Called when removed from DOM
|
|
108
|
+
console.log('Cleaned up!');
|
|
109
|
+
},
|
|
110
|
+
render() { // Returns a VNode tree
|
|
111
|
+
const { count } = this.getState();
|
|
112
|
+
return (
|
|
113
|
+
<div>
|
|
114
|
+
<p>Count: {count}</p>
|
|
115
|
+
<button events={{ click: () => this.increment() }}>
|
|
116
|
+
Increment
|
|
117
|
+
</button>
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Props
|
|
125
|
+
|
|
126
|
+
Pass data down from parent to child:
|
|
127
|
+
|
|
128
|
+
```jsx
|
|
129
|
+
// Parent
|
|
130
|
+
<MyComponent key="unique" title="Hello" count={5} />
|
|
131
|
+
|
|
132
|
+
// Child
|
|
133
|
+
render() {
|
|
134
|
+
return <h1>{this.props.title} — {this.props.count}</h1>;
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Sibling Components (Auto-Keyed)
|
|
139
|
+
|
|
140
|
+
**You don't need explicit `key` props for sibling components.** LiteralJS automatically assigns stable, position-based instance keys so each sibling gets isolated state:
|
|
141
|
+
|
|
142
|
+
```jsx
|
|
143
|
+
const Counter = component({
|
|
144
|
+
name: 'Counter',
|
|
145
|
+
state: { count: 0 },
|
|
146
|
+
methods() {
|
|
147
|
+
return {
|
|
148
|
+
increment() { this.setState({ count: this.getState().count + 1 }); }
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
render() {
|
|
152
|
+
return <span>{this.getState().count}</span>;
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const App = component({
|
|
157
|
+
name: 'App',
|
|
158
|
+
render() {
|
|
159
|
+
// Each Counter has its own independent state — no key prop needed
|
|
160
|
+
return (
|
|
161
|
+
<div>
|
|
162
|
+
<Counter /> {/* auto-key: __auto_0__ */}
|
|
163
|
+
<Counter /> {/* auto-key: __auto_1__ */}
|
|
164
|
+
<Counter /> {/* auto-key: __auto_2__ */}
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
> **How it works**: Each render cycle, component factories reset a position counter. The first keyless sibling gets `__auto_0__`, the second `__auto_1__`, etc. Because the counter resets each render, the same position always maps to the same key — so state persists across re-renders while remaining isolated between siblings.
|
|
172
|
+
|
|
173
|
+
You can still use explicit `key` props when you need semantic identity (e.g., for list items that reorder):
|
|
174
|
+
|
|
175
|
+
```jsx
|
|
176
|
+
{items.map(item => (
|
|
177
|
+
<ListItem key={item.id} item={item} />
|
|
178
|
+
))}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Lifecycle Hooks
|
|
182
|
+
|
|
183
|
+
| Hook | Called When | Use Case |
|
|
184
|
+
|------|------------|----------|
|
|
185
|
+
| `mounted()` | After first DOM render | Initialize third-party libs, DOM queries |
|
|
186
|
+
| `updated()` | After re-render | React to prop changes, DOM measurements |
|
|
187
|
+
| `unmounted()` | Before DOM removal | Clean up timers, event listeners, subscriptions |
|
|
188
|
+
|
|
189
|
+
### Component Instance Methods
|
|
190
|
+
|
|
191
|
+
| Method | Description |
|
|
192
|
+
|--------|-------------|
|
|
193
|
+
| `this.getState()` | Shallow copy of component state |
|
|
194
|
+
| `this.setState(updater)` | Update state and trigger re-render |
|
|
195
|
+
| `this.getStore()` | Shallow copy of global store |
|
|
196
|
+
| `this.setStore(updater)` | Update global store and trigger re-render |
|
|
197
|
+
| `this.props` | Current component props |
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## State Management
|
|
80
202
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
203
|
+
### Component State (private, isolated)
|
|
204
|
+
|
|
205
|
+
Each component instance has its own private state. Sibling instances do not share state:
|
|
206
|
+
|
|
207
|
+
```js
|
|
208
|
+
this.getState(); // Read current state (shallow copy)
|
|
209
|
+
this.setState({ count: 5 }); // Update and re-render
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Global Store (shared across components)
|
|
213
|
+
|
|
214
|
+
```js
|
|
215
|
+
// Write
|
|
216
|
+
this.setStore({ theme: 'dark' });
|
|
217
|
+
|
|
218
|
+
// Read
|
|
219
|
+
const theme = this.getStore().theme;
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Initialize the store when creating the app:
|
|
223
|
+
|
|
224
|
+
```js
|
|
225
|
+
new App(RootComponent, { theme: 'light', user: null }).mount('app');
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Keys and Reconciliation
|
|
231
|
+
|
|
232
|
+
### Auto-Keys (v8.0.4+)
|
|
233
|
+
|
|
234
|
+
LiteralJS automatically assigns position-based keys to sibling components. You don't need to add `key` props unless you need semantic identity for reordering.
|
|
235
|
+
|
|
236
|
+
### Explicit Keys
|
|
237
|
+
|
|
238
|
+
Use explicit `key` props when:
|
|
239
|
+
- List items can be reordered (keyed reconciliation tracks DOM identity)
|
|
240
|
+
- You want to force a component to remount when data changes
|
|
241
|
+
|
|
242
|
+
```jsx
|
|
243
|
+
{items.map(item => (
|
|
244
|
+
<TodoItem key={item.id} item={item} />
|
|
245
|
+
))}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Architecture
|
|
251
|
+
|
|
252
|
+
### Design Principles
|
|
253
|
+
|
|
254
|
+
- **Zero runtime dependencies** — only dev dependencies for builds and tests
|
|
255
|
+
- **Small surface area** — 9 exports, one component pattern, one state model
|
|
256
|
+
- **Plain functions** — no classes, no hooks, no decorators, no magic
|
|
257
|
+
- **Isolated instances** — multiple `App` instances on one page, zero globals
|
|
87
258
|
|
|
88
259
|
### Module Structure
|
|
89
260
|
|
|
90
261
|
```
|
|
91
262
|
App (container)
|
|
92
|
-
├── StateManager
|
|
93
|
-
├── EventManager
|
|
94
|
-
├── Renderer
|
|
95
|
-
├── LifecycleQueue
|
|
96
|
-
├── DiffEngine
|
|
97
|
-
|
|
263
|
+
├── StateManager — global store + component state with subscriptions
|
|
264
|
+
├── EventManager — WeakMap delegation + event cache
|
|
265
|
+
├── Renderer — DOM creation + virtual DOM diff/patch
|
|
266
|
+
├── LifecycleQueue — mounted/updated/unmounted lifecycle hooks
|
|
267
|
+
├── DiffEngine — keyed + non-keyed child reconciliation
|
|
268
|
+
├── MountOrchestrator — render cycle coordination + tree generation
|
|
269
|
+
├── UpdateLoop — microtask batched scheduler
|
|
270
|
+
├── ComponentInstance — per-instance state, methods, and lifecycle
|
|
271
|
+
└── VNode — lightweight virtual DOM representation
|
|
98
272
|
```
|
|
99
273
|
|
|
274
|
+
### v8 Performance Features
|
|
275
|
+
|
|
276
|
+
| Feature | Benefit |
|
|
277
|
+
|---------|---------|
|
|
278
|
+
| Keyed reconciliation | Preserves DOM identity across reordering |
|
|
279
|
+
| WeakMap event delegation | Skips ancestor walk when no handlers exist |
|
|
280
|
+
| Component memoization | Shallow props comparison skips re-render |
|
|
281
|
+
| Text node fast path | `textContent` update instead of `replaceChild` |
|
|
282
|
+
| Reference-equality shortcuts | Skips diffing for unchanged VNodes, children, attrs |
|
|
283
|
+
| Auto-instance keys | Sibling components isolated without manual `key` props |
|
|
284
|
+
| Microtask batching | Multiple `setState` calls collapse to one render |
|
|
285
|
+
|
|
100
286
|
---
|
|
101
287
|
|
|
102
288
|
## Bundle Size
|
|
103
289
|
|
|
104
|
-
| Format |
|
|
105
|
-
|
|
106
|
-
| ESM (modern) |
|
|
107
|
-
|
|
|
108
|
-
|
|
|
290
|
+
| Format | Minified | Gzipped |
|
|
291
|
+
|--------|----------|---------|
|
|
292
|
+
| ESM (modern) | 14.3 kB | **4.4 kB** |
|
|
293
|
+
| CJS | 14.4 kB | 4.4 kB |
|
|
294
|
+
| UMD | 14.5 kB | 4.5 kB |
|
|
109
295
|
|
|
110
|
-
|
|
296
|
+
Target: Chrome 90+, Firefox 90+, Safari 14+ (ES2018). No `Object.assign` polyfill needed.
|
|
111
297
|
|
|
112
298
|
---
|
|
113
299
|
|
|
114
|
-
## Performance
|
|
300
|
+
## Performance
|
|
115
301
|
|
|
116
|
-
|
|
117
|
-
|
|
302
|
+
Benchmarks measured in JSDOM. Real Chrome results are significantly faster.
|
|
303
|
+
|
|
304
|
+
| Benchmark | v7 | v8 | Change |
|
|
305
|
+
|-----------|----|----|--------|
|
|
118
306
|
| create 1k rows | ~45ms | ~47ms | stable |
|
|
119
307
|
| replace 1k rows | ~65ms | ~6ms | **-91%** |
|
|
120
308
|
| partial update | ~186ms | ~100ms | **-46%** |
|
|
121
309
|
| select row | ~22ms | ~0.05ms | **-99.8%** |
|
|
122
|
-
| swap rows | — | ~123ms* | *JSDOM artifact; real Chrome near-instant |
|
|
123
310
|
| remove row | ~74ms | ~5ms | **-93%** |
|
|
124
311
|
| clear rows | ~3ms | ~0.01ms | **-99.7%** |
|
|
125
312
|
|
|
126
|
-
*All benchmarks on JSDOM. Real Chrome results for `swap` are expected to be ~1ms (pointer swap).*
|
|
127
|
-
|
|
128
313
|
---
|
|
129
314
|
|
|
130
|
-
##
|
|
315
|
+
## Event Handling
|
|
316
|
+
|
|
317
|
+
LiteralJS uses event delegation. Define handlers via the `events` attribute:
|
|
318
|
+
|
|
319
|
+
```jsx
|
|
320
|
+
<button events={{ click: () => this.increment() }}>
|
|
321
|
+
Click me
|
|
322
|
+
</button>
|
|
323
|
+
```
|
|
131
324
|
|
|
132
|
-
|
|
133
|
-
- **Fast** — Keyed diffing, WeakMap event delegation, render memoization
|
|
134
|
-
- **Simple** — Plain functions + structured components. No classes, no hooks, no magic.
|
|
135
|
-
- **Virtual DOM** — Diffed updates only on state change
|
|
136
|
-
- **Flexible Syntax** — JSX (with `h` pragma), Hyperscript, or Object syntax
|
|
137
|
-
- **Lifecycle Methods** — `mounted`, `updated`, `unmounted`
|
|
138
|
-
- **Global + Component State** — Built-in store; no Redux needed
|
|
139
|
-
- **Event Delegation** — Most events delegated to root for performance
|
|
140
|
-
- **Isolated Instances** — Multiple `App` instances on one page, no globals
|
|
325
|
+
Supported events: `click`, `input`, `change`, `submit`, `keyup`, `keydown`, `focus`, `blur`, `mouseenter`, `mouseleave`, `touchstart`, `touchend`, and more.
|
|
141
326
|
|
|
142
327
|
---
|
|
143
328
|
|
|
144
|
-
##
|
|
329
|
+
## Syntax Options
|
|
145
330
|
|
|
146
|
-
|
|
331
|
+
### JSX (recommended)
|
|
332
|
+
|
|
333
|
+
```jsx
|
|
147
334
|
/** @jsx h */
|
|
148
335
|
import { h, component, App } from 'literaljs';
|
|
149
336
|
|
|
150
|
-
const
|
|
151
|
-
name: '
|
|
152
|
-
state: { count: 0 }, // Initial component state
|
|
153
|
-
methods() { // Bound functions available as `this.methodName`
|
|
154
|
-
return {
|
|
155
|
-
increment() { this.setState({ count: this.getState().count + 1 }); }
|
|
156
|
-
};
|
|
157
|
-
},
|
|
158
|
-
mounted() { console.log('mounted'); },
|
|
159
|
-
updated() { console.log('updated'); },
|
|
160
|
-
unmounted() { console.log('unmounted'); },
|
|
337
|
+
const View = component({
|
|
338
|
+
name: 'View',
|
|
161
339
|
render() {
|
|
162
|
-
|
|
163
|
-
return (
|
|
164
|
-
<div>
|
|
165
|
-
<p>Count: {count}</p>
|
|
166
|
-
<button events={{ click: () => this.increment() }}>Add</button>
|
|
167
|
-
</div>
|
|
168
|
-
);
|
|
340
|
+
return <div class="app"><h1>Hello</h1></div>;
|
|
169
341
|
}
|
|
170
342
|
});
|
|
171
|
-
|
|
172
|
-
new App(MyComponent, {}).mount('app');
|
|
173
343
|
```
|
|
174
344
|
|
|
175
|
-
###
|
|
345
|
+
### Hyperscript
|
|
176
346
|
|
|
177
347
|
```js
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return <h1>{this.props.title}</h1>;
|
|
185
|
-
}
|
|
348
|
+
const View = component({
|
|
349
|
+
name: 'View',
|
|
350
|
+
render() {
|
|
351
|
+
return h('div', { class: 'app' }, h('h1', {}, 'Hello'));
|
|
352
|
+
}
|
|
353
|
+
});
|
|
186
354
|
```
|
|
187
355
|
|
|
188
|
-
###
|
|
189
|
-
|
|
190
|
-
Use `key` for list items to enable DOM identity preservation:
|
|
356
|
+
### Object syntax
|
|
191
357
|
|
|
192
358
|
```js
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
359
|
+
const View = component({
|
|
360
|
+
name: 'View',
|
|
361
|
+
render() {
|
|
362
|
+
return { e: 'div', a: { class: 'app' }, c: [{ e: 'h1', a: {}, c: ['Hello'] }] };
|
|
363
|
+
}
|
|
364
|
+
});
|
|
199
365
|
```
|
|
200
366
|
|
|
201
367
|
---
|
|
202
368
|
|
|
203
|
-
##
|
|
369
|
+
## Style Handling
|
|
204
370
|
|
|
205
|
-
|
|
371
|
+
Pass styles as objects (not strings). String styles cause a `TypeError` because LiteralJS iterates over style keys:
|
|
206
372
|
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
```
|
|
373
|
+
```jsx
|
|
374
|
+
// ✅ Correct
|
|
375
|
+
<div style={{ position: 'fixed', top: '0', left: '0' }}>
|
|
211
376
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
```js
|
|
215
|
-
// In any component
|
|
216
|
-
this.setStore({ theme: 'dark' }); // Update global store
|
|
217
|
-
|
|
218
|
-
// Access in render
|
|
219
|
-
render() {
|
|
220
|
-
const theme = this.getStore().theme;
|
|
221
|
-
return <div class={theme}>...</div>;
|
|
222
|
-
}
|
|
377
|
+
// ❌ Wrong — causes TypeError
|
|
378
|
+
<div style="position:fixed;top:0;left:0">
|
|
223
379
|
```
|
|
224
380
|
|
|
225
381
|
---
|
|
226
382
|
|
|
227
|
-
##
|
|
383
|
+
## Changelog
|
|
228
384
|
|
|
229
|
-
|
|
230
|
-
- **Architecture decisions**: `docs/ADR/`
|
|
231
|
-
- **Phase plans**: `docs/v8-*-plan.md`
|
|
385
|
+
### [8.0.4] - 2026-05-19
|
|
232
386
|
|
|
233
|
-
|
|
387
|
+
**Fixed**: Sibling components without explicit `key` props now have isolated state.
|
|
234
388
|
|
|
235
|
-
|
|
389
|
+
- Replaced `__default__` singleton key with auto-incrementing position keys (`__auto_0__`, `__auto_1__`, etc.)
|
|
390
|
+
- Added render-cycle counter (`advanceRenderCycle`) for stable keys across re-renders
|
|
391
|
+
- `MountOrchestrator` calls `advanceRenderCycle()` before each render pass
|
|
392
|
+
- Exported `advanceRenderCycle` for testing
|
|
393
|
+
- Updated tree.js (simplified, removed `_resetPosition` from VNode walk)
|
|
236
394
|
|
|
237
|
-
|
|
395
|
+
### [8.0.3] - 2026-05-18
|
|
238
396
|
|
|
239
|
-
|
|
240
|
-
cd js-framework-benchmark-entry
|
|
241
|
-
npm install
|
|
242
|
-
npm run build-prod
|
|
243
|
-
```
|
|
397
|
+
**Fixed**: Null/undefined guard in `generateTree` before `typeof` check.
|
|
244
398
|
|
|
245
|
-
|
|
399
|
+
### [8.0.2] - 2026-05-18
|
|
246
400
|
|
|
247
|
-
|
|
401
|
+
**Fixed**: Tree direct-props fix — two code paths for backward compat (`newC.a.props`) and modern JSX (`{ ...newC.a }`).
|
|
402
|
+
|
|
403
|
+
### [8.0.1] - 2026-05-18
|
|
404
|
+
|
|
405
|
+
**Fixed**: WeakMap event delegation. Component render memoization. Keyed reconciliation.
|
|
248
406
|
|
|
249
|
-
|
|
407
|
+
### [8.0.0] - 2026-05-18
|
|
250
408
|
|
|
251
|
-
|
|
409
|
+
**Initial v8 release**. Full architecture refactor from monolith to 12 modules.
|
package/build/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class e{constructor(e,t,n){void 0===t&&(t={}),void 0===n&&(n=[]),this.e=e,this.a=t,this.c=n}withLifecycle(e){return e.mounted&&(this.m=e.mounted),e.updated&&(this.up=e.updated),e.unmounted&&(this.un=e.unmounted),e.deleteState&&(this.d=e.deleteState),this}withIdentity(e,t){return this.definitionId=e,this.instanceId=t,this.id=e+"_"+t,this}}function t(e,n){for(let s=0,i=n.length;s<i;s++)Array.isArray(n[s])?t(e,n[s]):e.push(n[s]);return e}function n(){return Math.random().toString(36).substring(2)+(new Date).getTime().toString(36)}class s{constructor(e,t,n,s,i,o){this.definitionId=e,this.instanceId=t,this.name=n,this.key=`${e}_${t}_${n}`,this.props=s,this._stateManager=o,this._config=i,o.createState(this.key,i.state),this.mounted=i.mounted.bind(this),this.updated=i.updated.bind(this),this.unmounted=i.unmounted.bind(this),this.deleteState=()=>{this._stateManager.deleteState(this.key)},this._renderedVNode=null,this._previousProps=null;const r=i.render.bind(this);this.render=()=>{if(!this.shouldUpdate())return this._renderedVNode;const e=r();return this._renderedVNode=e,this._previousProps=this.props,e}}getStore(){return this._stateManager.getStore()}setStore(e,t){this._stateManager.setStore(e,t)}getState(){return this._stateManager.getState(this.key)}setState(e,t){this._stateManager.setState(this.key,e,t)}createState(){this._stateManager.createState(this.key,this._config.state)}deleteState(){this._stateManager.deleteState(this.key)}shouldUpdate(){return!this._previousProps||!function(e,t){if(e===t)return!0;if(!e||!t||"object"!=typeof e||"object"!=typeof t)return!1;const n=Object.keys(e),s=Object.keys(t);if(n.length!==s.length)return!1;for(let s=0;s<n.length;s++)if(e[n[s]]!==t[n[s]])return!1;return!0}(this.props,this._previousProps)}bindMethods(e){"function"==typeof e&&(e=e.bind(this)());for(let t in e)this[t]=e[t].bind(this)}}function i(e,t){for(let n in t)e[n]=t[n];return e}class o{constructor(e){void 0===e&&(e={}),this.store={...e},this.componentStates={},this.listeners=[]}subscribe(e){this.listeners.push(e)}unsubscribe(e){const t=this.listeners.indexOf(e);t>-1&&this.listeners.splice(t,1)}_notify(){for(let e=0;e<this.listeners.length;e++)this.listeners[e]()}getStore(){return{...this.store}}setStore(e,t){"function"==typeof e&&(e=e(this.store)),this.store=i(i({},this.store),e),this._notify(),"function"==typeof t&&t()}createState(e,t){e in this.componentStates||(this.componentStates[e]={...t})}getState(e){return{...this.componentStates[e]}}setState(e,t,n){"function"==typeof t&&(t=t(this.componentStates[e])),this.componentStates[e]=i(i({},this.componentStates[e]),t),this._notify(),"function"==typeof n&&n()}deleteState(e){delete this.componentStates[e]}reset(){this.store={},this.componentStates={},this.listeners=[]}}class r{constructor(e,t,n){this.eventManager=e,this.lifecycleQueue=t,this.diffEngine=n}mount(e,t){const n=this.createElement(t);n&&e.appendChild(n)}createElement(e){if(null==e)return document.createTextNode("");const t=typeof e;return"string"===t||"number"===t?document.createTextNode(e):"boolean"===t||"undefined"===t?document.createTextNode(""):"object"===t&&e.e?this._createElementNode(e):null}_createElementNode(e){const t=document.createElement(e.e);if("object"==typeof e.a){const n=Object.keys(e.a);for(let s=n.length;s--;)if("events"===n[s])e.eid=this.eventManager.bindEvents(t,e.a[n[s]]);else if("style"===n[s])this._addStyles(e.a[n[s]],t);else{if("key"===n[s])continue;t.setAttribute(n[s],e.a[n[s]])}}if(this.lifecycleQueue.mounted(e),Array.isArray(e.c))for(let n=0,s=e.c.length;n<s;n++){const s=this.createElement(e.c[n]);s&&t.appendChild(s)}return t}_addStyles(e,t){if(void 0===e)return;const n=Object.keys(e);for(let s=n.length;s--;)t.style[n[s]]=e[n[s]]}patch(e,t,n,s){const i=typeof n;if(void 0===s)this._appendChild(e,n);else if("undefined"===i)this._unmountNodeAndChildren(s),t&&t.remove();else if(this.diffEngine.areNodesEqual(n,s)){if("object"===i&&n.e){if(n===s)return;if(this._updateNodes(t,n,s),n.c!==s.c)if(this.diffEngine._hasKeys(n.c)||this.diffEngine._hasKeys(s.c))this.diffEngine.reconcileChildren(t,n.c,s.c,this);else{let e;for(let i=s.c?s.c.length:0;i--&&void 0===n.c[i];)e=t.lastChild,e&&(this._unmountNodeAndChildren(s.c[i]),e.remove());if(Array.isArray(n.c))for(let e=0,i=n.c.length;e<i;e++)this.patch(t,t.childNodes[e]||null,n.c[e],s.c?s.c[e]:void 0)}}}else if(!t||3!==t.nodeType||"string"!==i&&"number"!==i)this._unmountNodeAndChildren(s),t&&e.replaceChild(this.createElement(n),t);else{const e=String(n);t.textContent!==e&&(t.textContent=e)}}_appendChild(e,t){const n=this.createElement(t);n&&e.appendChild(n)}_updateNodes(e,t,n){if(this.lifecycleQueue.updated(t),t.a===n.a)return;if(!t.a||!n.a)return;const s=Object.keys(t.a);let i,o;for(let r=s.length;r--;)if(o=t.a[s[r]],i=n.a[s[r]],"style"===s[r]){if(this._stylesAreEqual(o,i))continue;e.removeAttribute(s[r]),this._addStyles(o,e)}else if("events"===s[r])this.eventManager.unbindEvents(e,n.eid),t.eid=this.eventManager.bindEvents(e,o);else{if("key"===s[r])continue;"value"===s[r]&&o!==i?e.value=o:void 0!==i&&o===i||e.setAttribute(s[r],o)}}_stylesAreEqual(e,t){if(e===t)return!0;const n=typeof e,s=typeof t;if("undefined"===n&&"undefined"===s)return!0;if("object"!==n||"object"!==s)return!1;const i=Object.keys(e),o=Object.keys(t);if(i.length!==o.length)return!1;for(let n=i.length;n--;)if(e[i[n]]!==t[i[n]])return!1;return!0}_unmountNodeAndChildren(e){if(null!=e&&(this.lifecycleQueue.unmounted(e),this.lifecycleQueue.deleteState(e),this.eventManager.deleteCachedEvent(e.eid),Array.isArray(e.c)))for(let t=e.c.length;t--;)this._unmountNodeAndChildren(e.c[t])}unmount(e,t){this._unmountNodeAndChildren(t),e&&(e.innerHTML="")}}class h{constructor(e,t,n){this._getCache=e,this._resolveUUID=t,this._elementToUUID=n,this._attachedTypes=new Set,this._rootNode=null}attach(e,t){this._attachedTypes.has(t)||(this._attachedTypes.add(t),this._rootNode=e,e._literaljs_hasEvents=!0,e.addEventListener(t,e=>this._handle(e)))}_handle(e){if(!this._rootNode||!this._rootNode._literaljs_hasEvents)return;let t=e.target;for(;t&&t!==this._rootNode;){let n;if(this._elementToUUID&&(n=this._elementToUUID.get(t))){const t=this._getCache(n);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}const s=this._resolveUUID(t);if("string"==typeof s){const t=this._getCache(s);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}t=t.parentNode}}reset(){this._attachedTypes.clear()}}const d=["abort","blur","error","focus","load","mouseenter","mouseleave","resize","scroll","unload"],c="eid";class u{constructor(){this.cache={},this.rootNode=null,this._elementToUUID=new WeakMap,this.eventBus=new h(e=>this.cache[e],e=>this.getEventUUID(e),this._elementToUUID)}setRootNode(e){this.rootNode=e}getEventUUID(e){if(!e||!e.parentNode)return;if("#document"===e.parentNode.nodeName)return;const t=e.getAttribute("data-"+c);return"string"==typeof t?t:this.getEventUUID(e.parentNode)}bindEvents(e,t){const s=n();e.setAttribute("data-"+c,s),this.cache[s]=t,this._elementToUUID.set(e,s);const i=Object.keys(t);for(let t=i.length;t--;)d.includes(i[t])?e.addEventListener(i[t],this.cache[s][i[t]]):this.eventBus.attach(this.rootNode,i[t]);return s}unbindEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)d.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]]);this.deleteCachedEvent(t),this._elementToUUID.delete(e),e.removeAttribute("data-"+c)}addEvents(e,t,n){n.setAttribute("data-"+c,e),this.cache[e]=t,this._elementToUUID.set(n,e);const s=Object.keys(t);for(let t=s.length;t--;)d.includes(s[t])?n.addEventListener(s[t],this.cache[e][s[t]]):this.eventBus.attach(this.rootNode,s[t])}removeIndividualEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)d.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]])}deleteCachedEvent(e){"string"==typeof e&&delete this.cache[e]}destroy(){this.rootNode&&(this.rootNode._literaljs_hasEvents=!1),this.cache={},this.rootNode=null,this.eventBus.reset()}}class a{constructor(){this.queue=[]}mounted(e){"object"==typeof e&&"function"==typeof e.m&&this.queue.push(e.m)}updated(e){"object"==typeof e&&"function"==typeof e.up&&this.queue.push(e.up)}unmounted(e){"object"==typeof e&&"function"==typeof e.un&&this.queue.push(e.un)}deleteState(e){"object"==typeof e&&"function"==typeof e.d&&this.queue.push(e.d)}flush(){let e;for(;e=this.queue.shift();)e()}clear(){this.queue=[]}}function l(t,n){if(null==t)return t;if("function"==typeof t.e){let e;e=t.a&&t.a.props?{...t.a.props}:t.a?{...t.a}:{},delete(t={e:t.e,a:{...t.a},c:t.c}).a.props,t=t.e(e)}if(t&&"function"==typeof t.bind){const s=t.bind(n);let i;try{i=s.render()}catch(e){console.error("Component render error:",e),i={e:"div",a:{class:"error-boundary"},c:[`${e.name}: ${e.message}`]}}if("object"==typeof i&&null!==i&&i instanceof e)i.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),i.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=i;else if("object"==typeof i&&null!==i){const n=new e(i.e,i.a,i.c);n.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),n.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=n}else t=i}if(t&&Array.isArray(t.c))for(let e=0,s=t.c.length;e<s;e++)t.c[e]=l(t.c[e],n);return t}class f{areNodesEqual(e,t){const n=typeof e;return n===typeof t&&("object"===n&&e.e===t.e&&e.id===t.id||("string"===n||"number"===n)&&e===t)}reconcileChildren(e,t,n,s){return Array.isArray(t)?this._hasKeys(t)||this._hasKeys(n)?this._reconcileKeyed(e,t,n,s):this._reconcileNonKeyed(e,t,n,s):0}_reconcileNonKeyed(e,t,n,s){const i=t.length;if(0===i){if(n)for(let e=0;e<n.length;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const o=e.childNodes;for(let r=0;r<i;r++)s.patch(e,o[r]||null,t[r],n?n[r]:void 0);return i}_hasKeys(e){if(!Array.isArray(e))return!1;for(let t=0,n=e.length;t<n;t++)if(e[t]&&e[t].a&&null!=e[t].a.key)return!0;return!1}_reconcileKeyed(e,t,n,s){const i=n?n.length:0,o=t.length;if(0===o){for(let e=0;e<i;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const r=Object.create(null),h=Object.create(null);for(let t=0;t<i;t++){const s=n[t].a?n[t].a.key:null,i=e.childNodes[t];null!=s&&i&&(r[s]=i,h[s]=n[t])}const d=new Array(o),c=new Array(o);for(let e=0;e<o;e++){const n=t[e].a?t[e].a.key:null;null!=n&&r[n]?(d[e]=r[n],c[e]=h[n],delete r[n]):(d[e]=null,c[e]=null)}for(const t in r){const n=r[t];n&&(s.patch(e,n,void 0,h[t]),n.remove())}let u=e.firstChild;for(let n=0;n<o;n++){const i=d[n];if(i&&i===u)u=u.nextSibling;else if(i)e.insertBefore(i,u);else{const i=s.createElement(t[n]);i&&e.insertBefore(i,u)}}for(;u;){const e=u.nextSibling;u.remove(),u=e}for(let n=0;n<o;n++)c[n]&&s.patch(e,e.childNodes[n],t[n],c[n]);return o}removeExtraChildren(e,t,n,s){const i=t.c?t.c.length:0;if(!(i<=n))for(let o=i;o-- >n;){const n=e.lastChild;n&&(s._unmountNodeAndChildren(t.c[o]),n.remove())}}}class p{constructor(e,t,n){this.generateTree=e||l,this.renderer=t,this.lifecycleQueue=n}mount(e,t,n){const s=this.generateTree(t(),n);return this.renderer.mount(e,s),this.lifecycleQueue.flush(),s}update(e,t,n,s){const i=this.generateTree(t(),n);return this.renderer.patch(e,e.firstChild,i,s),this.lifecycleQueue.flush(),i}unmount(e,t){t&&(this.renderer.unmount(e,t),this.lifecycleQueue.flush())}}class y{constructor(e,t){void 0===t&&(t="microtask"),this._renderFn=e,this._scheduler=t,this._scheduled=!1}schedule(){this._scheduled||(this._scheduled=!0,"microtask"===this._scheduler?Promise.resolve().then(()=>this._execute()):"sync"===this._scheduler&&this._execute())}_execute(){this._scheduled=!1,this._renderFn()}}class m{constructor(e,t){void 0===t&&(t={}),this.rootComponent=e,this.savedTree=e,this.currentTree=null,this.rootNode=null,this.stateManager=new o(t),this.lifecycleQueue=new a,this.eventManager=new u,this.renderer=new r(this.eventManager,this.lifecycleQueue,new f),this.mountOrchestrator=new p(l,this.renderer,this.lifecycleQueue),this.updateLoop=new y(()=>this.update(),"microtask"),this._boundSchedule=()=>this.updateLoop.schedule(),this.stateManager.subscribe(this._boundSchedule)}mount(e){if(this.rootNode=document.getElementById(e),!this.rootNode)throw new Error(`Cannot mount app: element with id "${e}" not found`);return this.eventManager.setRootNode(this.rootNode),this.currentTree=this.mountOrchestrator.mount(this.rootNode,this.savedTree,this.stateManager),this}unmount(){this.mountOrchestrator.unmount(this.rootNode,this.currentTree),this.eventManager.destroy(),this.stateManager.unsubscribe(()=>this.updateLoop.schedule()),this.rootNode&&(this.rootNode.innerHTML=""),this.currentTree=null,this.rootNode=null}scheduleUpdate(){this.updateLoop.schedule()}update(){this.rootNode&&this.savedTree&&(this.currentTree=this.mountOrchestrator.update(this.rootNode,this.savedTree,this.stateManager,this.currentTree))}getStore(){return this.stateManager.getStore()}setStore(e,t){this.stateManager.setStore(e,t)}}exports.App=m,exports.EventManager=u,exports.LifecycleQueue=a,exports.Renderer=r,exports.StateManager=o,exports.component=function(e){let t=void 0===e?{}:e,i=t.name,o=void 0===i?"":i,r=t.state,h=void 0===r?{}:r,d=t.mounted,c=void 0===d?function(){}:d,u=t.updated,a=void 0===u?function(){}:u,l=t.unmounted,f=void 0===l?function(){}:l,p=t.methods,y=void 0===p?function(){}:p,m=t.render,_=void 0===m?function(){}:m;const g=n(),v=new Map;return function(e){void 0===e&&(e={});const t=e.key||"__default__";if(!v.has(t)){const i=n(),r=o+(e.key?"_"+e.key:"");v.set(t,{definitionId:g,instanceId:i,key:`${g}_${i}_${r}`,_props:null,_cachedRender:null,bind(e){const t=new s(g,i,r,this._props,{state:h,mounted:c,updated:a,unmounted:f,methods:y,render:_},e);return t.bindMethods(y),t}})}const i=v.get(t);return i._props=e,i}},exports.createApp=function(e,t,n){const s=new m(e,n);return s.mount(t),s},exports.flatten=t,exports.generateTree=l,exports.generateUUID=n,exports.h=function(n,s){const i={};for(let e in s)i[e]=s[e];return new e(n,i,t([],[].slice.call(arguments,2)))},exports.isVNode=function(t){return t instanceof e||null!==t&&"object"==typeof t&&"e"in t},exports.render=function(e,t,n){void 0===n&&(n={});const s=new m(e,n);return s.mount(t),s};
|
|
1
|
+
class e{constructor(e,t,n){void 0===t&&(t={}),void 0===n&&(n=[]),this.e=e,this.a=t,this.c=n}withLifecycle(e){return e.mounted&&(this.m=e.mounted),e.updated&&(this.up=e.updated),e.unmounted&&(this.un=e.unmounted),e.deleteState&&(this.d=e.deleteState),this}withIdentity(e,t){return this.definitionId=e,this.instanceId=t,this.id=e+"_"+t,this}}function t(e,n){for(let s=0,i=n.length;s<i;s++)Array.isArray(n[s])?t(e,n[s]):null!=n[s]&&"boolean"!=typeof n[s]&&e.push(n[s]);return e}function n(){return Math.random().toString(36).substring(2)+(new Date).getTime().toString(36)}class s{constructor(e,t,n,s,i,o){this.definitionId=e,this.instanceId=t,this.name=n,this.key=`${e}_${t}_${n}`,this.props=s,this._stateManager=o,this._config=i,o.createState(this.key,i.state),this.mounted=i.mounted.bind(this),this.updated=i.updated.bind(this),this.unmounted=i.unmounted.bind(this),this.deleteState=()=>{this._stateManager.deleteState(this.key)},this._renderedVNode=null,this._previousProps=null;const r=i.render.bind(this);this.render=()=>{if(!this.shouldUpdate())return this._renderedVNode;const e=r();return this._renderedVNode=e,this._previousProps=this.props,e}}getStore(){return this._stateManager.getStore()}setStore(e,t){this._stateManager.setStore(e,t)}getState(){return this._stateManager.getState(this.key)}setState(e,t){this._stateManager.setState(this.key,e,t)}createState(){this._stateManager.createState(this.key,this._config.state)}deleteState(){this._stateManager.deleteState(this.key)}shouldUpdate(){return!this._previousProps||!function(e,t){if(e===t)return!0;if(!e||!t||"object"!=typeof e||"object"!=typeof t)return!1;const n=Object.keys(e),s=Object.keys(t);if(n.length!==s.length)return!1;for(let s=0;s<n.length;s++)if(e[n[s]]!==t[n[s]])return!1;return!0}(this.props,this._previousProps)}bindMethods(e){"function"==typeof e&&(e=e.bind(this)());for(let t in e)this[t]=e[t].bind(this)}}let i=0;function o(){i++}function r(e,t){for(let n in t)e[n]=t[n];return e}class h{constructor(e){void 0===e&&(e={}),this.store={...e},this.componentStates={},this.listeners=[]}subscribe(e){this.listeners.push(e)}unsubscribe(e){const t=this.listeners.indexOf(e);t>-1&&this.listeners.splice(t,1)}_notify(){for(let e=0;e<this.listeners.length;e++)this.listeners[e]()}getStore(){return{...this.store}}setStore(e,t){"function"==typeof e&&(e=e(this.store)),this.store=r(r({},this.store),e),this._notify(),"function"==typeof t&&t()}createState(e,t){e in this.componentStates||(this.componentStates[e]={...t})}getState(e){return{...this.componentStates[e]}}setState(e,t,n){"function"==typeof t&&(t=t(this.componentStates[e])),this.componentStates[e]=r(r({},this.componentStates[e]),t),this._notify(),"function"==typeof n&&n()}deleteState(e){delete this.componentStates[e]}reset(){this.store={},this.componentStates={},this.listeners=[]}}class d{constructor(e,t,n){this.eventManager=e,this.lifecycleQueue=t,this.diffEngine=n}mount(e,t){const n=this.createElement(t);n&&e.appendChild(n)}createElement(e){if(null==e)return document.createTextNode("");const t=typeof e;return"string"===t||"number"===t?document.createTextNode(e):"boolean"===t||"undefined"===t?document.createTextNode(""):"object"===t&&e.e?this._createElementNode(e):null}_createElementNode(e){const t=document.createElement(e.e);if("object"==typeof e.a){const n=Object.keys(e.a);for(let s=n.length;s--;)if("events"===n[s])e.eid=this.eventManager.bindEvents(t,e.a[n[s]]);else if("style"===n[s])this._addStyles(e.a[n[s]],t);else{if("key"===n[s])continue;t.setAttribute(n[s],e.a[n[s]])}}if(this.lifecycleQueue.mounted(e),Array.isArray(e.c))for(let n=0,s=e.c.length;n<s;n++){const s=this.createElement(e.c[n]);s&&t.appendChild(s)}return t}_addStyles(e,t){if(void 0===e)return;const n=Object.keys(e);for(let s=n.length;s--;)t.style[n[s]]=e[n[s]]}patch(e,t,n,s){const i=typeof n;if(void 0===s)this._appendChild(e,n);else if("undefined"===i)this._unmountNodeAndChildren(s),t&&t.remove();else if(this.diffEngine.areNodesEqual(n,s)){if("object"===i&&n.e){if(n===s)return;if(this._updateNodes(t,n,s),n.c!==s.c)if(this.diffEngine._hasKeys(n.c)||this.diffEngine._hasKeys(s.c))this.diffEngine.reconcileChildren(t,n.c,s.c,this);else{let e;for(let i=s.c?s.c.length:0;i--&&void 0===n.c[i];)e=t.lastChild,e&&(this._unmountNodeAndChildren(s.c[i]),e.remove());if(Array.isArray(n.c))for(let e=0,i=n.c.length;e<i;e++)this.patch(t,t.childNodes[e]||null,n.c[e],s.c?s.c[e]:void 0)}}}else if(!t||3!==t.nodeType||"string"!==i&&"number"!==i)this._unmountNodeAndChildren(s),t&&e.replaceChild(this.createElement(n),t);else{const e=String(n);t.textContent!==e&&(t.textContent=e)}}_appendChild(e,t){const n=this.createElement(t);n&&e.appendChild(n)}_updateNodes(e,t,n){if(this.lifecycleQueue.updated(t),t.a===n.a)return;if(!t.a||!n.a)return;const s=Object.keys(t.a);let i,o;for(let r=s.length;r--;)if(o=t.a[s[r]],i=n.a[s[r]],"style"===s[r]){if(this._stylesAreEqual(o,i))continue;e.removeAttribute(s[r]),this._addStyles(o,e)}else if("events"===s[r])this.eventManager.unbindEvents(e,n.eid),t.eid=this.eventManager.bindEvents(e,o);else{if("key"===s[r])continue;"value"===s[r]&&o!==i?e.value=o:void 0!==i&&o===i||e.setAttribute(s[r],o)}}_stylesAreEqual(e,t){if(e===t)return!0;const n=typeof e,s=typeof t;if("undefined"===n&&"undefined"===s)return!0;if("object"!==n||"object"!==s)return!1;const i=Object.keys(e),o=Object.keys(t);if(i.length!==o.length)return!1;for(let n=i.length;n--;)if(e[i[n]]!==t[i[n]])return!1;return!0}_unmountNodeAndChildren(e){if(null!=e&&(this.lifecycleQueue.unmounted(e),this.lifecycleQueue.deleteState(e),this.eventManager.deleteCachedEvent(e.eid),Array.isArray(e.c)))for(let t=e.c.length;t--;)this._unmountNodeAndChildren(e.c[t])}unmount(e,t){this._unmountNodeAndChildren(t),e&&(e.innerHTML="")}}class c{constructor(e,t,n){this._getCache=e,this._resolveUUID=t,this._elementToUUID=n,this._attachedTypes=new Set,this._rootNode=null}attach(e,t){this._attachedTypes.has(t)||(this._attachedTypes.add(t),this._rootNode=e,e._literaljs_hasEvents=!0,e.addEventListener(t,e=>this._handle(e)))}_handle(e){if(!this._rootNode||!this._rootNode._literaljs_hasEvents)return;let t=e.target;for(;t&&t!==this._rootNode;){let n;if(this._elementToUUID&&(n=this._elementToUUID.get(t))){const t=this._getCache(n);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}const s=this._resolveUUID(t);if("string"==typeof s){const t=this._getCache(s);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}t=t.parentNode}}reset(){this._attachedTypes.clear()}}const u=["abort","blur","error","focus","load","mouseenter","mouseleave","resize","scroll","unload"],a="eid";class l{constructor(){this.cache={},this.rootNode=null,this._elementToUUID=new WeakMap,this.eventBus=new c(e=>this.cache[e],e=>this.getEventUUID(e),this._elementToUUID)}setRootNode(e){this.rootNode=e}getEventUUID(e){if(!e||!e.parentNode)return;if("#document"===e.parentNode.nodeName)return;const t=e.getAttribute("data-"+a);return"string"==typeof t?t:this.getEventUUID(e.parentNode)}bindEvents(e,t){const s=n();e.setAttribute("data-"+a,s),this.cache[s]=t,this._elementToUUID.set(e,s);const i=Object.keys(t);for(let t=i.length;t--;)u.includes(i[t])?e.addEventListener(i[t],this.cache[s][i[t]]):this.eventBus.attach(this.rootNode,i[t]);return s}unbindEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)u.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]]);this.deleteCachedEvent(t),this._elementToUUID.delete(e),e.removeAttribute("data-"+a)}addEvents(e,t,n){n.setAttribute("data-"+a,e),this.cache[e]=t,this._elementToUUID.set(n,e);const s=Object.keys(t);for(let t=s.length;t--;)u.includes(s[t])?n.addEventListener(s[t],this.cache[e][s[t]]):this.eventBus.attach(this.rootNode,s[t])}removeIndividualEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)u.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]])}deleteCachedEvent(e){"string"==typeof e&&delete this.cache[e]}destroy(){this.rootNode&&(this.rootNode._literaljs_hasEvents=!1),this.cache={},this.rootNode=null,this.eventBus.reset()}}class f{constructor(){this.queue=[]}mounted(e){"object"==typeof e&&"function"==typeof e.m&&this.queue.push(e.m)}updated(e){"object"==typeof e&&"function"==typeof e.up&&this.queue.push(e.up)}unmounted(e){"object"==typeof e&&"function"==typeof e.un&&this.queue.push(e.un)}deleteState(e){"object"==typeof e&&"function"==typeof e.d&&this.queue.push(e.d)}flush(){let e;for(;e=this.queue.shift();)e()}clear(){this.queue=[]}}function p(t,n){if(null==t)return t;if("function"==typeof t.e){let e;e=t.a&&t.a.props?{...t.a.props}:t.a?{...t.a}:{},delete(t={e:t.e,a:{...t.a},c:t.c}).a.props,t=t.e(e)}if(t&&"function"==typeof t.bind){const s=t.bind(n);let i;try{i=s.render()}catch(e){console.error("Component render error:",e),i={e:"div",a:{class:"error-boundary"},c:[`${e.name}: ${e.message}`]}}if("object"==typeof i&&null!==i&&i instanceof e)i.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),i.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=i;else if("object"==typeof i&&null!==i){const n=new e(i.e,i.a,i.c);n.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),n.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=n}else t=i}if(t&&Array.isArray(t.c))for(let e=0,s=t.c.length;e<s;e++)t.c[e]=p(t.c[e],n);return t}class y{areNodesEqual(e,t){const n=typeof e;return n===typeof t&&("object"===n&&e&&t&&e.e===t.e&&e.id===t.id||("string"===n||"number"===n)&&e===t)}reconcileChildren(e,t,n,s){return Array.isArray(t)?this._hasKeys(t)||this._hasKeys(n)?this._reconcileKeyed(e,t,n,s):this._reconcileNonKeyed(e,t,n,s):0}_reconcileNonKeyed(e,t,n,s){const i=t.length;if(0===i){if(n)for(let e=0;e<n.length;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const o=e.childNodes;for(let r=0;r<i;r++)s.patch(e,o[r]||null,t[r],n?n[r]:void 0);return i}_hasKeys(e){if(!Array.isArray(e))return!1;for(let t=0,n=e.length;t<n;t++)if(e[t]&&e[t].a&&null!=e[t].a.key)return!0;return!1}_reconcileKeyed(e,t,n,s){const i=n?n.length:0,o=t.length;if(0===o){for(let e=0;e<i;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const r=Object.create(null),h=Object.create(null);for(let t=0;t<i;t++){const s=n[t].a?n[t].a.key:null,i=e.childNodes[t];null!=s&&i&&(r[s]=i,h[s]=n[t])}const d=new Array(o),c=new Array(o);for(let e=0;e<o;e++){const n=t[e].a?t[e].a.key:null;null!=n&&r[n]?(d[e]=r[n],c[e]=h[n],delete r[n]):(d[e]=null,c[e]=null)}for(const t in r){const n=r[t];n&&(s.patch(e,n,void 0,h[t]),n.remove())}let u=e.firstChild;for(let n=0;n<o;n++){const i=d[n];if(i&&i===u)u=u.nextSibling;else if(i)e.insertBefore(i,u);else{const i=s.createElement(t[n]);i&&e.insertBefore(i,u)}}for(;u;){const e=u.nextSibling;u.remove(),u=e}for(let n=0;n<o;n++)c[n]&&s.patch(e,e.childNodes[n],t[n],c[n]);return o}removeExtraChildren(e,t,n,s){const i=t.c?t.c.length:0;if(!(i<=n))for(let o=i;o-- >n;){const n=e.lastChild;n&&(s._unmountNodeAndChildren(t.c[o]),n.remove())}}}class m{constructor(e,t,n){this.generateTree=e||p,this.renderer=t,this.lifecycleQueue=n}mount(e,t,n){o();const s=this.generateTree(t(),n);return this.renderer.mount(e,s),this.lifecycleQueue.flush(),s}update(e,t,n,s){o();const i=this.generateTree(t(),n);return this.renderer.patch(e,e.firstChild,i,s),this.lifecycleQueue.flush(),i}unmount(e,t){t&&(this.renderer.unmount(e,t),this.lifecycleQueue.flush())}}class _{constructor(e,t){void 0===t&&(t="microtask"),this._renderFn=e,this._scheduler=t,this._scheduled=!1}schedule(){this._scheduled||(this._scheduled=!0,"microtask"===this._scheduler?Promise.resolve().then(()=>this._execute()):"sync"===this._scheduler&&this._execute())}_execute(){this._scheduled=!1,this._renderFn()}}class g{constructor(e,t){void 0===t&&(t={}),this.rootComponent=e,this.savedTree=e,this.currentTree=null,this.rootNode=null,this.stateManager=new h(t),this.lifecycleQueue=new f,this.eventManager=new l,this.renderer=new d(this.eventManager,this.lifecycleQueue,new y),this.mountOrchestrator=new m(p,this.renderer,this.lifecycleQueue),this.updateLoop=new _(()=>this.update(),"microtask"),this._boundSchedule=()=>this.updateLoop.schedule(),this.stateManager.subscribe(this._boundSchedule)}mount(e){if(this.rootNode=document.getElementById(e),!this.rootNode)throw new Error(`Cannot mount app: element with id "${e}" not found`);return this.eventManager.setRootNode(this.rootNode),this.currentTree=this.mountOrchestrator.mount(this.rootNode,this.savedTree,this.stateManager),this}unmount(){this.mountOrchestrator.unmount(this.rootNode,this.currentTree),this.eventManager.destroy(),this.stateManager.unsubscribe(()=>this.updateLoop.schedule()),this.rootNode&&(this.rootNode.innerHTML=""),this.currentTree=null,this.rootNode=null}scheduleUpdate(){this.updateLoop.schedule()}update(){this.rootNode&&this.savedTree&&(this.currentTree=this.mountOrchestrator.update(this.rootNode,this.savedTree,this.stateManager,this.currentTree))}getStore(){return this.stateManager.getStore()}setStore(e,t){this.stateManager.setStore(e,t)}}exports.App=g,exports.EventManager=l,exports.LifecycleQueue=f,exports.Renderer=d,exports.StateManager=h,exports.advanceRenderCycle=o,exports.component=function(e){let t=void 0===e?{}:e,o=t.name,r=void 0===o?"":o,h=t.state,d=void 0===h?{}:h,c=t.mounted,u=void 0===c?function(){}:c,a=t.updated,l=void 0===a?function(){}:a,f=t.unmounted,p=void 0===f?function(){}:f,y=t.methods,m=void 0===y?function(){}:y,_=t.render,g=void 0===_?function(){}:_;const v=n(),b=new Map;let N=0,S=-1;return function(e){void 0===e&&(e={}),S!==i&&(N=0,S=i);const t=null!=e.key?String(e.key):`__auto_${N++}__`;if(!b.has(t)){const i=n(),o=r+(null!=e.key?"_"+String(e.key):"");b.set(t,{definitionId:v,instanceId:i,key:`${v}_${i}_${o}`,_props:null,_cachedRender:null,bind(e){const t=new s(v,i,o,this._props,{state:d,mounted:u,updated:l,unmounted:p,methods:m,render:g},e);return t.bindMethods(m),t}})}const o=b.get(t);return o._props=e,o}},exports.createApp=function(e,t,n){const s=new g(e,n);return s.mount(t),s},exports.flatten=t,exports.generateTree=p,exports.generateUUID=n,exports.h=function(n,s){const i={};for(let e in s)i[e]=s[e];return new e(n,i,t([],[].slice.call(arguments,2)))},exports.isVNode=function(t){return t instanceof e||null!==t&&"object"==typeof t&&"e"in t},exports.render=function(e,t,n){void 0===n&&(n={});const s=new g(e,n);return s.mount(t),s};
|
package/build/index.m.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class e{constructor(e,t,n){void 0===t&&(t={}),void 0===n&&(n=[]),this.e=e,this.a=t,this.c=n}withLifecycle(e){return e.mounted&&(this.m=e.mounted),e.updated&&(this.up=e.updated),e.unmounted&&(this.un=e.unmounted),e.deleteState&&(this.d=e.deleteState),this}withIdentity(e,t){return this.definitionId=e,this.instanceId=t,this.id=e+"_"+t,this}}function t(e,n){for(let s=0,i=n.length;s<i;s++)Array.isArray(n[s])?t(e,n[s]):e.push(n[s]);return e}function n(n,s){const i={};for(let e in s)i[e]=s[e];return new e(n,i,t([],[].slice.call(arguments,2)))}function s(t){return t instanceof e||null!==t&&"object"==typeof t&&"e"in t}function i(){return Math.random().toString(36).substring(2)+(new Date).getTime().toString(36)}class o{constructor(e,t,n,s,i,o){this.definitionId=e,this.instanceId=t,this.name=n,this.key=`${e}_${t}_${n}`,this.props=s,this._stateManager=o,this._config=i,o.createState(this.key,i.state),this.mounted=i.mounted.bind(this),this.updated=i.updated.bind(this),this.unmounted=i.unmounted.bind(this),this.deleteState=()=>{this._stateManager.deleteState(this.key)},this._renderedVNode=null,this._previousProps=null;const r=i.render.bind(this);this.render=()=>{if(!this.shouldUpdate())return this._renderedVNode;const e=r();return this._renderedVNode=e,this._previousProps=this.props,e}}getStore(){return this._stateManager.getStore()}setStore(e,t){this._stateManager.setStore(e,t)}getState(){return this._stateManager.getState(this.key)}setState(e,t){this._stateManager.setState(this.key,e,t)}createState(){this._stateManager.createState(this.key,this._config.state)}deleteState(){this._stateManager.deleteState(this.key)}shouldUpdate(){return!this._previousProps||!function(e,t){if(e===t)return!0;if(!e||!t||"object"!=typeof e||"object"!=typeof t)return!1;const n=Object.keys(e),s=Object.keys(t);if(n.length!==s.length)return!1;for(let s=0;s<n.length;s++)if(e[n[s]]!==t[n[s]])return!1;return!0}(this.props,this._previousProps)}bindMethods(e){"function"==typeof e&&(e=e.bind(this)());for(let t in e)this[t]=e[t].bind(this)}}function r(e){let t=void 0===e?{}:e,n=t.name,s=void 0===n?"":n,r=t.state,h=void 0===r?{}:r,d=t.mounted,c=void 0===d?function(){}:d,u=t.updated,a=void 0===u?function(){}:u,l=t.unmounted,f=void 0===l?function(){}:l,p=t.methods,y=void 0===p?function(){}:p,m=t.render,_=void 0===m?function(){}:m;const g=i(),v=new Map;return function(e){void 0===e&&(e={});const t=e.key||"__default__";if(!v.has(t)){const n=i(),r=s+(e.key?"_"+e.key:"");v.set(t,{definitionId:g,instanceId:n,key:`${g}_${n}_${r}`,_props:null,_cachedRender:null,bind(e){const t=new o(g,n,r,this._props,{state:h,mounted:c,updated:a,unmounted:f,methods:y,render:_},e);return t.bindMethods(y),t}})}const n=v.get(t);return n._props=e,n}}function h(e,t){for(let n in t)e[n]=t[n];return e}class d{constructor(e){void 0===e&&(e={}),this.store={...e},this.componentStates={},this.listeners=[]}subscribe(e){this.listeners.push(e)}unsubscribe(e){const t=this.listeners.indexOf(e);t>-1&&this.listeners.splice(t,1)}_notify(){for(let e=0;e<this.listeners.length;e++)this.listeners[e]()}getStore(){return{...this.store}}setStore(e,t){"function"==typeof e&&(e=e(this.store)),this.store=h(h({},this.store),e),this._notify(),"function"==typeof t&&t()}createState(e,t){e in this.componentStates||(this.componentStates[e]={...t})}getState(e){return{...this.componentStates[e]}}setState(e,t,n){"function"==typeof t&&(t=t(this.componentStates[e])),this.componentStates[e]=h(h({},this.componentStates[e]),t),this._notify(),"function"==typeof n&&n()}deleteState(e){delete this.componentStates[e]}reset(){this.store={},this.componentStates={},this.listeners=[]}}class c{constructor(e,t,n){this.eventManager=e,this.lifecycleQueue=t,this.diffEngine=n}mount(e,t){const n=this.createElement(t);n&&e.appendChild(n)}createElement(e){if(null==e)return document.createTextNode("");const t=typeof e;return"string"===t||"number"===t?document.createTextNode(e):"boolean"===t||"undefined"===t?document.createTextNode(""):"object"===t&&e.e?this._createElementNode(e):null}_createElementNode(e){const t=document.createElement(e.e);if("object"==typeof e.a){const n=Object.keys(e.a);for(let s=n.length;s--;)if("events"===n[s])e.eid=this.eventManager.bindEvents(t,e.a[n[s]]);else if("style"===n[s])this._addStyles(e.a[n[s]],t);else{if("key"===n[s])continue;t.setAttribute(n[s],e.a[n[s]])}}if(this.lifecycleQueue.mounted(e),Array.isArray(e.c))for(let n=0,s=e.c.length;n<s;n++){const s=this.createElement(e.c[n]);s&&t.appendChild(s)}return t}_addStyles(e,t){if(void 0===e)return;const n=Object.keys(e);for(let s=n.length;s--;)t.style[n[s]]=e[n[s]]}patch(e,t,n,s){const i=typeof n;if(void 0===s)this._appendChild(e,n);else if("undefined"===i)this._unmountNodeAndChildren(s),t&&t.remove();else if(this.diffEngine.areNodesEqual(n,s)){if("object"===i&&n.e){if(n===s)return;if(this._updateNodes(t,n,s),n.c!==s.c)if(this.diffEngine._hasKeys(n.c)||this.diffEngine._hasKeys(s.c))this.diffEngine.reconcileChildren(t,n.c,s.c,this);else{let e;for(let i=s.c?s.c.length:0;i--&&void 0===n.c[i];)e=t.lastChild,e&&(this._unmountNodeAndChildren(s.c[i]),e.remove());if(Array.isArray(n.c))for(let e=0,i=n.c.length;e<i;e++)this.patch(t,t.childNodes[e]||null,n.c[e],s.c?s.c[e]:void 0)}}}else if(!t||3!==t.nodeType||"string"!==i&&"number"!==i)this._unmountNodeAndChildren(s),t&&e.replaceChild(this.createElement(n),t);else{const e=String(n);t.textContent!==e&&(t.textContent=e)}}_appendChild(e,t){const n=this.createElement(t);n&&e.appendChild(n)}_updateNodes(e,t,n){if(this.lifecycleQueue.updated(t),t.a===n.a)return;if(!t.a||!n.a)return;const s=Object.keys(t.a);let i,o;for(let r=s.length;r--;)if(o=t.a[s[r]],i=n.a[s[r]],"style"===s[r]){if(this._stylesAreEqual(o,i))continue;e.removeAttribute(s[r]),this._addStyles(o,e)}else if("events"===s[r])this.eventManager.unbindEvents(e,n.eid),t.eid=this.eventManager.bindEvents(e,o);else{if("key"===s[r])continue;"value"===s[r]&&o!==i?e.value=o:void 0!==i&&o===i||e.setAttribute(s[r],o)}}_stylesAreEqual(e,t){if(e===t)return!0;const n=typeof e,s=typeof t;if("undefined"===n&&"undefined"===s)return!0;if("object"!==n||"object"!==s)return!1;const i=Object.keys(e),o=Object.keys(t);if(i.length!==o.length)return!1;for(let n=i.length;n--;)if(e[i[n]]!==t[i[n]])return!1;return!0}_unmountNodeAndChildren(e){if(null!=e&&(this.lifecycleQueue.unmounted(e),this.lifecycleQueue.deleteState(e),this.eventManager.deleteCachedEvent(e.eid),Array.isArray(e.c)))for(let t=e.c.length;t--;)this._unmountNodeAndChildren(e.c[t])}unmount(e,t){this._unmountNodeAndChildren(t),e&&(e.innerHTML="")}}class u{constructor(e,t,n){this._getCache=e,this._resolveUUID=t,this._elementToUUID=n,this._attachedTypes=new Set,this._rootNode=null}attach(e,t){this._attachedTypes.has(t)||(this._attachedTypes.add(t),this._rootNode=e,e._literaljs_hasEvents=!0,e.addEventListener(t,e=>this._handle(e)))}_handle(e){if(!this._rootNode||!this._rootNode._literaljs_hasEvents)return;let t=e.target;for(;t&&t!==this._rootNode;){let n;if(this._elementToUUID&&(n=this._elementToUUID.get(t))){const t=this._getCache(n);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}const s=this._resolveUUID(t);if("string"==typeof s){const t=this._getCache(s);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}t=t.parentNode}}reset(){this._attachedTypes.clear()}}const a=["abort","blur","error","focus","load","mouseenter","mouseleave","resize","scroll","unload"],l="eid";class f{constructor(){this.cache={},this.rootNode=null,this._elementToUUID=new WeakMap,this.eventBus=new u(e=>this.cache[e],e=>this.getEventUUID(e),this._elementToUUID)}setRootNode(e){this.rootNode=e}getEventUUID(e){if(!e||!e.parentNode)return;if("#document"===e.parentNode.nodeName)return;const t=e.getAttribute("data-"+l);return"string"==typeof t?t:this.getEventUUID(e.parentNode)}bindEvents(e,t){const n=i();e.setAttribute("data-"+l,n),this.cache[n]=t,this._elementToUUID.set(e,n);const s=Object.keys(t);for(let t=s.length;t--;)a.includes(s[t])?e.addEventListener(s[t],this.cache[n][s[t]]):this.eventBus.attach(this.rootNode,s[t]);return n}unbindEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)a.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]]);this.deleteCachedEvent(t),this._elementToUUID.delete(e),e.removeAttribute("data-"+l)}addEvents(e,t,n){n.setAttribute("data-"+l,e),this.cache[e]=t,this._elementToUUID.set(n,e);const s=Object.keys(t);for(let t=s.length;t--;)a.includes(s[t])?n.addEventListener(s[t],this.cache[e][s[t]]):this.eventBus.attach(this.rootNode,s[t])}removeIndividualEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)a.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]])}deleteCachedEvent(e){"string"==typeof e&&delete this.cache[e]}destroy(){this.rootNode&&(this.rootNode._literaljs_hasEvents=!1),this.cache={},this.rootNode=null,this.eventBus.reset()}}class p{constructor(){this.queue=[]}mounted(e){"object"==typeof e&&"function"==typeof e.m&&this.queue.push(e.m)}updated(e){"object"==typeof e&&"function"==typeof e.up&&this.queue.push(e.up)}unmounted(e){"object"==typeof e&&"function"==typeof e.un&&this.queue.push(e.un)}deleteState(e){"object"==typeof e&&"function"==typeof e.d&&this.queue.push(e.d)}flush(){let e;for(;e=this.queue.shift();)e()}clear(){this.queue=[]}}function y(t,n){if(null==t)return t;if("function"==typeof t.e){let e;e=t.a&&t.a.props?{...t.a.props}:t.a?{...t.a}:{},delete(t={e:t.e,a:{...t.a},c:t.c}).a.props,t=t.e(e)}if(t&&"function"==typeof t.bind){const s=t.bind(n);let i;try{i=s.render()}catch(e){console.error("Component render error:",e),i={e:"div",a:{class:"error-boundary"},c:[`${e.name}: ${e.message}`]}}if("object"==typeof i&&null!==i&&i instanceof e)i.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),i.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=i;else if("object"==typeof i&&null!==i){const n=new e(i.e,i.a,i.c);n.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),n.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=n}else t=i}if(t&&Array.isArray(t.c))for(let e=0,s=t.c.length;e<s;e++)t.c[e]=y(t.c[e],n);return t}class m{areNodesEqual(e,t){const n=typeof e;return n===typeof t&&("object"===n&&e.e===t.e&&e.id===t.id||("string"===n||"number"===n)&&e===t)}reconcileChildren(e,t,n,s){return Array.isArray(t)?this._hasKeys(t)||this._hasKeys(n)?this._reconcileKeyed(e,t,n,s):this._reconcileNonKeyed(e,t,n,s):0}_reconcileNonKeyed(e,t,n,s){const i=t.length;if(0===i){if(n)for(let e=0;e<n.length;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const o=e.childNodes;for(let r=0;r<i;r++)s.patch(e,o[r]||null,t[r],n?n[r]:void 0);return i}_hasKeys(e){if(!Array.isArray(e))return!1;for(let t=0,n=e.length;t<n;t++)if(e[t]&&e[t].a&&null!=e[t].a.key)return!0;return!1}_reconcileKeyed(e,t,n,s){const i=n?n.length:0,o=t.length;if(0===o){for(let e=0;e<i;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const r=Object.create(null),h=Object.create(null);for(let t=0;t<i;t++){const s=n[t].a?n[t].a.key:null,i=e.childNodes[t];null!=s&&i&&(r[s]=i,h[s]=n[t])}const d=new Array(o),c=new Array(o);for(let e=0;e<o;e++){const n=t[e].a?t[e].a.key:null;null!=n&&r[n]?(d[e]=r[n],c[e]=h[n],delete r[n]):(d[e]=null,c[e]=null)}for(const t in r){const n=r[t];n&&(s.patch(e,n,void 0,h[t]),n.remove())}let u=e.firstChild;for(let n=0;n<o;n++){const i=d[n];if(i&&i===u)u=u.nextSibling;else if(i)e.insertBefore(i,u);else{const i=s.createElement(t[n]);i&&e.insertBefore(i,u)}}for(;u;){const e=u.nextSibling;u.remove(),u=e}for(let n=0;n<o;n++)c[n]&&s.patch(e,e.childNodes[n],t[n],c[n]);return o}removeExtraChildren(e,t,n,s){const i=t.c?t.c.length:0;if(!(i<=n))for(let o=i;o-- >n;){const n=e.lastChild;n&&(s._unmountNodeAndChildren(t.c[o]),n.remove())}}}class _{constructor(e,t,n){this.generateTree=e||y,this.renderer=t,this.lifecycleQueue=n}mount(e,t,n){const s=this.generateTree(t(),n);return this.renderer.mount(e,s),this.lifecycleQueue.flush(),s}update(e,t,n,s){const i=this.generateTree(t(),n);return this.renderer.patch(e,e.firstChild,i,s),this.lifecycleQueue.flush(),i}unmount(e,t){t&&(this.renderer.unmount(e,t),this.lifecycleQueue.flush())}}class g{constructor(e,t){void 0===t&&(t="microtask"),this._renderFn=e,this._scheduler=t,this._scheduled=!1}schedule(){this._scheduled||(this._scheduled=!0,"microtask"===this._scheduler?Promise.resolve().then(()=>this._execute()):"sync"===this._scheduler&&this._execute())}_execute(){this._scheduled=!1,this._renderFn()}}class v{constructor(e,t){void 0===t&&(t={}),this.rootComponent=e,this.savedTree=e,this.currentTree=null,this.rootNode=null,this.stateManager=new d(t),this.lifecycleQueue=new p,this.eventManager=new f,this.renderer=new c(this.eventManager,this.lifecycleQueue,new m),this.mountOrchestrator=new _(y,this.renderer,this.lifecycleQueue),this.updateLoop=new g(()=>this.update(),"microtask"),this._boundSchedule=()=>this.updateLoop.schedule(),this.stateManager.subscribe(this._boundSchedule)}mount(e){if(this.rootNode=document.getElementById(e),!this.rootNode)throw new Error(`Cannot mount app: element with id "${e}" not found`);return this.eventManager.setRootNode(this.rootNode),this.currentTree=this.mountOrchestrator.mount(this.rootNode,this.savedTree,this.stateManager),this}unmount(){this.mountOrchestrator.unmount(this.rootNode,this.currentTree),this.eventManager.destroy(),this.stateManager.unsubscribe(()=>this.updateLoop.schedule()),this.rootNode&&(this.rootNode.innerHTML=""),this.currentTree=null,this.rootNode=null}scheduleUpdate(){this.updateLoop.schedule()}update(){this.rootNode&&this.savedTree&&(this.currentTree=this.mountOrchestrator.update(this.rootNode,this.savedTree,this.stateManager,this.currentTree))}getStore(){return this.stateManager.getStore()}setStore(e,t){this.stateManager.setStore(e,t)}}function b(e,t,n){const s=new v(e,n);return s.mount(t),s}function N(e,t,n){void 0===n&&(n={});const s=new v(e,n);return s.mount(t),s}export{v as App,f as EventManager,p as LifecycleQueue,c as Renderer,d as StateManager,r as component,b as createApp,t as flatten,y as generateTree,i as generateUUID,n as h,s as isVNode,N as render};
|
|
1
|
+
class e{constructor(e,t,n){void 0===t&&(t={}),void 0===n&&(n=[]),this.e=e,this.a=t,this.c=n}withLifecycle(e){return e.mounted&&(this.m=e.mounted),e.updated&&(this.up=e.updated),e.unmounted&&(this.un=e.unmounted),e.deleteState&&(this.d=e.deleteState),this}withIdentity(e,t){return this.definitionId=e,this.instanceId=t,this.id=e+"_"+t,this}}function t(e,n){for(let s=0,i=n.length;s<i;s++)Array.isArray(n[s])?t(e,n[s]):null!=n[s]&&"boolean"!=typeof n[s]&&e.push(n[s]);return e}function n(n,s){const i={};for(let e in s)i[e]=s[e];return new e(n,i,t([],[].slice.call(arguments,2)))}function s(t){return t instanceof e||null!==t&&"object"==typeof t&&"e"in t}function i(){return Math.random().toString(36).substring(2)+(new Date).getTime().toString(36)}class o{constructor(e,t,n,s,i,o){this.definitionId=e,this.instanceId=t,this.name=n,this.key=`${e}_${t}_${n}`,this.props=s,this._stateManager=o,this._config=i,o.createState(this.key,i.state),this.mounted=i.mounted.bind(this),this.updated=i.updated.bind(this),this.unmounted=i.unmounted.bind(this),this.deleteState=()=>{this._stateManager.deleteState(this.key)},this._renderedVNode=null,this._previousProps=null;const r=i.render.bind(this);this.render=()=>{if(!this.shouldUpdate())return this._renderedVNode;const e=r();return this._renderedVNode=e,this._previousProps=this.props,e}}getStore(){return this._stateManager.getStore()}setStore(e,t){this._stateManager.setStore(e,t)}getState(){return this._stateManager.getState(this.key)}setState(e,t){this._stateManager.setState(this.key,e,t)}createState(){this._stateManager.createState(this.key,this._config.state)}deleteState(){this._stateManager.deleteState(this.key)}shouldUpdate(){return!this._previousProps||!function(e,t){if(e===t)return!0;if(!e||!t||"object"!=typeof e||"object"!=typeof t)return!1;const n=Object.keys(e),s=Object.keys(t);if(n.length!==s.length)return!1;for(let s=0;s<n.length;s++)if(e[n[s]]!==t[n[s]])return!1;return!0}(this.props,this._previousProps)}bindMethods(e){"function"==typeof e&&(e=e.bind(this)());for(let t in e)this[t]=e[t].bind(this)}}let r=0;function h(){r++}function d(e){let t=void 0===e?{}:e,n=t.name,s=void 0===n?"":n,h=t.state,d=void 0===h?{}:h,u=t.mounted,c=void 0===u?function(){}:u,a=t.updated,l=void 0===a?function(){}:a,f=t.unmounted,p=void 0===f?function(){}:f,y=t.methods,m=void 0===y?function(){}:y,_=t.render,g=void 0===_?function(){}:_;const v=i(),b=new Map;let N=0,S=-1;return function(e){void 0===e&&(e={}),S!==r&&(N=0,S=r);const t=null!=e.key?String(e.key):`__auto_${N++}__`;if(!b.has(t)){const n=i(),r=s+(null!=e.key?"_"+String(e.key):"");b.set(t,{definitionId:v,instanceId:n,key:`${v}_${n}_${r}`,_props:null,_cachedRender:null,bind(e){const t=new o(v,n,r,this._props,{state:d,mounted:c,updated:l,unmounted:p,methods:m,render:g},e);return t.bindMethods(m),t}})}const n=b.get(t);return n._props=e,n}}function u(e,t){for(let n in t)e[n]=t[n];return e}class c{constructor(e){void 0===e&&(e={}),this.store={...e},this.componentStates={},this.listeners=[]}subscribe(e){this.listeners.push(e)}unsubscribe(e){const t=this.listeners.indexOf(e);t>-1&&this.listeners.splice(t,1)}_notify(){for(let e=0;e<this.listeners.length;e++)this.listeners[e]()}getStore(){return{...this.store}}setStore(e,t){"function"==typeof e&&(e=e(this.store)),this.store=u(u({},this.store),e),this._notify(),"function"==typeof t&&t()}createState(e,t){e in this.componentStates||(this.componentStates[e]={...t})}getState(e){return{...this.componentStates[e]}}setState(e,t,n){"function"==typeof t&&(t=t(this.componentStates[e])),this.componentStates[e]=u(u({},this.componentStates[e]),t),this._notify(),"function"==typeof n&&n()}deleteState(e){delete this.componentStates[e]}reset(){this.store={},this.componentStates={},this.listeners=[]}}class a{constructor(e,t,n){this.eventManager=e,this.lifecycleQueue=t,this.diffEngine=n}mount(e,t){const n=this.createElement(t);n&&e.appendChild(n)}createElement(e){if(null==e)return document.createTextNode("");const t=typeof e;return"string"===t||"number"===t?document.createTextNode(e):"boolean"===t||"undefined"===t?document.createTextNode(""):"object"===t&&e.e?this._createElementNode(e):null}_createElementNode(e){const t=document.createElement(e.e);if("object"==typeof e.a){const n=Object.keys(e.a);for(let s=n.length;s--;)if("events"===n[s])e.eid=this.eventManager.bindEvents(t,e.a[n[s]]);else if("style"===n[s])this._addStyles(e.a[n[s]],t);else{if("key"===n[s])continue;t.setAttribute(n[s],e.a[n[s]])}}if(this.lifecycleQueue.mounted(e),Array.isArray(e.c))for(let n=0,s=e.c.length;n<s;n++){const s=this.createElement(e.c[n]);s&&t.appendChild(s)}return t}_addStyles(e,t){if(void 0===e)return;const n=Object.keys(e);for(let s=n.length;s--;)t.style[n[s]]=e[n[s]]}patch(e,t,n,s){const i=typeof n;if(void 0===s)this._appendChild(e,n);else if("undefined"===i)this._unmountNodeAndChildren(s),t&&t.remove();else if(this.diffEngine.areNodesEqual(n,s)){if("object"===i&&n.e){if(n===s)return;if(this._updateNodes(t,n,s),n.c!==s.c)if(this.diffEngine._hasKeys(n.c)||this.diffEngine._hasKeys(s.c))this.diffEngine.reconcileChildren(t,n.c,s.c,this);else{let e;for(let i=s.c?s.c.length:0;i--&&void 0===n.c[i];)e=t.lastChild,e&&(this._unmountNodeAndChildren(s.c[i]),e.remove());if(Array.isArray(n.c))for(let e=0,i=n.c.length;e<i;e++)this.patch(t,t.childNodes[e]||null,n.c[e],s.c?s.c[e]:void 0)}}}else if(!t||3!==t.nodeType||"string"!==i&&"number"!==i)this._unmountNodeAndChildren(s),t&&e.replaceChild(this.createElement(n),t);else{const e=String(n);t.textContent!==e&&(t.textContent=e)}}_appendChild(e,t){const n=this.createElement(t);n&&e.appendChild(n)}_updateNodes(e,t,n){if(this.lifecycleQueue.updated(t),t.a===n.a)return;if(!t.a||!n.a)return;const s=Object.keys(t.a);let i,o;for(let r=s.length;r--;)if(o=t.a[s[r]],i=n.a[s[r]],"style"===s[r]){if(this._stylesAreEqual(o,i))continue;e.removeAttribute(s[r]),this._addStyles(o,e)}else if("events"===s[r])this.eventManager.unbindEvents(e,n.eid),t.eid=this.eventManager.bindEvents(e,o);else{if("key"===s[r])continue;"value"===s[r]&&o!==i?e.value=o:void 0!==i&&o===i||e.setAttribute(s[r],o)}}_stylesAreEqual(e,t){if(e===t)return!0;const n=typeof e,s=typeof t;if("undefined"===n&&"undefined"===s)return!0;if("object"!==n||"object"!==s)return!1;const i=Object.keys(e),o=Object.keys(t);if(i.length!==o.length)return!1;for(let n=i.length;n--;)if(e[i[n]]!==t[i[n]])return!1;return!0}_unmountNodeAndChildren(e){if(null!=e&&(this.lifecycleQueue.unmounted(e),this.lifecycleQueue.deleteState(e),this.eventManager.deleteCachedEvent(e.eid),Array.isArray(e.c)))for(let t=e.c.length;t--;)this._unmountNodeAndChildren(e.c[t])}unmount(e,t){this._unmountNodeAndChildren(t),e&&(e.innerHTML="")}}class l{constructor(e,t,n){this._getCache=e,this._resolveUUID=t,this._elementToUUID=n,this._attachedTypes=new Set,this._rootNode=null}attach(e,t){this._attachedTypes.has(t)||(this._attachedTypes.add(t),this._rootNode=e,e._literaljs_hasEvents=!0,e.addEventListener(t,e=>this._handle(e)))}_handle(e){if(!this._rootNode||!this._rootNode._literaljs_hasEvents)return;let t=e.target;for(;t&&t!==this._rootNode;){let n;if(this._elementToUUID&&(n=this._elementToUUID.get(t))){const t=this._getCache(n);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}const s=this._resolveUUID(t);if("string"==typeof s){const t=this._getCache(s);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}t=t.parentNode}}reset(){this._attachedTypes.clear()}}const f=["abort","blur","error","focus","load","mouseenter","mouseleave","resize","scroll","unload"],p="eid";class y{constructor(){this.cache={},this.rootNode=null,this._elementToUUID=new WeakMap,this.eventBus=new l(e=>this.cache[e],e=>this.getEventUUID(e),this._elementToUUID)}setRootNode(e){this.rootNode=e}getEventUUID(e){if(!e||!e.parentNode)return;if("#document"===e.parentNode.nodeName)return;const t=e.getAttribute("data-"+p);return"string"==typeof t?t:this.getEventUUID(e.parentNode)}bindEvents(e,t){const n=i();e.setAttribute("data-"+p,n),this.cache[n]=t,this._elementToUUID.set(e,n);const s=Object.keys(t);for(let t=s.length;t--;)f.includes(s[t])?e.addEventListener(s[t],this.cache[n][s[t]]):this.eventBus.attach(this.rootNode,s[t]);return n}unbindEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)f.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]]);this.deleteCachedEvent(t),this._elementToUUID.delete(e),e.removeAttribute("data-"+p)}addEvents(e,t,n){n.setAttribute("data-"+p,e),this.cache[e]=t,this._elementToUUID.set(n,e);const s=Object.keys(t);for(let t=s.length;t--;)f.includes(s[t])?n.addEventListener(s[t],this.cache[e][s[t]]):this.eventBus.attach(this.rootNode,s[t])}removeIndividualEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)f.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]])}deleteCachedEvent(e){"string"==typeof e&&delete this.cache[e]}destroy(){this.rootNode&&(this.rootNode._literaljs_hasEvents=!1),this.cache={},this.rootNode=null,this.eventBus.reset()}}class m{constructor(){this.queue=[]}mounted(e){"object"==typeof e&&"function"==typeof e.m&&this.queue.push(e.m)}updated(e){"object"==typeof e&&"function"==typeof e.up&&this.queue.push(e.up)}unmounted(e){"object"==typeof e&&"function"==typeof e.un&&this.queue.push(e.un)}deleteState(e){"object"==typeof e&&"function"==typeof e.d&&this.queue.push(e.d)}flush(){let e;for(;e=this.queue.shift();)e()}clear(){this.queue=[]}}function _(t,n){if(null==t)return t;if("function"==typeof t.e){let e;e=t.a&&t.a.props?{...t.a.props}:t.a?{...t.a}:{},delete(t={e:t.e,a:{...t.a},c:t.c}).a.props,t=t.e(e)}if(t&&"function"==typeof t.bind){const s=t.bind(n);let i;try{i=s.render()}catch(e){console.error("Component render error:",e),i={e:"div",a:{class:"error-boundary"},c:[`${e.name}: ${e.message}`]}}if("object"==typeof i&&null!==i&&i instanceof e)i.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),i.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=i;else if("object"==typeof i&&null!==i){const n=new e(i.e,i.a,i.c);n.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),n.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=n}else t=i}if(t&&Array.isArray(t.c))for(let e=0,s=t.c.length;e<s;e++)t.c[e]=_(t.c[e],n);return t}class g{areNodesEqual(e,t){const n=typeof e;return n===typeof t&&("object"===n&&e&&t&&e.e===t.e&&e.id===t.id||("string"===n||"number"===n)&&e===t)}reconcileChildren(e,t,n,s){return Array.isArray(t)?this._hasKeys(t)||this._hasKeys(n)?this._reconcileKeyed(e,t,n,s):this._reconcileNonKeyed(e,t,n,s):0}_reconcileNonKeyed(e,t,n,s){const i=t.length;if(0===i){if(n)for(let e=0;e<n.length;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const o=e.childNodes;for(let r=0;r<i;r++)s.patch(e,o[r]||null,t[r],n?n[r]:void 0);return i}_hasKeys(e){if(!Array.isArray(e))return!1;for(let t=0,n=e.length;t<n;t++)if(e[t]&&e[t].a&&null!=e[t].a.key)return!0;return!1}_reconcileKeyed(e,t,n,s){const i=n?n.length:0,o=t.length;if(0===o){for(let e=0;e<i;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const r=Object.create(null),h=Object.create(null);for(let t=0;t<i;t++){const s=n[t].a?n[t].a.key:null,i=e.childNodes[t];null!=s&&i&&(r[s]=i,h[s]=n[t])}const d=new Array(o),u=new Array(o);for(let e=0;e<o;e++){const n=t[e].a?t[e].a.key:null;null!=n&&r[n]?(d[e]=r[n],u[e]=h[n],delete r[n]):(d[e]=null,u[e]=null)}for(const t in r){const n=r[t];n&&(s.patch(e,n,void 0,h[t]),n.remove())}let c=e.firstChild;for(let n=0;n<o;n++){const i=d[n];if(i&&i===c)c=c.nextSibling;else if(i)e.insertBefore(i,c);else{const i=s.createElement(t[n]);i&&e.insertBefore(i,c)}}for(;c;){const e=c.nextSibling;c.remove(),c=e}for(let n=0;n<o;n++)u[n]&&s.patch(e,e.childNodes[n],t[n],u[n]);return o}removeExtraChildren(e,t,n,s){const i=t.c?t.c.length:0;if(!(i<=n))for(let o=i;o-- >n;){const n=e.lastChild;n&&(s._unmountNodeAndChildren(t.c[o]),n.remove())}}}class v{constructor(e,t,n){this.generateTree=e||_,this.renderer=t,this.lifecycleQueue=n}mount(e,t,n){h();const s=this.generateTree(t(),n);return this.renderer.mount(e,s),this.lifecycleQueue.flush(),s}update(e,t,n,s){h();const i=this.generateTree(t(),n);return this.renderer.patch(e,e.firstChild,i,s),this.lifecycleQueue.flush(),i}unmount(e,t){t&&(this.renderer.unmount(e,t),this.lifecycleQueue.flush())}}class b{constructor(e,t){void 0===t&&(t="microtask"),this._renderFn=e,this._scheduler=t,this._scheduled=!1}schedule(){this._scheduled||(this._scheduled=!0,"microtask"===this._scheduler?Promise.resolve().then(()=>this._execute()):"sync"===this._scheduler&&this._execute())}_execute(){this._scheduled=!1,this._renderFn()}}class N{constructor(e,t){void 0===t&&(t={}),this.rootComponent=e,this.savedTree=e,this.currentTree=null,this.rootNode=null,this.stateManager=new c(t),this.lifecycleQueue=new m,this.eventManager=new y,this.renderer=new a(this.eventManager,this.lifecycleQueue,new g),this.mountOrchestrator=new v(_,this.renderer,this.lifecycleQueue),this.updateLoop=new b(()=>this.update(),"microtask"),this._boundSchedule=()=>this.updateLoop.schedule(),this.stateManager.subscribe(this._boundSchedule)}mount(e){if(this.rootNode=document.getElementById(e),!this.rootNode)throw new Error(`Cannot mount app: element with id "${e}" not found`);return this.eventManager.setRootNode(this.rootNode),this.currentTree=this.mountOrchestrator.mount(this.rootNode,this.savedTree,this.stateManager),this}unmount(){this.mountOrchestrator.unmount(this.rootNode,this.currentTree),this.eventManager.destroy(),this.stateManager.unsubscribe(()=>this.updateLoop.schedule()),this.rootNode&&(this.rootNode.innerHTML=""),this.currentTree=null,this.rootNode=null}scheduleUpdate(){this.updateLoop.schedule()}update(){this.rootNode&&this.savedTree&&(this.currentTree=this.mountOrchestrator.update(this.rootNode,this.savedTree,this.stateManager,this.currentTree))}getStore(){return this.stateManager.getStore()}setStore(e,t){this.stateManager.setStore(e,t)}}function S(e,t,n){const s=new N(e,n);return s.mount(t),s}function E(e,t,n){void 0===n&&(n={});const s=new N(e,n);return s.mount(t),s}export{N as App,y as EventManager,m as LifecycleQueue,a as Renderer,c as StateManager,h as advanceRenderCycle,d as component,S as createApp,t as flatten,_ as generateTree,i as generateUUID,n as h,s as isVNode,E as render};
|
package/build/index.modern.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class e{constructor(e,t={},n=[]){this.e=e,this.a=t,this.c=n}withLifecycle(e){return e.mounted&&(this.m=e.mounted),e.updated&&(this.up=e.updated),e.unmounted&&(this.un=e.unmounted),e.deleteState&&(this.d=e.deleteState),this}withIdentity(e,t){return this.definitionId=e,this.instanceId=t,this.id=e+"_"+t,this}}function t(e,n){for(let s=0,i=n.length;s<i;s++)Array.isArray(n[s])?t(e,n[s]):e.push(n[s]);return e}function n(n,s,...i){const r={};for(let e in s)r[e]=s[e];return new e(n,r,t([],i))}function s(t){return t instanceof e||null!==t&&"object"==typeof t&&"e"in t}function i(){return Math.random().toString(36).substring(2)+(new Date).getTime().toString(36)}class r{constructor(e,t,n,s,i,r){this.definitionId=e,this.instanceId=t,this.name=n,this.key=`${e}_${t}_${n}`,this.props=s,this._stateManager=r,this._config=i,r.createState(this.key,i.state),this.mounted=i.mounted.bind(this),this.updated=i.updated.bind(this),this.unmounted=i.unmounted.bind(this),this.deleteState=()=>{this._stateManager.deleteState(this.key)},this._renderedVNode=null,this._previousProps=null;const o=i.render.bind(this);this.render=()=>{if(!this.shouldUpdate())return this._renderedVNode;const e=o();return this._renderedVNode=e,this._previousProps=this.props,e}}getStore(){return this._stateManager.getStore()}setStore(e,t){this._stateManager.setStore(e,t)}getState(){return this._stateManager.getState(this.key)}setState(e,t){this._stateManager.setState(this.key,e,t)}createState(){this._stateManager.createState(this.key,this._config.state)}deleteState(){this._stateManager.deleteState(this.key)}shouldUpdate(){return!this._previousProps||!function(e,t){if(e===t)return!0;if(!e||!t||"object"!=typeof e||"object"!=typeof t)return!1;const n=Object.keys(e),s=Object.keys(t);if(n.length!==s.length)return!1;for(let s=0;s<n.length;s++)if(e[n[s]]!==t[n[s]])return!1;return!0}(this.props,this._previousProps)}bindMethods(e){"function"==typeof e&&(e=e.bind(this)());for(let t in e)this[t]=e[t].bind(this)}}function o({name:e="",state:t={},mounted:n=function(){},updated:s=function(){},unmounted:o=function(){},methods:h=function(){},render:u=function(){}}={}){const c=i(),d=new Map;return function(a={}){const l=a.key||"__default__";if(!d.has(l)){const f=i(),p=e+(a.key?"_"+a.key:"");d.set(l,{definitionId:c,instanceId:f,key:`${c}_${f}_${p}`,_props:null,_cachedRender:null,bind(e){const i=new r(c,f,p,this._props,{state:t,mounted:n,updated:s,unmounted:o,methods:h,render:u},e);return i.bindMethods(h),i}})}const f=d.get(l);return f._props=a,f}}function h(){return h=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var s in n)({}).hasOwnProperty.call(n,s)&&(e[s]=n[s])}return e},h.apply(null,arguments)}function u(e,t){for(let n in t)e[n]=t[n];return e}class c{constructor(e={}){this.store=h({},e),this.componentStates={},this.listeners=[]}subscribe(e){this.listeners.push(e)}unsubscribe(e){const t=this.listeners.indexOf(e);t>-1&&this.listeners.splice(t,1)}_notify(){for(let e=0;e<this.listeners.length;e++)this.listeners[e]()}getStore(){return h({},this.store)}setStore(e,t){"function"==typeof e&&(e=e(this.store)),this.store=u(u({},this.store),e),this._notify(),"function"==typeof t&&t()}createState(e,t){e in this.componentStates||(this.componentStates[e]=h({},t))}getState(e){return h({},this.componentStates[e])}setState(e,t,n){"function"==typeof t&&(t=t(this.componentStates[e])),this.componentStates[e]=u(u({},this.componentStates[e]),t),this._notify(),"function"==typeof n&&n()}deleteState(e){delete this.componentStates[e]}reset(){this.store={},this.componentStates={},this.listeners=[]}}class d{constructor(e,t,n){this.eventManager=e,this.lifecycleQueue=t,this.diffEngine=n}mount(e,t){const n=this.createElement(t);n&&e.appendChild(n)}createElement(e){if(null==e)return document.createTextNode("");const t=typeof e;return"string"===t||"number"===t?document.createTextNode(e):"boolean"===t||"undefined"===t?document.createTextNode(""):"object"===t&&e.e?this._createElementNode(e):null}_createElementNode(e){const t=document.createElement(e.e);if("object"==typeof e.a){const n=Object.keys(e.a);for(let s=n.length;s--;)if("events"===n[s])e.eid=this.eventManager.bindEvents(t,e.a[n[s]]);else if("style"===n[s])this._addStyles(e.a[n[s]],t);else{if("key"===n[s])continue;t.setAttribute(n[s],e.a[n[s]])}}if(this.lifecycleQueue.mounted(e),Array.isArray(e.c))for(let n=0,s=e.c.length;n<s;n++){const s=this.createElement(e.c[n]);s&&t.appendChild(s)}return t}_addStyles(e,t){if(void 0===e)return;const n=Object.keys(e);for(let s=n.length;s--;)t.style[n[s]]=e[n[s]]}patch(e,t,n,s){const i=typeof n;if(void 0===s)this._appendChild(e,n);else if("undefined"===i)this._unmountNodeAndChildren(s),t&&t.remove();else if(this.diffEngine.areNodesEqual(n,s)){if("object"===i&&n.e){if(n===s)return;if(this._updateNodes(t,n,s),n.c!==s.c)if(this.diffEngine._hasKeys(n.c)||this.diffEngine._hasKeys(s.c))this.diffEngine.reconcileChildren(t,n.c,s.c,this);else{let e;for(let i=s.c?s.c.length:0;i--&&void 0===n.c[i];)e=t.lastChild,e&&(this._unmountNodeAndChildren(s.c[i]),e.remove());if(Array.isArray(n.c))for(let e=0,i=n.c.length;e<i;e++)this.patch(t,t.childNodes[e]||null,n.c[e],s.c?s.c[e]:void 0)}}}else if(!t||3!==t.nodeType||"string"!==i&&"number"!==i)this._unmountNodeAndChildren(s),t&&e.replaceChild(this.createElement(n),t);else{const e=String(n);t.textContent!==e&&(t.textContent=e)}}_appendChild(e,t){const n=this.createElement(t);n&&e.appendChild(n)}_updateNodes(e,t,n){if(this.lifecycleQueue.updated(t),t.a===n.a)return;if(!t.a||!n.a)return;const s=Object.keys(t.a);let i,r;for(let o=s.length;o--;)if(r=t.a[s[o]],i=n.a[s[o]],"style"===s[o]){if(this._stylesAreEqual(r,i))continue;e.removeAttribute(s[o]),this._addStyles(r,e)}else if("events"===s[o])this.eventManager.unbindEvents(e,n.eid),t.eid=this.eventManager.bindEvents(e,r);else{if("key"===s[o])continue;"value"===s[o]&&r!==i?e.value=r:void 0!==i&&r===i||e.setAttribute(s[o],r)}}_stylesAreEqual(e,t){if(e===t)return!0;const n=typeof e,s=typeof t;if("undefined"===n&&"undefined"===s)return!0;if("object"!==n||"object"!==s)return!1;const i=Object.keys(e),r=Object.keys(t);if(i.length!==r.length)return!1;for(let n=i.length;n--;)if(e[i[n]]!==t[i[n]])return!1;return!0}_unmountNodeAndChildren(e){if(null!=e&&(this.lifecycleQueue.unmounted(e),this.lifecycleQueue.deleteState(e),this.eventManager.deleteCachedEvent(e.eid),Array.isArray(e.c)))for(let t=e.c.length;t--;)this._unmountNodeAndChildren(e.c[t])}unmount(e,t){this._unmountNodeAndChildren(t),e&&(e.innerHTML="")}}class a{constructor(e,t,n){this._getCache=e,this._resolveUUID=t,this._elementToUUID=n,this._attachedTypes=new Set,this._rootNode=null}attach(e,t){this._attachedTypes.has(t)||(this._attachedTypes.add(t),this._rootNode=e,e._literaljs_hasEvents=!0,e.addEventListener(t,e=>this._handle(e)))}_handle(e){if(!this._rootNode||!this._rootNode._literaljs_hasEvents)return;let t=e.target;for(;t&&t!==this._rootNode;){let n;if(this._elementToUUID&&(n=this._elementToUUID.get(t))){const t=this._getCache(n);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}const s=this._resolveUUID(t);if("string"==typeof s){const t=this._getCache(s);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}t=t.parentNode}}reset(){this._attachedTypes.clear()}}const l=["abort","blur","error","focus","load","mouseenter","mouseleave","resize","scroll","unload"],f="eid";class p{constructor(){this.cache={},this.rootNode=null,this._elementToUUID=new WeakMap,this.eventBus=new a(e=>this.cache[e],e=>this.getEventUUID(e),this._elementToUUID)}setRootNode(e){this.rootNode=e}getEventUUID(e){if(!e||!e.parentNode)return;if("#document"===e.parentNode.nodeName)return;const t=e.getAttribute("data-"+f);return"string"==typeof t?t:this.getEventUUID(e.parentNode)}bindEvents(e,t){const n=i();e.setAttribute("data-"+f,n),this.cache[n]=t,this._elementToUUID.set(e,n);const s=Object.keys(t);for(let t=s.length;t--;)l.includes(s[t])?e.addEventListener(s[t],this.cache[n][s[t]]):this.eventBus.attach(this.rootNode,s[t]);return n}unbindEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)l.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]]);this.deleteCachedEvent(t),this._elementToUUID.delete(e),e.removeAttribute("data-"+f)}addEvents(e,t,n){n.setAttribute("data-"+f,e),this.cache[e]=t,this._elementToUUID.set(n,e);const s=Object.keys(t);for(let t=s.length;t--;)l.includes(s[t])?n.addEventListener(s[t],this.cache[e][s[t]]):this.eventBus.attach(this.rootNode,s[t])}removeIndividualEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)l.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]])}deleteCachedEvent(e){"string"==typeof e&&delete this.cache[e]}destroy(){this.rootNode&&(this.rootNode._literaljs_hasEvents=!1),this.cache={},this.rootNode=null,this.eventBus.reset()}}class y{constructor(){this.queue=[]}mounted(e){"object"==typeof e&&"function"==typeof e.m&&this.queue.push(e.m)}updated(e){"object"==typeof e&&"function"==typeof e.up&&this.queue.push(e.up)}unmounted(e){"object"==typeof e&&"function"==typeof e.un&&this.queue.push(e.un)}deleteState(e){"object"==typeof e&&"function"==typeof e.d&&this.queue.push(e.d)}flush(){let e;for(;e=this.queue.shift();)e()}clear(){this.queue=[]}}function m(t,n){if(null==t)return t;if("function"==typeof t.e){let e;e=t.a&&t.a.props?h({},t.a.props):t.a?h({},t.a):{},delete(t={e:t.e,a:h({},t.a),c:t.c}).a.props,t=t.e(e)}if(t&&"function"==typeof t.bind){const s=t.bind(n);let i;try{i=s.render()}catch(e){console.error("Component render error:",e),i={e:"div",a:{class:"error-boundary"},c:[`${e.name}: ${e.message}`]}}if("object"==typeof i&&null!==i&&i instanceof e)i.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),i.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=i;else if("object"==typeof i&&null!==i){const n=new e(i.e,i.a,i.c);n.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),n.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=n}else t=i}if(t&&Array.isArray(t.c))for(let e=0,s=t.c.length;e<s;e++)t.c[e]=m(t.c[e],n);return t}class _{areNodesEqual(e,t){const n=typeof e;return n===typeof t&&("object"===n&&e.e===t.e&&e.id===t.id||("string"===n||"number"===n)&&e===t)}reconcileChildren(e,t,n,s){return Array.isArray(t)?this._hasKeys(t)||this._hasKeys(n)?this._reconcileKeyed(e,t,n,s):this._reconcileNonKeyed(e,t,n,s):0}_reconcileNonKeyed(e,t,n,s){const i=t.length;if(0===i){if(n)for(let e=0;e<n.length;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const r=e.childNodes;for(let o=0;o<i;o++)s.patch(e,r[o]||null,t[o],n?n[o]:void 0);return i}_hasKeys(e){if(!Array.isArray(e))return!1;for(let t=0,n=e.length;t<n;t++)if(e[t]&&e[t].a&&null!=e[t].a.key)return!0;return!1}_reconcileKeyed(e,t,n,s){const i=n?n.length:0,r=t.length;if(0===r){for(let e=0;e<i;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const o=Object.create(null),h=Object.create(null);for(let t=0;t<i;t++){const s=n[t].a?n[t].a.key:null,i=e.childNodes[t];null!=s&&i&&(o[s]=i,h[s]=n[t])}const u=new Array(r),c=new Array(r);for(let e=0;e<r;e++){const n=t[e].a?t[e].a.key:null;null!=n&&o[n]?(u[e]=o[n],c[e]=h[n],delete o[n]):(u[e]=null,c[e]=null)}for(const t in o){const n=o[t];n&&(s.patch(e,n,void 0,h[t]),n.remove())}let d=e.firstChild;for(let n=0;n<r;n++){const i=u[n];if(i&&i===d)d=d.nextSibling;else if(i)e.insertBefore(i,d);else{const i=s.createElement(t[n]);i&&e.insertBefore(i,d)}}for(;d;){const e=d.nextSibling;d.remove(),d=e}for(let n=0;n<r;n++)c[n]&&s.patch(e,e.childNodes[n],t[n],c[n]);return r}removeExtraChildren(e,t,n,s){const i=t.c?t.c.length:0;if(!(i<=n))for(let r=i;r-- >n;){const n=e.lastChild;n&&(s._unmountNodeAndChildren(t.c[r]),n.remove())}}}class g{constructor(e,t,n){this.generateTree=e||m,this.renderer=t,this.lifecycleQueue=n}mount(e,t,n){const s=this.generateTree(t(),n);return this.renderer.mount(e,s),this.lifecycleQueue.flush(),s}update(e,t,n,s){const i=this.generateTree(t(),n);return this.renderer.patch(e,e.firstChild,i,s),this.lifecycleQueue.flush(),i}unmount(e,t){t&&(this.renderer.unmount(e,t),this.lifecycleQueue.flush())}}class v{constructor(e,t="microtask"){this._renderFn=e,this._scheduler=t,this._scheduled=!1}schedule(){this._scheduled||(this._scheduled=!0,"microtask"===this._scheduler?Promise.resolve().then(()=>this._execute()):"sync"===this._scheduler&&this._execute())}_execute(){this._scheduled=!1,this._renderFn()}}class b{constructor(e,t={}){this.rootComponent=e,this.savedTree=e,this.currentTree=null,this.rootNode=null,this.stateManager=new c(t),this.lifecycleQueue=new y,this.eventManager=new p,this.renderer=new d(this.eventManager,this.lifecycleQueue,new _),this.mountOrchestrator=new g(m,this.renderer,this.lifecycleQueue),this.updateLoop=new v(()=>this.update(),"microtask"),this._boundSchedule=()=>this.updateLoop.schedule(),this.stateManager.subscribe(this._boundSchedule)}mount(e){if(this.rootNode=document.getElementById(e),!this.rootNode)throw new Error(`Cannot mount app: element with id "${e}" not found`);return this.eventManager.setRootNode(this.rootNode),this.currentTree=this.mountOrchestrator.mount(this.rootNode,this.savedTree,this.stateManager),this}unmount(){this.mountOrchestrator.unmount(this.rootNode,this.currentTree),this.eventManager.destroy(),this.stateManager.unsubscribe(()=>this.updateLoop.schedule()),this.rootNode&&(this.rootNode.innerHTML=""),this.currentTree=null,this.rootNode=null}scheduleUpdate(){this.updateLoop.schedule()}update(){this.rootNode&&this.savedTree&&(this.currentTree=this.mountOrchestrator.update(this.rootNode,this.savedTree,this.stateManager,this.currentTree))}getStore(){return this.stateManager.getStore()}setStore(e,t){this.stateManager.setStore(e,t)}}function N(e,t,n){const s=new b(e,n);return s.mount(t),s}function S(e,t,n={}){const s=new b(e,n);return s.mount(t),s}export{b as App,p as EventManager,y as LifecycleQueue,d as Renderer,c as StateManager,o as component,N as createApp,t as flatten,m as generateTree,i as generateUUID,n as h,s as isVNode,S as render};
|
|
1
|
+
class e{constructor(e,t={},n=[]){this.e=e,this.a=t,this.c=n}withLifecycle(e){return e.mounted&&(this.m=e.mounted),e.updated&&(this.up=e.updated),e.unmounted&&(this.un=e.unmounted),e.deleteState&&(this.d=e.deleteState),this}withIdentity(e,t){return this.definitionId=e,this.instanceId=t,this.id=e+"_"+t,this}}function t(e,n){for(let s=0,i=n.length;s<i;s++)Array.isArray(n[s])?t(e,n[s]):null!=n[s]&&"boolean"!=typeof n[s]&&e.push(n[s]);return e}function n(n,s,...i){const r={};for(let e in s)r[e]=s[e];return new e(n,r,t([],i))}function s(t){return t instanceof e||null!==t&&"object"==typeof t&&"e"in t}function i(){return Math.random().toString(36).substring(2)+(new Date).getTime().toString(36)}class r{constructor(e,t,n,s,i,r){this.definitionId=e,this.instanceId=t,this.name=n,this.key=`${e}_${t}_${n}`,this.props=s,this._stateManager=r,this._config=i,r.createState(this.key,i.state),this.mounted=i.mounted.bind(this),this.updated=i.updated.bind(this),this.unmounted=i.unmounted.bind(this),this.deleteState=()=>{this._stateManager.deleteState(this.key)},this._renderedVNode=null,this._previousProps=null;const o=i.render.bind(this);this.render=()=>{if(!this.shouldUpdate())return this._renderedVNode;const e=o();return this._renderedVNode=e,this._previousProps=this.props,e}}getStore(){return this._stateManager.getStore()}setStore(e,t){this._stateManager.setStore(e,t)}getState(){return this._stateManager.getState(this.key)}setState(e,t){this._stateManager.setState(this.key,e,t)}createState(){this._stateManager.createState(this.key,this._config.state)}deleteState(){this._stateManager.deleteState(this.key)}shouldUpdate(){return!this._previousProps||!function(e,t){if(e===t)return!0;if(!e||!t||"object"!=typeof e||"object"!=typeof t)return!1;const n=Object.keys(e),s=Object.keys(t);if(n.length!==s.length)return!1;for(let s=0;s<n.length;s++)if(e[n[s]]!==t[n[s]])return!1;return!0}(this.props,this._previousProps)}bindMethods(e){"function"==typeof e&&(e=e.bind(this)());for(let t in e)this[t]=e[t].bind(this)}}let o=0;function h(){o++}function u({name:e="",state:t={},mounted:n=function(){},updated:s=function(){},unmounted:h=function(){},methods:u=function(){},render:c=function(){}}={}){const d=i(),a=new Map;let l=0,f=-1;return function(p={}){f!==o&&(l=0,f=o);const y=null!=p.key?String(p.key):`__auto_${l++}__`;if(!a.has(y)){const o=i(),l=e+(null!=p.key?"_"+String(p.key):"");a.set(y,{definitionId:d,instanceId:o,key:`${d}_${o}_${l}`,_props:null,_cachedRender:null,bind(e){const i=new r(d,o,l,this._props,{state:t,mounted:n,updated:s,unmounted:h,methods:u,render:c},e);return i.bindMethods(u),i}})}const m=a.get(y);return m._props=p,m}}function c(){return c=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var s in n)({}).hasOwnProperty.call(n,s)&&(e[s]=n[s])}return e},c.apply(null,arguments)}function d(e,t){for(let n in t)e[n]=t[n];return e}class a{constructor(e={}){this.store=c({},e),this.componentStates={},this.listeners=[]}subscribe(e){this.listeners.push(e)}unsubscribe(e){const t=this.listeners.indexOf(e);t>-1&&this.listeners.splice(t,1)}_notify(){for(let e=0;e<this.listeners.length;e++)this.listeners[e]()}getStore(){return c({},this.store)}setStore(e,t){"function"==typeof e&&(e=e(this.store)),this.store=d(d({},this.store),e),this._notify(),"function"==typeof t&&t()}createState(e,t){e in this.componentStates||(this.componentStates[e]=c({},t))}getState(e){return c({},this.componentStates[e])}setState(e,t,n){"function"==typeof t&&(t=t(this.componentStates[e])),this.componentStates[e]=d(d({},this.componentStates[e]),t),this._notify(),"function"==typeof n&&n()}deleteState(e){delete this.componentStates[e]}reset(){this.store={},this.componentStates={},this.listeners=[]}}class l{constructor(e,t,n){this.eventManager=e,this.lifecycleQueue=t,this.diffEngine=n}mount(e,t){const n=this.createElement(t);n&&e.appendChild(n)}createElement(e){if(null==e)return document.createTextNode("");const t=typeof e;return"string"===t||"number"===t?document.createTextNode(e):"boolean"===t||"undefined"===t?document.createTextNode(""):"object"===t&&e.e?this._createElementNode(e):null}_createElementNode(e){const t=document.createElement(e.e);if("object"==typeof e.a){const n=Object.keys(e.a);for(let s=n.length;s--;)if("events"===n[s])e.eid=this.eventManager.bindEvents(t,e.a[n[s]]);else if("style"===n[s])this._addStyles(e.a[n[s]],t);else{if("key"===n[s])continue;t.setAttribute(n[s],e.a[n[s]])}}if(this.lifecycleQueue.mounted(e),Array.isArray(e.c))for(let n=0,s=e.c.length;n<s;n++){const s=this.createElement(e.c[n]);s&&t.appendChild(s)}return t}_addStyles(e,t){if(void 0===e)return;const n=Object.keys(e);for(let s=n.length;s--;)t.style[n[s]]=e[n[s]]}patch(e,t,n,s){const i=typeof n;if(void 0===s)this._appendChild(e,n);else if("undefined"===i)this._unmountNodeAndChildren(s),t&&t.remove();else if(this.diffEngine.areNodesEqual(n,s)){if("object"===i&&n.e){if(n===s)return;if(this._updateNodes(t,n,s),n.c!==s.c)if(this.diffEngine._hasKeys(n.c)||this.diffEngine._hasKeys(s.c))this.diffEngine.reconcileChildren(t,n.c,s.c,this);else{let e;for(let i=s.c?s.c.length:0;i--&&void 0===n.c[i];)e=t.lastChild,e&&(this._unmountNodeAndChildren(s.c[i]),e.remove());if(Array.isArray(n.c))for(let e=0,i=n.c.length;e<i;e++)this.patch(t,t.childNodes[e]||null,n.c[e],s.c?s.c[e]:void 0)}}}else if(!t||3!==t.nodeType||"string"!==i&&"number"!==i)this._unmountNodeAndChildren(s),t&&e.replaceChild(this.createElement(n),t);else{const e=String(n);t.textContent!==e&&(t.textContent=e)}}_appendChild(e,t){const n=this.createElement(t);n&&e.appendChild(n)}_updateNodes(e,t,n){if(this.lifecycleQueue.updated(t),t.a===n.a)return;if(!t.a||!n.a)return;const s=Object.keys(t.a);let i,r;for(let o=s.length;o--;)if(r=t.a[s[o]],i=n.a[s[o]],"style"===s[o]){if(this._stylesAreEqual(r,i))continue;e.removeAttribute(s[o]),this._addStyles(r,e)}else if("events"===s[o])this.eventManager.unbindEvents(e,n.eid),t.eid=this.eventManager.bindEvents(e,r);else{if("key"===s[o])continue;"value"===s[o]&&r!==i?e.value=r:void 0!==i&&r===i||e.setAttribute(s[o],r)}}_stylesAreEqual(e,t){if(e===t)return!0;const n=typeof e,s=typeof t;if("undefined"===n&&"undefined"===s)return!0;if("object"!==n||"object"!==s)return!1;const i=Object.keys(e),r=Object.keys(t);if(i.length!==r.length)return!1;for(let n=i.length;n--;)if(e[i[n]]!==t[i[n]])return!1;return!0}_unmountNodeAndChildren(e){if(null!=e&&(this.lifecycleQueue.unmounted(e),this.lifecycleQueue.deleteState(e),this.eventManager.deleteCachedEvent(e.eid),Array.isArray(e.c)))for(let t=e.c.length;t--;)this._unmountNodeAndChildren(e.c[t])}unmount(e,t){this._unmountNodeAndChildren(t),e&&(e.innerHTML="")}}class f{constructor(e,t,n){this._getCache=e,this._resolveUUID=t,this._elementToUUID=n,this._attachedTypes=new Set,this._rootNode=null}attach(e,t){this._attachedTypes.has(t)||(this._attachedTypes.add(t),this._rootNode=e,e._literaljs_hasEvents=!0,e.addEventListener(t,e=>this._handle(e)))}_handle(e){if(!this._rootNode||!this._rootNode._literaljs_hasEvents)return;let t=e.target;for(;t&&t!==this._rootNode;){let n;if(this._elementToUUID&&(n=this._elementToUUID.get(t))){const t=this._getCache(n);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}const s=this._resolveUUID(t);if("string"==typeof s){const t=this._getCache(s);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}t=t.parentNode}}reset(){this._attachedTypes.clear()}}const p=["abort","blur","error","focus","load","mouseenter","mouseleave","resize","scroll","unload"],y="eid";class m{constructor(){this.cache={},this.rootNode=null,this._elementToUUID=new WeakMap,this.eventBus=new f(e=>this.cache[e],e=>this.getEventUUID(e),this._elementToUUID)}setRootNode(e){this.rootNode=e}getEventUUID(e){if(!e||!e.parentNode)return;if("#document"===e.parentNode.nodeName)return;const t=e.getAttribute("data-"+y);return"string"==typeof t?t:this.getEventUUID(e.parentNode)}bindEvents(e,t){const n=i();e.setAttribute("data-"+y,n),this.cache[n]=t,this._elementToUUID.set(e,n);const s=Object.keys(t);for(let t=s.length;t--;)p.includes(s[t])?e.addEventListener(s[t],this.cache[n][s[t]]):this.eventBus.attach(this.rootNode,s[t]);return n}unbindEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)p.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]]);this.deleteCachedEvent(t),this._elementToUUID.delete(e),e.removeAttribute("data-"+y)}addEvents(e,t,n){n.setAttribute("data-"+y,e),this.cache[e]=t,this._elementToUUID.set(n,e);const s=Object.keys(t);for(let t=s.length;t--;)p.includes(s[t])?n.addEventListener(s[t],this.cache[e][s[t]]):this.eventBus.attach(this.rootNode,s[t])}removeIndividualEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)p.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]])}deleteCachedEvent(e){"string"==typeof e&&delete this.cache[e]}destroy(){this.rootNode&&(this.rootNode._literaljs_hasEvents=!1),this.cache={},this.rootNode=null,this.eventBus.reset()}}class _{constructor(){this.queue=[]}mounted(e){"object"==typeof e&&"function"==typeof e.m&&this.queue.push(e.m)}updated(e){"object"==typeof e&&"function"==typeof e.up&&this.queue.push(e.up)}unmounted(e){"object"==typeof e&&"function"==typeof e.un&&this.queue.push(e.un)}deleteState(e){"object"==typeof e&&"function"==typeof e.d&&this.queue.push(e.d)}flush(){let e;for(;e=this.queue.shift();)e()}clear(){this.queue=[]}}function g(t,n){if(null==t)return t;if("function"==typeof t.e){let e;e=t.a&&t.a.props?c({},t.a.props):t.a?c({},t.a):{},delete(t={e:t.e,a:c({},t.a),c:t.c}).a.props,t=t.e(e)}if(t&&"function"==typeof t.bind){const s=t.bind(n);let i;try{i=s.render()}catch(e){console.error("Component render error:",e),i={e:"div",a:{class:"error-boundary"},c:[`${e.name}: ${e.message}`]}}if("object"==typeof i&&null!==i&&i instanceof e)i.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),i.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=i;else if("object"==typeof i&&null!==i){const n=new e(i.e,i.a,i.c);n.withIdentity(t.definitionId||s.definitionId,t.instanceId||s.instanceId),n.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),t=n}else t=i}if(t&&Array.isArray(t.c))for(let e=0,s=t.c.length;e<s;e++)t.c[e]=g(t.c[e],n);return t}class b{areNodesEqual(e,t){const n=typeof e;return n===typeof t&&("object"===n&&e&&t&&e.e===t.e&&e.id===t.id||("string"===n||"number"===n)&&e===t)}reconcileChildren(e,t,n,s){return Array.isArray(t)?this._hasKeys(t)||this._hasKeys(n)?this._reconcileKeyed(e,t,n,s):this._reconcileNonKeyed(e,t,n,s):0}_reconcileNonKeyed(e,t,n,s){const i=t.length;if(0===i){if(n)for(let e=0;e<n.length;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const r=e.childNodes;for(let o=0;o<i;o++)s.patch(e,r[o]||null,t[o],n?n[o]:void 0);return i}_hasKeys(e){if(!Array.isArray(e))return!1;for(let t=0,n=e.length;t<n;t++)if(e[t]&&e[t].a&&null!=e[t].a.key)return!0;return!1}_reconcileKeyed(e,t,n,s){const i=n?n.length:0,r=t.length;if(0===r){for(let e=0;e<i;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const o=Object.create(null),h=Object.create(null);for(let t=0;t<i;t++){const s=n[t].a?n[t].a.key:null,i=e.childNodes[t];null!=s&&i&&(o[s]=i,h[s]=n[t])}const u=new Array(r),c=new Array(r);for(let e=0;e<r;e++){const n=t[e].a?t[e].a.key:null;null!=n&&o[n]?(u[e]=o[n],c[e]=h[n],delete o[n]):(u[e]=null,c[e]=null)}for(const t in o){const n=o[t];n&&(s.patch(e,n,void 0,h[t]),n.remove())}let d=e.firstChild;for(let n=0;n<r;n++){const i=u[n];if(i&&i===d)d=d.nextSibling;else if(i)e.insertBefore(i,d);else{const i=s.createElement(t[n]);i&&e.insertBefore(i,d)}}for(;d;){const e=d.nextSibling;d.remove(),d=e}for(let n=0;n<r;n++)c[n]&&s.patch(e,e.childNodes[n],t[n],c[n]);return r}removeExtraChildren(e,t,n,s){const i=t.c?t.c.length:0;if(!(i<=n))for(let r=i;r-- >n;){const n=e.lastChild;n&&(s._unmountNodeAndChildren(t.c[r]),n.remove())}}}class v{constructor(e,t,n){this.generateTree=e||g,this.renderer=t,this.lifecycleQueue=n}mount(e,t,n){h();const s=this.generateTree(t(),n);return this.renderer.mount(e,s),this.lifecycleQueue.flush(),s}update(e,t,n,s){h();const i=this.generateTree(t(),n);return this.renderer.patch(e,e.firstChild,i,s),this.lifecycleQueue.flush(),i}unmount(e,t){t&&(this.renderer.unmount(e,t),this.lifecycleQueue.flush())}}class N{constructor(e,t="microtask"){this._renderFn=e,this._scheduler=t,this._scheduled=!1}schedule(){this._scheduled||(this._scheduled=!0,"microtask"===this._scheduler?Promise.resolve().then(()=>this._execute()):"sync"===this._scheduler&&this._execute())}_execute(){this._scheduled=!1,this._renderFn()}}class S{constructor(e,t={}){this.rootComponent=e,this.savedTree=e,this.currentTree=null,this.rootNode=null,this.stateManager=new a(t),this.lifecycleQueue=new _,this.eventManager=new m,this.renderer=new l(this.eventManager,this.lifecycleQueue,new b),this.mountOrchestrator=new v(g,this.renderer,this.lifecycleQueue),this.updateLoop=new N(()=>this.update(),"microtask"),this._boundSchedule=()=>this.updateLoop.schedule(),this.stateManager.subscribe(this._boundSchedule)}mount(e){if(this.rootNode=document.getElementById(e),!this.rootNode)throw new Error(`Cannot mount app: element with id "${e}" not found`);return this.eventManager.setRootNode(this.rootNode),this.currentTree=this.mountOrchestrator.mount(this.rootNode,this.savedTree,this.stateManager),this}unmount(){this.mountOrchestrator.unmount(this.rootNode,this.currentTree),this.eventManager.destroy(),this.stateManager.unsubscribe(()=>this.updateLoop.schedule()),this.rootNode&&(this.rootNode.innerHTML=""),this.currentTree=null,this.rootNode=null}scheduleUpdate(){this.updateLoop.schedule()}update(){this.rootNode&&this.savedTree&&(this.currentTree=this.mountOrchestrator.update(this.rootNode,this.savedTree,this.stateManager,this.currentTree))}getStore(){return this.stateManager.getStore()}setStore(e,t){this.stateManager.setStore(e,t)}}function E(e,t,n){const s=new S(e,n);return s.mount(t),s}function A(e,t,n={}){const s=new S(e,n);return s.mount(t),s}export{S as App,m as EventManager,_ as LifecycleQueue,l as Renderer,a as StateManager,h as advanceRenderCycle,u as component,E as createApp,t as flatten,g as generateTree,i as generateUUID,n as h,s as isVNode,A as render};
|
package/build/index.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e||self).literaljs={})}(this,function(e){class t{constructor(e,t,n){void 0===t&&(t={}),void 0===n&&(n=[]),this.e=e,this.a=t,this.c=n}withLifecycle(e){return e.mounted&&(this.m=e.mounted),e.updated&&(this.up=e.updated),e.unmounted&&(this.un=e.unmounted),e.deleteState&&(this.d=e.deleteState),this}withIdentity(e,t){return this.definitionId=e,this.instanceId=t,this.id=e+"_"+t,this}}function n(e,t){for(let s=0,i=t.length;s<i;s++)Array.isArray(t[s])?n(e,t[s]):e.push(t[s]);return e}function s(){return Math.random().toString(36).substring(2)+(new Date).getTime().toString(36)}class i{constructor(e,t,n,s,i,o){this.definitionId=e,this.instanceId=t,this.name=n,this.key=`${e}_${t}_${n}`,this.props=s,this._stateManager=o,this._config=i,o.createState(this.key,i.state),this.mounted=i.mounted.bind(this),this.updated=i.updated.bind(this),this.unmounted=i.unmounted.bind(this),this.deleteState=()=>{this._stateManager.deleteState(this.key)},this._renderedVNode=null,this._previousProps=null;const r=i.render.bind(this);this.render=()=>{if(!this.shouldUpdate())return this._renderedVNode;const e=r();return this._renderedVNode=e,this._previousProps=this.props,e}}getStore(){return this._stateManager.getStore()}setStore(e,t){this._stateManager.setStore(e,t)}getState(){return this._stateManager.getState(this.key)}setState(e,t){this._stateManager.setState(this.key,e,t)}createState(){this._stateManager.createState(this.key,this._config.state)}deleteState(){this._stateManager.deleteState(this.key)}shouldUpdate(){return!this._previousProps||!function(e,t){if(e===t)return!0;if(!e||!t||"object"!=typeof e||"object"!=typeof t)return!1;const n=Object.keys(e),s=Object.keys(t);if(n.length!==s.length)return!1;for(let s=0;s<n.length;s++)if(e[n[s]]!==t[n[s]])return!1;return!0}(this.props,this._previousProps)}bindMethods(e){"function"==typeof e&&(e=e.bind(this)());for(let t in e)this[t]=e[t].bind(this)}}function o(e,t){for(let n in t)e[n]=t[n];return e}class r{constructor(e){void 0===e&&(e={}),this.store={...e},this.componentStates={},this.listeners=[]}subscribe(e){this.listeners.push(e)}unsubscribe(e){const t=this.listeners.indexOf(e);t>-1&&this.listeners.splice(t,1)}_notify(){for(let e=0;e<this.listeners.length;e++)this.listeners[e]()}getStore(){return{...this.store}}setStore(e,t){"function"==typeof e&&(e=e(this.store)),this.store=o(o({},this.store),e),this._notify(),"function"==typeof t&&t()}createState(e,t){e in this.componentStates||(this.componentStates[e]={...t})}getState(e){return{...this.componentStates[e]}}setState(e,t,n){"function"==typeof t&&(t=t(this.componentStates[e])),this.componentStates[e]=o(o({},this.componentStates[e]),t),this._notify(),"function"==typeof n&&n()}deleteState(e){delete this.componentStates[e]}reset(){this.store={},this.componentStates={},this.listeners=[]}}class h{constructor(e,t,n){this.eventManager=e,this.lifecycleQueue=t,this.diffEngine=n}mount(e,t){const n=this.createElement(t);n&&e.appendChild(n)}createElement(e){if(null==e)return document.createTextNode("");const t=typeof e;return"string"===t||"number"===t?document.createTextNode(e):"boolean"===t||"undefined"===t?document.createTextNode(""):"object"===t&&e.e?this._createElementNode(e):null}_createElementNode(e){const t=document.createElement(e.e);if("object"==typeof e.a){const n=Object.keys(e.a);for(let s=n.length;s--;)if("events"===n[s])e.eid=this.eventManager.bindEvents(t,e.a[n[s]]);else if("style"===n[s])this._addStyles(e.a[n[s]],t);else{if("key"===n[s])continue;t.setAttribute(n[s],e.a[n[s]])}}if(this.lifecycleQueue.mounted(e),Array.isArray(e.c))for(let n=0,s=e.c.length;n<s;n++){const s=this.createElement(e.c[n]);s&&t.appendChild(s)}return t}_addStyles(e,t){if(void 0===e)return;const n=Object.keys(e);for(let s=n.length;s--;)t.style[n[s]]=e[n[s]]}patch(e,t,n,s){const i=typeof n;if(void 0===s)this._appendChild(e,n);else if("undefined"===i)this._unmountNodeAndChildren(s),t&&t.remove();else if(this.diffEngine.areNodesEqual(n,s)){if("object"===i&&n.e){if(n===s)return;if(this._updateNodes(t,n,s),n.c!==s.c)if(this.diffEngine._hasKeys(n.c)||this.diffEngine._hasKeys(s.c))this.diffEngine.reconcileChildren(t,n.c,s.c,this);else{let e;for(let i=s.c?s.c.length:0;i--&&void 0===n.c[i];)e=t.lastChild,e&&(this._unmountNodeAndChildren(s.c[i]),e.remove());if(Array.isArray(n.c))for(let e=0,i=n.c.length;e<i;e++)this.patch(t,t.childNodes[e]||null,n.c[e],s.c?s.c[e]:void 0)}}}else if(!t||3!==t.nodeType||"string"!==i&&"number"!==i)this._unmountNodeAndChildren(s),t&&e.replaceChild(this.createElement(n),t);else{const e=String(n);t.textContent!==e&&(t.textContent=e)}}_appendChild(e,t){const n=this.createElement(t);n&&e.appendChild(n)}_updateNodes(e,t,n){if(this.lifecycleQueue.updated(t),t.a===n.a)return;if(!t.a||!n.a)return;const s=Object.keys(t.a);let i,o;for(let r=s.length;r--;)if(o=t.a[s[r]],i=n.a[s[r]],"style"===s[r]){if(this._stylesAreEqual(o,i))continue;e.removeAttribute(s[r]),this._addStyles(o,e)}else if("events"===s[r])this.eventManager.unbindEvents(e,n.eid),t.eid=this.eventManager.bindEvents(e,o);else{if("key"===s[r])continue;"value"===s[r]&&o!==i?e.value=o:void 0!==i&&o===i||e.setAttribute(s[r],o)}}_stylesAreEqual(e,t){if(e===t)return!0;const n=typeof e,s=typeof t;if("undefined"===n&&"undefined"===s)return!0;if("object"!==n||"object"!==s)return!1;const i=Object.keys(e),o=Object.keys(t);if(i.length!==o.length)return!1;for(let n=i.length;n--;)if(e[i[n]]!==t[i[n]])return!1;return!0}_unmountNodeAndChildren(e){if(null!=e&&(this.lifecycleQueue.unmounted(e),this.lifecycleQueue.deleteState(e),this.eventManager.deleteCachedEvent(e.eid),Array.isArray(e.c)))for(let t=e.c.length;t--;)this._unmountNodeAndChildren(e.c[t])}unmount(e,t){this._unmountNodeAndChildren(t),e&&(e.innerHTML="")}}class d{constructor(e,t,n){this._getCache=e,this._resolveUUID=t,this._elementToUUID=n,this._attachedTypes=new Set,this._rootNode=null}attach(e,t){this._attachedTypes.has(t)||(this._attachedTypes.add(t),this._rootNode=e,e._literaljs_hasEvents=!0,e.addEventListener(t,e=>this._handle(e)))}_handle(e){if(!this._rootNode||!this._rootNode._literaljs_hasEvents)return;let t=e.target;for(;t&&t!==this._rootNode;){let n;if(this._elementToUUID&&(n=this._elementToUUID.get(t))){const t=this._getCache(n);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}const s=this._resolveUUID(t);if("string"==typeof s){const t=this._getCache(s);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}t=t.parentNode}}reset(){this._attachedTypes.clear()}}const c=["abort","blur","error","focus","load","mouseenter","mouseleave","resize","scroll","unload"],u="eid";class a{constructor(){this.cache={},this.rootNode=null,this._elementToUUID=new WeakMap,this.eventBus=new d(e=>this.cache[e],e=>this.getEventUUID(e),this._elementToUUID)}setRootNode(e){this.rootNode=e}getEventUUID(e){if(!e||!e.parentNode)return;if("#document"===e.parentNode.nodeName)return;const t=e.getAttribute("data-"+u);return"string"==typeof t?t:this.getEventUUID(e.parentNode)}bindEvents(e,t){const n=s();e.setAttribute("data-"+u,n),this.cache[n]=t,this._elementToUUID.set(e,n);const i=Object.keys(t);for(let t=i.length;t--;)c.includes(i[t])?e.addEventListener(i[t],this.cache[n][i[t]]):this.eventBus.attach(this.rootNode,i[t]);return n}unbindEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)c.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]]);this.deleteCachedEvent(t),this._elementToUUID.delete(e),e.removeAttribute("data-"+u)}addEvents(e,t,n){n.setAttribute("data-"+u,e),this.cache[e]=t,this._elementToUUID.set(n,e);const s=Object.keys(t);for(let t=s.length;t--;)c.includes(s[t])?n.addEventListener(s[t],this.cache[e][s[t]]):this.eventBus.attach(this.rootNode,s[t])}removeIndividualEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)c.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]])}deleteCachedEvent(e){"string"==typeof e&&delete this.cache[e]}destroy(){this.rootNode&&(this.rootNode._literaljs_hasEvents=!1),this.cache={},this.rootNode=null,this.eventBus.reset()}}class l{constructor(){this.queue=[]}mounted(e){"object"==typeof e&&"function"==typeof e.m&&this.queue.push(e.m)}updated(e){"object"==typeof e&&"function"==typeof e.up&&this.queue.push(e.up)}unmounted(e){"object"==typeof e&&"function"==typeof e.un&&this.queue.push(e.un)}deleteState(e){"object"==typeof e&&"function"==typeof e.d&&this.queue.push(e.d)}flush(){let e;for(;e=this.queue.shift();)e()}clear(){this.queue=[]}}function f(e,n){if(null==e)return e;if("function"==typeof e.e){let t;t=e.a&&e.a.props?{...e.a.props}:e.a?{...e.a}:{},delete(e={e:e.e,a:{...e.a},c:e.c}).a.props,e=e.e(t)}if(e&&"function"==typeof e.bind){const s=e.bind(n);let i;try{i=s.render()}catch(e){console.error("Component render error:",e),i={e:"div",a:{class:"error-boundary"},c:[`${e.name}: ${e.message}`]}}if("object"==typeof i&&null!==i&&i instanceof t)i.withIdentity(e.definitionId||s.definitionId,e.instanceId||s.instanceId),i.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),e=i;else if("object"==typeof i&&null!==i){const n=new t(i.e,i.a,i.c);n.withIdentity(e.definitionId||s.definitionId,e.instanceId||s.instanceId),n.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),e=n}else e=i}if(e&&Array.isArray(e.c))for(let t=0,s=e.c.length;t<s;t++)e.c[t]=f(e.c[t],n);return e}class p{areNodesEqual(e,t){const n=typeof e;return n===typeof t&&("object"===n&&e.e===t.e&&e.id===t.id||("string"===n||"number"===n)&&e===t)}reconcileChildren(e,t,n,s){return Array.isArray(t)?this._hasKeys(t)||this._hasKeys(n)?this._reconcileKeyed(e,t,n,s):this._reconcileNonKeyed(e,t,n,s):0}_reconcileNonKeyed(e,t,n,s){const i=t.length;if(0===i){if(n)for(let e=0;e<n.length;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const o=e.childNodes;for(let r=0;r<i;r++)s.patch(e,o[r]||null,t[r],n?n[r]:void 0);return i}_hasKeys(e){if(!Array.isArray(e))return!1;for(let t=0,n=e.length;t<n;t++)if(e[t]&&e[t].a&&null!=e[t].a.key)return!0;return!1}_reconcileKeyed(e,t,n,s){const i=n?n.length:0,o=t.length;if(0===o){for(let e=0;e<i;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const r=Object.create(null),h=Object.create(null);for(let t=0;t<i;t++){const s=n[t].a?n[t].a.key:null,i=e.childNodes[t];null!=s&&i&&(r[s]=i,h[s]=n[t])}const d=new Array(o),c=new Array(o);for(let e=0;e<o;e++){const n=t[e].a?t[e].a.key:null;null!=n&&r[n]?(d[e]=r[n],c[e]=h[n],delete r[n]):(d[e]=null,c[e]=null)}for(const t in r){const n=r[t];n&&(s.patch(e,n,void 0,h[t]),n.remove())}let u=e.firstChild;for(let n=0;n<o;n++){const i=d[n];if(i&&i===u)u=u.nextSibling;else if(i)e.insertBefore(i,u);else{const i=s.createElement(t[n]);i&&e.insertBefore(i,u)}}for(;u;){const e=u.nextSibling;u.remove(),u=e}for(let n=0;n<o;n++)c[n]&&s.patch(e,e.childNodes[n],t[n],c[n]);return o}removeExtraChildren(e,t,n,s){const i=t.c?t.c.length:0;if(!(i<=n))for(let o=i;o-- >n;){const n=e.lastChild;n&&(s._unmountNodeAndChildren(t.c[o]),n.remove())}}}class y{constructor(e,t,n){this.generateTree=e||f,this.renderer=t,this.lifecycleQueue=n}mount(e,t,n){const s=this.generateTree(t(),n);return this.renderer.mount(e,s),this.lifecycleQueue.flush(),s}update(e,t,n,s){const i=this.generateTree(t(),n);return this.renderer.patch(e,e.firstChild,i,s),this.lifecycleQueue.flush(),i}unmount(e,t){t&&(this.renderer.unmount(e,t),this.lifecycleQueue.flush())}}class m{constructor(e,t){void 0===t&&(t="microtask"),this._renderFn=e,this._scheduler=t,this._scheduled=!1}schedule(){this._scheduled||(this._scheduled=!0,"microtask"===this._scheduler?Promise.resolve().then(()=>this._execute()):"sync"===this._scheduler&&this._execute())}_execute(){this._scheduled=!1,this._renderFn()}}class _{constructor(e,t){void 0===t&&(t={}),this.rootComponent=e,this.savedTree=e,this.currentTree=null,this.rootNode=null,this.stateManager=new r(t),this.lifecycleQueue=new l,this.eventManager=new a,this.renderer=new h(this.eventManager,this.lifecycleQueue,new p),this.mountOrchestrator=new y(f,this.renderer,this.lifecycleQueue),this.updateLoop=new m(()=>this.update(),"microtask"),this._boundSchedule=()=>this.updateLoop.schedule(),this.stateManager.subscribe(this._boundSchedule)}mount(e){if(this.rootNode=document.getElementById(e),!this.rootNode)throw new Error(`Cannot mount app: element with id "${e}" not found`);return this.eventManager.setRootNode(this.rootNode),this.currentTree=this.mountOrchestrator.mount(this.rootNode,this.savedTree,this.stateManager),this}unmount(){this.mountOrchestrator.unmount(this.rootNode,this.currentTree),this.eventManager.destroy(),this.stateManager.unsubscribe(()=>this.updateLoop.schedule()),this.rootNode&&(this.rootNode.innerHTML=""),this.currentTree=null,this.rootNode=null}scheduleUpdate(){this.updateLoop.schedule()}update(){this.rootNode&&this.savedTree&&(this.currentTree=this.mountOrchestrator.update(this.rootNode,this.savedTree,this.stateManager,this.currentTree))}getStore(){return this.stateManager.getStore()}setStore(e,t){this.stateManager.setStore(e,t)}}e.App=_,e.EventManager=a,e.LifecycleQueue=l,e.Renderer=h,e.StateManager=r,e.component=function(e){let t=void 0===e?{}:e,n=t.name,o=void 0===n?"":n,r=t.state,h=void 0===r?{}:r,d=t.mounted,c=void 0===d?function(){}:d,u=t.updated,a=void 0===u?function(){}:u,l=t.unmounted,f=void 0===l?function(){}:l,p=t.methods,y=void 0===p?function(){}:p,m=t.render,_=void 0===m?function(){}:m;const g=s(),v=new Map;return function(e){void 0===e&&(e={});const t=e.key||"__default__";if(!v.has(t)){const n=s(),r=o+(e.key?"_"+e.key:"");v.set(t,{definitionId:g,instanceId:n,key:`${g}_${n}_${r}`,_props:null,_cachedRender:null,bind(e){const t=new i(g,n,r,this._props,{state:h,mounted:c,updated:a,unmounted:f,methods:y,render:_},e);return t.bindMethods(y),t}})}const n=v.get(t);return n._props=e,n}},e.createApp=function(e,t,n){const s=new _(e,n);return s.mount(t),s},e.flatten=n,e.generateTree=f,e.generateUUID=s,e.h=function(e,s){const i={};for(let e in s)i[e]=s[e];return new t(e,i,n([],[].slice.call(arguments,2)))},e.isVNode=function(e){return e instanceof t||null!==e&&"object"==typeof e&&"e"in e},e.render=function(e,t,n){void 0===n&&(n={});const s=new _(e,n);return s.mount(t),s}});
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e||self).literaljs={})}(this,function(e){class t{constructor(e,t,n){void 0===t&&(t={}),void 0===n&&(n=[]),this.e=e,this.a=t,this.c=n}withLifecycle(e){return e.mounted&&(this.m=e.mounted),e.updated&&(this.up=e.updated),e.unmounted&&(this.un=e.unmounted),e.deleteState&&(this.d=e.deleteState),this}withIdentity(e,t){return this.definitionId=e,this.instanceId=t,this.id=e+"_"+t,this}}function n(e,t){for(let s=0,i=t.length;s<i;s++)Array.isArray(t[s])?n(e,t[s]):null!=t[s]&&"boolean"!=typeof t[s]&&e.push(t[s]);return e}function s(){return Math.random().toString(36).substring(2)+(new Date).getTime().toString(36)}class i{constructor(e,t,n,s,i,o){this.definitionId=e,this.instanceId=t,this.name=n,this.key=`${e}_${t}_${n}`,this.props=s,this._stateManager=o,this._config=i,o.createState(this.key,i.state),this.mounted=i.mounted.bind(this),this.updated=i.updated.bind(this),this.unmounted=i.unmounted.bind(this),this.deleteState=()=>{this._stateManager.deleteState(this.key)},this._renderedVNode=null,this._previousProps=null;const r=i.render.bind(this);this.render=()=>{if(!this.shouldUpdate())return this._renderedVNode;const e=r();return this._renderedVNode=e,this._previousProps=this.props,e}}getStore(){return this._stateManager.getStore()}setStore(e,t){this._stateManager.setStore(e,t)}getState(){return this._stateManager.getState(this.key)}setState(e,t){this._stateManager.setState(this.key,e,t)}createState(){this._stateManager.createState(this.key,this._config.state)}deleteState(){this._stateManager.deleteState(this.key)}shouldUpdate(){return!this._previousProps||!function(e,t){if(e===t)return!0;if(!e||!t||"object"!=typeof e||"object"!=typeof t)return!1;const n=Object.keys(e),s=Object.keys(t);if(n.length!==s.length)return!1;for(let s=0;s<n.length;s++)if(e[n[s]]!==t[n[s]])return!1;return!0}(this.props,this._previousProps)}bindMethods(e){"function"==typeof e&&(e=e.bind(this)());for(let t in e)this[t]=e[t].bind(this)}}let o=0;function r(){o++}function h(e,t){for(let n in t)e[n]=t[n];return e}class d{constructor(e){void 0===e&&(e={}),this.store={...e},this.componentStates={},this.listeners=[]}subscribe(e){this.listeners.push(e)}unsubscribe(e){const t=this.listeners.indexOf(e);t>-1&&this.listeners.splice(t,1)}_notify(){for(let e=0;e<this.listeners.length;e++)this.listeners[e]()}getStore(){return{...this.store}}setStore(e,t){"function"==typeof e&&(e=e(this.store)),this.store=h(h({},this.store),e),this._notify(),"function"==typeof t&&t()}createState(e,t){e in this.componentStates||(this.componentStates[e]={...t})}getState(e){return{...this.componentStates[e]}}setState(e,t,n){"function"==typeof t&&(t=t(this.componentStates[e])),this.componentStates[e]=h(h({},this.componentStates[e]),t),this._notify(),"function"==typeof n&&n()}deleteState(e){delete this.componentStates[e]}reset(){this.store={},this.componentStates={},this.listeners=[]}}class u{constructor(e,t,n){this.eventManager=e,this.lifecycleQueue=t,this.diffEngine=n}mount(e,t){const n=this.createElement(t);n&&e.appendChild(n)}createElement(e){if(null==e)return document.createTextNode("");const t=typeof e;return"string"===t||"number"===t?document.createTextNode(e):"boolean"===t||"undefined"===t?document.createTextNode(""):"object"===t&&e.e?this._createElementNode(e):null}_createElementNode(e){const t=document.createElement(e.e);if("object"==typeof e.a){const n=Object.keys(e.a);for(let s=n.length;s--;)if("events"===n[s])e.eid=this.eventManager.bindEvents(t,e.a[n[s]]);else if("style"===n[s])this._addStyles(e.a[n[s]],t);else{if("key"===n[s])continue;t.setAttribute(n[s],e.a[n[s]])}}if(this.lifecycleQueue.mounted(e),Array.isArray(e.c))for(let n=0,s=e.c.length;n<s;n++){const s=this.createElement(e.c[n]);s&&t.appendChild(s)}return t}_addStyles(e,t){if(void 0===e)return;const n=Object.keys(e);for(let s=n.length;s--;)t.style[n[s]]=e[n[s]]}patch(e,t,n,s){const i=typeof n;if(void 0===s)this._appendChild(e,n);else if("undefined"===i)this._unmountNodeAndChildren(s),t&&t.remove();else if(this.diffEngine.areNodesEqual(n,s)){if("object"===i&&n.e){if(n===s)return;if(this._updateNodes(t,n,s),n.c!==s.c)if(this.diffEngine._hasKeys(n.c)||this.diffEngine._hasKeys(s.c))this.diffEngine.reconcileChildren(t,n.c,s.c,this);else{let e;for(let i=s.c?s.c.length:0;i--&&void 0===n.c[i];)e=t.lastChild,e&&(this._unmountNodeAndChildren(s.c[i]),e.remove());if(Array.isArray(n.c))for(let e=0,i=n.c.length;e<i;e++)this.patch(t,t.childNodes[e]||null,n.c[e],s.c?s.c[e]:void 0)}}}else if(!t||3!==t.nodeType||"string"!==i&&"number"!==i)this._unmountNodeAndChildren(s),t&&e.replaceChild(this.createElement(n),t);else{const e=String(n);t.textContent!==e&&(t.textContent=e)}}_appendChild(e,t){const n=this.createElement(t);n&&e.appendChild(n)}_updateNodes(e,t,n){if(this.lifecycleQueue.updated(t),t.a===n.a)return;if(!t.a||!n.a)return;const s=Object.keys(t.a);let i,o;for(let r=s.length;r--;)if(o=t.a[s[r]],i=n.a[s[r]],"style"===s[r]){if(this._stylesAreEqual(o,i))continue;e.removeAttribute(s[r]),this._addStyles(o,e)}else if("events"===s[r])this.eventManager.unbindEvents(e,n.eid),t.eid=this.eventManager.bindEvents(e,o);else{if("key"===s[r])continue;"value"===s[r]&&o!==i?e.value=o:void 0!==i&&o===i||e.setAttribute(s[r],o)}}_stylesAreEqual(e,t){if(e===t)return!0;const n=typeof e,s=typeof t;if("undefined"===n&&"undefined"===s)return!0;if("object"!==n||"object"!==s)return!1;const i=Object.keys(e),o=Object.keys(t);if(i.length!==o.length)return!1;for(let n=i.length;n--;)if(e[i[n]]!==t[i[n]])return!1;return!0}_unmountNodeAndChildren(e){if(null!=e&&(this.lifecycleQueue.unmounted(e),this.lifecycleQueue.deleteState(e),this.eventManager.deleteCachedEvent(e.eid),Array.isArray(e.c)))for(let t=e.c.length;t--;)this._unmountNodeAndChildren(e.c[t])}unmount(e,t){this._unmountNodeAndChildren(t),e&&(e.innerHTML="")}}class c{constructor(e,t,n){this._getCache=e,this._resolveUUID=t,this._elementToUUID=n,this._attachedTypes=new Set,this._rootNode=null}attach(e,t){this._attachedTypes.has(t)||(this._attachedTypes.add(t),this._rootNode=e,e._literaljs_hasEvents=!0,e.addEventListener(t,e=>this._handle(e)))}_handle(e){if(!this._rootNode||!this._rootNode._literaljs_hasEvents)return;let t=e.target;for(;t&&t!==this._rootNode;){let n;if(this._elementToUUID&&(n=this._elementToUUID.get(t))){const t=this._getCache(n);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}const s=this._resolveUUID(t);if("string"==typeof s){const t=this._getCache(s);if(t&&"function"==typeof t[e.type])return void t[e.type](e)}t=t.parentNode}}reset(){this._attachedTypes.clear()}}const a=["abort","blur","error","focus","load","mouseenter","mouseleave","resize","scroll","unload"],l="eid";class f{constructor(){this.cache={},this.rootNode=null,this._elementToUUID=new WeakMap,this.eventBus=new c(e=>this.cache[e],e=>this.getEventUUID(e),this._elementToUUID)}setRootNode(e){this.rootNode=e}getEventUUID(e){if(!e||!e.parentNode)return;if("#document"===e.parentNode.nodeName)return;const t=e.getAttribute("data-"+l);return"string"==typeof t?t:this.getEventUUID(e.parentNode)}bindEvents(e,t){const n=s();e.setAttribute("data-"+l,n),this.cache[n]=t,this._elementToUUID.set(e,n);const i=Object.keys(t);for(let t=i.length;t--;)a.includes(i[t])?e.addEventListener(i[t],this.cache[n][i[t]]):this.eventBus.attach(this.rootNode,i[t]);return n}unbindEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)a.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]]);this.deleteCachedEvent(t),this._elementToUUID.delete(e),e.removeAttribute("data-"+l)}addEvents(e,t,n){n.setAttribute("data-"+l,e),this.cache[e]=t,this._elementToUUID.set(n,e);const s=Object.keys(t);for(let t=s.length;t--;)a.includes(s[t])?n.addEventListener(s[t],this.cache[e][s[t]]):this.eventBus.attach(this.rootNode,s[t])}removeIndividualEvents(e,t){if(!this.cache[t])return;const n=Object.keys(this.cache[t]);for(let s=n.length;s--;)a.includes(n[s])&&e.removeEventListener(n[s],this.cache[t][n[s]])}deleteCachedEvent(e){"string"==typeof e&&delete this.cache[e]}destroy(){this.rootNode&&(this.rootNode._literaljs_hasEvents=!1),this.cache={},this.rootNode=null,this.eventBus.reset()}}class p{constructor(){this.queue=[]}mounted(e){"object"==typeof e&&"function"==typeof e.m&&this.queue.push(e.m)}updated(e){"object"==typeof e&&"function"==typeof e.up&&this.queue.push(e.up)}unmounted(e){"object"==typeof e&&"function"==typeof e.un&&this.queue.push(e.un)}deleteState(e){"object"==typeof e&&"function"==typeof e.d&&this.queue.push(e.d)}flush(){let e;for(;e=this.queue.shift();)e()}clear(){this.queue=[]}}function y(e,n){if(null==e)return e;if("function"==typeof e.e){let t;t=e.a&&e.a.props?{...e.a.props}:e.a?{...e.a}:{},delete(e={e:e.e,a:{...e.a},c:e.c}).a.props,e=e.e(t)}if(e&&"function"==typeof e.bind){const s=e.bind(n);let i;try{i=s.render()}catch(e){console.error("Component render error:",e),i={e:"div",a:{class:"error-boundary"},c:[`${e.name}: ${e.message}`]}}if("object"==typeof i&&null!==i&&i instanceof t)i.withIdentity(e.definitionId||s.definitionId,e.instanceId||s.instanceId),i.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),e=i;else if("object"==typeof i&&null!==i){const n=new t(i.e,i.a,i.c);n.withIdentity(e.definitionId||s.definitionId,e.instanceId||s.instanceId),n.withLifecycle({mounted:s.mounted,updated:s.updated,unmounted:s.unmounted,deleteState:s.deleteState}),e=n}else e=i}if(e&&Array.isArray(e.c))for(let t=0,s=e.c.length;t<s;t++)e.c[t]=y(e.c[t],n);return e}class m{areNodesEqual(e,t){const n=typeof e;return n===typeof t&&("object"===n&&e&&t&&e.e===t.e&&e.id===t.id||("string"===n||"number"===n)&&e===t)}reconcileChildren(e,t,n,s){return Array.isArray(t)?this._hasKeys(t)||this._hasKeys(n)?this._reconcileKeyed(e,t,n,s):this._reconcileNonKeyed(e,t,n,s):0}_reconcileNonKeyed(e,t,n,s){const i=t.length;if(0===i){if(n)for(let e=0;e<n.length;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const o=e.childNodes;for(let r=0;r<i;r++)s.patch(e,o[r]||null,t[r],n?n[r]:void 0);return i}_hasKeys(e){if(!Array.isArray(e))return!1;for(let t=0,n=e.length;t<n;t++)if(e[t]&&e[t].a&&null!=e[t].a.key)return!0;return!1}_reconcileKeyed(e,t,n,s){const i=n?n.length:0,o=t.length;if(0===o){for(let e=0;e<i;e++)s._unmountNodeAndChildren(n[e]);return e.innerHTML="",0}const r=Object.create(null),h=Object.create(null);for(let t=0;t<i;t++){const s=n[t].a?n[t].a.key:null,i=e.childNodes[t];null!=s&&i&&(r[s]=i,h[s]=n[t])}const d=new Array(o),u=new Array(o);for(let e=0;e<o;e++){const n=t[e].a?t[e].a.key:null;null!=n&&r[n]?(d[e]=r[n],u[e]=h[n],delete r[n]):(d[e]=null,u[e]=null)}for(const t in r){const n=r[t];n&&(s.patch(e,n,void 0,h[t]),n.remove())}let c=e.firstChild;for(let n=0;n<o;n++){const i=d[n];if(i&&i===c)c=c.nextSibling;else if(i)e.insertBefore(i,c);else{const i=s.createElement(t[n]);i&&e.insertBefore(i,c)}}for(;c;){const e=c.nextSibling;c.remove(),c=e}for(let n=0;n<o;n++)u[n]&&s.patch(e,e.childNodes[n],t[n],u[n]);return o}removeExtraChildren(e,t,n,s){const i=t.c?t.c.length:0;if(!(i<=n))for(let o=i;o-- >n;){const n=e.lastChild;n&&(s._unmountNodeAndChildren(t.c[o]),n.remove())}}}class _{constructor(e,t,n){this.generateTree=e||y,this.renderer=t,this.lifecycleQueue=n}mount(e,t,n){r();const s=this.generateTree(t(),n);return this.renderer.mount(e,s),this.lifecycleQueue.flush(),s}update(e,t,n,s){r();const i=this.generateTree(t(),n);return this.renderer.patch(e,e.firstChild,i,s),this.lifecycleQueue.flush(),i}unmount(e,t){t&&(this.renderer.unmount(e,t),this.lifecycleQueue.flush())}}class g{constructor(e,t){void 0===t&&(t="microtask"),this._renderFn=e,this._scheduler=t,this._scheduled=!1}schedule(){this._scheduled||(this._scheduled=!0,"microtask"===this._scheduler?Promise.resolve().then(()=>this._execute()):"sync"===this._scheduler&&this._execute())}_execute(){this._scheduled=!1,this._renderFn()}}class v{constructor(e,t){void 0===t&&(t={}),this.rootComponent=e,this.savedTree=e,this.currentTree=null,this.rootNode=null,this.stateManager=new d(t),this.lifecycleQueue=new p,this.eventManager=new f,this.renderer=new u(this.eventManager,this.lifecycleQueue,new m),this.mountOrchestrator=new _(y,this.renderer,this.lifecycleQueue),this.updateLoop=new g(()=>this.update(),"microtask"),this._boundSchedule=()=>this.updateLoop.schedule(),this.stateManager.subscribe(this._boundSchedule)}mount(e){if(this.rootNode=document.getElementById(e),!this.rootNode)throw new Error(`Cannot mount app: element with id "${e}" not found`);return this.eventManager.setRootNode(this.rootNode),this.currentTree=this.mountOrchestrator.mount(this.rootNode,this.savedTree,this.stateManager),this}unmount(){this.mountOrchestrator.unmount(this.rootNode,this.currentTree),this.eventManager.destroy(),this.stateManager.unsubscribe(()=>this.updateLoop.schedule()),this.rootNode&&(this.rootNode.innerHTML=""),this.currentTree=null,this.rootNode=null}scheduleUpdate(){this.updateLoop.schedule()}update(){this.rootNode&&this.savedTree&&(this.currentTree=this.mountOrchestrator.update(this.rootNode,this.savedTree,this.stateManager,this.currentTree))}getStore(){return this.stateManager.getStore()}setStore(e,t){this.stateManager.setStore(e,t)}}e.App=v,e.EventManager=f,e.LifecycleQueue=p,e.Renderer=u,e.StateManager=d,e.advanceRenderCycle=r,e.component=function(e){let t=void 0===e?{}:e,n=t.name,r=void 0===n?"":n,h=t.state,d=void 0===h?{}:h,u=t.mounted,c=void 0===u?function(){}:u,a=t.updated,l=void 0===a?function(){}:a,f=t.unmounted,p=void 0===f?function(){}:f,y=t.methods,m=void 0===y?function(){}:y,_=t.render,g=void 0===_?function(){}:_;const v=s(),b=new Map;let N=0,S=-1;return function(e){void 0===e&&(e={}),S!==o&&(N=0,S=o);const t=null!=e.key?String(e.key):`__auto_${N++}__`;if(!b.has(t)){const n=s(),o=r+(null!=e.key?"_"+String(e.key):"");b.set(t,{definitionId:v,instanceId:n,key:`${v}_${n}_${o}`,_props:null,_cachedRender:null,bind(e){const t=new i(v,n,o,this._props,{state:d,mounted:c,updated:l,unmounted:p,methods:m,render:g},e);return t.bindMethods(m),t}})}const n=b.get(t);return n._props=e,n}},e.createApp=function(e,t,n){const s=new v(e,n);return s.mount(t),s},e.flatten=n,e.generateTree=y,e.generateUUID=s,e.h=function(e,s){const i={};for(let e in s)i[e]=s[e];return new t(e,i,n([],[].slice.call(arguments,2)))},e.isVNode=function(e){return e instanceof t||null!==e&&"object"==typeof e&&"e"in e},e.render=function(e,t,n){void 0===n&&(n={});const s=new v(e,n);return s.mount(t),s}});
|