loly-jsx 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/README.md +361 -0
- package/dist/dev-runtime-CEyE3QDn.js +207 -0
- package/dist/dev-runtime-CEyE3QDn.js.map +1 -0
- package/dist/dev-runtime-CRAwY4ll.cjs +2 -0
- package/dist/dev-runtime-CRAwY4ll.cjs.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +1206 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-dev-runtime.cjs +2 -0
- package/dist/jsx-dev-runtime.cjs.map +1 -0
- package/dist/jsx-dev-runtime.js +8 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.cjs +2 -0
- package/dist/jsx-runtime.cjs.map +1 -0
- package/dist/jsx-runtime.js +8 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/render-manifest.cjs +2 -0
- package/dist/render-manifest.cjs.map +1 -0
- package/dist/render-manifest.js +14 -0
- package/dist/render-manifest.js.map +1 -0
- package/package.json +93 -0
package/README.md
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
# loly-jsx
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
Lightweight JSX runtime with fine-grained reactivity, signals, computed values, and streaming server rendering.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install loly-jsx
|
|
12
|
+
# or
|
|
13
|
+
yarn add loly-jsx
|
|
14
|
+
# or
|
|
15
|
+
pnpm add loly-jsx
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { state, mount } from "loly-jsx";
|
|
22
|
+
|
|
23
|
+
function Counter() {
|
|
24
|
+
const [count, setCount] = state(0);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<button onClick={() => setCount(count + 1)}>
|
|
28
|
+
Count: {count}
|
|
29
|
+
</button>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
mount(<Counter />, document.getElementById("app")!);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Core Concepts
|
|
37
|
+
|
|
38
|
+
### Signals and Reactivity
|
|
39
|
+
|
|
40
|
+
loly-jsx uses a fine-grained reactivity system based on signals. Signals are reactive primitives that automatically track dependencies and update only what's necessary.
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { state, computed } from "loly-jsx";
|
|
44
|
+
|
|
45
|
+
// Create a signal
|
|
46
|
+
const [count, setCount] = state(0);
|
|
47
|
+
|
|
48
|
+
// Create a computed value
|
|
49
|
+
const doubled = computed(() => count() * 2);
|
|
50
|
+
|
|
51
|
+
// Signals are reactive in JSX
|
|
52
|
+
<div>Count: {count}, Doubled: {doubled}</div>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### JSX Runtime
|
|
56
|
+
|
|
57
|
+
loly-jsx provides its own JSX runtime that works seamlessly with TypeScript. Configure your `tsconfig.json`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"compilerOptions": {
|
|
62
|
+
"jsx": "react-jsx",
|
|
63
|
+
"jsxImportSource": "loly-jsx"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Stores
|
|
69
|
+
|
|
70
|
+
Stores provide scoped state management with SSR support. Use `createStore` to define a store and the `<Store>` component to provide scoped instances.
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { createStore, Store, useStore } from "loly-jsx";
|
|
74
|
+
|
|
75
|
+
// Define a store
|
|
76
|
+
const counterStore = createStore({ count: 0 }, "counterStore");
|
|
77
|
+
|
|
78
|
+
// Provide scoped store
|
|
79
|
+
function Layout({ children }) {
|
|
80
|
+
return (
|
|
81
|
+
<Store store={counterStore} initialData={{ count: 5 }}>
|
|
82
|
+
{children}
|
|
83
|
+
</Store>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Use store in components
|
|
88
|
+
function Counter() {
|
|
89
|
+
const store = useStore(counterStore);
|
|
90
|
+
return (
|
|
91
|
+
<button onClick={() => store.update(s => ({ count: s.count + 1 }))}>
|
|
92
|
+
{store.get().count}
|
|
93
|
+
</button>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Features
|
|
99
|
+
|
|
100
|
+
### SSR Rendering
|
|
101
|
+
|
|
102
|
+
Render components to HTML strings or streams for server-side rendering:
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
import { renderToString, renderToStream } from "loly-jsx";
|
|
106
|
+
|
|
107
|
+
// String rendering
|
|
108
|
+
const html = await renderToString(<App />);
|
|
109
|
+
|
|
110
|
+
// Streaming rendering
|
|
111
|
+
const stream = renderToStream(<App />, {
|
|
112
|
+
onAsyncTask: (id, fn) => {
|
|
113
|
+
// Handle async components
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Islands Architecture
|
|
119
|
+
|
|
120
|
+
Islands allow you to selectively hydrate components on the client. Define islands with `defineIsland` and use directives to control when they activate:
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import { defineIsland } from "loly-jsx";
|
|
124
|
+
|
|
125
|
+
const CounterIsland = defineIsland("CounterIsland", function Counter() {
|
|
126
|
+
const [count, setCount] = state(0);
|
|
127
|
+
return <button onClick={() => setCount(count + 1)}>{count}</button>;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Use with directives
|
|
131
|
+
<CounterIsland client:load /> // Load immediately
|
|
132
|
+
<CounterIsland client:idle /> // Load when idle
|
|
133
|
+
<CounterIsland client:visible /> // Load when visible
|
|
134
|
+
<CounterIsland client:media="(min-width: 768px)" /> // Load on media query
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Boot islands on the client:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { initLolyApplication } from "loly-jsx";
|
|
141
|
+
|
|
142
|
+
initLolyApplication();
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Router
|
|
146
|
+
|
|
147
|
+
Client-side routing with file-based route definitions:
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
import { defineRoutes, Router, Link, navigate } from "loly-jsx";
|
|
151
|
+
|
|
152
|
+
const routes = defineRoutes({
|
|
153
|
+
"/": () => <Home />,
|
|
154
|
+
"/about": () => <About />,
|
|
155
|
+
"/users/:id": ({ params }) => <User id={params.id} />,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
function App() {
|
|
159
|
+
return (
|
|
160
|
+
<div>
|
|
161
|
+
<nav>
|
|
162
|
+
<Link to="/">Home</Link>
|
|
163
|
+
<Link to="/about">About</Link>
|
|
164
|
+
</nav>
|
|
165
|
+
<Router routes={routes} />
|
|
166
|
+
</div>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Programmatic navigation
|
|
171
|
+
navigate("/about", { replace: true });
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Lists
|
|
175
|
+
|
|
176
|
+
Render reactive lists with the `<For>` component:
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
import { For, state } from "loly-jsx";
|
|
180
|
+
|
|
181
|
+
function TodoList() {
|
|
182
|
+
const [todos, setTodos] = state([
|
|
183
|
+
{ id: 1, text: "Learn loly-jsx" },
|
|
184
|
+
{ id: 2, text: "Build something" },
|
|
185
|
+
]);
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<For each={todos} key={(item) => item.id}>
|
|
189
|
+
{(item, ctx) => (
|
|
190
|
+
<div>
|
|
191
|
+
{item.text}
|
|
192
|
+
<button onClick={() => ctx.remove()}>Delete</button>
|
|
193
|
+
</div>
|
|
194
|
+
)}
|
|
195
|
+
</For>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Error Boundaries
|
|
201
|
+
|
|
202
|
+
Catch and handle errors in component trees:
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
import { ErrorBoundary } from "loly-jsx";
|
|
206
|
+
|
|
207
|
+
function App() {
|
|
208
|
+
return (
|
|
209
|
+
<ErrorBoundary
|
|
210
|
+
fallback={(error) => <div>Error: {error.message}</div>}
|
|
211
|
+
onError={(error) => console.error(error)}
|
|
212
|
+
>
|
|
213
|
+
<MyComponent />
|
|
214
|
+
</ErrorBoundary>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Lifecycle Hooks
|
|
220
|
+
|
|
221
|
+
Use lifecycle hooks in components:
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
import { onMount, onUnmount } from "loly-jsx";
|
|
225
|
+
|
|
226
|
+
function MyComponent() {
|
|
227
|
+
onMount(() => {
|
|
228
|
+
console.log("Component mounted");
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
onUnmount(() => {
|
|
232
|
+
console.log("Component unmounted");
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
return <div>Hello</div>;
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## API Reference
|
|
240
|
+
|
|
241
|
+
### Core
|
|
242
|
+
|
|
243
|
+
- `state<T>(initial: T)` - Create a reactive signal
|
|
244
|
+
- `computed<T>(fn: () => T)` - Create a computed value
|
|
245
|
+
- `createStore<T>(initial: T, storeId?: string)` - Create a store
|
|
246
|
+
- `Store` - Component to provide scoped store instances
|
|
247
|
+
- `useStore<T>(store: Store<T>)` - Hook to access scoped store
|
|
248
|
+
|
|
249
|
+
### JSX Runtime
|
|
250
|
+
|
|
251
|
+
- `jsx`, `jsxs`, `jsxDEV` - JSX runtime functions
|
|
252
|
+
- `h(type, props, ...children)` - Hyperscript function
|
|
253
|
+
- `Fragment` - Fragment component
|
|
254
|
+
|
|
255
|
+
### Rendering
|
|
256
|
+
|
|
257
|
+
- `mount(vnode, parent)` - Mount component to DOM
|
|
258
|
+
- `renderToString(node)` - Render to HTML string
|
|
259
|
+
- `renderToStream(node, options?)` - Render to stream
|
|
260
|
+
- `renderToHtml(options)` - Render full HTML document
|
|
261
|
+
- `renderToHtmlStream(options)` - Render HTML document as stream
|
|
262
|
+
|
|
263
|
+
### Islands
|
|
264
|
+
|
|
265
|
+
- `defineIsland(name, component)` - Define an island component
|
|
266
|
+
- `bootIslands(root?)` - Boot islands in the DOM
|
|
267
|
+
- `listRegisteredIslands()` - List all registered islands
|
|
268
|
+
|
|
269
|
+
### Router
|
|
270
|
+
|
|
271
|
+
- `defineRoutes(defs)` - Define route configuration
|
|
272
|
+
- `Router({ routes, url? })` - Router component
|
|
273
|
+
- `Link({ to, replace?, children })` - Link component
|
|
274
|
+
- `navigate(to, options?)` - Navigate programmatically
|
|
275
|
+
- `useLocation()` - Get current location signal
|
|
276
|
+
- `useParams()` - Get route params signal
|
|
277
|
+
|
|
278
|
+
### Lists
|
|
279
|
+
|
|
280
|
+
- `For<T>({ each, key?, children })` - List component
|
|
281
|
+
- `forBlock<T>(source, renderItem, getKey)` - Imperative list helper
|
|
282
|
+
|
|
283
|
+
### Utilities
|
|
284
|
+
|
|
285
|
+
- `createHead()` - Head collector for SSR
|
|
286
|
+
- `serializeData(data)` - Serialize data for SSR
|
|
287
|
+
- `injectData(key, data)` - Inject data into HTML
|
|
288
|
+
- `readData<T>(key)` - Read data from HTML
|
|
289
|
+
- `buildAssetsTags(input)` - Generate asset tags
|
|
290
|
+
- `configureRuntime(config)` - Configure runtime options
|
|
291
|
+
|
|
292
|
+
## Examples
|
|
293
|
+
|
|
294
|
+
### Counter with Store
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
import { createStore, Store, useStore, defineIsland } from "loly-jsx";
|
|
298
|
+
|
|
299
|
+
const counterStore = createStore({ count: 0 }, "counter");
|
|
300
|
+
|
|
301
|
+
const CounterIsland = defineIsland("Counter", function Counter() {
|
|
302
|
+
const store = useStore(counterStore);
|
|
303
|
+
return (
|
|
304
|
+
<div>
|
|
305
|
+
<p>Count: {store.get().count}</p>
|
|
306
|
+
<button onClick={() => store.update(s => ({ count: s.count + 1 }))}>
|
|
307
|
+
Increment
|
|
308
|
+
</button>
|
|
309
|
+
</div>
|
|
310
|
+
);
|
|
311
|
+
});
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Async Component
|
|
315
|
+
|
|
316
|
+
```tsx
|
|
317
|
+
import { state } from "loly-jsx";
|
|
318
|
+
|
|
319
|
+
async function UserProfile({ userId }) {
|
|
320
|
+
const user = await fetchUser(userId);
|
|
321
|
+
return <div>{user.name}</div>;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Component can return a Promise - handled automatically in SSR
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Form with Signals
|
|
328
|
+
|
|
329
|
+
```tsx
|
|
330
|
+
import { state, computed } from "loly-jsx";
|
|
331
|
+
|
|
332
|
+
function LoginForm() {
|
|
333
|
+
const [email, setEmail] = state("");
|
|
334
|
+
const [password, setPassword] = state("");
|
|
335
|
+
|
|
336
|
+
const isValid = computed(() =>
|
|
337
|
+
email().length > 0 && password().length >= 8
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
return (
|
|
341
|
+
<form>
|
|
342
|
+
<input
|
|
343
|
+
value={email()}
|
|
344
|
+
onInput={(e) => setEmail(e.target.value)}
|
|
345
|
+
/>
|
|
346
|
+
<input
|
|
347
|
+
type="password"
|
|
348
|
+
value={password()}
|
|
349
|
+
onInput={(e) => setPassword(e.target.value)}
|
|
350
|
+
/>
|
|
351
|
+
<button disabled={!isValid()}>Login</button>
|
|
352
|
+
</form>
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Links
|
|
358
|
+
|
|
359
|
+
- [Repository](https://github.com/MenvielleValen/loly)
|
|
360
|
+
- [Homepage](https://loly.dev)
|
|
361
|
+
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
const y = {
|
|
2
|
+
enableDevtools: !1,
|
|
3
|
+
enableWarnings: !1,
|
|
4
|
+
logLevel: "warn"
|
|
5
|
+
};
|
|
6
|
+
function W(e) {
|
|
7
|
+
e.enableDevtools !== void 0 && (y.enableDevtools = e.enableDevtools), e.enableWarnings !== void 0 && (y.enableWarnings = e.enableWarnings), e.logLevel !== void 0 && (y.logLevel = e.logLevel);
|
|
8
|
+
}
|
|
9
|
+
function h() {
|
|
10
|
+
return y;
|
|
11
|
+
}
|
|
12
|
+
const m = /* @__PURE__ */ new Set();
|
|
13
|
+
let p = !1;
|
|
14
|
+
const g = {
|
|
15
|
+
debug: 10,
|
|
16
|
+
info: 20,
|
|
17
|
+
warn: 30,
|
|
18
|
+
error: 40
|
|
19
|
+
};
|
|
20
|
+
function z(e) {
|
|
21
|
+
return m.add(e), () => m.delete(e);
|
|
22
|
+
}
|
|
23
|
+
function k(e, n, o, i) {
|
|
24
|
+
const t = h();
|
|
25
|
+
if (!t.enableDevtools || t.logLevel === "silent" || p) return;
|
|
26
|
+
const s = t.logLevel === "warn" ? g.warn : t.logLevel === "info" ? g.info : g.debug;
|
|
27
|
+
if (g[n] < s) return;
|
|
28
|
+
const r = {
|
|
29
|
+
scope: e,
|
|
30
|
+
level: n,
|
|
31
|
+
message: o,
|
|
32
|
+
payload: i,
|
|
33
|
+
timestamp: Date.now()
|
|
34
|
+
};
|
|
35
|
+
p = !0;
|
|
36
|
+
try {
|
|
37
|
+
m.forEach((l) => {
|
|
38
|
+
try {
|
|
39
|
+
l(r);
|
|
40
|
+
} catch {
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
} finally {
|
|
44
|
+
p = !1;
|
|
45
|
+
}
|
|
46
|
+
const c = `[loly-devtools][${e}]`;
|
|
47
|
+
switch (n) {
|
|
48
|
+
case "debug":
|
|
49
|
+
console.debug(c, o, i);
|
|
50
|
+
break;
|
|
51
|
+
case "info":
|
|
52
|
+
console.info(c, o, i);
|
|
53
|
+
break;
|
|
54
|
+
case "warn":
|
|
55
|
+
console.warn(c, o, i);
|
|
56
|
+
break;
|
|
57
|
+
case "error":
|
|
58
|
+
console.error(c, o, i);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
let d = null;
|
|
63
|
+
function F(e) {
|
|
64
|
+
let n = e;
|
|
65
|
+
const o = /* @__PURE__ */ new Set(), i = (l) => (o.add(l), () => o.delete(l)), t = () => {
|
|
66
|
+
if (d) {
|
|
67
|
+
const l = i(d.invalidate);
|
|
68
|
+
d.addDependency(l);
|
|
69
|
+
}
|
|
70
|
+
return n;
|
|
71
|
+
}, s = (l) => {
|
|
72
|
+
const u = typeof l == "function" ? l(n) : l, f = n;
|
|
73
|
+
n = u, h().enableWarnings && d && console.warn("[loly][signal] setting a signal while a computed is evaluating; posible loop"), h().enableDevtools && k("signal", "debug", "signal:update", { prev: f, next: u }), o.forEach((v) => v(n));
|
|
74
|
+
}, r = (l) => s(l(n)), c = () => t();
|
|
75
|
+
return c.get = t, c.set = s, c.update = r, c.subscribe = i, Object.defineProperty(c, "value", {
|
|
76
|
+
get: t,
|
|
77
|
+
set: s
|
|
78
|
+
}), [c, s];
|
|
79
|
+
}
|
|
80
|
+
function P(e) {
|
|
81
|
+
let n = !0, o, i = !1;
|
|
82
|
+
const t = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(), r = (a) => (t.add(a), () => t.delete(a)), c = () => {
|
|
83
|
+
s.forEach((a) => a()), s.clear();
|
|
84
|
+
}, l = () => {
|
|
85
|
+
n || (n = !0, i || (i = !0, queueMicrotask(() => {
|
|
86
|
+
if (n && t.size > 0) {
|
|
87
|
+
const a = f();
|
|
88
|
+
t.forEach((j) => j(a));
|
|
89
|
+
}
|
|
90
|
+
i = !1;
|
|
91
|
+
})));
|
|
92
|
+
}, u = () => {
|
|
93
|
+
c();
|
|
94
|
+
const a = d;
|
|
95
|
+
d = v;
|
|
96
|
+
try {
|
|
97
|
+
return o = e(), n = !1, h().enableDevtools && k("computed", "debug", "computed:evaluate", { value: o }), o;
|
|
98
|
+
} finally {
|
|
99
|
+
d = a;
|
|
100
|
+
}
|
|
101
|
+
}, f = () => {
|
|
102
|
+
if (d) {
|
|
103
|
+
const a = r(d.invalidate);
|
|
104
|
+
d.addDependency(a);
|
|
105
|
+
}
|
|
106
|
+
return n ? u() : o;
|
|
107
|
+
}, v = {
|
|
108
|
+
invalidate: l,
|
|
109
|
+
addDependency(a) {
|
|
110
|
+
s.add(a);
|
|
111
|
+
},
|
|
112
|
+
evaluate: u,
|
|
113
|
+
get: f
|
|
114
|
+
}, b = () => f();
|
|
115
|
+
return Object.defineProperty(b, "value", {
|
|
116
|
+
get: f,
|
|
117
|
+
configurable: !0
|
|
118
|
+
}), b.get = f, b.subscribe = (a) => (t.add(a), f(), () => t.delete(a)), b.toString = () => String(f()), b;
|
|
119
|
+
}
|
|
120
|
+
function L(e) {
|
|
121
|
+
const n = e;
|
|
122
|
+
return n !== null && (typeof e == "function" || typeof e == "object") && "get" in n && "set" in n && "subscribe" in n;
|
|
123
|
+
}
|
|
124
|
+
function R(e) {
|
|
125
|
+
const n = e;
|
|
126
|
+
return n !== null && (typeof e == "function" || typeof e == "object") && "get" in n && "subscribe" in n && !("set" in n);
|
|
127
|
+
}
|
|
128
|
+
const V = Symbol("Fragment");
|
|
129
|
+
function x(e) {
|
|
130
|
+
return typeof e == "object" && e !== null && "type" in e && "props" in e && "children" in e;
|
|
131
|
+
}
|
|
132
|
+
function D(e = []) {
|
|
133
|
+
const n = [], o = typeof window > "u", i = (t) => {
|
|
134
|
+
if (!(t == null || t === !1 || t === !0)) {
|
|
135
|
+
if (Array.isArray(t)) {
|
|
136
|
+
t.forEach((s) => i(s));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (x(t)) {
|
|
140
|
+
if (!o && t.children.some(
|
|
141
|
+
(r) => L(r) || R(r) || typeof r == "function"
|
|
142
|
+
)) {
|
|
143
|
+
n.push(() => t);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
n.push(t);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
n.push(t);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
return Array.isArray(e) ? e.forEach((t) => i(t)) : i(e), n;
|
|
153
|
+
}
|
|
154
|
+
function E(e, n = {}, o = [], i) {
|
|
155
|
+
const t = D(o);
|
|
156
|
+
return {
|
|
157
|
+
type: e,
|
|
158
|
+
props: n,
|
|
159
|
+
children: t,
|
|
160
|
+
key: i
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const w = "client:";
|
|
164
|
+
function C(e) {
|
|
165
|
+
let n;
|
|
166
|
+
for (const o of Object.keys(e)) {
|
|
167
|
+
if (!o.startsWith(w)) continue;
|
|
168
|
+
const i = o.slice(w.length), t = e[o];
|
|
169
|
+
if (delete e[o], i === "media" && typeof t == "string" && t.trim()) {
|
|
170
|
+
n = `media:${t.trim()}`;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
n = i;
|
|
174
|
+
}
|
|
175
|
+
return n;
|
|
176
|
+
}
|
|
177
|
+
function S(e, n = {}, o) {
|
|
178
|
+
const { children: i, ...t } = n ?? {}, s = D(i), r = { ...t }, c = C(r);
|
|
179
|
+
o !== void 0 ? r.key = o : r.key !== void 0 && (o = r.key, delete r.key);
|
|
180
|
+
const l = E(e, r, s, o);
|
|
181
|
+
return c && (l.__islandDirective = c), l;
|
|
182
|
+
}
|
|
183
|
+
const _ = S, A = S;
|
|
184
|
+
function O(e, n, ...o) {
|
|
185
|
+
const i = D(o), t = n && typeof n.key < "u" ? n.key : void 0, s = { ...n ?? {} }, r = C(s);
|
|
186
|
+
"key" in s && delete s.key;
|
|
187
|
+
const c = E(e, s, i, t);
|
|
188
|
+
return r && (c.__islandDirective = r), c;
|
|
189
|
+
}
|
|
190
|
+
export {
|
|
191
|
+
V as F,
|
|
192
|
+
R as a,
|
|
193
|
+
x as b,
|
|
194
|
+
P as c,
|
|
195
|
+
k as d,
|
|
196
|
+
E as e,
|
|
197
|
+
_ as f,
|
|
198
|
+
h as g,
|
|
199
|
+
W as h,
|
|
200
|
+
L as i,
|
|
201
|
+
A as j,
|
|
202
|
+
O as k,
|
|
203
|
+
D as n,
|
|
204
|
+
z as o,
|
|
205
|
+
F as s
|
|
206
|
+
};
|
|
207
|
+
//# sourceMappingURL=dev-runtime-CEyE3QDn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-runtime-CEyE3QDn.js","sources":["../src/runtime/config.ts","../src/devtools/logger.ts","../src/core/signal.ts","../src/core/vnode.ts","../src/jsx/runtime.tsx"],"sourcesContent":["export type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\";\r\n\r\nexport interface RuntimeConfig {\r\n enableDevtools: boolean;\r\n enableWarnings: boolean;\r\n logLevel: LogLevel;\r\n}\r\n\r\nconst config: RuntimeConfig = {\r\n enableDevtools: false,\r\n enableWarnings: false,\r\n logLevel: \"warn\"\r\n};\r\n\r\nexport function configureRuntime(partial: Partial<RuntimeConfig>) {\r\n if (partial.enableDevtools !== undefined) config.enableDevtools = partial.enableDevtools;\r\n if (partial.enableWarnings !== undefined) config.enableWarnings = partial.enableWarnings;\r\n if (partial.logLevel !== undefined) config.logLevel = partial.logLevel;\r\n}\r\n\r\nexport function getRuntimeConfig(): RuntimeConfig {\r\n return config;\r\n}\r\n\r\n","import { getRuntimeConfig } from \"../runtime/config\";\r\n\r\nexport type DevtoolsScope =\r\n | \"signal\"\r\n | \"store\"\r\n | \"computed\"\r\n | \"island\"\r\n | \"component\"\r\n | \"overlay\"\r\n | \"runtime\";\r\n\r\nexport type DevtoolsLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\r\n\r\nexport interface DevtoolsEvent {\r\n scope: DevtoolsScope;\r\n level: DevtoolsLevel;\r\n message: string;\r\n payload?: unknown;\r\n timestamp: number;\r\n}\r\n\r\ntype Listener = (event: DevtoolsEvent) => void;\r\n\r\nconst listeners = new Set<Listener>();\r\nlet isEmitting = false;\r\n\r\nconst levelOrder: Record<DevtoolsLevel, number> = {\r\n debug: 10,\r\n info: 20,\r\n warn: 30,\r\n error: 40\r\n};\r\n\r\nexport function onDevtoolsEvent(fn: Listener): () => void {\r\n listeners.add(fn);\r\n return () => listeners.delete(fn);\r\n}\r\n\r\nexport function devLog(scope: DevtoolsScope, level: DevtoolsLevel, message: string, payload?: unknown) {\r\n const cfg = getRuntimeConfig();\r\n if (!cfg.enableDevtools) return;\r\n if (cfg.logLevel === \"silent\") return;\r\n \r\n // Si ya estamos emitiendo, no emitir de nuevo (evita loops)\r\n if (isEmitting) return;\r\n \r\n const threshold = cfg.logLevel === \"warn\" ? levelOrder.warn : cfg.logLevel === \"info\" ? levelOrder.info : levelOrder.debug;\r\n if (levelOrder[level] < threshold) return;\r\n\r\n const evt: DevtoolsEvent = {\r\n scope,\r\n level,\r\n message,\r\n payload,\r\n timestamp: Date.now()\r\n };\r\n\r\n // Emit to listeners\r\n isEmitting = true;\r\n try {\r\n listeners.forEach((fn) => {\r\n try {\r\n fn(evt);\r\n } catch {\r\n // ignore listener errors\r\n }\r\n });\r\n } finally {\r\n isEmitting = false;\r\n }\r\n\r\n // Console fallback\r\n const prefix = `[loly-devtools][${scope}]`;\r\n switch (level) {\r\n case \"debug\":\r\n console.debug(prefix, message, payload);\r\n break;\r\n case \"info\":\r\n console.info(prefix, message, payload);\r\n break;\r\n case \"warn\":\r\n console.warn(prefix, message, payload);\r\n break;\r\n case \"error\":\r\n console.error(prefix, message, payload);\r\n break;\r\n }\r\n}\r\n","import { devLog } from \"../devtools/logger\";\nimport { getRuntimeConfig } from \"../runtime/config\";\n\nexport type Subscriber<T> = (value: T) => void;\n\nexport interface Signal<T> {\n (): T;\n get(): T;\n set(next: T | ((current: T) => T)): void;\n update(fn: (current: T) => T): void;\n subscribe(subscriber: Subscriber<T>): () => void;\n value: T;\n}\n\nexport interface Computed<T> {\n (): T;\n readonly value: T;\n get(): T;\n subscribe(subscriber: Subscriber<T>): () => void;\n toString(): string;\n}\n\ntype DepCleanup = () => void;\n\nlet activeComputed: InternalComputed<unknown> | null = null;\n\ninterface InternalComputed<T> {\n invalidate(): void;\n addDependency(cleanup: DepCleanup): void;\n evaluate(): T;\n get(): T;\n}\n\n/**\n * Nueva API de estado: devuelve [getter, setter].\n * El getter implementa la interfaz Signal<T> para compatibilidad interna.\n */\nexport function state<T>(initial: T): [Signal<T>, (next: T | ((current: T) => T)) => void] {\n let value = initial;\n const subscribers = new Set<Subscriber<T>>();\n\n const subscribe = (subscriber: Subscriber<T>) => {\n subscribers.add(subscriber);\n return () => subscribers.delete(subscriber);\n };\n\n const get = () => {\n if (activeComputed) {\n const unsubscribe = subscribe(activeComputed.invalidate);\n activeComputed.addDependency(unsubscribe);\n }\n return value;\n };\n\n const set = (next: T | ((current: T) => T)) => {\n const nextVal = typeof next === \"function\" ? (next as (c: T) => T)(value) : next;\n const prev = value;\n value = nextVal;\n if (getRuntimeConfig().enableWarnings && activeComputed) {\n console.warn(\"[loly][signal] setting a signal while a computed is evaluating; posible loop\");\n }\n if (getRuntimeConfig().enableDevtools) {\n devLog(\"signal\", \"debug\", \"signal:update\", { prev, next: nextVal });\n }\n subscribers.forEach((fn) => fn(value));\n };\n\n const update = (fn: (current: T) => T) => set(fn(value));\n\n // El getter también actúa como Signal<T>\n const getter = (() => get()) as Signal<T>;\n getter.get = get;\n getter.set = set;\n getter.update = update;\n getter.subscribe = subscribe;\n Object.defineProperty(getter, \"value\", {\n get,\n set\n });\n\n return [getter, set];\n}\n\nexport function computed<T>(fn: () => T): Computed<T> {\n let dirty = true;\n let cached!: T;\n let pendingNotification = false;\n\n const subscribers = new Set<Subscriber<T>>();\n const depCleanups = new Set<DepCleanup>();\n\n const subscribe = (subscriber: Subscriber<T>) => {\n subscribers.add(subscriber);\n return () => subscribers.delete(subscriber);\n };\n\n const cleanupDeps = () => {\n depCleanups.forEach((fn) => fn());\n depCleanups.clear();\n };\n\n const invalidate = () => {\n if (!dirty) {\n dirty = true;\n if (!pendingNotification) {\n pendingNotification = true;\n queueMicrotask(() => {\n if (dirty && subscribers.size > 0) {\n const newValue = get();\n subscribers.forEach((fn) => fn(newValue));\n }\n pendingNotification = false;\n });\n }\n }\n };\n\n const evaluate = (): T => {\n cleanupDeps();\n const prev = activeComputed;\n activeComputed = internal;\n try {\n cached = fn();\n dirty = false;\n if (getRuntimeConfig().enableDevtools) {\n devLog(\"computed\", \"debug\", \"computed:evaluate\", { value: cached });\n }\n return cached;\n } finally {\n activeComputed = prev;\n }\n };\n\n const get = (): T => {\n // Si hay un computed activo (otro computed que nos está leyendo), suscribirlo\n // Esto permite que los computed anidados funcionen correctamente\n if (activeComputed) {\n const unsubscribe = subscribe(activeComputed.invalidate);\n activeComputed.addDependency(unsubscribe);\n }\n \n if (dirty) return evaluate();\n return cached;\n };\n\n const internal: InternalComputed<T> = {\n invalidate,\n addDependency(cleanup) {\n depCleanups.add(cleanup);\n },\n evaluate,\n get\n };\n\n // Create a callable function that also has properties (like Signal)\n const computedFn = (() => get()) as Computed<T>;\n Object.defineProperty(computedFn, \"value\", {\n get,\n configurable: true\n });\n computedFn.get = get;\n computedFn.subscribe = (subscriber) => {\n subscribers.add(subscriber);\n // Ensure dependencies are tracked so invalidation works\n get();\n return () => subscribers.delete(subscriber);\n };\n computedFn.toString = () => String(get());\n\n return computedFn;\n}\n\n\nexport function isSignal(value: unknown): value is Signal<unknown> {\n const candidate = value as Record<string, unknown> | null;\n return (\n candidate !== null &&\n (typeof value === \"function\" || typeof value === \"object\") &&\n \"get\" in candidate &&\n \"set\" in candidate &&\n \"subscribe\" in candidate\n );\n}\n\nexport function isComputed(value: unknown): value is Computed<unknown> {\n const candidate = value as Record<string, unknown> | null;\n return (\n candidate !== null &&\n (typeof value === \"function\" || typeof value === \"object\") &&\n \"get\" in candidate &&\n \"subscribe\" in candidate &&\n !(\"set\" in candidate)\n );\n}\n\n","import type { Computed, Signal } from \"./signal\";\r\nimport { isSignal, isComputed } from \"./signal\";\r\nimport type { ForBlock } from \"../runtime/list\";\r\nimport type { ComponentInstance } from \"../runtime/instance\";\r\n\r\nexport const Fragment = Symbol(\"Fragment\");\r\n\r\nexport type PrimitiveChild = string | number | boolean | null | undefined;\r\nexport type VChild =\r\n | VNode\r\n | PrimitiveChild\r\n | Signal<unknown>\r\n | Computed<unknown>\r\n | (() => VChild)\r\n | ForBlock<any>\r\n | VChild[];\r\n\r\nexport type Component<Props = Record<string, unknown>> = (\r\n props: Props & { children?: VChild[] }\r\n) => VChild;\r\n\r\nexport interface VNode<Props = Record<string, unknown>> {\r\n type: string | Component<Props> | typeof Fragment;\r\n props: Record<string, unknown>;\r\n children: VChild[];\r\n key?: string | number;\r\n __instance?: ComponentInstance;\r\n __islandDirective?: string;\r\n}\r\n\r\nexport function isVNode(value: unknown): value is VNode {\r\n return (\r\n typeof value === \"object\" &&\r\n value !== null &&\r\n \"type\" in (value as Record<string, unknown>) &&\r\n \"props\" in (value as Record<string, unknown>) &&\r\n \"children\" in (value as Record<string, unknown>)\r\n );\r\n}\r\n\r\nexport function normalizeChildren(input: VChild | VChild[] = []): VChild[] {\r\n const result: VChild[] = [];\r\n const isSSR = typeof window === \"undefined\";\r\n\r\n const push = (value: VChild) => {\r\n if (value === null || value === undefined || value === false || value === true) {\r\n return;\r\n }\r\n if (Array.isArray(value)) {\r\n value.forEach((child) => push(child as VChild));\r\n return;\r\n }\r\n \r\n // Si es un VNode, verificar si tiene signals/computed/funciones directamente en children\r\n // Esto detecta expresiones condicionales como {submitted() ? <form> : <success>}\r\n // y las convierte en lambdas reactivas automáticamente\r\n // NOTA: En SSR (cuando window es undefined), NO convertimos a lambdas para evitar recursión\r\n if (isVNode(value)) {\r\n // Solo convertir a lambda reactiva en el cliente (no en SSR)\r\n if (!isSSR) {\r\n // Verificar si hay signals/computed/funciones DIRECTAMENTE en children\r\n // No verificar signals anidados en VNodes hijos para evitar falsos positivos\r\n // IMPORTANTE: En SSR, nunca convertir a lambda para evitar recursión infinita\r\n const hasDirectReactiveChildren = value.children.some(c => \r\n isSignal(c) || \r\n isComputed(c) || \r\n typeof c === \"function\"\r\n );\r\n \r\n // Si tiene children reactivos directos, convertir el VNode en lambda reactiva\r\n // Esto permite que expresiones condicionales sean automáticamente reactivas\r\n if (hasDirectReactiveChildren) {\r\n result.push(() => value);\r\n return;\r\n }\r\n }\r\n // En SSR, simplemente agregar el VNode sin modificar\r\n result.push(value);\r\n return;\r\n }\r\n \r\n result.push(value);\r\n };\r\n\r\n Array.isArray(input) ? input.forEach((child) => push(child)) : push(input);\r\n return result;\r\n}\r\n\r\nexport function createVNode(\r\n type: VNode[\"type\"],\r\n props: Record<string, unknown> = {},\r\n children: VChild[] = [],\r\n key?: string | number\r\n): VNode {\r\n const normalized = normalizeChildren(children);\r\n return {\r\n type,\r\n props,\r\n children: normalized,\r\n key\r\n };\r\n}\r\n\r\n","import { Fragment, VChild, createVNode, normalizeChildren } from \"../core/vnode\";\r\n\r\ntype AnyProps = Record<string, unknown>;\r\n\r\nconst DIRECTIVE_PREFIX = \"client:\";\r\n\r\nfunction extractDirective(props: AnyProps) {\r\n let directive: string | undefined;\r\n\r\n for (const key of Object.keys(props)) {\r\n if (!key.startsWith(DIRECTIVE_PREFIX)) continue;\r\n\r\n const mode = key.slice(DIRECTIVE_PREFIX.length);\r\n const value = props[key];\r\n\r\n delete props[key];\r\n\r\n if (mode === \"media\" && typeof value === \"string\" && value.trim()) {\r\n directive = `media:${value.trim()}`;\r\n continue;\r\n }\r\n\r\n directive = mode;\r\n }\r\n\r\n return directive;\r\n}\r\n\r\nfunction baseJsx(type: unknown, props: AnyProps = {}, key?: string | number) {\r\n const { children, ...rest } = props ?? {};\r\n const normalizedChildren = normalizeChildren(children as VChild | VChild[]);\r\n const cleanProps: AnyProps = { ...rest };\r\n const directive = extractDirective(cleanProps);\r\n if (key !== undefined) {\r\n cleanProps.key = key;\r\n } else if (cleanProps.key !== undefined) {\r\n key = cleanProps.key as string | number;\r\n delete cleanProps.key;\r\n }\r\n const vnode = createVNode(type as never, cleanProps, normalizedChildren, key);\r\n if (directive) {\r\n vnode.__islandDirective = directive;\r\n }\r\n return vnode;\r\n}\r\n\r\nexport const jsx = baseJsx;\r\nexport const jsxs = baseJsx;\r\n\r\nexport function h(type: unknown, props?: AnyProps, ...children: VChild[]) {\r\n const normalizedChildren = normalizeChildren(children);\r\n const key =\r\n props && typeof props.key !== \"undefined\" ? (props.key as string | number) : undefined;\r\n const cleanProps = { ...(props ?? {}) };\r\n const directive = extractDirective(cleanProps);\r\n if (\"key\" in cleanProps) {\r\n delete (cleanProps as Record<string, unknown>).key;\r\n }\r\n const vnode = createVNode(type as never, cleanProps, normalizedChildren, key);\r\n if (directive) {\r\n vnode.__islandDirective = directive;\r\n }\r\n return vnode;\r\n}\r\n\r\nexport { Fragment };\r\nexport type { VChild } from \"../core/vnode\";\r\n\r\ndeclare global {\r\n namespace JSX {\r\n type Element = any;\r\n interface ElementChildrenAttribute {\r\n children: {};\r\n }\r\n interface IntrinsicAttributes {\r\n [\"client:load\"]?: boolean;\r\n [\"client:idle\"]?: boolean;\r\n [\"client:visible\"]?: boolean;\r\n [\"client:media\"]?: string;\r\n }\r\n interface IntrinsicElements {\r\n [elemName: string]: Record<string, unknown>;\r\n }\r\n }\r\n}\r\n\r\n"],"names":["config","configureRuntime","partial","getRuntimeConfig","listeners","isEmitting","levelOrder","onDevtoolsEvent","fn","devLog","scope","level","message","payload","cfg","threshold","evt","prefix","activeComputed","state","initial","value","subscribers","subscribe","subscriber","get","unsubscribe","set","next","nextVal","prev","update","getter","computed","dirty","cached","pendingNotification","depCleanups","cleanupDeps","invalidate","newValue","evaluate","internal","cleanup","computedFn","isSignal","candidate","isComputed","Fragment","isVNode","normalizeChildren","input","result","isSSR","push","child","c","createVNode","type","props","children","key","normalized","DIRECTIVE_PREFIX","extractDirective","directive","mode","baseJsx","rest","normalizedChildren","cleanProps","vnode","jsx","jsxs","h"],"mappings":"AAQA,MAAMA,IAAwB;AAAA,EAC5B,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,UAAU;AACZ;AAEO,SAASC,EAAiBC,GAAiC;AAChE,EAAIA,EAAQ,mBAAmB,WAAWF,EAAO,iBAAiBE,EAAQ,iBACtEA,EAAQ,mBAAmB,WAAWF,EAAO,iBAAiBE,EAAQ,iBACtEA,EAAQ,aAAa,WAAWF,EAAO,WAAWE,EAAQ;AAChE;AAEO,SAASC,IAAkC;AAChD,SAAOH;AACT;ACCA,MAAMI,wBAAgB,IAAA;AACtB,IAAIC,IAAa;AAEjB,MAAMC,IAA4C;AAAA,EAChD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAEO,SAASC,EAAgBC,GAA0B;AACxD,SAAAJ,EAAU,IAAII,CAAE,GACT,MAAMJ,EAAU,OAAOI,CAAE;AAClC;AAEO,SAASC,EAAOC,GAAsBC,GAAsBC,GAAiBC,GAAmB;AACrG,QAAMC,IAAMX,EAAA;AAKZ,MAJI,CAACW,EAAI,kBACLA,EAAI,aAAa,YAGjBT,EAAY;AAEhB,QAAMU,IAAYD,EAAI,aAAa,SAASR,EAAW,OAAOQ,EAAI,aAAa,SAASR,EAAW,OAAOA,EAAW;AACrH,MAAIA,EAAWK,CAAK,IAAII,EAAW;AAEnC,QAAMC,IAAqB;AAAA,IACzB,OAAAN;AAAA,IACA,OAAAC;AAAA,IACA,SAAAC;AAAA,IACA,SAAAC;AAAA,IACA,WAAW,KAAK,IAAA;AAAA,EAAI;AAItB,EAAAR,IAAa;AACb,MAAI;AACF,IAAAD,EAAU,QAAQ,CAACI,MAAO;AACxB,UAAI;AACF,QAAAA,EAAGQ,CAAG;AAAA,MACR,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAAA,EACH,UAAA;AACE,IAAAX,IAAa;AAAA,EACf;AAGA,QAAMY,IAAS,mBAAmBP,CAAK;AACvC,UAAQC,GAAA;AAAA,IACN,KAAK;AACH,cAAQ,MAAMM,GAAQL,GAASC,CAAO;AACtC;AAAA,IACF,KAAK;AACH,cAAQ,KAAKI,GAAQL,GAASC,CAAO;AACrC;AAAA,IACF,KAAK;AACH,cAAQ,KAAKI,GAAQL,GAASC,CAAO;AACrC;AAAA,IACF,KAAK;AACH,cAAQ,MAAMI,GAAQL,GAASC,CAAO;AACtC;AAAA,EAAA;AAEN;AC/DA,IAAIK,IAAmD;AAahD,SAASC,EAASC,GAAkE;AACzF,MAAIC,IAAQD;AACZ,QAAME,wBAAkB,IAAA,GAElBC,IAAY,CAACC,OACjBF,EAAY,IAAIE,CAAU,GACnB,MAAMF,EAAY,OAAOE,CAAU,IAGtCC,IAAM,MAAM;AAChB,QAAIP,GAAgB;AAClB,YAAMQ,IAAcH,EAAUL,EAAe,UAAU;AACvD,MAAAA,EAAe,cAAcQ,CAAW;AAAA,IAC1C;AACA,WAAOL;AAAA,EACT,GAEMM,IAAM,CAACC,MAAkC;AAC7C,UAAMC,IAAU,OAAOD,KAAS,aAAcA,EAAqBP,CAAK,IAAIO,GACtEE,IAAOT;AACb,IAAAA,IAAQQ,GACJ1B,EAAA,EAAmB,kBAAkBe,KACvC,QAAQ,KAAK,8EAA8E,GAEzFf,EAAA,EAAmB,kBACrBM,EAAO,UAAU,SAAS,iBAAiB,EAAE,MAAAqB,GAAM,MAAMD,GAAS,GAEpEP,EAAY,QAAQ,CAACd,MAAOA,EAAGa,CAAK,CAAC;AAAA,EACvC,GAEMU,IAAS,CAACvB,MAA0BmB,EAAInB,EAAGa,CAAK,CAAC,GAGjDW,IAAU,MAAMP,EAAA;AACtB,SAAAO,EAAO,MAAMP,GACbO,EAAO,MAAML,GACbK,EAAO,SAASD,GAChBC,EAAO,YAAYT,GACnB,OAAO,eAAeS,GAAQ,SAAS;AAAA,IACrC,KAAAP;AAAA,IACA,KAAAE;AAAA,EAAA,CACD,GAEM,CAACK,GAAQL,CAAG;AACrB;AAEO,SAASM,EAAYzB,GAA0B;AACpD,MAAI0B,IAAQ,IACRC,GACAC,IAAsB;AAE1B,QAAMd,wBAAkB,IAAA,GAClBe,wBAAkB,IAAA,GAElBd,IAAY,CAACC,OACjBF,EAAY,IAAIE,CAAU,GACnB,MAAMF,EAAY,OAAOE,CAAU,IAGtCc,IAAc,MAAM;AACxB,IAAAD,EAAY,QAAQ,CAAC7B,MAAOA,EAAAA,CAAI,GAChC6B,EAAY,MAAA;AAAA,EACd,GAEME,IAAa,MAAM;AACvB,IAAKL,MACHA,IAAQ,IACHE,MACHA,IAAsB,IACtB,eAAe,MAAM;AACnB,UAAIF,KAASZ,EAAY,OAAO,GAAG;AACjC,cAAMkB,IAAWf,EAAA;AACjB,QAAAH,EAAY,QAAQ,CAACd,MAAOA,EAAGgC,CAAQ,CAAC;AAAA,MAC1C;AACA,MAAAJ,IAAsB;AAAA,IACxB,CAAC;AAAA,EAGP,GAEMK,IAAW,MAAS;AACxB,IAAAH,EAAA;AACA,UAAMR,IAAOZ;AACb,IAAAA,IAAiBwB;AACjB,QAAI;AACF,aAAAP,IAAS3B,EAAA,GACT0B,IAAQ,IACJ/B,EAAA,EAAmB,kBACrBM,EAAO,YAAY,SAAS,qBAAqB,EAAE,OAAO0B,GAAQ,GAE7DA;AAAA,IACT,UAAA;AACE,MAAAjB,IAAiBY;AAAA,IACnB;AAAA,EACF,GAEML,IAAM,MAAS;AAGnB,QAAIP,GAAgB;AAClB,YAAMQ,IAAcH,EAAUL,EAAe,UAAU;AACvD,MAAAA,EAAe,cAAcQ,CAAW;AAAA,IAC1C;AAEA,WAAIQ,IAAcO,EAAA,IACXN;AAAA,EACT,GAEMO,IAAgC;AAAA,IACpC,YAAAH;AAAA,IACA,cAAcI,GAAS;AACrB,MAAAN,EAAY,IAAIM,CAAO;AAAA,IACzB;AAAA,IACA,UAAAF;AAAA,IACA,KAAAhB;AAAA,EAAA,GAIImB,IAAc,MAAMnB,EAAA;AAC1B,gBAAO,eAAemB,GAAY,SAAS;AAAA,IACzC,KAAAnB;AAAA,IACA,cAAc;AAAA,EAAA,CACf,GACDmB,EAAW,MAAMnB,GACjBmB,EAAW,YAAY,CAACpB,OACtBF,EAAY,IAAIE,CAAU,GAE1BC,EAAA,GACO,MAAMH,EAAY,OAAOE,CAAU,IAE5CoB,EAAW,WAAW,MAAM,OAAOnB,EAAA,CAAK,GAEjCmB;AACT;AAGO,SAASC,EAASxB,GAA0C;AACjE,QAAMyB,IAAYzB;AAClB,SACEyB,MAAc,SACb,OAAOzB,KAAU,cAAc,OAAOA,KAAU,aACjD,SAASyB,KACT,SAASA,KACT,eAAeA;AAEnB;AAEO,SAASC,EAAW1B,GAA4C;AACrE,QAAMyB,IAAYzB;AAClB,SACEyB,MAAc,SACb,OAAOzB,KAAU,cAAc,OAAOA,KAAU,aACjD,SAASyB,KACT,eAAeA,KACf,EAAE,SAASA;AAEf;AC5LO,MAAME,IAAW,OAAO,UAAU;AAyBlC,SAASC,EAAQ5B,GAAgC;AACtD,SACE,OAAOA,KAAU,YACjBA,MAAU,QACV,UAAWA,KACX,WAAYA,KACZ,cAAeA;AAEnB;AAEO,SAAS6B,EAAkBC,IAA2B,IAAc;AACzE,QAAMC,IAAmB,CAAA,GACnBC,IAAQ,OAAO,SAAW,KAE1BC,IAAO,CAACjC,MAAkB;AAC9B,QAAI,EAAAA,KAAU,QAA+BA,MAAU,MAASA,MAAU,KAG1E;AAAA,UAAI,MAAM,QAAQA,CAAK,GAAG;AACxB,QAAAA,EAAM,QAAQ,CAACkC,MAAUD,EAAKC,CAAe,CAAC;AAC9C;AAAA,MACF;AAMA,UAAIN,EAAQ5B,CAAK,GAAG;AAElB,YAAI,CAACgC,KAI+BhC,EAAM,SAAS;AAAA,UAAK,CAAAmC,MACpDX,EAASW,CAAC,KACVT,EAAWS,CAAC,KACZ,OAAOA,KAAM;AAAA,QAAA,GAKgB;AAC7B,UAAAJ,EAAO,KAAK,MAAM/B,CAAK;AACvB;AAAA,QACF;AAGF,QAAA+B,EAAO,KAAK/B,CAAK;AACjB;AAAA,MACF;AAEA,MAAA+B,EAAO,KAAK/B,CAAK;AAAA;AAAA,EACnB;AAEA,eAAM,QAAQ8B,CAAK,IAAIA,EAAM,QAAQ,CAACI,MAAUD,EAAKC,CAAK,CAAC,IAAID,EAAKH,CAAK,GAClEC;AACT;AAEO,SAASK,EACdC,GACAC,IAAiC,CAAA,GACjCC,IAAqB,CAAA,GACrBC,GACO;AACP,QAAMC,IAAaZ,EAAkBU,CAAQ;AAC7C,SAAO;AAAA,IACL,MAAAF;AAAA,IACA,OAAAC;AAAA,IACA,UAAUG;AAAA,IACV,KAAAD;AAAA,EAAA;AAEJ;ACjGA,MAAME,IAAmB;AAEzB,SAASC,EAAiBL,GAAiB;AACzC,MAAIM;AAEJ,aAAWJ,KAAO,OAAO,KAAKF,CAAK,GAAG;AACpC,QAAI,CAACE,EAAI,WAAWE,CAAgB,EAAG;AAEvC,UAAMG,IAAOL,EAAI,MAAME,EAAiB,MAAM,GACxC1C,IAAQsC,EAAME,CAAG;AAIvB,QAFA,OAAOF,EAAME,CAAG,GAEZK,MAAS,WAAW,OAAO7C,KAAU,YAAYA,EAAM,QAAQ;AACjE,MAAA4C,IAAY,SAAS5C,EAAM,KAAA,CAAM;AACjC;AAAA,IACF;AAEA,IAAA4C,IAAYC;AAAA,EACd;AAEA,SAAOD;AACT;AAEA,SAASE,EAAQT,GAAeC,IAAkB,CAAA,GAAIE,GAAuB;AAC3E,QAAM,EAAE,UAAAD,GAAU,GAAGQ,EAAA,IAAST,KAAS,CAAA,GACjCU,IAAqBnB,EAAkBU,CAA6B,GACpEU,IAAuB,EAAE,GAAGF,EAAA,GAC5BH,IAAYD,EAAiBM,CAAU;AAC7C,EAAIT,MAAQ,SACVS,EAAW,MAAMT,IACRS,EAAW,QAAQ,WAC5BT,IAAMS,EAAW,KACjB,OAAOA,EAAW;AAEpB,QAAMC,IAAQd,EAAYC,GAAeY,GAAYD,GAAoBR,CAAG;AAC5E,SAAII,MACFM,EAAM,oBAAoBN,IAErBM;AACT;AAEO,MAAMC,IAAML,GACNM,IAAON;AAEb,SAASO,EAAEhB,GAAeC,MAAqBC,GAAoB;AACxE,QAAMS,IAAqBnB,EAAkBU,CAAQ,GAC/CC,IACJF,KAAS,OAAOA,EAAM,MAAQ,MAAeA,EAAM,MAA0B,QACzEW,IAAa,EAAE,GAAIX,KAAS,GAAC,GAC7BM,IAAYD,EAAiBM,CAAU;AAC7C,EAAI,SAASA,KACX,OAAQA,EAAuC;AAEjD,QAAMC,IAAQd,EAAYC,GAAeY,GAAYD,GAAoBR,CAAG;AAC5E,SAAII,MACFM,EAAM,oBAAoBN,IAErBM;AACT;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const y={enableDevtools:!1,enableWarnings:!1,logLevel:"warn"};function V(e){e.enableDevtools!==void 0&&(y.enableDevtools=e.enableDevtools),e.enableWarnings!==void 0&&(y.enableWarnings=e.enableWarnings),e.logLevel!==void 0&&(y.logLevel=e.logLevel)}function b(){return y}const D=new Set;let p=!1;const v={debug:10,info:20,warn:30,error:40};function z(e){return D.add(e),()=>D.delete(e)}function w(e,n,o,i){const t=b();if(!t.enableDevtools||t.logLevel==="silent"||p)return;const r=t.logLevel==="warn"?v.warn:t.logLevel==="info"?v.info:v.debug;if(v[n]<r)return;const s={scope:e,level:n,message:o,payload:i,timestamp:Date.now()};p=!0;try{D.forEach(l=>{try{l(s)}catch{}})}finally{p=!1}const c=`[loly-devtools][${e}]`;switch(n){case"debug":console.debug(c,o,i);break;case"info":console.info(c,o,i);break;case"warn":console.warn(c,o,i);break;case"error":console.error(c,o,i);break}}let u=null;function W(e){let n=e;const o=new Set,i=l=>(o.add(l),()=>o.delete(l)),t=()=>{if(u){const l=i(u.invalidate);u.addDependency(l)}return n},r=l=>{const f=typeof l=="function"?l(n):l,a=n;n=f,b().enableWarnings&&u&&console.warn("[loly][signal] setting a signal while a computed is evaluating; posible loop"),b().enableDevtools&&w("signal","debug","signal:update",{prev:a,next:f}),o.forEach(m=>m(n))},s=l=>r(l(n)),c=()=>t();return c.get=t,c.set=r,c.update=s,c.subscribe=i,Object.defineProperty(c,"value",{get:t,set:r}),[c,r]}function F(e){let n=!0,o,i=!1;const t=new Set,r=new Set,s=d=>(t.add(d),()=>t.delete(d)),c=()=>{r.forEach(d=>d()),r.clear()},l=()=>{n||(n=!0,i||(i=!0,queueMicrotask(()=>{if(n&&t.size>0){const d=a();t.forEach(x=>x(d))}i=!1})))},f=()=>{c();const d=u;u=m;try{return o=e(),n=!1,b().enableDevtools&&w("computed","debug","computed:evaluate",{value:o}),o}finally{u=d}},a=()=>{if(u){const d=s(u.invalidate);u.addDependency(d)}return n?f():o},m={invalidate:l,addDependency(d){r.add(d)},evaluate:f,get:a},g=()=>a();return Object.defineProperty(g,"value",{get:a,configurable:!0}),g.get=a,g.subscribe=d=>(t.add(d),a(),()=>t.delete(d)),g.toString=()=>String(a()),g}function E(e){const n=e;return n!==null&&(typeof e=="function"||typeof e=="object")&&"get"in n&&"set"in n&&"subscribe"in n}function S(e){const n=e;return n!==null&&(typeof e=="function"||typeof e=="object")&&"get"in n&&"subscribe"in n&&!("set"in n)}const N=Symbol("Fragment");function j(e){return typeof e=="object"&&e!==null&&"type"in e&&"props"in e&&"children"in e}function h(e=[]){const n=[],o=typeof window>"u",i=t=>{if(!(t==null||t===!1||t===!0)){if(Array.isArray(t)){t.forEach(r=>i(r));return}if(j(t)){if(!o&&t.children.some(s=>E(s)||S(s)||typeof s=="function")){n.push(()=>t);return}n.push(t);return}n.push(t)}};return Array.isArray(e)?e.forEach(t=>i(t)):i(e),n}function k(e,n={},o=[],i){const t=h(o);return{type:e,props:n,children:t,key:i}}const C="client:";function L(e){let n;for(const o of Object.keys(e)){if(!o.startsWith(C))continue;const i=o.slice(C.length),t=e[o];if(delete e[o],i==="media"&&typeof t=="string"&&t.trim()){n=`media:${t.trim()}`;continue}n=i}return n}function R(e,n={},o){const{children:i,...t}=n??{},r=h(i),s={...t},c=L(s);o!==void 0?s.key=o:s.key!==void 0&&(o=s.key,delete s.key);const l=k(e,s,r,o);return c&&(l.__islandDirective=c),l}const P=R,_=R;function A(e,n,...o){const i=h(o),t=n&&typeof n.key<"u"?n.key:void 0,r={...n??{}},s=L(r);"key"in r&&delete r.key;const c=k(e,r,i,t);return s&&(c.__islandDirective=s),c}exports.Fragment=N;exports.computed=F;exports.configureRuntime=V;exports.createVNode=k;exports.devLog=w;exports.getRuntimeConfig=b;exports.h=A;exports.isComputed=S;exports.isSignal=E;exports.isVNode=j;exports.jsx=P;exports.jsxs=_;exports.normalizeChildren=h;exports.onDevtoolsEvent=z;exports.state=W;
|
|
2
|
+
//# sourceMappingURL=dev-runtime-CRAwY4ll.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-runtime-CRAwY4ll.cjs","sources":["../src/runtime/config.ts","../src/devtools/logger.ts","../src/core/signal.ts","../src/core/vnode.ts","../src/jsx/runtime.tsx"],"sourcesContent":["export type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\";\r\n\r\nexport interface RuntimeConfig {\r\n enableDevtools: boolean;\r\n enableWarnings: boolean;\r\n logLevel: LogLevel;\r\n}\r\n\r\nconst config: RuntimeConfig = {\r\n enableDevtools: false,\r\n enableWarnings: false,\r\n logLevel: \"warn\"\r\n};\r\n\r\nexport function configureRuntime(partial: Partial<RuntimeConfig>) {\r\n if (partial.enableDevtools !== undefined) config.enableDevtools = partial.enableDevtools;\r\n if (partial.enableWarnings !== undefined) config.enableWarnings = partial.enableWarnings;\r\n if (partial.logLevel !== undefined) config.logLevel = partial.logLevel;\r\n}\r\n\r\nexport function getRuntimeConfig(): RuntimeConfig {\r\n return config;\r\n}\r\n\r\n","import { getRuntimeConfig } from \"../runtime/config\";\r\n\r\nexport type DevtoolsScope =\r\n | \"signal\"\r\n | \"store\"\r\n | \"computed\"\r\n | \"island\"\r\n | \"component\"\r\n | \"overlay\"\r\n | \"runtime\";\r\n\r\nexport type DevtoolsLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\r\n\r\nexport interface DevtoolsEvent {\r\n scope: DevtoolsScope;\r\n level: DevtoolsLevel;\r\n message: string;\r\n payload?: unknown;\r\n timestamp: number;\r\n}\r\n\r\ntype Listener = (event: DevtoolsEvent) => void;\r\n\r\nconst listeners = new Set<Listener>();\r\nlet isEmitting = false;\r\n\r\nconst levelOrder: Record<DevtoolsLevel, number> = {\r\n debug: 10,\r\n info: 20,\r\n warn: 30,\r\n error: 40\r\n};\r\n\r\nexport function onDevtoolsEvent(fn: Listener): () => void {\r\n listeners.add(fn);\r\n return () => listeners.delete(fn);\r\n}\r\n\r\nexport function devLog(scope: DevtoolsScope, level: DevtoolsLevel, message: string, payload?: unknown) {\r\n const cfg = getRuntimeConfig();\r\n if (!cfg.enableDevtools) return;\r\n if (cfg.logLevel === \"silent\") return;\r\n \r\n // Si ya estamos emitiendo, no emitir de nuevo (evita loops)\r\n if (isEmitting) return;\r\n \r\n const threshold = cfg.logLevel === \"warn\" ? levelOrder.warn : cfg.logLevel === \"info\" ? levelOrder.info : levelOrder.debug;\r\n if (levelOrder[level] < threshold) return;\r\n\r\n const evt: DevtoolsEvent = {\r\n scope,\r\n level,\r\n message,\r\n payload,\r\n timestamp: Date.now()\r\n };\r\n\r\n // Emit to listeners\r\n isEmitting = true;\r\n try {\r\n listeners.forEach((fn) => {\r\n try {\r\n fn(evt);\r\n } catch {\r\n // ignore listener errors\r\n }\r\n });\r\n } finally {\r\n isEmitting = false;\r\n }\r\n\r\n // Console fallback\r\n const prefix = `[loly-devtools][${scope}]`;\r\n switch (level) {\r\n case \"debug\":\r\n console.debug(prefix, message, payload);\r\n break;\r\n case \"info\":\r\n console.info(prefix, message, payload);\r\n break;\r\n case \"warn\":\r\n console.warn(prefix, message, payload);\r\n break;\r\n case \"error\":\r\n console.error(prefix, message, payload);\r\n break;\r\n }\r\n}\r\n","import { devLog } from \"../devtools/logger\";\nimport { getRuntimeConfig } from \"../runtime/config\";\n\nexport type Subscriber<T> = (value: T) => void;\n\nexport interface Signal<T> {\n (): T;\n get(): T;\n set(next: T | ((current: T) => T)): void;\n update(fn: (current: T) => T): void;\n subscribe(subscriber: Subscriber<T>): () => void;\n value: T;\n}\n\nexport interface Computed<T> {\n (): T;\n readonly value: T;\n get(): T;\n subscribe(subscriber: Subscriber<T>): () => void;\n toString(): string;\n}\n\ntype DepCleanup = () => void;\n\nlet activeComputed: InternalComputed<unknown> | null = null;\n\ninterface InternalComputed<T> {\n invalidate(): void;\n addDependency(cleanup: DepCleanup): void;\n evaluate(): T;\n get(): T;\n}\n\n/**\n * Nueva API de estado: devuelve [getter, setter].\n * El getter implementa la interfaz Signal<T> para compatibilidad interna.\n */\nexport function state<T>(initial: T): [Signal<T>, (next: T | ((current: T) => T)) => void] {\n let value = initial;\n const subscribers = new Set<Subscriber<T>>();\n\n const subscribe = (subscriber: Subscriber<T>) => {\n subscribers.add(subscriber);\n return () => subscribers.delete(subscriber);\n };\n\n const get = () => {\n if (activeComputed) {\n const unsubscribe = subscribe(activeComputed.invalidate);\n activeComputed.addDependency(unsubscribe);\n }\n return value;\n };\n\n const set = (next: T | ((current: T) => T)) => {\n const nextVal = typeof next === \"function\" ? (next as (c: T) => T)(value) : next;\n const prev = value;\n value = nextVal;\n if (getRuntimeConfig().enableWarnings && activeComputed) {\n console.warn(\"[loly][signal] setting a signal while a computed is evaluating; posible loop\");\n }\n if (getRuntimeConfig().enableDevtools) {\n devLog(\"signal\", \"debug\", \"signal:update\", { prev, next: nextVal });\n }\n subscribers.forEach((fn) => fn(value));\n };\n\n const update = (fn: (current: T) => T) => set(fn(value));\n\n // El getter también actúa como Signal<T>\n const getter = (() => get()) as Signal<T>;\n getter.get = get;\n getter.set = set;\n getter.update = update;\n getter.subscribe = subscribe;\n Object.defineProperty(getter, \"value\", {\n get,\n set\n });\n\n return [getter, set];\n}\n\nexport function computed<T>(fn: () => T): Computed<T> {\n let dirty = true;\n let cached!: T;\n let pendingNotification = false;\n\n const subscribers = new Set<Subscriber<T>>();\n const depCleanups = new Set<DepCleanup>();\n\n const subscribe = (subscriber: Subscriber<T>) => {\n subscribers.add(subscriber);\n return () => subscribers.delete(subscriber);\n };\n\n const cleanupDeps = () => {\n depCleanups.forEach((fn) => fn());\n depCleanups.clear();\n };\n\n const invalidate = () => {\n if (!dirty) {\n dirty = true;\n if (!pendingNotification) {\n pendingNotification = true;\n queueMicrotask(() => {\n if (dirty && subscribers.size > 0) {\n const newValue = get();\n subscribers.forEach((fn) => fn(newValue));\n }\n pendingNotification = false;\n });\n }\n }\n };\n\n const evaluate = (): T => {\n cleanupDeps();\n const prev = activeComputed;\n activeComputed = internal;\n try {\n cached = fn();\n dirty = false;\n if (getRuntimeConfig().enableDevtools) {\n devLog(\"computed\", \"debug\", \"computed:evaluate\", { value: cached });\n }\n return cached;\n } finally {\n activeComputed = prev;\n }\n };\n\n const get = (): T => {\n // Si hay un computed activo (otro computed que nos está leyendo), suscribirlo\n // Esto permite que los computed anidados funcionen correctamente\n if (activeComputed) {\n const unsubscribe = subscribe(activeComputed.invalidate);\n activeComputed.addDependency(unsubscribe);\n }\n \n if (dirty) return evaluate();\n return cached;\n };\n\n const internal: InternalComputed<T> = {\n invalidate,\n addDependency(cleanup) {\n depCleanups.add(cleanup);\n },\n evaluate,\n get\n };\n\n // Create a callable function that also has properties (like Signal)\n const computedFn = (() => get()) as Computed<T>;\n Object.defineProperty(computedFn, \"value\", {\n get,\n configurable: true\n });\n computedFn.get = get;\n computedFn.subscribe = (subscriber) => {\n subscribers.add(subscriber);\n // Ensure dependencies are tracked so invalidation works\n get();\n return () => subscribers.delete(subscriber);\n };\n computedFn.toString = () => String(get());\n\n return computedFn;\n}\n\n\nexport function isSignal(value: unknown): value is Signal<unknown> {\n const candidate = value as Record<string, unknown> | null;\n return (\n candidate !== null &&\n (typeof value === \"function\" || typeof value === \"object\") &&\n \"get\" in candidate &&\n \"set\" in candidate &&\n \"subscribe\" in candidate\n );\n}\n\nexport function isComputed(value: unknown): value is Computed<unknown> {\n const candidate = value as Record<string, unknown> | null;\n return (\n candidate !== null &&\n (typeof value === \"function\" || typeof value === \"object\") &&\n \"get\" in candidate &&\n \"subscribe\" in candidate &&\n !(\"set\" in candidate)\n );\n}\n\n","import type { Computed, Signal } from \"./signal\";\r\nimport { isSignal, isComputed } from \"./signal\";\r\nimport type { ForBlock } from \"../runtime/list\";\r\nimport type { ComponentInstance } from \"../runtime/instance\";\r\n\r\nexport const Fragment = Symbol(\"Fragment\");\r\n\r\nexport type PrimitiveChild = string | number | boolean | null | undefined;\r\nexport type VChild =\r\n | VNode\r\n | PrimitiveChild\r\n | Signal<unknown>\r\n | Computed<unknown>\r\n | (() => VChild)\r\n | ForBlock<any>\r\n | VChild[];\r\n\r\nexport type Component<Props = Record<string, unknown>> = (\r\n props: Props & { children?: VChild[] }\r\n) => VChild;\r\n\r\nexport interface VNode<Props = Record<string, unknown>> {\r\n type: string | Component<Props> | typeof Fragment;\r\n props: Record<string, unknown>;\r\n children: VChild[];\r\n key?: string | number;\r\n __instance?: ComponentInstance;\r\n __islandDirective?: string;\r\n}\r\n\r\nexport function isVNode(value: unknown): value is VNode {\r\n return (\r\n typeof value === \"object\" &&\r\n value !== null &&\r\n \"type\" in (value as Record<string, unknown>) &&\r\n \"props\" in (value as Record<string, unknown>) &&\r\n \"children\" in (value as Record<string, unknown>)\r\n );\r\n}\r\n\r\nexport function normalizeChildren(input: VChild | VChild[] = []): VChild[] {\r\n const result: VChild[] = [];\r\n const isSSR = typeof window === \"undefined\";\r\n\r\n const push = (value: VChild) => {\r\n if (value === null || value === undefined || value === false || value === true) {\r\n return;\r\n }\r\n if (Array.isArray(value)) {\r\n value.forEach((child) => push(child as VChild));\r\n return;\r\n }\r\n \r\n // Si es un VNode, verificar si tiene signals/computed/funciones directamente en children\r\n // Esto detecta expresiones condicionales como {submitted() ? <form> : <success>}\r\n // y las convierte en lambdas reactivas automáticamente\r\n // NOTA: En SSR (cuando window es undefined), NO convertimos a lambdas para evitar recursión\r\n if (isVNode(value)) {\r\n // Solo convertir a lambda reactiva en el cliente (no en SSR)\r\n if (!isSSR) {\r\n // Verificar si hay signals/computed/funciones DIRECTAMENTE en children\r\n // No verificar signals anidados en VNodes hijos para evitar falsos positivos\r\n // IMPORTANTE: En SSR, nunca convertir a lambda para evitar recursión infinita\r\n const hasDirectReactiveChildren = value.children.some(c => \r\n isSignal(c) || \r\n isComputed(c) || \r\n typeof c === \"function\"\r\n );\r\n \r\n // Si tiene children reactivos directos, convertir el VNode en lambda reactiva\r\n // Esto permite que expresiones condicionales sean automáticamente reactivas\r\n if (hasDirectReactiveChildren) {\r\n result.push(() => value);\r\n return;\r\n }\r\n }\r\n // En SSR, simplemente agregar el VNode sin modificar\r\n result.push(value);\r\n return;\r\n }\r\n \r\n result.push(value);\r\n };\r\n\r\n Array.isArray(input) ? input.forEach((child) => push(child)) : push(input);\r\n return result;\r\n}\r\n\r\nexport function createVNode(\r\n type: VNode[\"type\"],\r\n props: Record<string, unknown> = {},\r\n children: VChild[] = [],\r\n key?: string | number\r\n): VNode {\r\n const normalized = normalizeChildren(children);\r\n return {\r\n type,\r\n props,\r\n children: normalized,\r\n key\r\n };\r\n}\r\n\r\n","import { Fragment, VChild, createVNode, normalizeChildren } from \"../core/vnode\";\r\n\r\ntype AnyProps = Record<string, unknown>;\r\n\r\nconst DIRECTIVE_PREFIX = \"client:\";\r\n\r\nfunction extractDirective(props: AnyProps) {\r\n let directive: string | undefined;\r\n\r\n for (const key of Object.keys(props)) {\r\n if (!key.startsWith(DIRECTIVE_PREFIX)) continue;\r\n\r\n const mode = key.slice(DIRECTIVE_PREFIX.length);\r\n const value = props[key];\r\n\r\n delete props[key];\r\n\r\n if (mode === \"media\" && typeof value === \"string\" && value.trim()) {\r\n directive = `media:${value.trim()}`;\r\n continue;\r\n }\r\n\r\n directive = mode;\r\n }\r\n\r\n return directive;\r\n}\r\n\r\nfunction baseJsx(type: unknown, props: AnyProps = {}, key?: string | number) {\r\n const { children, ...rest } = props ?? {};\r\n const normalizedChildren = normalizeChildren(children as VChild | VChild[]);\r\n const cleanProps: AnyProps = { ...rest };\r\n const directive = extractDirective(cleanProps);\r\n if (key !== undefined) {\r\n cleanProps.key = key;\r\n } else if (cleanProps.key !== undefined) {\r\n key = cleanProps.key as string | number;\r\n delete cleanProps.key;\r\n }\r\n const vnode = createVNode(type as never, cleanProps, normalizedChildren, key);\r\n if (directive) {\r\n vnode.__islandDirective = directive;\r\n }\r\n return vnode;\r\n}\r\n\r\nexport const jsx = baseJsx;\r\nexport const jsxs = baseJsx;\r\n\r\nexport function h(type: unknown, props?: AnyProps, ...children: VChild[]) {\r\n const normalizedChildren = normalizeChildren(children);\r\n const key =\r\n props && typeof props.key !== \"undefined\" ? (props.key as string | number) : undefined;\r\n const cleanProps = { ...(props ?? {}) };\r\n const directive = extractDirective(cleanProps);\r\n if (\"key\" in cleanProps) {\r\n delete (cleanProps as Record<string, unknown>).key;\r\n }\r\n const vnode = createVNode(type as never, cleanProps, normalizedChildren, key);\r\n if (directive) {\r\n vnode.__islandDirective = directive;\r\n }\r\n return vnode;\r\n}\r\n\r\nexport { Fragment };\r\nexport type { VChild } from \"../core/vnode\";\r\n\r\ndeclare global {\r\n namespace JSX {\r\n type Element = any;\r\n interface ElementChildrenAttribute {\r\n children: {};\r\n }\r\n interface IntrinsicAttributes {\r\n [\"client:load\"]?: boolean;\r\n [\"client:idle\"]?: boolean;\r\n [\"client:visible\"]?: boolean;\r\n [\"client:media\"]?: string;\r\n }\r\n interface IntrinsicElements {\r\n [elemName: string]: Record<string, unknown>;\r\n }\r\n }\r\n}\r\n\r\n"],"names":["config","configureRuntime","partial","getRuntimeConfig","listeners","isEmitting","levelOrder","onDevtoolsEvent","fn","devLog","scope","level","message","payload","cfg","threshold","evt","prefix","activeComputed","state","initial","value","subscribers","subscribe","subscriber","get","unsubscribe","set","next","nextVal","prev","update","getter","computed","dirty","cached","pendingNotification","depCleanups","cleanupDeps","invalidate","newValue","evaluate","internal","cleanup","computedFn","isSignal","candidate","isComputed","Fragment","isVNode","normalizeChildren","input","result","isSSR","push","child","c","createVNode","type","props","children","key","normalized","DIRECTIVE_PREFIX","extractDirective","directive","mode","baseJsx","rest","normalizedChildren","cleanProps","vnode","jsx","jsxs","h"],"mappings":"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"}
|