@typed/navigation 0.18.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nvmrc +1 -0
- package/biome.json +39 -0
- package/dist/Blocking.d.ts +23 -0
- package/dist/Blocking.js +41 -0
- package/dist/Blocking.js.map +1 -0
- package/dist/Destination.d.ts +11 -0
- package/dist/Destination.js +10 -0
- package/dist/Destination.js.map +1 -0
- package/dist/Error.d.ts +33 -0
- package/dist/Error.js +22 -0
- package/dist/Error.js.map +1 -0
- package/dist/Event.d.ts +45 -0
- package/dist/Event.js +17 -0
- package/dist/Event.js.map +1 -0
- package/dist/Forms.d.ts +79 -0
- package/dist/Forms.js +111 -0
- package/dist/Forms.js.map +1 -0
- package/dist/Handler.d.ts +6 -0
- package/dist/Handler.js +2 -0
- package/dist/Handler.js.map +1 -0
- package/dist/{dts/Layer.d.ts → Layer.d.ts} +11 -8
- package/dist/{esm/Layer.js → Layer.js} +2 -2
- package/dist/Layer.js.map +1 -0
- package/dist/NavigateOptions.d.ts +7 -0
- package/dist/NavigateOptions.js +7 -0
- package/dist/NavigateOptions.js.map +1 -0
- package/dist/Navigation.d.ts +79 -0
- package/dist/Navigation.js +49 -0
- package/dist/Navigation.js.map +1 -0
- package/dist/NavigationType.d.ts +3 -0
- package/dist/NavigationType.js +3 -0
- package/dist/NavigationType.js.map +1 -0
- package/dist/ProposedDestination.d.ts +13 -0
- package/dist/ProposedDestination.js +4 -0
- package/dist/ProposedDestination.js.map +1 -0
- package/dist/Url.d.ts +13 -0
- package/dist/Url.js +72 -0
- package/dist/Url.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/fromWindow.d.ts +4 -0
- package/dist/{esm/internal → internal}/fromWindow.js +125 -136
- package/dist/internal/fromWindow.js.map +1 -0
- package/dist/internal/memory.d.ts +6 -0
- package/dist/internal/memory.js +59 -0
- package/dist/internal/memory.js.map +1 -0
- package/dist/{dts/internal → internal}/shared.d.ts +44 -46
- package/dist/{esm/internal → internal}/shared.js +121 -168
- package/dist/internal/shared.js.map +1 -0
- package/package.json +35 -53
- package/readme.md +243 -0
- package/src/Blocking.ts +65 -65
- package/src/Destination.ts +14 -0
- package/src/Error.ts +28 -0
- package/src/Event.ts +26 -0
- package/src/Forms.ts +216 -0
- package/src/Handler.ts +16 -0
- package/src/Layer.ts +20 -9
- package/src/NavigateOptions.ts +9 -0
- package/src/Navigation.test.ts +697 -0
- package/src/Navigation.ts +135 -472
- package/src/NavigationType.ts +5 -0
- package/src/ProposedDestination.ts +8 -0
- package/src/Url.ts +106 -0
- package/src/index.ts +12 -17
- package/src/internal/fromWindow.ts +163 -234
- package/src/internal/memory.ts +62 -49
- package/src/internal/shared.ts +218 -377
- package/tsconfig.json +30 -0
- package/Blocking/package.json +0 -6
- package/LICENSE +0 -21
- package/Layer/package.json +0 -6
- package/Navigation/package.json +0 -6
- package/README.md +0 -5
- package/dist/cjs/Blocking.js +0 -58
- package/dist/cjs/Blocking.js.map +0 -1
- package/dist/cjs/Layer.js +0 -27
- package/dist/cjs/Layer.js.map +0 -1
- package/dist/cjs/Navigation.js +0 -278
- package/dist/cjs/Navigation.js.map +0 -1
- package/dist/cjs/index.js +0 -39
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/internal/fromWindow.js +0 -436
- package/dist/cjs/internal/fromWindow.js.map +0 -1
- package/dist/cjs/internal/memory.js +0 -72
- package/dist/cjs/internal/memory.js.map +0 -1
- package/dist/cjs/internal/shared.js +0 -525
- package/dist/cjs/internal/shared.js.map +0 -1
- package/dist/dts/Blocking.d.ts +0 -34
- package/dist/dts/Blocking.d.ts.map +0 -1
- package/dist/dts/Layer.d.ts.map +0 -1
- package/dist/dts/Navigation.d.ts +0 -451
- package/dist/dts/Navigation.d.ts.map +0 -1
- package/dist/dts/index.d.ts +0 -17
- package/dist/dts/index.d.ts.map +0 -1
- package/dist/dts/internal/fromWindow.d.ts +0 -12
- package/dist/dts/internal/fromWindow.d.ts.map +0 -1
- package/dist/dts/internal/memory.d.ts +0 -6
- package/dist/dts/internal/memory.d.ts.map +0 -1
- package/dist/dts/internal/shared.d.ts.map +0 -1
- package/dist/esm/Blocking.js +0 -46
- package/dist/esm/Blocking.js.map +0 -1
- package/dist/esm/Layer.js.map +0 -1
- package/dist/esm/Navigation.js +0 -238
- package/dist/esm/Navigation.js.map +0 -1
- package/dist/esm/index.js +0 -17
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/internal/fromWindow.js.map +0 -1
- package/dist/esm/internal/memory.js +0 -56
- package/dist/esm/internal/memory.js.map +0 -1
- package/dist/esm/internal/shared.js.map +0 -1
- package/dist/esm/package.json +0 -4
package/src/Navigation.ts
CHANGED
|
@@ -1,534 +1,197 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import type * as
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import type {
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
import * as Effect from "effect/Effect"
|
|
16
|
-
import type * as Option from "effect/Option"
|
|
17
|
-
import type * as Scope from "effect/Scope"
|
|
18
|
-
import type { Simplify } from "effect/Types"
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @since 1.0.0
|
|
22
|
-
*/
|
|
1
|
+
import type { HttpClientResponse } from '@effect/platform'
|
|
2
|
+
import type { HttpClient } from '@effect/platform/HttpClient'
|
|
3
|
+
import * as LazyRef from '@typed/lazy-ref'
|
|
4
|
+
import * as Context from 'effect/Context'
|
|
5
|
+
import * as Effect from 'effect/Effect'
|
|
6
|
+
import type * as Option from 'effect/Option'
|
|
7
|
+
import type * as Scope from 'effect/Scope'
|
|
8
|
+
import type { Destination } from './Destination.js'
|
|
9
|
+
import { CancelNavigation, type FormSubmitError, NavigationError, RedirectError } from './Error.js'
|
|
10
|
+
import type { TransitionEvent } from './Event.js'
|
|
11
|
+
import type { FormSubmit } from './Forms.js'
|
|
12
|
+
import type { BeforeNavigationHandler, NavigationHandler } from './Handler.js'
|
|
13
|
+
import type { NavigateOptions } from './NavigateOptions.js'
|
|
14
|
+
|
|
23
15
|
export interface Navigation {
|
|
24
16
|
readonly origin: string
|
|
25
17
|
|
|
26
18
|
readonly base: string
|
|
27
19
|
|
|
28
|
-
readonly currentEntry:
|
|
20
|
+
readonly currentEntry: LazyRef.Computed<Destination>
|
|
29
21
|
|
|
30
|
-
readonly entries:
|
|
22
|
+
readonly entries: LazyRef.Computed<ReadonlyArray<Destination>>
|
|
31
23
|
|
|
32
|
-
readonly transition:
|
|
24
|
+
readonly transition: LazyRef.Computed<Option.Option<TransitionEvent>>
|
|
33
25
|
|
|
34
|
-
readonly canGoBack:
|
|
26
|
+
readonly canGoBack: LazyRef.Computed<boolean>
|
|
35
27
|
|
|
36
|
-
readonly canGoForward:
|
|
28
|
+
readonly canGoForward: LazyRef.Computed<boolean>
|
|
37
29
|
|
|
38
30
|
readonly navigate: (
|
|
39
31
|
url: string | URL,
|
|
40
|
-
options?: NavigateOptions
|
|
32
|
+
options?: NavigateOptions,
|
|
41
33
|
) => Effect.Effect<Destination, NavigationError>
|
|
42
34
|
|
|
43
|
-
readonly back: (options?: { readonly info?: unknown }) => Effect.Effect<
|
|
35
|
+
readonly back: (options?: { readonly info?: unknown }) => Effect.Effect<
|
|
36
|
+
Destination,
|
|
37
|
+
NavigationError
|
|
38
|
+
>
|
|
44
39
|
|
|
45
|
-
readonly forward: (options?: { readonly info?: unknown }) => Effect.Effect<
|
|
40
|
+
readonly forward: (options?: { readonly info?: unknown }) => Effect.Effect<
|
|
41
|
+
Destination,
|
|
42
|
+
NavigationError
|
|
43
|
+
>
|
|
46
44
|
|
|
47
45
|
readonly traverseTo: (
|
|
48
|
-
key: Destination[
|
|
49
|
-
options?: { readonly info?: unknown }
|
|
46
|
+
key: Destination['key'],
|
|
47
|
+
options?: { readonly info?: unknown },
|
|
50
48
|
) => Effect.Effect<Destination, NavigationError>
|
|
51
49
|
|
|
52
|
-
readonly updateCurrentEntry: (
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
readonly updateCurrentEntry: (options: { readonly state: unknown }) => Effect.Effect<
|
|
51
|
+
Destination,
|
|
52
|
+
NavigationError
|
|
53
|
+
>
|
|
55
54
|
|
|
56
|
-
readonly reload: (
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
readonly reload: (options?: {
|
|
56
|
+
readonly info?: unknown
|
|
57
|
+
readonly state?: unknown
|
|
58
|
+
}) => Effect.Effect<Destination, NavigationError>
|
|
59
59
|
|
|
60
60
|
readonly beforeNavigation: <R = never, R2 = never>(
|
|
61
|
-
handler: BeforeNavigationHandler<R, R2
|
|
61
|
+
handler: BeforeNavigationHandler<R, R2>,
|
|
62
62
|
) => Effect.Effect<void, never, R | R2 | Scope.Scope>
|
|
63
63
|
|
|
64
64
|
readonly onNavigation: <R = never, R2 = never>(
|
|
65
|
-
handler: NavigationHandler<R, R2
|
|
65
|
+
handler: NavigationHandler<R, R2>,
|
|
66
66
|
) => Effect.Effect<void, never, R | R2 | Scope.Scope>
|
|
67
67
|
|
|
68
68
|
readonly submit: (
|
|
69
|
-
|
|
70
|
-
formInput?: Simplify<Omit<FormInputFrom, "data">>
|
|
69
|
+
form: FormSubmit,
|
|
71
70
|
) => Effect.Effect<
|
|
72
|
-
|
|
73
|
-
NavigationError |
|
|
74
|
-
|
|
71
|
+
readonly [Destination, HttpClientResponse.HttpClientResponse],
|
|
72
|
+
NavigationError | FormSubmitError,
|
|
73
|
+
Navigation | HttpClient | Scope.Scope
|
|
75
74
|
>
|
|
76
|
-
|
|
77
|
-
readonly onFormData: <R = never, R2 = never>(
|
|
78
|
-
handler: FormDataHandler<R, R2>
|
|
79
|
-
) => Effect.Effect<void, never, R | R2 | Scope.Scope>
|
|
80
75
|
}
|
|
81
76
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const urlSchema_ = Schema.instanceOf(URL).pipe(Equivalence.equivalence(() => (a, b) => a.href === b.href))
|
|
88
|
-
|
|
89
|
-
const urlSchema = Schema.String.pipe(
|
|
90
|
-
Schema.transformOrFail(
|
|
91
|
-
urlSchema_,
|
|
92
|
-
{
|
|
93
|
-
decode: (s) =>
|
|
94
|
-
Effect.suspend(() => {
|
|
95
|
-
try {
|
|
96
|
-
return Effect.succeed(new URL(s))
|
|
97
|
-
} catch {
|
|
98
|
-
return Effect.fail(new ParseResult.Type(urlSchema_.ast, s, `Expected a URL`))
|
|
99
|
-
}
|
|
100
|
-
}),
|
|
101
|
-
encode: (url) => Effect.succeed(url.toString())
|
|
102
|
-
}
|
|
103
|
-
)
|
|
104
|
-
)
|
|
77
|
+
export const Navigation = Context.GenericTag<Navigation>('@typed/Navigation')
|
|
78
|
+
|
|
79
|
+
export const CurrentEntry: LazyRef.Computed<Destination, never, Navigation> =
|
|
80
|
+
LazyRef.computedFromTag(Navigation, (nav) => nav.currentEntry)
|
|
105
81
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
*/
|
|
109
|
-
export const Destination = Schema.Struct({
|
|
110
|
-
id: IdSchema.uuid,
|
|
111
|
-
key: IdSchema.uuid,
|
|
112
|
-
url: urlSchema,
|
|
113
|
-
state: Schema.Unknown,
|
|
114
|
-
sameDocument: Schema.Boolean
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* @since 1.0.0
|
|
119
|
-
*/
|
|
120
|
-
export type DestinationJson = Schema.Schema.Encoded<typeof Destination>
|
|
121
|
-
/**
|
|
122
|
-
* @since 1.0.0
|
|
123
|
-
*/
|
|
124
|
-
export interface Destination extends Schema.Schema.Type<typeof Destination> {}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* @since 1.0.0
|
|
128
|
-
*/
|
|
129
|
-
export const ProposedDestination = Destination.pipe(Schema.omit("id", "key"))
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* @since 1.0.0
|
|
133
|
-
*/
|
|
134
|
-
export type ProposedDestinationJson = Schema.Schema.Encoded<typeof ProposedDestination>
|
|
135
|
-
/**
|
|
136
|
-
* @since 1.0.0
|
|
137
|
-
*/
|
|
138
|
-
export interface ProposedDestination extends Schema.Schema.Type<typeof ProposedDestination> {}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @since 1.0.0
|
|
142
|
-
*/
|
|
143
|
-
export const NavigationType = Schema.Literal("push", "replace", "reload", "traverse")
|
|
144
|
-
/**
|
|
145
|
-
* @since 1.0.0
|
|
146
|
-
*/
|
|
147
|
-
export type NavigationType = Schema.Schema.Type<typeof NavigationType>
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* @since 1.0.0
|
|
151
|
-
*/
|
|
152
|
-
export const Transition = Schema.Struct({
|
|
153
|
-
type: NavigationType,
|
|
154
|
-
from: Destination,
|
|
155
|
-
to: Schema.Union(ProposedDestination, Destination)
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* @since 1.0.0
|
|
160
|
-
*/
|
|
161
|
-
export type TransitionJson = Schema.Schema.Encoded<typeof Transition>
|
|
162
|
-
/**
|
|
163
|
-
* @since 1.0.0
|
|
164
|
-
*/
|
|
165
|
-
export interface Transition extends Schema.Schema.Type<typeof Transition> {}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* @since 1.0.0
|
|
169
|
-
*/
|
|
170
|
-
export const BeforeNavigationEvent = Schema.Struct({
|
|
171
|
-
type: NavigationType,
|
|
172
|
-
from: Destination,
|
|
173
|
-
delta: Schema.Number,
|
|
174
|
-
to: Schema.Union(ProposedDestination, Destination),
|
|
175
|
-
info: Schema.Unknown
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* @since 1.0.0
|
|
180
|
-
*/
|
|
181
|
-
export type BeforeNavigationEventJson = Schema.Schema.Encoded<typeof BeforeNavigationEvent>
|
|
182
|
-
/**
|
|
183
|
-
* @since 1.0.0
|
|
184
|
-
*/
|
|
185
|
-
export interface BeforeNavigationEvent extends Schema.Schema.Type<typeof BeforeNavigationEvent> {}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* @since 1.0.0
|
|
189
|
-
*/
|
|
190
|
-
export const NavigationEvent = Schema.Struct({
|
|
191
|
-
type: NavigationType,
|
|
192
|
-
destination: Destination,
|
|
193
|
-
info: Schema.Unknown
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* @since 1.0.0
|
|
198
|
-
*/
|
|
199
|
-
export type NavigationEventJson = Schema.Schema.Encoded<typeof NavigationEvent>
|
|
200
|
-
/**
|
|
201
|
-
* @since 1.0.0
|
|
202
|
-
*/
|
|
203
|
-
export interface NavigationEvent extends Schema.Schema.Type<typeof NavigationEvent> {}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* @since 1.0.0
|
|
207
|
-
*/
|
|
208
|
-
export type BeforeNavigationHandler<R, R2> = (
|
|
209
|
-
event: BeforeNavigationEvent
|
|
210
|
-
) => Effect.Effect<
|
|
211
|
-
Option.Option<
|
|
212
|
-
Effect.Effect<unknown, RedirectError | CancelNavigation, R2>
|
|
213
|
-
>,
|
|
214
|
-
RedirectError | CancelNavigation,
|
|
215
|
-
R
|
|
216
|
-
>
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* @since 1.0.0
|
|
220
|
-
*/
|
|
221
|
-
export type NavigationHandler<R, R2> = (
|
|
222
|
-
event: NavigationEvent
|
|
223
|
-
) => Effect.Effect<
|
|
224
|
-
Option.Option<
|
|
225
|
-
Effect.Effect<unknown, never, R2>
|
|
226
|
-
>,
|
|
82
|
+
export const Entries: LazyRef.Computed<
|
|
83
|
+
ReadonlyArray<Destination>,
|
|
227
84
|
never,
|
|
228
|
-
|
|
229
|
-
>
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
*/
|
|
234
|
-
export type FormDataHandler<R, R2> = (
|
|
235
|
-
event: FormDataEvent
|
|
236
|
-
) => Effect.Effect<
|
|
237
|
-
Option.Option<
|
|
238
|
-
Effect.Effect<Option.Option<HttpClientResponse.HttpClientResponse>, RedirectError | CancelNavigation, R2>
|
|
239
|
-
>,
|
|
240
|
-
RedirectError | CancelNavigation,
|
|
241
|
-
R
|
|
242
|
-
>
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* @since 1.0.0
|
|
246
|
-
*/
|
|
247
|
-
export class NavigationError extends Data.TaggedError("NavigationError")<{ readonly error: unknown }> {}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* @since 1.0.0
|
|
251
|
-
*/
|
|
252
|
-
export class RedirectError extends Data.TaggedError("RedirectError")<
|
|
253
|
-
{
|
|
254
|
-
readonly path: string | URL
|
|
255
|
-
readonly options?: { readonly state?: unknown; readonly info?: unknown } | undefined
|
|
256
|
-
}
|
|
257
|
-
> {}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* @since 1.0.0
|
|
261
|
-
*/
|
|
262
|
-
export class CancelNavigation extends Data.TaggedError("CancelNavigation")<{}> {}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* @since 1.0.0
|
|
266
|
-
*/
|
|
267
|
-
export interface NavigateOptions {
|
|
268
|
-
readonly history?: "replace" | "push" | "auto"
|
|
269
|
-
readonly state?: unknown
|
|
270
|
-
readonly info?: unknown
|
|
85
|
+
Navigation
|
|
86
|
+
> = LazyRef.computedFromTag(Navigation, (nav) => nav.entries)
|
|
87
|
+
|
|
88
|
+
export function getCurrentPathFromUrl(location: Pick<URL, 'pathname' | 'search' | 'hash'>): string {
|
|
89
|
+
return location.pathname + location.search + location.hash
|
|
271
90
|
}
|
|
272
91
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
export const FileSchemaFrom = Schema.Struct({
|
|
277
|
-
_id: Schema.Literal("File"),
|
|
278
|
-
name: Schema.String,
|
|
279
|
-
data: Schema.String // Base64 encoded
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* @since 1.0.0
|
|
284
|
-
*/
|
|
285
|
-
export type FileSchemaFrom = Schema.Schema.Encoded<typeof FileSchemaFrom>
|
|
286
|
-
|
|
287
|
-
const decodeBase64 = ParseResult.decode(Schema.Uint8ArrayFromBase64Url)
|
|
288
|
-
const encodeBase64 = ParseResult.encode(Schema.Uint8ArrayFromBase64Url)
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* @since 1.0.0
|
|
292
|
-
*/
|
|
293
|
-
export const FileSchema = FileSchemaFrom.pipe(
|
|
294
|
-
Schema.transformOrFail(
|
|
295
|
-
Schema.instanceOf(File),
|
|
296
|
-
{
|
|
297
|
-
decode: ({ data, name }) => Effect.map(decodeBase64(data), (buffer) => new File([buffer], name)),
|
|
298
|
-
encode: (file) =>
|
|
299
|
-
Effect.promise(() => file.arrayBuffer()).pipe(
|
|
300
|
-
Effect.flatMap((buffer) => encodeBase64(new Uint8Array(buffer))),
|
|
301
|
-
Effect.map((data): FileSchemaFrom => ({ _id: "File", name: file.name, data }))
|
|
302
|
-
)
|
|
303
|
-
}
|
|
304
|
-
)
|
|
92
|
+
export const CurrentPath: LazyRef.Computed<string, never, Navigation> = LazyRef.computedFromTag(
|
|
93
|
+
Navigation,
|
|
94
|
+
(nav) => LazyRef.map(nav.currentEntry, (e) => getCurrentPathFromUrl(e.url)),
|
|
305
95
|
)
|
|
306
96
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
export
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* @since 1.0.0
|
|
368
|
-
*/
|
|
369
|
-
export interface FormDataEvent extends Schema.Schema.Type<typeof FormDataEvent> {}
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* @since 1.0.0
|
|
373
|
-
*/
|
|
374
|
-
export const cancelNavigation: CancelNavigation = new CancelNavigation()
|
|
375
|
-
|
|
376
|
-
/**
|
|
377
|
-
* @since 1.0.0
|
|
378
|
-
*/
|
|
97
|
+
export const CanGoForward: LazyRef.Computed<boolean, never, Navigation> = LazyRef.computedFromTag(
|
|
98
|
+
Navigation,
|
|
99
|
+
(nav) => nav.canGoForward,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
export const CanGoBack: LazyRef.Computed<boolean, never, Navigation> = LazyRef.computedFromTag(
|
|
103
|
+
Navigation,
|
|
104
|
+
(nav) => nav.canGoBack,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
export const navigate = (
|
|
108
|
+
url: string | URL,
|
|
109
|
+
options?: NavigateOptions,
|
|
110
|
+
): Effect.Effect<Destination, NavigationError, Navigation> =>
|
|
111
|
+
Effect.flatMap(Navigation, (nav) => nav.navigate(url, options))
|
|
112
|
+
|
|
113
|
+
export const back: (options?: { readonly info?: unknown }) => Effect.Effect<
|
|
114
|
+
Destination,
|
|
115
|
+
NavigationError,
|
|
116
|
+
Navigation
|
|
117
|
+
> = (opts) => Effect.flatMap(Navigation, (nav) => nav.back(opts))
|
|
118
|
+
|
|
119
|
+
export const forward: (options?: { readonly info?: unknown }) => Effect.Effect<
|
|
120
|
+
Destination,
|
|
121
|
+
NavigationError,
|
|
122
|
+
Navigation
|
|
123
|
+
> = (opts) => Effect.flatMap(Navigation, (nav) => nav.forward(opts))
|
|
124
|
+
|
|
125
|
+
export const traverseTo: (
|
|
126
|
+
key: string,
|
|
127
|
+
options?: { readonly info?: unknown },
|
|
128
|
+
) => Effect.Effect<Destination, NavigationError, Navigation> = (key, opts) =>
|
|
129
|
+
Effect.flatMap(Navigation, (nav) => nav.traverseTo(key, opts))
|
|
130
|
+
|
|
131
|
+
export const updateCurrentEntry: (options: { readonly state: unknown }) => Effect.Effect<
|
|
132
|
+
Destination,
|
|
133
|
+
NavigationError,
|
|
134
|
+
Navigation
|
|
135
|
+
> = (opts) => Effect.flatMap(Navigation, (nav) => nav.updateCurrentEntry(opts))
|
|
136
|
+
|
|
137
|
+
export const reload: (options?: {
|
|
138
|
+
readonly info?: unknown
|
|
139
|
+
readonly state?: unknown
|
|
140
|
+
}) => Effect.Effect<Destination, NavigationError, Navigation> = (opts) =>
|
|
141
|
+
Effect.flatMap(Navigation, (nav) => nav.reload(opts))
|
|
142
|
+
|
|
143
|
+
export const Transition: LazyRef.Computed<
|
|
144
|
+
Option.Option<TransitionEvent>,
|
|
145
|
+
never,
|
|
146
|
+
Navigation
|
|
147
|
+
> = LazyRef.computedFromTag(Navigation, (nav) => nav.transition)
|
|
148
|
+
|
|
149
|
+
export function handleRedirect(error: RedirectError) {
|
|
150
|
+
return navigate(error.path, {
|
|
151
|
+
history: 'replace',
|
|
152
|
+
...error.options,
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
|
|
379
156
|
export function redirectToPath(
|
|
380
157
|
path: string | URL,
|
|
381
|
-
options?: { readonly state?: unknown; readonly info?: unknown }
|
|
158
|
+
options?: { readonly state?: unknown; readonly info?: unknown },
|
|
382
159
|
): RedirectError {
|
|
383
160
|
return new RedirectError({ path, options })
|
|
384
161
|
}
|
|
385
162
|
|
|
386
|
-
/**
|
|
387
|
-
* @since 1.0.0
|
|
388
|
-
*/
|
|
389
163
|
export function isNavigationError(e: unknown): e is NavigationError {
|
|
390
|
-
return e
|
|
164
|
+
return NavigationError.is(e)
|
|
391
165
|
}
|
|
392
166
|
|
|
393
|
-
/**
|
|
394
|
-
* @since 1.0.0
|
|
395
|
-
*/
|
|
396
167
|
export function isRedirectError(e: unknown): e is RedirectError {
|
|
397
|
-
return e
|
|
168
|
+
return RedirectError.is(e)
|
|
398
169
|
}
|
|
399
170
|
|
|
400
|
-
/**
|
|
401
|
-
* @since 1.0.0
|
|
402
|
-
*/
|
|
403
171
|
export function isCancelNavigation(e: unknown): e is CancelNavigation {
|
|
404
|
-
return e
|
|
172
|
+
return CancelNavigation.is(e)
|
|
405
173
|
}
|
|
406
174
|
|
|
407
|
-
|
|
408
|
-
* @since 1.0.0
|
|
409
|
-
*/
|
|
410
|
-
export const navigate = (
|
|
411
|
-
url: string | URL,
|
|
412
|
-
options?: NavigateOptions
|
|
413
|
-
): Effect.Effect<Destination, NavigationError, Navigation> => Navigation.withEffect((n) => n.navigate(url, options))
|
|
414
|
-
|
|
415
|
-
/**
|
|
416
|
-
* @since 1.0.0
|
|
417
|
-
*/
|
|
418
|
-
export const back: (options?: { readonly info?: unknown }) => Effect.Effect<Destination, NavigationError, Navigation> =
|
|
419
|
-
(opts) => Navigation.withEffect((n) => n.back(opts))
|
|
420
|
-
|
|
421
|
-
/**
|
|
422
|
-
* @since 1.0.0
|
|
423
|
-
*/
|
|
424
|
-
export const forward: (
|
|
425
|
-
options?: { readonly info?: unknown }
|
|
426
|
-
) => Effect.Effect<Destination, NavigationError, Navigation> = (
|
|
427
|
-
opts
|
|
428
|
-
) => Navigation.withEffect((n) => n.forward(opts))
|
|
429
|
-
|
|
430
|
-
/**
|
|
431
|
-
* @since 1.0.0
|
|
432
|
-
*/
|
|
433
|
-
export const traverseTo: (
|
|
434
|
-
key: Uuid,
|
|
435
|
-
options?: { readonly info?: unknown }
|
|
436
|
-
) => Effect.Effect<Destination, NavigationError, Navigation> = (key, opts) =>
|
|
437
|
-
Navigation.withEffect((n) => n.traverseTo(key, opts))
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* @since 1.0.0
|
|
441
|
-
*/
|
|
442
|
-
export const updateCurrentEntry: (
|
|
443
|
-
options: { readonly state: unknown }
|
|
444
|
-
) => Effect.Effect<Destination, NavigationError, Navigation> = (opts) =>
|
|
445
|
-
Navigation.withEffect((n) => n.updateCurrentEntry(opts))
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* @since 1.0.0
|
|
449
|
-
*/
|
|
450
|
-
export const reload: (
|
|
451
|
-
options?: { readonly info?: unknown; readonly state?: unknown }
|
|
452
|
-
) => Effect.Effect<Destination, NavigationError, Navigation> = (
|
|
453
|
-
opts
|
|
454
|
-
) => Navigation.withEffect((n) => n.reload(opts))
|
|
455
|
-
|
|
456
|
-
/**
|
|
457
|
-
* @since 1.0.0
|
|
458
|
-
*/
|
|
459
|
-
export const CurrentEntry: RefSubject.Computed<Destination, never, Navigation> = RefSubject.computedFromTag(
|
|
460
|
-
Navigation,
|
|
461
|
-
(nav) => nav.currentEntry
|
|
462
|
-
)
|
|
175
|
+
export const cancelNavigation = Effect.suspend(() => new CancelNavigation())
|
|
463
176
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
return location.pathname + location.search + location.hash
|
|
177
|
+
export function beforeNavigation<R = never, R2 = never>(
|
|
178
|
+
handler: BeforeNavigationHandler<R, R2>,
|
|
179
|
+
): Effect.Effect<void, never, Navigation | R | R2 | Scope.Scope> {
|
|
180
|
+
return Effect.flatMap(Navigation, (nav) => nav.beforeNavigation(handler))
|
|
469
181
|
}
|
|
470
182
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
Navigation,
|
|
476
|
-
(nav) => RefSubject.map(nav.currentEntry, (e) => getCurrentPathFromUrl(e.url))
|
|
477
|
-
)
|
|
478
|
-
/**
|
|
479
|
-
* @since 1.0.0
|
|
480
|
-
*/
|
|
481
|
-
export const CurrentEntries: RefSubject.Computed<ReadonlyArray<Destination>, never, Navigation> = RefSubject
|
|
482
|
-
.computedFromTag(
|
|
483
|
-
Navigation,
|
|
484
|
-
(n) => n.entries
|
|
485
|
-
)
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
* @since 1.0.0
|
|
489
|
-
*/
|
|
490
|
-
export const CanGoForward: RefSubject.Computed<boolean, never, Navigation> = RefSubject.computedFromTag(
|
|
491
|
-
Navigation,
|
|
492
|
-
(n) => n.canGoForward
|
|
493
|
-
)
|
|
494
|
-
|
|
495
|
-
/**
|
|
496
|
-
* @since 1.0.0
|
|
497
|
-
*/
|
|
498
|
-
export const CanGoBack: RefSubject.Computed<boolean, never, Navigation> = RefSubject.computedFromTag(
|
|
499
|
-
Navigation,
|
|
500
|
-
(n) => n.canGoBack
|
|
501
|
-
)
|
|
502
|
-
|
|
503
|
-
/**
|
|
504
|
-
* @since 1.0.0
|
|
505
|
-
*/
|
|
506
|
-
export function handleRedirect(error: RedirectError) {
|
|
507
|
-
return navigate(error.path, {
|
|
508
|
-
history: "replace",
|
|
509
|
-
...error.options
|
|
510
|
-
})
|
|
183
|
+
export function onNavigation<R = never, R2 = never>(
|
|
184
|
+
handler: NavigationHandler<R, R2>,
|
|
185
|
+
): Effect.Effect<void, never, Navigation | R | R2 | Scope.Scope> {
|
|
186
|
+
return Effect.flatMap(Navigation, (nav) => nav.onNavigation(handler))
|
|
511
187
|
}
|
|
512
188
|
|
|
513
|
-
/**
|
|
514
|
-
* @since 1.0.0
|
|
515
|
-
*/
|
|
516
189
|
export function submit(
|
|
517
|
-
|
|
518
|
-
formInput?: Simplify<Omit<FormInputFrom, "data">>
|
|
190
|
+
form: FormSubmit,
|
|
519
191
|
): Effect.Effect<
|
|
520
|
-
|
|
521
|
-
NavigationError |
|
|
522
|
-
Navigation | HttpClient
|
|
192
|
+
readonly [Destination, HttpClientResponse.HttpClientResponse],
|
|
193
|
+
NavigationError | FormSubmitError,
|
|
194
|
+
Navigation | HttpClient | Scope.Scope
|
|
523
195
|
> {
|
|
524
|
-
return
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
/**
|
|
528
|
-
* @since 1.0.0
|
|
529
|
-
*/
|
|
530
|
-
export function onFormData<R = never, R2 = never>(
|
|
531
|
-
handler: FormDataHandler<R, R2>
|
|
532
|
-
): Effect.Effect<void, never, Navigation | R | R2 | Scope.Scope> {
|
|
533
|
-
return Navigation.withEffect((n) => n.onFormData(handler))
|
|
196
|
+
return Effect.flatMap(Navigation, (nav) => nav.submit(form))
|
|
534
197
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as Schema from 'effect/Schema'
|
|
2
|
+
import { Destination } from './Destination.js'
|
|
3
|
+
|
|
4
|
+
export const ProposedDestination = Destination.pipe(Schema.omit('id', 'key'))
|
|
5
|
+
|
|
6
|
+
export type ProposedDestinationEncoded = Schema.Schema.Encoded<typeof ProposedDestination>
|
|
7
|
+
|
|
8
|
+
export interface ProposedDestination extends Schema.Schema.Type<typeof ProposedDestination> {}
|