@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 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, [])(instance.state, instance.props, this.cells.createReadProxy(), this.pendingProbe(), ...locals);
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, [])(instance.state, instance.props, this.cells.createReadProxy(), this.pendingProbe(), ...locals);
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
- if (!nodes.length)
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, [])(instance.state, instance.props, this.cells.createReadProxy(), this.pendingProbe(), ...locals);
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
- if (!nodes.length)
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
- evaluate(expr: string, instance: ComponentInstance, locals?: any[]): any;
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, [])(instance.state, instance.props, this.cells.createReadProxy(), this.pendingProbe(), ...locals);
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
- if (!nodes.length)
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightspeed-js/core",
3
- "version": "0.4.7",
3
+ "version": "0.4.9",
4
4
  "description": "Lightspeed: a compile-first framework for islands of reactivity in static HTML.",
5
5
  "keywords": [
6
6
  "lightspeed",