react-statepod 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +514 -0
- package/dist/index.cjs +324 -0
- package/dist/index.d.ts +171 -0
- package/dist/index.mjs +300 -0
- package/index.ts +24 -0
- package/package.json +49 -0
- package/src/A.tsx +8 -0
- package/src/Area.tsx +8 -0
- package/src/RouteContext.ts +6 -0
- package/src/RouteProvider.tsx +30 -0
- package/src/TransientStateContext.ts +7 -0
- package/src/TransientStateProvider.tsx +40 -0
- package/src/URLContext.ts +6 -0
- package/src/URLProvider.tsx +28 -0
- package/src/types/AProps.ts +6 -0
- package/src/types/AreaProps.ts +6 -0
- package/src/types/EnhanceHref.ts +8 -0
- package/src/types/LinkNavigationProps.ts +8 -0
- package/src/types/RenderCallback.ts +4 -0
- package/src/types/TransientState.ts +6 -0
- package/src/useExternalState.ts +75 -0
- package/src/useLinkProps.ts +38 -0
- package/src/useNavigationComplete.ts +11 -0
- package/src/useNavigationStart.ts +9 -0
- package/src/useRoute.ts +19 -0
- package/src/useRouteLinks.ts +22 -0
- package/src/useRouteState.ts +56 -0
- package/src/useTransientState.ts +191 -0
- package/src/useURL.ts +9 -0
- package/tsconfig.json +18 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let statepod = require("statepod");
|
|
3
|
+
let react = require("react");
|
|
4
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
|
+
|
|
6
|
+
const RouteContext = (0, react.createContext)(new statepod.Route(null, { autoStart: false }));
|
|
7
|
+
|
|
8
|
+
const defaultRenderCallback = (render) => render();
|
|
9
|
+
function useExternalState(state, callback = defaultRenderCallback, event) {
|
|
10
|
+
if (!(0, statepod.isState)(state)) throw new TypeError("'state' is not an instance of State");
|
|
11
|
+
let [, setRevision] = (0, react.useState)(-1);
|
|
12
|
+
let setValue = (0, react.useMemo)(() => state.setValue.bind(state), [state]);
|
|
13
|
+
let initialStateRevision = (0, react.useRef)(state.revision);
|
|
14
|
+
let shouldUpdate = (0, react.useRef)(false);
|
|
15
|
+
(0, react.useEffect)(() => {
|
|
16
|
+
state.start();
|
|
17
|
+
if (callback === false) return;
|
|
18
|
+
shouldUpdate.current = true;
|
|
19
|
+
let render = () => {
|
|
20
|
+
if (shouldUpdate.current) setRevision(Math.random());
|
|
21
|
+
};
|
|
22
|
+
let resolvedCallback = typeof callback === "function" ? callback : defaultRenderCallback;
|
|
23
|
+
let unsubscribe = state.on(event ?? "update", (payload) => {
|
|
24
|
+
resolvedCallback(render, payload);
|
|
25
|
+
});
|
|
26
|
+
if (state.revision !== initialStateRevision.current) render();
|
|
27
|
+
return () => {
|
|
28
|
+
unsubscribe();
|
|
29
|
+
initialStateRevision.current = state.revision;
|
|
30
|
+
shouldUpdate.current = false;
|
|
31
|
+
};
|
|
32
|
+
}, [
|
|
33
|
+
state,
|
|
34
|
+
callback,
|
|
35
|
+
event
|
|
36
|
+
]);
|
|
37
|
+
return [state.getValue(), setValue];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function useRoute(callback) {
|
|
41
|
+
let route = (0, react.useContext)(RouteContext);
|
|
42
|
+
useExternalState(route, callback, "navigation");
|
|
43
|
+
return (0, react.useMemo)(() => ({
|
|
44
|
+
route,
|
|
45
|
+
at: route.at.bind(route)
|
|
46
|
+
}), [route]);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function useLinkProps({ href, target, onClick, ...props }) {
|
|
50
|
+
let { at, route } = useRoute();
|
|
51
|
+
let handleClick = (0, react.useCallback)((event) => {
|
|
52
|
+
onClick?.(event);
|
|
53
|
+
if (!event.defaultPrevented && (0, statepod.isRouteEvent)(event) && (!target || target === "_self")) {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
route.navigate((0, statepod.getNavigationOptions)(event.currentTarget));
|
|
56
|
+
}
|
|
57
|
+
}, [
|
|
58
|
+
route,
|
|
59
|
+
target,
|
|
60
|
+
onClick
|
|
61
|
+
]);
|
|
62
|
+
return {
|
|
63
|
+
...props,
|
|
64
|
+
href: href && String(href),
|
|
65
|
+
target,
|
|
66
|
+
onClick: handleClick,
|
|
67
|
+
"data-active": at(href, true)
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const A = ({ children, ...props }) => {
|
|
72
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
73
|
+
...useLinkProps(props),
|
|
74
|
+
children
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const Area = ({ alt, ...props }) => {
|
|
79
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("area", {
|
|
80
|
+
...useLinkProps(props),
|
|
81
|
+
alt
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* A component providing a Route instance to the nested components.
|
|
87
|
+
*/
|
|
88
|
+
const RouteProvider = ({ href, children }) => {
|
|
89
|
+
let route = (0, react.useMemo)(() => {
|
|
90
|
+
if (href instanceof statepod.Route) return href;
|
|
91
|
+
else if (href === void 0 || typeof href === "string") return new statepod.Route(href);
|
|
92
|
+
else throw new Error("URLProvider's 'href' of unsupported type");
|
|
93
|
+
}, [href]);
|
|
94
|
+
(0, react.useEffect)(() => {
|
|
95
|
+
route.start();
|
|
96
|
+
return () => route.stop();
|
|
97
|
+
}, [route]);
|
|
98
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RouteContext.Provider, {
|
|
99
|
+
value: route,
|
|
100
|
+
children
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const TransientStateContext = (0, react.createContext)(/* @__PURE__ */ new Map());
|
|
105
|
+
|
|
106
|
+
const TransientStateProvider = ({ value, children }) => {
|
|
107
|
+
let defaultValueRef = (0, react.useRef)(null);
|
|
108
|
+
let stateMap = (0, react.useMemo)(() => {
|
|
109
|
+
if (value instanceof Map) return value;
|
|
110
|
+
if (typeof value === "object" && value !== null) return new Map(Object.entries(value).map(([key, value]) => [key, new statepod.State(value)]));
|
|
111
|
+
if (defaultValueRef.current === null) defaultValueRef.current = /* @__PURE__ */ new Map();
|
|
112
|
+
return defaultValueRef.current;
|
|
113
|
+
}, [value]);
|
|
114
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TransientStateContext.Provider, {
|
|
115
|
+
value: stateMap,
|
|
116
|
+
children
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const URLContext = (0, react.createContext)(new statepod.URLState(null, { autoStart: false }));
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* A component providing a URL value to the nested components.
|
|
124
|
+
*/
|
|
125
|
+
const URLProvider = ({ href, children }) => {
|
|
126
|
+
let urlState = (0, react.useMemo)(() => {
|
|
127
|
+
if (href instanceof statepod.URLState) return href;
|
|
128
|
+
else if (href === void 0 || typeof href === "string") return new statepod.URLState(href);
|
|
129
|
+
else throw new Error("URLProvider's 'href' of unsupported type");
|
|
130
|
+
}, [href]);
|
|
131
|
+
(0, react.useEffect)(() => {
|
|
132
|
+
urlState.start();
|
|
133
|
+
return () => urlState.stop();
|
|
134
|
+
}, [urlState]);
|
|
135
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(URLContext.Provider, {
|
|
136
|
+
value: urlState,
|
|
137
|
+
children
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
function useNavigationComplete(callback) {
|
|
142
|
+
let route = (0, react.useContext)(RouteContext);
|
|
143
|
+
(0, react.useEffect)(() => route.on("navigationcomplete", callback), [route, callback]);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function useNavigationStart(callback) {
|
|
147
|
+
let route = (0, react.useContext)(RouteContext);
|
|
148
|
+
(0, react.useEffect)(() => route.on("navigationstart", callback), [route, callback]);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Converts plain HTML links to SPA route links.
|
|
153
|
+
*
|
|
154
|
+
* @param containerRef - A React Ref pointing to a container element.
|
|
155
|
+
* @param elements - An optional selector, or an HTML element, or a
|
|
156
|
+
* collection thereof, specifying the links inside the container to
|
|
157
|
+
* be converted to SPA route links. Default: `"a, area"`.
|
|
158
|
+
*/
|
|
159
|
+
function useRouteLinks(containerRef, elements) {
|
|
160
|
+
let route = (0, react.useContext)(RouteContext);
|
|
161
|
+
(0, react.useEffect)(() => {
|
|
162
|
+
return route.observe(() => containerRef.current, elements);
|
|
163
|
+
}, [
|
|
164
|
+
route,
|
|
165
|
+
elements,
|
|
166
|
+
containerRef
|
|
167
|
+
]);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Reads and sets URL parameters in a way similar to React's `useState()`.
|
|
172
|
+
* This hooks returns `[state, setState]`, where `state` contains path
|
|
173
|
+
* placeholder parameters and query parameters, `{ params?, query? }`.
|
|
174
|
+
*
|
|
175
|
+
* Note that the path placeholders, `params`, are only available if the
|
|
176
|
+
* `url` parameter is an output of a typed URL builder (like the one
|
|
177
|
+
* produced with *url-shape*).
|
|
178
|
+
*/
|
|
179
|
+
function useRouteState(url, options) {
|
|
180
|
+
let { route } = useRoute();
|
|
181
|
+
let getState = (0, react.useCallback)((href) => {
|
|
182
|
+
let resolvedHref = String(href ?? route.href);
|
|
183
|
+
return (0, statepod.matchURL)(url === void 0 ? resolvedHref : url, resolvedHref);
|
|
184
|
+
}, [url, route]);
|
|
185
|
+
let setState = (0, react.useCallback)((update) => {
|
|
186
|
+
let urlData = typeof update === "function" ? update(getState()) : update;
|
|
187
|
+
route.navigate({
|
|
188
|
+
...options,
|
|
189
|
+
href: (0, statepod.compileURL)(url, urlData)
|
|
190
|
+
});
|
|
191
|
+
}, [
|
|
192
|
+
url,
|
|
193
|
+
route,
|
|
194
|
+
options,
|
|
195
|
+
getState
|
|
196
|
+
]);
|
|
197
|
+
return [getState(), setState];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function createState(initial = true, pending = false, error) {
|
|
201
|
+
return {
|
|
202
|
+
initial,
|
|
203
|
+
pending,
|
|
204
|
+
error,
|
|
205
|
+
time: Date.now()
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function useTransientState(state, action) {
|
|
209
|
+
let stateMap = (0, react.useContext)(TransientStateContext);
|
|
210
|
+
let stateRef = (0, react.useRef)(null);
|
|
211
|
+
let [stateItemInited, setStateItemInited] = (0, react.useState)(false);
|
|
212
|
+
let [actionState, setActionState] = useExternalState((0, react.useMemo)(() => {
|
|
213
|
+
if ((0, statepod.isState)(state)) return state;
|
|
214
|
+
if (typeof state === "string") {
|
|
215
|
+
let stateItem = stateMap.get(state);
|
|
216
|
+
if (!stateItem) {
|
|
217
|
+
stateItem = new statepod.State(createState());
|
|
218
|
+
stateMap.set(state, stateItem);
|
|
219
|
+
if (!stateItemInited) setStateItemInited(true);
|
|
220
|
+
}
|
|
221
|
+
return stateItem;
|
|
222
|
+
}
|
|
223
|
+
if (!stateRef.current) stateRef.current = new statepod.State(createState());
|
|
224
|
+
return stateRef.current;
|
|
225
|
+
}, [
|
|
226
|
+
state,
|
|
227
|
+
stateMap,
|
|
228
|
+
stateItemInited
|
|
229
|
+
]));
|
|
230
|
+
let trackableAction = (0, react.useCallback)((...args) => {
|
|
231
|
+
if (!action) throw new Error("A trackable action is only available when the hook's 'action' parameter is set");
|
|
232
|
+
let options = args.at(-1);
|
|
233
|
+
let originalArgs = args.slice(0, -1);
|
|
234
|
+
let result;
|
|
235
|
+
try {
|
|
236
|
+
result = action(...originalArgs);
|
|
237
|
+
} catch (error) {
|
|
238
|
+
setActionState((prevState) => ({
|
|
239
|
+
...prevState,
|
|
240
|
+
...createState(false, false, error)
|
|
241
|
+
}));
|
|
242
|
+
if (options?.throws) throw error;
|
|
243
|
+
}
|
|
244
|
+
if (result instanceof Promise) {
|
|
245
|
+
let delayedTracking = null;
|
|
246
|
+
if (!options?.silent) {
|
|
247
|
+
let delay = options?.delay;
|
|
248
|
+
if (delay === void 0) setActionState((prevState) => ({
|
|
249
|
+
...prevState,
|
|
250
|
+
...createState(false, true)
|
|
251
|
+
}));
|
|
252
|
+
else delayedTracking = setTimeout(() => {
|
|
253
|
+
setActionState((prevState) => ({
|
|
254
|
+
...prevState,
|
|
255
|
+
...createState(false, true)
|
|
256
|
+
}));
|
|
257
|
+
delayedTracking = null;
|
|
258
|
+
}, delay);
|
|
259
|
+
}
|
|
260
|
+
return result.then((value) => {
|
|
261
|
+
if (delayedTracking !== null) clearTimeout(delayedTracking);
|
|
262
|
+
setActionState((prevState) => ({
|
|
263
|
+
...prevState,
|
|
264
|
+
...createState(false, false)
|
|
265
|
+
}));
|
|
266
|
+
return value;
|
|
267
|
+
}).catch((error) => {
|
|
268
|
+
if (delayedTracking !== null) clearTimeout(delayedTracking);
|
|
269
|
+
setActionState((prevState) => ({
|
|
270
|
+
...prevState,
|
|
271
|
+
...createState(false, false, error)
|
|
272
|
+
}));
|
|
273
|
+
if (options?.throws) throw error;
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
setActionState((prevState) => ({
|
|
277
|
+
...prevState,
|
|
278
|
+
...createState(false, false)
|
|
279
|
+
}));
|
|
280
|
+
return result;
|
|
281
|
+
}, [action, setActionState]);
|
|
282
|
+
return (0, react.useMemo)(() => {
|
|
283
|
+
let extendedActionState = {
|
|
284
|
+
...actionState,
|
|
285
|
+
update: setActionState
|
|
286
|
+
};
|
|
287
|
+
return action ? [extendedActionState, trackableAction] : [extendedActionState];
|
|
288
|
+
}, [
|
|
289
|
+
action,
|
|
290
|
+
trackableAction,
|
|
291
|
+
actionState,
|
|
292
|
+
setActionState
|
|
293
|
+
]);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function useURL(callback) {
|
|
297
|
+
return useExternalState((0, react.useContext)(URLContext), callback, "navigation");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
exports.A = A;
|
|
301
|
+
exports.Area = Area;
|
|
302
|
+
exports.RouteContext = RouteContext;
|
|
303
|
+
exports.RouteProvider = RouteProvider;
|
|
304
|
+
exports.TransientStateContext = TransientStateContext;
|
|
305
|
+
exports.TransientStateProvider = TransientStateProvider;
|
|
306
|
+
exports.URLContext = URLContext;
|
|
307
|
+
exports.URLProvider = URLProvider;
|
|
308
|
+
exports.useExternalState = useExternalState;
|
|
309
|
+
exports.useLinkProps = useLinkProps;
|
|
310
|
+
exports.useNavigationComplete = useNavigationComplete;
|
|
311
|
+
exports.useNavigationStart = useNavigationStart;
|
|
312
|
+
exports.useRoute = useRoute;
|
|
313
|
+
exports.useRouteLinks = useRouteLinks;
|
|
314
|
+
exports.useRouteState = useRouteState;
|
|
315
|
+
exports.useTransientState = useTransientState;
|
|
316
|
+
exports.useURL = useURL;
|
|
317
|
+
Object.keys(statepod).forEach(function(k) {
|
|
318
|
+
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
319
|
+
enumerable: true,
|
|
320
|
+
get: function() {
|
|
321
|
+
return statepod[k];
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import * as statepod from "statepod";
|
|
2
|
+
import { ContainerElement, EventCallback, LocationValue, MatchState, NavigationOptions, Route, State, StatePayloadMap, URLData, URLState } from "statepod";
|
|
3
|
+
import * as react from "react";
|
|
4
|
+
import { AnchorHTMLAttributes, AreaHTMLAttributes, MouseEvent, ReactNode, RefObject } from "react";
|
|
5
|
+
export * from "statepod";
|
|
6
|
+
|
|
7
|
+
type EnhanceHref<T extends {
|
|
8
|
+
href?: string | undefined;
|
|
9
|
+
}> = Omit<T, "href"> & {
|
|
10
|
+
href?: LocationValue;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type LinkNavigationProps = {
|
|
14
|
+
"data-spa"?: NavigationOptions["spa"];
|
|
15
|
+
"data-history"?: NavigationOptions["history"];
|
|
16
|
+
"data-scroll"?: NavigationOptions["scroll"];
|
|
17
|
+
"data-id"?: NavigationOptions["id"];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type AProps = EnhanceHref<AnchorHTMLAttributes<HTMLAnchorElement>> & LinkNavigationProps;
|
|
21
|
+
|
|
22
|
+
declare const A: ({
|
|
23
|
+
children,
|
|
24
|
+
...props
|
|
25
|
+
}: AProps) => react.JSX.Element;
|
|
26
|
+
|
|
27
|
+
type AreaProps = EnhanceHref<AreaHTMLAttributes<HTMLAreaElement>> & LinkNavigationProps;
|
|
28
|
+
|
|
29
|
+
declare const Area: ({
|
|
30
|
+
alt,
|
|
31
|
+
...props
|
|
32
|
+
}: AreaProps) => react.JSX.Element;
|
|
33
|
+
|
|
34
|
+
declare const RouteContext: react.Context<Route>;
|
|
35
|
+
|
|
36
|
+
type RouteProviderProps = {
|
|
37
|
+
href?: string | Route | undefined;
|
|
38
|
+
children?: ReactNode;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* A component providing a Route instance to the nested components.
|
|
42
|
+
*/
|
|
43
|
+
declare const RouteProvider: ({
|
|
44
|
+
href,
|
|
45
|
+
children
|
|
46
|
+
}: RouteProviderProps) => react.JSX.Element;
|
|
47
|
+
|
|
48
|
+
type TransientState = {
|
|
49
|
+
initial?: boolean | undefined;
|
|
50
|
+
pending?: boolean | undefined;
|
|
51
|
+
error?: unknown;
|
|
52
|
+
time?: number | undefined;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
declare const TransientStateContext: react.Context<Map<string, State<TransientState, statepod.StatePayloadMap<TransientState>>>>;
|
|
56
|
+
|
|
57
|
+
type TransientStateProviderProps = {
|
|
58
|
+
value?: Record<string, TransientState> | Map<string, State<TransientState>> | null | undefined;
|
|
59
|
+
children?: ReactNode;
|
|
60
|
+
};
|
|
61
|
+
declare const TransientStateProvider: ({
|
|
62
|
+
value,
|
|
63
|
+
children
|
|
64
|
+
}: TransientStateProviderProps) => react.JSX.Element;
|
|
65
|
+
|
|
66
|
+
type RenderCallback<T> = (render: () => void, payload: T) => boolean | undefined | void;
|
|
67
|
+
|
|
68
|
+
declare const URLContext: react.Context<URLState<statepod.URLStatePayloadMap>>;
|
|
69
|
+
|
|
70
|
+
type URLProviderProps = {
|
|
71
|
+
href?: string | URLState | undefined;
|
|
72
|
+
children?: ReactNode;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* A component providing a URL value to the nested components.
|
|
76
|
+
*/
|
|
77
|
+
declare const URLProvider: ({
|
|
78
|
+
href,
|
|
79
|
+
children
|
|
80
|
+
}: URLProviderProps) => react.JSX.Element;
|
|
81
|
+
|
|
82
|
+
type SetExternalStateValue<T, P extends StatePayloadMap<T> = StatePayloadMap<T>> = State<T, P>["setValue"];
|
|
83
|
+
declare function useExternalState<T, P extends StatePayloadMap<T>>(state: State<T, P>, callback?: RenderCallback<P["update"]> | boolean): [T, SetExternalStateValue<T, P>];
|
|
84
|
+
declare function useExternalState<T, P extends StatePayloadMap<T>, E extends keyof P>(state: State<T, P>, callback?: RenderCallback<P[E]> | boolean, event?: E): [T, SetExternalStateValue<T, P>];
|
|
85
|
+
|
|
86
|
+
declare function useLinkProps<T extends AProps | AreaProps>({
|
|
87
|
+
href,
|
|
88
|
+
target,
|
|
89
|
+
onClick,
|
|
90
|
+
...props
|
|
91
|
+
}: T): Omit<T, "href" | "target" | "onClick"> & {
|
|
92
|
+
href: string | undefined;
|
|
93
|
+
target: string | (string & {}) | undefined;
|
|
94
|
+
onClick: (event: MouseEvent<HTMLAnchorElement & HTMLAreaElement>) => void;
|
|
95
|
+
"data-active": boolean | undefined;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
declare function useNavigationComplete(callback: EventCallback<NavigationOptions>): void;
|
|
99
|
+
|
|
100
|
+
declare function useNavigationStart(callback: EventCallback<NavigationOptions>): void;
|
|
101
|
+
|
|
102
|
+
declare function useRoute(callback?: RenderCallback<NavigationOptions>): {
|
|
103
|
+
route: statepod.Route;
|
|
104
|
+
at: {
|
|
105
|
+
<P extends statepod.LocationPattern>(urlPattern: P): boolean;
|
|
106
|
+
<P extends statepod.LocationPattern, X>(urlPattern: P, x: X | statepod.MatchHandler<P, X>): X | undefined;
|
|
107
|
+
<P extends statepod.LocationPattern, X, Y>(urlPattern: P, x: X | statepod.MatchHandler<P, X>, y: Y | statepod.MatchHandler<P, Y>): X | Y;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Converts plain HTML links to SPA route links.
|
|
113
|
+
*
|
|
114
|
+
* @param containerRef - A React Ref pointing to a container element.
|
|
115
|
+
* @param elements - An optional selector, or an HTML element, or a
|
|
116
|
+
* collection thereof, specifying the links inside the container to
|
|
117
|
+
* be converted to SPA route links. Default: `"a, area"`.
|
|
118
|
+
*/
|
|
119
|
+
declare function useRouteLinks(containerRef: RefObject<ContainerElement>, elements?: Parameters<Route["observe"]>[1]): void;
|
|
120
|
+
|
|
121
|
+
type SetRouteState<T extends LocationValue> = (update: URLData<T> | ((state: MatchState<T>) => URLData<T>)) => void;
|
|
122
|
+
/**
|
|
123
|
+
* Reads and sets URL parameters in a way similar to React's `useState()`.
|
|
124
|
+
* This hooks returns `[state, setState]`, where `state` contains path
|
|
125
|
+
* placeholder parameters and query parameters, `{ params?, query? }`.
|
|
126
|
+
*
|
|
127
|
+
* Note that the path placeholders, `params`, are only available if the
|
|
128
|
+
* `url` parameter is an output of a typed URL builder (like the one
|
|
129
|
+
* produced with *url-shape*).
|
|
130
|
+
*/
|
|
131
|
+
declare function useRouteState<T extends LocationValue>(url?: T, options?: Omit<NavigationOptions, "href">): [MatchState<T>, SetRouteState<T>];
|
|
132
|
+
|
|
133
|
+
type TransientStateOptions = {
|
|
134
|
+
/**
|
|
135
|
+
* Whether to track the action state silently (e.g. with a background
|
|
136
|
+
* action or an optimistic update).
|
|
137
|
+
*
|
|
138
|
+
* When set to `true`, the state's `pending` property doesn't switch
|
|
139
|
+
* to `true` in the pending state.
|
|
140
|
+
*/
|
|
141
|
+
silent?: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Delays switching the action state's `pending` property to `true`
|
|
144
|
+
* in the pending state by the given number of milliseconds.
|
|
145
|
+
*
|
|
146
|
+
* Use case: to avoid flashing a process indicator if the action is
|
|
147
|
+
* likely to complete by the end of a short delay.
|
|
148
|
+
*/
|
|
149
|
+
delay?: number;
|
|
150
|
+
/**
|
|
151
|
+
* Allows the async action to reject explicitly, along with exposing
|
|
152
|
+
* the action state's `error` property that goes by default.
|
|
153
|
+
*/
|
|
154
|
+
throws?: boolean;
|
|
155
|
+
};
|
|
156
|
+
type ControllableTransientState = TransientState & {
|
|
157
|
+
update: SetExternalStateValue<TransientState>;
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* The hook's `state` parameter is a unique string key or an instance of
|
|
161
|
+
* `State`. Providing a string key or a `State` instance allows to share the
|
|
162
|
+
* action state across multiple components. If the key is omitted or set to
|
|
163
|
+
* `null`, the action state stays locally scoped to the component where the
|
|
164
|
+
* hook is used.
|
|
165
|
+
*/
|
|
166
|
+
declare function useTransientState<F extends (...args: unknown[]) => unknown>(state: string | State<TransientState> | null, action: F): [ControllableTransientState, (...args: [...Parameters<F>, TransientStateOptions?]) => ReturnType<F>];
|
|
167
|
+
declare function useTransientState(state: string | State<TransientState> | null): [ControllableTransientState];
|
|
168
|
+
|
|
169
|
+
declare function useURL(callback?: RenderCallback<NavigationOptions>): [string, (update: string | statepod.StateUpdate<string>) => void];
|
|
170
|
+
|
|
171
|
+
export { A, AProps, Area, AreaProps, ControllableTransientState, EnhanceHref, LinkNavigationProps, RenderCallback, RouteContext, RouteProvider, RouteProviderProps, SetExternalStateValue, SetRouteState, TransientState, TransientStateContext, TransientStateOptions, TransientStateProvider, TransientStateProviderProps, URLContext, URLProvider, URLProviderProps, useExternalState, useLinkProps, useNavigationComplete, useNavigationStart, useRoute, useRouteLinks, useRouteState, useTransientState, useURL };
|