@tailor-platform/app-shell 0.17.1 → 0.18.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/dist/app-shell.css +1 -0
- package/dist/app-shell.js +1421 -0
- package/dist/index.d.ts +572 -407
- package/package.json +12 -9
- package/dist/index.css +0 -2
- package/dist/index.js +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,407 +1,572 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
*
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* ```
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
*
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
*
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
*
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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
|
-
|
|
360
|
-
|
|
361
|
-
declare const
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
*
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
*
|
|
399
|
-
*/
|
|
400
|
-
declare
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
1
|
+
import { JSX } from 'react/jsx-runtime';
|
|
2
|
+
import { Link } from 'react-router';
|
|
3
|
+
import { PropsWithChildren } from 'react';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
import { useLocation } from 'react-router';
|
|
6
|
+
import { useNavigate } from 'react-router';
|
|
7
|
+
import { useParams } from 'react-router';
|
|
8
|
+
import { useRouteError } from 'react-router';
|
|
9
|
+
import { useSearchParams } from 'react-router';
|
|
10
|
+
|
|
11
|
+
export declare const AppShell: (props: AppShellProps) => JSX.Element | null;
|
|
12
|
+
|
|
13
|
+
declare type AppShellContextType = {
|
|
14
|
+
title?: string;
|
|
15
|
+
icon?: ReactNode;
|
|
16
|
+
configurations: RootConfiguration;
|
|
17
|
+
navItems: Array<NavItem>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export declare type AppShellProps = React.PropsWithChildren<{
|
|
21
|
+
/**
|
|
22
|
+
* App shell title
|
|
23
|
+
*/
|
|
24
|
+
title?: string;
|
|
25
|
+
/**
|
|
26
|
+
* App shell icon
|
|
27
|
+
*/
|
|
28
|
+
icon?: React.ReactNode;
|
|
29
|
+
/**
|
|
30
|
+
* Base path for the app shell
|
|
31
|
+
*/
|
|
32
|
+
basePath?: string;
|
|
33
|
+
/**
|
|
34
|
+
* A component to be rendered at the root level of AppShell,
|
|
35
|
+
* or a redirect configuration
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Render a component
|
|
40
|
+
* rootComponent: () => <DashboardHome />
|
|
41
|
+
*
|
|
42
|
+
* // Redirect to a resource
|
|
43
|
+
* rootComponent: redirectToResource("dashboard/overview")
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
rootComponent?: (() => React.ReactNode) | RedirectConfig;
|
|
47
|
+
/**
|
|
48
|
+
* Navigation configuration
|
|
49
|
+
*/
|
|
50
|
+
modules: Modules;
|
|
51
|
+
/**
|
|
52
|
+
* Settings resources to be included in the settings menu
|
|
53
|
+
*/
|
|
54
|
+
settingsResources?: Array<Resource>;
|
|
55
|
+
/**
|
|
56
|
+
* Locale code used for built-in UI strings.
|
|
57
|
+
*
|
|
58
|
+
* If not provided, auto-detects from browser preferences.
|
|
59
|
+
* No browser locale information avilable, "en" used as default.
|
|
60
|
+
*/
|
|
61
|
+
locale?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Global error boundary component applied to all routes.
|
|
64
|
+
*
|
|
65
|
+
* When an error occurs in any route component, this component will render.
|
|
66
|
+
* Module and resource-level error boundaries take precedence over this.
|
|
67
|
+
* Use the `useRouteError` hook to access error details within the component.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```tsx
|
|
71
|
+
* import { useRouteError } from "@tailor-platform/app-shell";
|
|
72
|
+
*
|
|
73
|
+
* const GlobalErrorBoundary = () => {
|
|
74
|
+
* const error = useRouteError() as Error;
|
|
75
|
+
* return (
|
|
76
|
+
* <div>
|
|
77
|
+
* <h1>Something went wrong</h1>
|
|
78
|
+
* <p>{error.message}</p>
|
|
79
|
+
* </div>
|
|
80
|
+
* );
|
|
81
|
+
* };
|
|
82
|
+
*
|
|
83
|
+
* <AppShell
|
|
84
|
+
* modules: [...],
|
|
85
|
+
* errorBoundary: <GlobalErrorBoundary />,
|
|
86
|
+
* />
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
errorBoundary?: ErrorBoundaryComponent;
|
|
90
|
+
}>;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* We need to build a Login URL with the correct parameters to redirect
|
|
94
|
+
* to our OAuth endpoint login page
|
|
95
|
+
*/
|
|
96
|
+
export declare const buildAuthorizationUrl: ({ apiEndpoint, clientId, state, codeChallenge, redirectUri, }: BuildAuthorizationUrlParams) => string;
|
|
97
|
+
|
|
98
|
+
declare interface BuildAuthorizationUrlParams {
|
|
99
|
+
apiEndpoint: string;
|
|
100
|
+
clientId: string;
|
|
101
|
+
state: string;
|
|
102
|
+
codeChallenge: string;
|
|
103
|
+
redirectUri?: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
declare interface BuiltinIdPAuthContextType {
|
|
107
|
+
/**
|
|
108
|
+
* Initiates the login process by redirecting to the OAuth2 authorization endpoint.
|
|
109
|
+
*/
|
|
110
|
+
login: () => Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Logs out the user by revoking the token and clearing session data.
|
|
113
|
+
*/
|
|
114
|
+
logout: () => Promise<void>;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export declare const BuiltinIdPAuthProvider: ({ apiEndpoint, clientId, redirectUri, children, }: PropsWithChildren<Props>) => JSX.Element;
|
|
118
|
+
|
|
119
|
+
declare type CommonModuleProps = {
|
|
120
|
+
/**
|
|
121
|
+
* Resource associated to the module.
|
|
122
|
+
*/
|
|
123
|
+
resources: Array<Resource>;
|
|
124
|
+
meta: CommonProps["meta"] & {
|
|
125
|
+
icon?: ReactNode;
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
declare type CommonPageResource = {
|
|
130
|
+
path: string;
|
|
131
|
+
type: "component";
|
|
132
|
+
component: () => ReactNode;
|
|
133
|
+
meta: {
|
|
134
|
+
title: LocalizedString;
|
|
135
|
+
icon?: ReactNode;
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
declare type CommonProps = {
|
|
140
|
+
/**
|
|
141
|
+
* Path of the resource.
|
|
142
|
+
*
|
|
143
|
+
* The path will be used to generate the URL for the resource.
|
|
144
|
+
* This also supports dynamic parameters using the syntax `:paramName`.
|
|
145
|
+
*/
|
|
146
|
+
path: string;
|
|
147
|
+
/**
|
|
148
|
+
* Metadata for the resource.
|
|
149
|
+
*/
|
|
150
|
+
meta?: ResourceMetaProps;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export declare const DefaultSidebar: (props: DefaultSidebarProps) => JSX.Element;
|
|
154
|
+
|
|
155
|
+
declare type DefaultSidebarProps = {
|
|
156
|
+
header?: React.ReactNode;
|
|
157
|
+
footer?: React.ReactNode;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Defines internationalization labels for multiple locales.
|
|
162
|
+
*
|
|
163
|
+
* `en` locale is required as the default locale.
|
|
164
|
+
* Labels can be either static strings or dynamic functions that take props.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```tsx
|
|
168
|
+
* import { defineI18nLabels } from "@tailor-platform/app-shell";
|
|
169
|
+
*
|
|
170
|
+
* export const labels = defineI18nLabels({
|
|
171
|
+
* en: {
|
|
172
|
+
* hello: "Hello",
|
|
173
|
+
* welcome: (props: { name: string }) => `Welcome, ${props.name}!`,
|
|
174
|
+
* },
|
|
175
|
+
* ja: {
|
|
176
|
+
* hello: "こんにちは",
|
|
177
|
+
* welcome: (props: { name: string }) => `ようこそ、${props.name}さん!`,
|
|
178
|
+
* },
|
|
179
|
+
* });
|
|
180
|
+
*
|
|
181
|
+
* // Hook to get the translated label resolver function
|
|
182
|
+
* export const useT = labels.useT;
|
|
183
|
+
*
|
|
184
|
+
* // Usage in component
|
|
185
|
+
* const t = useT();
|
|
186
|
+
* t("hello"); // "Hello"
|
|
187
|
+
* t("welcome", { name: "John" }); // "Welcome, John!"
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export declare const defineI18nLabels: <const L extends Exclude<string, "en">, const Def extends Record<string, LabelValue>>(labels: {
|
|
191
|
+
en: Def;
|
|
192
|
+
} & { [K in L]: LabelDefinition<Def>; } & DynamicLocales<Def>) => {
|
|
193
|
+
/**
|
|
194
|
+
* Hook to get the translated label resolver function.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```tsx
|
|
198
|
+
* import { useT } from "./i18n-labels";
|
|
199
|
+
*
|
|
200
|
+
* const YourComponent = () => {
|
|
201
|
+
* const t = useT();
|
|
202
|
+
*
|
|
203
|
+
* return (
|
|
204
|
+
* <div>
|
|
205
|
+
* {t("staticLabel")}
|
|
206
|
+
* {t("dynamicLabel", { name: "John" })}
|
|
207
|
+
* </div>
|
|
208
|
+
* );
|
|
209
|
+
* }
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
useT: () => <K extends keyof Def & string>(key: K, ...args: Def[K] extends (props: infer P) => string ? [props: P] : []) => string;
|
|
213
|
+
/**
|
|
214
|
+
* A function to get the translater for a specific label key.
|
|
215
|
+
* This is expected to be used in `meta.title` in module/resource definitions.
|
|
216
|
+
*
|
|
217
|
+
* Note: When using dynamic labels with props in meta.title, the props are
|
|
218
|
+
* bound at definition time (when calling labels.t), not at render time.
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```tsx
|
|
222
|
+
* import { labels } from "./i18n-labels";
|
|
223
|
+
*
|
|
224
|
+
* const resource = defineResource({
|
|
225
|
+
* path: "example",
|
|
226
|
+
* meta: {
|
|
227
|
+
* title: labels.t("someLabelKey"),
|
|
228
|
+
* // or with props for dynamic labels
|
|
229
|
+
* title: labels.t("dynamicKey", { id: "123" }),
|
|
230
|
+
* },
|
|
231
|
+
* component: ExampleComponent,
|
|
232
|
+
* });
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
t: <K extends keyof Def & string>(key: K, ...args: Def[K] extends (props: infer P) => string ? [props: P] : []) => LocalizedString;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Define a root-level resource that renders a React component.
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* ```
|
|
243
|
+
* // Define a minimal resource
|
|
244
|
+
* defineReactResource({
|
|
245
|
+
* path: "custom-page",
|
|
246
|
+
* component: () => {
|
|
247
|
+
* return (
|
|
248
|
+
* <div>
|
|
249
|
+
* <p>This is a custom page.</p>
|
|
250
|
+
* </div>
|
|
251
|
+
* );
|
|
252
|
+
* },
|
|
253
|
+
* });
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
export declare function defineModule(props: DefineModuleProps): Module;
|
|
257
|
+
|
|
258
|
+
declare type DefineModuleProps = CommonProps & CommonModuleProps & {
|
|
259
|
+
/**
|
|
260
|
+
* React component to render or redirect configuration
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```tsx
|
|
264
|
+
* // Render a component
|
|
265
|
+
* component: (props) => <div>{props.title}</div>
|
|
266
|
+
*
|
|
267
|
+
* // Redirect to a resource
|
|
268
|
+
* component: redirectToResource("dashboard/overview")
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
271
|
+
component: ((props: ResourceComponentProps) => ReactNode) | RedirectConfig;
|
|
272
|
+
/**
|
|
273
|
+
* Error boundary component for this module and its child resources.
|
|
274
|
+
* When an error occurs in this module or its resources, this component will render.
|
|
275
|
+
* Use the `useRouteError` hook to access error details within the component.
|
|
276
|
+
*/
|
|
277
|
+
errorBoundary?: ErrorBoundaryComponent;
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Define a resource that renders a React component.
|
|
282
|
+
*
|
|
283
|
+
* This resource can be used as a sub-resource of a module or as a root-level resource.
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```
|
|
287
|
+
* // Define a minimal resource
|
|
288
|
+
* defineResource({
|
|
289
|
+
* path: "custom-page",
|
|
290
|
+
* component: () => {
|
|
291
|
+
* return (
|
|
292
|
+
* <div>
|
|
293
|
+
* <p>This is a custom page.</p>
|
|
294
|
+
* </div>
|
|
295
|
+
* );
|
|
296
|
+
* },
|
|
297
|
+
* subResources: [
|
|
298
|
+
* defineResource({
|
|
299
|
+
* path: "sub-page",
|
|
300
|
+
* component: () => {
|
|
301
|
+
* return (
|
|
302
|
+
* <div>
|
|
303
|
+
* <p>This is a sub page.</p>
|
|
304
|
+
* </div>
|
|
305
|
+
* );
|
|
306
|
+
* },
|
|
307
|
+
* }),
|
|
308
|
+
* ]
|
|
309
|
+
* });
|
|
310
|
+
* ```
|
|
311
|
+
*
|
|
312
|
+
*/
|
|
313
|
+
export declare function defineResource(props: DefineResourceProps): Resource;
|
|
314
|
+
|
|
315
|
+
declare type DefineResourceProps = CommonProps & ReactResourceProps & {
|
|
316
|
+
/**
|
|
317
|
+
* Sub-resources of the resource.
|
|
318
|
+
*/
|
|
319
|
+
subResources?: Array<Resource>;
|
|
320
|
+
/**
|
|
321
|
+
* Error boundary component for this resource and its sub-resources.
|
|
322
|
+
* When an error occurs in this resource, this component will render.
|
|
323
|
+
* Overrides module-level or global error boundaries.
|
|
324
|
+
* Use the `useRouteError` hook to access error details within the component.
|
|
325
|
+
*/
|
|
326
|
+
errorBoundary?: ErrorBoundaryComponent;
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
declare type DynamicLocales<Def extends Record<string, LabelValue>> = {
|
|
330
|
+
[locale: string]: Partial<LabelDefinition<Def>> | undefined;
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Error boundary element type for route error handling.
|
|
335
|
+
*
|
|
336
|
+
* Pass a JSX element that will render when an error occurs.
|
|
337
|
+
* Use the `useRouteError` hook from react-router to access the error.
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```tsx
|
|
341
|
+
* import { useRouteError } from "@tailor-platform/app-shell";
|
|
342
|
+
*
|
|
343
|
+
* const MyErrorBoundary = () => {
|
|
344
|
+
* const error = useRouteError() as Error;
|
|
345
|
+
* return <div>Error: {error.message}</div>;
|
|
346
|
+
* };
|
|
347
|
+
*
|
|
348
|
+
* // In config:
|
|
349
|
+
* errorBoundary: <MyErrorBoundary />
|
|
350
|
+
* // Or with props:
|
|
351
|
+
* errorBoundary: <MyErrorBoundary theme="dark" onReport={handleReport} />
|
|
352
|
+
* ```
|
|
353
|
+
*/
|
|
354
|
+
export declare type ErrorBoundaryComponent = ReactNode;
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* We need to exchange the code and state we received from the OAuth endpoint
|
|
358
|
+
* for an actual authorization token, in Browser Client case, we get the token
|
|
359
|
+
* inside of a cookie so there is nothing else to do beyond that point
|
|
360
|
+
*/
|
|
361
|
+
export declare const exchangeCodeForToken: ({ code, returnedState, apiEndpoint, clientId, redirectUri, }: ExchangeCodeForTokenParams) => Promise<string>;
|
|
362
|
+
|
|
363
|
+
declare interface ExchangeCodeForTokenParams {
|
|
364
|
+
apiEndpoint: string;
|
|
365
|
+
clientId: string;
|
|
366
|
+
returnedState: string | null;
|
|
367
|
+
code: string | null;
|
|
368
|
+
redirectUri?: string;
|
|
369
|
+
silent?: boolean;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* When redirected from our IdP Provider, we need to exchange code and state
|
|
374
|
+
* for a token and clean up the URL params
|
|
375
|
+
*/
|
|
376
|
+
export declare const handleOAuthCallback: ({ currentUrl, apiEndpoint, clientId, redirectUri, }: {
|
|
377
|
+
currentUrl: URL;
|
|
378
|
+
apiEndpoint: string;
|
|
379
|
+
clientId: string;
|
|
380
|
+
redirectUri: string;
|
|
381
|
+
}) => Promise<void>;
|
|
382
|
+
|
|
383
|
+
export declare type I18nLabels<Def extends Record<string, LabelValue> = Record<string, LabelValue>, L extends string = never> = {
|
|
384
|
+
en: Def;
|
|
385
|
+
} & {
|
|
386
|
+
[K in L]: LabelDefinition<Def>;
|
|
387
|
+
} & DynamicLocales<Def>;
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Ensures that other locales have the same label structure as the base definition.
|
|
391
|
+
* For dynamic labels (functions), the props type must match.
|
|
392
|
+
*/
|
|
393
|
+
declare type LabelDefinition<Def extends Record<string, LabelValue>> = {
|
|
394
|
+
[K in keyof Def]: Def[K] extends (props: infer P) => string ? (props: P) => string : string;
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Label value can be either a static string or a dynamic function that takes props.
|
|
399
|
+
*/
|
|
400
|
+
declare type LabelValue = string | ((props: any) => string);
|
|
401
|
+
|
|
402
|
+
export { Link }
|
|
403
|
+
|
|
404
|
+
declare type LocalizedString = string | ((locale: string) => string);
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* A resource that can be included in the root-level content in the navigation.
|
|
408
|
+
*/
|
|
409
|
+
declare type Module = Omit<CommonPageResource, "meta"> & {
|
|
410
|
+
_type: "module";
|
|
411
|
+
meta: CommonPageResource["meta"] & {
|
|
412
|
+
icon?: ReactNode;
|
|
413
|
+
menuItemClickable: boolean;
|
|
414
|
+
};
|
|
415
|
+
resources: Array<Resource>;
|
|
416
|
+
loader?: () => Response;
|
|
417
|
+
errorBoundary: ErrorBoundaryComponent;
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
declare type Modules = Array<Module>;
|
|
421
|
+
|
|
422
|
+
declare type NavChildItem = {
|
|
423
|
+
title: string;
|
|
424
|
+
url: string;
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
declare type NavItem = {
|
|
428
|
+
title: string;
|
|
429
|
+
url: string | undefined;
|
|
430
|
+
icon: ReactNode;
|
|
431
|
+
isActive?: boolean;
|
|
432
|
+
items?: Array<NavChildItem>;
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
export declare const OAUTH_STATE_KEY = "oauth_state";
|
|
436
|
+
|
|
437
|
+
export declare const PKCE_VERIFIER_KEY = "oauth_pkce_verifier";
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* We need to generate a challenge and state key for OAuth login
|
|
441
|
+
* and stores them in sessionStorage for verification on callback redirect
|
|
442
|
+
*/
|
|
443
|
+
export declare const prepareLogin: () => Promise<{
|
|
444
|
+
codeChallenge: string;
|
|
445
|
+
state: string;
|
|
446
|
+
}>;
|
|
447
|
+
|
|
448
|
+
declare type Props = {
|
|
449
|
+
/**
|
|
450
|
+
* API endpoint of your Tailor Platform application. No `/query` suffix needed.
|
|
451
|
+
*
|
|
452
|
+
* @example https://xyz.erp.dev
|
|
453
|
+
*/
|
|
454
|
+
apiEndpoint: string;
|
|
455
|
+
/**
|
|
456
|
+
* OAuth2 Client ID of your Tailor Platform application.
|
|
457
|
+
*/
|
|
458
|
+
clientId: string;
|
|
459
|
+
/**
|
|
460
|
+
* Redirect URI after login is successful.
|
|
461
|
+
*
|
|
462
|
+
* @defaults `window.location.origin`
|
|
463
|
+
*/
|
|
464
|
+
redirectUri?: string;
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
declare type ReactResourceProps = {
|
|
468
|
+
/**
|
|
469
|
+
* React component to render.
|
|
470
|
+
*/
|
|
471
|
+
component: (props: ResourceComponentProps) => ReactNode;
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Redirect configuration for module or root component
|
|
476
|
+
*/
|
|
477
|
+
declare type RedirectConfig = {
|
|
478
|
+
/**
|
|
479
|
+
* Path to redirect to (under /resources/)
|
|
480
|
+
*/
|
|
481
|
+
redirectTo: string;
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Helper function to define a redirect to a resource path
|
|
486
|
+
*
|
|
487
|
+
* @param path - Path under `/resources/` (e.g., "dashboard/overview")
|
|
488
|
+
*
|
|
489
|
+
* @example
|
|
490
|
+
* ```tsx
|
|
491
|
+
* defineModule({
|
|
492
|
+
* path: "dashboard",
|
|
493
|
+
* component: redirectToResource("dashboard/overview"),
|
|
494
|
+
* resources: [overviewResource],
|
|
495
|
+
* });
|
|
496
|
+
* ```
|
|
497
|
+
*/
|
|
498
|
+
export declare function redirectToResource(path: string): RedirectConfig;
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* A resource that can be included in the sub-content in the root resource.
|
|
502
|
+
*
|
|
503
|
+
* This resource does not have `category` metadata.
|
|
504
|
+
*/
|
|
505
|
+
declare type Resource = CommonPageResource & {
|
|
506
|
+
_type: "resource";
|
|
507
|
+
subResources?: Array<Resource>;
|
|
508
|
+
errorBoundary: ErrorBoundaryComponent;
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
export declare type ResourceComponentProps = {
|
|
512
|
+
title: string;
|
|
513
|
+
icon?: ReactNode;
|
|
514
|
+
resources?: Array<Resource>;
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
declare type ResourceMetaProps = {
|
|
518
|
+
/**
|
|
519
|
+
* Title of the resource used in navigation.
|
|
520
|
+
*
|
|
521
|
+
* If not provided, the title will be generated from the path.
|
|
522
|
+
*/
|
|
523
|
+
title?: LocalizedString;
|
|
524
|
+
icon?: ReactNode;
|
|
525
|
+
/**
|
|
526
|
+
* Custom breadcrumb segment title for this resource. Can be a string or a function.
|
|
527
|
+
*/
|
|
528
|
+
breadcrumbTitle?: string | ((segment: string) => string);
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
declare type RootConfiguration = {
|
|
532
|
+
modules: Modules;
|
|
533
|
+
settingsResources: Resource[];
|
|
534
|
+
basePath?: string;
|
|
535
|
+
errorBoundary: ErrorBoundaryComponent;
|
|
536
|
+
locale: string;
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
export declare const SidebarLayout: (props: SidebarLayoutProps) => JSX.Element;
|
|
540
|
+
|
|
541
|
+
declare type SidebarLayoutProps = {
|
|
542
|
+
children?: (props: {
|
|
543
|
+
Outlet: () => React.ReactNode;
|
|
544
|
+
}) => React.ReactNode;
|
|
545
|
+
sidebar?: React.ReactNode;
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
declare type Theme = "dark" | "light" | "system";
|
|
549
|
+
|
|
550
|
+
declare type ThemeProviderState = {
|
|
551
|
+
theme: Theme;
|
|
552
|
+
resolvedTheme: Omit<Theme, "system">;
|
|
553
|
+
setTheme: (theme: Theme) => void;
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
export declare const useAppShell: () => AppShellContextType;
|
|
557
|
+
|
|
558
|
+
export declare const useBuiltinIdpAuth: () => BuiltinIdPAuthContextType;
|
|
559
|
+
|
|
560
|
+
export { useLocation }
|
|
561
|
+
|
|
562
|
+
export { useNavigate }
|
|
563
|
+
|
|
564
|
+
export { useParams }
|
|
565
|
+
|
|
566
|
+
export { useRouteError }
|
|
567
|
+
|
|
568
|
+
export { useSearchParams }
|
|
569
|
+
|
|
570
|
+
export declare const useTheme: () => ThemeProviderState;
|
|
571
|
+
|
|
572
|
+
export { }
|