@zeus-js/runtime-dom 0.1.1-beta.1 → 0.1.1-beta.10

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * runtime-dom v0.1.1-beta.1
2
+ * runtime-dom v0.1.1-beta.10
3
3
  * (c) 2026 baicie
4
4
  * Released under the MIT License.
5
5
  **/
@@ -495,42 +495,41 @@ function bindStyle(el, value, once = false) {
495
495
  prev = void 0;
496
496
  return;
497
497
  }
498
- patchStyle(el, prev, next);
499
- prev = next;
498
+ prev = patchStyle(el, prev, next);
500
499
  });
501
500
  }
502
501
  function patchStyle(el, prev, next) {
503
502
  const style = el.style;
504
- if (prev) {
505
- for (const key in prev) if (!(key in next)) style.setProperty(toKebabCase$2(key), "");
503
+ const values = prev ? prev[0] : Object.create(null);
504
+ const state = style.cssText + Object.keys(next);
505
+ const styleChanged = prev && state != prev[1];
506
+ for (const key in values) if (!(key in next)) {
507
+ style.setProperty(key.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`), "");
508
+ delete values[key];
506
509
  }
507
510
  for (const key in next) {
508
511
  const value = next[key];
509
- const name = toKebabCase$2(key);
510
- if (value == null) style.setProperty(name, "");
511
- else style.setProperty(name, normalizeStyleValue(key, value));
512
+ const expected = value == null ? "" : normalizeStyleValue(key, value);
513
+ if (values[key] === expected && !styleChanged) continue;
514
+ style.setProperty(key.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`), expected);
515
+ values[key] = expected;
512
516
  }
517
+ return [values, style.cssText + Object.keys(next)];
513
518
  }
514
519
  function normalizeStyleValue(key, value) {
515
- if (typeof value === "number" && value !== 0 && !isUnitlessNumber(key)) return `${value}px`;
520
+ if (typeof value === "number" && value !== 0 && unitlessNumbers[key] !== true) return `${value}px`;
516
521
  return String(value);
517
522
  }
518
- const unitlessNumbers = /* @__PURE__ */ new Set([
519
- "opacity",
520
- "zIndex",
521
- "fontWeight",
522
- "lineHeight",
523
- "flex",
524
- "flexGrow",
525
- "flexShrink",
526
- "order"
527
- ]);
528
- function isUnitlessNumber(key) {
529
- return unitlessNumbers.has(key);
530
- }
531
- function toKebabCase$2(value) {
532
- return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
533
- }
523
+ const unitlessNumbers = {
524
+ opacity: true,
525
+ zIndex: true,
526
+ fontWeight: true,
527
+ lineHeight: true,
528
+ flex: true,
529
+ flexGrow: true,
530
+ flexShrink: true,
531
+ order: true
532
+ };
534
533
  //#endregion
535
534
  //#region packages/core/runtime-dom/src/events.ts
536
535
  const delegatedEvents = /* @__PURE__ */ new Set();
