@typed/navigation 0.5.4 → 0.6.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 +5 -0
- package/dist/cjs/Blocking.js +53 -0
- package/dist/cjs/Blocking.js.map +1 -0
- package/dist/cjs/Layer.js +27 -0
- package/dist/cjs/Layer.js.map +1 -0
- package/dist/cjs/Navigation.js +184 -62
- package/dist/cjs/Navigation.js.map +1 -1
- package/dist/cjs/index.js +36 -17
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/internal/fromWindow.js +376 -0
- package/dist/cjs/internal/fromWindow.js.map +1 -0
- package/dist/cjs/internal/memory.js +67 -0
- package/dist/cjs/internal/memory.js.map +1 -0
- package/dist/cjs/internal/shared.js +403 -0
- package/dist/cjs/internal/shared.js.map +1 -0
- package/dist/dts/Blocking.d.ts +33 -0
- package/dist/dts/Blocking.d.ts.map +1 -0
- package/dist/dts/Layer.d.ts +44 -0
- package/dist/dts/Layer.d.ts.map +1 -0
- package/dist/dts/Navigation.d.ts +377 -0
- package/dist/dts/Navigation.d.ts.map +1 -0
- package/dist/dts/index.d.ts +17 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/internal/fromWindow.d.ts +12 -0
- package/dist/dts/internal/fromWindow.d.ts.map +1 -0
- package/dist/dts/internal/memory.d.ts +6 -0
- package/dist/dts/internal/memory.d.ts.map +1 -0
- package/dist/dts/internal/shared.d.ts +139 -0
- package/dist/dts/internal/shared.d.ts.map +1 -0
- package/dist/esm/Blocking.js +39 -0
- package/dist/esm/Blocking.js.map +1 -0
- package/dist/esm/Layer.js +18 -0
- package/dist/esm/Layer.js.map +1 -0
- package/dist/esm/Navigation.js +166 -0
- package/dist/esm/Navigation.js.map +1 -0
- package/dist/esm/index.js +17 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/fromWindow.js +273 -0
- package/dist/esm/internal/fromWindow.js.map +1 -0
- package/dist/esm/internal/memory.js +54 -0
- package/dist/esm/internal/memory.js.map +1 -0
- package/dist/esm/internal/shared.js +336 -0
- package/dist/esm/internal/shared.js.map +1 -0
- package/dist/esm/package.json +4 -0
- package/package.json +52 -32
- package/src/Blocking.ts +102 -0
- package/src/Layer.ts +53 -0
- package/src/Navigation.ts +342 -159
- package/src/index.ts +17 -3
- package/src/internal/fromWindow.ts +421 -0
- package/src/internal/memory.ts +79 -0
- package/src/internal/shared.ts +514 -0
- package/dist/DOM.d.ts +0 -12
- package/dist/DOM.d.ts.map +0 -1
- package/dist/DOM.js +0 -87
- package/dist/DOM.js.map +0 -1
- package/dist/Memory.d.ts +0 -10
- package/dist/Memory.d.ts.map +0 -1
- package/dist/Memory.js +0 -55
- package/dist/Memory.js.map +0 -1
- package/dist/Navigation.d.ts +0 -116
- package/dist/Navigation.d.ts.map +0 -1
- package/dist/Navigation.js +0 -36
- package/dist/Navigation.js.map +0 -1
- package/dist/_makeServerWindow.d.ts +0 -16
- package/dist/_makeServerWindow.d.ts.map +0 -1
- package/dist/_makeServerWindow.js +0 -9
- package/dist/_makeServerWindow.js.map +0 -1
- package/dist/cjs/DOM.d.ts +0 -12
- package/dist/cjs/DOM.d.ts.map +0 -1
- package/dist/cjs/DOM.js +0 -116
- package/dist/cjs/DOM.js.map +0 -1
- package/dist/cjs/Memory.d.ts +0 -10
- package/dist/cjs/Memory.d.ts.map +0 -1
- package/dist/cjs/Memory.js +0 -82
- package/dist/cjs/Memory.js.map +0 -1
- package/dist/cjs/Navigation.d.ts +0 -116
- package/dist/cjs/Navigation.d.ts.map +0 -1
- package/dist/cjs/_makeServerWindow.d.ts +0 -16
- package/dist/cjs/_makeServerWindow.d.ts.map +0 -1
- package/dist/cjs/_makeServerWindow.js +0 -36
- package/dist/cjs/_makeServerWindow.js.map +0 -1
- package/dist/cjs/dom-intent.d.ts +0 -28
- package/dist/cjs/dom-intent.d.ts.map +0 -1
- package/dist/cjs/dom-intent.js +0 -172
- package/dist/cjs/dom-intent.js.map +0 -1
- package/dist/cjs/history.d.ts +0 -31
- package/dist/cjs/history.d.ts.map +0 -1
- package/dist/cjs/history.js +0 -131
- package/dist/cjs/history.js.map +0 -1
- package/dist/cjs/index.d.ts +0 -4
- package/dist/cjs/index.d.ts.map +0 -1
- package/dist/cjs/json.d.ts +0 -13
- package/dist/cjs/json.d.ts.map +0 -1
- package/dist/cjs/json.js +0 -24
- package/dist/cjs/json.js.map +0 -1
- package/dist/cjs/memory-intent.d.ts +0 -27
- package/dist/cjs/memory-intent.d.ts.map +0 -1
- package/dist/cjs/memory-intent.js +0 -156
- package/dist/cjs/memory-intent.js.map +0 -1
- package/dist/cjs/model.d.ts +0 -22
- package/dist/cjs/model.d.ts.map +0 -1
- package/dist/cjs/model.js +0 -48
- package/dist/cjs/model.js.map +0 -1
- package/dist/cjs/shared-intent.d.ts +0 -14
- package/dist/cjs/shared-intent.d.ts.map +0 -1
- package/dist/cjs/shared-intent.js +0 -82
- package/dist/cjs/shared-intent.js.map +0 -1
- package/dist/cjs/storage.d.ts +0 -19
- package/dist/cjs/storage.d.ts.map +0 -1
- package/dist/cjs/storage.js +0 -101
- package/dist/cjs/storage.js.map +0 -1
- package/dist/cjs/util.d.ts +0 -5
- package/dist/cjs/util.d.ts.map +0 -1
- package/dist/cjs/util.js +0 -39
- package/dist/cjs/util.js.map +0 -1
- package/dist/dom-intent.d.ts +0 -28
- package/dist/dom-intent.d.ts.map +0 -1
- package/dist/dom-intent.js +0 -140
- package/dist/dom-intent.js.map +0 -1
- package/dist/history.d.ts +0 -31
- package/dist/history.d.ts.map +0 -1
- package/dist/history.js +0 -104
- package/dist/history.js.map +0 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +0 -1
- package/dist/json.d.ts +0 -13
- package/dist/json.d.ts.map +0 -1
- package/dist/json.js +0 -17
- package/dist/json.js.map +0 -1
- package/dist/memory-intent.d.ts +0 -27
- package/dist/memory-intent.d.ts.map +0 -1
- package/dist/memory-intent.js +0 -124
- package/dist/memory-intent.js.map +0 -1
- package/dist/model.d.ts +0 -22
- package/dist/model.d.ts.map +0 -1
- package/dist/model.js +0 -21
- package/dist/model.js.map +0 -1
- package/dist/shared-intent.d.ts +0 -14
- package/dist/shared-intent.d.ts.map +0 -1
- package/dist/shared-intent.js +0 -51
- package/dist/shared-intent.js.map +0 -1
- package/dist/storage.d.ts +0 -19
- package/dist/storage.d.ts.map +0 -1
- package/dist/storage.js +0 -73
- package/dist/storage.js.map +0 -1
- package/dist/tsconfig.cjs.build.tsbuildinfo +0 -1
- package/dist/util.d.ts +0 -5
- package/dist/util.d.ts.map +0 -1
- package/dist/util.js +0 -12
- package/dist/util.js.map +0 -1
- package/eslintrc.json +0 -3
- package/project.json +0 -46
- package/src/DOM.test.ts +0 -699
- package/src/DOM.ts +0 -163
- package/src/Memory.test.ts +0 -464
- package/src/Memory.ts +0 -102
- package/src/_makeServerWindow.ts +0 -28
- package/src/dom-intent.ts +0 -268
- package/src/history.ts +0 -165
- package/src/json.ts +0 -31
- package/src/memory-intent.ts +0 -224
- package/src/model.ts +0 -54
- package/src/shared-intent.ts +0 -117
- package/src/storage.ts +0 -101
- package/src/util.ts +0 -20
- package/tsconfig.build.json +0 -4
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.cjs.build.json +0 -22
- package/tsconfig.json +0 -27
- package/vite.config.mjs +0 -3
package/src/Navigation.ts
CHANGED
|
@@ -1,192 +1,375 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import * as
|
|
7
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { ParseResult } from "@effect/schema"
|
|
6
|
+
import * as Schema from "@effect/schema/Schema"
|
|
7
|
+
import { Tagged } from "@typed/context"
|
|
8
|
+
import * as Computed from "@typed/fx/Computed"
|
|
9
|
+
import type { Uuid } from "@typed/id"
|
|
10
|
+
import * as IdSchema from "@typed/id/Schema"
|
|
11
|
+
import type { Option, Scope } from "effect"
|
|
12
|
+
import { Data, Effect } from "effect"
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @since 1.0.0
|
|
16
|
+
*/
|
|
8
17
|
export interface Navigation {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*/
|
|
18
|
+
readonly origin: string
|
|
19
|
+
|
|
12
20
|
readonly base: string
|
|
13
21
|
|
|
14
|
-
|
|
15
|
-
* The list of navigation entries that are currently kept in-memory and
|
|
16
|
-
* saved within Local/Session Storage.
|
|
17
|
-
*/
|
|
18
|
-
readonly entries: Fx.Computed<never, never, readonly Destination[]>
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* The currently focused navigation entry.
|
|
22
|
-
*/
|
|
23
|
-
readonly currentEntry: Fx.Computed<never, never, Destination>
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Navigate to a new URL. NavigateOptions can be used to control how the
|
|
27
|
-
* navigation is handled via history.pushState or history.replaceState,
|
|
28
|
-
* set/update the state of the navigation entry, or provide a key to use
|
|
29
|
-
* for the navigation entry.
|
|
30
|
-
*/
|
|
31
|
-
readonly navigate: (
|
|
32
|
-
url: string,
|
|
33
|
-
options?: NavigateOptions,
|
|
34
|
-
) => Effect.Effect<never, never, Destination>
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Subscribe to navigation events. Any handler can cancel the or redirect
|
|
38
|
-
* the navigation by failing with a CancelNavigation or RedirectNavigation
|
|
39
|
-
* error.
|
|
40
|
-
*/
|
|
41
|
-
readonly onNavigation: <R>(
|
|
42
|
-
handler: (event: NavigationEvent) => Effect.Effect<R, NavigationError, void>,
|
|
43
|
-
options?: OnNavigationOptions,
|
|
44
|
-
) => Effect.Effect<R | Scope.Scope, never, void>
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Subscribe to navigation events after they have been commited.
|
|
48
|
-
*/
|
|
49
|
-
readonly onNavigationEnd: <R>(
|
|
50
|
-
handler: (event: NavigationEvent) => Effect.Effect<R, never, void>,
|
|
51
|
-
options?: OnNavigationOptions,
|
|
52
|
-
) => Effect.Effect<R | Scope.Scope, never, void>
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Returns true if there is a previous navigation entry to navigate to.
|
|
56
|
-
*/
|
|
57
|
-
readonly canGoBack: Fx.Computed<never, never, boolean>
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Navigate to the previous navigation entry. If you're on the first entry
|
|
61
|
-
* then this will do nothing.
|
|
62
|
-
*/
|
|
63
|
-
readonly back: Effect.Effect<never, never, Destination>
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Returns true if there is a next navigation entry to navigate to after you have gone back.
|
|
67
|
-
*/
|
|
68
|
-
readonly canGoForward: Fx.Computed<never, never, boolean>
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Navigate to the next navigation entry. If you're on the last entry then
|
|
72
|
-
* this will do nothing.
|
|
73
|
-
*/
|
|
74
|
-
readonly forward: Effect.Effect<never, never, Destination>
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Reload the current navigation entry.
|
|
78
|
-
*/
|
|
79
|
-
readonly reload: Effect.Effect<never, never, Destination>
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Navigate to a specific navigation entry by key. If the key does not
|
|
83
|
-
* exist then this will do nothing visible to the user and return Option.none().
|
|
84
|
-
*/
|
|
85
|
-
readonly goTo: (key: DestinationKey) => Effect.Effect<never, never, Option<Destination>>
|
|
86
|
-
}
|
|
22
|
+
readonly currentEntry: Computed.Computed<never, never, Destination>
|
|
87
23
|
|
|
88
|
-
|
|
24
|
+
readonly entries: Computed.Computed<never, never, ReadonlyArray<Destination>>
|
|
89
25
|
|
|
90
|
-
|
|
91
|
-
Navigation.withEffect((n) => n.navigate(url, options))
|
|
26
|
+
readonly transition: Computed.Computed<never, never, Option.Option<Transition>>
|
|
92
27
|
|
|
93
|
-
|
|
94
|
-
handler: (event: NavigationEvent) => Effect.Effect<R, never, void>,
|
|
95
|
-
) => Navigation.withEffect((n) => n.onNavigation(handler))
|
|
28
|
+
readonly canGoBack: Computed.Computed<never, never, boolean>
|
|
96
29
|
|
|
97
|
-
|
|
98
|
-
Fx.Fx<Navigation, never, boolean> = Object.assign(
|
|
99
|
-
Navigation.withEffect((n) => n.canGoBack),
|
|
100
|
-
Navigation.withFx((n) => n.canGoBack),
|
|
101
|
-
)
|
|
30
|
+
readonly canGoForward: Computed.Computed<never, never, boolean>
|
|
102
31
|
|
|
103
|
-
|
|
32
|
+
readonly navigate: (
|
|
33
|
+
url: string | URL,
|
|
34
|
+
options?: NavigateOptions
|
|
35
|
+
) => Effect.Effect<never, NavigationError, Destination>
|
|
104
36
|
|
|
105
|
-
|
|
106
|
-
Fx.Fx<Navigation, never, boolean> = Object.assign(
|
|
107
|
-
Navigation.withEffect((n) => n.canGoForward),
|
|
108
|
-
Navigation.withFx((n) => n.canGoForward),
|
|
109
|
-
)
|
|
37
|
+
readonly back: (options?: { readonly info?: unknown }) => Effect.Effect<never, NavigationError, Destination>
|
|
110
38
|
|
|
111
|
-
|
|
39
|
+
readonly forward: (options?: { readonly info?: unknown }) => Effect.Effect<never, NavigationError, Destination>
|
|
112
40
|
|
|
113
|
-
|
|
41
|
+
readonly traverseTo: (
|
|
42
|
+
key: Destination["key"],
|
|
43
|
+
options?: { readonly info?: unknown }
|
|
44
|
+
) => Effect.Effect<never, NavigationError, Destination>
|
|
114
45
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// History type
|
|
119
|
-
readonly history?: 'push' | 'replace'
|
|
120
|
-
// Key to use for Navigation entry
|
|
121
|
-
readonly key?: string
|
|
122
|
-
}
|
|
46
|
+
readonly updateCurrentEntry: (
|
|
47
|
+
options: { readonly state: unknown }
|
|
48
|
+
) => Effect.Effect<never, NavigationError, Destination>
|
|
123
49
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
readonly navigationType: NavigationType
|
|
128
|
-
}
|
|
50
|
+
readonly reload: (
|
|
51
|
+
options?: { readonly info?: unknown; readonly state?: unknown }
|
|
52
|
+
) => Effect.Effect<never, NavigationError, Destination>
|
|
129
53
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
navigationType: NavigationType,
|
|
134
|
-
): NavigationEvent {
|
|
135
|
-
return { destination, hashChange, navigationType }
|
|
136
|
-
}
|
|
54
|
+
readonly beforeNavigation: <R = never, R2 = never>(
|
|
55
|
+
handler: BeforeNavigationHandler<R, R2>
|
|
56
|
+
) => Effect.Effect<R | R2 | Scope.Scope, never, unknown>
|
|
137
57
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
readonly state: unknown
|
|
58
|
+
readonly onNavigation: <R = never, R2 = never>(
|
|
59
|
+
handler: NavigationHandler<R, R2>
|
|
60
|
+
) => Effect.Effect<R | R2 | Scope.Scope, never, unknown>
|
|
142
61
|
}
|
|
143
62
|
|
|
144
|
-
|
|
145
|
-
|
|
63
|
+
/**
|
|
64
|
+
* @since 1.0.0
|
|
65
|
+
*/
|
|
66
|
+
export const Navigation: Tagged<Navigation> = Tagged<Navigation, Navigation>("@typed/navigation/Navigation")
|
|
67
|
+
|
|
68
|
+
const urlSchema_ = Schema.instanceOf(URL).pipe(Schema.equivalence((a, b) => a.href === b.href))
|
|
69
|
+
|
|
70
|
+
const urlSchema = Schema.string.pipe(
|
|
71
|
+
Schema.transformOrFail(
|
|
72
|
+
urlSchema_,
|
|
73
|
+
(s) =>
|
|
74
|
+
Effect.suspend(() => {
|
|
75
|
+
try {
|
|
76
|
+
return Effect.succeed(new URL(s))
|
|
77
|
+
} catch {
|
|
78
|
+
return Effect.fail(ParseResult.parseError([ParseResult.type(urlSchema_.ast, s, `Expected a URL`)]))
|
|
79
|
+
}
|
|
80
|
+
}),
|
|
81
|
+
(url) => Effect.succeed(url.toString())
|
|
82
|
+
)
|
|
83
|
+
)
|
|
146
84
|
|
|
147
|
-
|
|
148
|
-
|
|
85
|
+
/**
|
|
86
|
+
* @since 1.0.0
|
|
87
|
+
*/
|
|
88
|
+
export const Destination = Schema.struct({
|
|
89
|
+
id: IdSchema.uuid,
|
|
90
|
+
key: IdSchema.uuid,
|
|
91
|
+
url: urlSchema,
|
|
92
|
+
state: Schema.unknown,
|
|
93
|
+
sameDocument: Schema.boolean
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @since 1.0.0
|
|
98
|
+
*/
|
|
99
|
+
export type DestinationJson = Schema.Schema.From<typeof Destination>
|
|
100
|
+
/**
|
|
101
|
+
* @since 1.0.0
|
|
102
|
+
*/
|
|
103
|
+
export interface Destination extends Schema.Schema.To<typeof Destination> {}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @since 1.0.0
|
|
107
|
+
*/
|
|
108
|
+
export const ProposedDestination = Destination.pipe(Schema.omit("id", "key"))
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @since 1.0.0
|
|
112
|
+
*/
|
|
113
|
+
export type ProposedDestinationJson = Schema.Schema.From<typeof ProposedDestination>
|
|
114
|
+
/**
|
|
115
|
+
* @since 1.0.0
|
|
116
|
+
*/
|
|
117
|
+
export interface ProposedDestination extends Schema.Schema.To<typeof ProposedDestination> {}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @since 1.0.0
|
|
121
|
+
*/
|
|
122
|
+
export const NavigationType = Schema.literal("push", "replace", "reload", "traverse")
|
|
123
|
+
/**
|
|
124
|
+
* @since 1.0.0
|
|
125
|
+
*/
|
|
126
|
+
export type NavigationType = Schema.Schema.To<typeof NavigationType>
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @since 1.0.0
|
|
130
|
+
*/
|
|
131
|
+
export const Transition = Schema.struct({
|
|
132
|
+
type: NavigationType,
|
|
133
|
+
from: Destination,
|
|
134
|
+
to: Schema.union(ProposedDestination, Destination)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @since 1.0.0
|
|
139
|
+
*/
|
|
140
|
+
export type TransitionJson = Schema.Schema.From<typeof Transition>
|
|
141
|
+
/**
|
|
142
|
+
* @since 1.0.0
|
|
143
|
+
*/
|
|
144
|
+
export interface Transition extends Schema.Schema.To<typeof Transition> {}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @since 1.0.0
|
|
148
|
+
*/
|
|
149
|
+
export const BeforeNavigationEvent = Schema.struct({
|
|
150
|
+
type: NavigationType,
|
|
151
|
+
from: Destination,
|
|
152
|
+
delta: Schema.number,
|
|
153
|
+
to: Schema.union(ProposedDestination, Destination),
|
|
154
|
+
info: Schema.unknown
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @since 1.0.0
|
|
159
|
+
*/
|
|
160
|
+
export type BeforeNavigationEventJson = Schema.Schema.From<typeof BeforeNavigationEvent>
|
|
161
|
+
/**
|
|
162
|
+
* @since 1.0.0
|
|
163
|
+
*/
|
|
164
|
+
export interface BeforeNavigationEvent extends Schema.Schema.To<typeof BeforeNavigationEvent> {}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @since 1.0.0
|
|
168
|
+
*/
|
|
169
|
+
export const NavigationEvent = Schema.struct({
|
|
170
|
+
type: NavigationType,
|
|
171
|
+
destination: Destination,
|
|
172
|
+
info: Schema.unknown
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @since 1.0.0
|
|
177
|
+
*/
|
|
178
|
+
export type NavigationEventJson = Schema.Schema.From<typeof NavigationEvent>
|
|
179
|
+
/**
|
|
180
|
+
* @since 1.0.0
|
|
181
|
+
*/
|
|
182
|
+
export interface NavigationEvent extends Schema.Schema.To<typeof NavigationEvent> {}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @since 1.0.0
|
|
186
|
+
*/
|
|
187
|
+
export type BeforeNavigationHandler<R, R2> = (
|
|
188
|
+
event: BeforeNavigationEvent
|
|
189
|
+
) => Effect.Effect<
|
|
190
|
+
R,
|
|
191
|
+
RedirectError | CancelNavigation,
|
|
192
|
+
Option.Option<
|
|
193
|
+
Effect.Effect<R2, RedirectError | CancelNavigation, unknown>
|
|
194
|
+
>
|
|
195
|
+
>
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @since 1.0.0
|
|
199
|
+
*/
|
|
200
|
+
export type NavigationHandler<R, R2> = (
|
|
201
|
+
event: NavigationEvent
|
|
202
|
+
) => Effect.Effect<
|
|
203
|
+
R,
|
|
204
|
+
never,
|
|
205
|
+
Option.Option<
|
|
206
|
+
Effect.Effect<R2, never, unknown>
|
|
207
|
+
>
|
|
208
|
+
>
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @since 1.0.0
|
|
212
|
+
*/
|
|
213
|
+
export class NavigationError extends Data.TaggedError("NavigationError")<{ readonly error: unknown }> {}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @since 1.0.0
|
|
217
|
+
*/
|
|
218
|
+
export class RedirectError extends Data.TaggedError("RedirectError")<
|
|
219
|
+
{
|
|
220
|
+
readonly path: string | URL
|
|
221
|
+
readonly options?: { readonly state?: unknown; readonly info?: unknown } | undefined
|
|
222
|
+
}
|
|
223
|
+
> {}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* @since 1.0.0
|
|
227
|
+
*/
|
|
228
|
+
export class CancelNavigation extends Data.TaggedError("CancelNavigation")<{}> {}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* @since 1.0.0
|
|
232
|
+
*/
|
|
233
|
+
export interface NavigateOptions {
|
|
234
|
+
readonly history?: "replace" | "push" | "auto"
|
|
235
|
+
readonly state?: unknown
|
|
236
|
+
readonly info?: unknown
|
|
149
237
|
}
|
|
150
238
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
239
|
+
/**
|
|
240
|
+
* @since 1.0.0
|
|
241
|
+
*/
|
|
242
|
+
export const cancelNavigation: CancelNavigation = new CancelNavigation()
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* @since 1.0.0
|
|
246
|
+
*/
|
|
247
|
+
export function redirectToPath(
|
|
248
|
+
path: string | URL,
|
|
249
|
+
options?: { readonly state?: unknown; readonly info?: unknown }
|
|
250
|
+
): RedirectError {
|
|
251
|
+
return new RedirectError({ path, options })
|
|
157
252
|
}
|
|
158
253
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
254
|
+
/**
|
|
255
|
+
* @since 1.0.0
|
|
256
|
+
*/
|
|
257
|
+
export function isNavigationError(e: unknown): e is NavigationError {
|
|
258
|
+
return e instanceof NavigationError
|
|
163
259
|
}
|
|
164
260
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
261
|
+
/**
|
|
262
|
+
* @since 1.0.0
|
|
263
|
+
*/
|
|
264
|
+
export function isRedirectError(e: unknown): e is RedirectError {
|
|
265
|
+
return e instanceof RedirectError
|
|
169
266
|
}
|
|
170
267
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
268
|
+
/**
|
|
269
|
+
* @since 1.0.0
|
|
270
|
+
*/
|
|
271
|
+
export function isCancelNavigation(e: unknown): e is CancelNavigation {
|
|
272
|
+
return e instanceof CancelNavigation
|
|
174
273
|
}
|
|
175
274
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
275
|
+
/**
|
|
276
|
+
* @since 1.0.0
|
|
277
|
+
*/
|
|
278
|
+
export const navigate = (
|
|
279
|
+
url: string | URL,
|
|
280
|
+
options?: NavigateOptions
|
|
281
|
+
): Effect.Effect<Navigation, NavigationError, Destination> => Navigation.withEffect((n) => n.navigate(url, options))
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* @since 1.0.0
|
|
285
|
+
*/
|
|
286
|
+
export const back: (options?: { readonly info?: unknown }) => Effect.Effect<Navigation, NavigationError, Destination> =
|
|
287
|
+
(opts) => Navigation.withEffect((n) => n.back(opts))
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* @since 1.0.0
|
|
291
|
+
*/
|
|
292
|
+
export const forward: (
|
|
293
|
+
options?: { readonly info?: unknown }
|
|
294
|
+
) => Effect.Effect<Navigation, NavigationError, Destination> = (
|
|
295
|
+
opts
|
|
296
|
+
) => Navigation.withEffect((n) => n.forward(opts))
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* @since 1.0.0
|
|
300
|
+
*/
|
|
301
|
+
export const traverseTo: (
|
|
302
|
+
key: Uuid,
|
|
303
|
+
options?: { readonly info?: unknown }
|
|
304
|
+
) => Effect.Effect<Navigation, NavigationError, Destination> = (key, opts) =>
|
|
305
|
+
Navigation.withEffect((n) => n.traverseTo(key, opts))
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* @since 1.0.0
|
|
309
|
+
*/
|
|
310
|
+
export const updateCurrentEntry: (
|
|
311
|
+
options: { readonly state: unknown }
|
|
312
|
+
) => Effect.Effect<Navigation, NavigationError, Destination> = (opts) =>
|
|
313
|
+
Navigation.withEffect((n) => n.updateCurrentEntry(opts))
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* @since 1.0.0
|
|
317
|
+
*/
|
|
318
|
+
export const reload: (
|
|
319
|
+
options?: { readonly info?: unknown; readonly state?: unknown }
|
|
320
|
+
) => Effect.Effect<Navigation, NavigationError, Destination> = (
|
|
321
|
+
opts
|
|
322
|
+
) => Navigation.withEffect((n) => n.reload(opts))
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* @since 1.0.0
|
|
326
|
+
*/
|
|
327
|
+
export const CurrentEntry: Computed.Computed<Navigation, never, Destination> = Computed.fromTag(
|
|
328
|
+
Navigation,
|
|
329
|
+
(nav) => nav.currentEntry
|
|
330
|
+
)
|
|
181
331
|
|
|
182
|
-
|
|
183
|
-
|
|
332
|
+
/**
|
|
333
|
+
* @since 1.0.0
|
|
334
|
+
*/
|
|
335
|
+
export function getCurrentPathFromUrl(location: Pick<URL, "pathname" | "search" | "hash">): string {
|
|
336
|
+
return location.pathname + location.search + location.hash
|
|
184
337
|
}
|
|
185
338
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
339
|
+
/**
|
|
340
|
+
* @since 1.0.0
|
|
341
|
+
*/
|
|
342
|
+
export const CurrentPath: Computed.Computed<Navigation, never, string> = CurrentEntry.map((d) =>
|
|
343
|
+
getCurrentPathFromUrl(d.url)
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* @since 1.0.0
|
|
348
|
+
*/
|
|
349
|
+
export const CurrentEntries: Computed.Computed<Navigation, never, ReadonlyArray<Destination>> = Computed.fromTag(
|
|
350
|
+
Navigation,
|
|
351
|
+
(n) => n.entries
|
|
352
|
+
)
|
|
189
353
|
|
|
190
|
-
|
|
191
|
-
|
|
354
|
+
/**
|
|
355
|
+
* @since 1.0.0
|
|
356
|
+
*/
|
|
357
|
+
export const CanGoForward: Computed.Computed<Navigation, never, boolean> = Computed.fromTag(
|
|
358
|
+
Navigation,
|
|
359
|
+
(n) => n.canGoForward
|
|
192
360
|
)
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* @since 1.0.0
|
|
364
|
+
*/
|
|
365
|
+
export const CanGoBack: Computed.Computed<Navigation, never, boolean> = Computed.fromTag(
|
|
366
|
+
Navigation,
|
|
367
|
+
(n) => n.canGoBack
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* @since 1.0.0
|
|
372
|
+
*/
|
|
373
|
+
export function handleRedirect(error: RedirectError) {
|
|
374
|
+
return navigate(error.path, error.options)
|
|
375
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Re-exports of other modules
|
|
3
|
+
* @since 1.0.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @since 1.0.0
|
|
8
|
+
*/
|
|
9
|
+
export * from "./Blocking"
|
|
10
|
+
/**
|
|
11
|
+
* @since 1.0.0
|
|
12
|
+
*/
|
|
13
|
+
export * from "./Layer"
|
|
14
|
+
/**
|
|
15
|
+
* @since 1.0.0
|
|
16
|
+
*/
|
|
17
|
+
export * from "./Navigation"
|