@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.
Files changed (174) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -0
  3. package/dist/cjs/Blocking.js +53 -0
  4. package/dist/cjs/Blocking.js.map +1 -0
  5. package/dist/cjs/Layer.js +27 -0
  6. package/dist/cjs/Layer.js.map +1 -0
  7. package/dist/cjs/Navigation.js +184 -62
  8. package/dist/cjs/Navigation.js.map +1 -1
  9. package/dist/cjs/index.js +36 -17
  10. package/dist/cjs/index.js.map +1 -1
  11. package/dist/cjs/internal/fromWindow.js +376 -0
  12. package/dist/cjs/internal/fromWindow.js.map +1 -0
  13. package/dist/cjs/internal/memory.js +67 -0
  14. package/dist/cjs/internal/memory.js.map +1 -0
  15. package/dist/cjs/internal/shared.js +403 -0
  16. package/dist/cjs/internal/shared.js.map +1 -0
  17. package/dist/dts/Blocking.d.ts +33 -0
  18. package/dist/dts/Blocking.d.ts.map +1 -0
  19. package/dist/dts/Layer.d.ts +44 -0
  20. package/dist/dts/Layer.d.ts.map +1 -0
  21. package/dist/dts/Navigation.d.ts +377 -0
  22. package/dist/dts/Navigation.d.ts.map +1 -0
  23. package/dist/dts/index.d.ts +17 -0
  24. package/dist/dts/index.d.ts.map +1 -0
  25. package/dist/dts/internal/fromWindow.d.ts +12 -0
  26. package/dist/dts/internal/fromWindow.d.ts.map +1 -0
  27. package/dist/dts/internal/memory.d.ts +6 -0
  28. package/dist/dts/internal/memory.d.ts.map +1 -0
  29. package/dist/dts/internal/shared.d.ts +139 -0
  30. package/dist/dts/internal/shared.d.ts.map +1 -0
  31. package/dist/esm/Blocking.js +39 -0
  32. package/dist/esm/Blocking.js.map +1 -0
  33. package/dist/esm/Layer.js +18 -0
  34. package/dist/esm/Layer.js.map +1 -0
  35. package/dist/esm/Navigation.js +166 -0
  36. package/dist/esm/Navigation.js.map +1 -0
  37. package/dist/esm/index.js +17 -0
  38. package/dist/esm/index.js.map +1 -0
  39. package/dist/esm/internal/fromWindow.js +273 -0
  40. package/dist/esm/internal/fromWindow.js.map +1 -0
  41. package/dist/esm/internal/memory.js +54 -0
  42. package/dist/esm/internal/memory.js.map +1 -0
  43. package/dist/esm/internal/shared.js +336 -0
  44. package/dist/esm/internal/shared.js.map +1 -0
  45. package/dist/esm/package.json +4 -0
  46. package/package.json +52 -32
  47. package/src/Blocking.ts +102 -0
  48. package/src/Layer.ts +53 -0
  49. package/src/Navigation.ts +342 -159
  50. package/src/index.ts +17 -3
  51. package/src/internal/fromWindow.ts +421 -0
  52. package/src/internal/memory.ts +79 -0
  53. package/src/internal/shared.ts +514 -0
  54. package/dist/DOM.d.ts +0 -12
  55. package/dist/DOM.d.ts.map +0 -1
  56. package/dist/DOM.js +0 -87
  57. package/dist/DOM.js.map +0 -1
  58. package/dist/Memory.d.ts +0 -10
  59. package/dist/Memory.d.ts.map +0 -1
  60. package/dist/Memory.js +0 -55
  61. package/dist/Memory.js.map +0 -1
  62. package/dist/Navigation.d.ts +0 -116
  63. package/dist/Navigation.d.ts.map +0 -1
  64. package/dist/Navigation.js +0 -36
  65. package/dist/Navigation.js.map +0 -1
  66. package/dist/_makeServerWindow.d.ts +0 -16
  67. package/dist/_makeServerWindow.d.ts.map +0 -1
  68. package/dist/_makeServerWindow.js +0 -9
  69. package/dist/_makeServerWindow.js.map +0 -1
  70. package/dist/cjs/DOM.d.ts +0 -12
  71. package/dist/cjs/DOM.d.ts.map +0 -1
  72. package/dist/cjs/DOM.js +0 -116
  73. package/dist/cjs/DOM.js.map +0 -1
  74. package/dist/cjs/Memory.d.ts +0 -10
  75. package/dist/cjs/Memory.d.ts.map +0 -1
  76. package/dist/cjs/Memory.js +0 -82
  77. package/dist/cjs/Memory.js.map +0 -1
  78. package/dist/cjs/Navigation.d.ts +0 -116
  79. package/dist/cjs/Navigation.d.ts.map +0 -1
  80. package/dist/cjs/_makeServerWindow.d.ts +0 -16
  81. package/dist/cjs/_makeServerWindow.d.ts.map +0 -1
  82. package/dist/cjs/_makeServerWindow.js +0 -36
  83. package/dist/cjs/_makeServerWindow.js.map +0 -1
  84. package/dist/cjs/dom-intent.d.ts +0 -28
  85. package/dist/cjs/dom-intent.d.ts.map +0 -1
  86. package/dist/cjs/dom-intent.js +0 -172
  87. package/dist/cjs/dom-intent.js.map +0 -1
  88. package/dist/cjs/history.d.ts +0 -31
  89. package/dist/cjs/history.d.ts.map +0 -1
  90. package/dist/cjs/history.js +0 -131
  91. package/dist/cjs/history.js.map +0 -1
  92. package/dist/cjs/index.d.ts +0 -4
  93. package/dist/cjs/index.d.ts.map +0 -1
  94. package/dist/cjs/json.d.ts +0 -13
  95. package/dist/cjs/json.d.ts.map +0 -1
  96. package/dist/cjs/json.js +0 -24
  97. package/dist/cjs/json.js.map +0 -1
  98. package/dist/cjs/memory-intent.d.ts +0 -27
  99. package/dist/cjs/memory-intent.d.ts.map +0 -1
  100. package/dist/cjs/memory-intent.js +0 -156
  101. package/dist/cjs/memory-intent.js.map +0 -1
  102. package/dist/cjs/model.d.ts +0 -22
  103. package/dist/cjs/model.d.ts.map +0 -1
  104. package/dist/cjs/model.js +0 -48
  105. package/dist/cjs/model.js.map +0 -1
  106. package/dist/cjs/shared-intent.d.ts +0 -14
  107. package/dist/cjs/shared-intent.d.ts.map +0 -1
  108. package/dist/cjs/shared-intent.js +0 -82
  109. package/dist/cjs/shared-intent.js.map +0 -1
  110. package/dist/cjs/storage.d.ts +0 -19
  111. package/dist/cjs/storage.d.ts.map +0 -1
  112. package/dist/cjs/storage.js +0 -101
  113. package/dist/cjs/storage.js.map +0 -1
  114. package/dist/cjs/util.d.ts +0 -5
  115. package/dist/cjs/util.d.ts.map +0 -1
  116. package/dist/cjs/util.js +0 -39
  117. package/dist/cjs/util.js.map +0 -1
  118. package/dist/dom-intent.d.ts +0 -28
  119. package/dist/dom-intent.d.ts.map +0 -1
  120. package/dist/dom-intent.js +0 -140
  121. package/dist/dom-intent.js.map +0 -1
  122. package/dist/history.d.ts +0 -31
  123. package/dist/history.d.ts.map +0 -1
  124. package/dist/history.js +0 -104
  125. package/dist/history.js.map +0 -1
  126. package/dist/index.d.ts +0 -4
  127. package/dist/index.d.ts.map +0 -1
  128. package/dist/index.js +0 -4
  129. package/dist/index.js.map +0 -1
  130. package/dist/json.d.ts +0 -13
  131. package/dist/json.d.ts.map +0 -1
  132. package/dist/json.js +0 -17
  133. package/dist/json.js.map +0 -1
  134. package/dist/memory-intent.d.ts +0 -27
  135. package/dist/memory-intent.d.ts.map +0 -1
  136. package/dist/memory-intent.js +0 -124
  137. package/dist/memory-intent.js.map +0 -1
  138. package/dist/model.d.ts +0 -22
  139. package/dist/model.d.ts.map +0 -1
  140. package/dist/model.js +0 -21
  141. package/dist/model.js.map +0 -1
  142. package/dist/shared-intent.d.ts +0 -14
  143. package/dist/shared-intent.d.ts.map +0 -1
  144. package/dist/shared-intent.js +0 -51
  145. package/dist/shared-intent.js.map +0 -1
  146. package/dist/storage.d.ts +0 -19
  147. package/dist/storage.d.ts.map +0 -1
  148. package/dist/storage.js +0 -73
  149. package/dist/storage.js.map +0 -1
  150. package/dist/tsconfig.cjs.build.tsbuildinfo +0 -1
  151. package/dist/util.d.ts +0 -5
  152. package/dist/util.d.ts.map +0 -1
  153. package/dist/util.js +0 -12
  154. package/dist/util.js.map +0 -1
  155. package/eslintrc.json +0 -3
  156. package/project.json +0 -46
  157. package/src/DOM.test.ts +0 -699
  158. package/src/DOM.ts +0 -163
  159. package/src/Memory.test.ts +0 -464
  160. package/src/Memory.ts +0 -102
  161. package/src/_makeServerWindow.ts +0 -28
  162. package/src/dom-intent.ts +0 -268
  163. package/src/history.ts +0 -165
  164. package/src/json.ts +0 -31
  165. package/src/memory-intent.ts +0 -224
  166. package/src/model.ts +0 -54
  167. package/src/shared-intent.ts +0 -117
  168. package/src/storage.ts +0 -101
  169. package/src/util.ts +0 -20
  170. package/tsconfig.build.json +0 -4
  171. package/tsconfig.build.tsbuildinfo +0 -1
  172. package/tsconfig.cjs.build.json +0 -22
  173. package/tsconfig.json +0 -27
  174. package/vite.config.mjs +0 -3
