@pyreon/runtime-dom 0.12.14 → 0.13.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/lib/analysis/index.js.html +1 -1
- package/lib/index.js +105 -16
- package/lib/index.js.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/manifest.ts +218 -0
- package/src/props.ts +58 -19
- package/src/tests/manifest-snapshot.test.ts +84 -0
- package/src/tests/mount.test.ts +89 -0
- package/src/tests/props.test.ts +117 -0
- package/src/tests/transition-timeout-leak.test.ts +45 -0
- package/src/transition-group.ts +80 -8
- package/src/transition.ts +26 -1
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"391d1e60-1","name":"delegate.ts"},{"uid":"391d1e60-3","name":"hydration-debug.ts"},{"uid":"391d1e60-5","name":"devtools.ts"},{"uid":"391d1e60-7","name":"nodes.ts"},{"uid":"391d1e60-9","name":"props.ts"},{"uid":"391d1e60-11","name":"mount.ts"},{"uid":"391d1e60-13","name":"hydrate.ts"},{"uid":"391d1e60-15","name":"keep-alive.ts"},{"uid":"391d1e60-17","name":"template.ts"},{"uid":"391d1e60-19","name":"transition.ts"},{"uid":"391d1e60-21","name":"transition-group.ts"},{"uid":"391d1e60-23","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"391d1e60-1":{"renderedLength":1990,"gzipLength":976,"brotliLength":0,"metaUid":"391d1e60-0"},"391d1e60-3":{"renderedLength":662,"gzipLength":370,"brotliLength":0,"metaUid":"391d1e60-2"},"391d1e60-5":{"renderedLength":6803,"gzipLength":2095,"brotliLength":0,"metaUid":"391d1e60-4"},"391d1e60-7":{"renderedLength":16207,"gzipLength":4334,"brotliLength":0,"metaUid":"391d1e60-6"},"391d1e60-9":{"renderedLength":7947,"gzipLength":3020,"brotliLength":0,"metaUid":"391d1e60-8"},"391d1e60-11":{"renderedLength":11649,"gzipLength":3717,"brotliLength":0,"metaUid":"391d1e60-10"},"391d1e60-13":{"renderedLength":8239,"gzipLength":2455,"brotliLength":0,"metaUid":"391d1e60-12"},"391d1e60-15":{"renderedLength":1473,"gzipLength":701,"brotliLength":0,"metaUid":"391d1e60-14"},"391d1e60-17":{"renderedLength":5319,"gzipLength":2069,"brotliLength":0,"metaUid":"391d1e60-16"},"391d1e60-19":{"renderedLength":4895,"gzipLength":1390,"brotliLength":0,"metaUid":"391d1e60-18"},"391d1e60-21":{"renderedLength":7942,"gzipLength":2070,"brotliLength":0,"metaUid":"391d1e60-20"},"391d1e60-23":{"renderedLength":769,"gzipLength":474,"brotliLength":0,"metaUid":"391d1e60-22"}},"nodeMetas":{"391d1e60-0":{"id":"/src/delegate.ts","moduleParts":{"index.js":"391d1e60-1"},"imported":[{"uid":"391d1e60-24"}],"importedBy":[{"uid":"391d1e60-22"},{"uid":"391d1e60-12"},{"uid":"391d1e60-8"}]},"391d1e60-2":{"id":"/src/hydration-debug.ts","moduleParts":{"index.js":"391d1e60-3"},"imported":[],"importedBy":[{"uid":"391d1e60-22"},{"uid":"391d1e60-12"}]},"391d1e60-4":{"id":"/src/devtools.ts","moduleParts":{"index.js":"391d1e60-5"},"imported":[],"importedBy":[{"uid":"391d1e60-22"},{"uid":"391d1e60-10"}]},"391d1e60-6":{"id":"/src/nodes.ts","moduleParts":{"index.js":"391d1e60-7"},"imported":[{"uid":"391d1e60-25"},{"uid":"391d1e60-24"}],"importedBy":[{"uid":"391d1e60-12"},{"uid":"391d1e60-10"}]},"391d1e60-8":{"id":"/src/props.ts","moduleParts":{"index.js":"391d1e60-9"},"imported":[{"uid":"391d1e60-25"},{"uid":"391d1e60-24"},{"uid":"391d1e60-0"}],"importedBy":[{"uid":"391d1e60-22"},{"uid":"391d1e60-12"},{"uid":"391d1e60-10"}]},"391d1e60-10":{"id":"/src/mount.ts","moduleParts":{"index.js":"391d1e60-11"},"imported":[{"uid":"391d1e60-25"},{"uid":"391d1e60-24"},{"uid":"391d1e60-4"},{"uid":"391d1e60-6"},{"uid":"391d1e60-8"}],"importedBy":[{"uid":"391d1e60-22"},{"uid":"391d1e60-12"},{"uid":"391d1e60-14"},{"uid":"391d1e60-16"},{"uid":"391d1e60-20"}]},"391d1e60-12":{"id":"/src/hydrate.ts","moduleParts":{"index.js":"391d1e60-13"},"imported":[{"uid":"391d1e60-25"},{"uid":"391d1e60-24"},{"uid":"391d1e60-0"},{"uid":"391d1e60-2"},{"uid":"391d1e60-10"},{"uid":"391d1e60-6"},{"uid":"391d1e60-8"}],"importedBy":[{"uid":"391d1e60-22"}]},"391d1e60-14":{"id":"/src/keep-alive.ts","moduleParts":{"index.js":"391d1e60-15"},"imported":[{"uid":"391d1e60-25"},{"uid":"391d1e60-24"},{"uid":"391d1e60-10"}],"importedBy":[{"uid":"391d1e60-22"}]},"391d1e60-16":{"id":"/src/template.ts","moduleParts":{"index.js":"391d1e60-17"},"imported":[{"uid":"391d1e60-24"},{"uid":"391d1e60-10"}],"importedBy":[{"uid":"391d1e60-22"}]},"391d1e60-18":{"id":"/src/transition.ts","moduleParts":{"index.js":"391d1e60-19"},"imported":[{"uid":"391d1e60-25"},{"uid":"391d1e60-24"}],"importedBy":[{"uid":"391d1e60-22"}]},"391d1e60-20":{"id":"/src/transition-group.ts","moduleParts":{"index.js":"391d1e60-21"},"imported":[{"uid":"391d1e60-25"},{"uid":"391d1e60-24"},{"uid":"391d1e60-10"}],"importedBy":[{"uid":"391d1e60-22"}]},"391d1e60-22":{"id":"/src/index.ts","moduleParts":{"index.js":"391d1e60-23"},"imported":[{"uid":"391d1e60-0"},{"uid":"391d1e60-12"},{"uid":"391d1e60-2"},{"uid":"391d1e60-14"},{"uid":"391d1e60-10"},{"uid":"391d1e60-8"},{"uid":"391d1e60-16"},{"uid":"391d1e60-18"},{"uid":"391d1e60-20"},{"uid":"391d1e60-4"}],"importedBy":[],"isEntry":true},"391d1e60-24":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"391d1e60-0"},{"uid":"391d1e60-12"},{"uid":"391d1e60-14"},{"uid":"391d1e60-10"},{"uid":"391d1e60-8"},{"uid":"391d1e60-16"},{"uid":"391d1e60-18"},{"uid":"391d1e60-20"},{"uid":"391d1e60-6"}]},"391d1e60-25":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"391d1e60-12"},{"uid":"391d1e60-14"},{"uid":"391d1e60-10"},{"uid":"391d1e60-8"},{"uid":"391d1e60-18"},{"uid":"391d1e60-20"},{"uid":"391d1e60-6"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
package/lib/index.js
CHANGED
|
@@ -994,19 +994,38 @@ function applyEventProp(el, key, value) {
|
|
|
994
994
|
el.addEventListener(eventName, batched);
|
|
995
995
|
return () => el.removeEventListener(eventName, batched);
|
|
996
996
|
}
|
|
997
|
-
|
|
998
|
-
|
|
997
|
+
/**
|
|
998
|
+
* Sink for a single prop's CALLED value (always a primitive / object /
|
|
999
|
+
* `null` — never a function). Called both directly for static values and
|
|
1000
|
+
* from the reactive `renderEffect` for accessor-bound values.
|
|
1001
|
+
*
|
|
1002
|
+
* NOTE on architecture: extracting the special-cased sinks
|
|
1003
|
+
* (`innerHTML` / `dangerouslySetInnerHTML`) into this single dispatch
|
|
1004
|
+
* function ensures every prop kind goes through the same reactive
|
|
1005
|
+
* wrapping at `applyProp`'s entry. Previously each special case had its
|
|
1006
|
+
* own early-return branch that needed to remember to handle function
|
|
1007
|
+
* values; missing the dance once meant the closure was stringified and
|
|
1008
|
+
* set as literal text. The structural fix (one reactive-wrap, then
|
|
1009
|
+
* dispatch) eliminates the entire bug class.
|
|
1010
|
+
*/
|
|
1011
|
+
function applyStaticProp(el, key, value) {
|
|
1012
|
+
if (__DEV__$3 && typeof value === "function") console.warn(`[Pyreon] applyStaticProp received a function for "${key}". This likely means a new special-cased prop sink in applyProp() bypassed the reactive-wrap path. The closure would be stringified and set as a literal value. Verify the dispatch in applyProp().`);
|
|
999
1013
|
if (key === "innerHTML") {
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1014
|
+
const html = String(value ?? "");
|
|
1015
|
+
if (typeof el.setHTML === "function") el.setHTML(html);
|
|
1016
|
+
else el.innerHTML = sanitizeHtml(html);
|
|
1017
|
+
return;
|
|
1003
1018
|
}
|
|
1004
1019
|
if (key === "dangerouslySetInnerHTML") {
|
|
1005
|
-
el.innerHTML = value
|
|
1006
|
-
return
|
|
1020
|
+
el.innerHTML = value?.__html ?? "";
|
|
1021
|
+
return;
|
|
1007
1022
|
}
|
|
1008
|
-
if (typeof value === "function") return renderEffect(() => setStaticProp(el, key, value()));
|
|
1009
1023
|
setStaticProp(el, key, value);
|
|
1024
|
+
}
|
|
1025
|
+
function applyProp(el, key, value) {
|
|
1026
|
+
if (EVENT_RE.test(key)) return applyEventProp(el, key, value);
|
|
1027
|
+
if (typeof value === "function") return renderEffect(() => applyStaticProp(el, key, value()));
|
|
1028
|
+
applyStaticProp(el, key, value);
|
|
1010
1029
|
return null;
|
|
1011
1030
|
}
|
|
1012
1031
|
const URL_ATTRS = new Set([
|
|
@@ -1944,11 +1963,14 @@ function Transition(props) {
|
|
|
1944
1963
|
};
|
|
1945
1964
|
const ref = createRef();
|
|
1946
1965
|
const isMounted = signal(runUntracked(props.show));
|
|
1966
|
+
let pendingEnterCancel = null;
|
|
1947
1967
|
let pendingLeaveCancel = null;
|
|
1948
1968
|
let initialized = false;
|
|
1949
1969
|
const applyEnter = (el) => {
|
|
1950
1970
|
pendingLeaveCancel?.();
|
|
1951
1971
|
pendingLeaveCancel = null;
|
|
1972
|
+
pendingEnterCancel?.();
|
|
1973
|
+
pendingEnterCancel = null;
|
|
1952
1974
|
props.onBeforeEnter?.(el);
|
|
1953
1975
|
el.classList.remove(cls.lf, cls.la, cls.lt);
|
|
1954
1976
|
el.classList.add(cls.ef, cls.ea);
|
|
@@ -1963,15 +1985,27 @@ function Transition(props) {
|
|
|
1963
1985
|
clearTimeout(safetyTimer);
|
|
1964
1986
|
safetyTimer = null;
|
|
1965
1987
|
}
|
|
1988
|
+
pendingEnterCancel = null;
|
|
1966
1989
|
el.classList.remove(cls.ea, cls.et);
|
|
1967
1990
|
props.onAfterEnter?.(el);
|
|
1968
1991
|
};
|
|
1992
|
+
pendingEnterCancel = () => {
|
|
1993
|
+
el.removeEventListener("transitionend", done);
|
|
1994
|
+
el.removeEventListener("animationend", done);
|
|
1995
|
+
if (safetyTimer !== null) {
|
|
1996
|
+
clearTimeout(safetyTimer);
|
|
1997
|
+
safetyTimer = null;
|
|
1998
|
+
}
|
|
1999
|
+
el.classList.remove(cls.ef, cls.ea, cls.et);
|
|
2000
|
+
};
|
|
1969
2001
|
el.addEventListener("transitionend", done, { once: true });
|
|
1970
2002
|
el.addEventListener("animationend", done, { once: true });
|
|
1971
2003
|
safetyTimer = setTimeout(done, 5e3);
|
|
1972
2004
|
});
|
|
1973
2005
|
};
|
|
1974
2006
|
const applyLeave = (el) => {
|
|
2007
|
+
pendingEnterCancel?.();
|
|
2008
|
+
pendingEnterCancel = null;
|
|
1975
2009
|
props.onBeforeLeave?.(el);
|
|
1976
2010
|
el.classList.remove(cls.ef, cls.ea, cls.et);
|
|
1977
2011
|
el.classList.add(cls.lf, cls.la);
|
|
@@ -2029,6 +2063,8 @@ function Transition(props) {
|
|
|
2029
2063
|
handleVisibilityChange(visible);
|
|
2030
2064
|
});
|
|
2031
2065
|
onUnmount(() => {
|
|
2066
|
+
pendingEnterCancel?.();
|
|
2067
|
+
pendingEnterCancel = null;
|
|
2032
2068
|
pendingLeaveCancel?.();
|
|
2033
2069
|
pendingLeaveCancel = null;
|
|
2034
2070
|
});
|
|
@@ -2095,39 +2131,71 @@ function TransitionGroup(props) {
|
|
|
2095
2131
|
const entries = /* @__PURE__ */ new Map();
|
|
2096
2132
|
const ready = signal(false);
|
|
2097
2133
|
let firstRun = true;
|
|
2098
|
-
const applyEnter = (el) => {
|
|
2134
|
+
const applyEnter = (entry, el) => {
|
|
2099
2135
|
props.onBeforeEnter?.(el);
|
|
2100
2136
|
el.classList.remove(cls.lf, cls.la, cls.lt);
|
|
2101
2137
|
el.classList.add(cls.ef, cls.ea);
|
|
2102
2138
|
requestAnimationFrame(() => {
|
|
2103
2139
|
el.classList.remove(cls.ef);
|
|
2104
2140
|
el.classList.add(cls.et);
|
|
2141
|
+
let safetyTimer = null;
|
|
2105
2142
|
const done = () => {
|
|
2106
2143
|
el.removeEventListener("transitionend", done);
|
|
2107
2144
|
el.removeEventListener("animationend", done);
|
|
2145
|
+
if (safetyTimer !== null) {
|
|
2146
|
+
clearTimeout(safetyTimer);
|
|
2147
|
+
safetyTimer = null;
|
|
2148
|
+
}
|
|
2149
|
+
entry.cancelTransition = null;
|
|
2108
2150
|
el.classList.remove(cls.ea, cls.et);
|
|
2109
2151
|
props.onAfterEnter?.(el);
|
|
2110
2152
|
};
|
|
2153
|
+
entry.cancelTransition = () => {
|
|
2154
|
+
el.removeEventListener("transitionend", done);
|
|
2155
|
+
el.removeEventListener("animationend", done);
|
|
2156
|
+
if (safetyTimer !== null) {
|
|
2157
|
+
clearTimeout(safetyTimer);
|
|
2158
|
+
safetyTimer = null;
|
|
2159
|
+
}
|
|
2160
|
+
el.classList.remove(cls.ef, cls.ea, cls.et);
|
|
2161
|
+
};
|
|
2111
2162
|
el.addEventListener("transitionend", done, { once: true });
|
|
2112
2163
|
el.addEventListener("animationend", done, { once: true });
|
|
2164
|
+
safetyTimer = setTimeout(done, 5e3);
|
|
2113
2165
|
});
|
|
2114
2166
|
};
|
|
2115
|
-
const applyLeave = (el, onDone) => {
|
|
2167
|
+
const applyLeave = (entry, el, onDone) => {
|
|
2116
2168
|
props.onBeforeLeave?.(el);
|
|
2117
2169
|
el.classList.remove(cls.ef, cls.ea, cls.et);
|
|
2118
2170
|
el.classList.add(cls.lf, cls.la);
|
|
2119
2171
|
requestAnimationFrame(() => {
|
|
2120
2172
|
el.classList.remove(cls.lf);
|
|
2121
2173
|
el.classList.add(cls.lt);
|
|
2174
|
+
let safetyTimer = null;
|
|
2122
2175
|
const done = () => {
|
|
2123
2176
|
el.removeEventListener("transitionend", done);
|
|
2124
2177
|
el.removeEventListener("animationend", done);
|
|
2178
|
+
if (safetyTimer !== null) {
|
|
2179
|
+
clearTimeout(safetyTimer);
|
|
2180
|
+
safetyTimer = null;
|
|
2181
|
+
}
|
|
2182
|
+
entry.cancelTransition = null;
|
|
2125
2183
|
el.classList.remove(cls.la, cls.lt);
|
|
2126
2184
|
props.onAfterLeave?.(el);
|
|
2127
2185
|
onDone();
|
|
2128
2186
|
};
|
|
2187
|
+
entry.cancelTransition = () => {
|
|
2188
|
+
el.removeEventListener("transitionend", done);
|
|
2189
|
+
el.removeEventListener("animationend", done);
|
|
2190
|
+
if (safetyTimer !== null) {
|
|
2191
|
+
clearTimeout(safetyTimer);
|
|
2192
|
+
safetyTimer = null;
|
|
2193
|
+
}
|
|
2194
|
+
el.classList.remove(cls.lf, cls.la, cls.lt);
|
|
2195
|
+
};
|
|
2129
2196
|
el.addEventListener("transitionend", done, { once: true });
|
|
2130
2197
|
el.addEventListener("animationend", done, { once: true });
|
|
2198
|
+
safetyTimer = setTimeout(done, 5e3);
|
|
2131
2199
|
});
|
|
2132
2200
|
};
|
|
2133
2201
|
/** Start leave animation for removed items. */
|
|
@@ -2136,7 +2204,7 @@ function TransitionGroup(props) {
|
|
|
2136
2204
|
if (newKeys.has(key) || entry.leaving) continue;
|
|
2137
2205
|
entry.leaving = true;
|
|
2138
2206
|
const el = entry.ref.current;
|
|
2139
|
-
if (el) applyLeave(el, () => {
|
|
2207
|
+
if (el) applyLeave(entry, el, () => {
|
|
2140
2208
|
entry.cleanup();
|
|
2141
2209
|
entries.delete(key);
|
|
2142
2210
|
});
|
|
@@ -2165,25 +2233,42 @@ function TransitionGroup(props) {
|
|
|
2165
2233
|
ref: itemRef
|
|
2166
2234
|
}
|
|
2167
2235
|
} : rawVNode, container, null),
|
|
2168
|
-
leaving: false
|
|
2236
|
+
leaving: false,
|
|
2237
|
+
cancelTransition: null
|
|
2169
2238
|
};
|
|
2170
2239
|
entries.set(key, entry);
|
|
2171
2240
|
newEntries.push(entry);
|
|
2172
2241
|
}
|
|
2173
2242
|
return newEntries;
|
|
2174
2243
|
};
|
|
2175
|
-
const startMoveAnimation = (el) => {
|
|
2244
|
+
const startMoveAnimation = (entry, el) => {
|
|
2176
2245
|
requestAnimationFrame(() => {
|
|
2177
2246
|
el.classList.add(cls.mv);
|
|
2178
2247
|
el.style.transform = "";
|
|
2179
2248
|
el.style.transition = "";
|
|
2249
|
+
let safetyTimer = null;
|
|
2180
2250
|
const done = () => {
|
|
2181
2251
|
el.removeEventListener("transitionend", done);
|
|
2182
2252
|
el.removeEventListener("animationend", done);
|
|
2253
|
+
if (safetyTimer !== null) {
|
|
2254
|
+
clearTimeout(safetyTimer);
|
|
2255
|
+
safetyTimer = null;
|
|
2256
|
+
}
|
|
2257
|
+
entry.cancelTransition = null;
|
|
2258
|
+
el.classList.remove(cls.mv);
|
|
2259
|
+
};
|
|
2260
|
+
entry.cancelTransition = () => {
|
|
2261
|
+
el.removeEventListener("transitionend", done);
|
|
2262
|
+
el.removeEventListener("animationend", done);
|
|
2263
|
+
if (safetyTimer !== null) {
|
|
2264
|
+
clearTimeout(safetyTimer);
|
|
2265
|
+
safetyTimer = null;
|
|
2266
|
+
}
|
|
2183
2267
|
el.classList.remove(cls.mv);
|
|
2184
2268
|
};
|
|
2185
2269
|
el.addEventListener("transitionend", done, { once: true });
|
|
2186
2270
|
el.addEventListener("animationend", done, { once: true });
|
|
2271
|
+
safetyTimer = setTimeout(done, 5e3);
|
|
2187
2272
|
});
|
|
2188
2273
|
};
|
|
2189
2274
|
const flipEntry = (entry, oldPos) => {
|
|
@@ -2195,7 +2280,7 @@ function TransitionGroup(props) {
|
|
|
2195
2280
|
const el = entry.ref.current;
|
|
2196
2281
|
el.style.transform = `translate(${dx}px, ${dy}px)`;
|
|
2197
2282
|
el.style.transition = "none";
|
|
2198
|
-
startMoveAnimation(el);
|
|
2283
|
+
startMoveAnimation(entry, el);
|
|
2199
2284
|
};
|
|
2200
2285
|
/** Apply FLIP move animations for items that shifted position. */
|
|
2201
2286
|
const applyFlipMoves = (oldPositions) => {
|
|
@@ -2223,7 +2308,7 @@ function TransitionGroup(props) {
|
|
|
2223
2308
|
};
|
|
2224
2309
|
const animateNewEntries = (newEntries) => {
|
|
2225
2310
|
for (const entry of newEntries) queueMicrotask(() => {
|
|
2226
|
-
if (entry.ref.current) applyEnter(entry.ref.current);
|
|
2311
|
+
if (entry.ref.current) applyEnter(entry, entry.ref.current);
|
|
2227
2312
|
});
|
|
2228
2313
|
};
|
|
2229
2314
|
const e = effect(() => {
|
|
@@ -2246,7 +2331,11 @@ function TransitionGroup(props) {
|
|
|
2246
2331
|
});
|
|
2247
2332
|
onUnmount(() => {
|
|
2248
2333
|
e.dispose();
|
|
2249
|
-
for (const entry of entries.values())
|
|
2334
|
+
for (const entry of entries.values()) {
|
|
2335
|
+
entry.cancelTransition?.();
|
|
2336
|
+
entry.cancelTransition = null;
|
|
2337
|
+
entry.cleanup();
|
|
2338
|
+
}
|
|
2250
2339
|
entries.clear();
|
|
2251
2340
|
});
|
|
2252
2341
|
return h(tag, { ref: containerRef });
|