ilha 0.15.0 → 0.15.2

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/dist/define.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as mount } from "./mount-qJHX_CfF.js";
1
+ import { t as mount } from "./mount-DKY_jSsG.js";
2
2
 
3
3
  //#region src/define.ts
4
4
  const define = (name, component) => {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { C as WatchOnceCleanup, S as WatchContext, _ as ResourceOptions, b as View, c as EventSourceStatus, d as Instruction, g as ResourceFetcher, h as Resource, i as Component, l as Fragment, n as AtomHandle, o as EventSourceFeed, r as AtomOptions, s as EventSourceOptions, t as AtomEquality, v as UnsafeHtml, w as Yielded, x as WatchCallback } from "./types-DsdtZMhG.js";
2
2
  import { t as h } from "./vnode-CpSQZnLM.js";
3
- import { r as watch } from "./runtime-B-sEGtAa.js";
3
+ import { r as watch } from "./runtime-Baq7MtkE.js";
4
4
  import * as Atom from "effect/reactivity/Atom";
5
5
  import { Equal } from "effect";
6
6
  import * as Effect$1 from "effect/Effect";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { _ as isString, f as errorView, i as Fragment, m as isFunction, t as h } from "./vnode-BHUY61Rm.js";
2
- import { C as makeFiber, S as getFiber, _ as structuralEqual, b as clearFiberView, d as interpret, f as atom, g as isAtomHandle, h as instr, m as handleOwner, n as unsafe, p as batch, u as runSetup, v as untrack, x as closeFiber, y as wrapHandle } from "./paint-core-Cw1HbMp6.js";
3
- import { n as renderToString, t as mount } from "./mount-qJHX_CfF.js";
2
+ import { C as getFiber, S as closeFiber, _ as isAtomHandle, b as wrapHandle, d as runSetup, f as interpret, g as instr, h as handleOwner, m as batch, n as unsafe, p as atom, v as structuralEqual, w as makeFiber, x as clearFiberView, y as untrack } from "./paint-core-B7jENZwS.js";
3
+ import { n as renderToString, t as mount } from "./mount-DKY_jSsG.js";
4
4
  import * as Atom from "effect/reactivity/Atom";
5
5
  import * as Effect from "effect/Effect";
6
6
  import * as Stream from "effect/Stream";
@@ -1,5 +1,5 @@
1
1
  import { _ as isString, c as KEEP, d as defer, g as isObject, m as isFunction, r as isVNode, u as SLOT_ATTR, y as unwrap } from "./vnode-BHUY61Rm.js";
2
- import { T as makeRuntime, a as morphInner, c as bindEvents, i as insertRendered, l as eventTypeFromProp, o as placeChildren, r as committedElement, s as standInFor, t as createPainter, u as runSetup, w as makeRootFiber, x as closeFiber } from "./paint-core-Cw1HbMp6.js";
2
+ import { E as makeRuntime, S as closeFiber, T as makeRootFiber, a as markControlled, c as standInFor, d as runSetup, i as insertRendered, l as bindEvents, o as morphInner, r as committedElement, s as placeChildren, t as createPainter, u as eventTypeFromProp } from "./paint-core-B7jENZwS.js";
3
3
 
4
4
  //#region src/paint.ts
5
5
  const noopDisconnect = () => {};
@@ -30,13 +30,19 @@ const core$1 = createPainter({
30
30
  reuseNode: (host) => host instanceof Element && host.isConnected ? standInFor(host) : host,
31
31
  setFormControl: (el, key, v) => {
32
32
  const node = el;
33
+ if (v !== null && v !== void 0) markControlled(el, key);
33
34
  if (key === "value") {
34
- if (v === null || v === void 0) {
35
+ const text = v === null || v === void 0 ? "" : String(v);
36
+ if (el.localName === "textarea") {
37
+ node.defaultValue = text;
38
+ node.value = text;
39
+ } else if (el.localName === "select") node.value = text;
40
+ else if (v === null || v === void 0) {
35
41
  el.removeAttribute("value");
36
42
  node.value = "";
37
43
  } else {
38
- el.setAttribute("value", String(v));
39
- node.value = String(v);
44
+ el.setAttribute("value", text);
45
+ node.value = text;
40
46
  }
41
47
  } else if (key === "checked") {
42
48
  node.checked = Boolean(v);
@@ -344,6 +350,26 @@ const bindSsrEvents = (el, props, fiber) => {
344
350
  el.dataset.ilhaOn = existing ? `${existing},${id}` : id;
345
351
  }
346
352
  };
353
+ const WHITESPACE_RUN = /\s+/gu;
354
+ /**
355
+ * Mark the first option whose value is `value` selected and clear the rest,
356
+ * as setting a live select's `.value` does. Returns whether one matched.
357
+ */
358
+ const selectOption = (parent, value, found) => {
359
+ let matched = found;
360
+ for (const child of parent.children) {
361
+ if (child.kind !== "element") continue;
362
+ if (child.localName === "optgroup") matched = selectOption(child, value, matched);
363
+ else if (child.localName === "option") {
364
+ const optionValue = child.getAttribute("value") ?? child.textContent.trim().replaceAll(WHITESPACE_RUN, " ");
365
+ if (!matched && optionValue === value) {
366
+ child.setAttribute("selected", "");
367
+ matched = true;
368
+ } else child.removeAttribute("selected");
369
+ }
370
+ }
371
+ return matched;
372
+ };
347
373
  const core = createPainter({
348
374
  appendRoot: (root, node) => ssrAs(root).append(node),
349
375
  asElement: (el) => ssrAs(el),
@@ -370,8 +396,13 @@ const core = createPainter({
370
396
  },
371
397
  reuseNode: (host) => ssrAs(host),
372
398
  setFormControl: (el, key, v) => {
373
- if (key === "value") el.setAttribute("value", String(v ?? ""));
374
- else if (v) el.setAttribute(key, "");
399
+ if (key === "value") {
400
+ const text = String(v ?? "");
401
+ if (el.localName === "textarea") el.textContent = text;
402
+ else if (el.localName === "select") {
403
+ if (v !== null && v !== void 0) selectOption(el, text, false);
404
+ } else el.setAttribute("value", text);
405
+ } else if (v) el.setAttribute(key, "");
375
406
  else el.removeAttribute(key);
376
407
  },
377
408
  setStyle: (el, css) => el.setAttribute("style", css)
@@ -362,8 +362,10 @@ const subscribeRenderDeps = (fiber, deps, run) => {
362
362
  const schedule = () => {
363
363
  if (scheduled) return;
364
364
  scheduled = true;
365
+ const seen = fiber.renderGen;
365
366
  fiber.runtime.later(() => {
366
367
  scheduled = false;
368
+ if (fiber.renderGen !== seen) return;
367
369
  run();
368
370
  });
369
371
  };
@@ -507,6 +509,7 @@ const runSetup = (fiber, fn) => {
507
509
  },
508
510
  render: () => {
509
511
  if (fiber.closed) return;
512
+ fiber.renderGen = (fiber.renderGen ?? 0) + 1;
510
513
  fiber.runtime.begin();
511
514
  beginPrimitiveFrame(fiber);
512
515
  withTrackGetRun(fiber, () => fn(), ({ value: out, deps }) => {
@@ -833,6 +836,20 @@ const collectKeys = (parent) => {
833
836
  }
834
837
  return keys;
835
838
  };
839
+ /** Rendered elements that carried a non-null form-control prop, per key.
840
+ * `checked={false}`, `selected={false}` and `<select value>` leave no
841
+ * attribute, so presence alone can't tell a controlled render from an
842
+ * uncontrolled one. */
843
+ const controlledBy = {
844
+ checked: /* @__PURE__ */ new WeakSet(),
845
+ selected: /* @__PURE__ */ new WeakSet(),
846
+ value: /* @__PURE__ */ new WeakSet()
847
+ };
848
+ /** Mark a rendered element controlled for `key`: the morph syncs it either way. */
849
+ const markControlled = (el, key) => {
850
+ controlledBy[key].add(el);
851
+ };
852
+ const isControlled = (el, key) => controlledBy[key].has(el);
836
853
  const morphInput = (fromEl, toEl) => {
837
854
  syncAttributes(fromEl, toEl);
838
855
  const from = fromEl;
@@ -842,7 +859,7 @@ const morphInput = (fromEl, toEl) => {
842
859
  if (toChecked) fromEl.setAttribute("checked", "");
843
860
  else fromEl.removeAttribute("checked");
844
861
  }
845
- if (toChecked && from.checked !== to.checked) from.checked = to.checked;
862
+ if ((toChecked || isControlled(toEl, "checked")) && from.checked !== to.checked) from.checked = to.checked;
846
863
  const toValue = toEl.getAttribute("value");
847
864
  if (toValue !== fromEl.getAttribute("value")) {
848
865
  if (toValue === null) fromEl.removeAttribute("value");
@@ -854,14 +871,32 @@ const morphTextarea = (fromEl, toEl) => {
854
871
  syncAttributes(fromEl, toEl);
855
872
  const from = fromEl;
856
873
  const to = toEl;
857
- if (to.textContent !== "" || from.textContent !== to.textContent) {
874
+ if (isControlled(toEl, "value") || to.textContent !== "" || from.textContent !== to.textContent) {
858
875
  if (from.value !== to.value) from.value = to.value;
859
876
  if (from.textContent !== to.textContent) from.textContent = to.textContent;
860
877
  }
861
878
  };
879
+ const isControlledSelect = (select) => {
880
+ if (isControlled(select, "value")) return true;
881
+ for (const o of select.options) if (isControlled(o, "selected")) return true;
882
+ return false;
883
+ };
862
884
  const morphSelect = (fromEl, toEl, api) => {
863
- const before = /* @__PURE__ */ new Map();
864
885
  const fromSelect = fromEl;
886
+ const toSelect = toEl;
887
+ if (isControlledSelect(toSelect)) {
888
+ syncAttributes(fromEl, toEl);
889
+ api.morphChildren(fromEl, toEl);
890
+ const want = toSelect.options;
891
+ let i = 0;
892
+ for (const o of fromSelect.options) {
893
+ const selected = want[i]?.selected ?? false;
894
+ if (o.selected !== selected) o.selected = selected;
895
+ i += 1;
896
+ }
897
+ return;
898
+ }
899
+ const before = /* @__PURE__ */ new Map();
865
900
  for (const o of fromSelect.options) before.set(o, {
866
901
  attr: o.hasAttribute("selected"),
867
902
  live: o.selected
@@ -1133,36 +1168,26 @@ const elementNs = (lower, parentNs) => {
1133
1168
  if (parentNs === "http://www.w3.org/2000/svg" || parentNs === "http://www.w3.org/1998/Math/MathML") return parentNs;
1134
1169
  };
1135
1170
  const canMorphRoot = (root) => typeof Element !== "undefined" && typeof document !== "undefined" && root instanceof Element && root.childNodes.length > 0;
1171
+ /** Close a child hole through the parent's hole list, so it disposes once. */
1172
+ const releaseHole = (fiber, hole) => {
1173
+ const idx = fiber.holes.findIndex((h) => h.holeFiber === hole);
1174
+ if (idx === -1) closeFiber(hole);
1175
+ else {
1176
+ const [removed] = fiber.holes.splice(idx, 1);
1177
+ removed?.dispose();
1178
+ }
1179
+ };
1136
1180
  const sweepComponentSlots = (fiber) => {
1137
1181
  const cframe = fiber.componentFrame;
1138
1182
  if (!cframe) return;
1139
1183
  const { slots } = cframe;
1140
1184
  for (let j = cframe.i; j < slots.length; j += 1) {
1141
1185
  const s = slots[j];
1142
- if (s) {
1143
- const { hole } = s;
1144
- if (!hole.closed) {
1145
- const idx = fiber.holes.findIndex((h) => h.holeFiber === hole);
1146
- if (idx === -1) closeFiber(hole);
1147
- else {
1148
- const [removed] = fiber.holes.splice(idx, 1);
1149
- removed?.dispose();
1150
- }
1151
- }
1152
- }
1186
+ if (s && !s.hole.closed) releaseHole(fiber, s.hole);
1153
1187
  slots[j] = void 0;
1154
1188
  }
1155
1189
  slots.length = cframe.i;
1156
1190
  };
1157
- /** Close a child hole through the parent's hole list, so it disposes once. */
1158
- const releaseHole = (fiber, hole) => {
1159
- const idx = fiber.holes.findIndex((h) => h.holeFiber === hole);
1160
- if (idx === -1) closeFiber(hole);
1161
- else {
1162
- const [removed] = fiber.holes.splice(idx, 1);
1163
- removed?.dispose();
1164
- }
1165
- };
1166
1191
  /** Close the keyed components the paint that just ran did not reach. */
1167
1192
  const sweepKeyedHoles = (fiber) => {
1168
1193
  const { keyedHoles, keyedGen } = fiber;
@@ -1183,6 +1208,61 @@ const pass = (fiber, fn) => {
1183
1208
  fn();
1184
1209
  sweepKeyedHoles(fiber);
1185
1210
  };
1211
+ /**
1212
+ * Dispose a hole fiber's child holes before it repaints, except the component
1213
+ * and island holes the repaint can reuse: positional children, keyed
1214
+ * children, and islands. Reuse pushes new props instead of remounting, and the
1215
+ * sweeps that end the paint close whatever it did not reach.
1216
+ */
1217
+ const keepReusableHoles = (fiber, cframe, frame) => {
1218
+ const kept = /* @__PURE__ */ new Set();
1219
+ for (const s of cframe.slots) if (s && !s.hole.closed) kept.add(s.hole);
1220
+ for (const hole of fiber.keyedHoles?.values() ?? []) if (!hole.closed) kept.add(hole);
1221
+ const keptIslands = new Set(frame.slots);
1222
+ const keep = [];
1223
+ for (const h of fiber.holes) {
1224
+ if (h.holeFiber && kept.has(h.holeFiber) || h.islandSlot && keptIslands.has(h.islandSlot)) {
1225
+ keep.push(h);
1226
+ continue;
1227
+ }
1228
+ h.dispose();
1229
+ }
1230
+ fiber.holes = keep;
1231
+ };
1232
+ /** Shallow equality of two prop bags, children compared item by item. */
1233
+ const sameProps = (prev, next) => {
1234
+ if (!prev) return false;
1235
+ const keys = Object.keys(next);
1236
+ if (keys.length !== Object.keys(prev).length) return false;
1237
+ return keys.every((k) => {
1238
+ const a = prev[k];
1239
+ const b = next[k];
1240
+ if (k === "children" && Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((x, i) => Object.is(x, b[i]));
1241
+ return Object.is(a, b);
1242
+ });
1243
+ };
1244
+ /**
1245
+ * Rerun a reused component hole with new props, in its own fiber. The props
1246
+ * box is updated in place, so every render closure of the hole reads the
1247
+ * latest props, including a self-render queued while an async render ran.
1248
+ */
1249
+ const rerunHole = (hole, run, props) => {
1250
+ const box = hole.propsBox ?? { current: props };
1251
+ box.current = props;
1252
+ hole.propsBox = box;
1253
+ runSetup(hole, () => run(box.current));
1254
+ };
1255
+ /**
1256
+ * Run a new component hole's first render after the paint that opened it. A
1257
+ * repaint that reached the hole first already rendered it with newer props.
1258
+ */
1259
+ const mountHoleLater = (fiber, hole, run) => {
1260
+ fiber.runtime.later(() => {
1261
+ const box = hole.propsBox;
1262
+ if (hole.closed || hole.renderGen !== void 0 || !box) return;
1263
+ runSetup(hole, () => run(box.current));
1264
+ });
1265
+ };
1186
1266
  const warnedKeys = /* @__PURE__ */ new Set();
1187
1267
  const warnDuplicateKey = (key) => {
1188
1268
  if (warnedKeys.has(key)) return;
@@ -1221,10 +1301,6 @@ const styleCss = (v) => {
1221
1301
  if (isString(v) || isObject(v)) return serializeStyleAttr(v);
1222
1302
  return "";
1223
1303
  };
1224
- const isThenable = (value) => {
1225
- if (!isObject(value) && !isFunction(value)) return false;
1226
- return isFunction(value.then);
1227
- };
1228
1304
  const writeAttr = (el, k, v) => {
1229
1305
  if (v === false || v === null || v === void 0) {
1230
1306
  el.removeAttribute(k);
@@ -1369,18 +1445,7 @@ const createPainter = (ops) => {
1369
1445
  sweepIslandSlots(fiber);
1370
1446
  return;
1371
1447
  }
1372
- const kept = /* @__PURE__ */ new Set();
1373
- for (const s of cframe.slots) if (s && !s.hole.closed) kept.add(s.hole);
1374
- const keptIslands = new Set(frame.slots);
1375
- const keep = [];
1376
- for (const h of fiber.holes) {
1377
- if (h.holeFiber && kept.has(h.holeFiber) || h.islandSlot && keptIslands.has(h.islandSlot)) {
1378
- keep.push(h);
1379
- continue;
1380
- }
1381
- h.dispose();
1382
- }
1383
- fiber.holes = keep;
1448
+ keepReusableHoles(fiber, cframe, frame);
1384
1449
  const fresh = api.materialize(view, fiber);
1385
1450
  if (canMorphRoot(fiber.root)) {
1386
1451
  const tmp = document.createElement("div");
@@ -1494,18 +1559,10 @@ const createPainter = (ops) => {
1494
1559
  if (existing) {
1495
1560
  const { hole } = existing;
1496
1561
  if (existing.type === type && !hole.closed) {
1497
- hole.propsBox = { current: props };
1498
- runSetup(hole, () => run(props));
1562
+ rerunHole(hole, run, props);
1499
1563
  return [ops.reuseNode(hole.root)];
1500
1564
  }
1501
- if (!hole.closed) {
1502
- const idx = fiber.holes.findIndex((h) => h.holeFiber === hole);
1503
- if (idx === -1) closeFiber(hole);
1504
- else {
1505
- const [removed] = fiber.holes.splice(idx, 1);
1506
- removed?.dispose();
1507
- }
1508
- }
1565
+ if (!hole.closed) releaseHole(fiber, hole);
1509
1566
  }
1510
1567
  const { fiber: hole, nodes } = api.openHole(fiber);
1511
1568
  hole.propsBox = { current: props };
@@ -1514,58 +1571,61 @@ const createPainter = (ops) => {
1514
1571
  hole,
1515
1572
  type
1516
1573
  };
1517
- fiber.runtime.later(() => {
1518
- if (hole.closed) return;
1519
- const box = hole.propsBox;
1520
- if (!box) return;
1521
- runSetup(hole, () => run(box.current));
1522
- });
1574
+ mountHoleLater(fiber, hole, run);
1523
1575
  trackHole(fiber, hole, void 0, { keyed: true });
1524
1576
  return nodes;
1525
1577
  };
1526
- const materializeComponent = (view, type, fiber) => {
1527
- const props = {
1528
- ...view.props,
1529
- children: view.children
1530
- };
1531
- const branded = type;
1532
- if (branded[ISLAND] === true) return materializeIsland(branded, props, fiber);
1533
- const k = view.key === null || view.key === void 0 ? void 0 : String(view.key);
1534
- const reuse = k ? fiber.keyedHoles?.get(k) : void 0;
1535
- const run = type;
1578
+ const materializeKeyedComponent = ({ run, type, props, key, fiber }) => {
1579
+ let reuse = fiber.keyedHoles?.get(key);
1536
1580
  const gen = fiber.keyedGen;
1537
- if (k && reuse && !reuse.closed && reuse.keyedSeen === gen) {
1538
- warnDuplicateKey(k);
1581
+ if (reuse && !reuse.closed && reuse.keyedSeen === gen) {
1582
+ warnDuplicateKey(key);
1539
1583
  return materializeUnkeyedComponent(run, type, props, fiber);
1540
1584
  }
1585
+ if (reuse && !reuse.closed && reuse.componentType !== type) {
1586
+ fiber.keyedHoles?.delete(key);
1587
+ releaseHole(fiber, reuse);
1588
+ reuse = void 0;
1589
+ }
1541
1590
  if (reuse && !reuse.closed) {
1542
1591
  reuse.keyedSeen = gen;
1543
- if (reuse.propsBox) reuse.propsBox.current = props;
1544
- const next = withFiber(fiber, () => run(reuse.propsBox?.current ?? props));
1545
- if (next && !isThenable(next) && !isSetupFn(next)) reuse.paint(next);
1592
+ if (!sameProps(reuse.propsBox?.current, props)) rerunHole(reuse, run, props);
1546
1593
  return [ops.reuseNode(reuse.root)];
1547
1594
  }
1548
- if (!k) return materializeUnkeyedComponent(run, type, props, fiber);
1549
1595
  const { fiber: khole, nodes: knodes } = api.openHole(fiber);
1550
1596
  khole.propsBox = { current: props };
1597
+ khole.componentType = type;
1551
1598
  khole.keyedSeen = gen;
1552
- fiber.keyedHoles?.set(k, khole);
1553
- fiber.runtime.later(() => {
1554
- if (khole.closed) return;
1555
- const box = khole.propsBox;
1556
- if (!box) return;
1557
- runSetup(khole, () => run(box.current));
1558
- });
1599
+ fiber.keyedHoles?.set(key, khole);
1600
+ mountHoleLater(fiber, khole, run);
1559
1601
  trackHole(fiber, khole, void 0, { keyed: true });
1560
1602
  return knodes;
1561
1603
  };
1604
+ const materializeComponent = (view, type, fiber) => {
1605
+ const props = {
1606
+ ...view.props,
1607
+ children: view.children
1608
+ };
1609
+ const branded = type;
1610
+ if (branded[ISLAND] === true) return materializeIsland(branded, props, fiber);
1611
+ const run = type;
1612
+ if (view.key === null || view.key === void 0) return materializeUnkeyedComponent(run, type, props, fiber);
1613
+ return materializeKeyedComponent({
1614
+ fiber,
1615
+ key: String(view.key),
1616
+ props,
1617
+ run,
1618
+ type
1619
+ });
1620
+ };
1562
1621
  const materializeElement = (view, fiber) => {
1563
1622
  const tag = view.type;
1564
1623
  const lower = tag.toLowerCase();
1565
1624
  const ns = elementNs(lower, parentNsOf(fiber.root));
1566
1625
  const el = ops.createElement(tag, ns);
1567
1626
  if (view.key !== null && view.key !== void 0) el.setAttribute(KEY_ATTR, String(view.key));
1568
- api.applyProps(el, view.props, fiber);
1627
+ const propsAfterChildren = lower === "select";
1628
+ if (!propsAfterChildren) api.applyProps(el, view.props, fiber);
1569
1629
  const childFiber = {
1570
1630
  ...fiber,
1571
1631
  holes: fiber.holes,
@@ -1573,6 +1633,7 @@ const createPainter = (ops) => {
1573
1633
  root: ops.asRoot(el)
1574
1634
  };
1575
1635
  for (const c of view.children) for (const n of api.materialize(c, childFiber)) el.append(n);
1636
+ if (propsAfterChildren) api.applyProps(el, view.props, fiber);
1576
1637
  return [el];
1577
1638
  };
1578
1639
  const materializeVNode = (view, fiber) => {
@@ -1602,8 +1663,14 @@ const createPainter = (ops) => {
1602
1663
  const nodes = [];
1603
1664
  for (const v of views) {
1604
1665
  const reuse = fiber.keyedHoles?.get(String(v.key));
1605
- if (reuse && !reuse.closed) {
1666
+ const reusable = reuse && !reuse.closed && reuse.keyedSeen !== fiber.keyedGen && reuse.componentType === v.type;
1667
+ if (reuse && reusable) {
1606
1668
  reuse.keyedSeen = fiber.keyedGen;
1669
+ const props = {
1670
+ ...v.props,
1671
+ children: v.children
1672
+ };
1673
+ if (!sameProps(reuse.propsBox?.current, props)) rerunHole(reuse, v.type, props);
1607
1674
  nodes.push(ops.asNode(reuse.root));
1608
1675
  continue;
1609
1676
  }
@@ -1623,4 +1690,4 @@ const createPainter = (ops) => {
1623
1690
  };
1624
1691
 
1625
1692
  //#endregion
1626
- export { makeFiber as C, getFiber as S, makeRuntime as T, structuralEqual as _, morphInner as a, clearFiberView as b, bindEvents as c, interpret as d, atom as f, isAtomHandle as g, instr as h, insertRendered as i, eventTypeFromProp as l, handleOwner as m, unsafe as n, placeChildren as o, batch as p, committedElement as r, standInFor as s, createPainter as t, runSetup as u, untrack as v, makeRootFiber as w, closeFiber as x, wrapHandle as y };
1693
+ export { getFiber as C, makeRuntime as E, closeFiber as S, makeRootFiber as T, isAtomHandle as _, markControlled as a, wrapHandle as b, standInFor as c, runSetup as d, interpret as f, instr as g, handleOwner as h, insertRendered as i, bindEvents as l, batch as m, unsafe as n, morphInner as o, atom as p, committedElement as r, placeChildren as s, createPainter as t, eventTypeFromProp as u, structuralEqual as v, makeFiber as w, clearFiberView as x, untrack as y };
@@ -1,5 +1,5 @@
1
1
  import { b as View, i as Component, m as PropValue, p as PropBag, u as IlhaRuntime } from "./types-DsdtZMhG.js";
2
- import { n as getFiber, t as FiberLocal } from "./runtime-B-sEGtAa.js";
2
+ import { n as getFiber, t as FiberLocal } from "./runtime-Baq7MtkE.js";
3
3
  //#region src/shared.d.ts
4
4
  declare const KEEP: unique symbol;
5
5
  //#endregion
package/dist/renderer.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { d as defer } from "./vnode-BHUY61Rm.js";
2
- import { S as getFiber, T as makeRuntime, c as bindEvents, t as createPainter, u as runSetup, w as makeRootFiber, x as closeFiber } from "./paint-core-Cw1HbMp6.js";
2
+ import { C as getFiber, E as makeRuntime, S as closeFiber, T as makeRootFiber, d as runSetup, l as bindEvents, t as createPainter } from "./paint-core-B7jENZwS.js";
3
3
 
4
4
  //#region src/renderer.ts
5
5
  /**
@@ -78,6 +78,8 @@ interface FiberLocal {
78
78
  componentFrame?: ComponentFrame;
79
79
  componentType?: unknown;
80
80
  renderSub?: () => void;
81
+ /** Counts the renders this fiber started; see `subscribeRenderDeps`. */
82
+ renderGen?: number;
81
83
  trackRestore?: () => void;
82
84
  propsBox?: {
83
85
  current: PropBag;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ilha",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
4
4
  "description": "Generator-first island UI on Effect",
5
5
  "keywords": [
6
6
  "effect",