@constela/runtime 0.15.0 → 0.15.2

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.
Files changed (2) hide show
  1. package/dist/index.js +88 -39
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -240,18 +240,18 @@ function createStateStore(definitions) {
240
240
  initialValue = cookieValue !== void 0 ? cookieValue : def.initial.default;
241
241
  } else {
242
242
  initialValue = def.initial;
243
- }
244
- if (name === "theme" && typeof window !== "undefined") {
245
- try {
246
- const stored = localStorage.getItem("theme");
247
- if (stored !== null) {
248
- try {
249
- initialValue = JSON.parse(stored);
250
- } catch {
251
- initialValue = stored;
243
+ if (name === "theme" && typeof window !== "undefined") {
244
+ try {
245
+ const stored = localStorage.getItem("theme");
246
+ if (stored !== null) {
247
+ try {
248
+ initialValue = JSON.parse(stored);
249
+ } catch {
250
+ initialValue = stored;
251
+ }
252
252
  }
253
+ } catch {
253
254
  }
254
- } catch {
255
255
  }
256
256
  }
257
257
  signals.set(name, createSignal(initialValue));
@@ -273,7 +273,8 @@ function createStateStore(definitions) {
273
273
  try {
274
274
  const valueStr = typeof value === "string" ? value : JSON.stringify(value);
275
275
  const oneYear = 365 * 24 * 60 * 60;
276
- document.cookie = `theme=${encodeURIComponent(valueStr)}; path=/; max-age=${oneYear}; SameSite=Lax`;
276
+ const secure = typeof location !== "undefined" && location.protocol === "https:" ? "; Secure" : "";
277
+ document.cookie = `theme=${encodeURIComponent(valueStr)}; path=/; max-age=${oneYear}; SameSite=Lax${secure}`;
277
278
  } catch {
278
279
  }
279
280
  }
@@ -4665,8 +4666,8 @@ var Rule = class {
4665
4666
  this._contentNameIsCapturing = RegexSource.hasCaptures(this._contentName);
4666
4667
  }
4667
4668
  get debugName() {
4668
- const location = this.$location ? `${basename(this.$location.filename)}:${this.$location.line}` : "unknown";
4669
- return `${this.constructor.name}#${this.id} @ ${location}`;
4669
+ const location2 = this.$location ? `${basename(this.$location.filename)}:${this.$location.line}` : "unknown";
4670
+ return `${this.constructor.name}#${this.id} @ ${location2}`;
4670
4671
  }
4671
4672
  getName(lineText, captureIndices) {
4672
4673
  if (!this._nameIsCapturing || this._name === null || lineText === null || captureIndices === null) {
@@ -14392,6 +14393,21 @@ function hydrateElement(node, el, ctx) {
14392
14393
  hydrateChildren(node.children, el, ctx);
14393
14394
  }
14394
14395
  }
14396
+ function findSsrIfBranchMarker(parent, beforeNode) {
14397
+ let current = beforeNode ? beforeNode.previousSibling : parent.lastChild;
14398
+ while (current) {
14399
+ if (current.nodeType === Node.COMMENT_NODE) {
14400
+ const comment2 = current;
14401
+ const text3 = comment2.textContent;
14402
+ if (text3 === "if:then") return { branch: "then", marker: comment2 };
14403
+ if (text3 === "if:else") return { branch: "else", marker: comment2 };
14404
+ if (text3 === "if:none") return { branch: "none", marker: comment2 };
14405
+ }
14406
+ if (current.nodeType === Node.ELEMENT_NODE) break;
14407
+ current = current.previousSibling;
14408
+ }
14409
+ return null;
14410
+ }
14395
14411
  function hydrateChildren(children, parent, ctx) {
14396
14412
  const domChildren = [];
14397
14413
  for (let i = 0; i < parent.childNodes.length; i++) {
@@ -14422,19 +14438,35 @@ function hydrateChildren(children, parent, ctx) {
14422
14438
  }
14423
14439
  } else if (childNode.kind === "if") {
14424
14440
  const ifNode = childNode;
14425
- const initialCondition = evaluate(ifNode.condition, {
14441
+ const clientCondition = evaluate(ifNode.condition, {
14426
14442
  state: ctx.state,
14427
14443
  locals: ctx.locals,
14428
14444
  ...ctx.imports && { imports: ctx.imports },
14429
14445
  ...ctx.route && { route: ctx.route }
14430
14446
  });
14431
- const hasDomForIf = Boolean(initialCondition) || Boolean(ifNode.else);
14447
+ const clientBranch = Boolean(clientCondition) ? "then" : ifNode.else ? "else" : "none";
14432
14448
  const domChild = domChildren[domIndex];
14433
- if (hasDomForIf && domChild) {
14434
- hydrate(childNode, domChild, ctx);
14449
+ const ssrInfo = findSsrIfBranchMarker(parent, domChild || null);
14450
+ const ssrBranch = ssrInfo?.branch ?? null;
14451
+ const ssrHasDom = ssrBranch === "then" || ssrBranch === "else";
14452
+ if (ssrInfo?.marker) {
14453
+ ssrInfo.marker.remove();
14454
+ }
14455
+ if (ssrHasDom && domChild) {
14456
+ hydrateIf(ifNode, domChild, ctx, { ssrBranch, clientBranch });
14435
14457
  domIndex++;
14458
+ } else if (ssrBranch === "none") {
14459
+ hydrateIfWithoutDom(ifNode, parent, domChildren[domIndex] || null, ctx, {
14460
+ clientBranch
14461
+ });
14436
14462
  } else {
14437
- hydrateIfWithoutDom(ifNode, parent, domChildren[domIndex] || null, ctx);
14463
+ const hasDomForIf = Boolean(clientCondition) || Boolean(ifNode.else);
14464
+ if (hasDomForIf && domChild) {
14465
+ hydrate(childNode, domChild, ctx);
14466
+ domIndex++;
14467
+ } else {
14468
+ hydrateIfWithoutDom(ifNode, parent, domChildren[domIndex] || null, ctx);
14469
+ }
14438
14470
  }
14439
14471
  } else if (childNode.kind === "each") {
14440
14472
  const items = evaluate(childNode.items, {
@@ -14524,32 +14556,37 @@ function formatValue2(value) {
14524
14556
  }
14525
14557
  return String(value);
14526
14558
  }
14527
- function hydrateIf(node, initialDomNode, ctx) {
14559
+ function hydrateIf(node, initialDomNode, ctx, branchInfo) {
14528
14560
  const anchor = document.createComment("if");
14529
14561
  const parent = initialDomNode.parentNode;
14530
14562
  if (!parent) return;
14531
14563
  parent.insertBefore(anchor, initialDomNode);
14532
14564
  let currentNode = initialDomNode;
14533
- let currentBranch = "none";
14534
14565
  let branchCleanups = [];
14535
14566
  let isFirstRun = true;
14536
- const initialCondition = evaluate(node.condition, {
14537
- state: ctx.state,
14538
- locals: ctx.locals,
14539
- ...ctx.imports && { imports: ctx.imports },
14540
- ...ctx.route && { route: ctx.route }
14541
- });
14542
- currentBranch = Boolean(initialCondition) ? "then" : node.else ? "else" : "none";
14543
- if (currentBranch === "then") {
14544
- const localCleanups = [];
14545
- const branchCtx = { ...ctx, cleanups: localCleanups };
14546
- hydrate(node.then, currentNode, branchCtx);
14547
- branchCleanups = localCleanups;
14548
- } else if (currentBranch === "else" && node.else) {
14549
- const localCleanups = [];
14550
- const branchCtx = { ...ctx, cleanups: localCleanups };
14551
- hydrate(node.else, currentNode, branchCtx);
14552
- branchCleanups = localCleanups;
14567
+ const hasMismatch = branchInfo && branchInfo.ssrBranch !== branchInfo.clientBranch;
14568
+ let currentBranch = branchInfo?.ssrBranch ?? "none";
14569
+ if (!branchInfo) {
14570
+ const initialCondition = evaluate(node.condition, {
14571
+ state: ctx.state,
14572
+ locals: ctx.locals,
14573
+ ...ctx.imports && { imports: ctx.imports },
14574
+ ...ctx.route && { route: ctx.route }
14575
+ });
14576
+ currentBranch = Boolean(initialCondition) ? "then" : node.else ? "else" : "none";
14577
+ }
14578
+ if (!hasMismatch) {
14579
+ if (currentBranch === "then") {
14580
+ const localCleanups = [];
14581
+ const branchCtx = { ...ctx, cleanups: localCleanups };
14582
+ hydrate(node.then, currentNode, branchCtx);
14583
+ branchCleanups = localCleanups;
14584
+ } else if (currentBranch === "else" && node.else) {
14585
+ const localCleanups = [];
14586
+ const branchCtx = { ...ctx, cleanups: localCleanups };
14587
+ hydrate(node.else, currentNode, branchCtx);
14588
+ branchCleanups = localCleanups;
14589
+ }
14553
14590
  }
14554
14591
  const effectCleanup = createEffect(() => {
14555
14592
  const condition = evaluate(node.condition, {
@@ -14562,7 +14599,10 @@ function hydrateIf(node, initialDomNode, ctx) {
14562
14599
  const newBranch = shouldShowThen ? "then" : node.else ? "else" : "none";
14563
14600
  if (isFirstRun) {
14564
14601
  isFirstRun = false;
14565
- return;
14602
+ if (hasMismatch) {
14603
+ } else {
14604
+ return;
14605
+ }
14566
14606
  }
14567
14607
  if (newBranch !== currentBranch) {
14568
14608
  for (const cleanup of branchCleanups) {
@@ -14602,7 +14642,7 @@ function hydrateIf(node, initialDomNode, ctx) {
14602
14642
  }
14603
14643
  });
14604
14644
  }
14605
- function hydrateIfWithoutDom(node, parent, nextSibling, ctx) {
14645
+ function hydrateIfWithoutDom(node, parent, nextSibling, ctx, branchInfo) {
14606
14646
  const anchor = document.createComment("if");
14607
14647
  if (nextSibling) {
14608
14648
  parent.insertBefore(anchor, nextSibling);
@@ -14612,6 +14652,8 @@ function hydrateIfWithoutDom(node, parent, nextSibling, ctx) {
14612
14652
  let currentNode = null;
14613
14653
  let currentBranch = "none";
14614
14654
  let branchCleanups = [];
14655
+ const needsImmediateRender = branchInfo && branchInfo.clientBranch !== "none";
14656
+ let isFirstRun = true;
14615
14657
  const effectCleanup = createEffect(() => {
14616
14658
  const condition = evaluate(node.condition, {
14617
14659
  state: ctx.state,
@@ -14621,6 +14663,13 @@ function hydrateIfWithoutDom(node, parent, nextSibling, ctx) {
14621
14663
  });
14622
14664
  const shouldShowThen = Boolean(condition);
14623
14665
  const newBranch = shouldShowThen ? "then" : node.else ? "else" : "none";
14666
+ if (isFirstRun) {
14667
+ isFirstRun = false;
14668
+ if (needsImmediateRender) {
14669
+ } else if (newBranch === "none") {
14670
+ return;
14671
+ }
14672
+ }
14624
14673
  if (newBranch !== currentBranch) {
14625
14674
  for (const cleanup of branchCleanups) {
14626
14675
  cleanup();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constela/runtime",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
4
4
  "description": "Runtime DOM renderer for Constela UI framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -29,7 +29,7 @@
29
29
  "tsup": "^8.0.0",
30
30
  "typescript": "^5.3.0",
31
31
  "vitest": "^2.0.0",
32
- "@constela/server": "8.0.0"
32
+ "@constela/server": "8.0.1"
33
33
  },
34
34
  "engines": {
35
35
  "node": ">=20.0.0"