@alepha/react 0.10.6 → 0.11.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.
@@ -1,203 +1,203 @@
1
1
  import { $inject, Alepha } from "@alepha/core";
2
2
  import type { PageDescriptor } from "../descriptors/$page.ts";
3
3
  import {
4
- ReactBrowserProvider,
5
- type RouterGoOptions,
4
+ ReactBrowserProvider,
5
+ type RouterGoOptions,
6
6
  } from "../providers/ReactBrowserProvider.ts";
7
7
  import {
8
- type AnchorProps,
9
- ReactPageProvider,
10
- type ReactRouterState,
8
+ type AnchorProps,
9
+ ReactPageProvider,
10
+ type ReactRouterState,
11
11
  } from "../providers/ReactPageProvider.ts";
12
12
 
13
13
  export class ReactRouter<T extends object> {
14
- protected readonly alepha = $inject(Alepha);
15
- protected readonly pageApi = $inject(ReactPageProvider);
16
-
17
- public get state(): ReactRouterState {
18
- return this.alepha.state.get("react.router.state")!;
19
- }
20
-
21
- public get pages() {
22
- return this.pageApi.getPages();
23
- }
24
-
25
- public get browser(): ReactBrowserProvider | undefined {
26
- if (this.alepha.isBrowser()) {
27
- return this.alepha.inject(ReactBrowserProvider);
28
- }
29
- // server-side
30
- return undefined;
31
- }
32
-
33
- public path(
34
- name: keyof VirtualRouter<T>,
35
- config: {
36
- params?: Record<string, any>;
37
- query?: Record<string, any>;
38
- } = {},
39
- ): string {
40
- return this.pageApi.pathname(name as string, {
41
- params: {
42
- ...this.state.params,
43
- ...config.params,
44
- },
45
- query: config.query,
46
- });
47
- }
48
-
49
- /**
50
- * Reload the current page.
51
- * This is equivalent to calling `go()` with the current pathname and search.
52
- */
53
- public async reload() {
54
- if (!this.browser) {
55
- return;
56
- }
57
-
58
- await this.go(this.location.pathname + this.location.search, {
59
- replace: true,
60
- force: true,
61
- });
62
- }
63
-
64
- public getURL(): URL {
65
- if (!this.browser) {
66
- return this.state.url;
67
- }
68
-
69
- return new URL(this.location.href);
70
- }
71
-
72
- public get location(): Location {
73
- if (!this.browser) {
74
- throw new Error("Browser is required");
75
- }
76
-
77
- return this.browser.location;
78
- }
79
-
80
- public get current(): ReactRouterState {
81
- return this.state;
82
- }
83
-
84
- public get pathname(): string {
85
- return this.state.url.pathname;
86
- }
87
-
88
- public get query(): Record<string, string> {
89
- const query: Record<string, string> = {};
90
-
91
- for (const [key, value] of new URLSearchParams(
92
- this.state.url.search,
93
- ).entries()) {
94
- query[key] = String(value);
95
- }
96
-
97
- return query;
98
- }
99
-
100
- public async back() {
101
- this.browser?.history.back();
102
- }
103
-
104
- public async forward() {
105
- this.browser?.history.forward();
106
- }
107
-
108
- public async invalidate(props?: Record<string, any>) {
109
- await this.browser?.invalidate(props);
110
- }
111
-
112
- public async go(path: string, options?: RouterGoOptions): Promise<void>;
113
- public async go(
114
- path: keyof VirtualRouter<T>,
115
- options?: RouterGoOptions,
116
- ): Promise<void>;
117
- public async go(
118
- path: string | keyof VirtualRouter<T>,
119
- options?: RouterGoOptions,
120
- ): Promise<void> {
121
- for (const page of this.pages) {
122
- if (page.name === path) {
123
- await this.browser?.go(
124
- this.path(path as keyof VirtualRouter<T>, options),
125
- options,
126
- );
127
- return;
128
- }
129
- }
130
-
131
- await this.browser?.go(path as string, options);
132
- }
133
-
134
- public anchor(path: string, options?: RouterGoOptions): AnchorProps;
135
- public anchor(
136
- path: keyof VirtualRouter<T>,
137
- options?: RouterGoOptions,
138
- ): AnchorProps;
139
- public anchor(
140
- path: string | keyof VirtualRouter<T>,
141
- options: RouterGoOptions = {},
142
- ): AnchorProps {
143
- let href = path as string;
144
-
145
- for (const page of this.pages) {
146
- if (page.name === path) {
147
- href = this.path(path as keyof VirtualRouter<T>, options);
148
- break;
149
- }
150
- }
151
-
152
- return {
153
- href: this.base(href),
154
- onClick: (ev: any) => {
155
- ev.stopPropagation();
156
- ev.preventDefault();
157
-
158
- this.go(href, options).catch(console.error);
159
- },
160
- };
161
- }
162
-
163
- public base(path: string): string {
164
- const base = import.meta.env?.BASE_URL;
165
- if (!base || base === "/") {
166
- return path;
167
- }
168
-
169
- return base + path;
170
- }
171
-
172
- /**
173
- * Set query params.
174
- *
175
- * @param record
176
- * @param options
177
- */
178
- public setQueryParams(
179
- record:
180
- | Record<string, any>
181
- | ((queryParams: Record<string, any>) => Record<string, any>),
182
- options: {
183
- /**
184
- * If true, this will add a new entry to the history stack.
185
- */
186
- push?: boolean;
187
- } = {},
188
- ) {
189
- const func = typeof record === "function" ? record : () => record;
190
- const search = new URLSearchParams(func(this.query)).toString();
191
- const state = search ? `${this.pathname}?${search}` : this.pathname;
192
-
193
- if (options.push) {
194
- window.history.pushState({}, "", state);
195
- } else {
196
- window.history.replaceState({}, "", state);
197
- }
198
- }
14
+ protected readonly alepha = $inject(Alepha);
15
+ protected readonly pageApi = $inject(ReactPageProvider);
16
+
17
+ public get state(): ReactRouterState {
18
+ return this.alepha.state.get("react.router.state")!;
19
+ }
20
+
21
+ public get pages() {
22
+ return this.pageApi.getPages();
23
+ }
24
+
25
+ public get browser(): ReactBrowserProvider | undefined {
26
+ if (this.alepha.isBrowser()) {
27
+ return this.alepha.inject(ReactBrowserProvider);
28
+ }
29
+ // server-side
30
+ return undefined;
31
+ }
32
+
33
+ public path(
34
+ name: keyof VirtualRouter<T>,
35
+ config: {
36
+ params?: Record<string, any>;
37
+ query?: Record<string, any>;
38
+ } = {},
39
+ ): string {
40
+ return this.pageApi.pathname(name as string, {
41
+ params: {
42
+ ...this.state.params,
43
+ ...config.params,
44
+ },
45
+ query: config.query,
46
+ });
47
+ }
48
+
49
+ /**
50
+ * Reload the current page.
51
+ * This is equivalent to calling `go()` with the current pathname and search.
52
+ */
53
+ public async reload() {
54
+ if (!this.browser) {
55
+ return;
56
+ }
57
+
58
+ await this.go(this.location.pathname + this.location.search, {
59
+ replace: true,
60
+ force: true,
61
+ });
62
+ }
63
+
64
+ public getURL(): URL {
65
+ if (!this.browser) {
66
+ return this.state.url;
67
+ }
68
+
69
+ return new URL(this.location.href);
70
+ }
71
+
72
+ public get location(): Location {
73
+ if (!this.browser) {
74
+ throw new Error("Browser is required");
75
+ }
76
+
77
+ return this.browser.location;
78
+ }
79
+
80
+ public get current(): ReactRouterState {
81
+ return this.state;
82
+ }
83
+
84
+ public get pathname(): string {
85
+ return this.state.url.pathname;
86
+ }
87
+
88
+ public get query(): Record<string, string> {
89
+ const query: Record<string, string> = {};
90
+
91
+ for (const [key, value] of new URLSearchParams(
92
+ this.state.url.search,
93
+ ).entries()) {
94
+ query[key] = String(value);
95
+ }
96
+
97
+ return query;
98
+ }
99
+
100
+ public async back() {
101
+ this.browser?.history.back();
102
+ }
103
+
104
+ public async forward() {
105
+ this.browser?.history.forward();
106
+ }
107
+
108
+ public async invalidate(props?: Record<string, any>) {
109
+ await this.browser?.invalidate(props);
110
+ }
111
+
112
+ public async go(path: string, options?: RouterGoOptions): Promise<void>;
113
+ public async go(
114
+ path: keyof VirtualRouter<T>,
115
+ options?: RouterGoOptions,
116
+ ): Promise<void>;
117
+ public async go(
118
+ path: string | keyof VirtualRouter<T>,
119
+ options?: RouterGoOptions,
120
+ ): Promise<void> {
121
+ for (const page of this.pages) {
122
+ if (page.name === path) {
123
+ await this.browser?.go(
124
+ this.path(path as keyof VirtualRouter<T>, options),
125
+ options,
126
+ );
127
+ return;
128
+ }
129
+ }
130
+
131
+ await this.browser?.go(path as string, options);
132
+ }
133
+
134
+ public anchor(path: string, options?: RouterGoOptions): AnchorProps;
135
+ public anchor(
136
+ path: keyof VirtualRouter<T>,
137
+ options?: RouterGoOptions,
138
+ ): AnchorProps;
139
+ public anchor(
140
+ path: string | keyof VirtualRouter<T>,
141
+ options: RouterGoOptions = {},
142
+ ): AnchorProps {
143
+ let href = path as string;
144
+
145
+ for (const page of this.pages) {
146
+ if (page.name === path) {
147
+ href = this.path(path as keyof VirtualRouter<T>, options);
148
+ break;
149
+ }
150
+ }
151
+
152
+ return {
153
+ href: this.base(href),
154
+ onClick: (ev: any) => {
155
+ ev.stopPropagation();
156
+ ev.preventDefault();
157
+
158
+ this.go(href, options).catch(console.error);
159
+ },
160
+ };
161
+ }
162
+
163
+ public base(path: string): string {
164
+ const base = import.meta.env?.BASE_URL;
165
+ if (!base || base === "/") {
166
+ return path;
167
+ }
168
+
169
+ return base + path;
170
+ }
171
+
172
+ /**
173
+ * Set query params.
174
+ *
175
+ * @param record
176
+ * @param options
177
+ */
178
+ public setQueryParams(
179
+ record:
180
+ | Record<string, any>
181
+ | ((queryParams: Record<string, any>) => Record<string, any>),
182
+ options: {
183
+ /**
184
+ * If true, this will add a new entry to the history stack.
185
+ */
186
+ push?: boolean;
187
+ } = {},
188
+ ) {
189
+ const func = typeof record === "function" ? record : () => record;
190
+ const search = new URLSearchParams(func(this.query)).toString();
191
+ const state = search ? `${this.pathname}?${search}` : this.pathname;
192
+
193
+ if (options.push) {
194
+ window.history.pushState({}, "", state);
195
+ } else {
196
+ window.history.replaceState({}, "", state);
197
+ }
198
+ }
199
199
  }
200
200
 
201
201
  export type VirtualRouter<T> = {
202
- [K in keyof T as T[K] extends PageDescriptor ? K : never]: T[K];
202
+ [K in keyof T as T[K] extends PageDescriptor ? K : never]: T[K];
203
203
  };