@alepha/react 0.7.4 → 0.7.5
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/index.browser.cjs +28 -11
- package/dist/index.browser.js +5 -5
- package/dist/index.cjs +27 -256
- package/dist/index.d.ts +62 -60
- package/dist/index.js +6 -235
- package/dist/{ReactBrowserProvider-CXDElhnK.cjs → useRouterState-BTmuHxkM.cjs} +241 -18
- package/dist/{ReactBrowserProvider-ufHSOTmv.js → useRouterState-cCucJfTC.js} +234 -19
- package/package.json +6 -6
- package/src/components/NotFound.tsx +0 -10
- package/src/descriptors/$page.ts +5 -2
- package/src/index.browser.ts +1 -0
- package/src/index.shared.ts +0 -4
- package/src/index.ts +0 -2
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { t, $logger, $inject, Alepha, $hook, OPTIONS, __bind } from '@alepha/core';
|
|
2
|
-
import { ServerRouterProvider, ServerTimingProvider, ServerLinksProvider, apiLinksResponseSchema,
|
|
2
|
+
import { ServerRouterProvider, ServerTimingProvider, ServerLinksProvider, apiLinksResponseSchema, AlephaServer } from '@alepha/server';
|
|
3
3
|
import { AlephaServerCache } from '@alepha/server-cache';
|
|
4
|
-
import { P as PageDescriptorProvider, $ as $page
|
|
5
|
-
export { C as ClientOnly, E as ErrorBoundary, N as NestedView,
|
|
4
|
+
import { P as PageDescriptorProvider, $ as $page } from './useRouterState-cCucJfTC.js';
|
|
5
|
+
export { C as ClientOnly, E as ErrorBoundary, L as Link, N as NestedView, l as ReactBrowserProvider, b as RedirectionError, R as RouterContext, c as RouterHookApi, a as RouterLayerContext, k as isPageRoute, u as useActive, d as useAlepha, e as useClient, f as useInject, g as useQueryParams, h as useRouter, i as useRouterEvents, j as useRouterState } from './useRouterState-cCucJfTC.js';
|
|
6
6
|
import { existsSync } from 'node:fs';
|
|
7
7
|
import { join } from 'node:path';
|
|
8
8
|
import { ServerStaticProvider } from '@alepha/server-static';
|
|
9
9
|
import { renderToString } from 'react-dom/server';
|
|
10
|
-
import
|
|
11
|
-
import
|
|
10
|
+
import 'react/jsx-runtime';
|
|
11
|
+
import 'react';
|
|
12
12
|
import '@alepha/router';
|
|
13
13
|
|
|
14
14
|
class ServerHeadProvider {
|
|
@@ -353,239 +353,10 @@ class ReactServerProvider {
|
|
|
353
353
|
}
|
|
354
354
|
}
|
|
355
355
|
|
|
356
|
-
class RouterHookApi {
|
|
357
|
-
constructor(pages, state, layer, browser) {
|
|
358
|
-
this.pages = pages;
|
|
359
|
-
this.state = state;
|
|
360
|
-
this.layer = layer;
|
|
361
|
-
this.browser = browser;
|
|
362
|
-
}
|
|
363
|
-
get current() {
|
|
364
|
-
return this.state;
|
|
365
|
-
}
|
|
366
|
-
get pathname() {
|
|
367
|
-
return this.state.pathname;
|
|
368
|
-
}
|
|
369
|
-
get query() {
|
|
370
|
-
const query = {};
|
|
371
|
-
for (const [key, value] of new URLSearchParams(
|
|
372
|
-
this.state.search
|
|
373
|
-
).entries()) {
|
|
374
|
-
query[key] = String(value);
|
|
375
|
-
}
|
|
376
|
-
return query;
|
|
377
|
-
}
|
|
378
|
-
async back() {
|
|
379
|
-
this.browser?.history.back();
|
|
380
|
-
}
|
|
381
|
-
async forward() {
|
|
382
|
-
this.browser?.history.forward();
|
|
383
|
-
}
|
|
384
|
-
async invalidate(props) {
|
|
385
|
-
await this.browser?.invalidate(props);
|
|
386
|
-
}
|
|
387
|
-
/**
|
|
388
|
-
* Create a valid href for the given pathname.
|
|
389
|
-
*
|
|
390
|
-
* @param pathname
|
|
391
|
-
* @param layer
|
|
392
|
-
*/
|
|
393
|
-
createHref(pathname, layer = this.layer, options = {}) {
|
|
394
|
-
if (typeof pathname === "object") {
|
|
395
|
-
pathname = pathname.options.path ?? "";
|
|
396
|
-
}
|
|
397
|
-
if (options.params) {
|
|
398
|
-
for (const [key, value] of Object.entries(options.params)) {
|
|
399
|
-
pathname = pathname.replace(`:${key}`, String(value));
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
return pathname.startsWith("/") ? pathname : `${layer.path}/${pathname}`.replace(/\/\/+/g, "/");
|
|
403
|
-
}
|
|
404
|
-
async go(path, options) {
|
|
405
|
-
for (const page of this.pages) {
|
|
406
|
-
if (page.name === path) {
|
|
407
|
-
path = page.path ?? "";
|
|
408
|
-
break;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
await this.browser?.go(this.createHref(path, this.layer, options), options);
|
|
412
|
-
}
|
|
413
|
-
anchor(path, options = {}) {
|
|
414
|
-
for (const page of this.pages) {
|
|
415
|
-
if (page.name === path) {
|
|
416
|
-
path = page.path ?? "";
|
|
417
|
-
break;
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
const href = this.createHref(path, this.layer, options);
|
|
421
|
-
return {
|
|
422
|
-
href,
|
|
423
|
-
onClick: (ev) => {
|
|
424
|
-
ev.stopPropagation();
|
|
425
|
-
ev.preventDefault();
|
|
426
|
-
this.go(path, options).catch(console.error);
|
|
427
|
-
}
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
/**
|
|
431
|
-
* Set query params.
|
|
432
|
-
*
|
|
433
|
-
* @param record
|
|
434
|
-
* @param options
|
|
435
|
-
*/
|
|
436
|
-
setQueryParams(record, options = {}) {
|
|
437
|
-
const func = typeof record === "function" ? record : () => record;
|
|
438
|
-
const search = new URLSearchParams(func(this.query)).toString();
|
|
439
|
-
const state = search ? `${this.pathname}?${search}` : this.pathname;
|
|
440
|
-
if (options.push) {
|
|
441
|
-
window.history.pushState({}, "", state);
|
|
442
|
-
} else {
|
|
443
|
-
window.history.replaceState({}, "", state);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
const useRouter = () => {
|
|
449
|
-
const ctx = useContext(RouterContext);
|
|
450
|
-
const layer = useContext(RouterLayerContext);
|
|
451
|
-
if (!ctx || !layer) {
|
|
452
|
-
throw new Error("useRouter must be used within a RouterProvider");
|
|
453
|
-
}
|
|
454
|
-
const pages = useMemo(() => {
|
|
455
|
-
return ctx.alepha.get(PageDescriptorProvider).getPages();
|
|
456
|
-
}, []);
|
|
457
|
-
return useMemo(
|
|
458
|
-
() => new RouterHookApi(
|
|
459
|
-
pages,
|
|
460
|
-
ctx.state,
|
|
461
|
-
layer,
|
|
462
|
-
ctx.alepha.isBrowser() ? ctx.alepha.get(ReactBrowserProvider) : void 0
|
|
463
|
-
),
|
|
464
|
-
[layer]
|
|
465
|
-
);
|
|
466
|
-
};
|
|
467
|
-
|
|
468
|
-
const Link = (props) => {
|
|
469
|
-
React.useContext(RouterContext);
|
|
470
|
-
const router = useRouter();
|
|
471
|
-
const to = typeof props.to === "string" ? props.to : props.to[OPTIONS].path;
|
|
472
|
-
if (!to) {
|
|
473
|
-
return null;
|
|
474
|
-
}
|
|
475
|
-
const can = typeof props.to === "string" ? void 0 : props.to[OPTIONS].can;
|
|
476
|
-
if (can && !can()) {
|
|
477
|
-
return null;
|
|
478
|
-
}
|
|
479
|
-
const name = typeof props.to === "string" ? void 0 : props.to[OPTIONS].name;
|
|
480
|
-
const anchorProps = {
|
|
481
|
-
...props,
|
|
482
|
-
to: void 0
|
|
483
|
-
};
|
|
484
|
-
return /* @__PURE__ */ jsx("a", { ...router.anchor(to), ...anchorProps, children: props.children ?? name });
|
|
485
|
-
};
|
|
486
|
-
|
|
487
|
-
const useActive = (path) => {
|
|
488
|
-
const router = useRouter();
|
|
489
|
-
const ctx = useContext(RouterContext);
|
|
490
|
-
const layer = useContext(RouterLayerContext);
|
|
491
|
-
if (!ctx || !layer) {
|
|
492
|
-
throw new Error("useRouter must be used within a RouterProvider");
|
|
493
|
-
}
|
|
494
|
-
let name;
|
|
495
|
-
if (typeof path === "object" && path.options.name) {
|
|
496
|
-
name = path.options.name;
|
|
497
|
-
}
|
|
498
|
-
const [current, setCurrent] = useState(ctx.state.pathname);
|
|
499
|
-
const href = useMemo(() => router.createHref(path, layer), [path, layer]);
|
|
500
|
-
const [isPending, setPending] = useState(false);
|
|
501
|
-
const isActive = current === href;
|
|
502
|
-
useRouterEvents({
|
|
503
|
-
onEnd: ({ state }) => setCurrent(state.pathname)
|
|
504
|
-
});
|
|
505
|
-
return {
|
|
506
|
-
name,
|
|
507
|
-
isPending,
|
|
508
|
-
isActive,
|
|
509
|
-
anchorProps: {
|
|
510
|
-
href,
|
|
511
|
-
onClick: (ev) => {
|
|
512
|
-
ev.stopPropagation();
|
|
513
|
-
ev.preventDefault();
|
|
514
|
-
if (isActive) return;
|
|
515
|
-
if (isPending) return;
|
|
516
|
-
setPending(true);
|
|
517
|
-
router.go(href).then(() => {
|
|
518
|
-
setPending(false);
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
};
|
|
523
|
-
};
|
|
524
|
-
|
|
525
|
-
const useInject = (clazz) => {
|
|
526
|
-
const ctx = useContext(RouterContext);
|
|
527
|
-
if (!ctx) {
|
|
528
|
-
throw new Error("useRouter must be used within a <RouterProvider>");
|
|
529
|
-
}
|
|
530
|
-
return useMemo(() => ctx.alepha.get(clazz), []);
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
const useClient = (_scope) => {
|
|
534
|
-
return useInject(HttpClient).of();
|
|
535
|
-
};
|
|
536
|
-
|
|
537
|
-
const useQueryParams = (schema, options = {}) => {
|
|
538
|
-
const ctx = useContext(RouterContext);
|
|
539
|
-
if (!ctx) {
|
|
540
|
-
throw new Error("useQueryParams must be used within a RouterProvider");
|
|
541
|
-
}
|
|
542
|
-
const key = options.key ?? "q";
|
|
543
|
-
const router = useRouter();
|
|
544
|
-
const querystring = router.query[key];
|
|
545
|
-
const [queryParams, setQueryParams] = useState(
|
|
546
|
-
decode(ctx.alepha, schema, router.query[key])
|
|
547
|
-
);
|
|
548
|
-
useEffect(() => {
|
|
549
|
-
setQueryParams(decode(ctx.alepha, schema, querystring));
|
|
550
|
-
}, [querystring]);
|
|
551
|
-
return [
|
|
552
|
-
queryParams,
|
|
553
|
-
(queryParams2) => {
|
|
554
|
-
setQueryParams(queryParams2);
|
|
555
|
-
router.setQueryParams((data) => {
|
|
556
|
-
return { ...data, [key]: encode(ctx.alepha, schema, queryParams2) };
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
];
|
|
560
|
-
};
|
|
561
|
-
const encode = (alepha, schema, data) => {
|
|
562
|
-
return btoa(JSON.stringify(alepha.parse(schema, data)));
|
|
563
|
-
};
|
|
564
|
-
const decode = (alepha, schema, data) => {
|
|
565
|
-
try {
|
|
566
|
-
return alepha.parse(schema, JSON.parse(atob(decodeURIComponent(data))));
|
|
567
|
-
} catch (_error) {
|
|
568
|
-
return {};
|
|
569
|
-
}
|
|
570
|
-
};
|
|
571
|
-
|
|
572
|
-
const useRouterState = () => {
|
|
573
|
-
const ctx = useContext(RouterContext);
|
|
574
|
-
const layer = useContext(RouterLayerContext);
|
|
575
|
-
if (!ctx || !layer) {
|
|
576
|
-
throw new Error("useRouter must be used within a RouterProvider");
|
|
577
|
-
}
|
|
578
|
-
const [state, setState] = useState(ctx.state);
|
|
579
|
-
useRouterEvents({
|
|
580
|
-
onEnd: ({ state: state2 }) => setState({ ...state2 })
|
|
581
|
-
});
|
|
582
|
-
return state;
|
|
583
|
-
};
|
|
584
|
-
|
|
585
356
|
class AlephaReact {
|
|
586
357
|
name = "alepha.react";
|
|
587
358
|
$services = (alepha) => alepha.with(AlephaServer).with(AlephaServerCache).with(ReactServerProvider).with(PageDescriptorProvider);
|
|
588
359
|
}
|
|
589
360
|
__bind($page, AlephaReact);
|
|
590
361
|
|
|
591
|
-
export { $page, AlephaReact,
|
|
362
|
+
export { $page, AlephaReact, PageDescriptorProvider, ReactServerProvider };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
3
4
|
var core = require('@alepha/core');
|
|
5
|
+
var React = require('react');
|
|
4
6
|
var server = require('@alepha/server');
|
|
5
7
|
var router = require('@alepha/router');
|
|
6
|
-
var React = require('react');
|
|
7
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
8
8
|
|
|
9
9
|
const KEY = "PAGE";
|
|
10
10
|
const $page = (options) => {
|
|
@@ -279,7 +279,7 @@ const NestedView = (props) => {
|
|
|
279
279
|
};
|
|
280
280
|
|
|
281
281
|
function NotFoundPage() {
|
|
282
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
282
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
283
283
|
"div",
|
|
284
284
|
{
|
|
285
285
|
style: {
|
|
@@ -292,21 +292,7 @@ function NotFoundPage() {
|
|
|
292
292
|
fontFamily: "sans-serif",
|
|
293
293
|
padding: "1rem"
|
|
294
294
|
},
|
|
295
|
-
children:
|
|
296
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontSize: "1rem", marginBottom: "0.5rem" }, children: "This page does not exist" }),
|
|
297
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
298
|
-
"a",
|
|
299
|
-
{
|
|
300
|
-
href: "/",
|
|
301
|
-
style: {
|
|
302
|
-
fontSize: "0.7rem",
|
|
303
|
-
color: "#007bff",
|
|
304
|
-
textDecoration: "none"
|
|
305
|
-
},
|
|
306
|
-
children: "\u2190 Back to home"
|
|
307
|
-
}
|
|
308
|
-
)
|
|
309
|
-
]
|
|
295
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontSize: "1rem", marginBottom: "0.5rem" }, children: "This page does not exist" })
|
|
310
296
|
}
|
|
311
297
|
);
|
|
312
298
|
}
|
|
@@ -945,16 +931,253 @@ class ReactBrowserProvider {
|
|
|
945
931
|
});
|
|
946
932
|
}
|
|
947
933
|
|
|
934
|
+
class RouterHookApi {
|
|
935
|
+
constructor(pages, state, layer, browser) {
|
|
936
|
+
this.pages = pages;
|
|
937
|
+
this.state = state;
|
|
938
|
+
this.layer = layer;
|
|
939
|
+
this.browser = browser;
|
|
940
|
+
}
|
|
941
|
+
get current() {
|
|
942
|
+
return this.state;
|
|
943
|
+
}
|
|
944
|
+
get pathname() {
|
|
945
|
+
return this.state.pathname;
|
|
946
|
+
}
|
|
947
|
+
get query() {
|
|
948
|
+
const query = {};
|
|
949
|
+
for (const [key, value] of new URLSearchParams(
|
|
950
|
+
this.state.search
|
|
951
|
+
).entries()) {
|
|
952
|
+
query[key] = String(value);
|
|
953
|
+
}
|
|
954
|
+
return query;
|
|
955
|
+
}
|
|
956
|
+
async back() {
|
|
957
|
+
this.browser?.history.back();
|
|
958
|
+
}
|
|
959
|
+
async forward() {
|
|
960
|
+
this.browser?.history.forward();
|
|
961
|
+
}
|
|
962
|
+
async invalidate(props) {
|
|
963
|
+
await this.browser?.invalidate(props);
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Create a valid href for the given pathname.
|
|
967
|
+
*
|
|
968
|
+
* @param pathname
|
|
969
|
+
* @param layer
|
|
970
|
+
*/
|
|
971
|
+
createHref(pathname, layer = this.layer, options = {}) {
|
|
972
|
+
if (typeof pathname === "object") {
|
|
973
|
+
pathname = pathname.options.path ?? "";
|
|
974
|
+
}
|
|
975
|
+
if (options.params) {
|
|
976
|
+
for (const [key, value] of Object.entries(options.params)) {
|
|
977
|
+
pathname = pathname.replace(`:${key}`, String(value));
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
return pathname.startsWith("/") ? pathname : `${layer.path}/${pathname}`.replace(/\/\/+/g, "/");
|
|
981
|
+
}
|
|
982
|
+
async go(path, options) {
|
|
983
|
+
for (const page of this.pages) {
|
|
984
|
+
if (page.name === path) {
|
|
985
|
+
path = page.path ?? "";
|
|
986
|
+
break;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
await this.browser?.go(this.createHref(path, this.layer, options), options);
|
|
990
|
+
}
|
|
991
|
+
anchor(path, options = {}) {
|
|
992
|
+
for (const page of this.pages) {
|
|
993
|
+
if (page.name === path) {
|
|
994
|
+
path = page.path ?? "";
|
|
995
|
+
break;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
const href = this.createHref(path, this.layer, options);
|
|
999
|
+
return {
|
|
1000
|
+
href,
|
|
1001
|
+
onClick: (ev) => {
|
|
1002
|
+
ev.stopPropagation();
|
|
1003
|
+
ev.preventDefault();
|
|
1004
|
+
this.go(path, options).catch(console.error);
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Set query params.
|
|
1010
|
+
*
|
|
1011
|
+
* @param record
|
|
1012
|
+
* @param options
|
|
1013
|
+
*/
|
|
1014
|
+
setQueryParams(record, options = {}) {
|
|
1015
|
+
const func = typeof record === "function" ? record : () => record;
|
|
1016
|
+
const search = new URLSearchParams(func(this.query)).toString();
|
|
1017
|
+
const state = search ? `${this.pathname}?${search}` : this.pathname;
|
|
1018
|
+
if (options.push) {
|
|
1019
|
+
window.history.pushState({}, "", state);
|
|
1020
|
+
} else {
|
|
1021
|
+
window.history.replaceState({}, "", state);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
const useRouter = () => {
|
|
1027
|
+
const ctx = React.useContext(RouterContext);
|
|
1028
|
+
const layer = React.useContext(RouterLayerContext);
|
|
1029
|
+
if (!ctx || !layer) {
|
|
1030
|
+
throw new Error("useRouter must be used within a RouterProvider");
|
|
1031
|
+
}
|
|
1032
|
+
const pages = React.useMemo(() => {
|
|
1033
|
+
return ctx.alepha.get(PageDescriptorProvider).getPages();
|
|
1034
|
+
}, []);
|
|
1035
|
+
return React.useMemo(
|
|
1036
|
+
() => new RouterHookApi(
|
|
1037
|
+
pages,
|
|
1038
|
+
ctx.state,
|
|
1039
|
+
layer,
|
|
1040
|
+
ctx.alepha.isBrowser() ? ctx.alepha.get(ReactBrowserProvider) : void 0
|
|
1041
|
+
),
|
|
1042
|
+
[layer]
|
|
1043
|
+
);
|
|
1044
|
+
};
|
|
1045
|
+
|
|
1046
|
+
const Link = (props) => {
|
|
1047
|
+
React.useContext(RouterContext);
|
|
1048
|
+
const router = useRouter();
|
|
1049
|
+
const to = typeof props.to === "string" ? props.to : props.to[core.OPTIONS].path;
|
|
1050
|
+
if (!to) {
|
|
1051
|
+
return null;
|
|
1052
|
+
}
|
|
1053
|
+
const can = typeof props.to === "string" ? void 0 : props.to[core.OPTIONS].can;
|
|
1054
|
+
if (can && !can()) {
|
|
1055
|
+
return null;
|
|
1056
|
+
}
|
|
1057
|
+
const name = typeof props.to === "string" ? void 0 : props.to[core.OPTIONS].name;
|
|
1058
|
+
const anchorProps = {
|
|
1059
|
+
...props,
|
|
1060
|
+
to: void 0
|
|
1061
|
+
};
|
|
1062
|
+
return /* @__PURE__ */ jsxRuntime.jsx("a", { ...router.anchor(to), ...anchorProps, children: props.children ?? name });
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
const useActive = (path) => {
|
|
1066
|
+
const router = useRouter();
|
|
1067
|
+
const ctx = React.useContext(RouterContext);
|
|
1068
|
+
const layer = React.useContext(RouterLayerContext);
|
|
1069
|
+
if (!ctx || !layer) {
|
|
1070
|
+
throw new Error("useRouter must be used within a RouterProvider");
|
|
1071
|
+
}
|
|
1072
|
+
let name;
|
|
1073
|
+
if (typeof path === "object" && path.options.name) {
|
|
1074
|
+
name = path.options.name;
|
|
1075
|
+
}
|
|
1076
|
+
const [current, setCurrent] = React.useState(ctx.state.pathname);
|
|
1077
|
+
const href = React.useMemo(() => router.createHref(path, layer), [path, layer]);
|
|
1078
|
+
const [isPending, setPending] = React.useState(false);
|
|
1079
|
+
const isActive = current === href;
|
|
1080
|
+
useRouterEvents({
|
|
1081
|
+
onEnd: ({ state }) => setCurrent(state.pathname)
|
|
1082
|
+
});
|
|
1083
|
+
return {
|
|
1084
|
+
name,
|
|
1085
|
+
isPending,
|
|
1086
|
+
isActive,
|
|
1087
|
+
anchorProps: {
|
|
1088
|
+
href,
|
|
1089
|
+
onClick: (ev) => {
|
|
1090
|
+
ev.stopPropagation();
|
|
1091
|
+
ev.preventDefault();
|
|
1092
|
+
if (isActive) return;
|
|
1093
|
+
if (isPending) return;
|
|
1094
|
+
setPending(true);
|
|
1095
|
+
router.go(href).then(() => {
|
|
1096
|
+
setPending(false);
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
};
|
|
1101
|
+
};
|
|
1102
|
+
|
|
1103
|
+
const useInject = (clazz) => {
|
|
1104
|
+
const ctx = React.useContext(RouterContext);
|
|
1105
|
+
if (!ctx) {
|
|
1106
|
+
throw new Error("useRouter must be used within a <RouterProvider>");
|
|
1107
|
+
}
|
|
1108
|
+
return React.useMemo(() => ctx.alepha.get(clazz), []);
|
|
1109
|
+
};
|
|
1110
|
+
|
|
1111
|
+
const useClient = (_scope) => {
|
|
1112
|
+
return useInject(server.HttpClient).of();
|
|
1113
|
+
};
|
|
1114
|
+
|
|
1115
|
+
const useQueryParams = (schema, options = {}) => {
|
|
1116
|
+
const ctx = React.useContext(RouterContext);
|
|
1117
|
+
if (!ctx) {
|
|
1118
|
+
throw new Error("useQueryParams must be used within a RouterProvider");
|
|
1119
|
+
}
|
|
1120
|
+
const key = options.key ?? "q";
|
|
1121
|
+
const router = useRouter();
|
|
1122
|
+
const querystring = router.query[key];
|
|
1123
|
+
const [queryParams, setQueryParams] = React.useState(
|
|
1124
|
+
decode(ctx.alepha, schema, router.query[key])
|
|
1125
|
+
);
|
|
1126
|
+
React.useEffect(() => {
|
|
1127
|
+
setQueryParams(decode(ctx.alepha, schema, querystring));
|
|
1128
|
+
}, [querystring]);
|
|
1129
|
+
return [
|
|
1130
|
+
queryParams,
|
|
1131
|
+
(queryParams2) => {
|
|
1132
|
+
setQueryParams(queryParams2);
|
|
1133
|
+
router.setQueryParams((data) => {
|
|
1134
|
+
return { ...data, [key]: encode(ctx.alepha, schema, queryParams2) };
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
];
|
|
1138
|
+
};
|
|
1139
|
+
const encode = (alepha, schema, data) => {
|
|
1140
|
+
return btoa(JSON.stringify(alepha.parse(schema, data)));
|
|
1141
|
+
};
|
|
1142
|
+
const decode = (alepha, schema, data) => {
|
|
1143
|
+
try {
|
|
1144
|
+
return alepha.parse(schema, JSON.parse(atob(decodeURIComponent(data))));
|
|
1145
|
+
} catch (_error) {
|
|
1146
|
+
return {};
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1150
|
+
const useRouterState = () => {
|
|
1151
|
+
const ctx = React.useContext(RouterContext);
|
|
1152
|
+
const layer = React.useContext(RouterLayerContext);
|
|
1153
|
+
if (!ctx || !layer) {
|
|
1154
|
+
throw new Error("useRouter must be used within a RouterProvider");
|
|
1155
|
+
}
|
|
1156
|
+
const [state, setState] = React.useState(ctx.state);
|
|
1157
|
+
useRouterEvents({
|
|
1158
|
+
onEnd: ({ state: state2 }) => setState({ ...state2 })
|
|
1159
|
+
});
|
|
1160
|
+
return state;
|
|
1161
|
+
};
|
|
1162
|
+
|
|
948
1163
|
exports.$page = $page;
|
|
949
1164
|
exports.BrowserRouterProvider = BrowserRouterProvider;
|
|
950
1165
|
exports.ClientOnly = ClientOnly;
|
|
951
1166
|
exports.ErrorBoundary = ErrorBoundary;
|
|
1167
|
+
exports.Link = Link;
|
|
952
1168
|
exports.NestedView = NestedView;
|
|
953
1169
|
exports.PageDescriptorProvider = PageDescriptorProvider;
|
|
954
1170
|
exports.ReactBrowserProvider = ReactBrowserProvider;
|
|
955
1171
|
exports.RedirectionError = RedirectionError;
|
|
956
1172
|
exports.RouterContext = RouterContext;
|
|
1173
|
+
exports.RouterHookApi = RouterHookApi;
|
|
957
1174
|
exports.RouterLayerContext = RouterLayerContext;
|
|
958
1175
|
exports.isPageRoute = isPageRoute;
|
|
1176
|
+
exports.useActive = useActive;
|
|
959
1177
|
exports.useAlepha = useAlepha;
|
|
1178
|
+
exports.useClient = useClient;
|
|
1179
|
+
exports.useInject = useInject;
|
|
1180
|
+
exports.useQueryParams = useQueryParams;
|
|
1181
|
+
exports.useRouter = useRouter;
|
|
960
1182
|
exports.useRouterEvents = useRouterEvents;
|
|
1183
|
+
exports.useRouterState = useRouterState;
|