@lark.js/mvc 0.0.11 → 0.0.13

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/devtool.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  nextCounter,
22
22
  refFn,
23
23
  strSafe
24
- } from "./chunk-RIV4NK3K.js";
24
+ } from "./chunk-66OZBBSP.js";
25
25
 
26
26
  // src/utils.ts
27
27
  var CALL_BREAK_TIME = 9;
@@ -698,61 +698,6 @@ var EventDelegator = {
698
698
  }
699
699
  };
700
700
 
701
- // src/safeguard.ts
702
- var proxiesPool = /* @__PURE__ */ new Map();
703
- var SAFEGUARD_SENTINEL = "_safe_";
704
- function safeguard(data, getter, setter, isRoot) {
705
- if (typeof window.__lark_Debug === "undefined" || !window.__lark_Debug) {
706
- return data;
707
- }
708
- if (typeof Proxy === "undefined") {
709
- return data;
710
- }
711
- if (isPrimitive(data)) {
712
- return data;
713
- }
714
- const build = (prefix, obj) => {
715
- const cacheKey = (getter || "") + "" + (setter || "");
716
- const cached = proxiesPool.get(obj);
717
- if (cached && cached.cacheKey === cacheKey) {
718
- return cached.entity;
719
- }
720
- if (Reflect.get(obj, SAFEGUARD_SENTINEL)) {
721
- return obj;
722
- }
723
- const entity = new Proxy(obj, {
724
- set(target, property, value) {
725
- if (!setter && !prefix) {
726
- throw new Error(
727
- "Avoid write back, key: " + prefix + property + " value:" + value + " more: https://github.com/hangtiancheng/lark"
728
- );
729
- }
730
- Reflect.set(target, property, value);
731
- if (setter) {
732
- setter(prefix + property, value);
733
- }
734
- return true;
735
- },
736
- get(target, property) {
737
- if (property === SAFEGUARD_SENTINEL) {
738
- return true;
739
- }
740
- const out = Reflect.get(target, property);
741
- if (!prefix && getter) {
742
- getter(property);
743
- }
744
- if (!isRoot && hasOwnProperty(target, property) && (Array.isArray(out) || isPlainObject(out))) {
745
- return build(prefix + property + ".", out);
746
- }
747
- return out;
748
- }
749
- });
750
- proxiesPool.set(obj, { cacheKey, entity });
751
- return entity;
752
- };
753
- return build("", data);
754
- }
755
-
756
701
  // src/module-loader.ts
