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