streetui 1.0.0 → 1.3.0

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/server.js CHANGED
@@ -131,6 +131,7 @@ function patchProp(dom, element, name, oldValue, newValue) {
131
131
 
132
132
  // ../renderer/src/events.ts
133
133
  function wireEvents(dom, graph, node, element, instance) {
134
+ if (node.events.length === 0) return;
134
135
  for (const eventDesc of node.events) {
135
136
  const handler = graph.getHandler(eventDesc.handlerKey);
136
137
  if (handler === void 0) continue;
@@ -260,6 +261,109 @@ function reconcileChildren(ctx, parentDom, oldInstances, newNodes, mountFn) {
260
261
  reorderDom(ctx, parentDom, newInstances);
261
262
  return { instances: newInstances, removed };
262
263
  }
264
+ function reconcileChildrenByPlan(ctx, parentDom, oldInstances, plan, mountFn) {
265
+ const oldByKey = /* @__PURE__ */ new Map();
266
+ for (const inst of oldInstances) {
267
+ oldByKey.set(inst.graphNode.key ?? inst.graphNode.id, inst);
268
+ }
269
+ const newInstances = [];
270
+ const usedKeys = /* @__PURE__ */ new Set();
271
+ const built = [];
272
+ for (const entry of plan) {
273
+ const existing = oldByKey.get(entry.key);
274
+ if (existing !== void 0) {
275
+ usedKeys.add(entry.key);
276
+ const oldItem = existing.graphNode.getProp("_item");
277
+ if (!Object.is(oldItem, entry.item)) {
278
+ const newSig = entry.sig();
279
+ const oldSig = existing.graphNode.getProp("_sig");
280
+ if (!Object.is(oldSig, newSig)) {
281
+ const freshNode = entry.build();
282
+ built.push(freshNode);
283
+ patchExistingInstance(ctx, existing, freshNode);
284
+ reconcileItemChildren(ctx, existing, freshNode, mountFn);
285
+ existing.graphNode.setProp("_sig", newSig);
286
+ }
287
+ existing.graphNode.setProp("_item", entry.item);
288
+ }
289
+ newInstances.push(existing);
290
+ } else {
291
+ const freshNode = entry.build();
292
+ built.push(freshNode);
293
+ const inst = mountFn(freshNode, parentDom);
294
+ newInstances.push(inst);
295
+ }
296
+ }
297
+ const removed = [];
298
+ for (const inst of oldInstances) {
299
+ const key = inst.graphNode.key ?? inst.graphNode.id;
300
+ if (!usedKeys.has(key)) removed.push(inst);
301
+ }
302
+ for (const inst of removed) {
303
+ const parent = ctx.dom.parentNode(inst.domNode);
304
+ if (parent !== null) ctx.dom.removeChild(parent, inst.domNode);
305
+ inst.dispose();
306
+ }
307
+ reorderDomMinimal(ctx, parentDom, oldInstances, newInstances);
308
+ return { instances: newInstances, removed, built };
309
+ }
310
+ function reorderDomMinimal(ctx, parentDom, oldInstances, newInstances) {
311
+ const n = newInstances.length;
312
+ if (n === 0) return;
313
+ const oldIndexOf = /* @__PURE__ */ new Map();
314
+ for (let i = 0; i < oldInstances.length; i++) oldIndexOf.set(oldInstances[i], i);
315
+ const source = new Array(n);
316
+ let moved = false;
317
+ let lastSeen = -1;
318
+ for (let i = 0; i < n; i++) {
319
+ const oi = oldIndexOf.get(newInstances[i]);
320
+ if (oi === void 0) {
321
+ source[i] = -1;
322
+ moved = true;
323
+ } else {
324
+ source[i] = oi;
325
+ if (oi < lastSeen) moved = true;
326
+ else lastSeen = oi;
327
+ }
328
+ }
329
+ if (!moved) return;
330
+ const keep = longestIncreasingSubsequence(source);
331
+ let refNode = null;
332
+ for (let i = n - 1; i >= 0; i--) {
333
+ const domNode = newInstances[i].domNode;
334
+ if (source[i] === -1 || !keep.has(i)) {
335
+ if (ctx.dom.nextSibling(domNode) !== refNode) {
336
+ ctx.dom.insertBefore(parentDom, domNode, refNode);
337
+ }
338
+ }
339
+ refNode = domNode;
340
+ }
341
+ }
342
+ function longestIncreasingSubsequence(source) {
343
+ const keep = /* @__PURE__ */ new Set();
344
+ const n = source.length;
345
+ const tails = [];
346
+ const prev = new Array(n).fill(-1);
347
+ for (let i = 0; i < n; i++) {
348
+ const v = source[i];
349
+ if (v < 0) continue;
350
+ let lo = 0;
351
+ let hi = tails.length;
352
+ while (lo < hi) {
353
+ const mid = lo + hi >> 1;
354
+ if (source[tails[mid]] < v) lo = mid + 1;
355
+ else hi = mid;
356
+ }
357
+ if (lo > 0) prev[i] = tails[lo - 1];
358
+ tails[lo] = i;
359
+ }
360
+ let idx = tails.length > 0 ? tails[tails.length - 1] : -1;
361
+ while (idx >= 0) {
362
+ keep.add(idx);
363
+ idx = prev[idx];
364
+ }
365
+ return keep;
366
+ }
263
367
  function reconcileItemChildren(ctx, itemInstance, newItemNode, mountFn) {
264
368
  const el = itemInstance.domNode;
265
369
  if (!ctx.dom.isElement(el)) return;
@@ -361,10 +465,12 @@ function mountNode(ctx, graphNode, parentDom) {
361
465
  const textNode = dom.createTextNode(text);
362
466
  dom.appendChild(el2, textNode);
363
467
  applyNodeProps(ctx, graphNode, el2);
364
- wireEvents(dom, graph, graphNode, el2, new NodeInstance(graphNode, el2));
365
468
  const instance2 = new NodeInstance(graphNode, el2);
366
469
  ctx.instances.set(graphNode.id, instance2);
367
- wireSignalBindings(ctx, graphNode, instance2, textUpdate(dom, el2, textNode));
470
+ wireEvents(dom, graph, graphNode, el2, instance2);
471
+ if (graphNode.stateRefs.length !== 0) {
472
+ wireSignalBindings(ctx, graphNode, instance2, textUpdate(dom, el2, textNode));
473
+ }
368
474
  dom.appendChild(parentDom, el2);
369
475
  return instance2;
370
476
  }
@@ -378,7 +484,9 @@ function mountNode(ctx, graphNode, parentDom) {
378
484
  const instance2 = new NodeInstance(graphNode, el2);
379
485
  ctx.instances.set(graphNode.id, instance2);
380
486
  wireEvents(dom, graph, graphNode, el2, instance2);
381
- wireSignalBindings(ctx, graphNode, instance2, headingUpdate(dom, el2));
487
+ if (graphNode.stateRefs.length !== 0) {
488
+ wireSignalBindings(ctx, graphNode, instance2, headingUpdate(dom, el2));
489
+ }
382
490
  dom.appendChild(parentDom, el2);
383
491
  return instance2;
384
492
  }
@@ -394,7 +502,9 @@ function mountNode(ctx, graphNode, parentDom) {
394
502
  const instance2 = new NodeInstance(graphNode, el2);
395
503
  ctx.instances.set(graphNode.id, instance2);
396
504
  wireEvents(dom, graph, graphNode, el2, instance2);
397
- wireSignalBindings(ctx, graphNode, instance2, inputUpdate(dom, el2));
505
+ if (graphNode.stateRefs.length !== 0) {
506
+ wireSignalBindings(ctx, graphNode, instance2, inputUpdate(dom, el2));
507
+ }
398
508
  dom.appendChild(parentDom, el2);
399
509
  return instance2;
400
510
  }
@@ -442,7 +552,9 @@ function mountNode(ctx, graphNode, parentDom) {
442
552
  const instance2 = new NodeInstance(graphNode, el2);
443
553
  ctx.instances.set(graphNode.id, instance2);
444
554
  wireEvents(dom, graph, graphNode, el2, instance2);
445
- wireSignalBindings(ctx, graphNode, instance2, buttonUpdate(dom, el2));
555
+ if (graphNode.stateRefs.length !== 0) {
556
+ wireSignalBindings(ctx, graphNode, instance2, buttonUpdate(dom, el2));
557
+ }
446
558
  dom.appendChild(parentDom, el2);
447
559
  return instance2;
448
560
  }
@@ -469,11 +581,11 @@ function mountNode(ctx, graphNode, parentDom) {
469
581
  dom.setAttribute(el, "data-streetui-key", String(itemKey));
470
582
  }
471
583
  }
472
- if (graphNode.type === "form") {
473
- wireEvents(dom, graph, graphNode, el, new NodeInstance(graphNode, el));
474
- }
475
584
  const instance = new NodeInstance(graphNode, el);
476
585
  ctx.instances.set(graphNode.id, instance);
586
+ if (graphNode.type === "form") {
587
+ wireEvents(dom, graph, graphNode, el, instance);
588
+ }
477
589
  for (const child of graphNode.children) {
478
590
  const childInstance = mountNode(ctx, child, el);
479
591
  instance.addChild(childInstance);
@@ -524,12 +636,15 @@ function buttonUpdate(dom, el) {
524
636
  };
525
637
  }
526
638
  function applyNodeProps(ctx, graphNode, el) {
527
- for (const [key, value] of Object.entries(graphNode.props)) {
639
+ const props = graphNode.props;
640
+ for (const key in props) {
641
+ if (!Object.hasOwn(props, key)) continue;
528
642
  if (SKIP_PROP_KEYS.has(key)) continue;
529
- applyProp(ctx.dom, el, key, value);
643
+ applyProp(ctx.dom, el, key, props[key]);
530
644
  }
531
645
  }
532
646
  function wireSignalBindings(ctx, graphNode, instance, onUpdate) {
647
+ if (graphNode.stateRefs.length === 0) return;
533
648
  for (const stateRef of graphNode.stateRefs) {
534
649
  const signalKey = `__signal__${stateRef.signalId}`;
535
650
  const maybeSig = ctx.graph.getHandler(signalKey);
@@ -541,18 +656,45 @@ function wireSignalBindings(ctx, graphNode, instance, onUpdate) {
541
656
  }
542
657
  }
543
658
  function wireReactiveList(ctx, graphNode, instance, el) {
659
+ const plan = ctx.graph.getHandler(`__listplan__${graphNode.id}`);
544
660
  const build = ctx.graph.getHandler(`__listbuild__${graphNode.id}`);
545
- if (build === void 0) return;
661
+ if (plan === void 0 && build === void 0) return;
546
662
  for (const stateRef of graphNode.stateRefs) {
547
663
  if (stateRef.propKey !== "items") continue;
548
664
  const sig = ctx.graph.getHandler(`__signal__${stateRef.signalId}`);
549
665
  if (sig === void 0 || typeof sig.subscribe !== "function") continue;
550
666
  const unsub = sig.subscribe((value) => {
551
- reconcileReactiveList(ctx, graphNode, instance, el, build(value));
667
+ if (plan !== void 0) {
668
+ reconcileReactiveListByPlan(ctx, graphNode, instance, el, plan(value));
669
+ } else {
670
+ reconcileReactiveList(ctx, graphNode, instance, el, build(value));
671
+ }
552
672
  });
553
673
  instance.trackCleanup(unsub);
554
674
  }
555
675
  }
676
+ function reconcileReactiveListByPlan(ctx, listNode, listInstance, listEl, plan) {
677
+ const oldInstances = [...listInstance.children];
678
+ const result = reconcileChildrenByPlan(
679
+ ctx,
680
+ listEl,
681
+ oldInstances,
682
+ plan,
683
+ (node, parent) => mountNode(ctx, node, parent)
684
+ );
685
+ listInstance.children.length = 0;
686
+ for (const inst of result.instances) listInstance.children.push(inst);
687
+ for (const removed of result.removed) {
688
+ forgetInstance(ctx, removed);
689
+ ctx.graph.detachNode(removed.graphNode);
690
+ }
691
+ const adopted = new Set(result.instances.map((i) => i.graphNode));
692
+ for (const node of result.built ?? []) {
693
+ if (!adopted.has(node)) ctx.graph.detachNode(node);
694
+ }
695
+ for (const child of [...listNode.children]) listNode.removeChild(child);
696
+ for (const inst of result.instances) listNode.appendChild(inst.graphNode);
697
+ }
556
698
  function reconcileReactiveList(ctx, listNode, listInstance, listEl, newNodes) {
557
699
  const oldInstances = [...listInstance.children];
558
700
  const result = reconcileChildren(
@@ -928,7 +1070,7 @@ function renderToString(compiled, options = {}) {
928
1070
  }
929
1071
 
930
1072
  // src/version.ts
931
- var VERSION = "1.0.0";
1073
+ var VERSION = "1.3.0";
932
1074
  export {
933
1075
  STATE_MARKER_ATTR,
934
1076
  ServerDOMAdapter,