kiru 0.50.0-preview.0 → 0.50.0-preview.1
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/dist/components/lazy.d.ts.map +1 -1
- package/dist/components/lazy.js +11 -136
- package/dist/components/lazy.js.map +1 -1
- package/dist/components/suspense.d.ts +7 -6
- package/dist/components/suspense.d.ts.map +1 -1
- package/dist/components/suspense.js +1 -4
- package/dist/components/suspense.js.map +1 -1
- package/dist/constants.d.ts +1 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -2
- package/dist/constants.js.map +1 -1
- package/dist/hmr.d.ts +1 -0
- package/dist/hmr.d.ts.map +1 -1
- package/dist/hmr.js +7 -0
- package/dist/hmr.js.map +1 -1
- package/dist/recursiveRender.d.ts +6 -0
- package/dist/recursiveRender.d.ts.map +1 -0
- package/dist/recursiveRender.js +109 -0
- package/dist/recursiveRender.js.map +1 -0
- package/dist/renderToString.d.ts.map +1 -1
- package/dist/renderToString.js +6 -112
- package/dist/renderToString.js.map +1 -1
- package/dist/router/config.d.ts +3 -0
- package/dist/router/config.d.ts.map +1 -0
- package/dist/router/config.js +13 -0
- package/dist/router/config.js.map +1 -0
- package/dist/router/context.d.ts +15 -0
- package/dist/router/context.d.ts.map +1 -0
- package/dist/router/context.js +11 -0
- package/dist/router/context.js.map +1 -0
- package/dist/router/errors.d.ts +4 -0
- package/dist/router/errors.d.ts.map +1 -0
- package/dist/router/errors.js +7 -0
- package/dist/router/errors.js.map +1 -0
- package/dist/router/fileRouter.d.ts +48 -0
- package/dist/router/fileRouter.d.ts.map +1 -0
- package/dist/router/fileRouter.js +311 -0
- package/dist/router/fileRouter.js.map +1 -0
- package/dist/router/globals.d.ts +5 -0
- package/dist/router/globals.d.ts.map +1 -0
- package/dist/router/globals.js +4 -0
- package/dist/router/globals.js.map +1 -0
- package/dist/router/index.d.ts +7 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +7 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/link.d.ts +8 -0
- package/dist/router/link.d.ts.map +1 -0
- package/dist/router/link.js +15 -0
- package/dist/router/link.js.map +1 -0
- package/dist/router/types.d.ts +63 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.internal.d.ts +12 -0
- package/dist/router/types.internal.d.ts.map +1 -0
- package/dist/router/types.internal.js +2 -0
- package/dist/router/types.internal.js.map +1 -0
- package/dist/router/types.js +2 -0
- package/dist/router/types.js.map +1 -0
- package/dist/ssr/server.d.ts.map +1 -1
- package/dist/ssr/server.js +5 -109
- package/dist/ssr/server.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.utils.d.ts +1 -8
- package/dist/types.utils.d.ts.map +1 -1
- package/dist/utils/vdom.d.ts.map +1 -1
- package/dist/utils/vdom.js +2 -5
- package/dist/utils/vdom.js.map +1 -1
- package/package.json +4 -8
- package/src/components/lazy.ts +12 -169
- package/src/components/suspense.ts +8 -10
- package/src/constants.ts +0 -2
- package/src/hmr.ts +8 -0
- package/src/recursiveRender.ts +127 -0
- package/src/renderToString.ts +7 -137
- package/src/router/config.ts +15 -0
- package/src/router/context.ts +23 -0
- package/src/router/errors.ts +6 -0
- package/src/router/fileRouter.ts +475 -0
- package/src/router/globals.ts +5 -0
- package/src/router/index.ts +6 -0
- package/src/router/link.ts +32 -0
- package/src/router/types.internal.ts +14 -0
- package/src/router/types.ts +81 -0
- package/src/ssr/server.ts +6 -136
- package/src/types.ts +0 -2
- package/src/types.utils.ts +1 -14
- package/src/utils/vdom.ts +1 -5
- package/dist/components/router/index.d.ts +0 -3
- package/dist/components/router/index.d.ts.map +0 -1
- package/dist/components/router/index.js +0 -3
- package/dist/components/router/index.js.map +0 -1
- package/dist/components/router/route.d.ts +0 -46
- package/dist/components/router/route.d.ts.map +0 -1
- package/dist/components/router/route.js +0 -8
- package/dist/components/router/route.js.map +0 -1
- package/dist/components/router/router.d.ts +0 -62
- package/dist/components/router/router.d.ts.map +0 -1
- package/dist/components/router/router.js +0 -177
- package/dist/components/router/router.js.map +0 -1
- package/dist/components/router/routerUtils.d.ts +0 -5
- package/dist/components/router/routerUtils.d.ts.map +0 -1
- package/dist/components/router/routerUtils.js +0 -39
- package/dist/components/router/routerUtils.js.map +0 -1
- package/dist/ssr/hydrationBoundary.d.ts +0 -27
- package/dist/ssr/hydrationBoundary.d.ts.map +0 -1
- package/dist/ssr/hydrationBoundary.js +0 -30
- package/dist/ssr/hydrationBoundary.js.map +0 -1
- package/dist/ssr/index.d.ts +0 -2
- package/dist/ssr/index.d.ts.map +0 -1
- package/dist/ssr/index.js +0 -2
- package/dist/ssr/index.js.map +0 -1
- package/src/components/router/index.ts +0 -2
- package/src/components/router/route.ts +0 -51
- package/src/components/router/router.ts +0 -273
- package/src/components/router/routerUtils.ts +0 -49
- package/src/ssr/hydrationBoundary.ts +0 -63
- package/src/ssr/index.ts +0 -1
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { createContext } from "../context.js";
|
|
2
|
-
import { $HYDRATION_BOUNDARY } from "../constants.js";
|
|
3
|
-
import { createElement, Fragment } from "../element.js";
|
|
4
|
-
import { renderMode } from "../globals.js";
|
|
5
|
-
export const HYDRATION_BOUNDARY_MARKER = "kiru:h-boundary";
|
|
6
|
-
export const DEFAULT_INTERACTION_EVENTS = [
|
|
7
|
-
"pointerdown",
|
|
8
|
-
"keydown",
|
|
9
|
-
"focus",
|
|
10
|
-
"input",
|
|
11
|
-
];
|
|
12
|
-
export const HydrationBoundaryContext = createContext(null);
|
|
13
|
-
export function Experimental_HydrationBoundary(props) {
|
|
14
|
-
const provider = createElement(HydrationBoundaryContext.Provider, {
|
|
15
|
-
value: {
|
|
16
|
-
mode: props.mode || "eager",
|
|
17
|
-
// @ts-expect-error this is fine
|
|
18
|
-
events: props.events ?? DEFAULT_INTERACTION_EVENTS,
|
|
19
|
-
},
|
|
20
|
-
}, createElement($HYDRATION_BOUNDARY, props));
|
|
21
|
-
if (renderMode.current === "string" || renderMode.current === "stream") {
|
|
22
|
-
/**
|
|
23
|
-
* in order to ensure consistent tree structure, we're simulating
|
|
24
|
-
* the generated loader + wrapper components here.
|
|
25
|
-
*/
|
|
26
|
-
return Fragment({ children: Fragment({ children: provider }) });
|
|
27
|
-
}
|
|
28
|
-
return provider;
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=hydrationBoundary.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hydrationBoundary.js","sourceRoot":"","sources":["../../src/ssr/hydrationBoundary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAI1C,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAA;AAC1D,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,aAAa;IACb,SAAS;IACT,OAAO;IACP,OAAO;CACuB,CAAA;AAsBhC,MAAM,CAAC,MAAM,wBAAwB,GAAG,aAAa,CAGlD,IAAK,CAAC,CAAA;AAET,MAAM,UAAU,8BAA8B,CAC5C,KAAgC;IAEhC,MAAM,QAAQ,GAAG,aAAa,CAC5B,wBAAwB,CAAC,QAAQ,EACjC;QACE,KAAK,EAAE;YACL,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,OAAO;YAC3B,gCAAgC;YAChC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,0BAA0B;SACnD;KACF,EACD,aAAa,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAC1C,CAAA;IACD,IAAI,UAAU,CAAC,OAAO,KAAK,QAAQ,IAAI,UAAU,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACvE;;;WAGG;QACH,OAAO,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAA;IACjE,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC"}
|
package/dist/ssr/index.d.ts
DELETED
package/dist/ssr/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ssr/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA"}
|
package/dist/ssr/index.js
DELETED
package/dist/ssr/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ssr/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA"}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { isVNode } from "../../utils/index.js"
|
|
2
|
-
|
|
3
|
-
interface RouteProps {
|
|
4
|
-
/**
|
|
5
|
-
* The path to match.
|
|
6
|
-
* @example
|
|
7
|
-
* ```tsx
|
|
8
|
-
* <Router>
|
|
9
|
-
* <Route path="/" element={<h1>Home</h1>} />
|
|
10
|
-
* <Route path="/:id" element={<UserProfile />} />
|
|
11
|
-
* </Router>
|
|
12
|
-
* //
|
|
13
|
-
* const UserProfile = () => {
|
|
14
|
-
* const router = useRouter()
|
|
15
|
-
* const { id } = router.params
|
|
16
|
-
* return <h1>{id}</h1>
|
|
17
|
-
* }
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
path: string
|
|
21
|
-
/**
|
|
22
|
-
* Allow url with additional segments being matched. Useful with nested routers.
|
|
23
|
-
* @example
|
|
24
|
-
* ```tsx
|
|
25
|
-
* <Route path="/profile" fallthrough element={<UserProfile />} />
|
|
26
|
-
* //
|
|
27
|
-
* const UserProfile = () => {
|
|
28
|
-
* return (
|
|
29
|
-
* <Router>
|
|
30
|
-
* <Route path="/" element={<UserDetails />} />
|
|
31
|
-
* <Route path="/update" element={<UserUpdateForm />} />
|
|
32
|
-
* </Router>
|
|
33
|
-
* )
|
|
34
|
-
* }
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
|
-
fallthrough?: boolean
|
|
38
|
-
/**
|
|
39
|
-
* The element to render.
|
|
40
|
-
*/
|
|
41
|
-
element: JSX.Element
|
|
42
|
-
}
|
|
43
|
-
export function Route({ element }: RouteProps) {
|
|
44
|
-
return element
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function isRoute(
|
|
48
|
-
thing: unknown
|
|
49
|
-
): thing is Kiru.VNode & { props: RouteProps } {
|
|
50
|
-
return isVNode(thing) && thing.type === Route
|
|
51
|
-
}
|
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
import { createElement } from "../../element.js"
|
|
2
|
-
import {
|
|
3
|
-
useState,
|
|
4
|
-
useMemo,
|
|
5
|
-
useContext,
|
|
6
|
-
useLayoutEffect,
|
|
7
|
-
useRef,
|
|
8
|
-
} from "../../hooks/index.js"
|
|
9
|
-
import { __DEV__ } from "../../env.js"
|
|
10
|
-
import { createContext } from "../../context.js"
|
|
11
|
-
import { isRoute, Route } from "./route.js"
|
|
12
|
-
import { noop } from "../../utils/index.js"
|
|
13
|
-
import { node } from "../../globals.js"
|
|
14
|
-
import type { ElementProps } from "../../types.js"
|
|
15
|
-
import { flushSync, nextIdle } from "../../scheduler.js"
|
|
16
|
-
import {
|
|
17
|
-
parsePathParams,
|
|
18
|
-
parseSearchParams,
|
|
19
|
-
routeMatchesPath,
|
|
20
|
-
} from "./routerUtils.js"
|
|
21
|
-
|
|
22
|
-
export interface LinkProps extends Omit<ElementProps<"a">, "href"> {
|
|
23
|
-
/**
|
|
24
|
-
* The relative path to navigate to. If `inherit` is true,
|
|
25
|
-
* the path will be relative to the parent <Route> component.
|
|
26
|
-
*/
|
|
27
|
-
to: string
|
|
28
|
-
/**
|
|
29
|
-
* Event handler called when the link is clicked.
|
|
30
|
-
* If you call `e.preventDefault()`, the navigation will not happen.
|
|
31
|
-
*/
|
|
32
|
-
onclick?: (e: Event) => void
|
|
33
|
-
/**
|
|
34
|
-
* Specifies whether to replace the current history entry
|
|
35
|
-
* instead of adding a new one.
|
|
36
|
-
*/
|
|
37
|
-
replace?: boolean
|
|
38
|
-
/**
|
|
39
|
-
* If true, the path used for `to` will be relative to the parent <Route> component.
|
|
40
|
-
* @default false
|
|
41
|
-
*/
|
|
42
|
-
inherit?: boolean
|
|
43
|
-
}
|
|
44
|
-
export function Link({ to, onclick, replace, inherit, ...props }: LinkProps) {
|
|
45
|
-
const router = useContext(RouterContext, false)
|
|
46
|
-
|
|
47
|
-
const href = useMemo(() => {
|
|
48
|
-
if (!inherit || router.isDefault) return to
|
|
49
|
-
const parentPath = Object.entries(router.params).reduce(
|
|
50
|
-
(acc, [k, v]) => acc.replace(`:${k}`, v),
|
|
51
|
-
router.routePath
|
|
52
|
-
)
|
|
53
|
-
if (to === "/") return parentPath
|
|
54
|
-
return (parentPath + to).replaceAll(/\/+/g, "/")
|
|
55
|
-
}, [router.params, to, inherit])
|
|
56
|
-
|
|
57
|
-
return createElement("a", {
|
|
58
|
-
...props,
|
|
59
|
-
href,
|
|
60
|
-
onclick: (e: Event) => {
|
|
61
|
-
onclick?.(e)
|
|
62
|
-
if (e.defaultPrevented) return
|
|
63
|
-
e.preventDefault()
|
|
64
|
-
navigate(href, { replace })
|
|
65
|
-
},
|
|
66
|
-
})
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
type RouterCtx = {
|
|
70
|
-
viewTransition: Kiru.RefObject<ViewTransition>
|
|
71
|
-
queueSyncNav: (callback: () => void) => void
|
|
72
|
-
params: Record<string, string>
|
|
73
|
-
query: Record<string, string>
|
|
74
|
-
routePath: string
|
|
75
|
-
basePath?: string
|
|
76
|
-
isDefault: boolean
|
|
77
|
-
}
|
|
78
|
-
const RouterContext = createContext<RouterCtx>({
|
|
79
|
-
viewTransition: { current: null },
|
|
80
|
-
queueSyncNav: noop,
|
|
81
|
-
params: {},
|
|
82
|
-
query: {},
|
|
83
|
-
routePath: "/",
|
|
84
|
-
isDefault: true,
|
|
85
|
-
})
|
|
86
|
-
RouterContext.displayName = "Router"
|
|
87
|
-
|
|
88
|
-
function setQuery(query: Record<string, string>) {
|
|
89
|
-
const url = new URL(window.location.href)
|
|
90
|
-
Object.entries(query).forEach(([k, v]) => url.searchParams.set(k, v))
|
|
91
|
-
window.history.pushState({}, "", url.toString())
|
|
92
|
-
window.dispatchEvent(new PopStateEvent("popstate", { state: {} }))
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Gets state and methods provided by a parent <Router>.
|
|
97
|
-
*
|
|
98
|
-
* @see https://kirujs.dev/docs/api/routing
|
|
99
|
-
*/
|
|
100
|
-
export function useRouter() {
|
|
101
|
-
const { viewTransition, params, query } = useContext(RouterContext)
|
|
102
|
-
return { viewTransition, params, query, setQuery }
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export function navigate(to: string, options?: { replace?: boolean }) {
|
|
106
|
-
const doNav = () => {
|
|
107
|
-
window.history[options?.replace ? "replaceState" : "pushState"]({}, "", to)
|
|
108
|
-
window.dispatchEvent(new PopStateEvent("popstate", { state: {} }))
|
|
109
|
-
}
|
|
110
|
-
// not called during render, just do the navigation
|
|
111
|
-
if (!node.current) return doNav(), null
|
|
112
|
-
|
|
113
|
-
const routerCtx = useContext(RouterContext, false)
|
|
114
|
-
if (routerCtx.isDefault) {
|
|
115
|
-
/**
|
|
116
|
-
* called from a non-router-decendant - postpone
|
|
117
|
-
* until next tick to avoid race conditions
|
|
118
|
-
*/
|
|
119
|
-
return nextIdle(doNav), null
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* set the value of our router's syncNavCallback,
|
|
123
|
-
* causing it to be executed synchronously
|
|
124
|
-
* during the router's useLayoutEffect.
|
|
125
|
-
* consecutive calls to navigate will overwrite
|
|
126
|
-
* the previous value.
|
|
127
|
-
*/
|
|
128
|
-
return routerCtx.queueSyncNav(doNav), null
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export interface RouterProps {
|
|
132
|
-
/**
|
|
133
|
-
* Base path for all routes in this router. Use this
|
|
134
|
-
* to add a prefix to all routes
|
|
135
|
-
*/
|
|
136
|
-
basePath?: string
|
|
137
|
-
/**
|
|
138
|
-
* Enable ViewTransition API for navigations
|
|
139
|
-
*/
|
|
140
|
-
transition?: boolean
|
|
141
|
-
/**
|
|
142
|
-
* Children to render - the only supported children are <Route> components
|
|
143
|
-
*/
|
|
144
|
-
children?: JSX.Children
|
|
145
|
-
}
|
|
146
|
-
const initLoc = () => ({
|
|
147
|
-
pathname: window.location.pathname,
|
|
148
|
-
search: window.location.search,
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Main router component.
|
|
153
|
-
*
|
|
154
|
-
* @see https://kirujs.dev/docs/api/routing
|
|
155
|
-
*/
|
|
156
|
-
export function Router(props: RouterProps) {
|
|
157
|
-
const viewTransition = useRef<ViewTransition | null>(null)
|
|
158
|
-
const syncNavCallback = useRef<(() => void) | null>(null)
|
|
159
|
-
const parentRouterContext = useContext(RouterContext, false)
|
|
160
|
-
const dynamicParentPath = parentRouterContext.isDefault
|
|
161
|
-
? null
|
|
162
|
-
: parentRouterContext.routePath
|
|
163
|
-
const dynamicParentPathSegments = useMemo(
|
|
164
|
-
() => dynamicParentPath?.split("/").filter(Boolean) || [],
|
|
165
|
-
[dynamicParentPath]
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
const [loc, setLoc] = useState(initLoc)
|
|
169
|
-
const query = useMemo(() => parseSearchParams(loc.search), [loc.search])
|
|
170
|
-
const realPathSegments = useMemo(
|
|
171
|
-
() => loc.pathname.split("/").filter(Boolean),
|
|
172
|
-
[loc.pathname]
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
useLayoutEffect(() => {
|
|
176
|
-
const handler = () => {
|
|
177
|
-
if (!document.startViewTransition || !props.transition) {
|
|
178
|
-
return setLoc({
|
|
179
|
-
pathname: window.location.pathname,
|
|
180
|
-
search: window.location.search,
|
|
181
|
-
})
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
viewTransition.current = document.startViewTransition(() => {
|
|
185
|
-
setLoc({
|
|
186
|
-
pathname: window.location.pathname,
|
|
187
|
-
search: window.location.search,
|
|
188
|
-
})
|
|
189
|
-
flushSync()
|
|
190
|
-
})
|
|
191
|
-
viewTransition.current.finished.then(() => {
|
|
192
|
-
viewTransition.current = null
|
|
193
|
-
})
|
|
194
|
-
}
|
|
195
|
-
window.addEventListener("popstate", handler)
|
|
196
|
-
return () => window.removeEventListener("popstate", handler)
|
|
197
|
-
}, [])
|
|
198
|
-
|
|
199
|
-
useLayoutEffect(() => {
|
|
200
|
-
if (syncNavCallback.current) {
|
|
201
|
-
syncNavCallback.current()
|
|
202
|
-
syncNavCallback.current = null
|
|
203
|
-
}
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
type RouteComponent = Kiru.VNode & {
|
|
207
|
-
props: Kiru.InferProps<typeof Route>
|
|
208
|
-
}
|
|
209
|
-
let fallbackRoute: RouteComponent | undefined
|
|
210
|
-
let route: RouteComponent | undefined
|
|
211
|
-
const _children = (
|
|
212
|
-
Array.isArray(props.children) ? props.children : [props.children]
|
|
213
|
-
).flat()
|
|
214
|
-
|
|
215
|
-
for (const child of _children) {
|
|
216
|
-
if (!isRoute(child)) continue
|
|
217
|
-
|
|
218
|
-
if (child.props.path === "*") {
|
|
219
|
-
if (__DEV__) {
|
|
220
|
-
if (fallbackRoute) {
|
|
221
|
-
console.warn(
|
|
222
|
-
"[kiru]: More than one fallback route defined. Only the last one will be used."
|
|
223
|
-
)
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
fallbackRoute = child
|
|
227
|
-
continue
|
|
228
|
-
}
|
|
229
|
-
const dynamicChildPathSegments = ((props.basePath || "") + child.props.path)
|
|
230
|
-
.split("/")
|
|
231
|
-
.filter(Boolean)
|
|
232
|
-
if (
|
|
233
|
-
routeMatchesPath(
|
|
234
|
-
dynamicParentPathSegments.concat(dynamicChildPathSegments),
|
|
235
|
-
realPathSegments,
|
|
236
|
-
child.props.fallthrough
|
|
237
|
-
)
|
|
238
|
-
) {
|
|
239
|
-
route = child
|
|
240
|
-
break
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
let parsedParams = {}
|
|
245
|
-
if (route) {
|
|
246
|
-
const dynamicChildPathSegments = ((props.basePath || "") + route.props.path)
|
|
247
|
-
.split("/")
|
|
248
|
-
.filter(Boolean)
|
|
249
|
-
parsedParams = parsePathParams(
|
|
250
|
-
dynamicParentPathSegments.concat(dynamicChildPathSegments),
|
|
251
|
-
realPathSegments
|
|
252
|
-
)
|
|
253
|
-
}
|
|
254
|
-
const params = { ...parentRouterContext.params, ...parsedParams }
|
|
255
|
-
|
|
256
|
-
return RouterContext.Provider({
|
|
257
|
-
value: {
|
|
258
|
-
params,
|
|
259
|
-
query,
|
|
260
|
-
routePath:
|
|
261
|
-
(dynamicParentPath || "") +
|
|
262
|
-
(props.basePath || "") +
|
|
263
|
-
(route?.props.path || ""),
|
|
264
|
-
basePath: props.basePath,
|
|
265
|
-
isDefault: false,
|
|
266
|
-
queueSyncNav: (callback: () => void) => {
|
|
267
|
-
syncNavCallback.current = callback
|
|
268
|
-
},
|
|
269
|
-
viewTransition: viewTransition,
|
|
270
|
-
},
|
|
271
|
-
children: route ?? fallbackRoute ?? null,
|
|
272
|
-
})
|
|
273
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
export { routeMatchesPath, parsePathParams, parseSearchParams }
|
|
2
|
-
|
|
3
|
-
function routeMatchesPath(
|
|
4
|
-
dynamicPathSegments: string[],
|
|
5
|
-
realPathSegments: string[],
|
|
6
|
-
fallthrough?: boolean
|
|
7
|
-
) {
|
|
8
|
-
if (!fallthrough && dynamicPathSegments.length < realPathSegments.length) {
|
|
9
|
-
return false
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
for (let i = 0; i < dynamicPathSegments.length; i++) {
|
|
13
|
-
const segment = dynamicPathSegments[i]
|
|
14
|
-
if (segment.startsWith(":")) {
|
|
15
|
-
continue
|
|
16
|
-
} else if (segment !== realPathSegments[i]) {
|
|
17
|
-
return false
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return true
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function parsePathParams(
|
|
25
|
-
dynamicPathSegments: string[],
|
|
26
|
-
realPathSegments: string[]
|
|
27
|
-
) {
|
|
28
|
-
const params: Record<string, string> = {}
|
|
29
|
-
for (let i = 0; i < dynamicPathSegments.length; i++) {
|
|
30
|
-
const segment = dynamicPathSegments[i]
|
|
31
|
-
if (segment.startsWith(":")) {
|
|
32
|
-
params[segment.slice(1)] = realPathSegments[i]
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return params
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function parseSearchParams(search: string) {
|
|
39
|
-
const parsed: Record<string, string> = {}
|
|
40
|
-
const str = search.split("?")[1]
|
|
41
|
-
if (!str || str === "") return parsed
|
|
42
|
-
|
|
43
|
-
const parts = str.split("&")
|
|
44
|
-
for (let i = 0; i < parts.length; i++) {
|
|
45
|
-
const [key, val] = parts[i].split("=")
|
|
46
|
-
parsed[key] = val
|
|
47
|
-
}
|
|
48
|
-
return parsed
|
|
49
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { createContext } from "../context.js"
|
|
2
|
-
import { $HYDRATION_BOUNDARY } from "../constants.js"
|
|
3
|
-
import { createElement, Fragment } from "../element.js"
|
|
4
|
-
import { renderMode } from "../globals.js"
|
|
5
|
-
|
|
6
|
-
type EventsArray = (keyof GlobalEventHandlersEventMap)[]
|
|
7
|
-
|
|
8
|
-
export const HYDRATION_BOUNDARY_MARKER = "kiru:h-boundary"
|
|
9
|
-
export const DEFAULT_INTERACTION_EVENTS = [
|
|
10
|
-
"pointerdown",
|
|
11
|
-
"keydown",
|
|
12
|
-
"focus",
|
|
13
|
-
"input",
|
|
14
|
-
] as const satisfies EventsArray
|
|
15
|
-
|
|
16
|
-
export type HydrationBoundaryMode = "eager" | "interaction"
|
|
17
|
-
export type HydrationBoundaryProps<T extends HydrationBoundaryMode> = {
|
|
18
|
-
/**
|
|
19
|
-
* Determines the strategy to use when hydrating the boundary.
|
|
20
|
-
* - `eager`: hydrate immediately.
|
|
21
|
-
* - `interaction`: hydrate upon the first user interaction.
|
|
22
|
-
* @default "eager"
|
|
23
|
-
*/
|
|
24
|
-
mode?: T
|
|
25
|
-
children: JSX.Children
|
|
26
|
-
} & (T extends "interaction"
|
|
27
|
-
? {
|
|
28
|
-
/**
|
|
29
|
-
* List of events that will trigger the hydration.
|
|
30
|
-
* @default ["pointerdown", "keydown", "focus", "input"]
|
|
31
|
-
*/
|
|
32
|
-
events?: EventsArray
|
|
33
|
-
}
|
|
34
|
-
: {})
|
|
35
|
-
|
|
36
|
-
export const HydrationBoundaryContext = createContext<{
|
|
37
|
-
mode: HydrationBoundaryMode
|
|
38
|
-
events: string[]
|
|
39
|
-
}>(null!)
|
|
40
|
-
|
|
41
|
-
export function Experimental_HydrationBoundary<T extends HydrationBoundaryMode>(
|
|
42
|
-
props: HydrationBoundaryProps<T>
|
|
43
|
-
) {
|
|
44
|
-
const provider = createElement(
|
|
45
|
-
HydrationBoundaryContext.Provider,
|
|
46
|
-
{
|
|
47
|
-
value: {
|
|
48
|
-
mode: props.mode || "eager",
|
|
49
|
-
// @ts-expect-error this is fine
|
|
50
|
-
events: props.events ?? DEFAULT_INTERACTION_EVENTS,
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
createElement($HYDRATION_BOUNDARY, props)
|
|
54
|
-
)
|
|
55
|
-
if (renderMode.current === "string" || renderMode.current === "stream") {
|
|
56
|
-
/**
|
|
57
|
-
* in order to ensure consistent tree structure, we're simulating
|
|
58
|
-
* the generated loader + wrapper components here.
|
|
59
|
-
*/
|
|
60
|
-
return Fragment({ children: Fragment({ children: provider }) })
|
|
61
|
-
}
|
|
62
|
-
return provider
|
|
63
|
-
}
|
package/src/ssr/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./hydrationBoundary.js"
|