@@ -733,7 +732,9 @@ function mountIndexFor(parent, marker, each, render) {
733
732
  function mountKeyedFor(parent, marker, each, key, render) {
734
733
  let records = [];
735
734
  const subtreeContext = captureScopedSubtreeContext();
736
- let latestEntries = [];
735
+ let latestItems = [];
736
+ const latestKeys = [];
737
+ let latestItemsUseFixedSlots = false;
737
738
  let reconcileRequested = false;
738
739
  let reconciling = false;
739
740
  let disposed = false;
@@ -747,7 +748,7 @@ function mountKeyedFor(parent, marker, each, key, render) {
747
748
  for (const record of currentRecords) disposeListRecord(record);
748
749
  };
749
750
  (0, _zeus_js_signal_internal.onScopeDispose)(dispose, true);
750
- const reconcile = (nextEntries) => {
751
+ const reconcileEntries = (nextEntries) => {
751
752
  if (disposed) return;
752
753
  const oldMap = /* @__PURE__ */ new Map();
753
754
  for (const record of records) oldMap.set(record.key, record);
@@ -760,7 +761,10 @@ function mountKeyedFor(parent, marker, each, key, render) {
760
761
  const oldRecord = oldMap.get(itemKey);
761
762
  if (oldRecord) {
762
763
  oldMap.delete(itemKey);
763
- oldRecord.setItem(() => item);
764
+ if (!Object.is(oldRecord.item, item)) {
765
+ oldRecord.item = item;
766
+ oldRecord.setItem(() => item);
767
+ }
764
768
  oldRecord.setIndex(i);
765
769
  nextRecords.push(oldRecord);
766
770
  } else {
@@ -768,6 +772,7 @@ function mountKeyedFor(parent, marker, each, key, render) {
768
772
  const [readIndex, setIndex] = (0, _zeus_js_signal_internal.createSignal)(i);
769
773
  const subtree = new ScopedSubtree(parent, marker, subtreeContext);
770
774
  const record = {
775
+ item,
771
776
  key: itemKey,
772
777
  setItem,
773
778
  setIndex,
@@ -824,13 +829,48 @@ function mountKeyedFor(parent, marker, each, key, render) {
824
829
  throw error;
825
830
  }
826
831
  };
832
+ const reconcileLatestItems = () => {
833
+ if (disposed) return;
834
+ if (latestItemsUseFixedSlots) {
835
+ const items = latestItems;
836
+ (0, _zeus_js_signal_internal.batch)(() => {
837
+ for (let i = 0; i < items.length; i++) {
838
+ const item = items[i];
839
+ const record = records[i];
840
+ if (!Object.is(record.item, item)) {
841
+ record.item = item;
842
+ record.setItem(() => item);
843
+ }
844
+ }
845
+ });
846
+ if (!disposed) emitDevtoolsEvent({
847
+ type: "mount-for",
848
+ length: records.length
849
+ });
850
+ return;
851
+ }
852
+ const items = latestItems;
853
+ const nextEntries = [];
854
+ const nextKeys = /* @__PURE__ */ new Set();
855
+ for (let i = 0; i < items.length; i++) {
856
+ const item = items[i];
857
+ const itemKey = latestKeys[i];
858
+ if (nextKeys.has(itemKey)) throw duplicateKeyError(itemKey, i);
859
+ nextKeys.add(itemKey);
860
+ nextEntries.push({
861
+ item,
862
+ key: itemKey
863
+ });
864
+ }
865
+ reconcileEntries(nextEntries);
866
+ };
827
867
  const drainReconciliations = () => {
828
868
  if (reconciling) return;
829
869
  reconciling = true;
830
870
  try {
831
871
  while (reconcileRequested) {
832
872
  reconcileRequested = false;
833
- (0, _zeus_js_signal_internal.untrack)(() => reconcile(latestEntries));
873
+ (0, _zeus_js_signal_internal.untrack)(reconcileLatestItems);
834
874
  }
835
875
  } finally {
836
876
  reconciling = false;
@@ -847,19 +887,16 @@ function mountKeyedFor(parent, marker, each, key, render) {
847
887
  runner = (0, _zeus_js_signal_internal.effect)(() => {
848
888
  var _each2;
849
889
  const nextItems = (_each2 = each()) !== null && _each2 !== void 0 ? _each2 : [];
850
- const nextEntries = [];
851
- const nextKeys = /* @__PURE__ */ new Set();
890
+ let useFixedSlots = nextItems.length === records.length;
852
891
  for (let i = 0; i < nextItems.length; i++) {
853
892
  const item = nextItems[i];
854
893
  const itemKey = key(item, i);
855
- if (nextKeys.has(itemKey)) throw duplicateKeyError(itemKey, i);
856
- nextKeys.add(itemKey);
857
- nextEntries.push({
858
- item,
859
- key: itemKey
860
- });
894
+ latestKeys[i] = itemKey;
895
+ if (useFixedSlots && !Object.is(itemKey, records[i].key)) useFixedSlots = false;
861
896
  }
862
- latestEntries = nextEntries;
897
+ latestKeys.length = nextItems.length;
898
+ latestItems = nextItems;
899
+ latestItemsUseFixedSlots = useFixedSlots;
863
900
  }, { scheduler: scheduleReconciliation });
864
901
  } catch (error) {
865
902
  dispose();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zeus-js/runtime-dom",
3
3
  "type": "module",
4
- "version": "0.1.1-beta.1",
4
+ "version": "0.1.1-beta.10",
5
5
  "description": "@zeus-js/runtime-dom",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -31,7 +31,7 @@
31
31
  "dist"
32
32
  ],
33
33
  "dependencies": {
34
- "@zeus-js/signal": "0.1.1-beta.1"
34
+ "@zeus-js/signal": "0.1.1-beta.10"
35
35
  },
36
36
  "author": "Baicie",
37
37
  "bugs": {