@typed/router 0.0.2
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/Link.d.ts +14 -0
- package/dist/Link.d.ts.map +1 -0
- package/dist/Link.js +19 -0
- package/dist/Link.js.map +1 -0
- package/dist/RouteMatch.d.ts +16 -0
- package/dist/RouteMatch.d.ts.map +1 -0
- package/dist/RouteMatch.js +15 -0
- package/dist/RouteMatch.js.map +1 -0
- package/dist/RouteMatcher.d.ts +38 -0
- package/dist/RouteMatcher.d.ts.map +1 -0
- package/dist/RouteMatcher.js +103 -0
- package/dist/RouteMatcher.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/router.d.ts +67 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +123 -0
- package/dist/router.js.map +1 -0
- package/eslintrc.json +3 -0
- package/package.json +37 -0
- package/project.json +26 -0
- package/src/Link.ts +36 -0
- package/src/RouteMatch.ts +56 -0
- package/src/RouteMatcher.ts +253 -0
- package/src/index.ts +4 -0
- package/src/router.ts +279 -0
- package/tsconfig.build.json +4 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +33 -0
package/dist/Link.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as Effect from '@effect/io/Effect';
|
|
2
|
+
import * as Fx from '@typed/fx';
|
|
3
|
+
import { Hole, Placeholder } from '@typed/html';
|
|
4
|
+
import { Router } from './router.js';
|
|
5
|
+
export declare function Link<R = never, E = never, R2 = never>(props: LinkProps<R, E, R2>): Fx.Fx<R | R2 | Router, E, Hole>;
|
|
6
|
+
export interface LinkProps<R, E, R2> {
|
|
7
|
+
readonly href: string;
|
|
8
|
+
readonly label: string | Placeholder<R, E>;
|
|
9
|
+
readonly className?: string;
|
|
10
|
+
readonly onClick?: (event: MouseEvent & {
|
|
11
|
+
currentTarget: HTMLAnchorElement;
|
|
12
|
+
}) => Effect.Effect<R2, never, unknown>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=Link.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../src/Link.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAC3C,OAAO,KAAK,EAAE,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAsB,IAAI,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEnE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,wBAAgB,IAAI,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,EAAE,GAAG,KAAK,EACnD,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GACzB,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,CAkBjC;AAED,MAAM,WAAW,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,CACjB,KAAK,EAAE,UAAU,GAAG;QAAE,aAAa,EAAE,iBAAiB,CAAA;KAAE,KACrD,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;CACvC"}
|
package/dist/Link.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as Effect from '@effect/io/Effect';
|
|
2
|
+
import { EventHandler, html } from '@typed/html';
|
|
3
|
+
import { Router } from './router.js';
|
|
4
|
+
export function Link(props) {
|
|
5
|
+
const clickHandler = (event) => Effect.gen(function* ($) {
|
|
6
|
+
const { currentPath } = yield* $(Router.get);
|
|
7
|
+
yield* $(currentPath.set(props.href));
|
|
8
|
+
if (props.onClick) {
|
|
9
|
+
yield* $(props.onClick(event));
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
return html `<a
|
|
13
|
+
class=${props.className}
|
|
14
|
+
href="${props.href}"
|
|
15
|
+
onclick=${EventHandler.preventDefault(clickHandler)}
|
|
16
|
+
>${props.label}</a
|
|
17
|
+
>`;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=Link.js.map
|
package/dist/Link.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Link.js","sourceRoot":"","sources":["../src/Link.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAE3C,OAAO,EAAE,YAAY,EAAE,IAAI,EAAqB,MAAM,aAAa,CAAA;AAEnE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,MAAM,UAAU,IAAI,CAClB,KAA0B;IAE1B,MAAM,YAAY,GAAG,CAAC,KAAwD,EAAE,EAAE,CAChF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrB,MAAM,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAE5C,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;QAErC,IAAI,KAAK,CAAC,OAAO,EAAE;YACjB,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;SAC/B;IACH,CAAC,CAAC,CAAA;IAEJ,OAAO,IAAI,CAAA;YACD,KAAK,CAAC,SAAS;YACf,KAAK,CAAC,IAAI;cACR,YAAY,CAAC,cAAc,CAAC,YAAY,CAAC;OAChD,KAAK,CAAC,KAAK;IACd,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as Layer from '@effect/io/Layer';
|
|
2
|
+
import * as Context from '@typed/context';
|
|
3
|
+
import * as Fx from '@typed/fx';
|
|
4
|
+
import * as html from '@typed/html';
|
|
5
|
+
import * as Path from '@typed/path';
|
|
6
|
+
import * as Route from '@typed/route';
|
|
7
|
+
export interface RouteMatch<R, E, P extends string> {
|
|
8
|
+
readonly route: Route.Route<R, P>;
|
|
9
|
+
readonly layout?: Fx.Fx<R, E, html.Renderable>;
|
|
10
|
+
readonly match: (params: Fx.Fx<never, never, Path.ParamsOf<P>>) => Fx.Fx<R, E, html.Renderable>;
|
|
11
|
+
readonly provideEnvironment: (environment: Context.Context<R>) => RouteMatch<never, E, P>;
|
|
12
|
+
readonly provideService: <S>(tag: Context.Tag<S>, service: S) => RouteMatch<Exclude<R, S>, E, P>;
|
|
13
|
+
readonly provideLayer: <R2, S>(layer: Layer.Layer<R2, never, S>) => RouteMatch<R2 | Exclude<R, S>, E, P>;
|
|
14
|
+
}
|
|
15
|
+
export declare function RouteMatch<R, P extends string, R2, E2, R3, E3>(route: Route.Route<R, P>, match: (params: Fx.Fx<never, never, Path.ParamsOf<P>>) => Fx.Fx<R2, E2, html.Renderable>, layout?: Fx.Fx<R3, E3, html.Renderable>): RouteMatch<R | R2 | R3, E2 | E3, P>;
|
|
16
|
+
//# sourceMappingURL=RouteMatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RouteMatch.d.ts","sourceRoot":"","sources":["../src/RouteMatch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA;AAEzC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,WAAW,CAAA;AAC/B,OAAO,KAAK,IAAI,MAAM,aAAa,CAAA;AACnC,OAAO,KAAK,IAAI,MAAM,aAAa,CAAA;AACnC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,MAAM,WAAW,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,MAAM;IAChD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAEjC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;IAE9C,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;IAE/F,QAAQ,CAAC,kBAAkB,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IAEzF,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IAEhG,QAAQ,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC,EAC3B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAC7B,UAAU,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;CAC1C;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAC5D,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EACxB,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,EACxF,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,GACtC,UAAU,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CA0BrC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { flow } from '@fp-ts/data/Function';
|
|
2
|
+
import * as Fx from '@typed/fx';
|
|
3
|
+
import * as Route from '@typed/route';
|
|
4
|
+
export function RouteMatch(route, match, layout) {
|
|
5
|
+
const routeMatch = {
|
|
6
|
+
route,
|
|
7
|
+
match,
|
|
8
|
+
layout,
|
|
9
|
+
provideEnvironment: (env) => RouteMatch(Route.provideEnvironment(env)(route), flow(match, Fx.provideSomeEnvironment(env)), layout ? Fx.provideEnvironment(env)(layout) : undefined),
|
|
10
|
+
provideService: (tag, service) => RouteMatch(Route.provideService(tag, service)(route), flow(match, Fx.provideService(tag)(service)), layout ? Fx.provideService(tag)(service)(layout) : undefined),
|
|
11
|
+
provideLayer: (layer) => RouteMatch(Route.provideLayer(layer)(route), flow(match, Fx.provideSomeLayer(layer)), layout ? Fx.provideSomeLayer(layer)(layout) : undefined),
|
|
12
|
+
};
|
|
13
|
+
return routeMatch;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=RouteMatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RouteMatch.js","sourceRoot":"","sources":["../src/RouteMatch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAE3C,OAAO,KAAK,EAAE,MAAM,WAAW,CAAA;AAG/B,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAkBrC,MAAM,UAAU,UAAU,CACxB,KAAwB,EACxB,KAAwF,EACxF,MAAuC;IAEvC,MAAM,UAAU,GAAwC;QACtD,KAAK;QACL,KAAK;QACL,MAAM;QACN,kBAAkB,EAAE,CAAC,GAAG,EAAE,EAAE,CAC1B,UAAU,CACR,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EACpC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,EAC3C,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CACxD;QACH,cAAc,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAC/B,UAAU,CACR,KAAK,CAAC,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,EACzC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,EAC5C,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAC7D;QACH,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CACtB,UAAU,CACR,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAChC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EACvC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CACxD;KACJ,CAAA;IAED,OAAO,UAAU,CAAA;AACnB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as Effect from '@effect/io/Effect';
|
|
2
|
+
import * as Layer from '@effect/io/Layer';
|
|
3
|
+
import * as Context from '@typed/context';
|
|
4
|
+
import * as Fx from '@typed/fx';
|
|
5
|
+
import * as html from '@typed/html';
|
|
6
|
+
import * as Path from '@typed/path';
|
|
7
|
+
import * as Route from '@typed/route';
|
|
8
|
+
import { RouteMatch } from './RouteMatch.js';
|
|
9
|
+
import { Redirect, Router } from './router.js';
|
|
10
|
+
export interface RouteMatcher<R = never, E = never> {
|
|
11
|
+
readonly routes: ReadonlyMap<Route.Route<any, any>, RouteMatch<any, any, any>>;
|
|
12
|
+
readonly match: <R2, P extends string, R3, E3>(route: Route.Route<R2, P>, f: (params: Path.ParamsOf<P>) => Fx.Fx<R3, E3, html.Renderable>) => RouteMatcher<R | R2, E | E3>;
|
|
13
|
+
readonly matchFx: <R2, P extends string, R3, E3>(route: Route.Route<R2, P>, f: (params: Fx.Fx<never, never, Path.ParamsOf<P>>) => Fx.Fx<R3, E3, html.Renderable>) => RouteMatcher<R | R2, E | E3>;
|
|
14
|
+
readonly matchEffect: <R2, P extends string, R3, E3>(route: Route.Route<R2, P>, f: (params: Path.ParamsOf<P>) => Effect.Effect<R3, E3, html.Renderable>) => RouteMatcher<R | R2, E | E3>;
|
|
15
|
+
readonly withLayout: <R2, E2>(fx: Fx.Fx<R2, E2, html.Renderable>) => RouteMatcher<R | R2, E | E2>;
|
|
16
|
+
readonly provideEnvironment: <R2>(environment: Context.Context<R2>) => RouteMatcher<Exclude<R, R2>, E>;
|
|
17
|
+
readonly provideService: <R2>(tag: Context.Tag<R2>, service: R2) => RouteMatcher<Exclude<R, R2>, E>;
|
|
18
|
+
readonly provideLayer: <R2, S>(layer: Layer.Layer<R2, never, S>) => RouteMatcher<Exclude<R, S> | R2, E>;
|
|
19
|
+
readonly notFound: <R2, E2, R3 = never, E3 = never>(f: (path: string) => Fx.Fx<R2, E2, html.Renderable>, options?: FallbackOptions<R3, E3>) => Fx.Fx<Router | R | R2 | R3, E | E2 | E3, html.Renderable>;
|
|
20
|
+
readonly notFoundEffect: <R2, E2, R3 = never, E3 = never>(f: (path: string) => Effect.Effect<R2, E2, html.Renderable>, options?: FallbackOptions<R3, E3>) => Fx.Fx<Router | R | R2 | R3, E | E2 | E3, html.Renderable>;
|
|
21
|
+
readonly redirectTo: <R2, P extends string>(route: Route.Route<R2, P>, ...params: [keyof Path.ParamsOf<P>] extends [never] ? [
|
|
22
|
+
{}?
|
|
23
|
+
] : [(path: string) => Path.ParamsOf<P>]) => Fx.Fx<Router | R | R2, E | Redirect, html.Renderable>;
|
|
24
|
+
/**
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
readonly run: Fx.Fx<Router | R, E | Redirect, html.Renderable | null>;
|
|
28
|
+
}
|
|
29
|
+
export interface FallbackOptions<R, E> {
|
|
30
|
+
readonly layout?: Fx.Fx<R, E, html.Renderable>;
|
|
31
|
+
}
|
|
32
|
+
export declare function RouteMatcher<R, E>(routes: RouteMatcher<R, E>['routes']): RouteMatcher<R, E>;
|
|
33
|
+
export declare namespace RouteMatcher {
|
|
34
|
+
const empty: RouteMatcher<never, never>;
|
|
35
|
+
const concat: <R, E, R2, E2>(matcher: RouteMatcher<R, E>, matcher2: RouteMatcher<R2, E2>) => RouteMatcher<R | R2, E | E2>;
|
|
36
|
+
}
|
|
37
|
+
export declare const matchFx: <R2, P extends string, R3, E3>(route: Route.Route<R2, P>, f: (params: Fx.Fx<never, never, Path.PartsToParams<Path.PathToParts<P>, {}> extends infer T ? { readonly [K in keyof T]: Path.PartsToParams<Path.PathToParts<P>, {}>[K]; } : never>) => Fx.Fx<R3, E3, html.Renderable>) => RouteMatcher<R2, E3>, match: <R2, P extends string, R3, E3>(route: Route.Route<R2, P>, f: (params: Path.PartsToParams<Path.PathToParts<P>, {}> extends infer T ? { readonly [K in keyof T]: Path.PartsToParams<Path.PathToParts<P>, {}>[K]; } : never) => Fx.Fx<R3, E3, html.Renderable>) => RouteMatcher<R2, E3>, matchEffect: <R2, P extends string, R3, E3>(route: Route.Route<R2, P>, f: (params: Path.PartsToParams<Path.PathToParts<P>, {}> extends infer T ? { readonly [K in keyof T]: Path.PartsToParams<Path.PathToParts<P>, {}>[K]; } : never) => Effect.Effect<R3, E3, html.Renderable>) => RouteMatcher<R2, E3>;
|
|
38
|
+
//# sourceMappingURL=RouteMatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RouteMatcher.d.ts","sourceRoot":"","sources":["../src/RouteMatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/ban-types */
|
|
2
|
+
import * as Effect from '@effect/io/Effect';
|
|
3
|
+
import * as Fiber from '@effect/io/Fiber';
|
|
4
|
+
import { pipe } from '@fp-ts/data/Function';
|
|
5
|
+
import * as Option from '@fp-ts/data/Option';
|
|
6
|
+
import * as Fx from '@typed/fx';
|
|
7
|
+
import { RenderContext } from '@typed/html';
|
|
8
|
+
import * as Route from '@typed/route';
|
|
9
|
+
import { RouteMatch } from './RouteMatch.js';
|
|
10
|
+
import { currentPath, redirectTo, Router } from './router.js';
|
|
11
|
+
export function RouteMatcher(routes) {
|
|
12
|
+
const matcher = {
|
|
13
|
+
routes,
|
|
14
|
+
matchFx: (route, f) => RouteMatcher(new Map(routes).set(route, RouteMatch(route, f))),
|
|
15
|
+
match: (route, f) => RouteMatcher(new Map(routes).set(route, RouteMatch(route, Fx.switchMap(f)))),
|
|
16
|
+
matchEffect: (route, f) => RouteMatcher(new Map(routes).set(route, RouteMatch(route, Fx.switchMapEffect(f)))),
|
|
17
|
+
withLayout: (layout) => RouteMatcher(new Map(Array.from(routes).map(([k, match]) => [
|
|
18
|
+
k,
|
|
19
|
+
RouteMatch(match.route, match.match, match.layout ?? layout),
|
|
20
|
+
]))),
|
|
21
|
+
provideEnvironment: (environment) => RouteMatcher(new Map(Array.from(routes).map(([k, v]) => [k, v.provideEnvironment(environment)]))),
|
|
22
|
+
provideService: (tag, service) => RouteMatcher(new Map(Array.from(routes).map(([k, v]) => [k, v.provideService(tag, service)]))),
|
|
23
|
+
provideLayer: (layer) => RouteMatcher(new Map(Array.from(routes).map(([k, v]) => [k, v.provideLayer(layer)]))),
|
|
24
|
+
notFound: (f, options = {}) => Router.withFx((router) => Fx.gen(function* ($) {
|
|
25
|
+
const { environment } = yield* $(RenderContext.get);
|
|
26
|
+
// Create stable references to the route matchers
|
|
27
|
+
const matchers = Array.from(routes.values()).map((v) => [v, runRouteMatch(router, v)]);
|
|
28
|
+
const renderFallback = pipe(currentPath, Fx.switchMap(f));
|
|
29
|
+
const fallbackMatch = RouteMatch(Route.base, () => renderFallback, options?.layout);
|
|
30
|
+
let previousFiber;
|
|
31
|
+
let previousLayout;
|
|
32
|
+
let previousRender;
|
|
33
|
+
const samplePreviousValues = () => ({
|
|
34
|
+
fiber: previousFiber,
|
|
35
|
+
layout: previousLayout,
|
|
36
|
+
render: previousRender,
|
|
37
|
+
});
|
|
38
|
+
// This function helps us to ensure shared layouts are only rendered once
|
|
39
|
+
// and the outlet content is changed
|
|
40
|
+
const verifyShouldRerender = (match, render) => Effect.gen(function* ($) {
|
|
41
|
+
const previous = samplePreviousValues();
|
|
42
|
+
// Update the previous values
|
|
43
|
+
previousRender = render;
|
|
44
|
+
previousLayout = match.layout;
|
|
45
|
+
previousFiber = undefined;
|
|
46
|
+
// Skip rerendering if the render function is the same
|
|
47
|
+
if (previous.render === render) {
|
|
48
|
+
return Option.none;
|
|
49
|
+
}
|
|
50
|
+
// Interrupt the previous fiber if it exists
|
|
51
|
+
if (previous.fiber) {
|
|
52
|
+
yield* $(Fiber.interrupt(previous.fiber));
|
|
53
|
+
}
|
|
54
|
+
// If we have a layout, we need to render it and use the route outlet.
|
|
55
|
+
if (match.layout) {
|
|
56
|
+
// Render into the route outlet
|
|
57
|
+
previousFiber = yield* $(pipe(render, Fx.observe(router.outlet.set), Effect.forkScoped));
|
|
58
|
+
return Option.some(match.layout);
|
|
59
|
+
}
|
|
60
|
+
// If we don't have a layout, but we did, we need to clear the outlet
|
|
61
|
+
if (previous.layout) {
|
|
62
|
+
yield* $(router.outlet.set(null));
|
|
63
|
+
}
|
|
64
|
+
// Otherwise use the render function directly
|
|
65
|
+
return Option.some(render);
|
|
66
|
+
});
|
|
67
|
+
return pipe(router.currentPath, environment === 'browser' ? Fx.skipRepeats : Fx.take(1), Fx.switchMapEffect((path) => Effect.gen(function* ($) {
|
|
68
|
+
yield* $(Effect.logDebug(`[@typed/router] Matching path: ${path}.`));
|
|
69
|
+
// Attempt to find the best match
|
|
70
|
+
for (const [match, render] of matchers) {
|
|
71
|
+
yield* $(Effect.logDebug(`[@typed/router] Matching against: ${match.route.path}.`));
|
|
72
|
+
const result = yield* $(match.route.match(path));
|
|
73
|
+
if (Option.isSome(result)) {
|
|
74
|
+
yield* $(Effect.logDebug(`[@typed/router] Matched against: ${match.route.path}.`));
|
|
75
|
+
return yield* $(verifyShouldRerender(match, render));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
yield* $(Effect.logDebug(`[@typed/router] Rendering fallback.`));
|
|
79
|
+
// If we didn't find a match, render the not found page
|
|
80
|
+
return yield* $(verifyShouldRerender(fallbackMatch, renderFallback));
|
|
81
|
+
})), Fx.compact, Fx.skipRepeats, // Stable render references are used to avoid mounting the same component twice
|
|
82
|
+
Fx.switchLatest);
|
|
83
|
+
})),
|
|
84
|
+
notFoundEffect: (f) => matcher.notFound((path) => Fx.fromEffect(f(path))),
|
|
85
|
+
redirectTo: ((route, ...params) => matcher.notFound(() => redirectTo.fx(route, ...params))),
|
|
86
|
+
run: Fx.suspend(() => matcher.notFoundEffect(Effect.never)),
|
|
87
|
+
};
|
|
88
|
+
return matcher;
|
|
89
|
+
}
|
|
90
|
+
(function (RouteMatcher) {
|
|
91
|
+
RouteMatcher.empty = RouteMatcher(new Map());
|
|
92
|
+
RouteMatcher.concat = (matcher, matcher2) => RouteMatcher(new Map([...matcher.routes, ...matcher2.routes]));
|
|
93
|
+
})(RouteMatcher || (RouteMatcher = {}));
|
|
94
|
+
export const { matchFx, match, matchEffect } = RouteMatcher(new Map());
|
|
95
|
+
function runRouteMatch(router, { route, match }) {
|
|
96
|
+
return Fx.gen(function* ($) {
|
|
97
|
+
const env = yield* $(Effect.environment());
|
|
98
|
+
const nestedRouter = router.define(route);
|
|
99
|
+
const params = pipe(nestedRouter.params, Fx.provideEnvironment(env));
|
|
100
|
+
return pipe(match(params), Router.provideFx(nestedRouter));
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=RouteMatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RouteMatcher.js","sourceRoot":"","sources":["../src/RouteMatcher.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA"}
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as Effect from '@effect/io/Effect';
|
|
2
|
+
import * as Layer from '@effect/io/Layer';
|
|
3
|
+
import * as Scope from '@effect/io/Scope';
|
|
4
|
+
import * as Context from '@typed/context';
|
|
5
|
+
import { Location, History } from '@typed/dom';
|
|
6
|
+
import * as Fx from '@typed/fx';
|
|
7
|
+
import * as html from '@typed/html';
|
|
8
|
+
import { RenderContext } from '@typed/html';
|
|
9
|
+
import * as Path from '@typed/path';
|
|
10
|
+
import * as Route from '@typed/route';
|
|
11
|
+
export interface Router<out R = never, in out P extends string = string> {
|
|
12
|
+
/**
|
|
13
|
+
* The base route the Router is starting from.
|
|
14
|
+
*/
|
|
15
|
+
readonly route: Route.Route<R, P>;
|
|
16
|
+
/**
|
|
17
|
+
* The current path of the application
|
|
18
|
+
*/
|
|
19
|
+
readonly currentPath: Fx.RefSubject<string>;
|
|
20
|
+
/**
|
|
21
|
+
* The current matched params of the router
|
|
22
|
+
*/
|
|
23
|
+
readonly params: Fx.Fx<R, never, Path.ParamsOf<P>>;
|
|
24
|
+
/**
|
|
25
|
+
* The current outlet of this Router
|
|
26
|
+
*/
|
|
27
|
+
readonly outlet: Fx.RefSubject<html.Renderable>;
|
|
28
|
+
/**
|
|
29
|
+
* Helper for constructing a path from a route relative to the router.
|
|
30
|
+
*/
|
|
31
|
+
readonly createPath: <R2 extends Route.Route<any, string>, P extends Route.ParamsOf<R2>>(route: R2, ...[params]: [keyof P] extends [never] ? [] : [P]) => Effect.Effect<R, never, Path.PathJoin<[
|
|
32
|
+
Path.Interpolate<Route.PathOf<R>, Route.ParamsOf<R>>,
|
|
33
|
+
Path.Interpolate<Route.PathOf<R2>, P>
|
|
34
|
+
]>>;
|
|
35
|
+
/**
|
|
36
|
+
* Helper for constructing a nested router
|
|
37
|
+
*/
|
|
38
|
+
readonly define: <R2, Path2 extends string>(route: Route.Route<R2, Path2>) => Router<R | R2, Path.PathJoin<[P, Path2]>>;
|
|
39
|
+
/**
|
|
40
|
+
* Provide all the resources needed for a Router
|
|
41
|
+
*/
|
|
42
|
+
readonly provideEnvironment: (environment: Context.Context<R>) => Router<never, P>;
|
|
43
|
+
}
|
|
44
|
+
export declare const Router: (<R = never, P extends string = string>(route: Route.Route<R, P>, currentPath: Fx.RefSubject<string>) => Router<R, P>) & Context.Tag<Router<never, string>>;
|
|
45
|
+
export declare const outlet: Fx.Fx<RenderContext | Router, never, html.Renderable>;
|
|
46
|
+
export declare const currentPath: Fx.Fx<Router, never, string>;
|
|
47
|
+
export declare function provideEnvironment<R>(environment: Context.Context<R>): <P extends string>(router: Router<R, P>) => Router<never, P>;
|
|
48
|
+
export interface Redirect {
|
|
49
|
+
readonly _tag: 'Redirect';
|
|
50
|
+
readonly path: string;
|
|
51
|
+
}
|
|
52
|
+
export declare namespace Redirect {
|
|
53
|
+
const make: (path: string) => Redirect;
|
|
54
|
+
const is: (r: unknown) => r is Redirect;
|
|
55
|
+
}
|
|
56
|
+
export declare function redirect(path: string): Effect.Effect<never, Redirect, never>;
|
|
57
|
+
export declare namespace redirect {
|
|
58
|
+
var fx: (path: string) => Fx.Fx<never, Redirect, never>;
|
|
59
|
+
}
|
|
60
|
+
export declare const redirectTo: {
|
|
61
|
+
<R, P extends string>(route: Route.Route<R, P>, ...[params]: [keyof Path.PartsToParams<Path.PathToParts<P>, {}>] extends [never] ? [({} | undefined)?] : [Path.PartsToParams<Path.PathToParts<P>, {}> extends infer T ? { readonly [K in keyof T]: Path.PartsToParams<Path.PathToParts<P>, {}>[K]; } : never]): Effect.Effect<Router, Redirect, never>;
|
|
62
|
+
fx<R_1, P_1 extends string>(route: Route.Route<R_1, P_1>, ...params: [keyof Path.PartsToParams<Path.PathToParts<P_1>, {}>] extends [never] ? [({} | undefined)?] : [(path: string) => Path.PartsToParams<Path.PathToParts<P_1>, {}> extends infer T_1 ? { readonly [K_1 in keyof T_1]: Path.PartsToParams<Path.PathToParts<P_1>, {}>[K_1]; } : never]): Fx.Fx<Router, Redirect, never>;
|
|
63
|
+
};
|
|
64
|
+
export declare const makeRouter: (currentPath?: Fx.RefSubject<string>) => Effect.Effect<Location | History | Window | Document | Scope.Scope, never, Router>;
|
|
65
|
+
export declare const live: (currentPath?: Fx.RefSubject<string>) => Layer.Layer<Location | History | Window | Document, never, Router<never, string>>;
|
|
66
|
+
export declare function getCurrentPath(location: Location | HTMLAnchorElement): string;
|
|
67
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/ban-types */
|
|
2
|
+
import * as Effect from '@effect/io/Effect';
|
|
3
|
+
import { pipe } from '@fp-ts/data/Function';
|
|
4
|
+
import * as Option from '@fp-ts/data/Option';
|
|
5
|
+
import * as Context from '@typed/context';
|
|
6
|
+
import { Location, History, addWindowListener } from '@typed/dom';
|
|
7
|
+
import * as Fx from '@typed/fx';
|
|
8
|
+
import { RenderContext } from '@typed/html';
|
|
9
|
+
import * as Route from '@typed/route';
|
|
10
|
+
export const Router = Object.assign(function makeRouter(route, currentPath) {
|
|
11
|
+
const outlet = Fx.RefSubject.unsafeMake(() => null);
|
|
12
|
+
const createPath = (other, ...[params]) => Effect.gen(function* ($) {
|
|
13
|
+
const path = yield* $(currentPath.get);
|
|
14
|
+
const baseParams = yield* $(route.match(path));
|
|
15
|
+
if (Option.isNone(baseParams)) {
|
|
16
|
+
return yield* $(Effect.dieMessage(`Can not create path when the parent can not be matched.
|
|
17
|
+
Parent Route: ${route.path}
|
|
18
|
+
Current Route: ${other.path}
|
|
19
|
+
Current Path: ${path}`));
|
|
20
|
+
}
|
|
21
|
+
return route.concat(other).make({ ...baseParams.value, ...params });
|
|
22
|
+
});
|
|
23
|
+
const router = {
|
|
24
|
+
route,
|
|
25
|
+
currentPath,
|
|
26
|
+
params: pipe(currentPath, Fx.switchMapEffect(route.match), Fx.compact, Fx.skipRepeats),
|
|
27
|
+
outlet,
|
|
28
|
+
createPath: createPath,
|
|
29
|
+
define: (other) => makeRouter(route.concat(other), currentPath),
|
|
30
|
+
provideEnvironment: (env) => provideEnvironment(env)(router),
|
|
31
|
+
};
|
|
32
|
+
return router;
|
|
33
|
+
}, Context.Tag());
|
|
34
|
+
export const outlet = RenderContext.withFx(({ environment }) => Router.withFx((r) => environment === 'browser'
|
|
35
|
+
? r.outlet
|
|
36
|
+
: pipe(r.outlet, Fx.skipUntil((x) => x !== null), Fx.take(1))));
|
|
37
|
+
export const currentPath = Router.withFx((r) => r.currentPath);
|
|
38
|
+
export function provideEnvironment(environment) {
|
|
39
|
+
return (router) => {
|
|
40
|
+
const provided = {
|
|
41
|
+
...router,
|
|
42
|
+
params: pipe(router.params, Fx.provideEnvironment(environment)),
|
|
43
|
+
route: Route.provideEnvironment(environment)(router.route),
|
|
44
|
+
createPath: ((other, ...params) => Effect.provideEnvironment(environment)(router.createPath(other, ...params))),
|
|
45
|
+
provideEnvironment: (env) => provideEnvironment(env)(provided),
|
|
46
|
+
};
|
|
47
|
+
return provided;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export var Redirect;
|
|
51
|
+
(function (Redirect) {
|
|
52
|
+
Redirect.make = (path) => ({ _tag: 'Redirect', path });
|
|
53
|
+
Redirect.is = (r) => typeof r === 'object' && r !== null && '_tag' in r && r._tag === 'Redirect';
|
|
54
|
+
})(Redirect || (Redirect = {}));
|
|
55
|
+
export function redirect(path) {
|
|
56
|
+
return Effect.fail(Redirect.make(path));
|
|
57
|
+
}
|
|
58
|
+
redirect.fx = (path) => Fx.fail(Redirect.make(path));
|
|
59
|
+
export const redirectTo = (route, ...[params]) => pipe(Router.withEffect((r) => r.createPath(route, params)), Effect.flatMap(redirect));
|
|
60
|
+
redirectTo.fx = (route, ...params) => pipe(Router.withEffect((r) => r.createPath(route, params)), Fx.fromEffect, Fx.switchMap(redirect.fx));
|
|
61
|
+
export const makeRouter = (currentPath) => Effect.gen(function* ($) {
|
|
62
|
+
const history = yield* $(History.get);
|
|
63
|
+
const location = yield* $(Location.get);
|
|
64
|
+
if (!currentPath) {
|
|
65
|
+
currentPath = Fx.RefSubject.unsafeMake(() => getCurrentPath(location));
|
|
66
|
+
}
|
|
67
|
+
// Patch history events to emit an event when the path changes
|
|
68
|
+
const historyEvents = yield* $(patchHistory);
|
|
69
|
+
// Update the current path when events occur:
|
|
70
|
+
// - popstate
|
|
71
|
+
// - hashchange
|
|
72
|
+
// - history events
|
|
73
|
+
yield* $(pipe(Fx.mergeAll(addWindowListener('popstate'), addWindowListener('hashchange'), historyEvents),
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
75
|
+
Fx.switchMapEffect(() => currentPath.set(getCurrentPath(location))), Fx.forkScoped));
|
|
76
|
+
// Listen to path changes and update the current history location, if necessary
|
|
77
|
+
yield* $(pipe(currentPath, Fx.skipRepeats, Fx.observe((path) => Effect.sync(() => {
|
|
78
|
+
if (path !== getCurrentPath(location)) {
|
|
79
|
+
history.pushState({}, '', path);
|
|
80
|
+
}
|
|
81
|
+
})), Effect.forkScoped));
|
|
82
|
+
// Make our base router
|
|
83
|
+
return Router(Route.base, currentPath);
|
|
84
|
+
});
|
|
85
|
+
export const live = (currentPath) => Router.layerSoped(makeRouter(currentPath));
|
|
86
|
+
export function getCurrentPath(location) {
|
|
87
|
+
return location.pathname + location.search + location.hash;
|
|
88
|
+
}
|
|
89
|
+
const patchHistory = Effect.gen(function* ($) {
|
|
90
|
+
const history = yield* $(History.get);
|
|
91
|
+
const historyEvents = Fx.Subject.unsafeMake();
|
|
92
|
+
const runtime = yield* $(Effect.runtime());
|
|
93
|
+
patchHistory_(history, () => runtime.unsafeRun(historyEvents.event()));
|
|
94
|
+
return historyEvents;
|
|
95
|
+
});
|
|
96
|
+
function patchHistory_(history, sendEvent) {
|
|
97
|
+
const pushState = history.pushState.bind(history);
|
|
98
|
+
const replaceState = history.replaceState.bind(history);
|
|
99
|
+
const go = history.go.bind(history);
|
|
100
|
+
const back = history.back.bind(history);
|
|
101
|
+
const forward = history.forward.bind(history);
|
|
102
|
+
history.pushState = function (state, title, url) {
|
|
103
|
+
pushState(state, title, url);
|
|
104
|
+
sendEvent();
|
|
105
|
+
};
|
|
106
|
+
history.replaceState = function (state, title, url) {
|
|
107
|
+
replaceState(state, title, url);
|
|
108
|
+
sendEvent();
|
|
109
|
+
};
|
|
110
|
+
history.go = function (delta) {
|
|
111
|
+
go(delta);
|
|
112
|
+
sendEvent();
|
|
113
|
+
};
|
|
114
|
+
history.back = function () {
|
|
115
|
+
back();
|
|
116
|
+
sendEvent();
|
|
117
|
+
};
|
|
118
|
+
history.forward = function () {
|
|
119
|
+
forward();
|
|
120
|
+
sendEvent();
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|
package/eslintrc.json
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@typed/router",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"typings": "dist/index.d.ts",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./*": {
|
|
15
|
+
"import": "./dist/*.js",
|
|
16
|
+
"types": "./dist/*.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"./*.js": {
|
|
19
|
+
"import": "./dist/*.js",
|
|
20
|
+
"types": "./dist/*.d.ts"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@effect/io": "~0.0.52",
|
|
25
|
+
"@fp-ts/data": "~0.0.36",
|
|
26
|
+
"@typed/context": "0.0.2",
|
|
27
|
+
"@typed/dom": "8.0.1",
|
|
28
|
+
"@typed/fx": "1.0.1",
|
|
29
|
+
"@typed/html": "3.0.1",
|
|
30
|
+
"@typed/path": "0.0.2",
|
|
31
|
+
"@typed/route": "0.0.2"
|
|
32
|
+
},
|
|
33
|
+
"gitHead": "1d31563070523e63b479cf41b90655b4c9fa641e",
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
}
|
|
37
|
+
}
|
package/project.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
3
|
+
"projectType": "library",
|
|
4
|
+
"targets": {
|
|
5
|
+
"build": {
|
|
6
|
+
"executor": "nx:run-commands",
|
|
7
|
+
"options": {
|
|
8
|
+
"commands": [
|
|
9
|
+
{
|
|
10
|
+
"command": "tsc --build packages/router/tsconfig.build.json"
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
"outputs": ["{projectRoot}/dist"]
|
|
15
|
+
},
|
|
16
|
+
"lint": {
|
|
17
|
+
"executor": "@nrwl/linter:eslint",
|
|
18
|
+
"options": {
|
|
19
|
+
"lintFilePatterns": ["packages/router/src/**/*.ts"]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"test": {
|
|
23
|
+
"executor": "@nrwl/vite:test"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/Link.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as Effect from '@effect/io/Effect'
|
|
2
|
+
import * as Fx from '@typed/fx'
|
|
3
|
+
import { EventHandler, html, Hole, Placeholder } from '@typed/html'
|
|
4
|
+
|
|
5
|
+
import { Router } from './router.js'
|
|
6
|
+
|
|
7
|
+
export function Link<R = never, E = never, R2 = never>(
|
|
8
|
+
props: LinkProps<R, E, R2>,
|
|
9
|
+
): Fx.Fx<R | R2 | Router, E, Hole> {
|
|
10
|
+
const clickHandler = (event: MouseEvent & { currentTarget: HTMLAnchorElement }) =>
|
|
11
|
+
Effect.gen(function* ($) {
|
|
12
|
+
const { currentPath } = yield* $(Router.get)
|
|
13
|
+
|
|
14
|
+
yield* $(currentPath.set(props.href))
|
|
15
|
+
|
|
16
|
+
if (props.onClick) {
|
|
17
|
+
yield* $(props.onClick(event))
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
return html`<a
|
|
22
|
+
class=${props.className}
|
|
23
|
+
href="${props.href}"
|
|
24
|
+
onclick=${EventHandler.preventDefault(clickHandler)}
|
|
25
|
+
>${props.label}</a
|
|
26
|
+
>`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface LinkProps<R, E, R2> {
|
|
30
|
+
readonly href: string
|
|
31
|
+
readonly label: string | Placeholder<R, E>
|
|
32
|
+
readonly className?: string
|
|
33
|
+
readonly onClick?: (
|
|
34
|
+
event: MouseEvent & { currentTarget: HTMLAnchorElement },
|
|
35
|
+
) => Effect.Effect<R2, never, unknown>
|
|
36
|
+
}
|