@solidjs/web 2.0.0-beta.15 → 2.0.0-beta.16

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/dev.cjs CHANGED
@@ -60,9 +60,9 @@ const syncOptions = {
60
60
  sync: true
61
61
  };
62
62
  const effect = (fn, effectFn, options) => solidJs.createRenderEffect(fn, effectFn, options ? {
63
- transparent: true,
64
63
  sync: true,
65
- ...options
64
+ ...options,
65
+ transparent: !options.scope
66
66
  } : transparentOptions);
67
67
  const memo = fn => solidJs.createMemo(() => fn(), syncOptions);
68
68
 
@@ -335,20 +335,41 @@ function addEvent(node, name, handler, delegate) {
335
335
  }
336
336
  function style(node, value, prev) {
337
337
  if (!value) {
338
- if (prev) setAttribute(node, "style");
338
+ if (prev || node._$styles) {
339
+ setAttribute(node, "style");
340
+ node._$styles = undefined;
341
+ }
339
342
  return;
340
343
  }
341
344
  const nodeStyle = node.style;
342
- if (typeof value === "string") return nodeStyle.cssText = value;
343
- typeof prev === "string" && (nodeStyle.cssText = prev = undefined);
344
- prev || (prev = {});
345
+ if (typeof value === "string") {
346
+ node._$styles = undefined;
347
+ return nodeStyle.cssText = value;
348
+ }
349
+ if (typeof prev === "string") {
350
+ nodeStyle.cssText = "";
351
+ prev = undefined;
352
+ }
353
+ let applied = node._$styles;
354
+ if (!applied) {
355
+ applied = node._$styles = prev ? {
356
+ ...prev
357
+ } : {};
358
+ }
345
359
  let v, s;
360
+ for (s in applied) {
361
+ if (value[s] == null) {
362
+ nodeStyle.removeProperty(s);
363
+ delete applied[s];
364
+ }
365
+ }
346
366
  for (s in value) {
347
367
  v = value[s];
348
- if (v !== prev[s]) nodeStyle.setProperty(s, v);
349
- delete prev[s];
368
+ if (v != null && v !== applied[s]) {
369
+ nodeStyle.setProperty(s, v);
370
+ applied[s] = v;
371
+ }
350
372
  }
351
- for (s in prev) value[s] == null && nodeStyle.removeProperty(s);
352
373
  }