package/src/Navigation.ts CHANGED
@@ -1,192 +1,375 @@
1
- import * as Brand from '@effect/data/Brand'
2
- import { Option } from '@effect/data/Option'
3
- import * as Effect from '@effect/io/Effect'
4
- import * as Scope from '@effect/io/Scope'
5
- import * as Context from '@typed/context'
6
- import * as Fx from '@typed/fx'
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
- * Base path for all navigation entries.
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
- export const Navigation = Context.Tag<Navigation>('Navigation')
24
+ readonly entries: Computed.Computed<never, never, ReadonlyArray<Destination>>
89
25
 
90
- export const navigate = (url: string, options?: NavigateOptions) =>
91
- Navigation.withEffect((n) => n.navigate(url, options))
26
+ readonly transition: Computed.Computed<never, never, Option.Option<Transition>>
92
27
 
93
- export const onNavigation = <R>(
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
- export const canGoBack: Effect.Effect<Navigation, never, boolean> &
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
- export const back = Navigation.withEffect((n) => n.back)
32
+ readonly navigate: (
33
+ url: string | URL,
34
+ options?: NavigateOptions
35
+ ) => Effect.Effect<never, NavigationError, Destination>
104
36
 
105
- export const canGoForward: Effect.Effect<Navigation, never, boolean> &
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
- export const forward = Navigation.withEffect((n) => n.forward)
39
+ readonly forward: (options?: { readonly info?: unknown }) => Effect.Effect<never, NavigationError, Destination>
112
40
 
113
- export const reload = Navigation.withEffect((n) => n.reload)
41
+ readonly traverseTo: (
42
+ key: Destination["key"],
43
+ options?: { readonly info?: unknown }
44
+ ) => Effect.Effect<never, NavigationError, Destination>
114
45
 
115
- export interface NavigateOptions {
116
- // State to save to history
117
- readonly state?: unknown
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
- export interface NavigationEvent {
125
- readonly destination: Destination
126
- readonly hashChange: boolean
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
- export function NavigationEvent(
131
- destination: Destination,
132
- hashChange: boolean,
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
- export interface Destination {
139
- readonly key: DestinationKey
140
- readonly url: URL
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
- export type DestinationKey = string & Brand.Brand<'DestinationKey'>
145
- export const DestinationKey = Brand.nominal<DestinationKey>()
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
- export function Destination(key: DestinationKey, url: URL, state?: unknown): Destination {
148
- return { key, url, state }
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
- export enum NavigationType {
152
- Push = 'push',
153
- Reload = 'reload',
154
- Replace = 'replace',
155
- Back = 'back',
156
- Forward = 'forward',
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
- export type NavigationError = CancelNavigation | RedirectNavigation
160
-
161
- export interface CancelNavigation {
162
- readonly _tag: 'CancelNavigation'
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
- export const cancelNavigation = Effect.fail<CancelNavigation>({ _tag: 'CancelNavigation' })
166
-
167
- export function isCancelNavigation(error: NavigationError): error is CancelNavigation {
168
- return error._tag === 'CancelNavigation'
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
- export interface RedirectNavigation extends NavigateOptions {
172
- readonly _tag: 'RedirectNavigation'
173
- readonly url: string
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
- export const redirect = (
177
- url: string,
178
- options: NavigateOptions = {},
179
- ): Effect.Effect<never, RedirectNavigation, never> =>
180
- Effect.fail({ _tag: 'RedirectNavigation', url, ...options })
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
- export function isRedirectNavigation(error: NavigationError): error is RedirectNavigation {
183
- return error._tag === 'RedirectNavigation'
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
- export interface OnNavigationOptions {
187
- readonly passive?: boolean
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
- export const getCurrentUrl: Effect.Effect<Navigation, never, URL> = Navigation.withEffect((n) =>
191
- n.currentEntry.map((d) => d.url),
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
- export * from './Navigation.js'
2
- export * from './DOM.js'
3
- export * from './Memory.js'
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"