@lightspeed-js/core 0.4.7 → 0.4.9
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/compile.js +22 -3
- package/dist/index.js +53 -7
- package/dist/ssg.js +53 -7
- package/dist/types/src/runtime/bindings/BindingEvaluator.d.ts +6 -1
- package/dist/types/src/runtime/core.d.ts +6 -0
- package/dist/types/src/runtime/dom/ForBlock.d.ts +11 -0
- package/dist/types/test/branch-in-row-adoption.test.d.ts +1 -0
- package/dist/types/test/branch-switch.test.d.ts +1 -0
- package/dist/types/test/host-mount.test.d.ts +1 -0
- package/dist/types/test/nested-rows-in-branch.test.d.ts +1 -0
- package/dist/vite.js +53 -7
- package/package.json +1 -1
package/dist/compile.js
CHANGED
|
@@ -913,9 +913,9 @@ class BindingEvaluator {
|
|
|
913
913
|
compileExpression(expr, params = []) {
|
|
914
914
|
return this.compile(expr, params);
|
|
915
915
|
}
|
|
916
|
-
evaluate(expr, instance, locals = []) {
|
|
916
|
+
evaluate(expr, instance, locals = [], params = []) {
|
|
917
917
|
try {
|
|
918
|
-
return this.compile(expr,
|
|
918
|
+
return this.compile(expr, params)(instance.state, instance.props, this.cells.createReadProxy(), this.pendingProbe(), ...locals);
|
|
919
919
|
} catch (error) {
|
|
920
920
|
warn(`Error evaluating "${expr}" in ${instance.id}:`, error);
|
|
921
921
|
return;
|
|
@@ -1359,6 +1359,13 @@ class ForBlock {
|
|
|
1359
1359
|
async reconcile(items) {
|
|
1360
1360
|
const keys = this.keysFor(items);
|
|
1361
1361
|
const next = new Map;
|
|
1362
|
+
const keep = new Set(keys);
|
|
1363
|
+
this.rows.forEach((row, key) => {
|
|
1364
|
+
if (!keep.has(key)) {
|
|
1365
|
+
this.rows.delete(key);
|
|
1366
|
+
this.renderer.destroyRow(this, row);
|
|
1367
|
+
}
|
|
1368
|
+
});
|
|
1362
1369
|
for (let i = 0;i < items.length; i++) {
|
|
1363
1370
|
const key = keys[i];
|
|
1364
1371
|
const existing = this.rows.get(key);
|
|
@@ -1374,7 +1381,6 @@ class ForBlock {
|
|
|
1374
1381
|
next.set(key, row);
|
|
1375
1382
|
}
|
|
1376
1383
|
}
|
|
1377
|
-
this.rows.forEach((row) => this.renderer.destroyRow(this, row));
|
|
1378
1384
|
this.rows = next;
|
|
1379
1385
|
this.order = keys;
|
|
1380
1386
|
this.position();
|
|
@@ -1388,17 +1394,30 @@ class ForBlock {
|
|
|
1388
1394
|
const row = this.rows.get(this.order[i]);
|
|
1389
1395
|
if (!row)
|
|
1390
1396
|
continue;
|
|
1397
|
+
const nestedByAnchor = row.topLevelBlocks();
|
|
1391
1398
|
for (let j = row.nodes.length - 1;j >= 0; j--) {
|
|
1392
1399
|
const node = row.nodes[j];
|
|
1393
1400
|
if (node.nextSibling !== reference || node.parentNode !== parent) {
|
|
1394
1401
|
parent.insertBefore(node, reference);
|
|
1395
1402
|
}
|
|
1396
1403
|
reference = node;
|
|
1404
|
+
const nested = nestedByAnchor.get(node);
|
|
1405
|
+
if (nested)
|
|
1406
|
+
reference = nested.place();
|
|
1397
1407
|
}
|
|
1398
1408
|
}
|
|
1399
1409
|
if (parent.isConnected)
|
|
1400
1410
|
this.renderer.connected?.();
|
|
1401
1411
|
}
|
|
1412
|
+
place() {
|
|
1413
|
+
this.position();
|
|
1414
|
+
for (const key of this.order) {
|
|
1415
|
+
const row = this.rows.get(key);
|
|
1416
|
+
if (row?.nodes.length)
|
|
1417
|
+
return row.nodes[0];
|
|
1418
|
+
}
|
|
1419
|
+
return this.anchor;
|
|
1420
|
+
}
|
|
1402
1421
|
destroy() {
|
|
1403
1422
|
this.pendingItems = null;
|
|
1404
1423
|
this.rows.forEach((row) => this.renderer.destroyRow(this, row));
|
package/dist/index.js
CHANGED
|
@@ -485,9 +485,9 @@ class BindingEvaluator {
|
|
|
485
485
|
compileExpression(expr, params = []) {
|
|
486
486
|
return this.compile(expr, params);
|
|
487
487
|
}
|
|
488
|
-
evaluate(expr, instance, locals = []) {
|
|
488
|
+
evaluate(expr, instance, locals = [], params = []) {
|
|
489
489
|
try {
|
|
490
|
-
return this.compile(expr,
|
|
490
|
+
return this.compile(expr, params)(instance.state, instance.props, this.cells.createReadProxy(), this.pendingProbe(), ...locals);
|
|
491
491
|
} catch (error) {
|
|
492
492
|
warn(`Error evaluating "${expr}" in ${instance.id}:`, error);
|
|
493
493
|
return;
|
|
@@ -1103,6 +1103,22 @@ class Row {
|
|
|
1103
1103
|
set item(value) {
|
|
1104
1104
|
this.locals[this.locals.length - 1] = value;
|
|
1105
1105
|
}
|
|
1106
|
+
topLevelBlocks() {
|
|
1107
|
+
const byAnchor = new Map;
|
|
1108
|
+
for (const block of this.blocks) {
|
|
1109
|
+
if (this.nodes.includes(block.anchor))
|
|
1110
|
+
byAnchor.set(block.anchor, block);
|
|
1111
|
+
}
|
|
1112
|
+
return byAnchor;
|
|
1113
|
+
}
|
|
1114
|
+
disownNestedRows() {
|
|
1115
|
+
const owned = new Set;
|
|
1116
|
+
for (const block of this.topLevelBlocks().values()) {
|
|
1117
|
+
block.rows.forEach((row) => row.nodes.forEach((node) => owned.add(node)));
|
|
1118
|
+
}
|
|
1119
|
+
if (owned.size)
|
|
1120
|
+
this.nodes = this.nodes.filter((node) => !owned.has(node));
|
|
1121
|
+
}
|
|
1106
1122
|
}
|
|
1107
1123
|
var TAG_NAME = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
1108
1124
|
var REFUSED_TAGS = new Set([
|
|
@@ -1266,6 +1282,13 @@ class ForBlock {
|
|
|
1266
1282
|
async reconcile(items) {
|
|
1267
1283
|
const keys = this.keysFor(items);
|
|
1268
1284
|
const next = new Map;
|
|
1285
|
+
const keep = new Set(keys);
|
|
1286
|
+
this.rows.forEach((row, key) => {
|
|
1287
|
+
if (!keep.has(key)) {
|
|
1288
|
+
this.rows.delete(key);
|
|
1289
|
+
this.renderer.destroyRow(this, row);
|
|
1290
|
+
}
|
|
1291
|
+
});
|
|
1269
1292
|
for (let i = 0;i < items.length; i++) {
|
|
1270
1293
|
const key = keys[i];
|
|
1271
1294
|
const existing = this.rows.get(key);
|
|
@@ -1281,7 +1304,6 @@ class ForBlock {
|
|
|
1281
1304
|
next.set(key, row);
|
|
1282
1305
|
}
|
|
1283
1306
|
}
|
|
1284
|
-
this.rows.forEach((row) => this.renderer.destroyRow(this, row));
|
|
1285
1307
|
this.rows = next;
|
|
1286
1308
|
this.order = keys;
|
|
1287
1309
|
this.position();
|
|
@@ -1295,17 +1317,30 @@ class ForBlock {
|
|
|
1295
1317
|
const row = this.rows.get(this.order[i]);
|
|
1296
1318
|
if (!row)
|
|
1297
1319
|
continue;
|
|
1320
|
+
const nestedByAnchor = row.topLevelBlocks();
|
|
1298
1321
|
for (let j = row.nodes.length - 1;j >= 0; j--) {
|
|
1299
1322
|
const node = row.nodes[j];
|
|
1300
1323
|
if (node.nextSibling !== reference || node.parentNode !== parent) {
|
|
1301
1324
|
parent.insertBefore(node, reference);
|
|
1302
1325
|
}
|
|
1303
1326
|
reference = node;
|
|
1327
|
+
const nested = nestedByAnchor.get(node);
|
|
1328
|
+
if (nested)
|
|
1329
|
+
reference = nested.place();
|
|
1304
1330
|
}
|
|
1305
1331
|
}
|
|
1306
1332
|
if (parent.isConnected)
|
|
1307
1333
|
this.renderer.connected?.();
|
|
1308
1334
|
}
|
|
1335
|
+
place() {
|
|
1336
|
+
this.position();
|
|
1337
|
+
for (const key of this.order) {
|
|
1338
|
+
const row = this.rows.get(key);
|
|
1339
|
+
if (row?.nodes.length)
|
|
1340
|
+
return row.nodes[0];
|
|
1341
|
+
}
|
|
1342
|
+
return this.anchor;
|
|
1343
|
+
}
|
|
1309
1344
|
destroy() {
|
|
1310
1345
|
this.pendingItems = null;
|
|
1311
1346
|
this.rows.forEach((row) => this.renderer.destroyRow(this, row));
|
|
@@ -1569,7 +1604,8 @@ class Mounter {
|
|
|
1569
1604
|
outlet.replaceWith(holder);
|
|
1570
1605
|
}
|
|
1571
1606
|
for (const [name, nodes] of byName) {
|
|
1572
|
-
|
|
1607
|
+
const dropped = nodes.filter((node) => node.nodeType === 1 || node.nodeType === 3 && (node.textContent ?? "").trim() !== "");
|
|
1608
|
+
if (!dropped.length)
|
|
1573
1609
|
continue;
|
|
1574
1610
|
warn(name ? `No <slot name="${name}"> to receive this content - it was dropped.` : "Content passed to a component with no unnamed <slot> - it was dropped.");
|
|
1575
1611
|
}
|
|
@@ -1920,7 +1956,7 @@ class Mounter {
|
|
|
1920
1956
|
return block;
|
|
1921
1957
|
}
|
|
1922
1958
|
adoptRows(block, slices, context) {
|
|
1923
|
-
const value = this.bindings.evaluate(block.itemsExpr, context.owner, context.locals);
|
|
1959
|
+
const value = this.bindings.evaluate(block.itemsExpr, context.owner, context.locals, block.params);
|
|
1924
1960
|
const items = block.toItems(value);
|
|
1925
1961
|
if (items.length !== slices.length)
|
|
1926
1962
|
return false;
|
|
@@ -1943,6 +1979,7 @@ class Mounter {
|
|
|
1943
1979
|
if (!this.adoptNodes(templateNodes, content, rowContext, markers)) {
|
|
1944
1980
|
return false;
|
|
1945
1981
|
}
|
|
1982
|
+
row.disownNestedRows();
|
|
1946
1983
|
for (const marker of markers) {
|
|
1947
1984
|
this.mountMarker(marker, block.owner, rowContext).then((child) => {
|
|
1948
1985
|
if (child)
|
|
@@ -2006,6 +2043,7 @@ class Mounter {
|
|
|
2006
2043
|
row.instances.forEach((child) => this.bindings.updateTree(child));
|
|
2007
2044
|
await Promise.all(row.blocks.map((nested) => nested.settled()));
|
|
2008
2045
|
row.nodes = Array.from(fragment.childNodes);
|
|
2046
|
+
row.disownNestedRows();
|
|
2009
2047
|
return row;
|
|
2010
2048
|
}
|
|
2011
2049
|
connected() {
|
|
@@ -2941,6 +2979,9 @@ class LightspeedRuntime {
|
|
|
2941
2979
|
seedState(values) {
|
|
2942
2980
|
this.cells.seed(values);
|
|
2943
2981
|
}
|
|
2982
|
+
get signals() {
|
|
2983
|
+
return createSignalAPI(this.globalSignals);
|
|
2984
|
+
}
|
|
2944
2985
|
shared(key, init, options) {
|
|
2945
2986
|
const cell = this.cells.get(key, init, options);
|
|
2946
2987
|
return {
|
|
@@ -2992,11 +3033,16 @@ class LightspeedRuntime {
|
|
|
2992
3033
|
}
|
|
2993
3034
|
async mount(componentId, target, props = {}, slotHtml) {
|
|
2994
3035
|
const container = this.resolveTarget(target);
|
|
2995
|
-
if (!container)
|
|
3036
|
+
if (!container) {
|
|
3037
|
+
warn(`mount(${componentId}): no element matches ${String(target)}`);
|
|
2996
3038
|
return null;
|
|
3039
|
+
}
|
|
3040
|
+
componentId = componentId.toLowerCase();
|
|
2997
3041
|
const instance = await this.mounter.mountRoot(componentId, container, props, this.parseSlotHtml(slotHtml));
|
|
2998
|
-
if (!instance)
|
|
3042
|
+
if (!instance) {
|
|
3043
|
+
warn(`mount(${componentId}): no component with that id is registered. Known: ${[...new Set([...this.componentRegistry.getAllIds(), ...this.loaders.keys()])].join(", ") || "(none)"}`);
|
|
2999
3044
|
return null;
|
|
3045
|
+
}
|
|
3000
3046
|
const handle = {
|
|
3001
3047
|
id: `root#${++this.rootCounter}`,
|
|
3002
3048
|
componentId,
|
package/dist/ssg.js
CHANGED
|
@@ -504,9 +504,9 @@ class BindingEvaluator {
|
|
|
504
504
|
compileExpression(expr, params = []) {
|
|
505
505
|
return this.compile(expr, params);
|
|
506
506
|
}
|
|
507
|
-
evaluate(expr, instance, locals = []) {
|
|
507
|
+
evaluate(expr, instance, locals = [], params = []) {
|
|
508
508
|
try {
|
|
509
|
-
return this.compile(expr,
|
|
509
|
+
return this.compile(expr, params)(instance.state, instance.props, this.cells.createReadProxy(), this.pendingProbe(), ...locals);
|
|
510
510
|
} catch (error) {
|
|
511
511
|
warn(`Error evaluating "${expr}" in ${instance.id}:`, error);
|
|
512
512
|
return;
|
|
@@ -1122,6 +1122,22 @@ class Row {
|
|
|
1122
1122
|
set item(value) {
|
|
1123
1123
|
this.locals[this.locals.length - 1] = value;
|
|
1124
1124
|
}
|
|
1125
|
+
topLevelBlocks() {
|
|
1126
|
+
const byAnchor = new Map;
|
|
1127
|
+
for (const block of this.blocks) {
|
|
1128
|
+
if (this.nodes.includes(block.anchor))
|
|
1129
|
+
byAnchor.set(block.anchor, block);
|
|
1130
|
+
}
|
|
1131
|
+
return byAnchor;
|
|
1132
|
+
}
|
|
1133
|
+
disownNestedRows() {
|
|
1134
|
+
const owned = new Set;
|
|
1135
|
+
for (const block of this.topLevelBlocks().values()) {
|
|
1136
|
+
block.rows.forEach((row) => row.nodes.forEach((node) => owned.add(node)));
|
|
1137
|
+
}
|
|
1138
|
+
if (owned.size)
|
|
1139
|
+
this.nodes = this.nodes.filter((node) => !owned.has(node));
|
|
1140
|
+
}
|
|
1125
1141
|
}
|
|
1126
1142
|
var TAG_NAME = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
1127
1143
|
var REFUSED_TAGS = new Set([
|
|
@@ -1285,6 +1301,13 @@ class ForBlock {
|
|
|
1285
1301
|
async reconcile(items) {
|
|
1286
1302
|
const keys = this.keysFor(items);
|
|
1287
1303
|
const next = new Map;
|
|
1304
|
+
const keep = new Set(keys);
|
|
1305
|
+
this.rows.forEach((row, key) => {
|
|
1306
|
+
if (!keep.has(key)) {
|
|
1307
|
+
this.rows.delete(key);
|
|
1308
|
+
this.renderer.destroyRow(this, row);
|
|
1309
|
+
}
|
|
1310
|
+
});
|
|
1288
1311
|
for (let i = 0;i < items.length; i++) {
|
|
1289
1312
|
const key = keys[i];
|
|
1290
1313
|
const existing = this.rows.get(key);
|
|
@@ -1300,7 +1323,6 @@ class ForBlock {
|
|
|
1300
1323
|
next.set(key, row);
|
|
1301
1324
|
}
|
|
1302
1325
|
}
|
|
1303
|
-
this.rows.forEach((row) => this.renderer.destroyRow(this, row));
|
|
1304
1326
|
this.rows = next;
|
|
1305
1327
|
this.order = keys;
|
|
1306
1328
|
this.position();
|
|
@@ -1314,17 +1336,30 @@ class ForBlock {
|
|
|
1314
1336
|
const row = this.rows.get(this.order[i]);
|
|
1315
1337
|
if (!row)
|
|
1316
1338
|
continue;
|
|
1339
|
+
const nestedByAnchor = row.topLevelBlocks();
|
|
1317
1340
|
for (let j = row.nodes.length - 1;j >= 0; j--) {
|
|
1318
1341
|
const node = row.nodes[j];
|
|
1319
1342
|
if (node.nextSibling !== reference || node.parentNode !== parent) {
|
|
1320
1343
|
parent.insertBefore(node, reference);
|
|
1321
1344
|
}
|
|
1322
1345
|
reference = node;
|
|
1346
|
+
const nested = nestedByAnchor.get(node);
|
|
1347
|
+
if (nested)
|
|
1348
|
+
reference = nested.place();
|
|
1323
1349
|
}
|
|
1324
1350
|
}
|
|
1325
1351
|
if (parent.isConnected)
|
|
1326
1352
|
this.renderer.connected?.();
|
|
1327
1353
|
}
|
|
1354
|
+
place() {
|
|
1355
|
+
this.position();
|
|
1356
|
+
for (const key of this.order) {
|
|
1357
|
+
const row = this.rows.get(key);
|
|
1358
|
+
if (row?.nodes.length)
|
|
1359
|
+
return row.nodes[0];
|
|
1360
|
+
}
|
|
1361
|
+
return this.anchor;
|
|
1362
|
+
}
|
|
1328
1363
|
destroy() {
|
|
1329
1364
|
this.pendingItems = null;
|
|
1330
1365
|
this.rows.forEach((row) => this.renderer.destroyRow(this, row));
|
|
@@ -1592,7 +1627,8 @@ class Mounter {
|
|
|
1592
1627
|
outlet.replaceWith(holder);
|
|
1593
1628
|
}
|
|
1594
1629
|
for (const [name, nodes] of byName) {
|
|
1595
|
-
|
|
1630
|
+
const dropped = nodes.filter((node) => node.nodeType === 1 || node.nodeType === 3 && (node.textContent ?? "").trim() !== "");
|
|
1631
|
+
if (!dropped.length)
|
|
1596
1632
|
continue;
|
|
1597
1633
|
warn(name ? `No <slot name="${name}"> to receive this content - it was dropped.` : "Content passed to a component with no unnamed <slot> - it was dropped.");
|
|
1598
1634
|
}
|
|
@@ -1943,7 +1979,7 @@ class Mounter {
|
|
|
1943
1979
|
return block;
|
|
1944
1980
|
}
|
|
1945
1981
|
adoptRows(block, slices, context) {
|
|
1946
|
-
const value = this.bindings.evaluate(block.itemsExpr, context.owner, context.locals);
|
|
1982
|
+
const value = this.bindings.evaluate(block.itemsExpr, context.owner, context.locals, block.params);
|
|
1947
1983
|
const items = block.toItems(value);
|
|
1948
1984
|
if (items.length !== slices.length)
|
|
1949
1985
|
return false;
|
|
@@ -1966,6 +2002,7 @@ class Mounter {
|
|
|
1966
2002
|
if (!this.adoptNodes(templateNodes, content, rowContext, markers)) {
|
|
1967
2003
|
return false;
|
|
1968
2004
|
}
|
|
2005
|
+
row.disownNestedRows();
|
|
1969
2006
|
for (const marker of markers) {
|
|
1970
2007
|
this.mountMarker(marker, block.owner, rowContext).then((child) => {
|
|
1971
2008
|
if (child)
|
|
@@ -2029,6 +2066,7 @@ class Mounter {
|
|
|
2029
2066
|
row.instances.forEach((child) => this.bindings.updateTree(child));
|
|
2030
2067
|
await Promise.all(row.blocks.map((nested) => nested.settled()));
|
|
2031
2068
|
row.nodes = Array.from(fragment.childNodes);
|
|
2069
|
+
row.disownNestedRows();
|
|
2032
2070
|
return row;
|
|
2033
2071
|
}
|
|
2034
2072
|
connected() {
|
|
@@ -3049,6 +3087,9 @@ class LightspeedRuntime {
|
|
|
3049
3087
|
seedState(values) {
|
|
3050
3088
|
this.cells.seed(values);
|
|
3051
3089
|
}
|
|
3090
|
+
get signals() {
|
|
3091
|
+
return createSignalAPI(this.globalSignals);
|
|
3092
|
+
}
|
|
3052
3093
|
shared(key, init, options) {
|
|
3053
3094
|
const cell = this.cells.get(key, init, options);
|
|
3054
3095
|
return {
|
|
@@ -3100,11 +3141,16 @@ class LightspeedRuntime {
|
|
|
3100
3141
|
}
|
|
3101
3142
|
async mount(componentId, target, props = {}, slotHtml) {
|
|
3102
3143
|
const container = this.resolveTarget(target);
|
|
3103
|
-
if (!container)
|
|
3144
|
+
if (!container) {
|
|
3145
|
+
warn(`mount(${componentId}): no element matches ${String(target)}`);
|
|
3104
3146
|
return null;
|
|
3147
|
+
}
|
|
3148
|
+
componentId = componentId.toLowerCase();
|
|
3105
3149
|
const instance = await this.mounter.mountRoot(componentId, container, props, this.parseSlotHtml(slotHtml));
|
|
3106
|
-
if (!instance)
|
|
3150
|
+
if (!instance) {
|
|
3151
|
+
warn(`mount(${componentId}): no component with that id is registered. Known: ${[...new Set([...this.componentRegistry.getAllIds(), ...this.loaders.keys()])].join(", ") || "(none)"}`);
|
|
3107
3152
|
return null;
|
|
3153
|
+
}
|
|
3108
3154
|
const handle = {
|
|
3109
3155
|
id: `root#${++this.rootCounter}`,
|
|
3110
3156
|
componentId,
|
|
@@ -133,7 +133,12 @@ export declare class BindingEvaluator {
|
|
|
133
133
|
get cellManager(): CellManager;
|
|
134
134
|
/** Compile a standalone expression, e.g. a `$key`. */
|
|
135
135
|
compileExpression(expr: string, params?: string[]): Compiled;
|
|
136
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Evaluate once, outside a binding. `params` names the loop aliases `locals`
|
|
138
|
+
* holds: the compiled table is keyed by scope, so a block inside a `$for`
|
|
139
|
+
* row has to be looked up with the row's alias in scope, or it misses.
|
|
140
|
+
*/
|
|
141
|
+
evaluate(expr: string, instance: ComponentInstance, locals?: any[], params?: string[]): any;
|
|
137
142
|
applyBinding(binding: Binding, scope: BindingScope): void;
|
|
138
143
|
/** Re-evaluate everything owned by this instance, including its blocks. */
|
|
139
144
|
updateInstance(instance: ComponentInstance): void;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type SignalAPI } from "./signals/index.js";
|
|
1
2
|
import { ComponentInstance, type ComponentDefinition } from "./components/index.js";
|
|
2
3
|
import type { MarkerRange } from "./dom/Mounter.js";
|
|
3
4
|
/**
|
|
@@ -185,6 +186,11 @@ export declare class LightspeedRuntime {
|
|
|
185
186
|
* Unscoped, so a subscription here lives until its returned unsubscribe is
|
|
186
187
|
* called. Component logic gets the instance-bound facade instead.
|
|
187
188
|
*/
|
|
189
|
+
/**
|
|
190
|
+
* The page-wide signals, for code outside any component: a host app
|
|
191
|
+
* listening for what its islands emit, or emitting to them.
|
|
192
|
+
*/
|
|
193
|
+
get signals(): SignalAPI;
|
|
188
194
|
shared(key: string, init?: any, options?: any): {
|
|
189
195
|
key: string;
|
|
190
196
|
value: any;
|
|
@@ -30,6 +30,15 @@ export declare class Row implements BindingHolder {
|
|
|
30
30
|
addBlock(block: ForBlock): void;
|
|
31
31
|
get item(): any;
|
|
32
32
|
set item(value: any);
|
|
33
|
+
/** Nested blocks whose anchor sits among this row's own nodes, by anchor. */
|
|
34
|
+
topLevelBlocks(): Map<Node, ForBlock>;
|
|
35
|
+
/**
|
|
36
|
+
* Drop the nodes that belong to rows of a nested block at this row's top
|
|
37
|
+
* level - a `$for` in a `<template>` branch, say. That block adds and
|
|
38
|
+
* removes its rows on its own; if this row still listed them, positioning
|
|
39
|
+
* this row would put a removed row back before the nested anchor.
|
|
40
|
+
*/
|
|
41
|
+
disownNestedRows(): void;
|
|
33
42
|
}
|
|
34
43
|
export interface RowRenderer {
|
|
35
44
|
createRow(block: ForBlock, item: any): Promise<Row>;
|
|
@@ -140,5 +149,7 @@ export declare class ForBlock {
|
|
|
140
149
|
* moves are proportionate for the list sizes this targets.
|
|
141
150
|
*/
|
|
142
151
|
private position;
|
|
152
|
+
/** Put the rows in place and say where the block now starts. */
|
|
153
|
+
place(): Node;
|
|
143
154
|
destroy(): void;
|
|
144
155
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/vite.js
CHANGED
|
@@ -243,9 +243,9 @@ class BindingEvaluator {
|
|
|
243
243
|
compileExpression(expr, params = []) {
|
|
244
244
|
return this.compile(expr, params);
|
|
245
245
|
}
|
|
246
|
-
evaluate(expr, instance, locals = []) {
|
|
246
|
+
evaluate(expr, instance, locals = [], params = []) {
|
|
247
247
|
try {
|
|
248
|
-
return this.compile(expr,
|
|
248
|
+
return this.compile(expr, params)(instance.state, instance.props, this.cells.createReadProxy(), this.pendingProbe(), ...locals);
|
|
249
249
|
} catch (error) {
|
|
250
250
|
warn(`Error evaluating "${expr}" in ${instance.id}:`, error);
|
|
251
251
|
return;
|
|
@@ -553,6 +553,22 @@ class Row {
|
|
|
553
553
|
set item(value) {
|
|
554
554
|
this.locals[this.locals.length - 1] = value;
|
|
555
555
|
}
|
|
556
|
+
topLevelBlocks() {
|
|
557
|
+
const byAnchor = new Map;
|
|
558
|
+
for (const block of this.blocks) {
|
|
559
|
+
if (this.nodes.includes(block.anchor))
|
|
560
|
+
byAnchor.set(block.anchor, block);
|
|
561
|
+
}
|
|
562
|
+
return byAnchor;
|
|
563
|
+
}
|
|
564
|
+
disownNestedRows() {
|
|
565
|
+
const owned = new Set;
|
|
566
|
+
for (const block of this.topLevelBlocks().values()) {
|
|
567
|
+
block.rows.forEach((row) => row.nodes.forEach((node) => owned.add(node)));
|
|
568
|
+
}
|
|
569
|
+
if (owned.size)
|
|
570
|
+
this.nodes = this.nodes.filter((node) => !owned.has(node));
|
|
571
|
+
}
|
|
556
572
|
}
|
|
557
573
|
var TAG_NAME = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
558
574
|
var REFUSED_TAGS = new Set([
|
|
@@ -716,6 +732,13 @@ class ForBlock {
|
|
|
716
732
|
async reconcile(items) {
|
|
717
733
|
const keys = this.keysFor(items);
|
|
718
734
|
const next = new Map;
|
|
735
|
+
const keep = new Set(keys);
|
|
736
|
+
this.rows.forEach((row, key) => {
|
|
737
|
+
if (!keep.has(key)) {
|
|
738
|
+
this.rows.delete(key);
|
|
739
|
+
this.renderer.destroyRow(this, row);
|
|
740
|
+
}
|
|
741
|
+
});
|
|
719
742
|
for (let i = 0;i < items.length; i++) {
|
|
720
743
|
const key = keys[i];
|
|
721
744
|
const existing = this.rows.get(key);
|
|
@@ -731,7 +754,6 @@ class ForBlock {
|
|
|
731
754
|
next.set(key, row);
|
|
732
755
|
}
|
|
733
756
|
}
|
|
734
|
-
this.rows.forEach((row) => this.renderer.destroyRow(this, row));
|
|
735
757
|
this.rows = next;
|
|
736
758
|
this.order = keys;
|
|
737
759
|
this.position();
|
|
@@ -745,17 +767,30 @@ class ForBlock {
|
|
|
745
767
|
const row = this.rows.get(this.order[i]);
|
|
746
768
|
if (!row)
|
|
747
769
|
continue;
|
|
770
|
+
const nestedByAnchor = row.topLevelBlocks();
|
|
748
771
|
for (let j = row.nodes.length - 1;j >= 0; j--) {
|
|
749
772
|
const node = row.nodes[j];
|
|
750
773
|
if (node.nextSibling !== reference || node.parentNode !== parent) {
|
|
751
774
|
parent.insertBefore(node, reference);
|
|
752
775
|
}
|
|
753
776
|
reference = node;
|
|
777
|
+
const nested = nestedByAnchor.get(node);
|
|
778
|
+
if (nested)
|
|
779
|
+
reference = nested.place();
|
|
754
780
|
}
|
|
755
781
|
}
|
|
756
782
|
if (parent.isConnected)
|
|
757
783
|
this.renderer.connected?.();
|
|
758
784
|
}
|
|
785
|
+
place() {
|
|
786
|
+
this.position();
|
|
787
|
+
for (const key of this.order) {
|
|
788
|
+
const row = this.rows.get(key);
|
|
789
|
+
if (row?.nodes.length)
|
|
790
|
+
return row.nodes[0];
|
|
791
|
+
}
|
|
792
|
+
return this.anchor;
|
|
793
|
+
}
|
|
759
794
|
destroy() {
|
|
760
795
|
this.pendingItems = null;
|
|
761
796
|
this.rows.forEach((row) => this.renderer.destroyRow(this, row));
|
|
@@ -1023,7 +1058,8 @@ class Mounter {
|
|
|
1023
1058
|
outlet.replaceWith(holder);
|
|
1024
1059
|
}
|
|
1025
1060
|
for (const [name, nodes] of byName) {
|
|
1026
|
-
|
|
1061
|
+
const dropped = nodes.filter((node) => node.nodeType === 1 || node.nodeType === 3 && (node.textContent ?? "").trim() !== "");
|
|
1062
|
+
if (!dropped.length)
|
|
1027
1063
|
continue;
|
|
1028
1064
|
warn(name ? `No <slot name="${name}"> to receive this content - it was dropped.` : "Content passed to a component with no unnamed <slot> - it was dropped.");
|
|
1029
1065
|
}
|
|
@@ -1374,7 +1410,7 @@ class Mounter {
|
|
|
1374
1410
|
return block;
|
|
1375
1411
|
}
|
|
1376
1412
|
adoptRows(block, slices, context) {
|
|
1377
|
-
const value = this.bindings.evaluate(block.itemsExpr, context.owner, context.locals);
|
|
1413
|
+
const value = this.bindings.evaluate(block.itemsExpr, context.owner, context.locals, block.params);
|
|
1378
1414
|
const items = block.toItems(value);
|
|
1379
1415
|
if (items.length !== slices.length)
|
|
1380
1416
|
return false;
|
|
@@ -1397,6 +1433,7 @@ class Mounter {
|
|
|
1397
1433
|
if (!this.adoptNodes(templateNodes, content, rowContext, markers)) {
|
|
1398
1434
|
return false;
|
|
1399
1435
|
}
|
|
1436
|
+
row.disownNestedRows();
|
|
1400
1437
|
for (const marker of markers) {
|
|
1401
1438
|
this.mountMarker(marker, block.owner, rowContext).then((child) => {
|
|
1402
1439
|
if (child)
|
|
@@ -1460,6 +1497,7 @@ class Mounter {
|
|
|
1460
1497
|
row.instances.forEach((child) => this.bindings.updateTree(child));
|
|
1461
1498
|
await Promise.all(row.blocks.map((nested) => nested.settled()));
|
|
1462
1499
|
row.nodes = Array.from(fragment.childNodes);
|
|
1500
|
+
row.disownNestedRows();
|
|
1463
1501
|
return row;
|
|
1464
1502
|
}
|
|
1465
1503
|
connected() {
|
|
@@ -4440,6 +4478,9 @@ class LightspeedRuntime {
|
|
|
4440
4478
|
seedState(values) {
|
|
4441
4479
|
this.cells.seed(values);
|
|
4442
4480
|
}
|
|
4481
|
+
get signals() {
|
|
4482
|
+
return createSignalAPI(this.globalSignals);
|
|
4483
|
+
}
|
|
4443
4484
|
shared(key, init, options) {
|
|
4444
4485
|
const cell = this.cells.get(key, init, options);
|
|
4445
4486
|
return {
|
|
@@ -4491,11 +4532,16 @@ class LightspeedRuntime {
|
|
|
4491
4532
|
}
|
|
4492
4533
|
async mount(componentId, target, props = {}, slotHtml) {
|
|
4493
4534
|
const container = this.resolveTarget(target);
|
|
4494
|
-
if (!container)
|
|
4535
|
+
if (!container) {
|
|
4536
|
+
warn(`mount(${componentId}): no element matches ${String(target)}`);
|
|
4495
4537
|
return null;
|
|
4538
|
+
}
|
|
4539
|
+
componentId = componentId.toLowerCase();
|
|
4496
4540
|
const instance = await this.mounter.mountRoot(componentId, container, props, this.parseSlotHtml(slotHtml));
|
|
4497
|
-
if (!instance)
|
|
4541
|
+
if (!instance) {
|
|
4542
|
+
warn(`mount(${componentId}): no component with that id is registered. Known: ${[...new Set([...this.componentRegistry.getAllIds(), ...this.loaders.keys()])].join(", ") || "(none)"}`);
|
|
4498
4543
|
return null;
|
|
4544
|
+
}
|
|
4499
4545
|
const handle = {
|
|
4500
4546
|
id: `root#${++this.rootCounter}`,
|
|
4501
4547
|
componentId,
|