ilha 0.14.6 → 0.14.7
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 +2 -2
- package/dist/define.d.ts +1 -1
- package/dist/define.js +1 -1
- package/dist/index.d.ts +53 -32
- package/dist/index.js +465 -12
- package/dist/jsx-dev-runtime.d.ts +2 -2
- package/dist/jsx-dev-runtime.js +1 -1
- package/dist/jsx-runtime.d.ts +2 -2
- package/dist/jsx-runtime.js +1 -1
- package/dist/{mount-DiIEX8s7.js → mount-rXNnaIWf.js} +228 -54
- package/dist/types-CJF2qMK6.d.ts +100 -0
- package/dist/{vnode-C_BdUnIA.d.ts → vnode-CUTNGblA.d.ts} +13 -1
- package/dist/{vnode-DEMDQ0eA.js → vnode-M-oJMKcv.js} +1 -1
- package/package.json +3 -3
- package/dist/types-CyoYWhJf.d.ts +0 -48
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { _ as skip, a as ISLAND, b as failureMessage, c as KEEP, d as errorView, f as isBigInt, g as isString, h as isObject, i as Fragment, l as KEY_ATTR, m as isNumber, n as isSetupFn, o as ISLAND_MOUNT_INTERNAL, p as isFunction, r as isVNode, s as ISLAND_SLOT_TAG, u as SLOT_ATTR, v as unwrap, x as toError, y as asFailure } from "./vnode-
|
|
2
|
-
import * as
|
|
3
|
-
import
|
|
4
|
-
import * as
|
|
1
|
+
import { _ as skip, a as ISLAND, b as failureMessage, c as KEEP, d as errorView, f as isBigInt, g as isString, h as isObject, i as Fragment, l as KEY_ATTR, m as isNumber, n as isSetupFn, o as ISLAND_MOUNT_INTERNAL, p as isFunction, r as isVNode, s as ISLAND_SLOT_TAG, u as SLOT_ATTR, v as unwrap, x as toError, y as asFailure } from "./vnode-M-oJMKcv.js";
|
|
2
|
+
import * as Atom from "effect/reactivity/Atom";
|
|
3
|
+
import { Equal } from "effect";
|
|
4
|
+
import * as Effect$1 from "effect/Effect";
|
|
5
|
+
import * as Stream$1 from "effect/Stream";
|
|
5
6
|
import * as Cause from "effect/Cause";
|
|
6
7
|
import * as Exit from "effect/Exit";
|
|
7
8
|
import * as Fiber from "effect/Fiber";
|
|
9
|
+
import * as Registry from "effect/reactivity/AtomRegistry";
|
|
8
10
|
import * as Scope from "effect/Scope";
|
|
9
|
-
import * as Registry from "effect/unstable/reactivity/AtomRegistry";
|
|
10
11
|
|
|
11
12
|
//#region src/runtime.ts
|
|
12
13
|
const stack = [];
|
|
@@ -24,15 +25,15 @@ const withFiber = (fiber, fn) => {
|
|
|
24
25
|
stack.pop();
|
|
25
26
|
}
|
|
26
27
|
};
|
|
27
|
-
const provide = (effect, registry) => effect.pipe(Effect.provideService(Registry.AtomRegistry, registry));
|
|
28
|
+
const provide = (effect, registry) => effect.pipe(Effect$1.provideService(Registry.AtomRegistry, registry));
|
|
28
29
|
const runInScope = (effect, registry, scope, onOk, onErr, onDone) => {
|
|
29
30
|
const provided = provide(effect, registry);
|
|
30
|
-
const f = Effect.runFork(onOk || onDone ? provided.pipe(Effect.onExit((ex) => Effect.sync(() => {
|
|
31
|
+
const f = Effect$1.runFork(onOk || onDone ? provided.pipe(Effect$1.onExit((ex) => Effect$1.sync(() => {
|
|
31
32
|
onDone?.();
|
|
32
33
|
if (Exit.isSuccess(ex)) onOk?.(ex.value);
|
|
33
34
|
else if (!Cause.hasInterruptsOnly(ex.cause)) onErr?.(Cause.squash(ex.cause));
|
|
34
35
|
}))) : provided);
|
|
35
|
-
Effect.runSync(Scope.addFinalizer(scope, Fiber.interrupt(f)));
|
|
36
|
+
Effect$1.runSync(Scope.addFinalizer(scope, Fiber.interrupt(f)));
|
|
36
37
|
};
|
|
37
38
|
/** Clear render subscriptions and child holes without closing the fiber scope. */
|
|
38
39
|
const clearFiberView = (fiber) => {
|
|
@@ -55,7 +56,7 @@ const closeFiber = (fiber) => {
|
|
|
55
56
|
fiber.trackRestore = void 0;
|
|
56
57
|
fiber.handleError = void 0;
|
|
57
58
|
clearFiberView(fiber);
|
|
58
|
-
Effect.runFork(Scope.close(fiber.scope, Exit.void));
|
|
59
|
+
Effect$1.runFork(Scope.close(fiber.scope, Exit.void));
|
|
59
60
|
};
|
|
60
61
|
const makeRuntime = (opts) => {
|
|
61
62
|
const registry = Registry.make();
|
|
@@ -69,7 +70,7 @@ const makeRuntime = (opts) => {
|
|
|
69
70
|
},
|
|
70
71
|
close: () => {
|
|
71
72
|
onIdle = void 0;
|
|
72
|
-
Effect.runFork(Scope.close(scope, Exit.void));
|
|
73
|
+
Effect$1.runFork(Scope.close(scope, Exit.void));
|
|
73
74
|
registry.dispose();
|
|
74
75
|
},
|
|
75
76
|
end: () => {
|
|
@@ -183,6 +184,8 @@ const instr = (effect) => {
|
|
|
183
184
|
return out;
|
|
184
185
|
};
|
|
185
186
|
const isAtomHandle = (x) => isFunction(x) && x.$$atom === 1;
|
|
187
|
+
/** Key-order-insensitive deep equality for JSON-shaped values. */
|
|
188
|
+
const structuralEqual = Equal.equals;
|
|
186
189
|
let trackGet;
|
|
187
190
|
const trackStack = [];
|
|
188
191
|
/** Read atoms inside `fn` without subscribing the active render. Sync only. */
|
|
@@ -218,6 +221,34 @@ const beginPrimitiveFrame = (fiber) => {
|
|
|
218
221
|
islandFrame.slots.length = usedIslands;
|
|
219
222
|
}
|
|
220
223
|
islandFrame.i = 0;
|
|
224
|
+
let { componentFrame } = fiber;
|
|
225
|
+
if (!componentFrame) {
|
|
226
|
+
componentFrame = {
|
|
227
|
+
i: 0,
|
|
228
|
+
slots: []
|
|
229
|
+
};
|
|
230
|
+
fiber.componentFrame = componentFrame;
|
|
231
|
+
}
|
|
232
|
+
const usedComponents = componentFrame.i;
|
|
233
|
+
if (usedComponents < componentFrame.slots.length) {
|
|
234
|
+
for (let j = usedComponents; j < componentFrame.slots.length; j += 1) {
|
|
235
|
+
const slot = componentFrame.slots[j];
|
|
236
|
+
if (slot) {
|
|
237
|
+
const { hole } = slot;
|
|
238
|
+
if (!hole.closed) {
|
|
239
|
+
const idx = fiber.holes.findIndex((h) => h.holeFiber === hole);
|
|
240
|
+
if (idx === -1) closeFiber(hole);
|
|
241
|
+
else {
|
|
242
|
+
const [removed] = fiber.holes.splice(idx, 1);
|
|
243
|
+
removed?.dispose();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
componentFrame.slots[j] = void 0;
|
|
248
|
+
}
|
|
249
|
+
componentFrame.slots.length = usedComponents;
|
|
250
|
+
}
|
|
251
|
+
componentFrame.i = 0;
|
|
221
252
|
};
|
|
222
253
|
const readTracked = (atom, registry) => {
|
|
223
254
|
const frame = trackStack.at(-1);
|
|
@@ -333,19 +364,23 @@ const wrapHandle = (atom, fiber) => {
|
|
|
333
364
|
});
|
|
334
365
|
return read;
|
|
335
366
|
};
|
|
336
|
-
const makeAtom = (init) => {
|
|
367
|
+
const makeAtom = (init, options) => {
|
|
337
368
|
const fiber = getFiber();
|
|
338
369
|
const snap = fiber.runtime.hydrateValues;
|
|
339
370
|
const { atom: a, fresh } = usePrimitiveSlot(fiber, () => {
|
|
340
371
|
let seed = init;
|
|
341
|
-
if (snap && !Atom.isAtom(init) && !Effect.isEffect(init) && !Stream.isStream(init)) {
|
|
372
|
+
if (snap && !Atom.isAtom(init) && !Effect$1.isEffect(init) && !Stream$1.isStream(init)) {
|
|
342
373
|
const v = snap[fiber.runtime.hydrateI];
|
|
343
374
|
fiber.runtime.hydrateI += 1;
|
|
344
375
|
if (v !== void 0) seed = v;
|
|
345
376
|
}
|
|
346
377
|
if (Atom.isAtom(seed)) return seed;
|
|
347
|
-
if (Effect.isEffect(seed) || Stream.isStream(seed)) return Atom.make(seed);
|
|
348
|
-
|
|
378
|
+
if (Effect$1.isEffect(seed) || Stream$1.isStream(seed)) return Atom.make(seed);
|
|
379
|
+
const made = Atom.make(seed);
|
|
380
|
+
const eq = options?.equals;
|
|
381
|
+
if (eq === void 0) return made;
|
|
382
|
+
const equalsFn = eq === "structural" ? structuralEqual : eq;
|
|
383
|
+
return Atom.withEquality(made, equalsFn);
|
|
349
384
|
});
|
|
350
385
|
const handle = wrapHandle(a, fiber);
|
|
351
386
|
if (fresh && fiber.runtime.ssr) fiber.runtime.ssrValues.push(fiber.registry.get(a));
|
|
@@ -392,7 +427,7 @@ const interpret = (gen, fiber) => {
|
|
|
392
427
|
}
|
|
393
428
|
let effect;
|
|
394
429
|
if (isInstruction(step.value)) ({effect} = step.value);
|
|
395
|
-
else if (Effect.isEffect(step.value)) effect = step.value;
|
|
430
|
+
else if (Effect$1.isEffect(step.value)) effect = step.value;
|
|
396
431
|
if (effect) {
|
|
397
432
|
fiber.inFlight = true;
|
|
398
433
|
fiber.run(effect, (a) => {
|
|
@@ -507,7 +542,7 @@ const bindEvents = (node, props, fiber) => {
|
|
|
507
542
|
const fn = el.__ilhaProps?.[key];
|
|
508
543
|
if (!isFunction(fn)) return;
|
|
509
544
|
const out = fn(ev);
|
|
510
|
-
if (Effect.isEffect(out)) fiber.run(out);
|
|
545
|
+
if (Effect$1.isEffect(out)) fiber.run(out);
|
|
511
546
|
});
|
|
512
547
|
}
|
|
513
548
|
};
|
|
@@ -538,6 +573,7 @@ const syncAttributes = (from, to) => {
|
|
|
538
573
|
const names = [];
|
|
539
574
|
for (const { name } of from.attributes) names.push(name);
|
|
540
575
|
for (const name of names) {
|
|
576
|
+
if (name === "open" && !to.hasAttribute("open")) continue;
|
|
541
577
|
if (shouldPreserveMorphAttr(from, name)) continue;
|
|
542
578
|
if (!to.hasAttribute(name)) from.removeAttribute(name);
|
|
543
579
|
}
|
|
@@ -590,19 +626,29 @@ const collectKeys = (parent) => {
|
|
|
590
626
|
return keys;
|
|
591
627
|
};
|
|
592
628
|
const morphInput = (fromEl, toEl) => {
|
|
593
|
-
const hadChecked = fromEl.hasAttribute("checked");
|
|
594
|
-
const hadValue = fromEl.getAttribute("value");
|
|
595
629
|
syncAttributes(fromEl, toEl);
|
|
596
|
-
const
|
|
597
|
-
|
|
598
|
-
const
|
|
599
|
-
if (
|
|
630
|
+
const from = fromEl;
|
|
631
|
+
const to = toEl;
|
|
632
|
+
const toChecked = toEl.hasAttribute("checked");
|
|
633
|
+
if (toChecked !== fromEl.hasAttribute("checked")) {
|
|
634
|
+
if (toChecked) fromEl.setAttribute("checked", "");
|
|
635
|
+
else fromEl.removeAttribute("checked");
|
|
636
|
+
}
|
|
637
|
+
if (toChecked && from.checked !== to.checked) from.checked = to.checked;
|
|
638
|
+
const toValue = toEl.getAttribute("value");
|
|
639
|
+
if (toValue !== fromEl.getAttribute("value")) {
|
|
640
|
+
if (toValue === null) fromEl.removeAttribute("value");
|
|
641
|
+
else fromEl.setAttribute("value", toValue);
|
|
642
|
+
}
|
|
643
|
+
if (toValue !== null && from.value !== to.value) from.value = to.value;
|
|
600
644
|
};
|
|
601
645
|
const morphTextarea = (fromEl, toEl) => {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
646
|
+
syncAttributes(fromEl, toEl);
|
|
647
|
+
const from = fromEl;
|
|
648
|
+
const to = toEl;
|
|
649
|
+
if (to.textContent !== "" || from.textContent !== to.textContent) {
|
|
650
|
+
if (from.value !== to.value) from.value = to.value;
|
|
651
|
+
if (from.textContent !== to.textContent) from.textContent = to.textContent;
|
|
606
652
|
}
|
|
607
653
|
};
|
|
608
654
|
const morphSelect = (fromEl, toEl, api) => {
|
|
@@ -805,6 +851,9 @@ const isUnsafeHtml = (x) => {
|
|
|
805
851
|
|
|
806
852
|
//#endregion
|
|
807
853
|
//#region src/paint-core.ts
|
|
854
|
+
const SVG_NS = "http://www.w3.org/2000/svg";
|
|
855
|
+
const MATHML_NS = "http://www.w3.org/1998/Math/MathML";
|
|
856
|
+
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
808
857
|
const disposeHoles = (fiber, opts) => {
|
|
809
858
|
const keep = [];
|
|
810
859
|
for (const h of fiber.holes) {
|
|
@@ -816,6 +865,38 @@ const disposeHoles = (fiber, opts) => {
|
|
|
816
865
|
}
|
|
817
866
|
fiber.holes = keep;
|
|
818
867
|
};
|
|
868
|
+
const parentNsOf = (root) => {
|
|
869
|
+
if ("namespaceURI" in root) return root.namespaceURI ?? null;
|
|
870
|
+
return null;
|
|
871
|
+
};
|
|
872
|
+
const elementNs = (lower, parentNs) => {
|
|
873
|
+
if (lower === "svg") return SVG_NS;
|
|
874
|
+
if (lower === "math") return MATHML_NS;
|
|
875
|
+
if (lower === "foreignobject") return HTML_NS;
|
|
876
|
+
if (parentNs === "http://www.w3.org/2000/svg" || parentNs === "http://www.w3.org/1998/Math/MathML") return parentNs;
|
|
877
|
+
};
|
|
878
|
+
const canMorphRoot = (root) => typeof Element !== "undefined" && typeof document !== "undefined" && root instanceof Element && root.childNodes.length > 0;
|
|
879
|
+
const sweepComponentSlots = (fiber) => {
|
|
880
|
+
const cframe = fiber.componentFrame;
|
|
881
|
+
if (!cframe) return;
|
|
882
|
+
const { slots } = cframe;
|
|
883
|
+
for (let j = cframe.i; j < slots.length; j += 1) {
|
|
884
|
+
const s = slots[j];
|
|
885
|
+
if (s) {
|
|
886
|
+
const { hole } = s;
|
|
887
|
+
if (!hole.closed) {
|
|
888
|
+
const idx = fiber.holes.findIndex((h) => h.holeFiber === hole);
|
|
889
|
+
if (idx === -1) closeFiber(hole);
|
|
890
|
+
else {
|
|
891
|
+
const [removed] = fiber.holes.splice(idx, 1);
|
|
892
|
+
removed?.dispose();
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
slots[j] = void 0;
|
|
897
|
+
}
|
|
898
|
+
slots.length = cframe.i;
|
|
899
|
+
};
|
|
819
900
|
const findReusableAtomHost = (fiber, atom) => {
|
|
820
901
|
for (const h of fiber.holes) if (h.atom === atom && h.host?.isConnected && h.holeFiber && !h.holeFiber.closed) return {
|
|
821
902
|
hole: h.holeFiber,
|
|
@@ -945,14 +1026,41 @@ const createPainter = (ops) => {
|
|
|
945
1026
|
fiber.islandFrame = frame;
|
|
946
1027
|
}
|
|
947
1028
|
frame.i = 0;
|
|
1029
|
+
let cframe = fiber.componentFrame;
|
|
1030
|
+
if (!cframe) {
|
|
1031
|
+
cframe = {
|
|
1032
|
+
i: 0,
|
|
1033
|
+
slots: []
|
|
1034
|
+
};
|
|
1035
|
+
fiber.componentFrame = cframe;
|
|
1036
|
+
}
|
|
1037
|
+
cframe.i = 0;
|
|
948
1038
|
const list = Array.isArray(view) ? view : null;
|
|
949
1039
|
if (list && list.length > 0 && list.every((v) => isVNode(v) && v.key !== null && v.key !== void 0)) {
|
|
950
1040
|
paintFns.keyedPaintHole(fiber, list);
|
|
951
1041
|
return;
|
|
952
1042
|
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
1043
|
+
const kept = /* @__PURE__ */ new Set();
|
|
1044
|
+
for (const s of cframe.slots) if (s && !s.hole.closed) kept.add(s.hole);
|
|
1045
|
+
const keep = [];
|
|
1046
|
+
for (const h of fiber.holes) {
|
|
1047
|
+
if (h.holeFiber && kept.has(h.holeFiber)) {
|
|
1048
|
+
keep.push(h);
|
|
1049
|
+
continue;
|
|
1050
|
+
}
|
|
1051
|
+
h.dispose();
|
|
1052
|
+
}
|
|
1053
|
+
fiber.holes = keep;
|
|
1054
|
+
const fresh = api.materialize(view, fiber);
|
|
1055
|
+
if (canMorphRoot(fiber.root)) {
|
|
1056
|
+
const tmp = document.createElement("div");
|
|
1057
|
+
for (const n of fresh) tmp.append(n);
|
|
1058
|
+
morphInner(fiber.root, tmp);
|
|
1059
|
+
} else {
|
|
1060
|
+
ops.clearRoot(fiber.root);
|
|
1061
|
+
api.insert(fiber, fresh);
|
|
1062
|
+
}
|
|
1063
|
+
sweepComponentSlots(fiber);
|
|
956
1064
|
}
|
|
957
1065
|
};
|
|
958
1066
|
const materializeAtom = (view, fiber) => {
|
|
@@ -981,9 +1089,9 @@ const createPainter = (ops) => {
|
|
|
981
1089
|
};
|
|
982
1090
|
const materializeStream = (view, fiber) => {
|
|
983
1091
|
const { fiber: hole, nodes } = api.openHole(fiber);
|
|
984
|
-
const src = fiber.runtime.ssr ? view.pipe(Stream.take(1)) : view;
|
|
985
|
-
const effect = Effect.gen(function* streamPaint() {
|
|
986
|
-
const result = yield* Effect.result(Stream.runForEach(src, (v) => Effect.sync(() => {
|
|
1092
|
+
const src = fiber.runtime.ssr ? view.pipe(Stream$1.take(1)) : view;
|
|
1093
|
+
const effect = Effect$1.gen(function* streamPaint() {
|
|
1094
|
+
const result = yield* Effect$1.result(Stream$1.runForEach(src, (v) => Effect$1.sync(() => {
|
|
987
1095
|
if (!hole.closed) api.paintHole(hole, v);
|
|
988
1096
|
})));
|
|
989
1097
|
if (result._tag === "Failure" && !hole.closed) api.paintHole(hole, String(result.failure));
|
|
@@ -1033,6 +1141,50 @@ const createPainter = (ops) => {
|
|
|
1033
1141
|
}
|
|
1034
1142
|
return [el];
|
|
1035
1143
|
};
|
|
1144
|
+
const materializeUnkeyedComponent = (run, type, props, fiber) => {
|
|
1145
|
+
let { componentFrame: cframe } = fiber;
|
|
1146
|
+
if (!cframe) {
|
|
1147
|
+
cframe = {
|
|
1148
|
+
i: 0,
|
|
1149
|
+
slots: []
|
|
1150
|
+
};
|
|
1151
|
+
fiber.componentFrame = cframe;
|
|
1152
|
+
}
|
|
1153
|
+
const at = cframe.i;
|
|
1154
|
+
cframe.i = at + 1;
|
|
1155
|
+
const existing = cframe.slots[at];
|
|
1156
|
+
if (existing) {
|
|
1157
|
+
const { hole } = existing;
|
|
1158
|
+
if (existing.type === type && !hole.closed) {
|
|
1159
|
+
hole.propsBox = { current: props };
|
|
1160
|
+
runSetup(hole, () => run(props));
|
|
1161
|
+
return [ops.asNode(hole.root)];
|
|
1162
|
+
}
|
|
1163
|
+
if (!hole.closed) {
|
|
1164
|
+
const idx = fiber.holes.findIndex((h) => h.holeFiber === hole);
|
|
1165
|
+
if (idx === -1) closeFiber(hole);
|
|
1166
|
+
else {
|
|
1167
|
+
const [removed] = fiber.holes.splice(idx, 1);
|
|
1168
|
+
removed?.dispose();
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
const { fiber: hole, nodes } = api.openHole(fiber);
|
|
1173
|
+
hole.propsBox = { current: props };
|
|
1174
|
+
hole.componentType = type;
|
|
1175
|
+
cframe.slots[at] = {
|
|
1176
|
+
hole,
|
|
1177
|
+
type
|
|
1178
|
+
};
|
|
1179
|
+
fiber.runtime.later(() => {
|
|
1180
|
+
if (hole.closed) return;
|
|
1181
|
+
const box = hole.propsBox;
|
|
1182
|
+
if (!box) return;
|
|
1183
|
+
runSetup(hole, () => run(box.current));
|
|
1184
|
+
});
|
|
1185
|
+
trackHole(fiber, hole, void 0, { keyed: true });
|
|
1186
|
+
return nodes;
|
|
1187
|
+
};
|
|
1036
1188
|
const materializeComponent = (view, type, fiber) => {
|
|
1037
1189
|
const props = {
|
|
1038
1190
|
...view.props,
|
|
@@ -1049,23 +1201,25 @@ const createPainter = (ops) => {
|
|
|
1049
1201
|
if (next && !isThenable(next) && !isSetupFn(next)) reuse.paint(next);
|
|
1050
1202
|
return [ops.asNode(reuse.root)];
|
|
1051
1203
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
}
|
|
1204
|
+
if (!k) return materializeUnkeyedComponent(run, type, props, fiber);
|
|
1205
|
+
const { fiber: khole, nodes: knodes } = api.openHole(fiber);
|
|
1206
|
+
khole.propsBox = { current: props };
|
|
1207
|
+
fiber.keyedHoles ??= /* @__PURE__ */ new Map();
|
|
1208
|
+
fiber.keyedHoles.set(k, khole);
|
|
1058
1209
|
fiber.runtime.later(() => {
|
|
1059
|
-
if (
|
|
1060
|
-
const box =
|
|
1210
|
+
if (khole.closed) return;
|
|
1211
|
+
const box = khole.propsBox;
|
|
1061
1212
|
if (!box) return;
|
|
1062
|
-
runSetup(
|
|
1213
|
+
runSetup(khole, () => run(box.current));
|
|
1063
1214
|
});
|
|
1064
|
-
trackHole(fiber,
|
|
1065
|
-
return
|
|
1215
|
+
trackHole(fiber, khole, void 0, { keyed: true });
|
|
1216
|
+
return knodes;
|
|
1066
1217
|
};
|
|
1067
1218
|
const materializeElement = (view, fiber) => {
|
|
1068
|
-
const
|
|
1219
|
+
const tag = view.type;
|
|
1220
|
+
const lower = tag.toLowerCase();
|
|
1221
|
+
const ns = elementNs(lower, parentNsOf(fiber.root));
|
|
1222
|
+
const el = ops.createElement(tag, ns);
|
|
1069
1223
|
if (view.key !== null && view.key !== void 0) el.setAttribute(KEY_ATTR, String(view.key));
|
|
1070
1224
|
api.applyProps(el, view.props, fiber);
|
|
1071
1225
|
fiber.keyedHoles ??= /* @__PURE__ */ new Map();
|
|
@@ -1084,11 +1238,11 @@ const createPainter = (ops) => {
|
|
|
1084
1238
|
return materializeElement(view, fiber);
|
|
1085
1239
|
};
|
|
1086
1240
|
paintFns.materialize = (view, fiber) => {
|
|
1087
|
-
if (skip(view)) return [];
|
|
1241
|
+
if (skip(view)) return [ops.createText("")];
|
|
1088
1242
|
if (isUnsafeHtml(view)) return ops.createRaw(view.html, fiber.root);
|
|
1089
1243
|
if (isTextish(view)) return [ops.createText(String(view))];
|
|
1090
1244
|
if (isAtomHandle(view)) return materializeAtom(view, fiber);
|
|
1091
|
-
if (Stream.isStream(view)) return materializeStream(view, fiber);
|
|
1245
|
+
if (Stream$1.isStream(view)) return materializeStream(view, fiber);
|
|
1092
1246
|
if (isSetupFn(view)) {
|
|
1093
1247
|
const { fiber: hole, nodes } = api.openHole(fiber);
|
|
1094
1248
|
fiber.runtime.later(() => {
|
|
@@ -1145,7 +1299,7 @@ const core$1 = createPainter({
|
|
|
1145
1299
|
clearRoot: (root) => {
|
|
1146
1300
|
if (root instanceof Element) root.replaceChildren();
|
|
1147
1301
|
},
|
|
1148
|
-
createElement: (tag) => document.createElement(tag),
|
|
1302
|
+
createElement: (tag, ns) => ns ? document.createElementNS(ns, tag) : document.createElement(tag),
|
|
1149
1303
|
createRaw: (html, parent) => {
|
|
1150
1304
|
const range = document.createRange();
|
|
1151
1305
|
range.selectNodeContents(parent);
|
|
@@ -1161,9 +1315,23 @@ const core$1 = createPainter({
|
|
|
1161
1315
|
disconnect: noopDisconnect,
|
|
1162
1316
|
setFormControl: (el, key, v) => {
|
|
1163
1317
|
const node = el;
|
|
1164
|
-
if (key === "value")
|
|
1165
|
-
|
|
1166
|
-
|
|
1318
|
+
if (key === "value") {
|
|
1319
|
+
if (v === null || v === void 0) {
|
|
1320
|
+
el.removeAttribute("value");
|
|
1321
|
+
node.value = "";
|
|
1322
|
+
} else {
|
|
1323
|
+
el.setAttribute("value", String(v));
|
|
1324
|
+
node.value = String(v);
|
|
1325
|
+
}
|
|
1326
|
+
} else if (key === "checked") {
|
|
1327
|
+
node.checked = Boolean(v);
|
|
1328
|
+
if (v) el.setAttribute("checked", "");
|
|
1329
|
+
else el.removeAttribute("checked");
|
|
1330
|
+
} else {
|
|
1331
|
+
node.selected = Boolean(v);
|
|
1332
|
+
if (v) el.setAttribute("selected", "");
|
|
1333
|
+
else el.removeAttribute("selected");
|
|
1334
|
+
}
|
|
1167
1335
|
},
|
|
1168
1336
|
setStyle: (el, css) => {
|
|
1169
1337
|
el.style.cssText = css;
|
|
@@ -1209,8 +1377,14 @@ const paintMorphLive = (fiber, view) => {
|
|
|
1209
1377
|
if (!fiber.liveEl) return;
|
|
1210
1378
|
core$1.disposeHoles(fiber, { morph: true });
|
|
1211
1379
|
core$1.applyProps(fiber.liveEl, view.props, fiber);
|
|
1212
|
-
const
|
|
1213
|
-
|
|
1380
|
+
const liveNs = fiber.liveEl.namespaceURI;
|
|
1381
|
+
const tmp = liveNs && liveNs !== "http://www.w3.org/1999/xhtml" ? document.createElementNS(liveNs, fiber.liveEl.localName) : document.createElement(fiber.liveEl.localName);
|
|
1382
|
+
const childFiber = {
|
|
1383
|
+
...fiber,
|
|
1384
|
+
holes: fiber.holes,
|
|
1385
|
+
root: tmp
|
|
1386
|
+
};
|
|
1387
|
+
for (const c of view.children) for (const n of core$1.materialize(c, childFiber)) tmp.append(n);
|
|
1214
1388
|
morphInner(fiber.liveEl, tmp);
|
|
1215
1389
|
refreshAllAtomHosts(fiber);
|
|
1216
1390
|
pruneDisconnectedAtomHoles(fiber);
|
|
@@ -1233,7 +1407,7 @@ const paint$1 = (fiber, view) => {
|
|
|
1233
1407
|
paintMorphLive(fiber, view);
|
|
1234
1408
|
return;
|
|
1235
1409
|
}
|
|
1236
|
-
core$1.disposeHoles(fiber);
|
|
1410
|
+
core$1.disposeHoles(fiber, { morph: true });
|
|
1237
1411
|
if (fiber.root instanceof Element && fiber.root.childNodes.length > 0) {
|
|
1238
1412
|
const tmp = document.createElement("div");
|
|
1239
1413
|
for (const n of core$1.materialize(view, fiber)) tmp.append(n);
|
|
@@ -1596,4 +1770,4 @@ const renderToString = async (fn, opts) => {
|
|
|
1596
1770
|
};
|
|
1597
1771
|
|
|
1598
1772
|
//#endregion
|
|
1599
|
-
export { interpret as a, handleOwner as c,
|
|
1773
|
+
export { makeFiber as _, interpret as a, handleOwner as c, structuralEqual as d, untrack as f, getFiber as g, closeFiber as h, runSetup as i, instr as l, clearFiberView as m, renderToString as n, atom as o, wrapHandle as p, unsafe as r, batch as s, mount as t, isAtomHandle as u };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Effect, Stream } from "effect";
|
|
2
|
+
import { AtomRegistry } from "effect/reactivity/AtomRegistry";
|
|
3
|
+
import "effect/Scope";
|
|
4
|
+
import { Atom } from "effect/reactivity";
|
|
5
|
+
//#region src/types.d.ts
|
|
6
|
+
type JsonText = string | number | bigint | boolean | null | undefined;
|
|
7
|
+
/** Runtime prop bag values painted onto elements / passed to components. */
|
|
8
|
+
type PropValue = JsonText | PropBag | StyleObject | EventHandler | AtomHandle<JsonText> | readonly PropValue[];
|
|
9
|
+
type StyleObject = Readonly<Record<string, string | number | null | undefined>>;
|
|
10
|
+
type EventHandler = (event: Event) => void;
|
|
11
|
+
/** Indexed bag — interface so PropValue can recurse without a circular type alias. */
|
|
12
|
+
interface PropBag {
|
|
13
|
+
readonly [key: string]: PropValue | undefined;
|
|
14
|
+
}
|
|
15
|
+
type View = VNode | UnsafeHtml | JsonText | AtomHandle<unknown> | Stream.Stream<View, unknown, unknown> | GeneratorFn | Component | View[] | Iterable<View>;
|
|
16
|
+
declare const Fragment: unique symbol;
|
|
17
|
+
type Fragment = typeof Fragment;
|
|
18
|
+
type ComponentFn = (props: PropBag) => View | Promise<View | undefined> | undefined;
|
|
19
|
+
/** JSX/tag component with its own props shape (Provider, ErrorBoundary, …). */
|
|
20
|
+
type JsxComponent = (props: never) => View | Promise<View | undefined> | Generator<View, View | undefined, View> | undefined;
|
|
21
|
+
/** Raw HTML view produced by `unsafe()` — painted without escaping. */
|
|
22
|
+
interface UnsafeHtml {
|
|
23
|
+
readonly $$ilhaUnsafe: 1;
|
|
24
|
+
readonly html: string;
|
|
25
|
+
}
|
|
26
|
+
interface VNode {
|
|
27
|
+
readonly $$ilha: 1;
|
|
28
|
+
readonly type: string | Fragment | ComponentFn | JsxComponent;
|
|
29
|
+
readonly props: PropBag;
|
|
30
|
+
readonly children: View[];
|
|
31
|
+
readonly key?: string | number;
|
|
32
|
+
}
|
|
33
|
+
type GeneratorFn = () => Generator<Yielded, View | undefined, View>;
|
|
34
|
+
type Yielded = View | Instruction<unknown> | Effect.Effect<unknown, unknown, unknown>;
|
|
35
|
+
interface Instruction<A, E = Error> extends Iterable<Instruction<A, E>, A>, PromiseLike<A> {
|
|
36
|
+
readonly $$ilhaOp: 1;
|
|
37
|
+
readonly effect: Effect.Effect<A, E, AtomRegistry>;
|
|
38
|
+
}
|
|
39
|
+
type Component = (() => View | undefined | Promise<View | undefined>) | GeneratorFn;
|
|
40
|
+
interface AtomHandle<A> {
|
|
41
|
+
readonly $$atom: 1;
|
|
42
|
+
readonly atom: Atom.Atom<A>;
|
|
43
|
+
(): A;
|
|
44
|
+
set: (next: A) => void;
|
|
45
|
+
update: (f: (current: A) => A) => void;
|
|
46
|
+
}
|
|
47
|
+
/** Equality for plain-value atoms. `"structural"` deep-compares JSON-shaped values. */
|
|
48
|
+
type AtomEquality<A> = "structural" | ((prev: A, next: A) => boolean);
|
|
49
|
+
interface AtomOptions<A = unknown> {
|
|
50
|
+
/** Skip subscriber notify when `equals(prev, next)` holds. Plain values only. */
|
|
51
|
+
readonly equals?: AtomEquality<A>;
|
|
52
|
+
}
|
|
53
|
+
/** Optional disposer returned from `watch.once`. */
|
|
54
|
+
type WatchOnceCleanup = () => void;
|
|
55
|
+
/**
|
|
56
|
+
* Cancellation context handed to watch callbacks. `signal` aborts when the
|
|
57
|
+
* run goes stale (a newer value arrives), on unmount, or on slot disposal.
|
|
58
|
+
* Register extra teardowns with `onCleanup`.
|
|
59
|
+
*/
|
|
60
|
+
interface WatchContext {
|
|
61
|
+
readonly signal: AbortSignal;
|
|
62
|
+
onCleanup: (fn: () => void) => void;
|
|
63
|
+
}
|
|
64
|
+
type WatchCallback<A> = (value: A, ctx: WatchContext) => WatchOnceCleanup | undefined | Promise<WatchOnceCleanup | undefined>;
|
|
65
|
+
/** Options for `resource()`. */
|
|
66
|
+
interface ResourceOptions {
|
|
67
|
+
/** Serve cached data while revalidating in the background. Default `true`. */
|
|
68
|
+
readonly staleWhileRevalidate?: boolean;
|
|
69
|
+
}
|
|
70
|
+
/** Async fetch scoped to a resource key. Receives an abort signal. */
|
|
71
|
+
type ResourceFetcher<T> = (key: string, ctx: {
|
|
72
|
+
signal: AbortSignal;
|
|
73
|
+
}) => Promise<T>;
|
|
74
|
+
/** Handles returned by `resource()`. */
|
|
75
|
+
interface Resource<T> {
|
|
76
|
+
readonly data: AtomHandle<T | undefined>;
|
|
77
|
+
readonly error: AtomHandle<unknown>;
|
|
78
|
+
readonly loading: AtomHandle<boolean>;
|
|
79
|
+
refetch: () => Promise<T | undefined>;
|
|
80
|
+
}
|
|
81
|
+
/** Connection state of a `fromEventSource` feed. */
|
|
82
|
+
type EventSourceStatus = "connecting" | "open" | "retrying" | "closed";
|
|
83
|
+
/** Options for `fromEventSource()`. */
|
|
84
|
+
interface EventSourceOptions<T = string> {
|
|
85
|
+
/** Named event to listen for. Default: the `message` event. */
|
|
86
|
+
readonly event?: string;
|
|
87
|
+
/** Decode (and validate) `data` into `T`. Throwing skips the message. */
|
|
88
|
+
readonly schema?: (data: string) => T;
|
|
89
|
+
/** Base backoff between reconnects. Default `1000`. Capped at 30s. */
|
|
90
|
+
readonly retryBaseMs?: number;
|
|
91
|
+
}
|
|
92
|
+
/** Live server-sent-events feed. */
|
|
93
|
+
interface EventSourceFeed<T = string> {
|
|
94
|
+
/** Paint with `yield Stream.map(feed.stream, ...)`; watch `latest` instead in sync components. */
|
|
95
|
+
readonly stream: Stream.Stream<T, never, never>;
|
|
96
|
+
readonly status: AtomHandle<EventSourceStatus>;
|
|
97
|
+
readonly latest: AtomHandle<T | undefined>;
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { Yielded as S, VNode as _, ComponentFn as a, WatchContext as b, EventSourceStatus as c, JsxComponent as d, PropBag as f, UnsafeHtml as g, ResourceOptions as h, Component as i, Fragment as l, ResourceFetcher as m, AtomHandle as n, EventSourceFeed as o, Resource as p, AtomOptions as r, EventSourceOptions as s, AtomEquality as t, Instruction as u, View as v, WatchOnceCleanup as x, WatchCallback as y };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as VNode, a as ComponentFn, d as JsxComponent, f as PropBag, l as Fragment, n as AtomHandle, v as View } from "./types-CJF2qMK6.js";
|
|
2
2
|
//#region src/jsx-types.d.ts
|
|
3
3
|
declare namespace JSX {
|
|
4
4
|
export type Element = View;
|
|
@@ -71,9 +71,21 @@ declare namespace JSX {
|
|
|
71
71
|
onanimationend?: Handler<Target, globalThis.AnimationEvent>;
|
|
72
72
|
onanimationiteration?: Handler<Target, globalThis.AnimationEvent>;
|
|
73
73
|
ontransitionend?: Handler<Target, globalThis.TransitionEvent>;
|
|
74
|
+
ontoggle?: Handler<Target, globalThis.Event>;
|
|
75
|
+
onbeforetoggle?: Handler<Target, globalThis.Event>;
|
|
76
|
+
onclose?: Handler<Target, globalThis.Event>;
|
|
77
|
+
oncancel?: Handler<Target, globalThis.Event>;
|
|
74
78
|
onload?: Handler<Target, globalThis.Event>;
|
|
75
79
|
onerror?: Handler<Target, globalThis.Event>;
|
|
76
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Props every JSX tag accepts without a hand-added declaration.
|
|
83
|
+
* Components receive `key` through this interface, so you never add
|
|
84
|
+
* `key` to your own prop types.
|
|
85
|
+
*/
|
|
86
|
+
export interface IntrinsicAttributes {
|
|
87
|
+
key?: string | number;
|
|
88
|
+
}
|
|
77
89
|
type AriaProps = Partial<Record<`aria-${string}`, Attr>>;
|
|
78
90
|
type DataProps = Partial<Record<`data-${string}`, Attr>>;
|
|
79
91
|
/** Shared HTML attributes. Prefer `class` / `for`; `className` / `htmlFor` also work. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ilha",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.7",
|
|
4
4
|
"description": "Generator-first island UI on Effect",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"effect",
|
|
@@ -65,9 +65,9 @@
|
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@happy-dom/global-registrator": "^20.11.2",
|
|
68
|
-
"effect": "^4.0.0-rc.
|
|
68
|
+
"effect": "^4.0.0-rc.118"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"effect": "^4.0.0-rc.
|
|
71
|
+
"effect": "^4.0.0-rc.118"
|
|
72
72
|
}
|
|
73
73
|
}
|
package/dist/types-CyoYWhJf.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import "effect/Scope";
|
|
2
|
-
import { AtomRegistry } from "effect/unstable/reactivity/AtomRegistry";
|
|
3
|
-
import { Effect, Stream } from "effect";
|
|
4
|
-
import { Atom } from "effect/unstable/reactivity";
|
|
5
|
-
//#region src/types.d.ts
|
|
6
|
-
type JsonText = string | number | bigint | boolean | null | undefined;
|
|
7
|
-
/** Runtime prop bag values painted onto elements / passed to components. */
|
|
8
|
-
type PropValue = JsonText | PropBag | StyleObject | EventHandler | AtomHandle<JsonText> | readonly PropValue[];
|
|
9
|
-
type StyleObject = Readonly<Record<string, string | number | null | undefined>>;
|
|
10
|
-
type EventHandler = (event: Event) => void;
|
|
11
|
-
/** Indexed bag — interface so PropValue can recurse without a circular type alias. */
|
|
12
|
-
interface PropBag {
|
|
13
|
-
readonly [key: string]: PropValue | undefined;
|
|
14
|
-
}
|
|
15
|
-
type View = VNode | UnsafeHtml | JsonText | AtomHandle<unknown> | Stream.Stream<View, unknown, unknown> | GeneratorFn | Component | View[] | Iterable<View>;
|
|
16
|
-
declare const Fragment: unique symbol;
|
|
17
|
-
type Fragment = typeof Fragment;
|
|
18
|
-
type ComponentFn = (props: PropBag) => View | Promise<View | undefined> | undefined;
|
|
19
|
-
/** JSX/tag component with its own props shape (Provider, ErrorBoundary, …). */
|
|
20
|
-
type JsxComponent = (props: never) => View | Promise<View | undefined> | Generator<View, View | undefined, View> | undefined;
|
|
21
|
-
/** Raw HTML view produced by `unsafe()` — painted without escaping. */
|
|
22
|
-
interface UnsafeHtml {
|
|
23
|
-
readonly $$ilhaUnsafe: 1;
|
|
24
|
-
readonly html: string;
|
|
25
|
-
}
|
|
26
|
-
interface VNode {
|
|
27
|
-
readonly $$ilha: 1;
|
|
28
|
-
readonly type: string | Fragment | ComponentFn | JsxComponent;
|
|
29
|
-
readonly props: PropBag;
|
|
30
|
-
readonly children: View[];
|
|
31
|
-
readonly key?: string | number;
|
|
32
|
-
}
|
|
33
|
-
type GeneratorFn = () => Generator<Yielded, View | undefined, View>;
|
|
34
|
-
type Yielded = View | Instruction<unknown> | Effect.Effect<unknown, unknown, unknown>;
|
|
35
|
-
interface Instruction<A, E = Error> extends Iterable<Instruction<A, E>, A>, PromiseLike<A> {
|
|
36
|
-
readonly $$ilhaOp: 1;
|
|
37
|
-
readonly effect: Effect.Effect<A, E, AtomRegistry>;
|
|
38
|
-
}
|
|
39
|
-
type Component = (() => View | undefined | Promise<View | undefined>) | GeneratorFn;
|
|
40
|
-
interface AtomHandle<A> {
|
|
41
|
-
readonly $$atom: 1;
|
|
42
|
-
readonly atom: Atom.Atom<A>;
|
|
43
|
-
(): A;
|
|
44
|
-
set: (next: A) => void;
|
|
45
|
-
update: (f: (current: A) => A) => void;
|
|
46
|
-
}
|
|
47
|
-
//#endregion
|
|
48
|
-
export { Instruction as a, UnsafeHtml as c, Yielded as d, Fragment as i, VNode as l, Component as n, JsxComponent as o, ComponentFn as r, PropBag as s, AtomHandle as t, View as u };
|