sibujs 1.1.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/README.md +29 -25
- package/dist/browser.cjs +804 -2
- package/dist/browser.d.cts +591 -1
- package/dist/browser.d.ts +591 -1
- package/dist/browser.js +50 -8
- package/dist/build.cjs +706 -161
- package/dist/build.js +21 -12
- package/dist/cdn.global.js +188 -7
- package/dist/chunk-2BYQDGN3.js +742 -0
- package/dist/chunk-32DY64NT.js +282 -0
- package/dist/chunk-3AIRKM3B.js +1263 -0
- package/dist/chunk-3X2YG6YM.js +505 -0
- package/dist/chunk-5X6PP2UK.js +28 -0
- package/dist/chunk-77L6NL3X.js +1097 -0
- package/dist/chunk-B7SWRFUT.js +332 -0
- package/dist/chunk-BGN5ZMP4.js +26 -0
- package/dist/chunk-BTU3TJDS.js +365 -0
- package/dist/chunk-CHF5OHIA.js +61 -0
- package/dist/chunk-CMBFNA7L.js +27 -0
- package/dist/chunk-DAHRH4ON.js +331 -0
- package/dist/chunk-EBGIRKQY.js +616 -0
- package/dist/chunk-EUZND3CB.js +27 -0
- package/dist/chunk-F3FA4F32.js +292 -0
- package/dist/chunk-GCOK2LC3.js +282 -0
- package/dist/chunk-JAKHTMQU.js +1000 -0
- package/dist/chunk-JCI5M6U6.js +956 -0
- package/dist/chunk-KQPDEVVS.js +398 -0
- package/dist/chunk-NEKUBFPT.js +60 -0
- package/dist/chunk-NYVAC6P5.js +37 -0
- package/dist/chunk-OUZZEE4S.js +365 -0
- package/dist/chunk-P6W3STU4.js +2249 -0
- package/dist/chunk-PTQJDMRT.js +146 -0
- package/dist/chunk-QWZG56ET.js +2744 -0
- package/dist/chunk-TSOKIX5Z.js +654 -0
- package/dist/chunk-VMVDTCXB.js +712 -0
- package/dist/chunk-VRW3FULF.js +725 -0
- package/dist/chunk-WZSPOOER.js +84 -0
- package/dist/chunk-YT6HQ6AM.js +14 -0
- package/dist/chunk-ZD6OAMTH.js +277 -0
- package/dist/contracts-DDrwxvJ-.d.cts +245 -0
- package/dist/contracts-DDrwxvJ-.d.ts +245 -0
- package/dist/data.cjs +35 -2
- package/dist/data.d.cts +7 -0
- package/dist/data.d.ts +7 -0
- package/dist/data.js +9 -8
- package/dist/devtools.cjs +122 -0
- package/dist/devtools.d.cts +69 -461
- package/dist/devtools.d.ts +69 -461
- package/dist/devtools.js +127 -6
- package/dist/ecosystem.cjs +68 -23
- package/dist/ecosystem.d.cts +1 -1
- package/dist/ecosystem.d.ts +1 -1
- package/dist/ecosystem.js +10 -9
- package/dist/extras.cjs +1252 -82
- package/dist/extras.d.cts +5 -5
- package/dist/extras.d.ts +5 -5
- package/dist/extras.js +69 -24
- package/dist/index.cjs +708 -161
- package/dist/index.d.cts +397 -17
- package/dist/index.d.ts +397 -17
- package/dist/index.js +39 -17
- package/dist/introspect-BumjnBKr.d.cts +477 -0
- package/dist/introspect-CZrlcaYy.d.ts +477 -0
- package/dist/introspect-Cb0zgpi2.d.cts +477 -0
- package/dist/introspect-Y2xNXGSf.d.ts +477 -0
- package/dist/motion.js +4 -4
- package/dist/patterns.cjs +51 -2
- package/dist/patterns.d.cts +18 -8
- package/dist/patterns.d.ts +18 -8
- package/dist/patterns.js +7 -7
- package/dist/performance.js +4 -4
- package/dist/plugins.cjs +473 -98
- package/dist/plugins.d.cts +27 -4
- package/dist/plugins.d.ts +27 -4
- package/dist/plugins.js +156 -37
- package/dist/ssr-4PBXAOO3.js +40 -0
- package/dist/ssr-Do_SiVoL.d.cts +201 -0
- package/dist/ssr-Do_SiVoL.d.ts +201 -0
- package/dist/ssr.cjs +357 -77
- package/dist/ssr.d.cts +10 -1
- package/dist/ssr.d.ts +10 -1
- package/dist/ssr.js +13 -10
- package/dist/tagFactory-DaJ0YWX6.d.cts +47 -0
- package/dist/tagFactory-DaJ0YWX6.d.ts +47 -0
- package/dist/testing.cjs +233 -2
- package/dist/testing.d.cts +42 -1
- package/dist/testing.d.ts +42 -1
- package/dist/testing.js +129 -2
- package/dist/ui.cjs +374 -3
- package/dist/ui.d.cts +252 -2
- package/dist/ui.d.ts +252 -2
- package/dist/ui.js +328 -8
- package/dist/widgets.js +7 -7
- package/package.json +1 -1
package/dist/extras.cjs
CHANGED
|
@@ -32,6 +32,7 @@ __export(extras_exports, {
|
|
|
32
32
|
VirtualList: () => VirtualList,
|
|
33
33
|
accordion: () => accordion,
|
|
34
34
|
animate: () => animate,
|
|
35
|
+
animationFrame: () => animationFrame,
|
|
35
36
|
announce: () => announce,
|
|
36
37
|
antdAdapter: () => antdAdapter,
|
|
37
38
|
aria: () => aria,
|
|
@@ -44,6 +45,8 @@ __export(extras_exports, {
|
|
|
44
45
|
block: () => block,
|
|
45
46
|
bounceIn: () => bounceIn,
|
|
46
47
|
bounceOut: () => bounceOut,
|
|
48
|
+
bounds: () => bounds,
|
|
49
|
+
broadcast: () => broadcast,
|
|
47
50
|
bundlerMetadata: () => bundlerMetadata,
|
|
48
51
|
calculateDelay: () => calculateDelay,
|
|
49
52
|
chakraAdapter: () => chakraAdapter,
|
|
@@ -117,10 +120,12 @@ __export(extras_exports, {
|
|
|
117
120
|
email: () => email,
|
|
118
121
|
enableDebug: () => enableDebug,
|
|
119
122
|
env: () => env,
|
|
123
|
+
escapeScriptJson: () => escapeScriptJson,
|
|
120
124
|
eventBus: () => eventBus,
|
|
121
125
|
executeLoader: () => executeLoader,
|
|
122
126
|
fadeIn: () => fadeIn,
|
|
123
127
|
fadeOut: () => fadeOut,
|
|
128
|
+
favicon: () => favicon,
|
|
124
129
|
fileUpload: () => fileUpload,
|
|
125
130
|
flipIn: () => flipIn,
|
|
126
131
|
flushScheduler: () => flushScheduler,
|
|
@@ -129,6 +134,8 @@ __export(extras_exports, {
|
|
|
129
134
|
formatCurrency: () => formatCurrency,
|
|
130
135
|
formatError: () => formatError,
|
|
131
136
|
formatNumber: () => formatNumber,
|
|
137
|
+
fullscreen: () => fullscreen,
|
|
138
|
+
gamepad: () => gamepad,
|
|
132
139
|
generateStaticSite: () => generateStaticSite,
|
|
133
140
|
geo: () => geo,
|
|
134
141
|
getActiveDevTools: () => getActiveDevTools,
|
|
@@ -147,6 +154,7 @@ __export(extras_exports, {
|
|
|
147
154
|
hydrateIslands: () => hydrateIslands,
|
|
148
155
|
hydrateProgressively: () => hydrateProgressively,
|
|
149
156
|
idle: () => idle,
|
|
157
|
+
imageLoader: () => imageLoader,
|
|
150
158
|
infiniteQuery: () => infiniteQuery,
|
|
151
159
|
infiniteScroll: () => infiniteScroll,
|
|
152
160
|
initDevTools: () => initDevTools,
|
|
@@ -159,6 +167,7 @@ __export(extras_exports, {
|
|
|
159
167
|
isHMRAvailable: () => isHMRAvailable,
|
|
160
168
|
isWasmCached: () => isWasmCached,
|
|
161
169
|
island: () => island,
|
|
170
|
+
keyboard: () => keyboard,
|
|
162
171
|
lazyChunk: () => lazyChunk,
|
|
163
172
|
lazyLoad: () => lazyLoad,
|
|
164
173
|
lazyModule: () => lazyModule,
|
|
@@ -175,7 +184,10 @@ __export(extras_exports, {
|
|
|
175
184
|
min: () => min,
|
|
176
185
|
minLength: () => minLength,
|
|
177
186
|
mobXAdapter: () => mobXAdapter,
|
|
187
|
+
mouse: () => mouse,
|
|
178
188
|
mutation: () => mutation,
|
|
189
|
+
mutationObserver: () => mutationObserver,
|
|
190
|
+
network: () => network,
|
|
179
191
|
noSideEffect: () => noSideEffect,
|
|
180
192
|
normalize: () => normalize,
|
|
181
193
|
normalizedStore: () => normalizedStore,
|
|
@@ -192,6 +204,7 @@ __export(extras_exports, {
|
|
|
192
204
|
persisted: () => persisted,
|
|
193
205
|
phoneMask: () => phoneMask,
|
|
194
206
|
plugin: () => plugin,
|
|
207
|
+
pointerLock: () => pointerLock,
|
|
195
208
|
popover: () => popover,
|
|
196
209
|
precompile: () => precompile,
|
|
197
210
|
prefetch: () => prefetch,
|
|
@@ -243,6 +256,7 @@ __export(extras_exports, {
|
|
|
243
256
|
slideIn: () => slideIn,
|
|
244
257
|
slideOut: () => slideOut,
|
|
245
258
|
socket: () => socket,
|
|
259
|
+
speech: () => speech,
|
|
246
260
|
spring: () => spring,
|
|
247
261
|
springSignal: () => springSignal,
|
|
248
262
|
ssnMask: () => ssnMask,
|
|
@@ -254,8 +268,11 @@ __export(extras_exports, {
|
|
|
254
268
|
stream: () => stream,
|
|
255
269
|
suspenseSwapScript: () => suspenseSwapScript,
|
|
256
270
|
svgElement: () => svgElement,
|
|
271
|
+
svgFavicon: () => svgFavicon,
|
|
272
|
+
swipe: () => swipe,
|
|
257
273
|
syncAdapter: () => syncAdapter,
|
|
258
274
|
tabs: () => tabs,
|
|
275
|
+
textSelection: () => textSelection,
|
|
259
276
|
throttle: () => throttle,
|
|
260
277
|
timeMask: () => timeMask,
|
|
261
278
|
timeline: () => timeline,
|
|
@@ -270,11 +287,16 @@ __export(extras_exports, {
|
|
|
270
287
|
triggerPluginUnmount: () => triggerPluginUnmount,
|
|
271
288
|
trustHTML: () => trustHTML,
|
|
272
289
|
uniqueId: () => uniqueId,
|
|
290
|
+
urlState: () => urlState,
|
|
273
291
|
validateProps: () => validateProps,
|
|
274
292
|
validators: () => validators,
|
|
293
|
+
vibrate: () => vibrate,
|
|
275
294
|
viewTransition: () => viewTransition,
|
|
295
|
+
visibility: () => visibility,
|
|
296
|
+
wakeLock: () => wakeLock,
|
|
276
297
|
walkDependencyGraph: () => walkDependencyGraph,
|
|
277
298
|
wasm: () => wasm,
|
|
299
|
+
windowSize: () => windowSize,
|
|
278
300
|
withBoundary: () => withBoundary,
|
|
279
301
|
withDefaults: () => withDefaults,
|
|
280
302
|
withErrorTracking: () => withErrorTracking,
|
|
@@ -1512,6 +1534,13 @@ async function preloadRoute(route, context2) {
|
|
|
1512
1534
|
}
|
|
1513
1535
|
|
|
1514
1536
|
// src/ui/socket.ts
|
|
1537
|
+
function validateWsUrl(raw) {
|
|
1538
|
+
const trimmed = raw.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
|
|
1539
|
+
if (!trimmed) return null;
|
|
1540
|
+
const lower = trimmed.toLowerCase();
|
|
1541
|
+
if (lower.startsWith("ws://") || lower.startsWith("wss://")) return trimmed;
|
|
1542
|
+
return null;
|
|
1543
|
+
}
|
|
1515
1544
|
function socket(url, options) {
|
|
1516
1545
|
const autoReconnect = options?.autoReconnect ?? false;
|
|
1517
1546
|
const reconnectDelay = options?.reconnectDelay ?? 1e3;
|
|
@@ -1530,8 +1559,13 @@ function socket(url, options) {
|
|
|
1530
1559
|
}
|
|
1531
1560
|
function connect() {
|
|
1532
1561
|
if (disposed) return;
|
|
1562
|
+
const safeUrl = validateWsUrl(getUrl());
|
|
1563
|
+
if (safeUrl === null) {
|
|
1564
|
+
setStatus("closed");
|
|
1565
|
+
return;
|
|
1566
|
+
}
|
|
1533
1567
|
setStatus("connecting");
|
|
1534
|
-
ws = new WebSocket(
|
|
1568
|
+
ws = new WebSocket(safeUrl, protocols);
|
|
1535
1569
|
ws.onopen = () => {
|
|
1536
1570
|
setStatus("open");
|
|
1537
1571
|
reconnectCount = 0;
|
|
@@ -1592,7 +1626,34 @@ function socket(url, options) {
|
|
|
1592
1626
|
return { data: data2, status, send, close, dispose };
|
|
1593
1627
|
}
|
|
1594
1628
|
|
|
1629
|
+
// src/utils/sanitize.ts
|
|
1630
|
+
function sanitizeUrl(url) {
|
|
1631
|
+
const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
|
|
1632
|
+
if (!trimmed) return "";
|
|
1633
|
+
const lower = trimmed.toLowerCase();
|
|
1634
|
+
if (lower.startsWith("javascript:") || lower.startsWith("data:") || lower.startsWith("vbscript:") || lower.startsWith("blob:")) {
|
|
1635
|
+
return "";
|
|
1636
|
+
}
|
|
1637
|
+
return trimmed;
|
|
1638
|
+
}
|
|
1639
|
+
function sanitizeCSSValue(value) {
|
|
1640
|
+
const lower = value.toLowerCase().replace(/\s+/g, "");
|
|
1641
|
+
if (lower.includes("url(") || lower.includes("expression(") || lower.includes("javascript:") || lower.includes("-moz-binding")) {
|
|
1642
|
+
return "";
|
|
1643
|
+
}
|
|
1644
|
+
return value;
|
|
1645
|
+
}
|
|
1646
|
+
var URL_ATTRIBUTES = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "cite", "poster", "background", "srcset"]);
|
|
1647
|
+
function isUrlAttribute(attr) {
|
|
1648
|
+
return URL_ATTRIBUTES.has(attr);
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1595
1651
|
// src/ui/stream.ts
|
|
1652
|
+
function validateSseUrl(raw) {
|
|
1653
|
+
const safe = sanitizeUrl(raw);
|
|
1654
|
+
if (!safe) return null;
|
|
1655
|
+
return safe;
|
|
1656
|
+
}
|
|
1596
1657
|
function stream(url, options) {
|
|
1597
1658
|
const autoReconnect = options?.autoReconnect ?? false;
|
|
1598
1659
|
const [data2, setData] = signal(null);
|
|
@@ -1603,8 +1664,13 @@ function stream(url, options) {
|
|
|
1603
1664
|
let reconnectTimer = null;
|
|
1604
1665
|
function connect() {
|
|
1605
1666
|
if (disposed) return;
|
|
1667
|
+
const safeUrl = validateSseUrl(url);
|
|
1668
|
+
if (safeUrl === null) {
|
|
1669
|
+
setStatus("closed");
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1606
1672
|
setStatus("connecting");
|
|
1607
|
-
source2 = new EventSource(
|
|
1673
|
+
source2 = new EventSource(safeUrl, {
|
|
1608
1674
|
withCredentials: options?.withCredentials ?? false
|
|
1609
1675
|
});
|
|
1610
1676
|
source2.onopen = () => {
|
|
@@ -2103,6 +2169,766 @@ function formatCurrency(value, currency, options) {
|
|
|
2103
2169
|
}).format(value);
|
|
2104
2170
|
}
|
|
2105
2171
|
|
|
2172
|
+
// src/browser/visibility.ts
|
|
2173
|
+
function visibility() {
|
|
2174
|
+
if (typeof document === "undefined") {
|
|
2175
|
+
const [visible2] = signal(true);
|
|
2176
|
+
return { visible: visible2, dispose: () => {
|
|
2177
|
+
} };
|
|
2178
|
+
}
|
|
2179
|
+
const [visible, setVisible] = signal(!document.hidden);
|
|
2180
|
+
const handler = () => setVisible(!document.hidden);
|
|
2181
|
+
document.addEventListener("visibilitychange", handler);
|
|
2182
|
+
function dispose() {
|
|
2183
|
+
document.removeEventListener("visibilitychange", handler);
|
|
2184
|
+
}
|
|
2185
|
+
return { visible, dispose };
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
// src/browser/network.ts
|
|
2189
|
+
function network() {
|
|
2190
|
+
const connection = typeof navigator !== "undefined" ? navigator.connection ?? navigator.mozConnection ?? navigator.webkitConnection : void 0;
|
|
2191
|
+
const [effectiveType, setEffectiveType] = signal(connection?.effectiveType ?? "unknown");
|
|
2192
|
+
const [downlink, setDownlink] = signal(connection?.downlink ?? 0);
|
|
2193
|
+
const [rtt, setRtt] = signal(connection?.rtt ?? 0);
|
|
2194
|
+
const [saveData, setSaveData] = signal(connection?.saveData ?? false);
|
|
2195
|
+
if (!connection) {
|
|
2196
|
+
return { effectiveType, downlink, rtt, saveData, dispose: () => {
|
|
2197
|
+
} };
|
|
2198
|
+
}
|
|
2199
|
+
const update = () => {
|
|
2200
|
+
setEffectiveType(connection.effectiveType ?? "unknown");
|
|
2201
|
+
setDownlink(connection.downlink ?? 0);
|
|
2202
|
+
setRtt(connection.rtt ?? 0);
|
|
2203
|
+
setSaveData(connection.saveData ?? false);
|
|
2204
|
+
};
|
|
2205
|
+
connection.addEventListener("change", update);
|
|
2206
|
+
function dispose() {
|
|
2207
|
+
connection?.removeEventListener("change", update);
|
|
2208
|
+
}
|
|
2209
|
+
return { effectiveType, downlink, rtt, saveData, dispose };
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2212
|
+
// src/browser/mouse.ts
|
|
2213
|
+
function mouse(options = {}) {
|
|
2214
|
+
const [x, setX] = signal(0);
|
|
2215
|
+
const [y, setY] = signal(0);
|
|
2216
|
+
if (typeof window === "undefined") {
|
|
2217
|
+
return { x, y, dispose: () => {
|
|
2218
|
+
} };
|
|
2219
|
+
}
|
|
2220
|
+
const target = options.target ?? window;
|
|
2221
|
+
const trackTouch = options.touch ?? true;
|
|
2222
|
+
const onMove = (e) => {
|
|
2223
|
+
setX(e.clientX);
|
|
2224
|
+
setY(e.clientY);
|
|
2225
|
+
};
|
|
2226
|
+
const onTouchMove = (e) => {
|
|
2227
|
+
if (e.touches.length === 0) return;
|
|
2228
|
+
setX(e.touches[0].clientX);
|
|
2229
|
+
setY(e.touches[0].clientY);
|
|
2230
|
+
};
|
|
2231
|
+
target.addEventListener("mousemove", onMove, { passive: true });
|
|
2232
|
+
if (trackTouch) {
|
|
2233
|
+
target.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
2234
|
+
}
|
|
2235
|
+
function dispose() {
|
|
2236
|
+
target.removeEventListener("mousemove", onMove);
|
|
2237
|
+
if (trackTouch) {
|
|
2238
|
+
target.removeEventListener("touchmove", onTouchMove);
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
return { x, y, dispose };
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
// src/browser/swipe.ts
|
|
2245
|
+
function swipe(target, options = {}) {
|
|
2246
|
+
const threshold = options.threshold ?? 50;
|
|
2247
|
+
const [direction, setDirection] = signal(null);
|
|
2248
|
+
if (typeof window === "undefined") {
|
|
2249
|
+
return { direction, dispose: () => {
|
|
2250
|
+
} };
|
|
2251
|
+
}
|
|
2252
|
+
let startX = 0;
|
|
2253
|
+
let startY = 0;
|
|
2254
|
+
let tracking = false;
|
|
2255
|
+
const onStart = (e) => {
|
|
2256
|
+
if (e.touches.length === 0) return;
|
|
2257
|
+
startX = e.touches[0].clientX;
|
|
2258
|
+
startY = e.touches[0].clientY;
|
|
2259
|
+
tracking = true;
|
|
2260
|
+
};
|
|
2261
|
+
const onEnd = (e) => {
|
|
2262
|
+
if (!tracking) return;
|
|
2263
|
+
tracking = false;
|
|
2264
|
+
const touch = e.changedTouches[0];
|
|
2265
|
+
if (!touch) return;
|
|
2266
|
+
const dx = touch.clientX - startX;
|
|
2267
|
+
const dy = touch.clientY - startY;
|
|
2268
|
+
const absX = Math.abs(dx);
|
|
2269
|
+
const absY = Math.abs(dy);
|
|
2270
|
+
if (Math.max(absX, absY) < threshold) return;
|
|
2271
|
+
let dir;
|
|
2272
|
+
if (absX > absY) {
|
|
2273
|
+
dir = dx > 0 ? "right" : "left";
|
|
2274
|
+
} else {
|
|
2275
|
+
dir = dy > 0 ? "down" : "up";
|
|
2276
|
+
}
|
|
2277
|
+
setDirection(dir);
|
|
2278
|
+
options.onSwipe?.(dir, Math.max(absX, absY));
|
|
2279
|
+
};
|
|
2280
|
+
target.addEventListener("touchstart", onStart, { passive: true });
|
|
2281
|
+
target.addEventListener("touchend", onEnd, { passive: true });
|
|
2282
|
+
function dispose() {
|
|
2283
|
+
target.removeEventListener("touchstart", onStart);
|
|
2284
|
+
target.removeEventListener("touchend", onEnd);
|
|
2285
|
+
}
|
|
2286
|
+
return { direction, dispose };
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
// src/browser/windowSize.ts
|
|
2290
|
+
function windowSize() {
|
|
2291
|
+
if (typeof window === "undefined") {
|
|
2292
|
+
const [width2] = signal(0);
|
|
2293
|
+
const [height2] = signal(0);
|
|
2294
|
+
return { width: width2, height: height2, dispose: () => {
|
|
2295
|
+
} };
|
|
2296
|
+
}
|
|
2297
|
+
const [width, setWidth] = signal(window.innerWidth);
|
|
2298
|
+
const [height, setHeight] = signal(window.innerHeight);
|
|
2299
|
+
const handler = () => {
|
|
2300
|
+
setWidth(window.innerWidth);
|
|
2301
|
+
setHeight(window.innerHeight);
|
|
2302
|
+
};
|
|
2303
|
+
window.addEventListener("resize", handler, { passive: true });
|
|
2304
|
+
function dispose() {
|
|
2305
|
+
window.removeEventListener("resize", handler);
|
|
2306
|
+
}
|
|
2307
|
+
return { width, height, dispose };
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
// src/browser/urlState.ts
|
|
2311
|
+
function urlState() {
|
|
2312
|
+
if (typeof window === "undefined") {
|
|
2313
|
+
const [params2] = signal(new URLSearchParams());
|
|
2314
|
+
const [hash2] = signal("");
|
|
2315
|
+
return {
|
|
2316
|
+
params: params2,
|
|
2317
|
+
hash: hash2,
|
|
2318
|
+
setParams: () => {
|
|
2319
|
+
},
|
|
2320
|
+
setHash: () => {
|
|
2321
|
+
},
|
|
2322
|
+
dispose: () => {
|
|
2323
|
+
}
|
|
2324
|
+
};
|
|
2325
|
+
}
|
|
2326
|
+
const [params, setParamsSignal] = signal(new URLSearchParams(window.location.search));
|
|
2327
|
+
const [hash, setHashSignal] = signal(window.location.hash);
|
|
2328
|
+
const syncFromLocation = () => {
|
|
2329
|
+
setParamsSignal(new URLSearchParams(window.location.search));
|
|
2330
|
+
setHashSignal(window.location.hash);
|
|
2331
|
+
};
|
|
2332
|
+
const onPopState = () => syncFromLocation();
|
|
2333
|
+
window.addEventListener("popstate", onPopState);
|
|
2334
|
+
function setParams(next, opts = {}) {
|
|
2335
|
+
const p2 = next instanceof URLSearchParams ? next : new URLSearchParams(next);
|
|
2336
|
+
const query2 = p2.toString();
|
|
2337
|
+
const newUrl = `${window.location.pathname}${query2 ? `?${query2}` : ""}${window.location.hash}`;
|
|
2338
|
+
if (opts.replace) window.history.replaceState(null, "", newUrl);
|
|
2339
|
+
else window.history.pushState(null, "", newUrl);
|
|
2340
|
+
setParamsSignal(new URLSearchParams(p2));
|
|
2341
|
+
}
|
|
2342
|
+
function setHash(next, opts = {}) {
|
|
2343
|
+
const normalized = next.startsWith("#") ? next : next ? `#${next}` : "";
|
|
2344
|
+
const newUrl = `${window.location.pathname}${window.location.search}${normalized}`;
|
|
2345
|
+
if (opts.replace) window.history.replaceState(null, "", newUrl);
|
|
2346
|
+
else window.history.pushState(null, "", newUrl);
|
|
2347
|
+
setHashSignal(normalized);
|
|
2348
|
+
}
|
|
2349
|
+
function dispose() {
|
|
2350
|
+
window.removeEventListener("popstate", onPopState);
|
|
2351
|
+
}
|
|
2352
|
+
return { params, hash, setParams, setHash, dispose };
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2355
|
+
// src/browser/broadcast.ts
|
|
2356
|
+
function broadcast(channelName) {
|
|
2357
|
+
if (typeof BroadcastChannel === "undefined") {
|
|
2358
|
+
const [last2] = signal(null);
|
|
2359
|
+
return { last: last2, post: () => {
|
|
2360
|
+
}, dispose: () => {
|
|
2361
|
+
} };
|
|
2362
|
+
}
|
|
2363
|
+
const [last, setLast] = signal(null);
|
|
2364
|
+
const channel = new BroadcastChannel(channelName);
|
|
2365
|
+
const handler = (ev) => setLast(ev.data);
|
|
2366
|
+
channel.addEventListener("message", handler);
|
|
2367
|
+
function post(message) {
|
|
2368
|
+
channel.postMessage(message);
|
|
2369
|
+
}
|
|
2370
|
+
function dispose() {
|
|
2371
|
+
channel.removeEventListener("message", handler);
|
|
2372
|
+
channel.close();
|
|
2373
|
+
}
|
|
2374
|
+
return { last, post, dispose };
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2377
|
+
// src/browser/fullscreen.ts
|
|
2378
|
+
function fullscreen() {
|
|
2379
|
+
if (typeof document === "undefined") {
|
|
2380
|
+
const [isFullscreen2] = signal(false);
|
|
2381
|
+
const [element2] = signal(null);
|
|
2382
|
+
return {
|
|
2383
|
+
isFullscreen: isFullscreen2,
|
|
2384
|
+
element: element2,
|
|
2385
|
+
enter: async () => {
|
|
2386
|
+
},
|
|
2387
|
+
exit: async () => {
|
|
2388
|
+
},
|
|
2389
|
+
toggle: async () => {
|
|
2390
|
+
},
|
|
2391
|
+
dispose: () => {
|
|
2392
|
+
}
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
const [isFullscreen, setIsFullscreen] = signal(!!document.fullscreenElement);
|
|
2396
|
+
const [element, setElement] = signal(document.fullscreenElement);
|
|
2397
|
+
const handler = () => {
|
|
2398
|
+
setIsFullscreen(!!document.fullscreenElement);
|
|
2399
|
+
setElement(document.fullscreenElement);
|
|
2400
|
+
};
|
|
2401
|
+
document.addEventListener("fullscreenchange", handler);
|
|
2402
|
+
async function enter(el) {
|
|
2403
|
+
if (!document.fullscreenElement && el.requestFullscreen) {
|
|
2404
|
+
await el.requestFullscreen();
|
|
2405
|
+
}
|
|
2406
|
+
}
|
|
2407
|
+
async function exit() {
|
|
2408
|
+
if (document.fullscreenElement && document.exitFullscreen) {
|
|
2409
|
+
await document.exitFullscreen();
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
async function toggle(el) {
|
|
2413
|
+
if (document.fullscreenElement) await exit();
|
|
2414
|
+
else await enter(el);
|
|
2415
|
+
}
|
|
2416
|
+
function dispose() {
|
|
2417
|
+
document.removeEventListener("fullscreenchange", handler);
|
|
2418
|
+
}
|
|
2419
|
+
return { isFullscreen, element, enter, exit, toggle, dispose };
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
// src/browser/wakeLock.ts
|
|
2423
|
+
function wakeLock() {
|
|
2424
|
+
const [active, setActive] = signal(false);
|
|
2425
|
+
if (typeof navigator === "undefined" || !("wakeLock" in navigator) || typeof document === "undefined") {
|
|
2426
|
+
return {
|
|
2427
|
+
active,
|
|
2428
|
+
request: async () => {
|
|
2429
|
+
},
|
|
2430
|
+
release: async () => {
|
|
2431
|
+
},
|
|
2432
|
+
dispose: () => {
|
|
2433
|
+
}
|
|
2434
|
+
};
|
|
2435
|
+
}
|
|
2436
|
+
const api = navigator.wakeLock;
|
|
2437
|
+
let sentinel = null;
|
|
2438
|
+
async function request() {
|
|
2439
|
+
try {
|
|
2440
|
+
sentinel = await api.request("screen");
|
|
2441
|
+
setActive(true);
|
|
2442
|
+
sentinel.addEventListener("release", () => {
|
|
2443
|
+
setActive(false);
|
|
2444
|
+
});
|
|
2445
|
+
} catch {
|
|
2446
|
+
setActive(false);
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
async function release() {
|
|
2450
|
+
if (sentinel && !sentinel.released) {
|
|
2451
|
+
await sentinel.release();
|
|
2452
|
+
}
|
|
2453
|
+
sentinel = null;
|
|
2454
|
+
setActive(false);
|
|
2455
|
+
}
|
|
2456
|
+
const onVisibility = () => {
|
|
2457
|
+
if (sentinel?.released && !document.hidden) {
|
|
2458
|
+
void request();
|
|
2459
|
+
}
|
|
2460
|
+
};
|
|
2461
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
2462
|
+
function dispose() {
|
|
2463
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
2464
|
+
void release();
|
|
2465
|
+
}
|
|
2466
|
+
return { active, request, release, dispose };
|
|
2467
|
+
}
|
|
2468
|
+
|
|
2469
|
+
// src/browser/animationFrame.ts
|
|
2470
|
+
function animationFrame(options = {}) {
|
|
2471
|
+
const [delta, setDelta] = signal(0);
|
|
2472
|
+
const [elapsed, setElapsed] = signal(0);
|
|
2473
|
+
const [running, setRunning] = signal(false);
|
|
2474
|
+
if (typeof requestAnimationFrame === "undefined") {
|
|
2475
|
+
return {
|
|
2476
|
+
delta,
|
|
2477
|
+
elapsed,
|
|
2478
|
+
running,
|
|
2479
|
+
pause: () => {
|
|
2480
|
+
},
|
|
2481
|
+
resume: () => {
|
|
2482
|
+
},
|
|
2483
|
+
dispose: () => {
|
|
2484
|
+
}
|
|
2485
|
+
};
|
|
2486
|
+
}
|
|
2487
|
+
let id = null;
|
|
2488
|
+
let prev = -1;
|
|
2489
|
+
let start = -1;
|
|
2490
|
+
const minFrameMs = options.fpsLimit ? 1e3 / options.fpsLimit : 0;
|
|
2491
|
+
const step = (now) => {
|
|
2492
|
+
if (start < 0) start = now;
|
|
2493
|
+
const firstTick = prev < 0;
|
|
2494
|
+
const dt2 = firstTick ? 0 : now - prev;
|
|
2495
|
+
if (firstTick || dt2 >= minFrameMs) {
|
|
2496
|
+
setDelta(dt2);
|
|
2497
|
+
setElapsed(now - start);
|
|
2498
|
+
prev = now;
|
|
2499
|
+
}
|
|
2500
|
+
id = requestAnimationFrame(step);
|
|
2501
|
+
};
|
|
2502
|
+
function resume() {
|
|
2503
|
+
if (id !== null) return;
|
|
2504
|
+
setRunning(true);
|
|
2505
|
+
id = requestAnimationFrame(step);
|
|
2506
|
+
}
|
|
2507
|
+
function pause() {
|
|
2508
|
+
if (id !== null) {
|
|
2509
|
+
cancelAnimationFrame(id);
|
|
2510
|
+
id = null;
|
|
2511
|
+
}
|
|
2512
|
+
setRunning(false);
|
|
2513
|
+
prev = -1;
|
|
2514
|
+
start = -1;
|
|
2515
|
+
}
|
|
2516
|
+
function dispose() {
|
|
2517
|
+
pause();
|
|
2518
|
+
}
|
|
2519
|
+
if (options.immediate !== false) resume();
|
|
2520
|
+
return { delta, elapsed, running, pause, resume, dispose };
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
// src/browser/mutationObserver.ts
|
|
2524
|
+
function mutationObserver(target, options = { childList: true, subtree: true }) {
|
|
2525
|
+
const [records, setRecords] = signal([]);
|
|
2526
|
+
if (typeof MutationObserver === "undefined") {
|
|
2527
|
+
return { records, dispose: () => {
|
|
2528
|
+
} };
|
|
2529
|
+
}
|
|
2530
|
+
const observer = new MutationObserver((batch2) => {
|
|
2531
|
+
setRecords(batch2);
|
|
2532
|
+
});
|
|
2533
|
+
observer.observe(target, options);
|
|
2534
|
+
function dispose() {
|
|
2535
|
+
observer.disconnect();
|
|
2536
|
+
}
|
|
2537
|
+
return { records, dispose };
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2540
|
+
// src/browser/bounds.ts
|
|
2541
|
+
var ZERO = {
|
|
2542
|
+
x: 0,
|
|
2543
|
+
y: 0,
|
|
2544
|
+
width: 0,
|
|
2545
|
+
height: 0,
|
|
2546
|
+
top: 0,
|
|
2547
|
+
left: 0,
|
|
2548
|
+
right: 0,
|
|
2549
|
+
bottom: 0
|
|
2550
|
+
};
|
|
2551
|
+
function readRect(el) {
|
|
2552
|
+
const r = el.getBoundingClientRect();
|
|
2553
|
+
return {
|
|
2554
|
+
x: r.x,
|
|
2555
|
+
y: r.y,
|
|
2556
|
+
width: r.width,
|
|
2557
|
+
height: r.height,
|
|
2558
|
+
top: r.top,
|
|
2559
|
+
left: r.left,
|
|
2560
|
+
right: r.right,
|
|
2561
|
+
bottom: r.bottom
|
|
2562
|
+
};
|
|
2563
|
+
}
|
|
2564
|
+
function bounds(target) {
|
|
2565
|
+
const [rect2, setRect] = signal(ZERO);
|
|
2566
|
+
if (typeof window === "undefined" || !target) {
|
|
2567
|
+
return {
|
|
2568
|
+
rect: rect2,
|
|
2569
|
+
refresh: () => {
|
|
2570
|
+
},
|
|
2571
|
+
dispose: () => {
|
|
2572
|
+
}
|
|
2573
|
+
};
|
|
2574
|
+
}
|
|
2575
|
+
function refresh() {
|
|
2576
|
+
setRect(readRect(target));
|
|
2577
|
+
}
|
|
2578
|
+
refresh();
|
|
2579
|
+
let resizeObserver = null;
|
|
2580
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
2581
|
+
resizeObserver = new ResizeObserver(refresh);
|
|
2582
|
+
resizeObserver.observe(target);
|
|
2583
|
+
}
|
|
2584
|
+
const onScroll = () => refresh();
|
|
2585
|
+
window.addEventListener("scroll", onScroll, { passive: true, capture: true });
|
|
2586
|
+
function dispose() {
|
|
2587
|
+
resizeObserver?.disconnect();
|
|
2588
|
+
window.removeEventListener("scroll", onScroll, { capture: true });
|
|
2589
|
+
}
|
|
2590
|
+
return { rect: rect2, refresh, dispose };
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2593
|
+
// src/browser/keyboard.ts
|
|
2594
|
+
function keyboard(options = {}) {
|
|
2595
|
+
const [pressed, setPressed] = signal(/* @__PURE__ */ new Set());
|
|
2596
|
+
if (typeof window === "undefined") {
|
|
2597
|
+
return {
|
|
2598
|
+
pressed,
|
|
2599
|
+
isPressed: () => false,
|
|
2600
|
+
dispose: () => {
|
|
2601
|
+
}
|
|
2602
|
+
};
|
|
2603
|
+
}
|
|
2604
|
+
const target = options.target ?? window;
|
|
2605
|
+
const filter = options.keys ? new Set(options.keys) : null;
|
|
2606
|
+
const onDown = (e) => {
|
|
2607
|
+
if (filter && !filter.has(e.key)) return;
|
|
2608
|
+
setPressed((prev) => {
|
|
2609
|
+
if (prev.has(e.key)) return prev;
|
|
2610
|
+
const next = new Set(prev);
|
|
2611
|
+
next.add(e.key);
|
|
2612
|
+
return next;
|
|
2613
|
+
});
|
|
2614
|
+
};
|
|
2615
|
+
const onUp = (e) => {
|
|
2616
|
+
if (filter && !filter.has(e.key)) return;
|
|
2617
|
+
setPressed((prev) => {
|
|
2618
|
+
if (!prev.has(e.key)) return prev;
|
|
2619
|
+
const next = new Set(prev);
|
|
2620
|
+
next.delete(e.key);
|
|
2621
|
+
return next;
|
|
2622
|
+
});
|
|
2623
|
+
};
|
|
2624
|
+
const onBlur = () => setPressed(/* @__PURE__ */ new Set());
|
|
2625
|
+
target.addEventListener("keydown", onDown);
|
|
2626
|
+
target.addEventListener("keyup", onUp);
|
|
2627
|
+
window.addEventListener("blur", onBlur);
|
|
2628
|
+
function isPressed(key) {
|
|
2629
|
+
return pressed().has(key);
|
|
2630
|
+
}
|
|
2631
|
+
function dispose() {
|
|
2632
|
+
target.removeEventListener("keydown", onDown);
|
|
2633
|
+
target.removeEventListener("keyup", onUp);
|
|
2634
|
+
window.removeEventListener("blur", onBlur);
|
|
2635
|
+
}
|
|
2636
|
+
return { pressed, isPressed, dispose };
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
// src/browser/speech.ts
|
|
2640
|
+
function speech() {
|
|
2641
|
+
const [speaking, setSpeaking] = signal(false);
|
|
2642
|
+
const [paused, setPaused] = signal(false);
|
|
2643
|
+
if (typeof window === "undefined" || typeof window.speechSynthesis === "undefined") {
|
|
2644
|
+
return {
|
|
2645
|
+
speaking,
|
|
2646
|
+
paused,
|
|
2647
|
+
speak: () => {
|
|
2648
|
+
},
|
|
2649
|
+
pause: () => {
|
|
2650
|
+
},
|
|
2651
|
+
resume: () => {
|
|
2652
|
+
},
|
|
2653
|
+
cancel: () => {
|
|
2654
|
+
},
|
|
2655
|
+
dispose: () => {
|
|
2656
|
+
}
|
|
2657
|
+
};
|
|
2658
|
+
}
|
|
2659
|
+
const synth = window.speechSynthesis;
|
|
2660
|
+
const interval = setInterval(() => {
|
|
2661
|
+
setSpeaking(synth.speaking);
|
|
2662
|
+
setPaused(synth.paused);
|
|
2663
|
+
}, 200);
|
|
2664
|
+
function speak(text2, options = {}) {
|
|
2665
|
+
const u2 = new SpeechSynthesisUtterance(text2);
|
|
2666
|
+
if (options.lang) u2.lang = options.lang;
|
|
2667
|
+
if (options.rate != null) u2.rate = options.rate;
|
|
2668
|
+
if (options.pitch != null) u2.pitch = options.pitch;
|
|
2669
|
+
if (options.volume != null) u2.volume = options.volume;
|
|
2670
|
+
if (options.voice) {
|
|
2671
|
+
const voices = synth.getVoices();
|
|
2672
|
+
const match = voices.find((v) => v.name === options.voice);
|
|
2673
|
+
if (match) u2.voice = match;
|
|
2674
|
+
}
|
|
2675
|
+
u2.addEventListener("start", () => setSpeaking(true));
|
|
2676
|
+
u2.addEventListener("end", () => {
|
|
2677
|
+
setSpeaking(false);
|
|
2678
|
+
setPaused(false);
|
|
2679
|
+
});
|
|
2680
|
+
u2.addEventListener("error", () => {
|
|
2681
|
+
setSpeaking(false);
|
|
2682
|
+
setPaused(false);
|
|
2683
|
+
});
|
|
2684
|
+
synth.speak(u2);
|
|
2685
|
+
}
|
|
2686
|
+
function dispose() {
|
|
2687
|
+
clearInterval(interval);
|
|
2688
|
+
synth.cancel();
|
|
2689
|
+
}
|
|
2690
|
+
return {
|
|
2691
|
+
speaking,
|
|
2692
|
+
paused,
|
|
2693
|
+
speak,
|
|
2694
|
+
pause: () => synth.pause(),
|
|
2695
|
+
resume: () => synth.resume(),
|
|
2696
|
+
cancel: () => synth.cancel(),
|
|
2697
|
+
dispose
|
|
2698
|
+
};
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
// src/browser/gamepad.ts
|
|
2702
|
+
function gamepad() {
|
|
2703
|
+
const [pads, setPads] = signal([]);
|
|
2704
|
+
if (typeof window === "undefined" || typeof navigator === "undefined" || typeof navigator.getGamepads !== "function") {
|
|
2705
|
+
return { pads, dispose: () => {
|
|
2706
|
+
} };
|
|
2707
|
+
}
|
|
2708
|
+
let rafId = null;
|
|
2709
|
+
function snapshot(pad) {
|
|
2710
|
+
return {
|
|
2711
|
+
index: pad.index,
|
|
2712
|
+
id: pad.id,
|
|
2713
|
+
connected: pad.connected,
|
|
2714
|
+
buttons: pad.buttons.map((b2) => ({ pressed: b2.pressed, value: b2.value })),
|
|
2715
|
+
axes: [...pad.axes]
|
|
2716
|
+
};
|
|
2717
|
+
}
|
|
2718
|
+
function equal(a2, b2) {
|
|
2719
|
+
if (a2.length !== b2.length) return false;
|
|
2720
|
+
for (let i2 = 0; i2 < a2.length; i2++) {
|
|
2721
|
+
const pa = a2[i2];
|
|
2722
|
+
const pb = b2[i2];
|
|
2723
|
+
if (pa.index !== pb.index || pa.connected !== pb.connected) return false;
|
|
2724
|
+
if (pa.buttons.length !== pb.buttons.length) return false;
|
|
2725
|
+
for (let j = 0; j < pa.buttons.length; j++) {
|
|
2726
|
+
if (pa.buttons[j].pressed !== pb.buttons[j].pressed) return false;
|
|
2727
|
+
if (pa.buttons[j].value !== pb.buttons[j].value) return false;
|
|
2728
|
+
}
|
|
2729
|
+
if (pa.axes.length !== pb.axes.length) return false;
|
|
2730
|
+
for (let j = 0; j < pa.axes.length; j++) {
|
|
2731
|
+
if (pa.axes[j] !== pb.axes[j]) return false;
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
return true;
|
|
2735
|
+
}
|
|
2736
|
+
function poll() {
|
|
2737
|
+
const raw = navigator.getGamepads();
|
|
2738
|
+
const snap = Array.from(raw).filter((g2) => g2 !== null).map(snapshot);
|
|
2739
|
+
const current = pads();
|
|
2740
|
+
if (!equal(current, snap)) setPads(snap);
|
|
2741
|
+
rafId = requestAnimationFrame(poll);
|
|
2742
|
+
}
|
|
2743
|
+
function startPolling() {
|
|
2744
|
+
if (rafId === null) poll();
|
|
2745
|
+
}
|
|
2746
|
+
function stopPolling() {
|
|
2747
|
+
if (rafId !== null) {
|
|
2748
|
+
cancelAnimationFrame(rafId);
|
|
2749
|
+
rafId = null;
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
const onConnect = () => startPolling();
|
|
2753
|
+
const onDisconnect = () => {
|
|
2754
|
+
const raw = navigator.getGamepads();
|
|
2755
|
+
const hasAny = Array.from(raw).some((g2) => g2 !== null);
|
|
2756
|
+
if (!hasAny) stopPolling();
|
|
2757
|
+
};
|
|
2758
|
+
window.addEventListener("gamepadconnected", onConnect);
|
|
2759
|
+
window.addEventListener("gamepaddisconnected", onDisconnect);
|
|
2760
|
+
const initial = Array.from(navigator.getGamepads()).some((g2) => g2 !== null);
|
|
2761
|
+
if (initial) startPolling();
|
|
2762
|
+
function dispose() {
|
|
2763
|
+
stopPolling();
|
|
2764
|
+
window.removeEventListener("gamepadconnected", onConnect);
|
|
2765
|
+
window.removeEventListener("gamepaddisconnected", onDisconnect);
|
|
2766
|
+
}
|
|
2767
|
+
return { pads, dispose };
|
|
2768
|
+
}
|
|
2769
|
+
|
|
2770
|
+
// src/browser/pointerLock.ts
|
|
2771
|
+
function pointerLock() {
|
|
2772
|
+
const [locked, setLocked] = signal(false);
|
|
2773
|
+
if (typeof document === "undefined") {
|
|
2774
|
+
return {
|
|
2775
|
+
locked,
|
|
2776
|
+
request: () => {
|
|
2777
|
+
},
|
|
2778
|
+
exit: () => {
|
|
2779
|
+
},
|
|
2780
|
+
dispose: () => {
|
|
2781
|
+
}
|
|
2782
|
+
};
|
|
2783
|
+
}
|
|
2784
|
+
const handler = () => {
|
|
2785
|
+
setLocked(!!document.pointerLockElement);
|
|
2786
|
+
};
|
|
2787
|
+
document.addEventListener("pointerlockchange", handler);
|
|
2788
|
+
function request(element) {
|
|
2789
|
+
if (typeof element.requestPointerLock === "function") {
|
|
2790
|
+
element.requestPointerLock();
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
function exit() {
|
|
2794
|
+
if (typeof document.exitPointerLock === "function") {
|
|
2795
|
+
document.exitPointerLock();
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
function dispose() {
|
|
2799
|
+
document.removeEventListener("pointerlockchange", handler);
|
|
2800
|
+
}
|
|
2801
|
+
return { locked, request, exit, dispose };
|
|
2802
|
+
}
|
|
2803
|
+
|
|
2804
|
+
// src/browser/vibrate.ts
|
|
2805
|
+
function vibrate(pattern2) {
|
|
2806
|
+
if (typeof navigator === "undefined" || typeof navigator.vibrate !== "function") {
|
|
2807
|
+
return false;
|
|
2808
|
+
}
|
|
2809
|
+
return navigator.vibrate(pattern2);
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
// src/browser/favicon.ts
|
|
2813
|
+
function favicon(url) {
|
|
2814
|
+
if (typeof document === "undefined") return;
|
|
2815
|
+
let link2 = document.querySelector("link[rel='icon']");
|
|
2816
|
+
if (!link2) {
|
|
2817
|
+
link2 = document.createElement("link");
|
|
2818
|
+
link2.rel = "icon";
|
|
2819
|
+
document.head.appendChild(link2);
|
|
2820
|
+
}
|
|
2821
|
+
link2.href = url;
|
|
2822
|
+
}
|
|
2823
|
+
function svgFavicon(svg2) {
|
|
2824
|
+
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg2)}`;
|
|
2825
|
+
}
|
|
2826
|
+
|
|
2827
|
+
// src/browser/textSelection.ts
|
|
2828
|
+
function textSelection() {
|
|
2829
|
+
const [text2, setText] = signal("");
|
|
2830
|
+
const [rect2, setRect] = signal(null);
|
|
2831
|
+
if (typeof document === "undefined") {
|
|
2832
|
+
return {
|
|
2833
|
+
text: text2,
|
|
2834
|
+
rect: rect2,
|
|
2835
|
+
hasSelection: () => false,
|
|
2836
|
+
clear: () => {
|
|
2837
|
+
},
|
|
2838
|
+
dispose: () => {
|
|
2839
|
+
}
|
|
2840
|
+
};
|
|
2841
|
+
}
|
|
2842
|
+
const handler = () => {
|
|
2843
|
+
const sel = document.getSelection();
|
|
2844
|
+
if (!sel || sel.rangeCount === 0 || sel.isCollapsed) {
|
|
2845
|
+
setText("");
|
|
2846
|
+
setRect(null);
|
|
2847
|
+
return;
|
|
2848
|
+
}
|
|
2849
|
+
setText(sel.toString());
|
|
2850
|
+
try {
|
|
2851
|
+
const r = sel.getRangeAt(0).getBoundingClientRect();
|
|
2852
|
+
setRect(r.width > 0 || r.height > 0 ? r : null);
|
|
2853
|
+
} catch {
|
|
2854
|
+
setRect(null);
|
|
2855
|
+
}
|
|
2856
|
+
};
|
|
2857
|
+
document.addEventListener("selectionchange", handler);
|
|
2858
|
+
function clear() {
|
|
2859
|
+
const sel = document.getSelection();
|
|
2860
|
+
sel?.removeAllRanges();
|
|
2861
|
+
setText("");
|
|
2862
|
+
setRect(null);
|
|
2863
|
+
}
|
|
2864
|
+
function dispose() {
|
|
2865
|
+
document.removeEventListener("selectionchange", handler);
|
|
2866
|
+
}
|
|
2867
|
+
return {
|
|
2868
|
+
text: text2,
|
|
2869
|
+
rect: rect2,
|
|
2870
|
+
hasSelection: () => text2().length > 0,
|
|
2871
|
+
clear,
|
|
2872
|
+
dispose
|
|
2873
|
+
};
|
|
2874
|
+
}
|
|
2875
|
+
|
|
2876
|
+
// src/browser/imageLoader.ts
|
|
2877
|
+
function imageLoader(src) {
|
|
2878
|
+
const [status, setStatus] = signal("pending");
|
|
2879
|
+
const [image, setImage] = signal(null);
|
|
2880
|
+
const [width, setWidth] = signal(0);
|
|
2881
|
+
const [height, setHeight] = signal(0);
|
|
2882
|
+
if (typeof Image === "undefined") {
|
|
2883
|
+
return {
|
|
2884
|
+
status,
|
|
2885
|
+
image,
|
|
2886
|
+
width,
|
|
2887
|
+
height,
|
|
2888
|
+
dispose: () => {
|
|
2889
|
+
}
|
|
2890
|
+
};
|
|
2891
|
+
}
|
|
2892
|
+
let current = null;
|
|
2893
|
+
let disposed = false;
|
|
2894
|
+
function start(url) {
|
|
2895
|
+
if (current) {
|
|
2896
|
+
current.onload = null;
|
|
2897
|
+
current.onerror = null;
|
|
2898
|
+
}
|
|
2899
|
+
setStatus("pending");
|
|
2900
|
+
setImage(null);
|
|
2901
|
+
const img2 = new Image();
|
|
2902
|
+
current = img2;
|
|
2903
|
+
img2.onload = () => {
|
|
2904
|
+
if (disposed || current !== img2) return;
|
|
2905
|
+
setImage(img2);
|
|
2906
|
+
setWidth(img2.naturalWidth);
|
|
2907
|
+
setHeight(img2.naturalHeight);
|
|
2908
|
+
setStatus("loaded");
|
|
2909
|
+
};
|
|
2910
|
+
img2.onerror = () => {
|
|
2911
|
+
if (disposed || current !== img2) return;
|
|
2912
|
+
setStatus("error");
|
|
2913
|
+
};
|
|
2914
|
+
img2.src = url;
|
|
2915
|
+
}
|
|
2916
|
+
if (typeof src === "function") {
|
|
2917
|
+
start(src());
|
|
2918
|
+
} else {
|
|
2919
|
+
start(src);
|
|
2920
|
+
}
|
|
2921
|
+
function dispose() {
|
|
2922
|
+
disposed = true;
|
|
2923
|
+
if (current) {
|
|
2924
|
+
current.onload = null;
|
|
2925
|
+
current.onerror = null;
|
|
2926
|
+
current = null;
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
return { status, image, width, height, dispose };
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2106
2932
|
// src/patterns/machine.ts
|
|
2107
2933
|
function machine(config) {
|
|
2108
2934
|
const [state, setState] = signal(config.initial);
|
|
@@ -2133,8 +2959,13 @@ function machine(config) {
|
|
|
2133
2959
|
stateDef.exit(ctx);
|
|
2134
2960
|
}
|
|
2135
2961
|
if (action) {
|
|
2136
|
-
const
|
|
2137
|
-
|
|
2962
|
+
const rawPatch = action(ctx);
|
|
2963
|
+
const next = { ...ctx };
|
|
2964
|
+
for (const key of Object.keys(rawPatch)) {
|
|
2965
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
|
2966
|
+
next[key] = rawPatch[key];
|
|
2967
|
+
}
|
|
2968
|
+
setContext(next);
|
|
2138
2969
|
}
|
|
2139
2970
|
setState(target);
|
|
2140
2971
|
const targetDef = config.states[target];
|
|
@@ -2167,6 +2998,7 @@ function persisted(key, initial, options = {}) {
|
|
|
2167
2998
|
const deserialize = options.deserialize || JSON.parse;
|
|
2168
2999
|
const encrypt = options.encrypt;
|
|
2169
3000
|
const decrypt = options.decrypt;
|
|
3001
|
+
const syncTabs = options.session ? false : options.syncTabs ?? true;
|
|
2170
3002
|
let restored = initial;
|
|
2171
3003
|
try {
|
|
2172
3004
|
let raw = storage.getItem(key);
|
|
@@ -2178,8 +3010,10 @@ function persisted(key, initial, options = {}) {
|
|
|
2178
3010
|
} catch {
|
|
2179
3011
|
}
|
|
2180
3012
|
const [value, setValue] = signal(restored);
|
|
3013
|
+
let applyingFromStorage = false;
|
|
2181
3014
|
effect(() => {
|
|
2182
3015
|
const current = value();
|
|
3016
|
+
if (applyingFromStorage) return;
|
|
2183
3017
|
try {
|
|
2184
3018
|
let serialized = serialize(current);
|
|
2185
3019
|
if (encrypt) serialized = encrypt(serialized);
|
|
@@ -2187,6 +3021,47 @@ function persisted(key, initial, options = {}) {
|
|
|
2187
3021
|
} catch {
|
|
2188
3022
|
}
|
|
2189
3023
|
});
|
|
3024
|
+
let storageListener = null;
|
|
3025
|
+
if (syncTabs && typeof window !== "undefined") {
|
|
3026
|
+
storageListener = (e) => {
|
|
3027
|
+
if (e.storageArea !== storage || e.key !== key) return;
|
|
3028
|
+
if (e.newValue === null) {
|
|
3029
|
+
applyingFromStorage = true;
|
|
3030
|
+
try {
|
|
3031
|
+
setValue(initial);
|
|
3032
|
+
} finally {
|
|
3033
|
+
applyingFromStorage = false;
|
|
3034
|
+
}
|
|
3035
|
+
return;
|
|
3036
|
+
}
|
|
3037
|
+
try {
|
|
3038
|
+
let raw = e.newValue;
|
|
3039
|
+
if (decrypt) raw = decrypt(raw);
|
|
3040
|
+
const parsed = deserialize(raw);
|
|
3041
|
+
if (options.validate && !options.validate(parsed)) return;
|
|
3042
|
+
applyingFromStorage = true;
|
|
3043
|
+
try {
|
|
3044
|
+
setValue(parsed);
|
|
3045
|
+
} finally {
|
|
3046
|
+
applyingFromStorage = false;
|
|
3047
|
+
}
|
|
3048
|
+
} catch {
|
|
3049
|
+
}
|
|
3050
|
+
};
|
|
3051
|
+
window.addEventListener("storage", storageListener);
|
|
3052
|
+
}
|
|
3053
|
+
const dispose = () => {
|
|
3054
|
+
if (storageListener && typeof window !== "undefined") {
|
|
3055
|
+
window.removeEventListener("storage", storageListener);
|
|
3056
|
+
storageListener = null;
|
|
3057
|
+
}
|
|
3058
|
+
};
|
|
3059
|
+
Object.defineProperty(setValue, "dispose", {
|
|
3060
|
+
value: dispose,
|
|
3061
|
+
enumerable: false,
|
|
3062
|
+
writable: false,
|
|
3063
|
+
configurable: false
|
|
3064
|
+
});
|
|
2190
3065
|
return [value, setValue];
|
|
2191
3066
|
}
|
|
2192
3067
|
|
|
@@ -3375,8 +4250,25 @@ function announce(message, priority = "polite") {
|
|
|
3375
4250
|
|
|
3376
4251
|
// src/ui/scopedStyle.ts
|
|
3377
4252
|
var scopeCounter = 0;
|
|
4253
|
+
function decodeCssEscapes(css) {
|
|
4254
|
+
return css.replace(/\\([0-9a-f]{1,6})[ \t\n\r\f]?|\\([^\n])/gi, (_match, hex, ch) => {
|
|
4255
|
+
if (hex) {
|
|
4256
|
+
const code2 = Number.parseInt(hex, 16);
|
|
4257
|
+
if (Number.isFinite(code2) && code2 > 0 && code2 <= 1114111) {
|
|
4258
|
+
try {
|
|
4259
|
+
return String.fromCodePoint(code2);
|
|
4260
|
+
} catch {
|
|
4261
|
+
return "";
|
|
4262
|
+
}
|
|
4263
|
+
}
|
|
4264
|
+
return "";
|
|
4265
|
+
}
|
|
4266
|
+
return ch || "";
|
|
4267
|
+
});
|
|
4268
|
+
}
|
|
3378
4269
|
function sanitizeCSS(css) {
|
|
3379
|
-
let sanitized = css
|
|
4270
|
+
let sanitized = decodeCssEscapes(css);
|
|
4271
|
+
sanitized = sanitized.replace(/@import\s+[^;]+;/gi, "/* @import removed */");
|
|
3380
4272
|
sanitized = sanitized.replace(/url\s*\(\s*(?:"[^"]*"|'[^']*'|[^)]*)\s*\)/gi, "/* url() removed */");
|
|
3381
4273
|
sanitized = sanitized.replace(/expression\s*\(\s*(?:"[^"]*"|'[^']*'|[^)]*)\s*\)/gi, "/* expression() removed */");
|
|
3382
4274
|
sanitized = sanitized.replace(/-moz-binding\s*:[^;]+;/gi, "/* -moz-binding removed */");
|
|
@@ -3426,31 +4318,22 @@ function removeScopedStyle(scopeId) {
|
|
|
3426
4318
|
if (el) el.remove();
|
|
3427
4319
|
}
|
|
3428
4320
|
|
|
3429
|
-
// src/utils/sanitize.ts
|
|
3430
|
-
function sanitizeUrl(url) {
|
|
3431
|
-
const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
|
|
3432
|
-
if (!trimmed) return "";
|
|
3433
|
-
const lower = trimmed.toLowerCase();
|
|
3434
|
-
if (lower.startsWith("javascript:") || lower.startsWith("data:") || lower.startsWith("vbscript:") || lower.startsWith("blob:")) {
|
|
3435
|
-
return "";
|
|
3436
|
-
}
|
|
3437
|
-
return trimmed;
|
|
3438
|
-
}
|
|
3439
|
-
function sanitizeCSSValue(value) {
|
|
3440
|
-
const lower = value.toLowerCase().replace(/\s+/g, "");
|
|
3441
|
-
if (lower.includes("url(") || lower.includes("expression(") || lower.includes("javascript:") || lower.includes("-moz-binding")) {
|
|
3442
|
-
return "";
|
|
3443
|
-
}
|
|
3444
|
-
return value;
|
|
3445
|
-
}
|
|
3446
|
-
var URL_ATTRIBUTES = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "cite", "poster", "background", "srcset"]);
|
|
3447
|
-
function isUrlAttribute(attr) {
|
|
3448
|
-
return URL_ATTRIBUTES.has(attr);
|
|
3449
|
-
}
|
|
3450
|
-
|
|
3451
4321
|
// src/reactivity/bindAttribute.ts
|
|
3452
4322
|
var _isDev4 = isDev();
|
|
4323
|
+
function isEventHandlerAttr(name) {
|
|
4324
|
+
if (name.length < 3) return false;
|
|
4325
|
+
const lower = name.toLowerCase();
|
|
4326
|
+
return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
|
|
4327
|
+
}
|
|
3453
4328
|
function bindAttribute(el, attr, getter) {
|
|
4329
|
+
if (isEventHandlerAttr(attr)) {
|
|
4330
|
+
if (_isDev4)
|
|
4331
|
+
devWarn(
|
|
4332
|
+
`bindAttribute: refusing to bind event-handler attribute "${attr}". Use on:{ ${attr.slice(2)}: fn } instead.`
|
|
4333
|
+
);
|
|
4334
|
+
return () => {
|
|
4335
|
+
};
|
|
4336
|
+
}
|
|
3454
4337
|
function commit() {
|
|
3455
4338
|
let value;
|
|
3456
4339
|
try {
|
|
@@ -4374,11 +5257,34 @@ function preloadModules(urls) {
|
|
|
4374
5257
|
}
|
|
4375
5258
|
|
|
4376
5259
|
// src/platform/head.ts
|
|
4377
|
-
var HEAD_URL_ATTRS = /* @__PURE__ */ new Set(["href", "src"
|
|
5260
|
+
var HEAD_URL_ATTRS = /* @__PURE__ */ new Set(["href", "src"]);
|
|
4378
5261
|
function sanitizeHeadAttr(key, value) {
|
|
4379
5262
|
if (HEAD_URL_ATTRS.has(key)) return sanitizeUrl(value);
|
|
4380
5263
|
return value;
|
|
4381
5264
|
}
|
|
5265
|
+
function isDangerousMetaRefresh(metaProps) {
|
|
5266
|
+
const httpEquiv = metaProps["http-equiv"];
|
|
5267
|
+
if (typeof httpEquiv !== "string") return false;
|
|
5268
|
+
if (httpEquiv.toLowerCase() !== "refresh") return false;
|
|
5269
|
+
const content = metaProps.content;
|
|
5270
|
+
if (typeof content !== "string") return false;
|
|
5271
|
+
const normalized = content.replace(/[\x00-\x20\x7f-\x9f]+/g, "").toLowerCase();
|
|
5272
|
+
return normalized.includes("url=javascript:") || normalized.includes("url=data:") || normalized.includes("url=vbscript:") || normalized.includes("url=blob:");
|
|
5273
|
+
}
|
|
5274
|
+
var SAFE_HEAD_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
|
|
5275
|
+
function isEventHandlerAttr2(name) {
|
|
5276
|
+
if (name.length < 3) return false;
|
|
5277
|
+
const lower = name.toLowerCase();
|
|
5278
|
+
return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
|
|
5279
|
+
}
|
|
5280
|
+
function isSafeHeadAttr(name) {
|
|
5281
|
+
if (!SAFE_HEAD_ATTR_NAME.test(name)) return false;
|
|
5282
|
+
if (isEventHandlerAttr2(name)) return false;
|
|
5283
|
+
return true;
|
|
5284
|
+
}
|
|
5285
|
+
function escapeScriptJsonLocal(json) {
|
|
5286
|
+
return json.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
5287
|
+
}
|
|
4382
5288
|
function Head(props) {
|
|
4383
5289
|
const anchor = document.createComment("sibu-head");
|
|
4384
5290
|
const managedElements = [];
|
|
@@ -4405,15 +5311,17 @@ function Head(props) {
|
|
|
4405
5311
|
}
|
|
4406
5312
|
if (props.meta) {
|
|
4407
5313
|
for (const metaProps of props.meta) {
|
|
5314
|
+
if (isDangerousMetaRefresh(metaProps)) continue;
|
|
4408
5315
|
const el = document.createElement("meta");
|
|
4409
5316
|
for (const [key, value] of Object.entries(metaProps)) {
|
|
5317
|
+
if (!isSafeHeadAttr(key)) continue;
|
|
4410
5318
|
if (typeof value === "function") {
|
|
4411
5319
|
const cleanupFn = effect(() => {
|
|
4412
|
-
el.setAttribute(key, value());
|
|
5320
|
+
el.setAttribute(key, sanitizeHeadAttr(key, value()));
|
|
4413
5321
|
});
|
|
4414
5322
|
effectCleanups.push(cleanupFn);
|
|
4415
5323
|
} else {
|
|
4416
|
-
el.setAttribute(key, value);
|
|
5324
|
+
el.setAttribute(key, sanitizeHeadAttr(key, value));
|
|
4417
5325
|
}
|
|
4418
5326
|
}
|
|
4419
5327
|
document.head.appendChild(el);
|
|
@@ -4424,6 +5332,7 @@ function Head(props) {
|
|
|
4424
5332
|
for (const linkProps of props.link) {
|
|
4425
5333
|
const el = document.createElement("link");
|
|
4426
5334
|
for (const [key, value] of Object.entries(linkProps)) {
|
|
5335
|
+
if (!isSafeHeadAttr(key)) continue;
|
|
4427
5336
|
el.setAttribute(key, sanitizeHeadAttr(key, value));
|
|
4428
5337
|
}
|
|
4429
5338
|
document.head.appendChild(el);
|
|
@@ -4434,6 +5343,7 @@ function Head(props) {
|
|
|
4434
5343
|
for (const scriptProps of props.script) {
|
|
4435
5344
|
const el = document.createElement("script");
|
|
4436
5345
|
for (const [key, value] of Object.entries(scriptProps)) {
|
|
5346
|
+
if (!isSafeHeadAttr(key)) continue;
|
|
4437
5347
|
el.setAttribute(key, sanitizeHeadAttr(key, value));
|
|
4438
5348
|
}
|
|
4439
5349
|
document.head.appendChild(el);
|
|
@@ -4444,7 +5354,10 @@ function Head(props) {
|
|
|
4444
5354
|
const existing = document.head.querySelector("base");
|
|
4445
5355
|
if (existing) existing.remove();
|
|
4446
5356
|
const el = document.createElement("base");
|
|
4447
|
-
if (props.base.href)
|
|
5357
|
+
if (props.base.href) {
|
|
5358
|
+
const safeHref = sanitizeUrl(props.base.href);
|
|
5359
|
+
if (safeHref) el.href = safeHref;
|
|
5360
|
+
}
|
|
4448
5361
|
if (props.base.target) el.target = props.base.target;
|
|
4449
5362
|
document.head.appendChild(el);
|
|
4450
5363
|
managedElements.push(el);
|
|
@@ -4459,7 +5372,7 @@ function setStructuredData(data2) {
|
|
|
4459
5372
|
const script2 = document.createElement("script");
|
|
4460
5373
|
script2.type = "application/ld+json";
|
|
4461
5374
|
script2.setAttribute("data-sibu", "true");
|
|
4462
|
-
script2.textContent = JSON.stringify(data2);
|
|
5375
|
+
script2.textContent = escapeScriptJsonLocal(JSON.stringify(data2));
|
|
4463
5376
|
document.head.appendChild(script2);
|
|
4464
5377
|
}
|
|
4465
5378
|
function setCanonical(url) {
|
|
@@ -4474,12 +5387,39 @@ function setCanonical(url) {
|
|
|
4474
5387
|
|
|
4475
5388
|
// src/platform/ssr.ts
|
|
4476
5389
|
var _isDev5 = isDev();
|
|
5390
|
+
var SAFE_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
|
|
5391
|
+
function isSafeAttrName(name) {
|
|
5392
|
+
return SAFE_ATTR_NAME.test(name);
|
|
5393
|
+
}
|
|
5394
|
+
function isEventHandlerAttr3(name) {
|
|
5395
|
+
if (name.length < 3) return false;
|
|
5396
|
+
const lower = name.toLowerCase();
|
|
5397
|
+
return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
|
|
5398
|
+
}
|
|
5399
|
+
var URL_ATTRS = /* @__PURE__ */ new Set([
|
|
5400
|
+
"href",
|
|
5401
|
+
"src",
|
|
5402
|
+
"action",
|
|
5403
|
+
"formaction",
|
|
5404
|
+
"cite",
|
|
5405
|
+
"poster",
|
|
5406
|
+
"background",
|
|
5407
|
+
"srcset",
|
|
5408
|
+
"ping",
|
|
5409
|
+
"manifest",
|
|
5410
|
+
"data",
|
|
5411
|
+
"xlink:href"
|
|
5412
|
+
]);
|
|
4477
5413
|
function ssrErrorComment(err) {
|
|
4478
5414
|
if (_isDev5) {
|
|
4479
|
-
|
|
5415
|
+
const msg = escapeHtml(err instanceof Error ? err.message : String(err));
|
|
5416
|
+
return `<!--SSR error: ${safeCommentText(msg)}-->`;
|
|
4480
5417
|
}
|
|
4481
5418
|
return "<!--SSR error-->";
|
|
4482
5419
|
}
|
|
5420
|
+
function safeCommentText(text2) {
|
|
5421
|
+
return text2.replace(/-->/g, "-->").replace(/--!>/g, "--!>").replace(/<!--/g, "<!--").replace(/--$/g, "---");
|
|
5422
|
+
}
|
|
4483
5423
|
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
4484
5424
|
"area",
|
|
4485
5425
|
"base",
|
|
@@ -4510,16 +5450,30 @@ function renderToString(element) {
|
|
|
4510
5450
|
return escapeHtml(element.textContent || "");
|
|
4511
5451
|
}
|
|
4512
5452
|
if (element.nodeType === 8) {
|
|
4513
|
-
|
|
4514
|
-
return `<!--${content}-->`;
|
|
5453
|
+
return `<!--${safeCommentText(element.textContent || "")}-->`;
|
|
4515
5454
|
}
|
|
4516
5455
|
if (!(element instanceof HTMLElement)) {
|
|
4517
|
-
return element.textContent || "";
|
|
5456
|
+
return escapeHtml(element.textContent || "");
|
|
4518
5457
|
}
|
|
4519
5458
|
const tag = element.tagName.toLowerCase();
|
|
5459
|
+
if (tag === "script" || tag === "style") {
|
|
5460
|
+
return _isDev5 ? `<!--ssr:${tag}-stripped-->` : "";
|
|
5461
|
+
}
|
|
5462
|
+
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
5463
|
+
return _isDev5 ? "<!--ssr:invalid-tag-->" : "";
|
|
5464
|
+
}
|
|
4520
5465
|
let html2 = `<${tag}`;
|
|
4521
5466
|
for (const attr of Array.from(element.attributes)) {
|
|
4522
|
-
|
|
5467
|
+
const rawName = attr.name;
|
|
5468
|
+
if (!isSafeAttrName(rawName)) continue;
|
|
5469
|
+
if (isEventHandlerAttr3(rawName)) continue;
|
|
5470
|
+
const lowerName = rawName.toLowerCase();
|
|
5471
|
+
let value = attr.value;
|
|
5472
|
+
if (URL_ATTRS.has(lowerName)) {
|
|
5473
|
+
value = sanitizeUrl(value);
|
|
5474
|
+
if (!value) continue;
|
|
5475
|
+
}
|
|
5476
|
+
html2 += ` ${rawName}="${escapeAttr(value)}"`;
|
|
4523
5477
|
}
|
|
4524
5478
|
if (element.dataset && !element.dataset.sibuHydrate) {
|
|
4525
5479
|
html2 += ` data-sibu-ssr="true"`;
|
|
@@ -4538,8 +5492,25 @@ function renderToString(element) {
|
|
|
4538
5492
|
html2 += `</${tag}>`;
|
|
4539
5493
|
return html2;
|
|
4540
5494
|
}
|
|
4541
|
-
function hydrate(component, container) {
|
|
5495
|
+
function hydrate(component, container, options = {}) {
|
|
4542
5496
|
const clientTree = component();
|
|
5497
|
+
if (options.diagnostics) {
|
|
5498
|
+
const mismatches = [];
|
|
5499
|
+
collectMismatches(container.firstElementChild, clientTree, "", mismatches);
|
|
5500
|
+
if (mismatches.length > 0) {
|
|
5501
|
+
const first = mismatches[0];
|
|
5502
|
+
if (options.onMismatch) {
|
|
5503
|
+
options.onMismatch(first);
|
|
5504
|
+
} else if (_isDev5) {
|
|
5505
|
+
console.warn(
|
|
5506
|
+
`[Sibu hydration] ${first.message}
|
|
5507
|
+
at ${first.path}
|
|
5508
|
+
server: ${first.serverValue}
|
|
5509
|
+
client: ${first.clientValue}`
|
|
5510
|
+
);
|
|
5511
|
+
}
|
|
5512
|
+
}
|
|
5513
|
+
}
|
|
4543
5514
|
hydrateNode(container.firstElementChild, clientTree);
|
|
4544
5515
|
container.setAttribute("data-sibu-hydrated", "true");
|
|
4545
5516
|
}
|
|
@@ -4551,9 +5522,119 @@ function hydrateNode(serverNode, clientNode) {
|
|
|
4551
5522
|
hydrateNode(serverChildren[i2], clientChildren[i2]);
|
|
4552
5523
|
}
|
|
4553
5524
|
}
|
|
5525
|
+
function collectMismatches(serverNode, clientNode, path2, out, max2 = 5) {
|
|
5526
|
+
if (out.length >= max2) return;
|
|
5527
|
+
const nodePath = path2 || clientNode?.tagName?.toLowerCase() || "(root)";
|
|
5528
|
+
if (!serverNode && clientNode) {
|
|
5529
|
+
out.push({
|
|
5530
|
+
kind: "child-count",
|
|
5531
|
+
path: nodePath,
|
|
5532
|
+
serverValue: "(missing)",
|
|
5533
|
+
clientValue: clientNode.tagName.toLowerCase(),
|
|
5534
|
+
message: "Client rendered a node that the server did not emit."
|
|
5535
|
+
});
|
|
5536
|
+
return;
|
|
5537
|
+
}
|
|
5538
|
+
if (serverNode && !clientNode) {
|
|
5539
|
+
out.push({
|
|
5540
|
+
kind: "child-count",
|
|
5541
|
+
path: nodePath,
|
|
5542
|
+
serverValue: serverNode.tagName.toLowerCase(),
|
|
5543
|
+
clientValue: "(missing)",
|
|
5544
|
+
message: "Server rendered a node that the client did not produce."
|
|
5545
|
+
});
|
|
5546
|
+
return;
|
|
5547
|
+
}
|
|
5548
|
+
if (!serverNode || !clientNode) return;
|
|
5549
|
+
if (serverNode.tagName !== clientNode.tagName) {
|
|
5550
|
+
out.push({
|
|
5551
|
+
kind: "tag",
|
|
5552
|
+
path: nodePath,
|
|
5553
|
+
serverValue: serverNode.tagName.toLowerCase(),
|
|
5554
|
+
clientValue: clientNode.tagName.toLowerCase(),
|
|
5555
|
+
message: "Element tag mismatch \u2014 server and client disagree on the element type."
|
|
5556
|
+
});
|
|
5557
|
+
return;
|
|
5558
|
+
}
|
|
5559
|
+
const skipAttrs = /* @__PURE__ */ new Set(["data-sibu-ssr", "data-sibu-hydrated", "data-sibu-island"]);
|
|
5560
|
+
const serverAttrs = /* @__PURE__ */ new Map();
|
|
5561
|
+
for (const a2 of Array.from(serverNode.attributes)) {
|
|
5562
|
+
if (!skipAttrs.has(a2.name)) serverAttrs.set(a2.name, a2.value);
|
|
5563
|
+
}
|
|
5564
|
+
const clientAttrs = /* @__PURE__ */ new Map();
|
|
5565
|
+
for (const a2 of Array.from(clientNode.attributes)) {
|
|
5566
|
+
if (!skipAttrs.has(a2.name)) clientAttrs.set(a2.name, a2.value);
|
|
5567
|
+
}
|
|
5568
|
+
for (const [name, value] of serverAttrs) {
|
|
5569
|
+
if (out.length >= max2) return;
|
|
5570
|
+
if (!clientAttrs.has(name)) {
|
|
5571
|
+
out.push({
|
|
5572
|
+
kind: "attribute",
|
|
5573
|
+
path: `${nodePath}[${name}]`,
|
|
5574
|
+
serverValue: value,
|
|
5575
|
+
clientValue: "(missing)",
|
|
5576
|
+
message: `Attribute "${name}" present on server but missing on client.`
|
|
5577
|
+
});
|
|
5578
|
+
} else if (clientAttrs.get(name) !== value) {
|
|
5579
|
+
out.push({
|
|
5580
|
+
kind: "attribute",
|
|
5581
|
+
path: `${nodePath}[${name}]`,
|
|
5582
|
+
serverValue: value,
|
|
5583
|
+
clientValue: clientAttrs.get(name) ?? "",
|
|
5584
|
+
message: `Attribute "${name}" differs between server and client.`
|
|
5585
|
+
});
|
|
5586
|
+
}
|
|
5587
|
+
}
|
|
5588
|
+
for (const [name, value] of clientAttrs) {
|
|
5589
|
+
if (out.length >= max2) return;
|
|
5590
|
+
if (!serverAttrs.has(name)) {
|
|
5591
|
+
out.push({
|
|
5592
|
+
kind: "attribute",
|
|
5593
|
+
path: `${nodePath}[${name}]`,
|
|
5594
|
+
serverValue: "(missing)",
|
|
5595
|
+
clientValue: value,
|
|
5596
|
+
message: `Attribute "${name}" present on client but missing on server.`
|
|
5597
|
+
});
|
|
5598
|
+
}
|
|
5599
|
+
}
|
|
5600
|
+
const serverChildren = Array.from(serverNode.children);
|
|
5601
|
+
const clientChildren = Array.from(clientNode.children);
|
|
5602
|
+
const max22 = Math.max(serverChildren.length, clientChildren.length);
|
|
5603
|
+
for (let i2 = 0; i2 < max22; i2++) {
|
|
5604
|
+
if (out.length >= max2) return;
|
|
5605
|
+
const childPath = `${nodePath} > ${clientChildren[i2]?.tagName?.toLowerCase() ?? serverChildren[i2]?.tagName?.toLowerCase() ?? "?"}:nth-child(${i2 + 1})`;
|
|
5606
|
+
collectMismatches(serverChildren[i2] ?? null, clientChildren[i2] ?? null, childPath, out, max2);
|
|
5607
|
+
}
|
|
5608
|
+
}
|
|
4554
5609
|
function trustHTML(html2) {
|
|
4555
5610
|
return html2;
|
|
4556
5611
|
}
|
|
5612
|
+
function buildAttrString(attrs, { allowEventHandlers = false } = {}) {
|
|
5613
|
+
if (!attrs) return "";
|
|
5614
|
+
const out = [];
|
|
5615
|
+
for (const rawKey of Object.keys(attrs)) {
|
|
5616
|
+
if (!Object.hasOwn(attrs, rawKey)) continue;
|
|
5617
|
+
if (!isSafeAttrName(rawKey)) continue;
|
|
5618
|
+
if (!allowEventHandlers && isEventHandlerAttr3(rawKey)) continue;
|
|
5619
|
+
const lowerKey = rawKey.toLowerCase();
|
|
5620
|
+
let value = String(attrs[rawKey]);
|
|
5621
|
+
if (URL_ATTRS.has(lowerKey)) {
|
|
5622
|
+
value = sanitizeUrl(value);
|
|
5623
|
+
if (!value) continue;
|
|
5624
|
+
}
|
|
5625
|
+
out.push(`${rawKey}="${escapeAttr(value)}"`);
|
|
5626
|
+
}
|
|
5627
|
+
return out.join(" ");
|
|
5628
|
+
}
|
|
5629
|
+
function isDangerousMetaRefresh2(metaProps) {
|
|
5630
|
+
const httpEquiv = metaProps["http-equiv"];
|
|
5631
|
+
if (typeof httpEquiv !== "string") return false;
|
|
5632
|
+
if (httpEquiv.toLowerCase() !== "refresh") return false;
|
|
5633
|
+
const content = metaProps.content;
|
|
5634
|
+
if (typeof content !== "string") return false;
|
|
5635
|
+
const normalized = content.replace(/[\x00-\x20\x7f-\x9f]+/g, "").toLowerCase();
|
|
5636
|
+
return normalized.includes("url=javascript:") || normalized.includes("url=data:") || normalized.includes("url=vbscript:") || normalized.includes("url=blob:");
|
|
5637
|
+
}
|
|
4557
5638
|
function renderToDocument(component, options = {}) {
|
|
4558
5639
|
let content;
|
|
4559
5640
|
try {
|
|
@@ -4561,14 +5642,22 @@ function renderToDocument(component, options = {}) {
|
|
|
4561
5642
|
} catch (err) {
|
|
4562
5643
|
content = ssrErrorComment(err);
|
|
4563
5644
|
}
|
|
4564
|
-
const metaTags = (options.meta || []).map(
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
).
|
|
4570
|
-
|
|
4571
|
-
|
|
5645
|
+
const metaTags = (options.meta || []).map((attrs) => {
|
|
5646
|
+
if (isDangerousMetaRefresh2(attrs)) return "";
|
|
5647
|
+
const pairs = buildAttrString(attrs);
|
|
5648
|
+
return pairs ? `<meta ${pairs} />` : "";
|
|
5649
|
+
}).filter(Boolean).join("\n ");
|
|
5650
|
+
const linkTags = (options.links || []).map((attrs) => {
|
|
5651
|
+
const pairs = buildAttrString(attrs);
|
|
5652
|
+
return pairs ? `<link ${pairs} />` : "";
|
|
5653
|
+
}).filter(Boolean).join("\n ");
|
|
5654
|
+
const scriptTags = (options.scripts || []).map((src) => {
|
|
5655
|
+
const safe = sanitizeUrl(String(src));
|
|
5656
|
+
if (!safe) return "";
|
|
5657
|
+
return `<script src="${escapeAttr(safe)}"></script>`;
|
|
5658
|
+
}).filter(Boolean).join("\n ");
|
|
5659
|
+
const bodyAttrPairs = buildAttrString(options.bodyAttrs);
|
|
5660
|
+
const bodyAttrs = bodyAttrPairs ? ` ${bodyAttrPairs}` : "";
|
|
4572
5661
|
return `<!DOCTYPE html>
|
|
4573
5662
|
<html>
|
|
4574
5663
|
<head>
|
|
@@ -4601,18 +5690,34 @@ async function* renderToStream(element) {
|
|
|
4601
5690
|
return;
|
|
4602
5691
|
}
|
|
4603
5692
|
if (element.nodeType === 8) {
|
|
4604
|
-
|
|
4605
|
-
yield `<!--${content}-->`;
|
|
5693
|
+
yield `<!--${safeCommentText(element.textContent || "")}-->`;
|
|
4606
5694
|
return;
|
|
4607
5695
|
}
|
|
4608
5696
|
if (!(element instanceof HTMLElement)) {
|
|
4609
|
-
yield element.textContent || "";
|
|
5697
|
+
yield escapeHtml(element.textContent || "");
|
|
4610
5698
|
return;
|
|
4611
5699
|
}
|
|
4612
5700
|
const tag = element.tagName.toLowerCase();
|
|
5701
|
+
if (tag === "script" || tag === "style") {
|
|
5702
|
+
if (_isDev5) yield `<!--ssr:${tag}-stripped-->`;
|
|
5703
|
+
return;
|
|
5704
|
+
}
|
|
5705
|
+
if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
|
|
5706
|
+
if (_isDev5) yield "<!--ssr:invalid-tag-->";
|
|
5707
|
+
return;
|
|
5708
|
+
}
|
|
4613
5709
|
let openTag = `<${tag}`;
|
|
4614
5710
|
for (const attr of Array.from(element.attributes)) {
|
|
4615
|
-
|
|
5711
|
+
const rawName = attr.name;
|
|
5712
|
+
if (!isSafeAttrName(rawName)) continue;
|
|
5713
|
+
if (isEventHandlerAttr3(rawName)) continue;
|
|
5714
|
+
const lowerName = rawName.toLowerCase();
|
|
5715
|
+
let value = attr.value;
|
|
5716
|
+
if (URL_ATTRS.has(lowerName)) {
|
|
5717
|
+
value = sanitizeUrl(value);
|
|
5718
|
+
if (!value) continue;
|
|
5719
|
+
}
|
|
5720
|
+
openTag += ` ${rawName}="${escapeAttr(value)}"`;
|
|
4616
5721
|
}
|
|
4617
5722
|
if (VOID_ELEMENTS.has(tag)) {
|
|
4618
5723
|
yield `${openTag} />`;
|
|
@@ -4660,8 +5765,9 @@ function hydrateIslands(container, islands) {
|
|
|
4660
5765
|
const markers = container.querySelectorAll("[data-sibu-island]");
|
|
4661
5766
|
for (const marker2 of Array.from(markers)) {
|
|
4662
5767
|
const id = marker2.getAttribute("data-sibu-island") ?? "";
|
|
5768
|
+
if (!Object.hasOwn(islands, id)) continue;
|
|
4663
5769
|
const factory = islands[id];
|
|
4664
|
-
if (
|
|
5770
|
+
if (typeof factory !== "function") continue;
|
|
4665
5771
|
const clientTree = factory();
|
|
4666
5772
|
hydrateNode(marker2, clientTree);
|
|
4667
5773
|
marker2.setAttribute("data-sibu-hydrated", "true");
|
|
@@ -4673,8 +5779,9 @@ function hydrateProgressively(container, islands, options) {
|
|
|
4673
5779
|
const cleanups = [];
|
|
4674
5780
|
for (const marker2 of Array.from(markers)) {
|
|
4675
5781
|
const id = marker2.getAttribute("data-sibu-island") ?? "";
|
|
5782
|
+
if (!Object.hasOwn(islands, id)) continue;
|
|
4676
5783
|
const factory = islands[id];
|
|
4677
|
-
if (
|
|
5784
|
+
if (typeof factory !== "function") continue;
|
|
4678
5785
|
const observer = new IntersectionObserver(
|
|
4679
5786
|
(entries) => {
|
|
4680
5787
|
for (const entry of entries) {
|
|
@@ -4713,24 +5820,33 @@ function ssrSuspense(props) {
|
|
|
4713
5820
|
}));
|
|
4714
5821
|
return { element: wrapper, promise };
|
|
4715
5822
|
}
|
|
5823
|
+
var SAFE_SUSPENSE_ID = /^[A-Za-z0-9_-]+$/;
|
|
4716
5824
|
function suspenseSwapScript(id, nonce) {
|
|
4717
|
-
|
|
5825
|
+
if (!SAFE_SUSPENSE_ID.test(id)) {
|
|
5826
|
+
throw new Error(
|
|
5827
|
+
`[SibuJS SSR] suspenseSwapScript: id must match [A-Za-z0-9_-]+ (got: ${JSON.stringify(id.slice(0, 32))})`
|
|
5828
|
+
);
|
|
5829
|
+
}
|
|
4718
5830
|
const nonceAttr = nonce ? ` nonce="${escapeAttr(nonce)}"` : "";
|
|
4719
|
-
return `<script${nonceAttr}>(function(){var t=document.getElementById("sibu-resolved-${
|
|
5831
|
+
return `<script${nonceAttr}>(function(){var t=document.getElementById("sibu-resolved-${id}");var f=document.querySelector('[data-sibu-suspense-id="${id}"]');if(t&&f){while(t.firstChild)f.appendChild(t.firstChild);t.remove();f.removeAttribute("data-sibu-suspense-id");}})()</script>`;
|
|
4720
5832
|
}
|
|
4721
|
-
async function* renderToSuspenseStream(element, pendingBoundaries = []) {
|
|
5833
|
+
async function* renderToSuspenseStream(element, pendingBoundaries = [], options) {
|
|
4722
5834
|
yield* renderToStream(element);
|
|
4723
5835
|
if (pendingBoundaries.length > 0) {
|
|
4724
5836
|
const resolved = await Promise.all(pendingBoundaries);
|
|
4725
5837
|
for (const { id, html: html2 } of resolved) {
|
|
4726
|
-
|
|
4727
|
-
yield
|
|
5838
|
+
if (!SAFE_SUSPENSE_ID.test(id)) continue;
|
|
5839
|
+
yield `<div hidden id="sibu-resolved-${id}">${html2}</div>`;
|
|
5840
|
+
yield suspenseSwapScript(id, options?.nonce);
|
|
4728
5841
|
}
|
|
4729
5842
|
}
|
|
4730
5843
|
}
|
|
4731
5844
|
var SSR_DATA_ATTR = "__SIBU_SSR_DATA__";
|
|
5845
|
+
function escapeScriptJson(json) {
|
|
5846
|
+
return json.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
5847
|
+
}
|
|
4732
5848
|
function serializeState(state, nonce) {
|
|
4733
|
-
const json = JSON.stringify(state)
|
|
5849
|
+
const json = escapeScriptJson(JSON.stringify(state));
|
|
4734
5850
|
const nonceAttr = nonce ? ` nonce="${escapeAttr(nonce)}"` : "";
|
|
4735
5851
|
return `<script${nonceAttr}>window.${SSR_DATA_ATTR}=${json}</script>`;
|
|
4736
5852
|
}
|
|
@@ -4745,7 +5861,7 @@ function escapeHtml(str) {
|
|
|
4745
5861
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
4746
5862
|
}
|
|
4747
5863
|
function escapeAttr(str) {
|
|
4748
|
-
return str.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
5864
|
+
return str.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
4749
5865
|
}
|
|
4750
5866
|
|
|
4751
5867
|
// src/platform/customElement.ts
|
|
@@ -5100,11 +6216,11 @@ function bindChildNode(placeholder, getter) {
|
|
|
5100
6216
|
if (_isDev6) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
5101
6217
|
return;
|
|
5102
6218
|
}
|
|
5103
|
-
for (let i2 = 0; i2 < lastNodes.length; i2++) {
|
|
5104
|
-
const node = lastNodes[i2];
|
|
5105
|
-
if (node.parentNode) node.parentNode.removeChild(node);
|
|
5106
|
-
}
|
|
5107
6219
|
if (result == null || typeof result === "boolean") {
|
|
6220
|
+
for (let i2 = 0; i2 < lastNodes.length; i2++) {
|
|
6221
|
+
const node = lastNodes[i2];
|
|
6222
|
+
if (node.parentNode) node.parentNode.removeChild(node);
|
|
6223
|
+
}
|
|
5108
6224
|
lastNodes.length = 0;
|
|
5109
6225
|
return;
|
|
5110
6226
|
}
|
|
@@ -5113,24 +6229,46 @@ function bindChildNode(placeholder, getter) {
|
|
|
5113
6229
|
lastNodes.length = 0;
|
|
5114
6230
|
return;
|
|
5115
6231
|
}
|
|
5116
|
-
|
|
5117
|
-
let count = 0;
|
|
6232
|
+
let newNodes;
|
|
5118
6233
|
if (Array.isArray(result)) {
|
|
5119
|
-
|
|
6234
|
+
newNodes = [];
|
|
5120
6235
|
for (let i2 = 0; i2 < result.length; i2++) {
|
|
5121
6236
|
const item = result[i2];
|
|
5122
6237
|
if (item == null || typeof item === "boolean") continue;
|
|
5123
|
-
|
|
5124
|
-
parent.insertBefore(node, anchor);
|
|
5125
|
-
lastNodes[count++] = node;
|
|
6238
|
+
newNodes.push(item instanceof Node ? item : document.createTextNode(String(item)));
|
|
5126
6239
|
}
|
|
5127
6240
|
} else {
|
|
5128
|
-
if (lastNodes.length < 1) lastNodes = [null];
|
|
5129
6241
|
const node = result instanceof Node ? result : document.createTextNode(String(result));
|
|
5130
|
-
|
|
5131
|
-
|
|
6242
|
+
newNodes = [node];
|
|
6243
|
+
}
|
|
6244
|
+
const reused = lastNodes.length > 0 && newNodes.length > 0 ? /* @__PURE__ */ new Set() : void 0;
|
|
6245
|
+
if (reused) {
|
|
6246
|
+
for (let i2 = 0; i2 < newNodes.length; i2++) {
|
|
6247
|
+
for (let j = 0; j < lastNodes.length; j++) {
|
|
6248
|
+
if (newNodes[i2] === lastNodes[j]) {
|
|
6249
|
+
reused.add(newNodes[i2]);
|
|
6250
|
+
break;
|
|
6251
|
+
}
|
|
6252
|
+
}
|
|
6253
|
+
}
|
|
6254
|
+
}
|
|
6255
|
+
for (let i2 = 0; i2 < lastNodes.length; i2++) {
|
|
6256
|
+
const node = lastNodes[i2];
|
|
6257
|
+
if (reused?.has(node)) continue;
|
|
6258
|
+
if (node.parentNode) node.parentNode.removeChild(node);
|
|
5132
6259
|
}
|
|
5133
|
-
|
|
6260
|
+
const anchor = placeholder.nextSibling;
|
|
6261
|
+
for (let i2 = 0; i2 < newNodes.length; i2++) {
|
|
6262
|
+
const node = newNodes[i2];
|
|
6263
|
+
if (reused?.has(node) && node.parentNode === parent) {
|
|
6264
|
+
if (node.nextSibling !== anchor) {
|
|
6265
|
+
parent.insertBefore(node, anchor);
|
|
6266
|
+
}
|
|
6267
|
+
} else {
|
|
6268
|
+
parent.insertBefore(node, anchor);
|
|
6269
|
+
}
|
|
6270
|
+
}
|
|
6271
|
+
lastNodes = newNodes;
|
|
5134
6272
|
}
|
|
5135
6273
|
return track(commit);
|
|
5136
6274
|
}
|
|
@@ -5278,16 +6416,20 @@ function appendChildren(el, nodes) {
|
|
|
5278
6416
|
var tagFactory = (tag, ns) => (first, second) => {
|
|
5279
6417
|
const el = ns ? document.createElementNS(ns, tag) : document.createElement(tag);
|
|
5280
6418
|
if (first === void 0) return el;
|
|
5281
|
-
if (
|
|
6419
|
+
if (typeof first === "string") {
|
|
6420
|
+
if (second !== void 0) {
|
|
6421
|
+
el.setAttribute("class", first);
|
|
6422
|
+
appendChildren(el, second);
|
|
6423
|
+
return el;
|
|
6424
|
+
}
|
|
5282
6425
|
el.textContent = first;
|
|
5283
6426
|
return el;
|
|
5284
6427
|
}
|
|
5285
|
-
if (
|
|
5286
|
-
el.
|
|
5287
|
-
appendChildren(el, second);
|
|
6428
|
+
if (typeof first === "number") {
|
|
6429
|
+
el.textContent = String(first);
|
|
5288
6430
|
return el;
|
|
5289
6431
|
}
|
|
5290
|
-
if (Array.isArray(first) || first instanceof Node) {
|
|
6432
|
+
if (Array.isArray(first) || first instanceof Node || typeof first === "function") {
|
|
5291
6433
|
appendChildren(el, first);
|
|
5292
6434
|
return el;
|
|
5293
6435
|
}
|
|
@@ -5296,7 +6438,7 @@ var tagFactory = (tag, ns) => (first, second) => {
|
|
|
5296
6438
|
if (pClass != null) applyClass(el, pClass);
|
|
5297
6439
|
const pId = props.id;
|
|
5298
6440
|
if (pId != null) el.id = pId;
|
|
5299
|
-
const pNodes = props.nodes;
|
|
6441
|
+
const pNodes = second !== void 0 ? second : props.nodes;
|
|
5300
6442
|
if (pNodes != null) appendChildren(el, pNodes);
|
|
5301
6443
|
const pOn = props.on;
|
|
5302
6444
|
if (pOn) {
|
|
@@ -5321,12 +6463,18 @@ var tagFactory = (tag, ns) => (first, second) => {
|
|
|
5321
6463
|
// already handled above / below
|
|
5322
6464
|
default: {
|
|
5323
6465
|
const value = props[key];
|
|
5324
|
-
if (value == null
|
|
6466
|
+
if (value == null) continue;
|
|
5325
6467
|
if (key[0] === "o" && key[1] === "n") continue;
|
|
5326
6468
|
if (typeof value === "function") {
|
|
5327
6469
|
registerDisposer(el, bindAttribute(el, key, value));
|
|
5328
|
-
} else if (value ===
|
|
5329
|
-
el
|
|
6470
|
+
} else if (typeof value === "boolean") {
|
|
6471
|
+
if (key in el && (key === "checked" || key === "disabled" || key === "selected")) {
|
|
6472
|
+
el[key] = value;
|
|
6473
|
+
} else if (value) {
|
|
6474
|
+
el.setAttribute(key, "");
|
|
6475
|
+
} else {
|
|
6476
|
+
el.removeAttribute(key);
|
|
6477
|
+
}
|
|
5330
6478
|
} else {
|
|
5331
6479
|
const str = String(value);
|
|
5332
6480
|
el.setAttribute(key, isUrlAttribute(key) ? sanitizeUrl(str) : str);
|
|
@@ -8591,6 +9739,7 @@ var materialAdapter = componentAdapter(materialConfig);
|
|
|
8591
9739
|
VirtualList,
|
|
8592
9740
|
accordion,
|
|
8593
9741
|
animate,
|
|
9742
|
+
animationFrame,
|
|
8594
9743
|
announce,
|
|
8595
9744
|
antdAdapter,
|
|
8596
9745
|
aria,
|
|
@@ -8603,6 +9752,8 @@ var materialAdapter = componentAdapter(materialConfig);
|
|
|
8603
9752
|
block,
|
|
8604
9753
|
bounceIn,
|
|
8605
9754
|
bounceOut,
|
|
9755
|
+
bounds,
|
|
9756
|
+
broadcast,
|
|
8606
9757
|
bundlerMetadata,
|
|
8607
9758
|
calculateDelay,
|
|
8608
9759
|
chakraAdapter,
|
|
@@ -8676,10 +9827,12 @@ var materialAdapter = componentAdapter(materialConfig);
|
|
|
8676
9827
|
email,
|
|
8677
9828
|
enableDebug,
|
|
8678
9829
|
env,
|
|
9830
|
+
escapeScriptJson,
|
|
8679
9831
|
eventBus,
|
|
8680
9832
|
executeLoader,
|
|
8681
9833
|
fadeIn,
|
|
8682
9834
|
fadeOut,
|
|
9835
|
+
favicon,
|
|
8683
9836
|
fileUpload,
|
|
8684
9837
|
flipIn,
|
|
8685
9838
|
flushScheduler,
|
|
@@ -8688,6 +9841,8 @@ var materialAdapter = componentAdapter(materialConfig);
|
|
|
8688
9841
|
formatCurrency,
|
|
8689
9842
|
formatError,
|
|
8690
9843
|
formatNumber,
|
|
9844
|
+
fullscreen,
|
|
9845
|
+
gamepad,
|
|
8691
9846
|
generateStaticSite,
|
|
8692
9847
|
geo,
|
|
8693
9848
|
getActiveDevTools,
|
|
@@ -8706,6 +9861,7 @@ var materialAdapter = componentAdapter(materialConfig);
|
|
|
8706
9861
|
hydrateIslands,
|
|
8707
9862
|
hydrateProgressively,
|
|
8708
9863
|
idle,
|
|
9864
|
+
imageLoader,
|
|
8709
9865
|
infiniteQuery,
|
|
8710
9866
|
infiniteScroll,
|
|
8711
9867
|
initDevTools,
|
|
@@ -8718,6 +9874,7 @@ var materialAdapter = componentAdapter(materialConfig);
|
|
|
8718
9874
|
isHMRAvailable,
|
|
8719
9875
|
isWasmCached,
|
|
8720
9876
|
island,
|
|
9877
|
+
keyboard,
|
|
8721
9878
|
lazyChunk,
|
|
8722
9879
|
lazyLoad,
|
|
8723
9880
|
lazyModule,
|
|
@@ -8734,7 +9891,10 @@ var materialAdapter = componentAdapter(materialConfig);
|
|
|
8734
9891
|
min,
|
|
8735
9892
|
minLength,
|
|
8736
9893
|
mobXAdapter,
|
|
9894
|
+
mouse,
|
|
8737
9895
|
mutation,
|
|
9896
|
+
mutationObserver,
|
|
9897
|
+
network,
|
|
8738
9898
|
noSideEffect,
|
|
8739
9899
|
normalize,
|
|
8740
9900
|
normalizedStore,
|
|
@@ -8751,6 +9911,7 @@ var materialAdapter = componentAdapter(materialConfig);
|
|
|
8751
9911
|
persisted,
|
|
8752
9912
|
phoneMask,
|
|
8753
9913
|
plugin,
|
|
9914
|
+
pointerLock,
|
|
8754
9915
|
popover,
|
|
8755
9916
|
precompile,
|
|
8756
9917
|
prefetch,
|
|
@@ -8802,6 +9963,7 @@ var materialAdapter = componentAdapter(materialConfig);
|
|
|
8802
9963
|
slideIn,
|
|
8803
9964
|
slideOut,
|
|
8804
9965
|
socket,
|
|
9966
|
+
speech,
|
|
8805
9967
|
spring,
|
|
8806
9968
|
springSignal,
|
|
8807
9969
|
ssnMask,
|
|
@@ -8813,8 +9975,11 @@ var materialAdapter = componentAdapter(materialConfig);
|
|
|
8813
9975
|
stream,
|
|
8814
9976
|
suspenseSwapScript,
|
|
8815
9977
|
svgElement,
|
|
9978
|
+
svgFavicon,
|
|
9979
|
+
swipe,
|
|
8816
9980
|
syncAdapter,
|
|
8817
9981
|
tabs,
|
|
9982
|
+
textSelection,
|
|
8818
9983
|
throttle,
|
|
8819
9984
|
timeMask,
|
|
8820
9985
|
timeline,
|
|
@@ -8829,11 +9994,16 @@ var materialAdapter = componentAdapter(materialConfig);
|
|
|
8829
9994
|
triggerPluginUnmount,
|
|
8830
9995
|
trustHTML,
|
|
8831
9996
|
uniqueId,
|
|
9997
|
+
urlState,
|
|
8832
9998
|
validateProps,
|
|
8833
9999
|
validators,
|
|
10000
|
+
vibrate,
|
|
8834
10001
|
viewTransition,
|
|
10002
|
+
visibility,
|
|
10003
|
+
wakeLock,
|
|
8835
10004
|
walkDependencyGraph,
|
|
8836
10005
|
wasm,
|
|
10006
|
+
windowSize,
|
|
8837
10007
|
withBoundary,
|
|
8838
10008
|
withDefaults,
|
|
8839
10009
|
withErrorTracking,
|