round-core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,106 @@
1
+ import { signal } from './signals.js';
2
+ import { createElement, Fragment } from './dom.js';
3
+
4
+ function isPromiseLike(v) {
5
+ return v && (typeof v === 'object' || typeof v === 'function') && typeof v.then === 'function';
6
+ }
7
+
8
+ export function lazy(loader) {
9
+ if (typeof loader !== 'function') {
10
+ throw new Error('lazy(loader) expects a function that returns a Promise');
11
+ }
12
+
13
+ let status = 'uninitialized';
14
+ let promise = null;
15
+ let component = null;
16
+ let error = null;
17
+
18
+ function pickComponent(mod) {
19
+ if (!mod) return null;
20
+ if (typeof mod === 'function') return mod;
21
+ if (typeof mod.default === 'function') return mod.default;
22
+ if (typeof mod.Counter === 'function') return mod.Counter;
23
+
24
+ const fns = [];
25
+ for (const k of Object.keys(mod)) {
26
+ if (typeof mod[k] === 'function') fns.push(mod[k]);
27
+ }
28
+ if (fns.length === 1) return fns[0];
29
+ return null;
30
+ }
31
+
32
+ return function LazyComponent(props = {}) {
33
+ if (status === 'resolved') {
34
+ return createElement(component, props);
35
+ }
36
+
37
+ if (status === 'rejected') {
38
+ throw error;
39
+ }
40
+
41
+ if (!promise) {
42
+ status = 'pending';
43
+ try {
44
+ promise = Promise.resolve(loader())
45
+ .then((mod) => {
46
+ const resolved = pickComponent(mod);
47
+ if (typeof resolved !== 'function') {
48
+ throw new Error('lazy() loaded module does not export a component');
49
+ }
50
+ component = resolved;
51
+ status = 'resolved';
52
+ })
53
+ .catch((e) => {
54
+ error = e instanceof Error ? e : new Error(String(e));
55
+ status = 'rejected';
56
+ });
57
+ } catch (e) {
58
+ error = e instanceof Error ? e : new Error(String(e));
59
+ status = 'rejected';
60
+ throw error;
61
+ }
62
+ }
63
+
64
+ throw promise;
65
+ };
66
+ }
67
+
68
+ export function Suspense(props = {}) {
69
+ const tick = signal(0);
70
+ let lastPromise = null;
71
+
72
+ const child = Array.isArray(props.children) ? props.children[0] : props.children;
73
+ const childFn = typeof child === 'function' ? child : () => child;
74
+
75
+ return createElement('span', { style: { display: 'contents' } }, () => {
76
+ tick();
77
+
78
+ try {
79
+ const res = childFn();
80
+ if (isPromiseLike(res)) {
81
+ if (lastPromise !== res) {
82
+ lastPromise = res;
83
+ res.then(
84
+ () => tick(tick.peek() + 1),
85
+ () => tick(tick.peek() + 1)
86
+ );
87
+ }
88
+ return props.fallback ?? null;
89
+ }
90
+ lastPromise = null;
91
+ return res ?? null;
92
+ } catch (e) {
93
+ if (isPromiseLike(e)) {
94
+ if (lastPromise !== e) {
95
+ lastPromise = e;
96
+ e.then(
97
+ () => tick(tick.peek() + 1),
98
+ () => tick(tick.peek() + 1)
99
+ );
100
+ }
101
+ return props.fallback ?? null;
102
+ }
103
+ throw e;
104
+ }
105
+ });
106
+ }
package/vite.config.js ADDED
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from 'vite';
2
+ import RoundPlugin from './src/compiler/vite-plugin.js';
3
+
4
+ export default defineConfig({
5
+ plugins: [RoundPlugin({ configPath: './start_exmpl/round.config.json' })],
6
+ root: './', // Serve from root
7
+ server: {
8
+ port: 3000
9
+ }
10
+ });
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: 'jsdom',
6
+ globals: true
7
+ }
8
+ });