757
702
  var config = {
758
703
  rootId: "root",
@@ -1070,18 +1015,6 @@ var DOM_SPECIALS = {
1070
1015
  function isSameVDomNode(a, b) {
1071
1016
  return a.compareKey && b.compareKey === a.compareKey || !a.compareKey && !b.compareKey && a.tag === b.tag || a.tag === SPLITTER || b.tag === SPLITTER;
1072
1017
  }
1073
- function getKeyNodes(list, nodes, start, end, realEnd) {
1074
- const keyedNodes = {};
1075
- for (let i = end, re = realEnd; i >= start; i--, re--) {
1076
- const oc = list[i];
1077
- const cKey = oc.compareKey;
1078
- if (cKey) {
1079
- const bucket = keyedNodes[cKey] || (keyedNodes[cKey] = []);
1080
- bucket.push(nodes[re]);
1081
- }
1082
- }
1083
- return keyedNodes;
1084
- }
1085
1018
  function vdomCreateNode(vnode, owner, ref) {
1086
1019
  const tag = vnode.tag;
1087
1020
  if (tag === V_TEXT_NODE) {
@@ -1170,9 +1103,10 @@ function vdomSetNode(realNode, oldParent, lastVDom, newVDom, ref, frame, keys, r
1170
1103
  return;
1171
1104
  }
1172
1105
  if (lastTag === newTag) {
1173
- const lastAMap = lastVDom.attrsMap || {};
1174
- const newAMap = newVDom.attrsMap || {};
1175
- if (lastVDom.compareKey && lastVDom.compareKey === newVDom.compareKey && !lastAMap["id"] && !newAMap["id"]) {
1106
+ if (lastVDom.attrs === newVDom.attrs && lastVDom.html === newVDom.html) {
1107
+ if (newVDom.hasSpecials) {
1108
+ vdomSyncFormState(realNode, newVDom);
1109
+ }
1176
1110
  return;
1177
1111
  }
1178
1112
  let attrChanged = 0;
@@ -1213,261 +1147,209 @@ function vdomSetNode(realNode, oldParent, lastVDom, newVDom, ref, frame, keys, r
1213
1147
  oldParent.replaceChild(vdomCreateNode(newVDom, oldParent, ref), realNode);
1214
1148
  }
1215
1149
  }
1150
+ function computeLIS(sequence) {
1151
+ const len = sequence.length;
1152
+ if (len === 0) return [];
1153
+ const result = [];
1154
+ const tails = [];
1155
+ const predecessors = new Array(len);
1156
+ let lisLength = 0;
1157
+ for (let i = 0; i < len; i++) {
1158
+ const value = sequence[i];
1159
+ if (value < 0) continue;
1160
+ let lo = 0;
1161
+ let hi = lisLength;
1162
+ while (lo < hi) {
1163
+ const mid = lo + hi >>> 1;
1164
+ if (sequence[tails[mid]] < value) lo = mid + 1;
1165
+ else hi = mid;
1166
+ }
1167
+ tails[lo] = i;
1168
+ predecessors[i] = lo > 0 ? tails[lo - 1] : -1;
1169
+ if (lo === lisLength) lisLength++;
1170
+ }
1171
+ let cursor = tails[lisLength - 1];
1172
+ for (let i = lisLength - 1; i >= 0; i--) {
1173
+ result[i] = cursor;
1174
+ cursor = predecessors[cursor];
1175
+ }
1176
+ return result;
1177
+ }
1216
1178
  function vdomSetChildNodes(realNode, lastVDom, newVDom, ref, frame, keys, view, ready) {
1217
1179
  if (!lastVDom) {
1218
1180
  ref.changed = 1;
1219
1181
  realNode.innerHTML = newVDom.html;
1182
+ callFunction(ready, []);
1220
1183
  return;
1221
1184
  }
1222
1185
  if (lastVDom.html === newVDom.html) {
1186
+ callFunction(ready, []);
1223
1187
  return;
1224
1188
  }
1225
1189
  const oldChildren = lastVDom.children;
1226
1190
  const newChildren = newVDom.children;
1227
1191
  const oldLen = oldChildren?.length || 0;
1228
1192
  const newLen = newChildren?.length || 0;
1229
- if (oldLen === 0 && newLen === 0) return;
1193
+ if (oldLen === 0 && newLen === 0) {
1194
+ callFunction(ready, []);
1195
+ return;
1196
+ }
1230
1197
  const nodes = realNode.childNodes;
1231
- let oldStart = 0;
1232
- let oldEnd = oldLen - 1;
1233
- let newStart = 0;
1234
- let newEnd = newLen - 1;
1235
- let realStart = oldStart;
1236
- let realEnd = oldEnd;
1237
- let keyedNodes;
1238
- const oldReusedTotal = lastVDom.reusedTotal || 0;
1239
- const newReusedTotal = newVDom.reusedTotal || 0;
1240
- let oldStartNode = oldChildren?.[oldStart];
1241
- let oldEndNode = oldChildren?.[oldEnd];
1242
- let newStartNode = newChildren?.[newStart];
1243
- let newEndNode = newChildren?.[newEnd];
1244
- while (oldStart <= oldEnd && newStart <= newEnd) {
1245
- if (!oldStartNode) {
1246
- oldStartNode = oldChildren?.[++oldStart];
1247
- realStart++;
1248
- continue;
1249
- }
1250
- if (!oldEndNode) {
1251
- oldEndNode = oldChildren?.[--oldEnd];
1252
- realEnd--;
1253
- continue;
1254
- }
1255
- if (isSameVDomNode(newStartNode, oldStartNode)) {
1256
- if (newStartNode.tag === SPLITTER || oldStartNode.tag === SPLITTER) {
1257
- ref.changed = 1;
1258
- domUnmountFrames(frame, realNode);
1259
- if (newStartNode.tag === SPLITTER) {
1260
- realNode.innerHTML = newStartNode.html;
1261
- } else {
1262
- realNode.innerHTML = "";
1263
- realNode.appendChild(vdomCreateNode(newStartNode, realNode, ref));
1264
- }
1265
- } else {
1266
- vdomSetNode(
1267
- nodes[realStart],
1268
- realNode,
1269
- oldStartNode,
1270
- newStartNode,
1271
- ref,
1272
- frame,
1273
- keys,
1274
- view,
1275
- ready
1276
- );
1277
- }
1278
- reduceCached(keyedNodes, oldStartNode, nodes[realStart]);
1279
- realStart++;
1280
- oldStartNode = oldChildren?.[++oldStart];
1281
- newStartNode = newChildren?.[++newStart];
1282
- } else if (isSameVDomNode(newEndNode, oldEndNode)) {
1283
- if (newEndNode.tag === SPLITTER || oldEndNode.tag === SPLITTER) {
1284
- ref.changed = 1;
1285
- domUnmountFrames(frame, realNode);
1286
- realNode.innerHTML = newEndNode.tag === SPLITTER ? newEndNode.html : "";
1287
- if (newEndNode.tag !== SPLITTER) {
1288
- realNode.appendChild(vdomCreateNode(newEndNode, realNode, ref));
1289
- }
1290
- } else {
1291
- vdomSetNode(
1292
- nodes[realEnd],
1293
- realNode,
1294
- oldEndNode,
1295
- newEndNode,
1296
- ref,
1297
- frame,
1298
- keys,
1299
- view,
1300
- ready
1301
- );
1302
- }
1303
- reduceCached(keyedNodes, oldEndNode, nodes[realEnd]);
1304
- realEnd--;
1305
- oldEndNode = oldChildren?.[--oldEnd];
1306
- newEndNode = newChildren?.[--newEnd];
1307
- } else if (isSameVDomNode(newEndNode, oldStartNode)) {
1308
- if (newEndNode.tag === SPLITTER || oldStartNode.tag === SPLITTER) {
1309
- ref.changed = 1;
1310
- domUnmountFrames(frame, realNode);
1311
- realNode.innerHTML = newEndNode.tag === SPLITTER ? newEndNode.html : "";
1312
- if (newEndNode.tag !== SPLITTER) {
1313
- realNode.appendChild(vdomCreateNode(newEndNode, realNode, ref));
1314
- }
1315
- } else {
1316
- const oi = nodes[realStart];
1317
- realNode.insertBefore(oi, nodes[realEnd + 1] || null);
1318
- vdomSetNode(
1319
- oi,
1320
- realNode,
1321
- oldStartNode,
1322
- newEndNode,
1323
- ref,
1324
- frame,
1325
- keys,
1326
- view,
1327
- ready
1328
- );
1329
- }
1330
- reduceCached(keyedNodes, oldStartNode, nodes[realStart]);
1331
- realStart++;
1332
- oldStartNode = oldChildren?.[++oldStart];
1333
- newEndNode = newChildren?.[--newEnd];
1334
- } else if (isSameVDomNode(newStartNode, oldEndNode)) {
1335
- if (newStartNode.tag === SPLITTER || oldEndNode.tag === SPLITTER) {
1336
- ref.changed = 1;
1337
- domUnmountFrames(frame, realNode);
1338
- realNode.innerHTML = newStartNode.tag === SPLITTER ? newStartNode.html : "";
1339
- if (newStartNode.tag !== SPLITTER) {
1340
- realNode.appendChild(vdomCreateNode(newStartNode, realNode, ref));
1341
- }
1342
- } else {
1343
- const oi = nodes[realEnd];
1344
- realNode.insertBefore(oi, nodes[realStart]);
1345
- vdomSetNode(
1346
- oi,
1347
- realNode,
1348
- oldEndNode,
1349
- newStartNode,
1350
- ref,
1351
- frame,
1352
- keys,
1353
- view,
1354
- ready
1355
- );
1356
- }
1357
- reduceCached(keyedNodes, oldEndNode, nodes[realEnd]);
1358
- realEnd--;
1359
- oldEndNode = oldChildren?.[--oldEnd];
1360
- newStartNode = newChildren?.[++newStart];
1198
+ const oldDomNodes = new Array(oldLen);
1199
+ for (let i = 0; i < oldLen; i++) {
1200
+ oldDomNodes[i] = nodes[i];
1201
+ }
1202
+ const usedOldDomNodes = /* @__PURE__ */ new Set();
1203
+ let headIdx = 0;
1204
+ let tailIdx = oldLen - 1;
1205
+ let newHead = 0;
1206
+ let newTail = newLen - 1;
1207
+ while (headIdx <= tailIdx && newHead <= newTail) {
1208
+ const oc = oldChildren[headIdx];
1209
+ const nc = newChildren[newHead];
1210
+ if (!isSameVDomNode(nc, oc)) break;
1211
+ if (nc.tag === SPLITTER || oc.tag === SPLITTER) break;
1212
+ vdomSetNode(
1213
+ oldDomNodes[headIdx],
1214
+ realNode,
1215
+ oc,
1216
+ nc,
1217
+ ref,
1218
+ frame,
1219
+ keys,
1220
+ view,
1221
+ ready
1222
+ );
1223
+ usedOldDomNodes.add(oldDomNodes[headIdx]);
1224
+ headIdx++;
1225
+ newHead++;
1226
+ }
1227
+ while (headIdx <= tailIdx && newHead <= newTail) {
1228
+ const oc = oldChildren[tailIdx];
1229
+ const nc = newChildren[newTail];
1230
+ if (!isSameVDomNode(nc, oc)) break;
1231
+ if (nc.tag === SPLITTER || oc.tag === SPLITTER) break;
1232
+ vdomSetNode(
1233
+ oldDomNodes[tailIdx],
1234
+ realNode,
1235
+ oc,
1236
+ nc,
1237
+ ref,
1238
+ frame,
1239
+ keys,
1240
+ view,
1241
+ ready
1242
+ );
1243
+ usedOldDomNodes.add(oldDomNodes[tailIdx]);
1244
+ tailIdx--;
1245
+ newTail--;
1246
+ }
1247
+ if (headIdx > tailIdx && newHead > newTail) {
1248
+ if (ref.asyncCount === 0) callFunction(ready, []);
1249
+ return;
1250
+ }
1251
+ const keyMap = {};
1252
+ for (let i = headIdx; i <= tailIdx; i++) {
1253
+ const c = oldChildren[i];
1254
+ if (c?.compareKey) {
1255
+ if (!keyMap[c.compareKey]) keyMap[c.compareKey] = [];
1256
+ keyMap[c.compareKey].push({ domNode: oldDomNodes[i], vdomNode: c });
1257
+ }
1258
+ }
1259
+ const newRemaining = newTail - newHead + 1;
1260
+ const sequence = new Array(newRemaining);
1261
+ for (let i = 0; i < newRemaining; i++) {
1262
+ const nc = newChildren[newHead + i];
1263
+ const cKey = nc.compareKey;
1264
+ const entries = cKey ? keyMap[cKey] : void 0;
1265
+ if (entries && entries.length > 0) {
1266
+ const entry = entries.shift();
1267
+ if (entries.length === 0) delete keyMap[cKey];
1268
+ const oldIdx = oldChildren.indexOf(entry.vdomNode, headIdx);
1269
+ sequence[i] = oldIdx >= 0 ? oldIdx : -1;
1270
+ usedOldDomNodes.add(entry.domNode);
1361
1271
  } else {
1362
- if (!keyedNodes && newReusedTotal > 0 && oldReusedTotal > 0) {
1363
- keyedNodes = getKeyNodes(
1364
- oldChildren,
1365
- nodes,
1366
- oldStart,
1367
- oldEnd,
1368
- realEnd
1369
- );
1370
- }
1371
- const cKey = newStartNode.compareKey;
1372
- let found;
1373
- let compareKey;
1374
- if (cKey && keyedNodes) {
1375
- found = keyedNodes[cKey];
1376
- compareKey = void 0;
1377
- while (found && found.length > 0) {
1378
- compareKey = found.pop();
1379
- if (compareKey) break;
1380
- }
1381
- if (found && found.length === 0) delete keyedNodes[cKey];
1382
- }
1383
- if (compareKey) {
1384
- if (compareKey !== nodes[realStart]) {
1385
- for (let j = oldStart + 1; j <= oldEnd; j++) {
1386
- const oc = oldChildren?.[j];
1387
- if (oc && nodes[realStart + (j - oldStart)] === compareKey) {
1388
- oldChildren[j] = void 0;
1389
- break;
1390
- }
1391
- }
1392
- realNode.insertBefore(compareKey, nodes[realStart]);
1393
- }
1394
- vdomSetNode(
1395
- compareKey,
1396
- realNode,
1397
- oldStartNode,
1398
- newStartNode,
1399
- ref,
1400
- frame,
1401
- keys,
1402
- view,
1403
- ready
1404
- );
1405
- } else if (oldStartNode.compareKey && lastVDom.reused?.[oldStartNode.compareKey] && newVDom.reused?.[oldStartNode.compareKey] || nodes[realStart]?.id && realNode.querySelectorAll?.(
1406
- `#${nodes[realStart].id}`
1407
- )?.length && !newStartNode.isLarkView) {
1272
+ sequence[i] = -1;
1273
+ }
1274
+ }
1275
+ if (newHead > newTail) {
1276
+ for (let i = 0; i < oldLen; i++) {
1277
+ const domNode = oldDomNodes[i];
1278
+ if (domNode && !usedOldDomNodes.has(domNode) && domNode.parentNode === realNode) {
1279
+ domUnmountFrames(frame, domNode);
1408
1280
  ref.changed = 1;
1409
- const newNode = vdomCreateNode(newStartNode, realNode, ref);
1410
- realNode.insertBefore(newNode, nodes[realStart]);
1411
- realStart--;
1412
- realEnd++;
1413
- } else {
1414
- vdomSetNode(
1415
- nodes[realStart],
1416
- realNode,
1417
- oldStartNode,
1418
- newStartNode,
1419
- ref,
1420
- frame,
1421
- keys,
1422
- view,
1423
- ready
1424
- );
1281
+ realNode.removeChild(domNode);
1425
1282
  }
1426
- realStart++;
1427
- oldStartNode = oldChildren?.[++oldStart];
1428
- newStartNode = newChildren?.[++newStart];
1429
1283
  }
1284
+ if (ref.asyncCount === 0) callFunction(ready, []);
1285
+ return;
1430
1286
  }
1431
- if (newStart <= newEnd) {
1432
- const refNode = nodes[realEnd + 1] || null;
1433
- for (let i = newStart; i <= newEnd; i++) {
1287
+ if (headIdx > tailIdx) {
1288
+ const insertRef = tailIdx < oldLen ? oldDomNodes[tailIdx + 1] ?? null : null;
1289
+ for (let i = newHead; i <= newTail; i++) {
1290
+ ref.changed = 1;
1291
+ const newNode = vdomCreateNode(newChildren[i], realNode, ref);
1292
+ realNode.insertBefore(newNode, insertRef);
1293
+ }
1294
+ if (ref.asyncCount === 0) callFunction(ready, []);
1295
+ return;
1296
+ }
1297
+ const lis = computeLIS(sequence);
1298
+ let lisCursor = lis.length - 1;
1299
+ let nextNode = tailIdx + 1 < oldLen ? oldDomNodes[tailIdx + 1] : null;
1300
+ for (let j = newRemaining - 1; j >= 0; j--) {
1301
+ const newIdx = newHead + j;
1302
+ const nc = newChildren[newIdx];
1303
+ if (lisCursor >= 0 && lis[lisCursor] === j) {
1304
+ const oldIdx = sequence[j];
1305
+ vdomSetNode(
1306
+ oldDomNodes[oldIdx],
1307
+ realNode,
1308
+ oldChildren[oldIdx],
1309
+ nc,
1310
+ ref,
1311
+ frame,
1312
+ keys,
1313
+ view,
1314
+ ready
1315
+ );
1316
+ nextNode = oldDomNodes[oldIdx];
1317
+ lisCursor--;
1318
+ } else if (sequence[j] >= 0) {
1319
+ const oldIdx = sequence[j];
1320
+ ref.changed = 1;
1321
+ realNode.insertBefore(oldDomNodes[oldIdx], nextNode);
1322
+ vdomSetNode(
1323
+ oldDomNodes[oldIdx],
1324
+ realNode,
1325
+ oldChildren[oldIdx],
1326
+ nc,
1327
+ ref,
1328
+ frame,
1329
+ keys,
1330
+ view,
1331
+ ready
1332
+ );
1333
+ nextNode = oldDomNodes[oldIdx];
1334
+ } else {
1434
1335
  ref.changed = 1;
1435
- const nc = newChildren[i];
1436
- if (nc.tag === SPLITTER) {
1437
- domUnmountFrames(frame, realNode);
1438
- realNode.innerHTML = nc.html;
1439
- return;
1440
- }
1441
1336
  const newNode = vdomCreateNode(nc, realNode, ref);
1442
- realNode.insertBefore(newNode, refNode);
1337
+ realNode.insertBefore(newNode, nextNode);
1338
+ nextNode = newNode;
1443
1339
  }
1444
1340
  }
1445
- if (oldStart <= oldEnd) {
1446
- for (let i = realEnd; i >= realStart; i--) {
1447
- const node = nodes[i];
1448
- if (node) {
1449
- domUnmountFrames(frame, node);
1450
- ref.changed = 1;
1451
- realNode.removeChild(node);
1452
- }
1341
+ for (let i = 0; i < oldLen; i++) {
1342
+ const domNode = oldDomNodes[i];
1343
+ if (domNode && !usedOldDomNodes.has(domNode) && domNode.parentNode === realNode) {
1344
+ domUnmountFrames(frame, domNode);
1345
+ ref.changed = 1;
1346
+ realNode.removeChild(domNode);
1453
1347
  }
1454
1348
  }
1455
1349
  if (ref.asyncCount === 0) {
1456
1350
  callFunction(ready, []);
1457
1351
  }
1458
1352
  }
1459
- function reduceCached(keyedNodes, node, compared) {
1460
- if (!keyedNodes || !node.compareKey) return;
1461
- const bucket = keyedNodes[node.compareKey];
1462
- if (bucket) {
1463
- for (let i = bucket.length; i--; ) {
1464
- if (bucket[i] === compared) {
1465
- bucket[i] = void 0;
1466
- break;
1467
- }
1468
- }
1469
- }
1470
- }
1471
1353
  function createVDomRef(viewId) {
1472
1354
  return {
1473
1355
  viewId,
@@ -1520,9 +1402,6 @@ var Updater = class {
1520
1402
  if (key) {
1521
1403
  result = this.data[key];
1522
1404
  }
1523
- if (typeof window !== "undefined" && window.__lark_Debug) {
1524
- return safeguard(result);
1525
- }
1526
1405
  return result;
1527
1406
  }
1528
1407
  /**
@@ -1610,9 +1489,6 @@ var Updater = class {
1610
1489
  view,
1611
1490
  ready
1612
1491
  );
1613
- if (ref.asyncCount === 0) {
1614
- ready();
1615
- }
1616
1492
  } else {
1617
1493
  const html = template(
1618
1494
  this.data,
@@ -1901,9 +1777,6 @@ var Router = {
1901
1777
  attachViewAndPath(location);
1902
1778
  hrefCache.set(href, location);
1903
1779
  }
1904
- if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug) {
1905
- location["params"] = safeguard(location["params"]);
1906
- }
1907
1780
  return location;
1908
1781
  },
1909
1782
  /**
@@ -1922,9 +1795,6 @@ var Router = {
1922
1795
  emitter.fire(RouterEvents.CHANGED, asRecord(lastChanged));
1923
1796
  }
1924
1797
  silent = 0;
1925
- if (typeof window.__lark_Debug !== "undefined" && window.__lark_Debug && lastChanged) {
1926
- lastChanged = safeguard(lastChanged);
1927
- }
1928
1798
  return lastChanged;
1929
1799
  },
1930
1800
  /**
@@ -2109,6 +1979,60 @@ var Router = {
2109
1979
  }
2110
1980
  };
2111
1981
 
1982
+ // src/view-registry.ts
1983
+ var viewClassRegistry = {};
1984
+ function getViewClass(path) {
1985
+ return viewClassRegistry[path];
1986
+ }
1987
+ function registerViewClass(viewPath, ViewClass) {
1988
+ const parsed = parseUri(viewPath);
1989
+ const path = parsed.path;
1990
+ if (path) {
1991
+ viewClassRegistry[path] = ViewClass;
1992
+ }
1993
+ }
1994
+ function invalidateViewClass(viewPath) {
1995
+ const parsed = parseUri(viewPath);
1996
+ const path = parsed.path;
1997
+ if (path) {
1998
+ Reflect.deleteProperty(viewClassRegistry, path);
1999
+ }
2000
+ }
2001
+
2002
+ // src/hmr.ts
2003
+ function reloadViews(viewPath) {
2004
+ const allFrames = Frame.getAll();
2005
+ const toReload = [];
2006
+ for (const [, frame] of allFrames) {
2007
+ if (frame.viewPath) {
2008
+ const parsed = parseUri(frame.viewPath);
2009
+ if (parsed.path === viewPath) {
2010
+ toReload.push({ frame, fullPath: frame.viewPath });
2011
+ }
2012
+ }
2013
+ }
2014
+ for (const { frame, fullPath } of toReload) {
2015
+ frame.mountView(fullPath);
2016
+ }
2017
+ }
2018
+ function acceptView(hot, viewPath) {
2019
+ hot.accept((newModule) => {
2020
+ const candidate = newModule?.default ?? newModule;
2021
+ if (typeof candidate === "function") {
2022
+ const NewViewClass = candidate;
2023
+ registerViewClass(viewPath, NewViewClass);
2024
+ reloadViews(viewPath);
2025
+ } else {
2026
+ hot.invalidate();
2027
+ }
2028
+ });
2029
+ }
2030
+ function disposeView(hot, viewPath) {
2031
+ hot.dispose(() => {
2032
+ invalidateViewClass(viewPath);
2033
+ });
2034
+ }
2035
+
2112
2036
  // src/view.ts
2113
2037
  var VIEW_GLOBALS = {};
2114
2038
  if (typeof window !== "undefined") {
@@ -2699,20 +2623,47 @@ var View = class _View {
2699
2623
  _View.mergeMixins(mixins, this, existingCtors);
2700
2624
  return this;
2701
2625
  }
2702
- };
2703
-
2704
- // src/view-registry.ts
2705
- var viewClassRegistry = {};
2706
- function getViewClass(path) {
2707
- return viewClassRegistry[path];
2708
- }
2709
- function registerViewClass(viewPath, ViewClass) {
2710
- const parsed = parseUri(viewPath);
2711
- const path = parsed.path;
2712
- if (path) {
2713
- viewClassRegistry[path] = ViewClass;
2626
+ // ============================================================
2627
+ // HMR support (static accept / dispose)
2628
+ // ============================================================
2629
+ /**
2630
+ * Set up HMR accept handler for this view module.
2631
+ *
2632
+ * When the module is hot-replaced, the new View class is extracted from
2633
+ * the new module, registered in the view registry, and all currently
2634
+ * mounted frames using this viewPath are re-mounted.
2635
+ *
2636
+ * No-op when `hot` is undefined (production / non-HMR environment).
2637
+ *
2638
+ * ```ts
2639
+ * if (import.meta.hot) {
2640
+ * HomeView.accept(import.meta.hot, 'home');
2641
+ * }
2642
+ * ```
2643
+ */
2644
+ static accept(hot, viewPath) {
2645
+ if (!hot) return;
2646
+ acceptView(hot, viewPath);
2714
2647
  }
2715
- }
2648
+ /**
2649
+ * Set up HMR dispose handler for this view module.
2650
+ *
2651
+ * When the module is about to be replaced, the old View class is removed
2652
+ * from the registry so subsequent lookups don't return the stale class.
2653
+ *
2654
+ * No-op when `hot` is undefined (production / non-HMR environment).
2655
+ *
2656
+ * ```ts
2657
+ * if (import.meta.hot) {
2658
+ * HomeView.dispose(import.meta.hot, 'home');
2659
+ * }
2660
+ * ```
2661
+ */
2662
+ static dispose(hot, viewPath) {
2663
+ if (!hot) return;
2664
+ disposeView(hot, viewPath);
2665
+ }
2666
+ };
2716
2667
 
2717
2668
  // src/frame.ts
2718
2669
  var frameRegistry = /* @__PURE__ */ new Map();