@siddh-dev/fabric 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +430 -0
- package/dist/core/component/ComponentInstance.d.ts +2 -0
- package/dist/core/component/ComponentInstance.js +15 -0
- package/dist/core/component/ComponentInstance.js.map +1 -0
- package/dist/core/component/ComponentRuntime.d.ts +3 -0
- package/dist/core/component/ComponentRuntime.js +19 -0
- package/dist/core/component/ComponentRuntime.js.map +1 -0
- package/dist/core/hooks/HookRuntime.d.ts +3 -0
- package/dist/core/hooks/HookRuntime.js +11 -0
- package/dist/core/hooks/HookRuntime.js.map +1 -0
- package/dist/core/hooks/useEffect.d.ts +4 -0
- package/dist/core/hooks/useEffect.js +68 -0
- package/dist/core/hooks/useEffect.js.map +1 -0
- package/dist/core/hooks/useState.d.ts +7 -0
- package/dist/core/hooks/useState.js +35 -0
- package/dist/core/hooks/useState.js.map +1 -0
- package/dist/core/jsx/jsx-dev-runtime.d.ts +2 -0
- package/dist/core/jsx/jsx-dev-runtime.js +5 -0
- package/dist/core/jsx/jsx-dev-runtime.js.map +1 -0
- package/dist/core/jsx/jsx-runtime.d.ts +3 -0
- package/dist/core/jsx/jsx-runtime.js +8 -0
- package/dist/core/jsx/jsx-runtime.js.map +1 -0
- package/dist/core/jsx/jsx.d.ts +68 -0
- package/dist/core/jsx/jsx.js +46 -0
- package/dist/core/jsx/jsx.js.map +1 -0
- package/dist/core/scheduler/Scheduler.d.ts +3 -0
- package/dist/core/scheduler/Scheduler.js +21 -0
- package/dist/core/scheduler/Scheduler.js.map +1 -0
- package/dist/core/vnode/VNode.d.ts +34 -0
- package/dist/core/vnode/VNode.js +24 -0
- package/dist/core/vnode/VNode.js.map +1 -0
- package/dist/core/vnode/createElement.d.ts +2 -0
- package/dist/core/vnode/createElement.js +5 -0
- package/dist/core/vnode/createElement.js.map +1 -0
- package/dist/dom/DOMProperties.d.ts +2 -0
- package/dist/dom/DOMProperties.js +46 -0
- package/dist/dom/DOMProperties.js.map +1 -0
- package/dist/dom/EventSystem.d.ts +7 -0
- package/dist/dom/EventSystem.js +53 -0
- package/dist/dom/EventSystem.js.map +1 -0
- package/dist/dom/Reconciler.d.ts +20 -0
- package/dist/dom/Reconciler.js +326 -0
- package/dist/dom/Reconciler.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime/createRoot.d.ts +6 -0
- package/dist/runtime/createRoot.js +25 -0
- package/dist/runtime/createRoot.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Siddhant Mul
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
# Fabric
|
|
2
|
+
|
|
3
|
+
A lightweight frontend UI runtime built from scratch with TypeScript.
|
|
4
|
+
|
|
5
|
+
Fabric is an experimental frontend runtime focused on understanding and implementing the core concepts behind modern UI libraries, including:
|
|
6
|
+
|
|
7
|
+
- Virtual DOM.
|
|
8
|
+
- Components.
|
|
9
|
+
- State.
|
|
10
|
+
- Effects.
|
|
11
|
+
- Reconciliation.
|
|
12
|
+
- Scheduling.
|
|
13
|
+
- DOM updates.
|
|
14
|
+
|
|
15
|
+
> Fabric is not a React clone. It is an independent runtime built from first principles.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
Fabric currently supports:
|
|
22
|
+
|
|
23
|
+
- Virtual DOM.
|
|
24
|
+
- `createElement()`.
|
|
25
|
+
- JSX.
|
|
26
|
+
- Automatic JSX runtime.
|
|
27
|
+
- Function components.
|
|
28
|
+
- Props.
|
|
29
|
+
- `useState()`.
|
|
30
|
+
- `useEffect()`.
|
|
31
|
+
- Effect cleanup.
|
|
32
|
+
- DOM events.
|
|
33
|
+
- Reconciliation.
|
|
34
|
+
- Keyed reconciliation.
|
|
35
|
+
- DOM property updates.
|
|
36
|
+
- Update scheduling and batching.
|
|
37
|
+
- Component lifecycle handling.
|
|
38
|
+
- TypeScript.
|
|
39
|
+
- Automated tests.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Runtime Overview
|
|
44
|
+
|
|
45
|
+
At a high level, Fabric works like this:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
JSX / createElement()
|
|
49
|
+
↓
|
|
50
|
+
JSX Runtime
|
|
51
|
+
↓
|
|
52
|
+
VNode
|
|
53
|
+
↓
|
|
54
|
+
Components
|
|
55
|
+
↓
|
|
56
|
+
State / Effects
|
|
57
|
+
↓
|
|
58
|
+
Scheduler
|
|
59
|
+
↓
|
|
60
|
+
Reconciliation
|
|
61
|
+
↓
|
|
62
|
+
DOM
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
For JSX, TypeScript uses Fabric's automatic JSX runtime:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
JSX
|
|
69
|
+
↓
|
|
70
|
+
TypeScript JSX transform
|
|
71
|
+
↓
|
|
72
|
+
@siddh-dev/fabric/jsx-runtime
|
|
73
|
+
↓
|
|
74
|
+
createElement()
|
|
75
|
+
↓
|
|
76
|
+
VNode
|
|
77
|
+
↓
|
|
78
|
+
Reconciliation
|
|
79
|
+
↓
|
|
80
|
+
DOM
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
When state changes:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
setState()
|
|
87
|
+
↓
|
|
88
|
+
schedule update
|
|
89
|
+
↓
|
|
90
|
+
component re-renders
|
|
91
|
+
↓
|
|
92
|
+
new VNode
|
|
93
|
+
↓
|
|
94
|
+
reconciliation
|
|
95
|
+
↓
|
|
96
|
+
DOM update
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Quick Example
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import {
|
|
105
|
+
createRoot,
|
|
106
|
+
useState
|
|
107
|
+
} from "@siddh-dev/fabric";
|
|
108
|
+
|
|
109
|
+
function Counter() {
|
|
110
|
+
const [count, setCount] = useState(0);
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<div>
|
|
114
|
+
<h1>Fabric</h1>
|
|
115
|
+
|
|
116
|
+
<p>
|
|
117
|
+
Count: {count}
|
|
118
|
+
</p>
|
|
119
|
+
|
|
120
|
+
<button onClick={() => setCount(count + 1)}>
|
|
121
|
+
Increment
|
|
122
|
+
</button>
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const container = document.getElementById("app");
|
|
128
|
+
|
|
129
|
+
if (container === null) {
|
|
130
|
+
throw new Error("App container not found.");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
createRoot(container).render(
|
|
134
|
+
<Counter />
|
|
135
|
+
);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Fabric supports the automatic JSX runtime, so you do not need to import `jsx()` manually.
|
|
139
|
+
|
|
140
|
+
For TypeScript consumers, configure JSX like this:
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"compilerOptions": {
|
|
145
|
+
"jsx": "react-jsx",
|
|
146
|
+
"jsxImportSource": "@siddh-dev/fabric"
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The `"jsxImportSource": "@siddh-dev/fabric"` option tells TypeScript to use Fabric's JSX runtime.
|
|
152
|
+
|
|
153
|
+
Application code does not need to manually import `jsx()`.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Installation
|
|
158
|
+
|
|
159
|
+
Using pnpm:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
pnpm add @siddh-dev/fabric
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Using npm:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npm install @siddh-dev/fabric
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
For development setup and TypeScript configuration, see the [Installation Guide](./docs/getting-started/installation.md).
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Documentation
|
|
176
|
+
|
|
177
|
+
The complete documentation is available in the [`docs/`](./docs/) directory.
|
|
178
|
+
|
|
179
|
+
### Getting Started
|
|
180
|
+
|
|
181
|
+
- [Installation](./docs/getting-started/installation.md)
|
|
182
|
+
- [Quick Start](./docs/getting-started/quick-start.md)
|
|
183
|
+
|
|
184
|
+
### Concepts
|
|
185
|
+
|
|
186
|
+
- [Architecture](./docs/concepts/architecture.md)
|
|
187
|
+
- [Virtual DOM](./docs/concepts/virtual-dom.md)
|
|
188
|
+
- [Components](./docs/concepts/components.md)
|
|
189
|
+
- [Props](./docs/concepts/props.md)
|
|
190
|
+
- [State](./docs/concepts/state.md)
|
|
191
|
+
- [Effects](./docs/concepts/effects.md)
|
|
192
|
+
|
|
193
|
+
### Runtime
|
|
194
|
+
|
|
195
|
+
- [JSX](./docs/runtime/jsx.md)
|
|
196
|
+
- [Events](./docs/runtime/events.md)
|
|
197
|
+
- [Reconciliation](./docs/runtime/reconciliation.md)
|
|
198
|
+
- [Keyed Reconciliation](./docs/runtime/keyed-reconciliation.md)
|
|
199
|
+
- [Scheduler](./docs/runtime/scheduler.md)
|
|
200
|
+
- [DOM](./docs/runtime/dom.md)
|
|
201
|
+
|
|
202
|
+
### API
|
|
203
|
+
|
|
204
|
+
- [Public API](./docs/api/public-api.md)
|
|
205
|
+
|
|
206
|
+
### Development
|
|
207
|
+
|
|
208
|
+
- [Testing](./docs/development/testing.md)
|
|
209
|
+
- [Packaging](./docs/development/packaging.md)
|
|
210
|
+
- [Contributing](./docs/development/contributing.md)
|
|
211
|
+
|
|
212
|
+
### Project
|
|
213
|
+
|
|
214
|
+
- [Roadmap](./docs/project/roadmap.md)
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Development
|
|
219
|
+
|
|
220
|
+
Clone the repository:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
git clone <repository-url>
|
|
224
|
+
cd Fabric
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Install dependencies:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
pnpm install
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Start development mode:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
pnpm dev
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Run tests in watch mode:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
pnpm test
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Run the test suite once:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
pnpm test:run
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Run type checking:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
pnpm check
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Build the package:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
pnpm build
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Clean generated build output:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
pnpm clean
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Testing
|
|
272
|
+
|
|
273
|
+
Fabric uses:
|
|
274
|
+
|
|
275
|
+
- Vitest.
|
|
276
|
+
- jsdom.
|
|
277
|
+
- TypeScript.
|
|
278
|
+
|
|
279
|
+
Run the complete test suite:
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
pnpm test:run
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Tests cover areas including:
|
|
286
|
+
|
|
287
|
+
- VNode creation.
|
|
288
|
+
- JSX.
|
|
289
|
+
- Components.
|
|
290
|
+
- Props.
|
|
291
|
+
- State.
|
|
292
|
+
- Effects.
|
|
293
|
+
- Effect cleanup.
|
|
294
|
+
- Events.
|
|
295
|
+
- Reconciliation.
|
|
296
|
+
- Keyed reconciliation.
|
|
297
|
+
- Scheduler behavior.
|
|
298
|
+
- Root rendering.
|
|
299
|
+
- DOM updates.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Project Structure
|
|
304
|
+
|
|
305
|
+
```text
|
|
306
|
+
Fabric/
|
|
307
|
+
├── src/
|
|
308
|
+
│ ├── core/
|
|
309
|
+
│ │ ├── component/
|
|
310
|
+
│ │ ├── hooks/
|
|
311
|
+
│ │ ├── jsx/
|
|
312
|
+
│ │ ├── scheduler/
|
|
313
|
+
│ │ └── vnode/
|
|
314
|
+
│ │
|
|
315
|
+
│ ├── dom/
|
|
316
|
+
│ │ ├── DOMProperties.ts
|
|
317
|
+
│ │ ├── EventSystem.ts
|
|
318
|
+
│ │ └── Reconciler.ts
|
|
319
|
+
│ │
|
|
320
|
+
│ ├── runtime/
|
|
321
|
+
│ │ └── createRoot.ts
|
|
322
|
+
│ │
|
|
323
|
+
│ └── index.ts
|
|
324
|
+
│
|
|
325
|
+
├── tests/
|
|
326
|
+
├── docs/
|
|
327
|
+
├── index.html
|
|
328
|
+
├── package.json
|
|
329
|
+
├── tsconfig.json
|
|
330
|
+
├── tests/tsconfig.json
|
|
331
|
+
└── vitest.config.ts
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
The runtime is broadly organized as:
|
|
335
|
+
|
|
336
|
+
```text
|
|
337
|
+
VNode
|
|
338
|
+
↓
|
|
339
|
+
Components / Hooks
|
|
340
|
+
↓
|
|
341
|
+
Scheduler
|
|
342
|
+
↓
|
|
343
|
+
Reconciler
|
|
344
|
+
↓
|
|
345
|
+
DOM
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## V0.1
|
|
351
|
+
|
|
352
|
+
The initial goal of Fabric is to establish a small but functional frontend runtime.
|
|
353
|
+
|
|
354
|
+
V0.1 focuses on:
|
|
355
|
+
|
|
356
|
+
- VNodes.
|
|
357
|
+
- JSX.
|
|
358
|
+
- Automatic JSX runtime.
|
|
359
|
+
- Function components.
|
|
360
|
+
- Props.
|
|
361
|
+
- State.
|
|
362
|
+
- Effects.
|
|
363
|
+
- Effect cleanup.
|
|
364
|
+
- Events.
|
|
365
|
+
- Reconciliation.
|
|
366
|
+
- Keyed reconciliation.
|
|
367
|
+
- Scheduler and batching.
|
|
368
|
+
- Basic DOM operations.
|
|
369
|
+
- Public API.
|
|
370
|
+
- Tests.
|
|
371
|
+
- Packaging.
|
|
372
|
+
- Documentation.
|
|
373
|
+
|
|
374
|
+
The V0.1 scope is intentionally limited. The goal is to establish a reliable foundation rather than implement every possible framework feature.
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## Future
|
|
379
|
+
|
|
380
|
+
Possible future areas include:
|
|
381
|
+
|
|
382
|
+
- Context.
|
|
383
|
+
- Additional hooks.
|
|
384
|
+
- Refs.
|
|
385
|
+
- Fragments.
|
|
386
|
+
- Memoization.
|
|
387
|
+
- Portals.
|
|
388
|
+
- Error boundaries.
|
|
389
|
+
- Suspense-like rendering.
|
|
390
|
+
- Advanced scheduling.
|
|
391
|
+
- Concurrent rendering.
|
|
392
|
+
- Server-side rendering.
|
|
393
|
+
- Hydration.
|
|
394
|
+
- Developer tools.
|
|
395
|
+
|
|
396
|
+
These are future possibilities, not commitments to the current V0.1 scope.
|
|
397
|
+
|
|
398
|
+
See the [Roadmap](./docs/project/roadmap.md) for more information.
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Contributing
|
|
403
|
+
|
|
404
|
+
Contributions are welcome.
|
|
405
|
+
|
|
406
|
+
Before contributing, read the [Contributing Guide](./docs/development/contributing.md).
|
|
407
|
+
|
|
408
|
+
For development information, see:
|
|
409
|
+
|
|
410
|
+
- [Testing](./docs/development/testing.md)
|
|
411
|
+
- [Packaging](./docs/development/packaging.md)
|
|
412
|
+
- [Architecture](./docs/concepts/architecture.md)
|
|
413
|
+
|
|
414
|
+
Good contributions can include:
|
|
415
|
+
|
|
416
|
+
- Bug fixes.
|
|
417
|
+
- Regression tests.
|
|
418
|
+
- Documentation improvements.
|
|
419
|
+
- Runtime improvements.
|
|
420
|
+
- Refactors that improve clarity.
|
|
421
|
+
- Performance improvements supported by measurements.
|
|
422
|
+
- Better package validation.
|
|
423
|
+
|
|
424
|
+
Please keep changes focused and aligned with Fabric's architecture.
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## License
|
|
429
|
+
|
|
430
|
+
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function createComponentInstance(component, props) {
|
|
2
|
+
return {
|
|
3
|
+
component,
|
|
4
|
+
props,
|
|
5
|
+
states: [],
|
|
6
|
+
stateIndex: 0,
|
|
7
|
+
effects: [],
|
|
8
|
+
effectIndex: 0,
|
|
9
|
+
renderedVNode: null,
|
|
10
|
+
dom: null,
|
|
11
|
+
mounted: false,
|
|
12
|
+
update: null
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=ComponentInstance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComponentInstance.js","sourceRoot":"","sources":["../../../src/core/component/ComponentInstance.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,uBAAuB,CACnC,SAA6B,EAE7B,KAAa;IAEb,OAAO;QACH,SAAS;QAET,KAAK;QAEL,MAAM,EAAE,EAAE;QAEV,UAAU,EAAE,CAAC;QAEb,OAAO,EAAE,EAAE;QAEX,WAAW,EAAE,CAAC;QAEd,aAAa,EAAE,IAAI;QAEnB,GAAG,EAAE,IAAI;QAET,OAAO,EAAE,KAAK;QAEd,MAAM,EAAE,IAAI;KACf,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
let currentComponent = null;
|
|
2
|
+
export function runComponent(instance, callback) {
|
|
3
|
+
const previousComponent = currentComponent;
|
|
4
|
+
currentComponent =
|
|
5
|
+
instance;
|
|
6
|
+
instance.stateIndex = 0;
|
|
7
|
+
instance.effectIndex = 0;
|
|
8
|
+
try {
|
|
9
|
+
return callback();
|
|
10
|
+
}
|
|
11
|
+
finally {
|
|
12
|
+
currentComponent =
|
|
13
|
+
previousComponent;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function getCurrentComponent() {
|
|
17
|
+
return currentComponent;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=ComponentRuntime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComponentRuntime.js","sourceRoot":"","sources":["../../../src/core/component/ComponentRuntime.ts"],"names":[],"mappings":"AAIA,IAAI,gBAAgB,GAEP,IAAI,CAAC;AAElB,MAAM,UAAU,YAAY,CACxB,QAA4B,EAE5B,QAAiB;IAEjB,MAAM,iBAAiB,GACnB,gBAAgB,CAAC;IAErB,gBAAgB;QACZ,QAAQ,CAAC;IAEb,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC;IAExB,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAC;IAEzB,IAAI,CAAC;QACD,OAAO,QAAQ,EAAE,CAAC;IACtB,CAAC;YAAS,CAAC;QACP,gBAAgB;YACZ,iBAAiB,CAAC;IAC1B,CAAC;AACL,CAAC;AAED,MAAM,UAAU,mBAAmB;IAG/B,OAAO,gBAAgB,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function getHookIndex(instance) {
|
|
2
|
+
const index = instance.stateIndex;
|
|
3
|
+
instance.stateIndex++;
|
|
4
|
+
return index;
|
|
5
|
+
}
|
|
6
|
+
export function getEffectIndex(instance) {
|
|
7
|
+
const index = instance.effectIndex;
|
|
8
|
+
instance.effectIndex++;
|
|
9
|
+
return index;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=HookRuntime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HookRuntime.js","sourceRoot":"","sources":["../../../src/core/hooks/HookRuntime.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,YAAY,CACxB,QAA4B;IAE5B,MAAM,KAAK,GACP,QAAQ,CAAC,UAAU,CAAC;IAExB,QAAQ,CAAC,UAAU,EAAE,CAAC;IAEtB,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,cAAc,CAC1B,QAA4B;IAE5B,MAAM,KAAK,GACP,QAAQ,CAAC,WAAW,CAAC;IAEzB,QAAQ,CAAC,WAAW,EAAE,CAAC;IAEvB,OAAO,KAAK,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IComponentInstance } from "../vnode/VNode.js";
|
|
2
|
+
export declare function useEffect(callback: () => void | (() => void), dependencies?: readonly unknown[] | undefined): void;
|
|
3
|
+
export declare function executeEffects(instance: IComponentInstance): void;
|
|
4
|
+
export declare function cleanupEffects(instance: IComponentInstance): void;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { getCurrentComponent } from "../component/ComponentRuntime.js";
|
|
2
|
+
import { getEffectIndex } from "./HookRuntime.js";
|
|
3
|
+
export function useEffect(callback, dependencies) {
|
|
4
|
+
const instance = getCurrentComponent();
|
|
5
|
+
if (instance === null) {
|
|
6
|
+
throw new Error("useEffect() must be called inside a component.");
|
|
7
|
+
}
|
|
8
|
+
const index = getEffectIndex(instance);
|
|
9
|
+
const previous = instance.effects[index];
|
|
10
|
+
const effect = {
|
|
11
|
+
callback,
|
|
12
|
+
dependencies,
|
|
13
|
+
previousDependencies: previous?.dependencies,
|
|
14
|
+
cleanup: previous?.cleanup ?? null
|
|
15
|
+
};
|
|
16
|
+
instance.effects[index] =
|
|
17
|
+
effect;
|
|
18
|
+
}
|
|
19
|
+
function areDependenciesEqual(previous, next) {
|
|
20
|
+
if (previous === undefined ||
|
|
21
|
+
next === undefined) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (previous.length !==
|
|
25
|
+
next.length) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
for (let index = 0; index < next.length; index++) {
|
|
29
|
+
if (!Object.is(previous[index], next[index])) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
export function executeEffects(instance) {
|
|
36
|
+
for (const effect of instance.effects) {
|
|
37
|
+
const shouldRun = effect.previousDependencies ===
|
|
38
|
+
undefined ||
|
|
39
|
+
effect.dependencies ===
|
|
40
|
+
undefined ||
|
|
41
|
+
!areDependenciesEqual(effect.previousDependencies, effect.dependencies);
|
|
42
|
+
if (!shouldRun) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (effect.cleanup !== null) {
|
|
46
|
+
effect.cleanup();
|
|
47
|
+
effect.cleanup = null;
|
|
48
|
+
}
|
|
49
|
+
const cleanup = effect.callback();
|
|
50
|
+
if (typeof cleanup ===
|
|
51
|
+
"function") {
|
|
52
|
+
effect.cleanup =
|
|
53
|
+
cleanup;
|
|
54
|
+
}
|
|
55
|
+
effect.previousDependencies =
|
|
56
|
+
effect.dependencies;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export function cleanupEffects(instance) {
|
|
60
|
+
for (const effect of instance.effects) {
|
|
61
|
+
if (effect.cleanup !== null) {
|
|
62
|
+
effect.cleanup();
|
|
63
|
+
effect.cleanup = null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
instance.effects = [];
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=useEffect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEffect.js","sourceRoot":"","sources":["../../../src/core/hooks/useEffect.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EACtB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACH,cAAc,EACjB,MAAM,kBAAkB,CAAC;AAO1B,MAAM,UAAU,SAAS,CACrB,QAAmC,EAEnC,YAEe;IAEf,MAAM,QAAQ,GACV,mBAAmB,EAAE,CAAC;IAE1B,IACI,QAAQ,KAAK,IAAI,EACnB,CAAC;QACC,MAAM,IAAI,KAAK,CACX,gDAAgD,CACnD,CAAC;IACN,CAAC;IAED,MAAM,KAAK,GACP,cAAc,CACV,QAAQ,CACX,CAAC;IAEN,MAAM,QAAQ,GACV,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAE5B,MAAM,MAAM,GACQ;QAChB,QAAQ;QAER,YAAY;QAEZ,oBAAoB,EACpB,QAAQ,EAAE,YAAY;QAEtB,OAAO,EACH,QAAQ,EAAE,OAAO,IAAI,IAAI;KAChC,CAAC;IAEF,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC;QACnB,MAAM,CAAC;AACf,CAAC;AAED,SAAS,oBAAoB,CACzB,QAEe,EAEf,IAEe;IAEf,IACI,QAAQ,KAAK,SAAS;QACtB,IAAI,KAAK,SAAS,EACpB,CAAC;QACC,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,IACI,QAAQ,CAAC,MAAM;QACf,IAAI,CAAC,MAAM,EACb,CAAC;QACC,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,KACI,IAAI,KAAK,GAAG,CAAC,EACb,KAAK,GAAG,IAAI,CAAC,MAAM,EACnB,KAAK,EAAE,EACT,CAAC;QACC,IACI,CAAC,MAAM,CAAC,EAAE,CACN,QAAQ,CAAC,KAAK,CAAC,EACf,IAAI,CAAC,KAAK,CAAC,CACd,EACH,CAAC;YACC,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,cAAc,CAC1B,QAA4B;IAE5B,KACI,MAAM,MAAM,IACT,QAAQ,CAAC,OAAO,EACjB,CAAC;QACH,MAAM,SAAS,GACX,MAAM,CAAC,oBAAoB;YAC3B,SAAS;YACT,MAAM,CAAC,YAAY;gBACnB,SAAS;YACT,CAAC,oBAAoB,CACjB,MAAM,CAAC,oBAAoB,EAE3B,MAAM,CAAC,YAAY,CACtB,CAAC;QAEN,IACI,CAAC,SAAS,EACZ,CAAC;YACC,SAAS;QACb,CAAC;QAED,IACI,MAAM,CAAC,OAAO,KAAK,IAAI,EACzB,CAAC;YACC,MAAM,CAAC,OAAO,EAAE,CAAC;YAEjB,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;QAC1B,CAAC;QAED,MAAM,OAAO,GACT,MAAM,CAAC,QAAQ,EAAE,CAAC;QAEtB,IACI,OAAO,OAAO;YACd,UAAU,EACZ,CAAC;YACC,MAAM,CAAC,OAAO;gBACV,OAAO,CAAC;QAChB,CAAC;QAED,MAAM,CAAC,oBAAoB;YACvB,MAAM,CAAC,YAAY,CAAC;IAC5B,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAC1B,QAA4B;IAE5B,KACI,MAAM,MAAM,IACT,QAAQ,CAAC,OAAO,EACjB,CAAC;QACH,IACI,MAAM,CAAC,OAAO,KAAK,IAAI,EACzB,CAAC;YACC,MAAM,CAAC,OAAO,EAAE,CAAC;YAEjB,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;QAC1B,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,OAAO,GAAG,EAAE,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { scheduleUpdate } from "../scheduler/Scheduler.js";
|
|
2
|
+
import { getCurrentComponent } from "../component/ComponentRuntime.js";
|
|
3
|
+
import { getHookIndex } from "./HookRuntime.js";
|
|
4
|
+
export function useState(initialValue) {
|
|
5
|
+
const instance = getCurrentComponent();
|
|
6
|
+
if (instance === null) {
|
|
7
|
+
throw new Error("useState() must be called inside a component.");
|
|
8
|
+
}
|
|
9
|
+
const index = getHookIndex(instance);
|
|
10
|
+
if (index >=
|
|
11
|
+
instance.states.length) {
|
|
12
|
+
instance.states.push(initialValue);
|
|
13
|
+
}
|
|
14
|
+
const state = instance.states[index];
|
|
15
|
+
const setState = value => {
|
|
16
|
+
const previous = instance.states[index];
|
|
17
|
+
const next = typeof value ===
|
|
18
|
+
"function"
|
|
19
|
+
? value(previous)
|
|
20
|
+
: value;
|
|
21
|
+
if (Object.is(previous, next)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
instance.states[index] =
|
|
25
|
+
next;
|
|
26
|
+
if (instance.update !== null) {
|
|
27
|
+
scheduleUpdate(instance.update);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
return [
|
|
31
|
+
state,
|
|
32
|
+
setState
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=useState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useState.js","sourceRoot":"","sources":["../../../src/core/hooks/useState.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,cAAc,EACjB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACH,mBAAmB,EACtB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACH,YAAY,EACf,MAAM,kBAAkB,CAAC;AAU1B,MAAM,UAAU,QAAQ,CACpB,YAAe;IAKf,MAAM,QAAQ,GACV,mBAAmB,EAAE,CAAC;IAE1B,IACI,QAAQ,KAAK,IAAI,EACnB,CAAC;QACC,MAAM,IAAI,KAAK,CACX,+CAA+C,CAClD,CAAC;IACN,CAAC;IAED,MAAM,KAAK,GACP,YAAY,CACR,QAAQ,CACX,CAAC;IAEN,IACI,KAAK;QACL,QAAQ,CAAC,MAAM,CAAC,MAAM,EACxB,CAAC;QACC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAChB,YAAY,CACf,CAAC;IACN,CAAC;IAED,MAAM,KAAK,GACP,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAM,CAAC;IAEhC,MAAM,QAAQ,GAEV,KAAK,CAAC,EAAE;QACJ,MAAM,QAAQ,GACV,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAM,CAAC;QAEhC,MAAM,IAAI,GACN,OAAO,KAAK;YACZ,UAAU;YACN,CAAC,CACG,KAGH,CAAC,QAAQ,CAAC;YACX,CAAC,CAAC,KAAK,CAAC;QAEhB,IACI,MAAM,CAAC,EAAE,CACL,QAAQ,EACR,IAAI,CACP,EACH,CAAC;YACC,OAAO;QACX,CAAC;QAED,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;YAClB,IAAI,CAAC;QAET,IACI,QAAQ,CAAC,MAAM,KAAK,IAAI,EAC1B,CAAC;YACC,cAAc,CACV,QAAQ,CAAC,MAAM,CAClB,CAAC;QACN,CAAC;IACL,CAAC,CAAC;IAEN,OAAO;QACH,KAAK;QACL,QAAQ;KACX,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsx-dev-runtime.js","sourceRoot":"","sources":["../../../src/core/jsx/jsx-dev-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,uBAAuB,EAC1B,MAAM,UAAU,CAAC;AAQlB,MAAM,UAAU,MAAM,CAClB,IAAgB,EAChB,KAAoB;IAEpB,OAAO,uBAAuB,CAC1B,IAAI,EACJ,KAAK,CACR,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createAutomaticJSXVNode } from "./jsx.js";
|
|
2
|
+
export function jsx(type, props) {
|
|
3
|
+
return createAutomaticJSXVNode(type, props);
|
|
4
|
+
}
|
|
5
|
+
export function jsxs(type, props) {
|
|
6
|
+
return createAutomaticJSXVNode(type, props);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=jsx-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsx-runtime.js","sourceRoot":"","sources":["../../../src/core/jsx/jsx-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,uBAAuB,EAC1B,MAAM,UAAU,CAAC;AAQlB,MAAM,UAAU,GAAG,CACf,IAAgB,EAChB,KAAoB;IAEpB,OAAO,uBAAuB,CAC1B,IAAI,EACJ,KAAK,CACR,CAAC;AACN,CAAC;AAED,MAAM,UAAU,IAAI,CAChB,IAAgB,EAChB,KAAoB;IAEpB,OAAO,uBAAuB,CAC1B,IAAI,EACJ,KAAK,CACR,CAAC;AACN,CAAC"}
|