353
374
  function setStyleProperty(node, name, value) {
354
375
  value != null ? node.style.setProperty(name, value) : node.style.removeProperty(name);
@@ -387,19 +408,28 @@ function ref(fn, element) {
387
408
  const resolved = solidJs.untrack(fn);
388
409
  solidJs.runWithOwner(null, () => applyRef(resolved, element));
389
410
  }
411
+ function scope(fn) {
412
+ fn.$s = true;
413
+ return fn;
414
+ }
415
+ const SCOPE_OPTIONS = {
416
+ scope: true
417
+ };
418
+ function stripTextSeparators(nodes) {
419
+ let j = 0;
420
+ for (let i = 0; i < nodes.length; i++) {
421
+ if (nodes[i].nodeType === 8 && nodes[i].nodeValue === "!$") nodes[i].remove();else nodes[j++] = nodes[i];
422
+ }
423
+ nodes.length = j;
424
+ return nodes;
425
+ }
390
426
  function insert(parent, accessor, marker, initial, options) {
391
427
  const multi = marker !== undefined;
392
428
  const host = options && options.host;
393
429
  if (multi && !initial) initial = [];
394
430
  if (isHydrating(parent)) {
395
431
  if (!multi && initial === undefined && parent) initial = [...parent.childNodes];
396
- if (Array.isArray(initial)) {
397
- let j = 0;
398
- for (let i = 0; i < initial.length; i++) {
399
- if (initial[i].nodeType === 8 && initial[i].nodeValue === "!$") initial[i].remove();else initial[j++] = initial[i];
400
- }
401
- initial.length = j;
402
- }
432
+ if (Array.isArray(initial)) stripTextSeparators(initial);
403
433
  }
404
434
  if (typeof accessor !== "function") {
405
435
  accessor = normalize(accessor, initial, multi, true);
@@ -415,10 +445,34 @@ function insert(parent, accessor, marker, initial, options) {
415
445
  initial = [placeholder];
416
446
  }
417
447
  let current = initial;
448
+ function reclaimSwappedRegion() {
449
+ if (!solidJs.sharedConfig.hydrating || !current || !parent.isConnected) return;
450
+ const first = Array.isArray(current) ? current[0] : current;
451
+ if (!first || !first.nodeType || first.isConnected) return;
452
+ let nodes;
453
+ if (marker) {
454
+ nodes = [];
455
+ let node = marker.previousSibling,
456
+ depth = 0;
457
+ while (node) {
458
+ if (node.nodeType === 8) {
459
+ const v = node.nodeValue;
460
+ if (v === "/") depth++;else if (v === "$") {
461
+ if (depth === 0) break;
462
+ depth--;
463
+ }
464
+ }
465
+ nodes.unshift(node);
466
+ node = node.previousSibling;
467
+ }
468
+ } else nodes = [...parent.childNodes];
469
+ current = stripTextSeparators(nodes);
470
+ }
418
471
  effect(prev => {
472
+ reclaimSwappedRegion();
419
473
  const value = normalize(accessor(), current, multi, true);
420
474
  if (typeof value !== "function") return value;
421
- effect(() => normalize(value, current, multi), inner => {
475
+ effect(() => (reclaimSwappedRegion(), normalize(value, current, multi)), inner => {
422
476
  insertExpression(parent, inner, current, marker);
423
477
  current = inner;
424
478
  host && tagHost(current, host);
@@ -432,7 +486,11 @@ function insert(parent, accessor, marker, initial, options) {
432
486
  insertExpression(parent, value, current, marker);
433
487
  current = value;
434
488
  host && tagHost(current, host);
435
- }, options);
489
+ },
490
+ accessor.$s ? options ? {
491
+ ...options,
492
+ scope: true
493
+ } : SCOPE_OPTIONS : options);
436
494
  }
437
495
  function assign(node, props, skipChildren, prevProps = {}, skipRef = false) {
438
496
  const nodeName = node.nodeName;
@@ -461,6 +519,9 @@ function loadModuleAssets(mapping) {
461
519
  if (!hy.loading[moduleUrl]) {
462
520
  hy.loading[moduleUrl] = import(entryUrl).then(mod => {
463
521
  hy.modules[moduleUrl] = mod;
522
+ }, err => {
523
+ delete hy.loading[moduleUrl];
524
+ throw err;
464
525
  });
465
526
  }
466
527
  pending.push(hy.loading[moduleUrl]);
@@ -518,8 +579,11 @@ function hydrate$1(code, element, options = {}) {
518
579
  } finally {
519
580
  solidJs.sharedConfig.hydrating = false;
520
581
  }
521
- }, () => {
582
+ }, err => {
583
+ console.error("Hydration module preload failed, falling back to client render:", err);
522
584
  solidJs.sharedConfig.hydrating = false;
585
+ solidJs.sharedConfig.registry = undefined;
586
+ disposer = render$1(code, element, [...element.childNodes], options);
523
587
  });
524
588
  return () => disposer && disposer();
525
589
  }
@@ -631,17 +695,32 @@ function runHydrationEvents() {
631
695
  const [el, e] = events[0];
632
696
  if (!completed.has(el)) return;
633
697
  events.shift();
634
- let match;
698
+ let matchContainer, matchState, matchDistance, matches;
635
699
  for (const [container, state] of delegatedContainers) {
636
700
  if (!state.handlers.has(e.type)) continue;
637
701
  const entry = findOwner(e.target, state);
638
- if (entry && (!match || entry.distance < match.distance)) match = {
639
- container,
640
- state,
641
- distance: entry.distance
642
- };
702
+ if (!entry) continue;
703
+ if (matchContainer) {
704
+ if (!matches) matches = [{
705
+ container: matchContainer,
706
+ state: matchState,
707
+ distance: matchDistance
708
+ }];
709
+ matches.push({
710
+ container,
711
+ state,
712
+ distance: entry.distance
713
+ });
714
+ } else {
715
+ matchContainer = container;
716
+ matchState = state;
717
+ matchDistance = entry.distance;
718
+ }
643
719
  }
644
- if (match) eventHandler(e, match.container, match.state);
720
+ if (matches) {
721
+ matches.sort((a, b) => a.distance - b.distance);
722
+ for (let i = 0; i < matches.length; i++) eventHandler(e, matches[i].container, matches[i].state);
723
+ } else if (matchContainer) eventHandler(e, matchContainer, matchState);
645
724
  }
646
725
  if (solidJs.sharedConfig.done) {
647
726
  solidJs.sharedConfig.events = _$HY.events = null;
@@ -712,11 +791,16 @@ function eventHandler(e, container, state) {
712
791
  if (solidJs.sharedConfig.registry && solidJs.sharedConfig.events) {
713
792
  if (solidJs.sharedConfig.events.find(([el, ev]) => ev === e)) return;
714
793
  }
715
- if (e[$$EVENT_OWNER]) return;
794
+ const prev = e[$$EVENT_OWNER];
795
+ let resumeNode;
796
+ if (prev) {
797
+ if (prev === true || prev === container || !container.contains(prev)) return;
798
+ resumeNode = prev;
799
+ }
716
800
  const owner = state && (state.owners.size === 1 && state.owners.has(container) ? container : findOwner(e.target, state)?.owner);
717
801
  if (state && !owner) return;
718
802
  e[$$EVENT_OWNER] = owner || true;
719
- let node = e.target;
803
+ let node = resumeNode || e.target;
720
804
  const key = `$$${e.type}`;
721
805
  const oriTarget = e.target;
722
806
  const boundary = owner || container || e.currentTarget;
@@ -746,7 +830,10 @@ function eventHandler(e, container, state) {
746
830
  return node || boundary || document;
747
831
  }
748
832
  });
749
- if (e.composedPath) {
833
+ if (resumeNode) {
834
+ if (resumeNode === e.target) node = resumeNode._$host || resumeNode.parentNode || resumeNode.host;
835
+ if (node && node !== boundary) walkUpTree();
836
+ } else if (e.composedPath) {
750
837
  const path = e.composedPath();
751
838
  if (path.length) {
752
839
  retarget(path[0]);
@@ -931,9 +1018,10 @@ function Portal(props) {
931
1018
  return () => {
932
1019
  dispose();
933
1020
  let c = startMarker;
934
- while (c && c !== endMarker) {
1021
+ while (c) {
935
1022
  const n = c.nextSibling;
936
1023
  m.removeChild(c);
1024
+ if (c === endMarker) break;
937
1025
  c = n;
938
1026
  }
939
1027
  };
@@ -1080,6 +1168,7 @@ exports.renderToString = renderToString;
1080
1168
  exports.renderToStringAsync = renderToStringAsync;
1081
1169
  exports.resolveSSRNode = resolveSSRNode;
1082
1170
  exports.runHydrationEvents = runHydrationEvents;
1171
+ exports.scope = scope;
1083
1172
  exports.setAttribute = setAttribute;
1084
1173
  exports.setAttributeNS = setAttributeNS;
1085
1174
  exports.setProperty = setProperty;
package/dist/dev.js CHANGED
@@ -59,9 +59,9 @@ const syncOptions = {
59
59
  sync: true
60
60
  };
61
61
  const effect = (fn, effectFn, options) => createRenderEffect(fn, effectFn, options ? {
62
- transparent: true,
63
62
  sync: true,
64
- ...options
63
+ ...options,
64
+ transparent: !options.scope
65
65
  } : transparentOptions);
66
66
  const memo = fn => createMemo(() => fn(), syncOptions);
67
67
 
@@ -334,20 +334,41 @@ function addEvent(node, name, handler, delegate) {
334
334
  }
335
335
  function style(node, value, prev) {
336
336
  if (!value) {
337
- if (prev) setAttribute(node, "style");
337
+ if (prev || node._$styles) {
338
+ setAttribute(node, "style");
339
+ node._$styles = undefined;
340
+ }
338
341
  return;
339
342
  }
340
343
  const nodeStyle = node.style;
341
- if (typeof value === "string") return nodeStyle.cssText = value;
342
- typeof prev === "string" && (nodeStyle.cssText = prev = undefined);
343
- prev || (prev = {});
344
+ if (typeof value === "string") {
345
+ node._$styles = undefined;
346
+ return nodeStyle.cssText = value;
347
+ }
348
+ if (typeof prev === "string") {
349
+ nodeStyle.cssText = "";
350
+ prev = undefined;
351
+ }
352
+ let applied = node._$styles;
353
+ if (!applied) {
354
+ applied = node._$styles = prev ? {
355
+ ...prev
356
+ } : {};
357
+ }
344
358
  let v, s;
359
+ for (s in applied) {
360
+ if (value[s] == null) {
361
+ nodeStyle.removeProperty(s);
362
+ delete applied[s];
363
+ }
364
+ }
345
365
  for (s in value) {
346
366
  v = value[s];
347
- if (v !== prev[s]) nodeStyle.setProperty(s, v);
348
- delete prev[s];
367
+ if (v != null && v !== applied[s]) {
368
+ nodeStyle.setProperty(s, v);
369
+ applied[s] = v;
370
+ }
349
371
  }
350
- for (s in prev) value[s] == null && nodeStyle.removeProperty(s);
351
372
  }
352
373
  function setStyleProperty(node, name, value) {
353
374
  value != null ? node.style.setProperty(name, value) : node.style.removeProperty(name);
@@ -386,19 +407,28 @@ function ref(fn, element) {
386
407
  const resolved = untrack(fn);
387
408
  runWithOwner(null, () => applyRef(resolved, element));
388
409
  }
410
+ function scope(fn) {
411
+ fn.$s = true;
412
+ return fn;
413
+ }
414
+ const SCOPE_OPTIONS = {
415
+ scope: true
416
+ };
417
+ function stripTextSeparators(nodes) {
418
+ let j = 0;
419
+ for (let i = 0; i < nodes.length; i++) {
420
+ if (nodes[i].nodeType === 8 && nodes[i].nodeValue === "!$") nodes[i].remove();else nodes[j++] = nodes[i];
421
+ }
422
+ nodes.length = j;
423
+ return nodes;
424
+ }
389
425
  function insert(parent, accessor, marker, initial, options) {
390
426
  const multi = marker !== undefined;
391
427
  const host = options && options.host;
392
428
  if (multi && !initial) initial = [];
393
429
  if (isHydrating(parent)) {
394
430
  if (!multi && initial === undefined && parent) initial = [...parent.childNodes];
395
- if (Array.isArray(initial)) {
396
- let j = 0;
397
- for (let i = 0; i < initial.length; i++) {
398
- if (initial[i].nodeType === 8 && initial[i].nodeValue === "!$") initial[i].remove();else initial[j++] = initial[i];
399
- }
400
- initial.length = j;
401
- }
431
+ if (Array.isArray(initial)) stripTextSeparators(initial);
402
432
  }
403
433
  if (typeof accessor !== "function") {
404
434
  accessor = normalize(accessor, initial, multi, true);
@@ -414,10 +444,34 @@ function insert(parent, accessor, marker, initial, options) {
414
444
  initial = [placeholder];
415
445
  }
416
446
  let current = initial;
447
+ function reclaimSwappedRegion() {
448
+ if (!sharedConfig.hydrating || !current || !parent.isConnected) return;
449
+ const first = Array.isArray(current) ? current[0] : current;
450
+ if (!first || !first.nodeType || first.isConnected) return;
451
+ let nodes;
452
+ if (marker) {
453
+ nodes = [];
454
+ let node = marker.previousSibling,
455
+ depth = 0;
456
+ while (node) {
457
+ if (node.nodeType === 8) {
458
+ const v = node.nodeValue;
459
+ if (v === "/") depth++;else if (v === "$") {
460
+ if (depth === 0) break;
461
+ depth--;
462
+ }
463
+ }
464
+ nodes.unshift(node);
465
+ node = node.previousSibling;
466
+ }
467
+ } else nodes = [...parent.childNodes];
468
+ current = stripTextSeparators(nodes);
469
+ }
417
470
  effect(prev => {
471
+ reclaimSwappedRegion();
418
472
  const value = normalize(accessor(), current, multi, true);
419
473
  if (typeof value !== "function") return value;
420
- effect(() => normalize(value, current, multi), inner => {
474
+ effect(() => (reclaimSwappedRegion(), normalize(value, current, multi)), inner => {
421
475
  insertExpression(parent, inner, current, marker);
422
476
  current = inner;
423
477
  host && tagHost(current, host);
@@ -431,7 +485,11 @@ function insert(parent, accessor, marker, initial, options) {
431
485
  insertExpression(parent, value, current, marker);
432
486
  current = value;
433
487
  host && tagHost(current, host);
434
- }, options);
488
+ },
489
+ accessor.$s ? options ? {
490
+ ...options,
491
+ scope: true
492
+ } : SCOPE_OPTIONS : options);
435
493
  }
436
494
  function assign(node, props, skipChildren, prevProps = {}, skipRef = false) {
437
495
  const nodeName = node.nodeName;
@@ -460,6 +518,9 @@ function loadModuleAssets(mapping) {
460
518
  if (!hy.loading[moduleUrl]) {
461
519
  hy.loading[moduleUrl] = import(entryUrl).then(mod => {
462
520
  hy.modules[moduleUrl] = mod;
521
+ }, err => {
522
+ delete hy.loading[moduleUrl];
523
+ throw err;
463
524
  });
464
525
  }
465
526
  pending.push(hy.loading[moduleUrl]);
@@ -517,8 +578,11 @@ function hydrate$1(code, element, options = {}) {
517
578
  } finally {
518
579
  sharedConfig.hydrating = false;
519
580
  }
520
- }, () => {
581
+ }, err => {
582
+ console.error("Hydration module preload failed, falling back to client render:", err);
521
583
  sharedConfig.hydrating = false;
584
+ sharedConfig.registry = undefined;
585
+ disposer = render$1(code, element, [...element.childNodes], options);
522
586
  });
523
587
  return () => disposer && disposer();
524
588
  }
@@ -630,17 +694,32 @@ function runHydrationEvents() {
630
694
  const [el, e] = events[0];
631
695
  if (!completed.has(el)) return;
632
696
  events.shift();
633
- let match;
697
+ let matchContainer, matchState, matchDistance, matches;
634
698
  for (const [container, state] of delegatedContainers) {
635
699
  if (!state.handlers.has(e.type)) continue;
636
700
  const entry = findOwner(e.target, state);
637
- if (entry && (!match || entry.distance < match.distance)) match = {
638
- container,
639
- state,
640
- distance: entry.distance
641
- };
701
+ if (!entry) continue;
702
+ if (matchContainer) {
703
+ if (!matches) matches = [{
704
+ container: matchContainer,
705
+ state: matchState,
706
+ distance: matchDistance
707
+ }];
708
+ matches.push({
709
+ container,
710
+ state,
711
+ distance: entry.distance
712
+ });
713
+ } else {
714
+ matchContainer = container;
715
+ matchState = state;
716
+ matchDistance = entry.distance;
717
+ }
642
718
  }
643
- if (match) eventHandler(e, match.container, match.state);
719
+ if (matches) {
720
+ matches.sort((a, b) => a.distance - b.distance);
721
+ for (let i = 0; i < matches.length; i++) eventHandler(e, matches[i].container, matches[i].state);
722
+ } else if (matchContainer) eventHandler(e, matchContainer, matchState);
644
723
  }
645
724
  if (sharedConfig.done) {
646
725
  sharedConfig.events = _$HY.events = null;
@@ -711,11 +790,16 @@ function eventHandler(e, container, state) {
711
790
  if (sharedConfig.registry && sharedConfig.events) {
712
791
  if (sharedConfig.events.find(([el, ev]) => ev === e)) return;
713
792
  }
714
- if (e[$$EVENT_OWNER]) return;
793
+ const prev = e[$$EVENT_OWNER];
794
+ let resumeNode;
795
+ if (prev) {
796
+ if (prev === true || prev === container || !container.contains(prev)) return;
797
+ resumeNode = prev;
798
+ }
715
799
  const owner = state && (state.owners.size === 1 && state.owners.has(container) ? container : findOwner(e.target, state)?.owner);
716
800
  if (state && !owner) return;
717
801
  e[$$EVENT_OWNER] = owner || true;
718
- let node = e.target;
802
+ let node = resumeNode || e.target;
719
803
  const key = `$$${e.type}`;
720
804
  const oriTarget = e.target;
721
805
  const boundary = owner || container || e.currentTarget;
@@ -745,7 +829,10 @@ function eventHandler(e, container, state) {
745
829
  return node || boundary || document;
746
830
  }
747
831
  });
748
- if (e.composedPath) {
832
+ if (resumeNode) {
833
+ if (resumeNode === e.target) node = resumeNode._$host || resumeNode.parentNode || resumeNode.host;
834
+ if (node && node !== boundary) walkUpTree();
835
+ } else if (e.composedPath) {
749
836
  const path = e.composedPath();
750
837
  if (path.length) {
751
838
  retarget(path[0]);
@@ -930,9 +1017,10 @@ function Portal(props) {
930
1017
  return () => {
931
1018
  dispose();
932
1019
  let c = startMarker;
933
- while (c && c !== endMarker) {
1020
+ while (c) {
934
1021
  const n = c.nextSibling;
935
1022
  m.removeChild(c);
1023
+ if (c === endMarker) break;
936
1024
  c = n;
937
1025
  }
938
1026
  };
@@ -979,4 +1067,4 @@ function createElement(tagName, is = undefined) {
979
1067
  });
980
1068
  }
981
1069
 
982
- export { voidFn as Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, SVGElements, VoidElements, addEvent, applyRef, assign, className, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, voidFn as getAssets, getDelegatedRoot, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, hydrate, insert, isDev, isServer, memo, mergeProps, ref, registerDelegatedContainer, registerDelegatedRoot, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, runHydrationEvents, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrStyle, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, voidFn as useAssets };
1070
+ export { voidFn as Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, SVGElements, VoidElements, addEvent, applyRef, assign, className, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, voidFn as getAssets, getDelegatedRoot, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, hydrate, insert, isDev, isServer, memo, mergeProps, ref, registerDelegatedContainer, registerDelegatedRoot, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, runHydrationEvents, scope, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrStyle, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, voidFn as useAssets };