@tanstack/start-client-core
Advanced tools
| export { condition } from './hydration/condition.js'; | ||
| export type { HydrationCondition } from './hydration/condition.js'; | ||
| export { hydrateIdAttribute, hydrateInteractionEventsAttribute, hydrateWhenAttribute, } from './hydration/constants.js'; | ||
| export declare const hydrateIdSelector = "[data-ts-hydrate-id]"; | ||
| export { idle } from './hydration/idle.js'; | ||
| export type { IdleHydrationOptions } from './hydration/idle.js'; | ||
| export { interaction } from './hydration/interaction.js'; | ||
| export { load } from './hydration/load.js'; | ||
| export { media } from './hydration/media.js'; | ||
| export { never } from './hydration/never.js'; | ||
| export { clearResolvedGateIdsInMarker, createResolvedGate, getFallbackHtml, getMarkerGate, getOrCreateGate, onGateResolve, releaseGate, resolveHydrationMarker, runHydrationStrategyCleanup, saveFallbackHtml, waitForHydrationPrefetchStrategy, } from './hydration/runtime.js'; | ||
| export { withHydrationRenderer } from './hydration/renderer.js'; | ||
| export { visible } from './hydration/visible.js'; | ||
| export { listenForDelegatedHydrationIntent } from './hydration/interaction.js'; | ||
| export type { VisibleHydrationOptions } from './hydration/visible.js'; | ||
| export type { HydrationGateRecord } from './hydration/runtime.js'; | ||
| export type { HydrationStrategyWithRenderer } from './hydration/renderer.js'; | ||
| export type { HydrationInteractionEvent, HydrationInteractionEvents, HydrationMarkerAttributes, HydrationPrefetchContext, HydrationPrefetchFunction, HydrationPrefetchWhen, HydrationPrefetchStrategy, HydrationPrefetchWaitReason, HydrationRuntimeContext, HydrationRuntimeGate, HydrationStrategy, HydrationStrategyTypes, HydrationWhen, } from './hydration/types.js'; |
| import { hydrateIdAttribute, hydrateInteractionEventsAttribute, hydrateWhenAttribute } from "./hydration/constants.js"; | ||
| import { condition } from "./hydration/condition.js"; | ||
| import { idle } from "./hydration/idle.js"; | ||
| import { clearResolvedGateIdsInMarker, createResolvedGate, getFallbackHtml, getMarkerGate, getOrCreateGate, onGateResolve, releaseGate, resolveHydrationMarker, runHydrationStrategyCleanup, saveFallbackHtml, waitForHydrationPrefetchStrategy } from "./hydration/runtime.js"; | ||
| import { interaction, listenForDelegatedHydrationIntent } from "./hydration/interaction.js"; | ||
| import { load } from "./hydration/load.js"; | ||
| import { media } from "./hydration/media.js"; | ||
| import { never } from "./hydration/never.js"; | ||
| import { withHydrationRenderer } from "./hydration/renderer.js"; | ||
| import { visible } from "./hydration/visible.js"; | ||
| //#region src/hydration.ts | ||
| var hydrateIdSelector = `[${hydrateIdAttribute}]`; | ||
| //#endregion | ||
| export { clearResolvedGateIdsInMarker, condition, createResolvedGate, getFallbackHtml, getMarkerGate, getOrCreateGate, hydrateIdAttribute, hydrateIdSelector, hydrateInteractionEventsAttribute, hydrateWhenAttribute, idle, interaction, listenForDelegatedHydrationIntent, load, media, never, onGateResolve, releaseGate, resolveHydrationMarker, runHydrationStrategyCleanup, saveFallbackHtml, visible, waitForHydrationPrefetchStrategy, withHydrationRenderer }; | ||
| //# sourceMappingURL=hydration.js.map |
| {"version":3,"file":"hydration.js","names":[],"sources":["../../src/hydration.ts"],"sourcesContent":["import { hydrateIdAttribute } from './hydration/constants'\n\nexport { condition } from './hydration/condition'\nexport type { HydrationCondition } from './hydration/condition'\nexport {\n hydrateIdAttribute,\n hydrateInteractionEventsAttribute,\n hydrateWhenAttribute,\n} from './hydration/constants'\nexport const hydrateIdSelector = `[${hydrateIdAttribute}]`\nexport { idle } from './hydration/idle'\nexport type { IdleHydrationOptions } from './hydration/idle'\nexport { interaction } from './hydration/interaction'\nexport { load } from './hydration/load'\nexport { media } from './hydration/media'\nexport { never } from './hydration/never'\nexport {\n clearResolvedGateIdsInMarker,\n createResolvedGate,\n getFallbackHtml,\n getMarkerGate,\n getOrCreateGate,\n onGateResolve,\n releaseGate,\n resolveHydrationMarker,\n runHydrationStrategyCleanup,\n saveFallbackHtml,\n waitForHydrationPrefetchStrategy,\n} from './hydration/runtime'\nexport { withHydrationRenderer } from './hydration/renderer'\nexport { visible } from './hydration/visible'\nexport { listenForDelegatedHydrationIntent } from './hydration/interaction'\nexport type { VisibleHydrationOptions } from './hydration/visible'\nexport type { HydrationGateRecord } from './hydration/runtime'\nexport type { HydrationStrategyWithRenderer } from './hydration/renderer'\nexport type {\n HydrationInteractionEvent,\n HydrationInteractionEvents,\n HydrationMarkerAttributes,\n HydrationPrefetchContext,\n HydrationPrefetchFunction,\n HydrationPrefetchWhen,\n HydrationPrefetchStrategy,\n HydrationPrefetchWaitReason,\n HydrationRuntimeContext,\n HydrationRuntimeGate,\n HydrationStrategy,\n HydrationStrategyTypes,\n HydrationWhen,\n} from './hydration/types'\n"],"mappings":";;;;;;;;;;;AASA,IAAa,oBAAoB,IAAI,mBAAmB"} |
| import { HydrationStrategy } from './types.js'; | ||
| declare const conditionType = "condition"; | ||
| export type HydrationCondition = boolean | (() => boolean); | ||
| export declare function condition(condition: HydrationCondition): HydrationStrategy<typeof conditionType, false>; | ||
| export {}; |
| //#region src/hydration/condition.ts | ||
| var conditionType = "condition"; | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| function condition(condition) { | ||
| return { | ||
| _t: conditionType, | ||
| _d: () => !(typeof condition === "function" ? condition() : condition), | ||
| _s: ({ gate }) => { | ||
| if (typeof condition === "function" ? condition() : condition) gate.resolve(); | ||
| } | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { condition }; | ||
| //# sourceMappingURL=condition.js.map |
| {"version":3,"file":"condition.js","names":[],"sources":["../../../src/hydration/condition.ts"],"sourcesContent":["import type { HydrationStrategy } from './types'\n\nconst conditionType = 'condition'\n\nexport type HydrationCondition = boolean | (() => boolean)\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function condition(\n condition: HydrationCondition,\n): HydrationStrategy<typeof conditionType, false> {\n return {\n _t: conditionType,\n _d: () => !(typeof condition === 'function' ? condition() : condition),\n _s: ({ gate }) => {\n if (typeof condition === 'function' ? condition() : condition) {\n gate!.resolve()\n }\n },\n }\n}\n"],"mappings":";AAEA,IAAM,gBAAgB;;AAKtB,SAAgB,UACd,WACgD;AAChD,QAAO;EACL,IAAI;EACJ,UAAU,EAAE,OAAO,cAAc,aAAa,WAAW,GAAG;EAC5D,KAAK,EAAE,WAAW;AAChB,OAAI,OAAO,cAAc,aAAa,WAAW,GAAG,UAClD,MAAM,SAAS;;EAGpB"} |
| export declare const hydrateIdAttribute = "data-ts-hydrate-id"; | ||
| export declare const hydrateWhenAttribute = "data-ts-hydrate-when"; | ||
| export declare const hydrateInteractionEventsAttribute = "data-ts-hydrate-interaction-events"; |
| //#region src/hydration/constants.ts | ||
| var hydrateIdAttribute = "data-ts-hydrate-id"; | ||
| var hydrateWhenAttribute = "data-ts-hydrate-when"; | ||
| var hydrateInteractionEventsAttribute = "data-ts-hydrate-interaction-events"; | ||
| //#endregion | ||
| export { hydrateIdAttribute, hydrateInteractionEventsAttribute, hydrateWhenAttribute }; | ||
| //# sourceMappingURL=constants.js.map |
| {"version":3,"file":"constants.js","names":[],"sources":["../../../src/hydration/constants.ts"],"sourcesContent":["export const hydrateIdAttribute = 'data-ts-hydrate-id'\nexport const hydrateWhenAttribute = 'data-ts-hydrate-when'\nexport const hydrateInteractionEventsAttribute =\n 'data-ts-hydrate-interaction-events'\n"],"mappings":";AAAA,IAAa,qBAAqB;AAClC,IAAa,uBAAuB;AACpC,IAAa,oCACX"} |
| import { HydrationPrefetchStrategy } from './types.js'; | ||
| declare const idleType = "idle"; | ||
| export type IdleHydrationOptions = { | ||
| timeout?: number; | ||
| }; | ||
| export declare function idle(options?: IdleHydrationOptions): HydrationPrefetchStrategy<typeof idleType>; | ||
| export {}; |
| //#region src/hydration/idle.ts | ||
| var idleType = "idle"; | ||
| function idle(options = {}) { | ||
| const timeout = options.timeout ?? 2e3; | ||
| return { | ||
| _t: idleType, | ||
| _s: ({ gate, prefetch }) => { | ||
| const schedule = globalThis; | ||
| const callback = prefetch ?? gate.resolve; | ||
| if (schedule.requestIdleCallback) { | ||
| const handle = schedule.requestIdleCallback(callback, { timeout }); | ||
| return () => schedule.cancelIdleCallback?.(handle); | ||
| } | ||
| const timeoutId = globalThis.setTimeout(callback, timeout); | ||
| return () => globalThis.clearTimeout(timeoutId); | ||
| } | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { idle }; | ||
| //# sourceMappingURL=idle.js.map |
| {"version":3,"file":"idle.js","names":[],"sources":["../../../src/hydration/idle.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst idleType = 'idle'\n\nexport type IdleHydrationOptions = {\n timeout?: number\n}\n\nexport function idle(\n options: IdleHydrationOptions = {},\n): HydrationPrefetchStrategy<typeof idleType> {\n const timeout = options.timeout ?? 2000\n\n return {\n _t: idleType,\n _s: ({ gate, prefetch }) => {\n const schedule = globalThis as unknown as {\n requestIdleCallback?: (\n callback: IdleRequestCallback,\n options?: IdleRequestOptions,\n ) => number\n cancelIdleCallback?: (handle: number) => void\n }\n const callback = prefetch ?? gate!.resolve\n\n if (schedule.requestIdleCallback) {\n const handle = schedule.requestIdleCallback(callback, { timeout })\n return () => schedule.cancelIdleCallback?.(handle)\n }\n\n const timeoutId = globalThis.setTimeout(callback, timeout)\n return () => globalThis.clearTimeout(timeoutId)\n },\n }\n}\n"],"mappings":";AAEA,IAAM,WAAW;AAMjB,SAAgB,KACd,UAAgC,EAAE,EACU;CAC5C,MAAM,UAAU,QAAQ,WAAW;AAEnC,QAAO;EACL,IAAI;EACJ,KAAK,EAAE,MAAM,eAAe;GAC1B,MAAM,WAAW;GAOjB,MAAM,WAAW,YAAY,KAAM;AAEnC,OAAI,SAAS,qBAAqB;IAChC,MAAM,SAAS,SAAS,oBAAoB,UAAU,EAAE,SAAS,CAAC;AAClE,iBAAa,SAAS,qBAAqB,OAAO;;GAGpD,MAAM,YAAY,WAAW,WAAW,UAAU,QAAQ;AAC1D,gBAAa,WAAW,aAAa,UAAU;;EAElD"} |
| import { HydrationInteractionEvents, HydrationPrefetchStrategy, HydrationRuntimeContext } from './types.js'; | ||
| export type InteractionHydrationOptions = { | ||
| events?: HydrationInteractionEvents; | ||
| }; | ||
| declare const interactionType = "interaction"; | ||
| export declare function listenForDelegatedHydrationIntent(element: Element, context: HydrationRuntimeContext): (() => void) | undefined; | ||
| export declare function interaction(options?: InteractionHydrationOptions): HydrationPrefetchStrategy<typeof interactionType>; | ||
| export {}; |
| import { hydrateIdAttribute, hydrateInteractionEventsAttribute, hydrateWhenAttribute } from "./constants.js"; | ||
| import { clearResolvedGateIdsInMarker, getMarkerGate, resolveHydrationMarker } from "./runtime.js"; | ||
| //#region src/hydration/interaction.ts | ||
| var hydrateIdSelector = `[${hydrateIdAttribute}]`; | ||
| var defaultInteractionEvents = [ | ||
| "pointerenter", | ||
| "focusin", | ||
| "pointerdown", | ||
| "click" | ||
| ]; | ||
| var supportedInteractionEvents = [ | ||
| "auxclick", | ||
| "click", | ||
| "contextmenu", | ||
| "dblclick", | ||
| "focusin", | ||
| "keydown", | ||
| "keyup", | ||
| "mousedown", | ||
| "mouseenter", | ||
| "mouseover", | ||
| "mouseup", | ||
| "pointerdown", | ||
| "pointerenter", | ||
| "pointerover", | ||
| "pointerup" | ||
| ]; | ||
| var interactionType = "interaction"; | ||
| var dynamicType = "dynamic"; | ||
| var delegatedHydrateSelector = `${`[${hydrateWhenAttribute}="${interactionType}"]`},[${hydrateWhenAttribute}="${dynamicType}"]`; | ||
| var replayEventsByGateId = /* @__PURE__ */ new Map(); | ||
| function getIntentListenerEvents(marker, events) { | ||
| const listenerEvents = new Set(events); | ||
| marker.querySelectorAll(delegatedHydrateSelector).forEach((childMarker) => { | ||
| if (childMarker.getAttribute("data-ts-hydrate-when") === dynamicType) { | ||
| supportedInteractionEvents.forEach((eventName) => { | ||
| listenerEvents.add(eventName); | ||
| }); | ||
| return; | ||
| } | ||
| const attr = childMarker.getAttribute(hydrateInteractionEventsAttribute); | ||
| for (const eventName of attr === null ? defaultInteractionEvents : attr.split(/\s+/).filter(Boolean)) listenerEvents.add(eventName); | ||
| }); | ||
| return [...listenerEvents]; | ||
| } | ||
| function queueHydrationReplayEvent(marker, event) { | ||
| if (!event.bubbles) return; | ||
| const id = marker.getAttribute(hydrateIdAttribute); | ||
| const when = marker.getAttribute(hydrateWhenAttribute); | ||
| if (!id || !when || when === "never") return; | ||
| const target = event.target; | ||
| if (!target) return; | ||
| if (getMarkerGate(marker)?.resolved) return; | ||
| event.preventDefault(); | ||
| event.stopPropagation(); | ||
| event.stopImmediatePropagation(); | ||
| let targetPath = []; | ||
| if (target instanceof Node && marker.contains(target)) { | ||
| let node = target instanceof Element ? target : target.parentElement; | ||
| while (node && node !== marker) { | ||
| const parent = node.parentElement; | ||
| if (!parent) { | ||
| targetPath = []; | ||
| break; | ||
| } | ||
| targetPath.push(Array.prototype.indexOf.call(parent.children, node)); | ||
| node = parent; | ||
| } | ||
| targetPath.reverse(); | ||
| } | ||
| const pendingEvents = replayEventsByGateId.get(id) ?? []; | ||
| pendingEvents.push({ | ||
| marker, | ||
| targetPath, | ||
| type: event.type, | ||
| event | ||
| }); | ||
| replayEventsByGateId.set(id, pendingEvents); | ||
| } | ||
| if (typeof document !== "undefined") { | ||
| const onIntent = (event) => { | ||
| const target = event.target; | ||
| if (!(target instanceof Element)) return; | ||
| let marker = target.closest(hydrateIdSelector); | ||
| const markers = []; | ||
| let shouldHandle = false; | ||
| while (marker) { | ||
| markers.push(marker); | ||
| const when = marker.getAttribute(hydrateWhenAttribute); | ||
| if (when === dynamicType) shouldHandle ||= event.type === "click"; | ||
| else if (when === interactionType) { | ||
| const attr = marker.getAttribute(hydrateInteractionEventsAttribute); | ||
| const events = attr === null ? defaultInteractionEvents : attr.split(/\s+/).filter(Boolean); | ||
| shouldHandle ||= events.includes(event.type); | ||
| } | ||
| marker = marker.parentElement?.closest(hydrateIdSelector) ?? null; | ||
| } | ||
| if (!shouldHandle) return; | ||
| markers.reverse(); | ||
| if (markers.every((marker) => getMarkerGate(marker))) return; | ||
| markers.forEach((marker) => { | ||
| queueHydrationReplayEvent(marker, event); | ||
| resolveHydrationMarker(marker); | ||
| }); | ||
| }; | ||
| supportedInteractionEvents.forEach((eventName) => { | ||
| document.addEventListener(eventName, onIntent, true); | ||
| }); | ||
| } | ||
| function listenForIntent(element, events, context) { | ||
| const onIntent = (event) => { | ||
| const target = event.target; | ||
| let marker; | ||
| if (target instanceof Element) { | ||
| const closestMarker = target.closest(hydrateIdSelector); | ||
| marker = closestMarker && element.contains(closestMarker) ? closestMarker : element; | ||
| } else marker = element; | ||
| const markers = []; | ||
| while (marker) { | ||
| if (marker.hasAttribute("data-ts-hydrate-id")) markers.push(marker); | ||
| if (marker === element) break; | ||
| marker = marker.parentElement; | ||
| } | ||
| if (!markers.includes(element)) markers.push(element); | ||
| markers.reverse(); | ||
| if (context.delegated && !markers.some((marker) => marker.getAttribute("data-ts-hydrate-when") === interactionType || marker.getAttribute("data-ts-hydrate-when") === dynamicType)) return; | ||
| markers.forEach((marker) => { | ||
| queueHydrationReplayEvent(marker, event); | ||
| resolveHydrationMarker(marker); | ||
| }); | ||
| }; | ||
| let disposed = false; | ||
| events.forEach((eventName) => { | ||
| element.addEventListener(eventName, onIntent, true); | ||
| }); | ||
| return () => { | ||
| if (disposed) return; | ||
| disposed = true; | ||
| events.forEach((eventName) => { | ||
| element.removeEventListener(eventName, onIntent, true); | ||
| }); | ||
| }; | ||
| } | ||
| function listenForDelegatedHydrationIntent(element, context) { | ||
| const listenerEvents = getIntentListenerEvents(element, []); | ||
| if (!listenerEvents.length) return; | ||
| const cleanupIntent = listenForIntent(element, listenerEvents, { | ||
| ...context, | ||
| delegated: true | ||
| }); | ||
| return () => { | ||
| cleanupIntent(); | ||
| clearResolvedGateIdsInMarker(element); | ||
| }; | ||
| } | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| function interaction(options = {}) { | ||
| let events = defaultInteractionEvents; | ||
| if (options.events !== void 0) { | ||
| const eventList = typeof options.events === "string" ? [options.events] : options.events; | ||
| const normalizedEvents = []; | ||
| const seen = /* @__PURE__ */ new Set(); | ||
| for (const eventName of eventList) { | ||
| if (!eventName || seen.has(eventName)) continue; | ||
| seen.add(eventName); | ||
| normalizedEvents.push(eventName); | ||
| } | ||
| events = normalizedEvents; | ||
| } | ||
| const eventKey = events.join(" "); | ||
| return { | ||
| _t: interactionType, | ||
| _s: (context) => { | ||
| const element = context.element; | ||
| if (!element) return; | ||
| const prefetch = context.prefetch; | ||
| if (prefetch) { | ||
| if (!events.length) return; | ||
| let disposed = false; | ||
| events.forEach((eventName) => { | ||
| element.addEventListener(eventName, prefetch, true); | ||
| }); | ||
| return () => { | ||
| if (disposed) return; | ||
| disposed = true; | ||
| events.forEach((eventName) => { | ||
| element.removeEventListener(eventName, prefetch, true); | ||
| }); | ||
| }; | ||
| } | ||
| const listenerEvents = getIntentListenerEvents(element, events); | ||
| const cleanupIntent = listenerEvents.length ? listenForIntent(element, listenerEvents, context) : void 0; | ||
| return () => { | ||
| cleanupIntent?.(); | ||
| clearResolvedGateIdsInMarker(element); | ||
| }; | ||
| }, | ||
| _o: (id) => { | ||
| globalThis.requestAnimationFrame(() => { | ||
| const pendingEvents = replayEventsByGateId.get(id); | ||
| if (!pendingEvents?.length) return; | ||
| replayEventsByGateId.delete(id); | ||
| for (const pendingEvent of pendingEvents) { | ||
| let replayTarget = pendingEvent.marker; | ||
| for (const index of pendingEvent.targetPath) { | ||
| replayTarget = replayTarget.children[index] ?? null; | ||
| if (!replayTarget) break; | ||
| } | ||
| const event = pendingEvent.event; | ||
| replayTarget ??= pendingEvent.marker; | ||
| replayTarget.dispatchEvent(event instanceof MouseEvent ? new MouseEvent(event.type, event) : event instanceof FocusEvent ? new FocusEvent(event.type, event) : new Event(event.type, event)); | ||
| } | ||
| }); | ||
| }, | ||
| _a: () => options.events === void 0 ? void 0 : { [hydrateInteractionEventsAttribute]: eventKey } | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { interaction, listenForDelegatedHydrationIntent }; | ||
| //# sourceMappingURL=interaction.js.map |
| {"version":3,"file":"interaction.js","names":[],"sources":["../../../src/hydration/interaction.ts"],"sourcesContent":["import {\n hydrateIdAttribute,\n hydrateInteractionEventsAttribute,\n hydrateWhenAttribute,\n} from './constants'\nimport {\n clearResolvedGateIdsInMarker,\n getMarkerGate,\n resolveHydrationMarker,\n} from './runtime'\nimport type {\n HydrationInteractionEvents,\n HydrationPrefetchStrategy,\n HydrationRuntimeContext,\n} from './types'\n\nexport type InteractionHydrationOptions = {\n events?: HydrationInteractionEvents\n}\n\nconst hydrateIdSelector = `[${hydrateIdAttribute}]`\n\ntype PendingReplayEvent = {\n marker: Element\n targetPath: Array<number>\n type: string\n event: Event\n}\n\nconst defaultInteractionEvents = [\n 'pointerenter',\n 'focusin',\n 'pointerdown',\n 'click',\n] as const\nconst supportedInteractionEvents = [\n 'auxclick',\n 'click',\n 'contextmenu',\n 'dblclick',\n 'focusin',\n 'keydown',\n 'keyup',\n 'mousedown',\n 'mouseenter',\n 'mouseover',\n 'mouseup',\n 'pointerdown',\n 'pointerenter',\n 'pointerover',\n 'pointerup',\n] as const\nconst interactionType = 'interaction'\nconst dynamicType = 'dynamic'\nconst interactionHydrateSelector = `[${hydrateWhenAttribute}=\"${interactionType}\"]`\nconst delegatedHydrateSelector = `${interactionHydrateSelector},[${hydrateWhenAttribute}=\"${dynamicType}\"]`\nconst replayEventsByGateId = /* @__PURE__ */ new Map<\n string,\n Array<PendingReplayEvent>\n>()\n\nfunction getIntentListenerEvents(\n marker: Element,\n events: ReadonlyArray<string>,\n) {\n const listenerEvents = new Set(events)\n\n marker.querySelectorAll(delegatedHydrateSelector).forEach((childMarker) => {\n if (childMarker.getAttribute(hydrateWhenAttribute) === dynamicType) {\n supportedInteractionEvents.forEach((eventName) => {\n listenerEvents.add(eventName)\n })\n return\n }\n\n const attr = childMarker.getAttribute(hydrateInteractionEventsAttribute)\n for (const eventName of attr === null\n ? defaultInteractionEvents\n : attr.split(/\\s+/).filter(Boolean)) {\n listenerEvents.add(eventName)\n }\n })\n\n return [...listenerEvents]\n}\n\nfunction queueHydrationReplayEvent(marker: Element, event: Event) {\n if (!event.bubbles) return\n\n const id = marker.getAttribute(hydrateIdAttribute)\n const when = marker.getAttribute(hydrateWhenAttribute)\n if (!id || !when || when === 'never') return\n\n const target = event.target\n if (!target) return\n\n const gate = getMarkerGate(marker)\n if (gate?.resolved) return\n\n event.preventDefault()\n event.stopPropagation()\n event.stopImmediatePropagation()\n\n let targetPath: Array<number> = []\n if (target instanceof Node && marker.contains(target)) {\n let node: Element | null =\n target instanceof Element ? target : target.parentElement\n\n while (node && node !== marker) {\n const parent = node.parentElement\n if (!parent) {\n targetPath = []\n break\n }\n targetPath.push(Array.prototype.indexOf.call(parent.children, node))\n node = parent\n }\n targetPath.reverse()\n }\n\n const pendingEvents = replayEventsByGateId.get(id) ?? []\n pendingEvents.push({\n marker,\n targetPath,\n type: event.type,\n event,\n })\n replayEventsByGateId.set(id, pendingEvents)\n}\n\nif (typeof document !== 'undefined') {\n const onIntent = (event: Event) => {\n const target = event.target\n if (!(target instanceof Element)) return\n\n let marker: Element | null = target.closest(hydrateIdSelector)\n const markers: Array<Element> = []\n let shouldHandle = false\n\n while (marker) {\n markers.push(marker)\n\n const when = marker.getAttribute(hydrateWhenAttribute)\n if (when === dynamicType) {\n shouldHandle ||= event.type === 'click'\n } else if (when === interactionType) {\n const attr = marker.getAttribute(hydrateInteractionEventsAttribute)\n const events: ReadonlyArray<string> =\n attr === null\n ? defaultInteractionEvents\n : attr.split(/\\s+/).filter(Boolean)\n shouldHandle ||= events.includes(event.type)\n }\n\n marker = marker.parentElement?.closest(hydrateIdSelector) ?? null\n }\n\n if (!shouldHandle) return\n\n markers.reverse()\n if (markers.every((marker) => getMarkerGate(marker))) return\n\n markers.forEach((marker) => {\n queueHydrationReplayEvent(marker, event)\n resolveHydrationMarker(marker)\n })\n }\n\n supportedInteractionEvents.forEach((eventName) => {\n document.addEventListener(eventName, onIntent, true)\n })\n}\n\nfunction listenForIntent(\n element: Element,\n events: ReadonlyArray<string>,\n context: HydrationRuntimeContext,\n) {\n const onIntent = (event: Event) => {\n const target = event.target\n let marker: Element | null\n if (target instanceof Element) {\n const closestMarker = target.closest(hydrateIdSelector)\n marker =\n closestMarker && element.contains(closestMarker)\n ? closestMarker\n : element\n } else {\n marker = element\n }\n\n const markers: Array<Element> = []\n while (marker) {\n if (marker.hasAttribute(hydrateIdAttribute)) {\n markers.push(marker)\n }\n if (marker === element) break\n marker = marker.parentElement\n }\n\n if (!markers.includes(element)) {\n markers.push(element)\n }\n\n markers.reverse()\n\n if (\n context.delegated &&\n !markers.some(\n (marker) =>\n marker.getAttribute(hydrateWhenAttribute) === interactionType ||\n marker.getAttribute(hydrateWhenAttribute) === dynamicType,\n )\n ) {\n return\n }\n\n markers.forEach((marker) => {\n queueHydrationReplayEvent(marker, event)\n resolveHydrationMarker(marker)\n })\n }\n let disposed = false\n\n events.forEach((eventName) => {\n element.addEventListener(eventName, onIntent, true)\n })\n\n return () => {\n if (disposed) return\n disposed = true\n events.forEach((eventName) => {\n element.removeEventListener(eventName, onIntent, true)\n })\n }\n}\n\nexport function listenForDelegatedHydrationIntent(\n element: Element,\n context: HydrationRuntimeContext,\n) {\n const listenerEvents = getIntentListenerEvents(element, [])\n if (!listenerEvents.length) return\n\n const cleanupIntent = listenForIntent(element, listenerEvents, {\n ...context,\n delegated: true,\n })\n return () => {\n cleanupIntent()\n clearResolvedGateIdsInMarker(element)\n }\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function interaction(\n options: InteractionHydrationOptions = {},\n): HydrationPrefetchStrategy<typeof interactionType> {\n let events: ReadonlyArray<string> = defaultInteractionEvents\n if (options.events !== undefined) {\n const eventList: ReadonlyArray<string> =\n typeof options.events === 'string' ? [options.events] : options.events\n const normalizedEvents: Array<string> = []\n const seen = new Set<string>()\n\n for (const eventName of eventList) {\n if (!eventName || seen.has(eventName)) continue\n seen.add(eventName)\n normalizedEvents.push(eventName)\n }\n\n events = normalizedEvents\n }\n\n const eventKey = events.join(' ')\n\n return {\n _t: interactionType,\n _s: (context) => {\n const element = context.element\n if (!element) return\n const prefetch = context.prefetch\n if (prefetch) {\n if (!events.length) return\n let disposed = false\n\n events.forEach((eventName) => {\n element.addEventListener(eventName, prefetch, true)\n })\n\n return () => {\n if (disposed) return\n disposed = true\n events.forEach((eventName) => {\n element.removeEventListener(eventName, prefetch, true)\n })\n }\n }\n\n const listenerEvents = getIntentListenerEvents(element, events)\n const cleanupIntent = listenerEvents.length\n ? listenForIntent(element, listenerEvents, context)\n : undefined\n return () => {\n cleanupIntent?.()\n clearResolvedGateIdsInMarker(element)\n }\n },\n _o: (id) => {\n globalThis.requestAnimationFrame(() => {\n const pendingEvents = replayEventsByGateId.get(id)\n if (!pendingEvents?.length) return\n\n replayEventsByGateId.delete(id)\n\n for (const pendingEvent of pendingEvents) {\n let replayTarget: Element | null = pendingEvent.marker\n for (const index of pendingEvent.targetPath) {\n replayTarget = replayTarget.children[index] ?? null\n if (!replayTarget) break\n }\n\n const event = pendingEvent.event\n replayTarget ??= pendingEvent.marker\n replayTarget.dispatchEvent(\n event instanceof MouseEvent\n ? new MouseEvent(event.type, event)\n : event instanceof FocusEvent\n ? new FocusEvent(event.type, event)\n : new Event(event.type, event),\n )\n }\n })\n },\n _a: () =>\n options.events === undefined\n ? undefined\n : {\n [hydrateInteractionEventsAttribute]: eventKey,\n },\n }\n}\n"],"mappings":"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"} |
| import { HydrationPrefetchStrategy } from './types.js'; | ||
| declare const loadType = "load"; | ||
| export declare function load(): HydrationPrefetchStrategy<typeof loadType>; | ||
| export {}; |
| //#region src/hydration/load.ts | ||
| var loadStrategy = { | ||
| _t: "load", | ||
| _d: () => false, | ||
| _s: ({ gate, prefetch }) => { | ||
| (prefetch ?? gate.resolve)(); | ||
| } | ||
| }; | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| function load() { | ||
| return loadStrategy; | ||
| } | ||
| //#endregion | ||
| export { load }; | ||
| //# sourceMappingURL=load.js.map |
| {"version":3,"file":"load.js","names":[],"sources":["../../../src/hydration/load.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst loadType = 'load'\n\nconst loadStrategy: HydrationPrefetchStrategy<typeof loadType> = {\n _t: loadType,\n _d: () => false,\n _s: ({ gate, prefetch }) => {\n ;(prefetch ?? gate!.resolve)()\n },\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function load(): HydrationPrefetchStrategy<typeof loadType> {\n return loadStrategy\n}\n"],"mappings":";AAIA,IAAM,eAA2D;CAC/D,IAHe;CAIf,UAAU;CACV,KAAK,EAAE,MAAM,eAAe;AACzB,GAAC,YAAY,KAAM,UAAU;;CAEjC;;AAGD,SAAgB,OAAmD;AACjE,QAAO"} |
| import { HydrationPrefetchStrategy } from './types.js'; | ||
| declare const mediaType = "media"; | ||
| export declare function media(query: string): HydrationPrefetchStrategy<typeof mediaType>; | ||
| export {}; |
| //#region src/hydration/media.ts | ||
| var mediaType = "media"; | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| function media(query) { | ||
| return { | ||
| _t: mediaType, | ||
| _s: ({ gate, prefetch }) => { | ||
| if (!query) return; | ||
| const callback = prefetch ?? gate.resolve; | ||
| const mediaQuery = window.matchMedia(query); | ||
| const onChange = () => { | ||
| if (mediaQuery.matches) callback(); | ||
| }; | ||
| mediaQuery.addEventListener("change", onChange); | ||
| onChange(); | ||
| return () => mediaQuery.removeEventListener("change", onChange); | ||
| } | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { media }; | ||
| //# sourceMappingURL=media.js.map |
| {"version":3,"file":"media.js","names":[],"sources":["../../../src/hydration/media.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst mediaType = 'media'\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function media(\n query: string,\n): HydrationPrefetchStrategy<typeof mediaType> {\n return {\n _t: mediaType,\n _s: ({ gate, prefetch }) => {\n if (!query) return\n\n const callback = prefetch ?? gate!.resolve\n const mediaQuery = window.matchMedia(query)\n const onChange = () => {\n if (mediaQuery.matches) callback()\n }\n mediaQuery.addEventListener('change', onChange)\n onChange()\n\n return () => mediaQuery.removeEventListener('change', onChange)\n },\n }\n}\n"],"mappings":";AAEA,IAAM,YAAY;;AAGlB,SAAgB,MACd,OAC6C;AAC7C,QAAO;EACL,IAAI;EACJ,KAAK,EAAE,MAAM,eAAe;AAC1B,OAAI,CAAC,MAAO;GAEZ,MAAM,WAAW,YAAY,KAAM;GACnC,MAAM,aAAa,OAAO,WAAW,MAAM;GAC3C,MAAM,iBAAiB;AACrB,QAAI,WAAW,QAAS,WAAU;;AAEpC,cAAW,iBAAiB,UAAU,SAAS;AAC/C,aAAU;AAEV,gBAAa,WAAW,oBAAoB,UAAU,SAAS;;EAElE"} |
| import { HydrationStrategy } from './types.js'; | ||
| declare const neverType = "never"; | ||
| export declare function never(): HydrationStrategy<typeof neverType, false>; | ||
| export {}; |
| //#region src/hydration/never.ts | ||
| var neverStrategy = { | ||
| _t: "never", | ||
| _d: () => true | ||
| }; | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| function never() { | ||
| return neverStrategy; | ||
| } | ||
| //#endregion | ||
| export { never }; | ||
| //# sourceMappingURL=never.js.map |
| {"version":3,"file":"never.js","names":[],"sources":["../../../src/hydration/never.ts"],"sourcesContent":["import type { HydrationStrategy } from './types'\n\nconst neverType = 'never'\n\nconst neverStrategy: HydrationStrategy<typeof neverType, false> = {\n _t: neverType,\n _d: () => true,\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function never(): HydrationStrategy<typeof neverType, false> {\n return neverStrategy\n}\n"],"mappings":";AAIA,IAAM,gBAA4D;CAChE,IAHgB;CAIhB,UAAU;CACX;;AAGD,SAAgB,QAAoD;AAClE,QAAO"} |
| import { HydrationStrategy } from './types.js'; | ||
| export type HydrationStrategyWithRenderer<TStrategy extends HydrationStrategy, TRenderer> = TStrategy & { | ||
| _h: TRenderer; | ||
| }; | ||
| export declare function withHydrationRenderer<TStrategy extends HydrationStrategy, TRenderer>(strategy: TStrategy, renderer: TRenderer): HydrationStrategyWithRenderer<TStrategy, TRenderer>; |
| //#region src/hydration/renderer.ts | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| function withHydrationRenderer(strategy, renderer) { | ||
| return /* @__PURE__ */ Object.assign(strategy, { _h: renderer }); | ||
| } | ||
| //#endregion | ||
| export { withHydrationRenderer }; | ||
| //# sourceMappingURL=renderer.js.map |
| {"version":3,"file":"renderer.js","names":[],"sources":["../../../src/hydration/renderer.ts"],"sourcesContent":["import type { HydrationStrategy } from './types'\n\nexport type HydrationStrategyWithRenderer<\n TStrategy extends HydrationStrategy,\n TRenderer,\n> = TStrategy & {\n _h: TRenderer\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function withHydrationRenderer<\n TStrategy extends HydrationStrategy,\n TRenderer,\n>(\n strategy: TStrategy,\n renderer: TRenderer,\n): HydrationStrategyWithRenderer<TStrategy, TRenderer> {\n return /* @__PURE__ */ Object.assign(strategy, {\n _h: renderer,\n })\n}\n"],"mappings":";;AAUA,SAAgB,sBAId,UACA,UACqD;AACrD,QAAuB,uBAAO,OAAO,UAAU,EAC7C,IAAI,UACL,CAAC"} |
| import { HydrationPrefetchStrategy, HydrationPrefetchWaitReason, HydrationRuntimeGate, HydrationWhen } from './types.js'; | ||
| export type HydrationGateRecord = HydrationRuntimeGate & { | ||
| id: string; | ||
| when: HydrationWhen; | ||
| promise: Promise<void>; | ||
| consumers: number; | ||
| resolveListeners: Set<() => void>; | ||
| }; | ||
| export declare function createResolvedGate(id: string, when: HydrationWhen): HydrationGateRecord; | ||
| export declare function getOrCreateGate(id: string, when: HydrationWhen): HydrationGateRecord; | ||
| export declare function releaseGate(gate: HydrationGateRecord): void; | ||
| export declare function onGateResolve(gate: HydrationGateRecord, listener: () => void): () => void; | ||
| export declare function runHydrationStrategyCleanup(cleanup: void | (() => void)): (() => void) | undefined; | ||
| export declare function waitForHydrationPrefetchStrategy(strategy: HydrationPrefetchStrategy, options: { | ||
| element: Element | null; | ||
| signal: AbortSignal; | ||
| onHydrate: (listener: () => void) => () => void; | ||
| }): Promise<HydrationPrefetchWaitReason>; | ||
| export declare function getMarkerGate(marker: Element): HydrationGateRecord | undefined; | ||
| export declare function resolveHydrationMarker(marker: Element): void; | ||
| export declare function clearResolvedGateIdsInMarker(marker: Element): void; | ||
| export declare function saveFallbackHtml(id: string, element: Element): void; | ||
| export declare function getFallbackHtml(id: string): string | undefined; |
| import { hydrateIdAttribute, hydrateWhenAttribute } from "./constants.js"; | ||
| //#region src/hydration/runtime.ts | ||
| var hydrateIdSelector = `[${hydrateIdAttribute}]`; | ||
| var gateRegistry = /* @__PURE__ */ new Map(); | ||
| var resolvedGateIds = /* @__PURE__ */ new Set(); | ||
| var fallbackHtmlByGateId = /* @__PURE__ */ new Map(); | ||
| function createResolvedGate(id, when) { | ||
| return { | ||
| id, | ||
| when, | ||
| promise: Promise.resolve(), | ||
| resolve: () => {}, | ||
| resolved: true, | ||
| consumers: 0, | ||
| resolveListeners: /* @__PURE__ */ new Set() | ||
| }; | ||
| } | ||
| function getOrCreateGate(id, when) { | ||
| const existing = gateRegistry.get(id); | ||
| if (existing?.when === when) { | ||
| existing.consumers++; | ||
| return existing; | ||
| } | ||
| let resolvePromise; | ||
| const gate = { | ||
| id, | ||
| promise: new Promise((resolve) => { | ||
| resolvePromise = resolve; | ||
| }), | ||
| resolved: false, | ||
| consumers: 1, | ||
| when, | ||
| resolveListeners: /* @__PURE__ */ new Set(), | ||
| resolve: () => { | ||
| if (gate.resolved) return; | ||
| gate.resolved = true; | ||
| resolvePromise(); | ||
| gate.resolveListeners.forEach((listener) => listener()); | ||
| gate.resolveListeners.clear(); | ||
| } | ||
| }; | ||
| gateRegistry.set(id, gate); | ||
| if (when !== "never" && resolvedGateIds.has(id)) { | ||
| resolvedGateIds.delete(id); | ||
| gate.resolve(); | ||
| } | ||
| return gate; | ||
| } | ||
| function releaseGate(gate) { | ||
| resolvedGateIds.delete(gate.id); | ||
| gate.consumers--; | ||
| if (gate.consumers > 0) return; | ||
| if (gateRegistry.get(gate.id) === gate) { | ||
| gateRegistry.delete(gate.id); | ||
| fallbackHtmlByGateId.delete(gate.id); | ||
| gate.resolveListeners.clear(); | ||
| } | ||
| } | ||
| function onGateResolve(gate, listener) { | ||
| if (gate.resolved) { | ||
| listener(); | ||
| return () => {}; | ||
| } | ||
| gate.resolveListeners.add(listener); | ||
| return () => { | ||
| gate.resolveListeners.delete(listener); | ||
| }; | ||
| } | ||
| function runHydrationStrategyCleanup(cleanup) { | ||
| if (typeof cleanup === "function") return cleanup; | ||
| } | ||
| function waitForHydrationPrefetchStrategy(strategy, options) { | ||
| if (options.signal.aborted) return Promise.resolve("abort"); | ||
| return new Promise((resolve) => { | ||
| const state = { disposed: false }; | ||
| const cleanupStrategyRef = { current: void 0 }; | ||
| let cleanupHydrate = () => {}; | ||
| const finish = (reason) => { | ||
| if (state.disposed) return; | ||
| state.disposed = true; | ||
| options.signal.removeEventListener("abort", onAbort); | ||
| cleanupHydrate(); | ||
| runHydrationStrategyCleanup(cleanupStrategyRef.current)?.(); | ||
| resolve(reason); | ||
| }; | ||
| const onAbort = () => finish("abort"); | ||
| options.signal.addEventListener("abort", onAbort, { once: true }); | ||
| cleanupHydrate = options.onHydrate(() => finish("hydrate")); | ||
| const cleanupStrategy = strategy._s?.({ | ||
| element: options.element, | ||
| prefetch: () => finish("prefetch") | ||
| }); | ||
| cleanupStrategyRef.current = cleanupStrategy; | ||
| if (state.disposed) runHydrationStrategyCleanup(cleanupStrategy)?.(); | ||
| }); | ||
| } | ||
| function getMarkerGate(marker) { | ||
| const id = marker.getAttribute(hydrateIdAttribute); | ||
| return id ? gateRegistry.get(id) : void 0; | ||
| } | ||
| function resolveHydrationMarker(marker) { | ||
| const id = marker.getAttribute(hydrateIdAttribute); | ||
| const when = marker.getAttribute(hydrateWhenAttribute); | ||
| if (!id || !when || when === "never") return; | ||
| const gate = gateRegistry.get(id); | ||
| if (gate) { | ||
| if (gate.when !== "never") gate.resolve(); | ||
| return; | ||
| } | ||
| resolvedGateIds.add(id); | ||
| } | ||
| function clearResolvedGateIdsInMarker(marker) { | ||
| const ownId = marker.getAttribute(hydrateIdAttribute); | ||
| if (ownId) resolvedGateIds.delete(ownId); | ||
| marker.querySelectorAll(hydrateIdSelector).forEach((childMarker) => { | ||
| const childId = childMarker.getAttribute(hydrateIdAttribute); | ||
| if (childId) resolvedGateIds.delete(childId); | ||
| }); | ||
| } | ||
| function saveFallbackHtml(id, element) { | ||
| if (!fallbackHtmlByGateId.has(id)) fallbackHtmlByGateId.set(id, element.innerHTML); | ||
| } | ||
| function getFallbackHtml(id) { | ||
| return fallbackHtmlByGateId.get(id); | ||
| } | ||
| //#endregion | ||
| export { clearResolvedGateIdsInMarker, createResolvedGate, getFallbackHtml, getMarkerGate, getOrCreateGate, onGateResolve, releaseGate, resolveHydrationMarker, runHydrationStrategyCleanup, saveFallbackHtml, waitForHydrationPrefetchStrategy }; | ||
| //# sourceMappingURL=runtime.js.map |
| {"version":3,"file":"runtime.js","names":[],"sources":["../../../src/hydration/runtime.ts"],"sourcesContent":["import { hydrateIdAttribute, hydrateWhenAttribute } from './constants'\nimport type {\n HydrationPrefetchStrategy,\n HydrationPrefetchWaitReason,\n HydrationRuntimeGate,\n HydrationWhen,\n} from './types'\n\nconst hydrateIdSelector = `[${hydrateIdAttribute}]`\n\nexport type HydrationGateRecord = HydrationRuntimeGate & {\n id: string\n when: HydrationWhen\n promise: Promise<void>\n consumers: number\n resolveListeners: Set<() => void>\n}\n\nconst gateRegistry = /* @__PURE__ */ new Map<string, HydrationGateRecord>()\nconst resolvedGateIds = /* @__PURE__ */ new Set<string>()\nconst fallbackHtmlByGateId = /* @__PURE__ */ new Map<string, string>()\n\nexport function createResolvedGate(\n id: string,\n when: HydrationWhen,\n): HydrationGateRecord {\n return {\n id,\n when,\n promise: Promise.resolve(),\n resolve: () => {},\n resolved: true,\n consumers: 0,\n resolveListeners: new Set<() => void>(),\n }\n}\n\nexport function getOrCreateGate(\n id: string,\n when: HydrationWhen,\n): HydrationGateRecord {\n const existing = gateRegistry.get(id)\n if (existing?.when === when) {\n existing.consumers++\n return existing\n }\n\n let resolvePromise!: () => void\n const promise = new Promise<void>((resolve) => {\n resolvePromise = resolve\n })\n\n const gate: HydrationGateRecord = {\n id,\n promise,\n resolved: false,\n consumers: 1,\n when,\n resolveListeners: new Set(),\n resolve: () => {\n if (gate.resolved) return\n gate.resolved = true\n resolvePromise()\n gate.resolveListeners.forEach((listener) => listener())\n gate.resolveListeners.clear()\n },\n }\n\n gateRegistry.set(id, gate)\n if (when !== 'never' && resolvedGateIds.has(id)) {\n resolvedGateIds.delete(id)\n gate.resolve()\n }\n return gate\n}\n\nexport function releaseGate(gate: HydrationGateRecord) {\n resolvedGateIds.delete(gate.id)\n gate.consumers--\n if (gate.consumers > 0) return\n if (gateRegistry.get(gate.id) === gate) {\n gateRegistry.delete(gate.id)\n fallbackHtmlByGateId.delete(gate.id)\n gate.resolveListeners.clear()\n }\n}\n\nexport function onGateResolve(gate: HydrationGateRecord, listener: () => void) {\n if (gate.resolved) {\n listener()\n return () => {}\n }\n\n gate.resolveListeners.add(listener)\n return () => {\n gate.resolveListeners.delete(listener)\n }\n}\n\nexport function runHydrationStrategyCleanup(cleanup: void | (() => void)) {\n if (typeof cleanup === 'function') return cleanup\n return undefined\n}\n\nexport function waitForHydrationPrefetchStrategy(\n strategy: HydrationPrefetchStrategy,\n options: {\n element: Element | null\n signal: AbortSignal\n onHydrate: (listener: () => void) => () => void\n },\n): Promise<HydrationPrefetchWaitReason> {\n if (options.signal.aborted) {\n return Promise.resolve('abort')\n }\n\n return new Promise((resolve) => {\n const state = { disposed: false }\n const cleanupStrategyRef: { current: void | (() => void) } = {\n current: undefined,\n }\n let cleanupHydrate = () => {}\n\n const finish = (reason: HydrationPrefetchWaitReason) => {\n if (state.disposed) return\n state.disposed = true\n options.signal.removeEventListener('abort', onAbort)\n cleanupHydrate()\n runHydrationStrategyCleanup(cleanupStrategyRef.current)?.()\n resolve(reason)\n }\n\n const onAbort = () => finish('abort')\n\n options.signal.addEventListener('abort', onAbort, { once: true })\n cleanupHydrate = options.onHydrate(() => finish('hydrate'))\n const cleanupStrategy = strategy._s?.({\n element: options.element,\n prefetch: () => finish('prefetch'),\n })\n cleanupStrategyRef.current = cleanupStrategy\n if (state.disposed) {\n runHydrationStrategyCleanup(cleanupStrategy)?.()\n }\n })\n}\n\nexport function getMarkerGate(marker: Element) {\n const id = marker.getAttribute(hydrateIdAttribute)\n return id ? gateRegistry.get(id) : undefined\n}\n\nexport function resolveHydrationMarker(marker: Element) {\n const id = marker.getAttribute(hydrateIdAttribute)\n const when = marker.getAttribute(hydrateWhenAttribute)\n if (!id || !when || when === 'never') {\n return\n }\n\n const gate = gateRegistry.get(id)\n if (gate) {\n if (gate.when !== 'never') gate.resolve()\n return\n }\n\n resolvedGateIds.add(id)\n}\n\nexport function clearResolvedGateIdsInMarker(marker: Element) {\n const ownId = marker.getAttribute(hydrateIdAttribute)\n if (ownId) {\n resolvedGateIds.delete(ownId)\n }\n\n marker.querySelectorAll(hydrateIdSelector).forEach((childMarker) => {\n const childId = childMarker.getAttribute(hydrateIdAttribute)\n if (childId) {\n resolvedGateIds.delete(childId)\n }\n })\n}\n\nexport function saveFallbackHtml(id: string, element: Element) {\n if (!fallbackHtmlByGateId.has(id)) {\n fallbackHtmlByGateId.set(id, element.innerHTML)\n }\n}\n\nexport function getFallbackHtml(id: string) {\n return fallbackHtmlByGateId.get(id)\n}\n"],"mappings":"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"} |
| export type HydrationWhen = 'load' | 'idle' | 'visible' | 'media' | 'interaction' | 'condition' | 'never' | 'dynamic'; | ||
| export type HydrationInteractionEvent = 'auxclick' | 'click' | 'contextmenu' | 'dblclick' | 'focusin' | 'keydown' | 'keyup' | 'mousedown' | 'mouseenter' | 'mouseover' | 'mouseup' | 'pointerdown' | 'pointerenter' | 'pointerover' | 'pointerup'; | ||
| export type HydrationInteractionEvents = HydrationInteractionEvent | ReadonlyArray<HydrationInteractionEvent>; | ||
| export type HydrationMarkerAttributes = Record<string, string | undefined>; | ||
| export type HydrationRuntimeGate = { | ||
| id?: string; | ||
| when?: HydrationWhen; | ||
| resolved: boolean; | ||
| resolve: () => void; | ||
| }; | ||
| export type HydrationRuntimeContext = { | ||
| element: Element | null; | ||
| gate?: HydrationRuntimeGate; | ||
| prefetch?: () => void; | ||
| delegated?: boolean; | ||
| }; | ||
| export type HydrationStrategyTypes<TWhen extends HydrationWhen = HydrationWhen, TCanPrefetch extends boolean = boolean> = { | ||
| when: TWhen; | ||
| canPrefetch: TCanPrefetch; | ||
| }; | ||
| export type HydrationStrategy<TWhen extends HydrationWhen = HydrationWhen, TCanPrefetch extends boolean = boolean> = { | ||
| _t?: TWhen; | ||
| readonly '~types'?: HydrationStrategyTypes<TWhen, TCanPrefetch>; | ||
| _d?: () => boolean; | ||
| _s?: (context: HydrationRuntimeContext) => void | (() => void); | ||
| _o?: (id: string) => void; | ||
| _a?: () => HydrationMarkerAttributes | undefined; | ||
| }; | ||
| export type HydrationPrefetchWhen = Exclude<HydrationWhen, 'condition' | 'never' | 'dynamic'>; | ||
| export type HydrationPrefetchStrategy<TWhen extends HydrationPrefetchWhen = HydrationPrefetchWhen> = HydrationStrategy<TWhen, true>; | ||
| export type HydrationPrefetchWaitReason = 'prefetch' | 'hydrate' | 'abort'; | ||
| export type HydrationPrefetchContext = { | ||
| element: Element | null; | ||
| signal: AbortSignal; | ||
| preload: () => Promise<void>; | ||
| waitFor: (strategy: HydrationPrefetchStrategy) => Promise<HydrationPrefetchWaitReason>; | ||
| }; | ||
| export type HydrationPrefetchFunction = (context: HydrationPrefetchContext) => void | Promise<void>; |
| import { HydrationPrefetchStrategy } from './types.js'; | ||
| declare const visibleType = "visible"; | ||
| export type VisibleHydrationOptions = { | ||
| rootMargin?: string; | ||
| threshold?: number | Array<number>; | ||
| }; | ||
| export declare function visible(options?: VisibleHydrationOptions): HydrationPrefetchStrategy<typeof visibleType>; | ||
| export {}; |
| //#region src/hydration/visible.ts | ||
| var visibleType = "visible"; | ||
| var observerRegistry = /* @__PURE__ */ new Map(); | ||
| function cleanupVisibleObserverEntry(observerEntry) { | ||
| if (observerEntry.elements.size > 0) return; | ||
| observerEntry.observer.disconnect(); | ||
| observerRegistry.delete(observerEntry.key); | ||
| } | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| function visible(options = {}) { | ||
| const rootMargin = options.rootMargin ?? "600px"; | ||
| const threshold = options.threshold ?? 0; | ||
| return { | ||
| _t: visibleType, | ||
| _s: ({ element, gate, prefetch }) => { | ||
| const callback = prefetch ?? gate.resolve; | ||
| if (!element) { | ||
| callback(); | ||
| return; | ||
| } | ||
| const key = `${rootMargin}|${Array.isArray(threshold) ? threshold.join(",") : String(threshold)}`; | ||
| let observerEntry = observerRegistry.get(key); | ||
| if (!observerEntry) { | ||
| const entry = { | ||
| key, | ||
| elements: /* @__PURE__ */ new Map(), | ||
| observer: new IntersectionObserver((entries) => { | ||
| for (const intersectingEntry of entries) { | ||
| if (!intersectingEntry.isIntersecting) continue; | ||
| const callbacks = entry.elements.get(intersectingEntry.target); | ||
| if (!callbacks) continue; | ||
| callbacks.forEach((callback) => callback()); | ||
| entry.elements.delete(intersectingEntry.target); | ||
| entry.observer.unobserve(intersectingEntry.target); | ||
| cleanupVisibleObserverEntry(entry); | ||
| } | ||
| }, { | ||
| rootMargin, | ||
| threshold | ||
| }) | ||
| }; | ||
| observerRegistry.set(key, entry); | ||
| observerEntry = entry; | ||
| } | ||
| let callbacks = observerEntry.elements.get(element); | ||
| if (!callbacks) { | ||
| callbacks = /* @__PURE__ */ new Set(); | ||
| observerEntry.elements.set(element, callbacks); | ||
| observerEntry.observer.observe(element); | ||
| } | ||
| callbacks.add(callback); | ||
| return () => { | ||
| const currentCallbacks = observerEntry.elements.get(element); | ||
| currentCallbacks?.delete(callback); | ||
| if (currentCallbacks?.size === 0) { | ||
| observerEntry.elements.delete(element); | ||
| observerEntry.observer.unobserve(element); | ||
| } | ||
| cleanupVisibleObserverEntry(observerEntry); | ||
| }; | ||
| } | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { visible }; | ||
| //# sourceMappingURL=visible.js.map |
| {"version":3,"file":"visible.js","names":[],"sources":["../../../src/hydration/visible.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst visibleType = 'visible'\n\nexport type VisibleHydrationOptions = {\n rootMargin?: string\n threshold?: number | Array<number>\n}\n\ntype VisibleObserverEntry = {\n key: string\n observer: IntersectionObserver\n elements: Map<Element, Set<() => void>>\n}\n\nconst observerRegistry = /* @__PURE__ */ new Map<string, VisibleObserverEntry>()\n\nfunction cleanupVisibleObserverEntry(observerEntry: VisibleObserverEntry) {\n if (observerEntry.elements.size > 0) return\n observerEntry.observer.disconnect()\n observerRegistry.delete(observerEntry.key)\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function visible(\n options: VisibleHydrationOptions = {},\n): HydrationPrefetchStrategy<typeof visibleType> {\n const rootMargin = options.rootMargin ?? '600px'\n const threshold = options.threshold ?? 0\n\n return {\n _t: visibleType,\n _s: ({ element, gate, prefetch }) => {\n const callback = prefetch ?? gate!.resolve\n\n if (!element) {\n callback()\n return\n }\n\n const key = `${rootMargin}|${\n Array.isArray(threshold) ? threshold.join(',') : String(threshold)\n }`\n let observerEntry = observerRegistry.get(key)\n\n if (!observerEntry) {\n const entry: VisibleObserverEntry = {\n key,\n elements: new Map<Element, Set<() => void>>(),\n observer: new IntersectionObserver(\n (entries) => {\n for (const intersectingEntry of entries) {\n if (!intersectingEntry.isIntersecting) continue\n\n const callbacks = entry.elements.get(intersectingEntry.target)\n if (!callbacks) continue\n\n callbacks.forEach((callback) => callback())\n entry.elements.delete(intersectingEntry.target)\n entry.observer.unobserve(intersectingEntry.target)\n cleanupVisibleObserverEntry(entry)\n }\n },\n { rootMargin, threshold },\n ),\n }\n observerRegistry.set(key, entry)\n observerEntry = entry\n }\n\n let callbacks = observerEntry.elements.get(element)\n if (!callbacks) {\n callbacks = new Set()\n observerEntry.elements.set(element, callbacks)\n observerEntry.observer.observe(element)\n }\n callbacks.add(callback)\n\n return () => {\n const currentCallbacks = observerEntry.elements.get(element)\n currentCallbacks?.delete(callback)\n if (currentCallbacks?.size === 0) {\n observerEntry.elements.delete(element)\n observerEntry.observer.unobserve(element)\n }\n cleanupVisibleObserverEntry(observerEntry)\n }\n },\n }\n}\n"],"mappings":";AAEA,IAAM,cAAc;AAapB,IAAM,mCAAmC,IAAI,KAAmC;AAEhF,SAAS,4BAA4B,eAAqC;AACxE,KAAI,cAAc,SAAS,OAAO,EAAG;AACrC,eAAc,SAAS,YAAY;AACnC,kBAAiB,OAAO,cAAc,IAAI;;;AAI5C,SAAgB,QACd,UAAmC,EAAE,EACU;CAC/C,MAAM,aAAa,QAAQ,cAAc;CACzC,MAAM,YAAY,QAAQ,aAAa;AAEvC,QAAO;EACL,IAAI;EACJ,KAAK,EAAE,SAAS,MAAM,eAAe;GACnC,MAAM,WAAW,YAAY,KAAM;AAEnC,OAAI,CAAC,SAAS;AACZ,cAAU;AACV;;GAGF,MAAM,MAAM,GAAG,WAAW,GACxB,MAAM,QAAQ,UAAU,GAAG,UAAU,KAAK,IAAI,GAAG,OAAO,UAAU;GAEpE,IAAI,gBAAgB,iBAAiB,IAAI,IAAI;AAE7C,OAAI,CAAC,eAAe;IAClB,MAAM,QAA8B;KAClC;KACA,0BAAU,IAAI,KAA+B;KAC7C,UAAU,IAAI,sBACX,YAAY;AACX,WAAK,MAAM,qBAAqB,SAAS;AACvC,WAAI,CAAC,kBAAkB,eAAgB;OAEvC,MAAM,YAAY,MAAM,SAAS,IAAI,kBAAkB,OAAO;AAC9D,WAAI,CAAC,UAAW;AAEhB,iBAAU,SAAS,aAAa,UAAU,CAAC;AAC3C,aAAM,SAAS,OAAO,kBAAkB,OAAO;AAC/C,aAAM,SAAS,UAAU,kBAAkB,OAAO;AAClD,mCAA4B,MAAM;;QAGtC;MAAE;MAAY;MAAW,CAC1B;KACF;AACD,qBAAiB,IAAI,KAAK,MAAM;AAChC,oBAAgB;;GAGlB,IAAI,YAAY,cAAc,SAAS,IAAI,QAAQ;AACnD,OAAI,CAAC,WAAW;AACd,gCAAY,IAAI,KAAK;AACrB,kBAAc,SAAS,IAAI,SAAS,UAAU;AAC9C,kBAAc,SAAS,QAAQ,QAAQ;;AAEzC,aAAU,IAAI,SAAS;AAEvB,gBAAa;IACX,MAAM,mBAAmB,cAAc,SAAS,IAAI,QAAQ;AAC5D,sBAAkB,OAAO,SAAS;AAClC,QAAI,kBAAkB,SAAS,GAAG;AAChC,mBAAc,SAAS,OAAO,QAAQ;AACtC,mBAAc,SAAS,UAAU,QAAQ;;AAE3C,gCAA4B,cAAc;;;EAG/C"} |
| import { hydrateIdAttribute } from './hydration/constants' | ||
| export { condition } from './hydration/condition' | ||
| export type { HydrationCondition } from './hydration/condition' | ||
| export { | ||
| hydrateIdAttribute, | ||
| hydrateInteractionEventsAttribute, | ||
| hydrateWhenAttribute, | ||
| } from './hydration/constants' | ||
| export const hydrateIdSelector = `[${hydrateIdAttribute}]` | ||
| export { idle } from './hydration/idle' | ||
| export type { IdleHydrationOptions } from './hydration/idle' | ||
| export { interaction } from './hydration/interaction' | ||
| export { load } from './hydration/load' | ||
| export { media } from './hydration/media' | ||
| export { never } from './hydration/never' | ||
| export { | ||
| clearResolvedGateIdsInMarker, | ||
| createResolvedGate, | ||
| getFallbackHtml, | ||
| getMarkerGate, | ||
| getOrCreateGate, | ||
| onGateResolve, | ||
| releaseGate, | ||
| resolveHydrationMarker, | ||
| runHydrationStrategyCleanup, | ||
| saveFallbackHtml, | ||
| waitForHydrationPrefetchStrategy, | ||
| } from './hydration/runtime' | ||
| export { withHydrationRenderer } from './hydration/renderer' | ||
| export { visible } from './hydration/visible' | ||
| export { listenForDelegatedHydrationIntent } from './hydration/interaction' | ||
| export type { VisibleHydrationOptions } from './hydration/visible' | ||
| export type { HydrationGateRecord } from './hydration/runtime' | ||
| export type { HydrationStrategyWithRenderer } from './hydration/renderer' | ||
| export type { | ||
| HydrationInteractionEvent, | ||
| HydrationInteractionEvents, | ||
| HydrationMarkerAttributes, | ||
| HydrationPrefetchContext, | ||
| HydrationPrefetchFunction, | ||
| HydrationPrefetchWhen, | ||
| HydrationPrefetchStrategy, | ||
| HydrationPrefetchWaitReason, | ||
| HydrationRuntimeContext, | ||
| HydrationRuntimeGate, | ||
| HydrationStrategy, | ||
| HydrationStrategyTypes, | ||
| HydrationWhen, | ||
| } from './hydration/types' |
| import type { HydrationStrategy } from './types' | ||
| const conditionType = 'condition' | ||
| export type HydrationCondition = boolean | (() => boolean) | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| export function condition( | ||
| condition: HydrationCondition, | ||
| ): HydrationStrategy<typeof conditionType, false> { | ||
| return { | ||
| _t: conditionType, | ||
| _d: () => !(typeof condition === 'function' ? condition() : condition), | ||
| _s: ({ gate }) => { | ||
| if (typeof condition === 'function' ? condition() : condition) { | ||
| gate!.resolve() | ||
| } | ||
| }, | ||
| } | ||
| } |
| export const hydrateIdAttribute = 'data-ts-hydrate-id' | ||
| export const hydrateWhenAttribute = 'data-ts-hydrate-when' | ||
| export const hydrateInteractionEventsAttribute = | ||
| 'data-ts-hydrate-interaction-events' |
| import type { HydrationPrefetchStrategy } from './types' | ||
| const idleType = 'idle' | ||
| export type IdleHydrationOptions = { | ||
| timeout?: number | ||
| } | ||
| export function idle( | ||
| options: IdleHydrationOptions = {}, | ||
| ): HydrationPrefetchStrategy<typeof idleType> { | ||
| const timeout = options.timeout ?? 2000 | ||
| return { | ||
| _t: idleType, | ||
| _s: ({ gate, prefetch }) => { | ||
| const schedule = globalThis as unknown as { | ||
| requestIdleCallback?: ( | ||
| callback: IdleRequestCallback, | ||
| options?: IdleRequestOptions, | ||
| ) => number | ||
| cancelIdleCallback?: (handle: number) => void | ||
| } | ||
| const callback = prefetch ?? gate!.resolve | ||
| if (schedule.requestIdleCallback) { | ||
| const handle = schedule.requestIdleCallback(callback, { timeout }) | ||
| return () => schedule.cancelIdleCallback?.(handle) | ||
| } | ||
| const timeoutId = globalThis.setTimeout(callback, timeout) | ||
| return () => globalThis.clearTimeout(timeoutId) | ||
| }, | ||
| } | ||
| } |
| import { | ||
| hydrateIdAttribute, | ||
| hydrateInteractionEventsAttribute, | ||
| hydrateWhenAttribute, | ||
| } from './constants' | ||
| import { | ||
| clearResolvedGateIdsInMarker, | ||
| getMarkerGate, | ||
| resolveHydrationMarker, | ||
| } from './runtime' | ||
| import type { | ||
| HydrationInteractionEvents, | ||
| HydrationPrefetchStrategy, | ||
| HydrationRuntimeContext, | ||
| } from './types' | ||
| export type InteractionHydrationOptions = { | ||
| events?: HydrationInteractionEvents | ||
| } | ||
| const hydrateIdSelector = `[${hydrateIdAttribute}]` | ||
| type PendingReplayEvent = { | ||
| marker: Element | ||
| targetPath: Array<number> | ||
| type: string | ||
| event: Event | ||
| } | ||
| const defaultInteractionEvents = [ | ||
| 'pointerenter', | ||
| 'focusin', | ||
| 'pointerdown', | ||
| 'click', | ||
| ] as const | ||
| const supportedInteractionEvents = [ | ||
| 'auxclick', | ||
| 'click', | ||
| 'contextmenu', | ||
| 'dblclick', | ||
| 'focusin', | ||
| 'keydown', | ||
| 'keyup', | ||
| 'mousedown', | ||
| 'mouseenter', | ||
| 'mouseover', | ||
| 'mouseup', | ||
| 'pointerdown', | ||
| 'pointerenter', | ||
| 'pointerover', | ||
| 'pointerup', | ||
| ] as const | ||
| const interactionType = 'interaction' | ||
| const dynamicType = 'dynamic' | ||
| const interactionHydrateSelector = `[${hydrateWhenAttribute}="${interactionType}"]` | ||
| const delegatedHydrateSelector = `${interactionHydrateSelector},[${hydrateWhenAttribute}="${dynamicType}"]` | ||
| const replayEventsByGateId = /* @__PURE__ */ new Map< | ||
| string, | ||
| Array<PendingReplayEvent> | ||
| >() | ||
| function getIntentListenerEvents( | ||
| marker: Element, | ||
| events: ReadonlyArray<string>, | ||
| ) { | ||
| const listenerEvents = new Set(events) | ||
| marker.querySelectorAll(delegatedHydrateSelector).forEach((childMarker) => { | ||
| if (childMarker.getAttribute(hydrateWhenAttribute) === dynamicType) { | ||
| supportedInteractionEvents.forEach((eventName) => { | ||
| listenerEvents.add(eventName) | ||
| }) | ||
| return | ||
| } | ||
| const attr = childMarker.getAttribute(hydrateInteractionEventsAttribute) | ||
| for (const eventName of attr === null | ||
| ? defaultInteractionEvents | ||
| : attr.split(/\s+/).filter(Boolean)) { | ||
| listenerEvents.add(eventName) | ||
| } | ||
| }) | ||
| return [...listenerEvents] | ||
| } | ||
| function queueHydrationReplayEvent(marker: Element, event: Event) { | ||
| if (!event.bubbles) return | ||
| const id = marker.getAttribute(hydrateIdAttribute) | ||
| const when = marker.getAttribute(hydrateWhenAttribute) | ||
| if (!id || !when || when === 'never') return | ||
| const target = event.target | ||
| if (!target) return | ||
| const gate = getMarkerGate(marker) | ||
| if (gate?.resolved) return | ||
| event.preventDefault() | ||
| event.stopPropagation() | ||
| event.stopImmediatePropagation() | ||
| let targetPath: Array<number> = [] | ||
| if (target instanceof Node && marker.contains(target)) { | ||
| let node: Element | null = | ||
| target instanceof Element ? target : target.parentElement | ||
| while (node && node !== marker) { | ||
| const parent = node.parentElement | ||
| if (!parent) { | ||
| targetPath = [] | ||
| break | ||
| } | ||
| targetPath.push(Array.prototype.indexOf.call(parent.children, node)) | ||
| node = parent | ||
| } | ||
| targetPath.reverse() | ||
| } | ||
| const pendingEvents = replayEventsByGateId.get(id) ?? [] | ||
| pendingEvents.push({ | ||
| marker, | ||
| targetPath, | ||
| type: event.type, | ||
| event, | ||
| }) | ||
| replayEventsByGateId.set(id, pendingEvents) | ||
| } | ||
| if (typeof document !== 'undefined') { | ||
| const onIntent = (event: Event) => { | ||
| const target = event.target | ||
| if (!(target instanceof Element)) return | ||
| let marker: Element | null = target.closest(hydrateIdSelector) | ||
| const markers: Array<Element> = [] | ||
| let shouldHandle = false | ||
| while (marker) { | ||
| markers.push(marker) | ||
| const when = marker.getAttribute(hydrateWhenAttribute) | ||
| if (when === dynamicType) { | ||
| shouldHandle ||= event.type === 'click' | ||
| } else if (when === interactionType) { | ||
| const attr = marker.getAttribute(hydrateInteractionEventsAttribute) | ||
| const events: ReadonlyArray<string> = | ||
| attr === null | ||
| ? defaultInteractionEvents | ||
| : attr.split(/\s+/).filter(Boolean) | ||
| shouldHandle ||= events.includes(event.type) | ||
| } | ||
| marker = marker.parentElement?.closest(hydrateIdSelector) ?? null | ||
| } | ||
| if (!shouldHandle) return | ||
| markers.reverse() | ||
| if (markers.every((marker) => getMarkerGate(marker))) return | ||
| markers.forEach((marker) => { | ||
| queueHydrationReplayEvent(marker, event) | ||
| resolveHydrationMarker(marker) | ||
| }) | ||
| } | ||
| supportedInteractionEvents.forEach((eventName) => { | ||
| document.addEventListener(eventName, onIntent, true) | ||
| }) | ||
| } | ||
| function listenForIntent( | ||
| element: Element, | ||
| events: ReadonlyArray<string>, | ||
| context: HydrationRuntimeContext, | ||
| ) { | ||
| const onIntent = (event: Event) => { | ||
| const target = event.target | ||
| let marker: Element | null | ||
| if (target instanceof Element) { | ||
| const closestMarker = target.closest(hydrateIdSelector) | ||
| marker = | ||
| closestMarker && element.contains(closestMarker) | ||
| ? closestMarker | ||
| : element | ||
| } else { | ||
| marker = element | ||
| } | ||
| const markers: Array<Element> = [] | ||
| while (marker) { | ||
| if (marker.hasAttribute(hydrateIdAttribute)) { | ||
| markers.push(marker) | ||
| } | ||
| if (marker === element) break | ||
| marker = marker.parentElement | ||
| } | ||
| if (!markers.includes(element)) { | ||
| markers.push(element) | ||
| } | ||
| markers.reverse() | ||
| if ( | ||
| context.delegated && | ||
| !markers.some( | ||
| (marker) => | ||
| marker.getAttribute(hydrateWhenAttribute) === interactionType || | ||
| marker.getAttribute(hydrateWhenAttribute) === dynamicType, | ||
| ) | ||
| ) { | ||
| return | ||
| } | ||
| markers.forEach((marker) => { | ||
| queueHydrationReplayEvent(marker, event) | ||
| resolveHydrationMarker(marker) | ||
| }) | ||
| } | ||
| let disposed = false | ||
| events.forEach((eventName) => { | ||
| element.addEventListener(eventName, onIntent, true) | ||
| }) | ||
| return () => { | ||
| if (disposed) return | ||
| disposed = true | ||
| events.forEach((eventName) => { | ||
| element.removeEventListener(eventName, onIntent, true) | ||
| }) | ||
| } | ||
| } | ||
| export function listenForDelegatedHydrationIntent( | ||
| element: Element, | ||
| context: HydrationRuntimeContext, | ||
| ) { | ||
| const listenerEvents = getIntentListenerEvents(element, []) | ||
| if (!listenerEvents.length) return | ||
| const cleanupIntent = listenForIntent(element, listenerEvents, { | ||
| ...context, | ||
| delegated: true, | ||
| }) | ||
| return () => { | ||
| cleanupIntent() | ||
| clearResolvedGateIdsInMarker(element) | ||
| } | ||
| } | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| export function interaction( | ||
| options: InteractionHydrationOptions = {}, | ||
| ): HydrationPrefetchStrategy<typeof interactionType> { | ||
| let events: ReadonlyArray<string> = defaultInteractionEvents | ||
| if (options.events !== undefined) { | ||
| const eventList: ReadonlyArray<string> = | ||
| typeof options.events === 'string' ? [options.events] : options.events | ||
| const normalizedEvents: Array<string> = [] | ||
| const seen = new Set<string>() | ||
| for (const eventName of eventList) { | ||
| if (!eventName || seen.has(eventName)) continue | ||
| seen.add(eventName) | ||
| normalizedEvents.push(eventName) | ||
| } | ||
| events = normalizedEvents | ||
| } | ||
| const eventKey = events.join(' ') | ||
| return { | ||
| _t: interactionType, | ||
| _s: (context) => { | ||
| const element = context.element | ||
| if (!element) return | ||
| const prefetch = context.prefetch | ||
| if (prefetch) { | ||
| if (!events.length) return | ||
| let disposed = false | ||
| events.forEach((eventName) => { | ||
| element.addEventListener(eventName, prefetch, true) | ||
| }) | ||
| return () => { | ||
| if (disposed) return | ||
| disposed = true | ||
| events.forEach((eventName) => { | ||
| element.removeEventListener(eventName, prefetch, true) | ||
| }) | ||
| } | ||
| } | ||
| const listenerEvents = getIntentListenerEvents(element, events) | ||
| const cleanupIntent = listenerEvents.length | ||
| ? listenForIntent(element, listenerEvents, context) | ||
| : undefined | ||
| return () => { | ||
| cleanupIntent?.() | ||
| clearResolvedGateIdsInMarker(element) | ||
| } | ||
| }, | ||
| _o: (id) => { | ||
| globalThis.requestAnimationFrame(() => { | ||
| const pendingEvents = replayEventsByGateId.get(id) | ||
| if (!pendingEvents?.length) return | ||
| replayEventsByGateId.delete(id) | ||
| for (const pendingEvent of pendingEvents) { | ||
| let replayTarget: Element | null = pendingEvent.marker | ||
| for (const index of pendingEvent.targetPath) { | ||
| replayTarget = replayTarget.children[index] ?? null | ||
| if (!replayTarget) break | ||
| } | ||
| const event = pendingEvent.event | ||
| replayTarget ??= pendingEvent.marker | ||
| replayTarget.dispatchEvent( | ||
| event instanceof MouseEvent | ||
| ? new MouseEvent(event.type, event) | ||
| : event instanceof FocusEvent | ||
| ? new FocusEvent(event.type, event) | ||
| : new Event(event.type, event), | ||
| ) | ||
| } | ||
| }) | ||
| }, | ||
| _a: () => | ||
| options.events === undefined | ||
| ? undefined | ||
| : { | ||
| [hydrateInteractionEventsAttribute]: eventKey, | ||
| }, | ||
| } | ||
| } |
| import type { HydrationPrefetchStrategy } from './types' | ||
| const loadType = 'load' | ||
| const loadStrategy: HydrationPrefetchStrategy<typeof loadType> = { | ||
| _t: loadType, | ||
| _d: () => false, | ||
| _s: ({ gate, prefetch }) => { | ||
| ;(prefetch ?? gate!.resolve)() | ||
| }, | ||
| } | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| export function load(): HydrationPrefetchStrategy<typeof loadType> { | ||
| return loadStrategy | ||
| } |
| import type { HydrationPrefetchStrategy } from './types' | ||
| const mediaType = 'media' | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| export function media( | ||
| query: string, | ||
| ): HydrationPrefetchStrategy<typeof mediaType> { | ||
| return { | ||
| _t: mediaType, | ||
| _s: ({ gate, prefetch }) => { | ||
| if (!query) return | ||
| const callback = prefetch ?? gate!.resolve | ||
| const mediaQuery = window.matchMedia(query) | ||
| const onChange = () => { | ||
| if (mediaQuery.matches) callback() | ||
| } | ||
| mediaQuery.addEventListener('change', onChange) | ||
| onChange() | ||
| return () => mediaQuery.removeEventListener('change', onChange) | ||
| }, | ||
| } | ||
| } |
| import type { HydrationStrategy } from './types' | ||
| const neverType = 'never' | ||
| const neverStrategy: HydrationStrategy<typeof neverType, false> = { | ||
| _t: neverType, | ||
| _d: () => true, | ||
| } | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| export function never(): HydrationStrategy<typeof neverType, false> { | ||
| return neverStrategy | ||
| } |
| import type { HydrationStrategy } from './types' | ||
| export type HydrationStrategyWithRenderer< | ||
| TStrategy extends HydrationStrategy, | ||
| TRenderer, | ||
| > = TStrategy & { | ||
| _h: TRenderer | ||
| } | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| export function withHydrationRenderer< | ||
| TStrategy extends HydrationStrategy, | ||
| TRenderer, | ||
| >( | ||
| strategy: TStrategy, | ||
| renderer: TRenderer, | ||
| ): HydrationStrategyWithRenderer<TStrategy, TRenderer> { | ||
| return /* @__PURE__ */ Object.assign(strategy, { | ||
| _h: renderer, | ||
| }) | ||
| } |
| import { hydrateIdAttribute, hydrateWhenAttribute } from './constants' | ||
| import type { | ||
| HydrationPrefetchStrategy, | ||
| HydrationPrefetchWaitReason, | ||
| HydrationRuntimeGate, | ||
| HydrationWhen, | ||
| } from './types' | ||
| const hydrateIdSelector = `[${hydrateIdAttribute}]` | ||
| export type HydrationGateRecord = HydrationRuntimeGate & { | ||
| id: string | ||
| when: HydrationWhen | ||
| promise: Promise<void> | ||
| consumers: number | ||
| resolveListeners: Set<() => void> | ||
| } | ||
| const gateRegistry = /* @__PURE__ */ new Map<string, HydrationGateRecord>() | ||
| const resolvedGateIds = /* @__PURE__ */ new Set<string>() | ||
| const fallbackHtmlByGateId = /* @__PURE__ */ new Map<string, string>() | ||
| export function createResolvedGate( | ||
| id: string, | ||
| when: HydrationWhen, | ||
| ): HydrationGateRecord { | ||
| return { | ||
| id, | ||
| when, | ||
| promise: Promise.resolve(), | ||
| resolve: () => {}, | ||
| resolved: true, | ||
| consumers: 0, | ||
| resolveListeners: new Set<() => void>(), | ||
| } | ||
| } | ||
| export function getOrCreateGate( | ||
| id: string, | ||
| when: HydrationWhen, | ||
| ): HydrationGateRecord { | ||
| const existing = gateRegistry.get(id) | ||
| if (existing?.when === when) { | ||
| existing.consumers++ | ||
| return existing | ||
| } | ||
| let resolvePromise!: () => void | ||
| const promise = new Promise<void>((resolve) => { | ||
| resolvePromise = resolve | ||
| }) | ||
| const gate: HydrationGateRecord = { | ||
| id, | ||
| promise, | ||
| resolved: false, | ||
| consumers: 1, | ||
| when, | ||
| resolveListeners: new Set(), | ||
| resolve: () => { | ||
| if (gate.resolved) return | ||
| gate.resolved = true | ||
| resolvePromise() | ||
| gate.resolveListeners.forEach((listener) => listener()) | ||
| gate.resolveListeners.clear() | ||
| }, | ||
| } | ||
| gateRegistry.set(id, gate) | ||
| if (when !== 'never' && resolvedGateIds.has(id)) { | ||
| resolvedGateIds.delete(id) | ||
| gate.resolve() | ||
| } | ||
| return gate | ||
| } | ||
| export function releaseGate(gate: HydrationGateRecord) { | ||
| resolvedGateIds.delete(gate.id) | ||
| gate.consumers-- | ||
| if (gate.consumers > 0) return | ||
| if (gateRegistry.get(gate.id) === gate) { | ||
| gateRegistry.delete(gate.id) | ||
| fallbackHtmlByGateId.delete(gate.id) | ||
| gate.resolveListeners.clear() | ||
| } | ||
| } | ||
| export function onGateResolve(gate: HydrationGateRecord, listener: () => void) { | ||
| if (gate.resolved) { | ||
| listener() | ||
| return () => {} | ||
| } | ||
| gate.resolveListeners.add(listener) | ||
| return () => { | ||
| gate.resolveListeners.delete(listener) | ||
| } | ||
| } | ||
| export function runHydrationStrategyCleanup(cleanup: void | (() => void)) { | ||
| if (typeof cleanup === 'function') return cleanup | ||
| return undefined | ||
| } | ||
| export function waitForHydrationPrefetchStrategy( | ||
| strategy: HydrationPrefetchStrategy, | ||
| options: { | ||
| element: Element | null | ||
| signal: AbortSignal | ||
| onHydrate: (listener: () => void) => () => void | ||
| }, | ||
| ): Promise<HydrationPrefetchWaitReason> { | ||
| if (options.signal.aborted) { | ||
| return Promise.resolve('abort') | ||
| } | ||
| return new Promise((resolve) => { | ||
| const state = { disposed: false } | ||
| const cleanupStrategyRef: { current: void | (() => void) } = { | ||
| current: undefined, | ||
| } | ||
| let cleanupHydrate = () => {} | ||
| const finish = (reason: HydrationPrefetchWaitReason) => { | ||
| if (state.disposed) return | ||
| state.disposed = true | ||
| options.signal.removeEventListener('abort', onAbort) | ||
| cleanupHydrate() | ||
| runHydrationStrategyCleanup(cleanupStrategyRef.current)?.() | ||
| resolve(reason) | ||
| } | ||
| const onAbort = () => finish('abort') | ||
| options.signal.addEventListener('abort', onAbort, { once: true }) | ||
| cleanupHydrate = options.onHydrate(() => finish('hydrate')) | ||
| const cleanupStrategy = strategy._s?.({ | ||
| element: options.element, | ||
| prefetch: () => finish('prefetch'), | ||
| }) | ||
| cleanupStrategyRef.current = cleanupStrategy | ||
| if (state.disposed) { | ||
| runHydrationStrategyCleanup(cleanupStrategy)?.() | ||
| } | ||
| }) | ||
| } | ||
| export function getMarkerGate(marker: Element) { | ||
| const id = marker.getAttribute(hydrateIdAttribute) | ||
| return id ? gateRegistry.get(id) : undefined | ||
| } | ||
| export function resolveHydrationMarker(marker: Element) { | ||
| const id = marker.getAttribute(hydrateIdAttribute) | ||
| const when = marker.getAttribute(hydrateWhenAttribute) | ||
| if (!id || !when || when === 'never') { | ||
| return | ||
| } | ||
| const gate = gateRegistry.get(id) | ||
| if (gate) { | ||
| if (gate.when !== 'never') gate.resolve() | ||
| return | ||
| } | ||
| resolvedGateIds.add(id) | ||
| } | ||
| export function clearResolvedGateIdsInMarker(marker: Element) { | ||
| const ownId = marker.getAttribute(hydrateIdAttribute) | ||
| if (ownId) { | ||
| resolvedGateIds.delete(ownId) | ||
| } | ||
| marker.querySelectorAll(hydrateIdSelector).forEach((childMarker) => { | ||
| const childId = childMarker.getAttribute(hydrateIdAttribute) | ||
| if (childId) { | ||
| resolvedGateIds.delete(childId) | ||
| } | ||
| }) | ||
| } | ||
| export function saveFallbackHtml(id: string, element: Element) { | ||
| if (!fallbackHtmlByGateId.has(id)) { | ||
| fallbackHtmlByGateId.set(id, element.innerHTML) | ||
| } | ||
| } | ||
| export function getFallbackHtml(id: string) { | ||
| return fallbackHtmlByGateId.get(id) | ||
| } |
| export type HydrationWhen = | ||
| | 'load' | ||
| | 'idle' | ||
| | 'visible' | ||
| | 'media' | ||
| | 'interaction' | ||
| | 'condition' | ||
| | 'never' | ||
| | 'dynamic' | ||
| export type HydrationInteractionEvent = | ||
| | 'auxclick' | ||
| | 'click' | ||
| | 'contextmenu' | ||
| | 'dblclick' | ||
| | 'focusin' | ||
| | 'keydown' | ||
| | 'keyup' | ||
| | 'mousedown' | ||
| | 'mouseenter' | ||
| | 'mouseover' | ||
| | 'mouseup' | ||
| | 'pointerdown' | ||
| | 'pointerenter' | ||
| | 'pointerover' | ||
| | 'pointerup' | ||
| export type HydrationInteractionEvents = | ||
| | HydrationInteractionEvent | ||
| | ReadonlyArray<HydrationInteractionEvent> | ||
| export type HydrationMarkerAttributes = Record<string, string | undefined> | ||
| export type HydrationRuntimeGate = { | ||
| id?: string | ||
| when?: HydrationWhen | ||
| resolved: boolean | ||
| resolve: () => void | ||
| } | ||
| export type HydrationRuntimeContext = { | ||
| element: Element | null | ||
| gate?: HydrationRuntimeGate | ||
| prefetch?: () => void | ||
| delegated?: boolean | ||
| } | ||
| export type HydrationStrategyTypes< | ||
| TWhen extends HydrationWhen = HydrationWhen, | ||
| TCanPrefetch extends boolean = boolean, | ||
| > = { | ||
| when: TWhen | ||
| canPrefetch: TCanPrefetch | ||
| } | ||
| export type HydrationStrategy< | ||
| TWhen extends HydrationWhen = HydrationWhen, | ||
| TCanPrefetch extends boolean = boolean, | ||
| > = { | ||
| _t?: TWhen | ||
| readonly '~types'?: HydrationStrategyTypes<TWhen, TCanPrefetch> | ||
| _d?: () => boolean | ||
| _s?: (context: HydrationRuntimeContext) => void | (() => void) | ||
| _o?: (id: string) => void | ||
| _a?: () => HydrationMarkerAttributes | undefined | ||
| } | ||
| export type HydrationPrefetchWhen = Exclude< | ||
| HydrationWhen, | ||
| 'condition' | 'never' | 'dynamic' | ||
| > | ||
| export type HydrationPrefetchStrategy< | ||
| TWhen extends HydrationPrefetchWhen = HydrationPrefetchWhen, | ||
| > = HydrationStrategy<TWhen, true> | ||
| export type HydrationPrefetchWaitReason = 'prefetch' | 'hydrate' | 'abort' | ||
| export type HydrationPrefetchContext = { | ||
| element: Element | null | ||
| signal: AbortSignal | ||
| preload: () => Promise<void> | ||
| waitFor: ( | ||
| strategy: HydrationPrefetchStrategy, | ||
| ) => Promise<HydrationPrefetchWaitReason> | ||
| } | ||
| export type HydrationPrefetchFunction = ( | ||
| context: HydrationPrefetchContext, | ||
| ) => void | Promise<void> |
| import type { HydrationPrefetchStrategy } from './types' | ||
| const visibleType = 'visible' | ||
| export type VisibleHydrationOptions = { | ||
| rootMargin?: string | ||
| threshold?: number | Array<number> | ||
| } | ||
| type VisibleObserverEntry = { | ||
| key: string | ||
| observer: IntersectionObserver | ||
| elements: Map<Element, Set<() => void>> | ||
| } | ||
| const observerRegistry = /* @__PURE__ */ new Map<string, VisibleObserverEntry>() | ||
| function cleanupVisibleObserverEntry(observerEntry: VisibleObserverEntry) { | ||
| if (observerEntry.elements.size > 0) return | ||
| observerEntry.observer.disconnect() | ||
| observerRegistry.delete(observerEntry.key) | ||
| } | ||
| /* @__NO_SIDE_EFFECTS__ */ | ||
| export function visible( | ||
| options: VisibleHydrationOptions = {}, | ||
| ): HydrationPrefetchStrategy<typeof visibleType> { | ||
| const rootMargin = options.rootMargin ?? '600px' | ||
| const threshold = options.threshold ?? 0 | ||
| return { | ||
| _t: visibleType, | ||
| _s: ({ element, gate, prefetch }) => { | ||
| const callback = prefetch ?? gate!.resolve | ||
| if (!element) { | ||
| callback() | ||
| return | ||
| } | ||
| const key = `${rootMargin}|${ | ||
| Array.isArray(threshold) ? threshold.join(',') : String(threshold) | ||
| }` | ||
| let observerEntry = observerRegistry.get(key) | ||
| if (!observerEntry) { | ||
| const entry: VisibleObserverEntry = { | ||
| key, | ||
| elements: new Map<Element, Set<() => void>>(), | ||
| observer: new IntersectionObserver( | ||
| (entries) => { | ||
| for (const intersectingEntry of entries) { | ||
| if (!intersectingEntry.isIntersecting) continue | ||
| const callbacks = entry.elements.get(intersectingEntry.target) | ||
| if (!callbacks) continue | ||
| callbacks.forEach((callback) => callback()) | ||
| entry.elements.delete(intersectingEntry.target) | ||
| entry.observer.unobserve(intersectingEntry.target) | ||
| cleanupVisibleObserverEntry(entry) | ||
| } | ||
| }, | ||
| { rootMargin, threshold }, | ||
| ), | ||
| } | ||
| observerRegistry.set(key, entry) | ||
| observerEntry = entry | ||
| } | ||
| let callbacks = observerEntry.elements.get(element) | ||
| if (!callbacks) { | ||
| callbacks = new Set() | ||
| observerEntry.elements.set(element, callbacks) | ||
| observerEntry.observer.observe(element) | ||
| } | ||
| callbacks.add(callback) | ||
| return () => { | ||
| const currentCallbacks = observerEntry.elements.get(element) | ||
| currentCallbacks?.delete(callback) | ||
| if (currentCallbacks?.size === 0) { | ||
| observerEntry.elements.delete(element) | ||
| observerEntry.observer.unobserve(element) | ||
| } | ||
| cleanupVisibleObserverEntry(observerEntry) | ||
| } | ||
| }, | ||
| } | ||
| } |
| import { AnyRouter } from '@tanstack/router-core'; | ||
| export declare function hydrateStart(): Promise<AnyRouter>; | ||
| type HotContext = { | ||
| data?: Record<string, unknown>; | ||
| dispose?: (cb: (data: Record<string, unknown>) => void) => void; | ||
| }; | ||
| declare global { | ||
| interface ImportMeta { | ||
| hot?: HotContext; | ||
| webpackHot?: HotContext; | ||
| } | ||
| } | ||
| declare function hydrateStart(): Promise<AnyRouter>; | ||
| declare const exportedHydrateStart: typeof hydrateStart; | ||
| export { exportedHydrateStart as hydrateStart }; |
@@ -30,5 +30,24 @@ import { ServerFunctionSerializationAdapter } from "./ServerFunctionSerializationAdapter.js"; | ||
| } | ||
| function hydrateStartWithHmr() { | ||
| const hot = import.meta.hot ?? import.meta.webpackHot; | ||
| if (!hot) return hydrateStart(); | ||
| const key = "tss-hydrate-start-promise"; | ||
| const hotData = hot.data ??= {}; | ||
| let hydrationPromise = hotData[key]; | ||
| if (!hydrationPromise) { | ||
| hydrationPromise = hydrateStart().catch((error) => { | ||
| if (hotData[key] === hydrationPromise) hotData[key] = void 0; | ||
| throw error; | ||
| }); | ||
| hotData[key] = hydrationPromise; | ||
| } | ||
| hot.dispose?.((data) => { | ||
| data[key] = hotData[key]; | ||
| }); | ||
| return hydrationPromise; | ||
| } | ||
| var exportedHydrateStart = process.env.NODE_ENV !== "production" ? hydrateStartWithHmr : hydrateStart; | ||
| //#endregion | ||
| export { hydrateStart }; | ||
| export { exportedHydrateStart }; | ||
| //# sourceMappingURL=hydrateStart.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"hydrateStart.js","names":[],"sources":["../../../src/client/hydrateStart.ts"],"sourcesContent":["import { hydrate } from '@tanstack/router-core/ssr/client'\n\nimport { startInstance } from '#tanstack-start-entry'\nimport {\n hasPluginAdapters,\n pluginSerializationAdapters,\n} from '#tanstack-start-plugin-adapters'\nimport { getRouter } from '#tanstack-router-entry'\nimport { ServerFunctionSerializationAdapter } from './ServerFunctionSerializationAdapter'\nimport type { AnyRouter, AnySerializationAdapter } from '@tanstack/router-core'\nimport type { AnyStartInstanceOptions } from '../createStart'\n\nexport async function hydrateStart(): Promise<AnyRouter> {\n const router = await getRouter()\n\n let serializationAdapters: Array<AnySerializationAdapter>\n if (startInstance) {\n const startOptions = await startInstance.getOptions()\n startOptions.serializationAdapters =\n startOptions.serializationAdapters ?? []\n window.__TSS_START_OPTIONS__ = startOptions as AnyStartInstanceOptions\n serializationAdapters = startOptions.serializationAdapters\n router.options.defaultSsr = startOptions.defaultSsr\n } else {\n serializationAdapters = []\n window.__TSS_START_OPTIONS__ = {\n serializationAdapters,\n } as AnyStartInstanceOptions\n }\n\n // Only spread plugin adapters if any are configured (this will tree-shake away otherwise)\n if (hasPluginAdapters) {\n serializationAdapters.push(...pluginSerializationAdapters)\n }\n serializationAdapters.push(ServerFunctionSerializationAdapter)\n if (router.options.serializationAdapters) {\n serializationAdapters.push(...router.options.serializationAdapters)\n }\n\n router.update({\n basepath: process.env.TSS_ROUTER_BASEPATH,\n ...{ serializationAdapters },\n })\n if (!router.stores.matchesId.get().length) {\n await hydrate(router)\n }\n\n return router\n}\n"],"mappings":";;;;;;AAYA,eAAsB,eAAmC;CACvD,MAAM,SAAS,MAAM,WAAW;CAEhC,IAAI;AACJ,KAAI,eAAe;EACjB,MAAM,eAAe,MAAM,cAAc,YAAY;AACrD,eAAa,wBACX,aAAa,yBAAyB,EAAE;AAC1C,SAAO,wBAAwB;AAC/B,0BAAwB,aAAa;AACrC,SAAO,QAAQ,aAAa,aAAa;QACpC;AACL,0BAAwB,EAAE;AAC1B,SAAO,wBAAwB,EAC7B,uBACD;;AAIH,KAAI,kBACF,uBAAsB,KAAK,GAAG,4BAA4B;AAE5D,uBAAsB,KAAK,mCAAmC;AAC9D,KAAI,OAAO,QAAQ,sBACjB,uBAAsB,KAAK,GAAG,OAAO,QAAQ,sBAAsB;AAGrE,QAAO,OAAO;EACZ,UAAU,QAAQ,IAAI;EACjB;EACN,CAAC;AACF,KAAI,CAAC,OAAO,OAAO,UAAU,KAAK,CAAC,OACjC,OAAM,QAAQ,OAAO;AAGvB,QAAO"} | ||
| {"version":3,"file":"hydrateStart.js","names":[],"sources":["../../../src/client/hydrateStart.ts"],"sourcesContent":["import { hydrate } from '@tanstack/router-core/ssr/client'\nimport { startInstance } from '#tanstack-start-entry'\nimport {\n hasPluginAdapters,\n pluginSerializationAdapters,\n} from '#tanstack-start-plugin-adapters'\nimport { getRouter } from '#tanstack-router-entry'\nimport { ServerFunctionSerializationAdapter } from './ServerFunctionSerializationAdapter'\nimport type { AnyRouter, AnySerializationAdapter } from '@tanstack/router-core'\nimport type { AnyStartInstanceOptions } from '../createStart'\n\ntype HotContext = {\n data?: Record<string, unknown>\n dispose?: (cb: (data: Record<string, unknown>) => void) => void\n}\n\ndeclare global {\n interface ImportMeta {\n hot?: HotContext\n webpackHot?: HotContext\n }\n}\n\nasync function hydrateStart(): Promise<AnyRouter> {\n const router = await getRouter()\n\n let serializationAdapters: Array<AnySerializationAdapter>\n if (startInstance) {\n const startOptions = await startInstance.getOptions()\n startOptions.serializationAdapters =\n startOptions.serializationAdapters ?? []\n window.__TSS_START_OPTIONS__ = startOptions as AnyStartInstanceOptions\n serializationAdapters = startOptions.serializationAdapters\n router.options.defaultSsr = startOptions.defaultSsr\n } else {\n serializationAdapters = []\n window.__TSS_START_OPTIONS__ = {\n serializationAdapters,\n } as AnyStartInstanceOptions\n }\n\n // Only spread plugin adapters if any are configured (this will tree-shake away otherwise)\n if (hasPluginAdapters) {\n serializationAdapters.push(...pluginSerializationAdapters)\n }\n serializationAdapters.push(ServerFunctionSerializationAdapter)\n if (router.options.serializationAdapters) {\n serializationAdapters.push(...router.options.serializationAdapters)\n }\n\n router.update({\n basepath: process.env.TSS_ROUTER_BASEPATH,\n ...{ serializationAdapters },\n })\n if (!router.stores.matchesId.get().length) {\n await hydrate(router)\n }\n\n return router\n}\n\nfunction hydrateStartWithHmr(): Promise<AnyRouter> {\n const hot = import.meta.hot ?? import.meta.webpackHot\n\n if (!hot) {\n return hydrateStart()\n }\n\n const key = 'tss-hydrate-start-promise'\n const hotData = (hot.data ??= {})\n let hydrationPromise = hotData[key] as Promise<AnyRouter> | undefined\n\n if (!hydrationPromise) {\n hydrationPromise = hydrateStart().catch((error) => {\n if (hotData[key] === hydrationPromise) {\n hotData[key] = undefined\n }\n\n throw error\n })\n\n hotData[key] = hydrationPromise\n }\n\n hot.dispose?.((data) => {\n data[key] = hotData[key]\n })\n\n return hydrationPromise\n}\n\nconst exportedHydrateStart =\n process.env.NODE_ENV !== 'production' ? hydrateStartWithHmr : hydrateStart\n\nexport { exportedHydrateStart as hydrateStart }\n"],"mappings":";;;;;;AAuBA,eAAe,eAAmC;CAChD,MAAM,SAAS,MAAM,WAAW;CAEhC,IAAI;AACJ,KAAI,eAAe;EACjB,MAAM,eAAe,MAAM,cAAc,YAAY;AACrD,eAAa,wBACX,aAAa,yBAAyB,EAAE;AAC1C,SAAO,wBAAwB;AAC/B,0BAAwB,aAAa;AACrC,SAAO,QAAQ,aAAa,aAAa;QACpC;AACL,0BAAwB,EAAE;AAC1B,SAAO,wBAAwB,EAC7B,uBACD;;AAIH,KAAI,kBACF,uBAAsB,KAAK,GAAG,4BAA4B;AAE5D,uBAAsB,KAAK,mCAAmC;AAC9D,KAAI,OAAO,QAAQ,sBACjB,uBAAsB,KAAK,GAAG,OAAO,QAAQ,sBAAsB;AAGrE,QAAO,OAAO;EACZ,UAAU,QAAQ,IAAI;EACjB;EACN,CAAC;AACF,KAAI,CAAC,OAAO,OAAO,UAAU,KAAK,CAAC,OACjC,OAAM,QAAQ,OAAO;AAGvB,QAAO;;AAGT,SAAS,sBAA0C;CACjD,MAAM,MAAA,OAAA,KAAA,OAAyB,OAAO,KAAK;AAE3C,KAAI,CAAC,IACH,QAAO,cAAc;CAGvB,MAAM,MAAM;CACZ,MAAM,UAAW,IAAI,SAAS,EAAE;CAChC,IAAI,mBAAmB,QAAQ;AAE/B,KAAI,CAAC,kBAAkB;AACrB,qBAAmB,cAAc,CAAC,OAAO,UAAU;AACjD,OAAI,QAAQ,SAAS,iBACnB,SAAQ,OAAO,KAAA;AAGjB,SAAM;IACN;AAEF,UAAQ,OAAO;;AAGjB,KAAI,WAAW,SAAS;AACtB,OAAK,OAAO,QAAQ;GACpB;AAEF,QAAO;;AAGT,IAAM,uBAAA,QAAA,IAAA,aACqB,eAAe,sBAAsB"} |
@@ -1,2 +0,2 @@ | ||
| import { hydrateStart } from "./hydrateStart.js"; | ||
| export { hydrateStart }; | ||
| import { exportedHydrateStart } from "./hydrateStart.js"; | ||
| export { exportedHydrateStart as hydrateStart }; |
+24
-3
| { | ||
| "name": "@tanstack/start-client-core", | ||
| "version": "1.169.4", | ||
| "version": "1.170.0", | ||
| "description": "Modern and scalable routing for React applications", | ||
@@ -47,2 +47,20 @@ "author": "Tanner Linsley", | ||
| }, | ||
| "./hydration": { | ||
| "import": { | ||
| "types": "./dist/esm/hydration.d.ts", | ||
| "default": "./dist/esm/hydration.js" | ||
| } | ||
| }, | ||
| "./hydration/constants": { | ||
| "import": { | ||
| "types": "./dist/esm/hydration/constants.d.ts", | ||
| "default": "./dist/esm/hydration/constants.js" | ||
| } | ||
| }, | ||
| "./hydration/runtime": { | ||
| "import": { | ||
| "types": "./dist/esm/hydration/runtime.d.ts", | ||
| "default": "./dist/esm/hydration/runtime.js" | ||
| } | ||
| }, | ||
| "./package.json": "./package.json" | ||
@@ -52,8 +70,11 @@ }, | ||
| "#tanstack-start-entry": { | ||
| "types": "./src/start-entry.d.ts", | ||
| "default": "./dist/esm/fake-entries/start.js" | ||
| }, | ||
| "#tanstack-router-entry": { | ||
| "types": "./src/start-entry.d.ts", | ||
| "default": "./dist/esm/fake-entries/router.js" | ||
| }, | ||
| "#tanstack-start-plugin-adapters": { | ||
| "types": "./src/start-entry.d.ts", | ||
| "default": "./dist/esm/fake-entries/plugin-adapters.js" | ||
@@ -75,5 +96,5 @@ } | ||
| "seroval": "^1.5.4", | ||
| "@tanstack/router-core": "1.171.2", | ||
| "@tanstack/router-core": "1.171.3", | ||
| "@tanstack/start-fn-stubs": "1.162.0", | ||
| "@tanstack/start-storage-context": "1.167.4" | ||
| "@tanstack/start-storage-context": "1.167.5" | ||
| }, | ||
@@ -80,0 +101,0 @@ "devDependencies": { |
| import { hydrate } from '@tanstack/router-core/ssr/client' | ||
| import { startInstance } from '#tanstack-start-entry' | ||
@@ -13,3 +12,15 @@ import { | ||
| export async function hydrateStart(): Promise<AnyRouter> { | ||
| type HotContext = { | ||
| data?: Record<string, unknown> | ||
| dispose?: (cb: (data: Record<string, unknown>) => void) => void | ||
| } | ||
| declare global { | ||
| interface ImportMeta { | ||
| hot?: HotContext | ||
| webpackHot?: HotContext | ||
| } | ||
| } | ||
| async function hydrateStart(): Promise<AnyRouter> { | ||
| const router = await getRouter() | ||
@@ -51,1 +62,36 @@ | ||
| } | ||
| function hydrateStartWithHmr(): Promise<AnyRouter> { | ||
| const hot = import.meta.hot ?? import.meta.webpackHot | ||
| if (!hot) { | ||
| return hydrateStart() | ||
| } | ||
| const key = 'tss-hydrate-start-promise' | ||
| const hotData = (hot.data ??= {}) | ||
| let hydrationPromise = hotData[key] as Promise<AnyRouter> | undefined | ||
| if (!hydrationPromise) { | ||
| hydrationPromise = hydrateStart().catch((error) => { | ||
| if (hotData[key] === hydrationPromise) { | ||
| hotData[key] = undefined | ||
| } | ||
| throw error | ||
| }) | ||
| hotData[key] = hydrationPromise | ||
| } | ||
| hot.dispose?.((data) => { | ||
| data[key] = hotData[key] | ||
| }) | ||
| return hydrationPromise | ||
| } | ||
| const exportedHydrateStart = | ||
| process.env.NODE_ENV !== 'production' ? hydrateStartWithHmr : hydrateStart | ||
| export { exportedHydrateStart as hydrateStart } |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
529437
19.45%152
43.4%8368
21.72%13
18.18%+ Added
+ Added
- Removed
- Removed