@tailor-platform/app-shell 1.11.0 → 1.13.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 (140) hide show
  1. package/README.md +1 -0
  2. package/dist/app-shell-core.css +3 -1
  3. package/dist/app-shell.d.ts +1192 -88
  4. package/dist/app-shell.js +10669 -13117
  5. package/dist/appshell-CSQWUk6q.js +1823 -0
  6. package/dist/fonts/NOTO-SANS-JP-LICENSE.txt +93 -0
  7. package/dist/fonts/files/noto-sans-jp-0-wght-normal.woff2 +0 -0
  8. package/dist/fonts/files/noto-sans-jp-1-wght-normal.woff2 +0 -0
  9. package/dist/fonts/files/noto-sans-jp-10-wght-normal.woff2 +0 -0
  10. package/dist/fonts/files/noto-sans-jp-100-wght-normal.woff2 +0 -0
  11. package/dist/fonts/files/noto-sans-jp-101-wght-normal.woff2 +0 -0
  12. package/dist/fonts/files/noto-sans-jp-102-wght-normal.woff2 +0 -0
  13. package/dist/fonts/files/noto-sans-jp-103-wght-normal.woff2 +0 -0
  14. package/dist/fonts/files/noto-sans-jp-104-wght-normal.woff2 +0 -0
  15. package/dist/fonts/files/noto-sans-jp-105-wght-normal.woff2 +0 -0
  16. package/dist/fonts/files/noto-sans-jp-106-wght-normal.woff2 +0 -0
  17. package/dist/fonts/files/noto-sans-jp-107-wght-normal.woff2 +0 -0
  18. package/dist/fonts/files/noto-sans-jp-108-wght-normal.woff2 +0 -0
  19. package/dist/fonts/files/noto-sans-jp-109-wght-normal.woff2 +0 -0
  20. package/dist/fonts/files/noto-sans-jp-11-wght-normal.woff2 +0 -0
  21. package/dist/fonts/files/noto-sans-jp-110-wght-normal.woff2 +0 -0
  22. package/dist/fonts/files/noto-sans-jp-111-wght-normal.woff2 +0 -0
  23. package/dist/fonts/files/noto-sans-jp-112-wght-normal.woff2 +0 -0
  24. package/dist/fonts/files/noto-sans-jp-113-wght-normal.woff2 +0 -0
  25. package/dist/fonts/files/noto-sans-jp-114-wght-normal.woff2 +0 -0
  26. package/dist/fonts/files/noto-sans-jp-115-wght-normal.woff2 +0 -0
  27. package/dist/fonts/files/noto-sans-jp-116-wght-normal.woff2 +0 -0
  28. package/dist/fonts/files/noto-sans-jp-117-wght-normal.woff2 +0 -0
  29. package/dist/fonts/files/noto-sans-jp-118-wght-normal.woff2 +0 -0
  30. package/dist/fonts/files/noto-sans-jp-119-wght-normal.woff2 +0 -0
  31. package/dist/fonts/files/noto-sans-jp-12-wght-normal.woff2 +0 -0
  32. package/dist/fonts/files/noto-sans-jp-13-wght-normal.woff2 +0 -0
  33. package/dist/fonts/files/noto-sans-jp-14-wght-normal.woff2 +0 -0
  34. package/dist/fonts/files/noto-sans-jp-15-wght-normal.woff2 +0 -0
  35. package/dist/fonts/files/noto-sans-jp-16-wght-normal.woff2 +0 -0
  36. package/dist/fonts/files/noto-sans-jp-17-wght-normal.woff2 +0 -0
  37. package/dist/fonts/files/noto-sans-jp-18-wght-normal.woff2 +0 -0
  38. package/dist/fonts/files/noto-sans-jp-19-wght-normal.woff2 +0 -0
  39. package/dist/fonts/files/noto-sans-jp-2-wght-normal.woff2 +0 -0
  40. package/dist/fonts/files/noto-sans-jp-20-wght-normal.woff2 +0 -0
  41. package/dist/fonts/files/noto-sans-jp-21-wght-normal.woff2 +0 -0
  42. package/dist/fonts/files/noto-sans-jp-22-wght-normal.woff2 +0 -0
  43. package/dist/fonts/files/noto-sans-jp-23-wght-normal.woff2 +0 -0
  44. package/dist/fonts/files/noto-sans-jp-24-wght-normal.woff2 +0 -0
  45. package/dist/fonts/files/noto-sans-jp-25-wght-normal.woff2 +0 -0
  46. package/dist/fonts/files/noto-sans-jp-26-wght-normal.woff2 +0 -0
  47. package/dist/fonts/files/noto-sans-jp-27-wght-normal.woff2 +0 -0
  48. package/dist/fonts/files/noto-sans-jp-28-wght-normal.woff2 +0 -0
  49. package/dist/fonts/files/noto-sans-jp-29-wght-normal.woff2 +0 -0
  50. package/dist/fonts/files/noto-sans-jp-3-wght-normal.woff2 +0 -0
  51. package/dist/fonts/files/noto-sans-jp-30-wght-normal.woff2 +0 -0
  52. package/dist/fonts/files/noto-sans-jp-31-wght-normal.woff2 +0 -0
  53. package/dist/fonts/files/noto-sans-jp-32-wght-normal.woff2 +0 -0
  54. package/dist/fonts/files/noto-sans-jp-33-wght-normal.woff2 +0 -0
  55. package/dist/fonts/files/noto-sans-jp-34-wght-normal.woff2 +0 -0
  56. package/dist/fonts/files/noto-sans-jp-35-wght-normal.woff2 +0 -0
  57. package/dist/fonts/files/noto-sans-jp-36-wght-normal.woff2 +0 -0
  58. package/dist/fonts/files/noto-sans-jp-37-wght-normal.woff2 +0 -0
  59. package/dist/fonts/files/noto-sans-jp-38-wght-normal.woff2 +0 -0
  60. package/dist/fonts/files/noto-sans-jp-39-wght-normal.woff2 +0 -0
  61. package/dist/fonts/files/noto-sans-jp-4-wght-normal.woff2 +0 -0
  62. package/dist/fonts/files/noto-sans-jp-40-wght-normal.woff2 +0 -0
  63. package/dist/fonts/files/noto-sans-jp-41-wght-normal.woff2 +0 -0
  64. package/dist/fonts/files/noto-sans-jp-42-wght-normal.woff2 +0 -0
  65. package/dist/fonts/files/noto-sans-jp-43-wght-normal.woff2 +0 -0
  66. package/dist/fonts/files/noto-sans-jp-44-wght-normal.woff2 +0 -0
  67. package/dist/fonts/files/noto-sans-jp-45-wght-normal.woff2 +0 -0
  68. package/dist/fonts/files/noto-sans-jp-46-wght-normal.woff2 +0 -0
  69. package/dist/fonts/files/noto-sans-jp-47-wght-normal.woff2 +0 -0
  70. package/dist/fonts/files/noto-sans-jp-48-wght-normal.woff2 +0 -0
  71. package/dist/fonts/files/noto-sans-jp-49-wght-normal.woff2 +0 -0
  72. package/dist/fonts/files/noto-sans-jp-5-wght-normal.woff2 +0 -0
  73. package/dist/fonts/files/noto-sans-jp-50-wght-normal.woff2 +0 -0
  74. package/dist/fonts/files/noto-sans-jp-51-wght-normal.woff2 +0 -0
  75. package/dist/fonts/files/noto-sans-jp-52-wght-normal.woff2 +0 -0
  76. package/dist/fonts/files/noto-sans-jp-53-wght-normal.woff2 +0 -0
  77. package/dist/fonts/files/noto-sans-jp-54-wght-normal.woff2 +0 -0
  78. package/dist/fonts/files/noto-sans-jp-55-wght-normal.woff2 +0 -0
  79. package/dist/fonts/files/noto-sans-jp-6-wght-normal.woff2 +0 -0
  80. package/dist/fonts/files/noto-sans-jp-60-wght-normal.woff2 +0 -0
  81. package/dist/fonts/files/noto-sans-jp-61-wght-normal.woff2 +0 -0
  82. package/dist/fonts/files/noto-sans-jp-62-wght-normal.woff2 +0 -0
  83. package/dist/fonts/files/noto-sans-jp-63-wght-normal.woff2 +0 -0
  84. package/dist/fonts/files/noto-sans-jp-64-wght-normal.woff2 +0 -0
  85. package/dist/fonts/files/noto-sans-jp-65-wght-normal.woff2 +0 -0
  86. package/dist/fonts/files/noto-sans-jp-66-wght-normal.woff2 +0 -0
  87. package/dist/fonts/files/noto-sans-jp-67-wght-normal.woff2 +0 -0
  88. package/dist/fonts/files/noto-sans-jp-68-wght-normal.woff2 +0 -0
  89. package/dist/fonts/files/noto-sans-jp-69-wght-normal.woff2 +0 -0
  90. package/dist/fonts/files/noto-sans-jp-7-wght-normal.woff2 +0 -0
  91. package/dist/fonts/files/noto-sans-jp-70-wght-normal.woff2 +0 -0
  92. package/dist/fonts/files/noto-sans-jp-71-wght-normal.woff2 +0 -0
  93. package/dist/fonts/files/noto-sans-jp-72-wght-normal.woff2 +0 -0
  94. package/dist/fonts/files/noto-sans-jp-73-wght-normal.woff2 +0 -0
  95. package/dist/fonts/files/noto-sans-jp-74-wght-normal.woff2 +0 -0
  96. package/dist/fonts/files/noto-sans-jp-75-wght-normal.woff2 +0 -0
  97. package/dist/fonts/files/noto-sans-jp-76-wght-normal.woff2 +0 -0
  98. package/dist/fonts/files/noto-sans-jp-77-wght-normal.woff2 +0 -0
  99. package/dist/fonts/files/noto-sans-jp-78-wght-normal.woff2 +0 -0
  100. package/dist/fonts/files/noto-sans-jp-79-wght-normal.woff2 +0 -0
  101. package/dist/fonts/files/noto-sans-jp-8-wght-normal.woff2 +0 -0
  102. package/dist/fonts/files/noto-sans-jp-80-wght-normal.woff2 +0 -0
  103. package/dist/fonts/files/noto-sans-jp-81-wght-normal.woff2 +0 -0
  104. package/dist/fonts/files/noto-sans-jp-82-wght-normal.woff2 +0 -0
  105. package/dist/fonts/files/noto-sans-jp-83-wght-normal.woff2 +0 -0
  106. package/dist/fonts/files/noto-sans-jp-84-wght-normal.woff2 +0 -0
  107. package/dist/fonts/files/noto-sans-jp-85-wght-normal.woff2 +0 -0
  108. package/dist/fonts/files/noto-sans-jp-86-wght-normal.woff2 +0 -0
  109. package/dist/fonts/files/noto-sans-jp-87-wght-normal.woff2 +0 -0
  110. package/dist/fonts/files/noto-sans-jp-88-wght-normal.woff2 +0 -0
  111. package/dist/fonts/files/noto-sans-jp-89-wght-normal.woff2 +0 -0
  112. package/dist/fonts/files/noto-sans-jp-9-wght-normal.woff2 +0 -0
  113. package/dist/fonts/files/noto-sans-jp-90-wght-normal.woff2 +0 -0
  114. package/dist/fonts/files/noto-sans-jp-91-wght-normal.woff2 +0 -0
  115. package/dist/fonts/files/noto-sans-jp-92-wght-normal.woff2 +0 -0
  116. package/dist/fonts/files/noto-sans-jp-93-wght-normal.woff2 +0 -0
  117. package/dist/fonts/files/noto-sans-jp-94-wght-normal.woff2 +0 -0
  118. package/dist/fonts/files/noto-sans-jp-95-wght-normal.woff2 +0 -0
  119. package/dist/fonts/files/noto-sans-jp-96-wght-normal.woff2 +0 -0
  120. package/dist/fonts/files/noto-sans-jp-97-wght-normal.woff2 +0 -0
  121. package/dist/fonts/files/noto-sans-jp-98-wght-normal.woff2 +0 -0
  122. package/dist/fonts/files/noto-sans-jp-99-wght-normal.woff2 +0 -0
  123. package/dist/fonts/noto-sans-jp.css +2506 -0
  124. package/dist/style-entry.d.ts +600 -0
  125. package/dist/style-entry.js +0 -1
  126. package/dist/testing.d.ts +1140 -0
  127. package/dist/testing.js +14 -0
  128. package/dist/theme-bridge.test.ts +59 -0
  129. package/dist/theme.bridge.css +50 -1
  130. package/dist/vite-plugin.d.ts +600 -0
  131. package/dist/vite-plugin.js +2 -4
  132. package/package.json +27 -19
  133. package/skills/app-shell-patterns/SKILL.md +14 -7
  134. package/skills/app-shell-patterns/references/fundamental/components.md +56 -3
  135. package/skills/app-shell-patterns/references/fundamental/design-system.md +216 -162
  136. package/skills/app-shell-patterns/references/migrations.md +167 -0
  137. package/skills/app-shell-patterns/references/patterns/form-composer.md +142 -0
  138. package/skills/app-shell-patterns/references/patterns/form-single-page.md +3 -3
  139. package/skills/app-shell-patterns/references/patterns/form-wizard.md +5 -3
  140. package/skills/app-shell-patterns/references/patterns/interaction-multi-select.md +1 -1
@@ -0,0 +1,1140 @@
1
+ import { FC } from 'react';
2
+ import { JSX } from 'react/jsx-runtime';
3
+ import { LoaderFunctionArgs } from 'react-router';
4
+ import { PropsWithChildren } from 'react';
5
+ import { ReactNode } from 'react';
6
+
7
+ declare type AppInfo = {
8
+ /** Additional app-defined rows shown on the built-in "/__appinfo" page. */
9
+ metadata?: readonly AppInfoEntry[];
10
+ };
11
+
12
+ declare type AppInfoEntry = {
13
+ /** Display label shown on the built-in "/__appinfo" page. */
14
+ label: string;
15
+ /** Primitive value rendered as text. Format complex values before passing them in. */
16
+ value: string | number | boolean | null | undefined;
17
+ };
18
+
19
+ export declare const AppShell: {
20
+ (props: TestAppShellProps): JSX.Element | null;
21
+ WithPages(pages: PageEntry[]): FC<AppShellProps>;
22
+ };
23
+
24
+ /**
25
+ * Props that can be attached to a page component via static field.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * const DashboardPage = () => <div>Dashboard</div>;
30
+ *
31
+ * DashboardPage.appShellPageProps = {
32
+ * meta: { title: "Dashboard", icon: <DashboardIcon /> },
33
+ * guards: [authGuard],
34
+ * } satisfies AppShellPageProps;
35
+ *
36
+ * export default DashboardPage;
37
+ * ```
38
+ */
39
+ declare type AppShellPageProps = {
40
+ /**
41
+ * Metadata for the page used in navigation and breadcrumbs.
42
+ */
43
+ meta?: {
44
+ /**
45
+ * Title of the page displayed in navigation and breadcrumbs.
46
+ * Supports localized strings with translations.
47
+ */
48
+ title?: LocalizedString;
49
+ /**
50
+ * Icon displayed alongside the title in navigation.
51
+ */
52
+ icon?: ReactNode;
53
+ /**
54
+ * Custom breadcrumb segment title for this page.
55
+ * Can be a static string or a function that receives the URL segment.
56
+ */
57
+ breadcrumbTitle?: string | ((segment: string) => string);
58
+ };
59
+ /**
60
+ * Guards to control access to this page.
61
+ * Guards are executed in order. Each page must define its own guards explicitly.
62
+ *
63
+ * @example
64
+ * ```tsx
65
+ * guards: [authGuard, adminGuard]
66
+ * ```
67
+ */
68
+ guards?: Guard[];
69
+ };
70
+
71
+ /**
72
+ * Props for AppShell component.
73
+ *
74
+ * Routes can be configured in two ways:
75
+ * 1. **Automatic (recommended)**: Use the vite-plugin which automatically
76
+ * configures pages via `AppShell.WithPages()`.
77
+ * 2. **Explicit modules**: Pass the `modules` prop for manual configuration.
78
+ *
79
+ * @example
80
+ * ```tsx
81
+ * // Automatic mode (configured by vite-plugin)
82
+ * import { AppShell } from "@tailor-platform/app-shell";
83
+ *
84
+ * <AppShell title="My App">
85
+ * <SidebarLayout />
86
+ * </AppShell>
87
+ * ```
88
+ *
89
+ * @example
90
+ * ```tsx
91
+ * // Explicit modules mode
92
+ * import { AppShell, defineModule } from "@tailor-platform/app-shell";
93
+ *
94
+ * <AppShell title="My App" modules={[...]}>
95
+ * <SidebarLayout />
96
+ * </AppShell>
97
+ * ```
98
+ */
99
+ declare type AppShellProps = SharedAppShellProps & {
100
+ /**
101
+ * Navigation configuration.
102
+ *
103
+ * When using vite-plugin, this is automatically set via `AppShell.WithPages()`.
104
+ * For manual configuration, pass modules directly.
105
+ */
106
+ modules?: Modules;
107
+ };
108
+
109
+ /**
110
+ * Empty interface for module augmentation.
111
+ * Users can extend this to define their own context data type and route parameters.
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * declare module "@tailor-platform/app-shell" {
116
+ * interface AppShellRegister {
117
+ * contextData: {
118
+ * apiClient: ApiClient;
119
+ * currentUser: User;
120
+ * };
121
+ * routeParams: {
122
+ * "/": {};
123
+ * "/dashboard": {};
124
+ * "/orders/:id": { id: string };
125
+ * };
126
+ * }
127
+ * }
128
+ * ```
129
+ */
130
+ declare interface AppShellRegister {
131
+ }
132
+
133
+ /**
134
+ * Color theme — the end-user accessibility preference. `system` follows the OS
135
+ * light/dark setting. Applied to `<html>` as the `.light` / `.dark` class.
136
+ */
137
+ declare type ColorTheme = "light" | "dark" | "system";
138
+
139
+ /**
140
+ * A single search result returned by a `SearchSource`.
141
+ *
142
+ * Selecting a result navigates to `path`.
143
+ */
144
+ declare type CommandPaletteSearchResult = {
145
+ /** Unique key for React reconciliation */
146
+ key: string;
147
+ /** Visible label shown in the palette (e.g. "Order #ORD-1234") */
148
+ label: string;
149
+ /** Optional secondary text (e.g. "山田太郎 - 2024/01/15") */
150
+ description?: string;
151
+ /** Optional icon for this specific result */
152
+ icon?: ReactNode;
153
+ /** Resolved navigation path (e.g. "/orders/abc-123") */
154
+ path: string;
155
+ };
156
+
157
+ declare type CommonPageResource = {
158
+ path: string;
159
+ type: "component";
160
+ meta: {
161
+ title: LocalizedString;
162
+ icon?: ReactNode;
163
+ breadcrumbTitle?: string | ((segment: string) => string);
164
+ };
165
+ };
166
+
167
+ /**
168
+ * Context data type inferred from AppShellRegister.
169
+ * Falls back to Record<string, unknown> if not augmented.
170
+ */
171
+ declare type ContextData = AppShellRegister extends {
172
+ contextData: infer T;
173
+ } ? T : Record<string, unknown>;
174
+
175
+ /**
176
+ * Error boundary element type for route error handling.
177
+ *
178
+ * Pass a JSX element that will render when an error occurs.
179
+ * Use the `useRouteError` hook from react-router to access the error.
180
+ *
181
+ * @example
182
+ * ```tsx
183
+ * import { useRouteError } from "@tailor-platform/app-shell";
184
+ *
185
+ * const MyErrorBoundary = () => {
186
+ * const error = useRouteError() as Error;
187
+ * return <div>Error: {error.message}</div>;
188
+ * };
189
+ *
190
+ * // In config:
191
+ * errorBoundary: <MyErrorBoundary />
192
+ * // Or with props:
193
+ * errorBoundary: <MyErrorBoundary theme="dark" onReport={handleReport} />
194
+ * ```
195
+ */
196
+ declare type ErrorBoundaryComponent = ReactNode;
197
+
198
+ /**
199
+ * Guard function type.
200
+ * Guards are executed in order and stop on the first non-pass result.
201
+ */
202
+ declare type Guard = (ctx: GuardContext) => Promise<GuardResult> | GuardResult;
203
+
204
+ /**
205
+ * Context provided to guard functions
206
+ */
207
+ declare type GuardContext = {
208
+ context: ContextData;
209
+ };
210
+
211
+ /**
212
+ * Result of guard evaluation.
213
+ * Guards can only return one of these constrained result types.
214
+ */
215
+ declare type GuardResult =
216
+ /** Allow access and render the component */
217
+ {
218
+ type: "pass";
219
+ }
220
+ /** Deny access and show 404 */
221
+ | {
222
+ type: "hidden";
223
+ }
224
+ /** Redirect to another path */
225
+ | {
226
+ type: "redirect";
227
+ to: string;
228
+ };
229
+
230
+ declare type LoaderHandler = (args: LoaderFunctionArgs) => Promise<unknown> | unknown;
231
+
232
+ declare type LocalizedString = string | ((locale: string) => string);
233
+
234
+ /**
235
+ * A resource that can be included in the root-level content in the navigation.
236
+ */
237
+ declare type Module = Omit<CommonPageResource, "meta"> & {
238
+ _type: "module";
239
+ component?: () => ReactNode;
240
+ meta: CommonPageResource["meta"] & {
241
+ icon?: ReactNode;
242
+ menuItemClickable: boolean;
243
+ };
244
+ resources: Array<Resource>;
245
+ errorBoundary: ErrorBoundaryComponent;
246
+ guards?: Guard[];
247
+ loader?: LoaderHandler;
248
+ };
249
+
250
+ declare type Modules = Array<Module>;
251
+
252
+ /**
253
+ * A React component that can be used as a page in file-based routing.
254
+ *
255
+ * The component can optionally have an `appShellPageProps` static field
256
+ * for configuring navigation metadata and guards.
257
+ */
258
+ declare type PageComponent = FC & {
259
+ appShellPageProps?: AppShellPageProps;
260
+ };
261
+
262
+ /**
263
+ * A page entry generated by the Vite plugin from file system.
264
+ */
265
+ declare type PageEntry = {
266
+ /**
267
+ * The resolved path for this page (e.g., "/dashboard/orders/:id")
268
+ */
269
+ path: string;
270
+ /**
271
+ * The page component with optional appShellProps
272
+ */
273
+ component: PageComponent;
274
+ };
275
+
276
+ /**
277
+ * A resource that can be included in the sub-content in the root resource.
278
+ *
279
+ * This resource does not have `category` metadata.
280
+ */
281
+ declare type Resource = CommonPageResource & {
282
+ _type: "resource";
283
+ component?: () => ReactNode;
284
+ subResources?: Array<Resource>;
285
+ errorBoundary: ErrorBoundaryComponent;
286
+ guards?: Guard[];
287
+ loader?: LoaderHandler;
288
+ };
289
+
290
+ declare type RouterContainerProps = {
291
+ memory?: false;
292
+ } | {
293
+ memory: true;
294
+ initialEntries: Array<string>;
295
+ };
296
+
297
+ /**
298
+ * An async search source that can be plugged into the CommandPalette.
299
+ *
300
+ * Each source is activated by typing its `prefix` followed by `:` in the
301
+ * search input (e.g. `PO:` for Purchase Orders). The prefix match is
302
+ * case-sensitive.
303
+ */
304
+ declare type SearchSource = {
305
+ /** Mode-switching prefix (e.g. "PO"). Case-sensitive, alphanumeric only. */
306
+ prefix: string;
307
+ /** Heading shown above search results (e.g. "Purchase Orders") */
308
+ title: string;
309
+ /** Optional icon shown next to each result that lacks its own icon */
310
+ icon?: ReactNode;
311
+ /** Async search function. Receives the query after the prefix and an AbortSignal. */
312
+ search: (query: string, options: {
313
+ signal: AbortSignal;
314
+ }) => Promise<CommandPaletteSearchResult[]>;
315
+ };
316
+
317
+ /**
318
+ * Shared props between `AppShellProps` and the internal `WithPages` wrapper.
319
+ *
320
+ * These props are available regardless of whether routes are configured
321
+ * automatically (via vite-plugin) or manually (via `modules` prop).
322
+ */
323
+ declare type SharedAppShellProps = React.PropsWithChildren<{
324
+ /**
325
+ * App shell title.
326
+ *
327
+ * Also used as the suffix of the browser tab title: AppShell keeps
328
+ * `document.title` in sync with the active page as `"<page> · <title>"`
329
+ * (the page part is the current breadcrumb leaf, including any
330
+ * {@link useOverrideBreadcrumb} override). When omitted, the tab shows just
331
+ * the page title.
332
+ */
333
+ title?: string;
334
+ /**
335
+ * App shell icon
336
+ */
337
+ icon?: React.ReactNode;
338
+ /**
339
+ * Browser-tab favicon href. Accepts anything valid on `<link rel="icon">` —
340
+ * a public-path URL (e.g. `/favicon.ico`) or a data URI. AppShell renders the
341
+ * `<link rel="icon">` for you (React hoists it into `<head>`). When omitted,
342
+ * AppShell preserves any favicon link already declared by the host page and
343
+ * only falls back to the bundled Tailor favicon when none exists.
344
+ *
345
+ * If you pass this prop, prefer not to also declare a static
346
+ * `<link rel="icon">` in `index.html`.
347
+ */
348
+ favicon?: string;
349
+ /**
350
+ * Additional application metadata shown on the built-in `/__appinfo` page.
351
+ *
352
+ * AppShell always includes its own version there; use this prop to append
353
+ * app-defined rows such as environment, release, or commit.
354
+ */
355
+ appInfo?: AppInfo;
356
+ /**
357
+ * Base path for the app shell
358
+ */
359
+ basePath?: string;
360
+ /**
361
+ * A component to be rendered at the root level of AppShell.
362
+ * Use guards with redirectTo() for redirects.
363
+ *
364
+ * @example
365
+ * ```tsx
366
+ * rootComponent: () => <DashboardHome />
367
+ * ```
368
+ */
369
+ rootComponent?: () => React.ReactNode;
370
+ /**
371
+ * Guards for the root route.
372
+ *
373
+ * When using file-based routing, this is automatically set from
374
+ * the root page's guards via `AppShell.WithPages()`.
375
+ *
376
+ * @example
377
+ * ```tsx
378
+ * import { redirectTo } from "@tailor-platform/app-shell";
379
+ *
380
+ * <AppShell
381
+ * modules={[...]}
382
+ * rootGuards={[() => redirectTo("/dashboard")]}
383
+ * />
384
+ * ```
385
+ */
386
+ rootGuards?: Guard[];
387
+ /**
388
+ * Settings resources to be included in the settings menu
389
+ */
390
+ settingsResources?: Array<Resource>;
391
+ /**
392
+ * Locale code used for built-in UI strings.
393
+ *
394
+ * If not provided, auto-detects from browser preferences.
395
+ * No browser locale information avilable, "en" used as default.
396
+ */
397
+ locale?: string;
398
+ /**
399
+ * IANA timezone (e.g. "America/Los_Angeles") used by date/time components
400
+ * as the default for resolving "today" and for `ZonedDateTime` values.
401
+ *
402
+ * If not provided, date/time components fall back to the user's local timezone.
403
+ */
404
+ timeZone?: string;
405
+ /**
406
+ * Global error boundary component applied to all routes.
407
+ *
408
+ * When an error occurs in any route component, this component will render.
409
+ * Module and resource-level error boundaries take precedence over this.
410
+ * Use the `useRouteError` hook to access error details within the component.
411
+ *
412
+ * @example
413
+ * ```tsx
414
+ * import { useRouteError } from "@tailor-platform/app-shell";
415
+ *
416
+ * const GlobalErrorBoundary = () => {
417
+ * const error = useRouteError() as Error;
418
+ * return (
419
+ * <div>
420
+ * <h1>Something went wrong</h1>
421
+ * <p>{error.message}</p>
422
+ * </div>
423
+ * );
424
+ * };
425
+ *
426
+ * <AppShell
427
+ * modules: [...],
428
+ * errorBoundary: <GlobalErrorBoundary />,
429
+ * />
430
+ * ```
431
+ */
432
+ errorBoundary?: ErrorBoundaryComponent;
433
+ /**
434
+ * Custom context data accessible from guards and components.
435
+ *
436
+ * Use module augmentation to define the type of context data:
437
+ *
438
+ * @example
439
+ * ```typescript
440
+ * // types.d.ts
441
+ * declare module "@tailor-platform/app-shell" {
442
+ * interface AppShellRegister {
443
+ * contextData: {
444
+ * apiClient: ApiClient;
445
+ * currentUser: User;
446
+ * };
447
+ * }
448
+ * }
449
+ *
450
+ * // App.tsx
451
+ * <AppShell
452
+ * modules={modules}
453
+ * contextData={{ apiClient, currentUser }}
454
+ * />
455
+ * ```
456
+ */
457
+ contextData?: ContextData;
458
+ /**
459
+ * Async search sources for the built-in CommandPalette.
460
+ *
461
+ * The CommandPalette (opened via Cmd+K / Ctrl+K, or the sidebar Search
462
+ * button) always searches pages and contextual actions. When
463
+ * `searchSources` is also provided, those async sources are available
464
+ * as prefix-activated search modes.
465
+ *
466
+ * Note: `DefaultSidebar` always renders a Search entry at the top of
467
+ * the navigation menu, regardless of whether this prop is supplied.
468
+ *
469
+ * @example
470
+ * ```tsx
471
+ * <AppShell
472
+ * modules={modules}
473
+ * searchSources={[
474
+ * {
475
+ * prefix: "PO",
476
+ * title: "Purchase Orders",
477
+ * search: async (query, { signal }) => {
478
+ * const results = await api.searchOrders(query, { signal });
479
+ * return results.map((o) => ({
480
+ * key: o.id,
481
+ * label: o.number,
482
+ * path: `/orders/${o.id}`,
483
+ * }));
484
+ * },
485
+ * },
486
+ * ]}
487
+ * />
488
+ * ```
489
+ */
490
+ searchSources?: readonly SearchSource[];
491
+ /**
492
+ * Initial color mode before any value is loaded from localStorage (`appshell-ui-theme`).
493
+ * This is the end-user accessibility preference; does not replace a stored preference.
494
+ *
495
+ * One of **`light`**, **`dark`**, or **`system`** (follows the OS).
496
+ *
497
+ * @default "system"
498
+ */
499
+ defaultColorTheme?: ColorTheme;
500
+ }>;
501
+
502
+ /**
503
+ * AppShell's props plus the routing mode. Memory routing is absent from the
504
+ * public {@link AppShellProps} so it cannot be shipped by accident; tests reach
505
+ * it via `@tailor-platform/app-shell/testing`, which re-exports this as
506
+ * `TestAppShellProps`.
507
+ */
508
+ export declare type TestAppShellProps = AppShellProps & RouterContainerProps;
509
+
510
+ /**
511
+ * Router context for unit-testing a single component, without booting the whole
512
+ * shell. For a page or integration test, mount `AppShell` with `memory`
513
+ * instead, so the test exercises AppShell's own router.
514
+ *
515
+ * ```tsx
516
+ * render(
517
+ * <TestRouter path="/orders/:id" initialEntries={["/orders/A42"]}>
518
+ * <OrderBadge />
519
+ * </TestRouter>,
520
+ * );
521
+ * ```
522
+ */
523
+ export declare const TestRouter: ({ children, initialEntries, initialIndex, path, }: TestRouterProps) => JSX.Element;
524
+
525
+ export declare type TestRouterProps = PropsWithChildren<{
526
+ /** History stack; the last entry is the current location. Defaults to `["/"]`. */
527
+ initialEntries?: Array<string>;
528
+ /** Index into `initialEntries` to start at. Defaults to the last entry. */
529
+ initialIndex?: number;
530
+ /**
531
+ * Route pattern to match the children against, e.g. `"/orders/:id"`.
532
+ *
533
+ * Required for `useParams`, `useMatch`, or relative `<Link>` targets: a router
534
+ * on its own matches nothing, so without this `useParams()` is `{}` even when
535
+ * `initialEntries` holds a URL that looks like it should match.
536
+ */
537
+ path?: string;
538
+ }>;
539
+
540
+ export { }
541
+
542
+
543
+ declare namespace Root {
544
+ var displayName: string;
545
+ }
546
+
547
+
548
+ declare namespace Title {
549
+ var displayName: string;
550
+ }
551
+
552
+
553
+ declare namespace Description {
554
+ var displayName: string;
555
+ }
556
+
557
+
558
+ declare namespace Root {
559
+ var displayName: string;
560
+ }
561
+
562
+
563
+ declare namespace Image {
564
+ var displayName: string;
565
+ }
566
+
567
+
568
+ declare namespace Fallback {
569
+ var displayName: string;
570
+ }
571
+
572
+
573
+ declare namespace Root {
574
+ var displayName: string;
575
+ }
576
+
577
+
578
+ declare namespace Viewport {
579
+ var displayName: string;
580
+ }
581
+
582
+
583
+ declare namespace Row {
584
+ var displayName: string;
585
+ }
586
+
587
+
588
+ declare namespace Interval {
589
+ var displayName: string;
590
+ }
591
+
592
+
593
+ declare namespace TimelineLink {
594
+ var displayName: string;
595
+ }
596
+
597
+
598
+ declare namespace Root {
599
+ var displayName: string;
600
+ }
601
+
602
+
603
+ declare namespace Trigger {
604
+ var displayName: string;
605
+ }
606
+
607
+
608
+ declare namespace Content {
609
+ var displayName: string;
610
+ }
611
+
612
+
613
+ declare namespace Item {
614
+ var displayName: string;
615
+ }
616
+
617
+
618
+ declare namespace LinkItem {
619
+ var displayName: string;
620
+ }
621
+
622
+
623
+ declare namespace CheckboxItem {
624
+ var displayName: string;
625
+ }
626
+
627
+
628
+ declare namespace CheckboxItemIndicator {
629
+ var displayName: string;
630
+ }
631
+
632
+
633
+ declare namespace RadioItem {
634
+ var displayName: string;
635
+ }
636
+
637
+
638
+ declare namespace RadioItemIndicator {
639
+ var displayName: string;
640
+ }
641
+
642
+
643
+ declare namespace RadioGroup {
644
+ var displayName: string;
645
+ }
646
+
647
+
648
+ declare namespace Group {
649
+ var displayName: string;
650
+ }
651
+
652
+
653
+ declare namespace GroupLabel {
654
+ var displayName: string;
655
+ }
656
+
657
+
658
+ declare namespace MenuSeparator {
659
+ var displayName: string;
660
+ }
661
+
662
+
663
+ declare namespace SubmenuRoot {
664
+ var displayName: string;
665
+ }
666
+
667
+
668
+ declare namespace SubmenuTrigger {
669
+ var displayName: string;
670
+ }
671
+
672
+
673
+ declare namespace Root {
674
+ var displayName: string;
675
+ }
676
+
677
+
678
+ declare namespace List {
679
+ var displayName: string;
680
+ }
681
+
682
+
683
+ declare namespace Tab {
684
+ var displayName: string;
685
+ }
686
+
687
+
688
+ declare namespace Panel {
689
+ var displayName: string;
690
+ }
691
+
692
+
693
+ declare namespace Root {
694
+ var displayName: string;
695
+ }
696
+
697
+
698
+ declare namespace Trigger {
699
+ var displayName: string;
700
+ }
701
+
702
+
703
+ declare namespace Close {
704
+ var displayName: string;
705
+ }
706
+
707
+
708
+ declare namespace Content {
709
+ var displayName: string;
710
+ }
711
+
712
+
713
+ declare namespace Header {
714
+ var displayName: string;
715
+ }
716
+
717
+
718
+ declare namespace Footer {
719
+ var displayName: string;
720
+ }
721
+
722
+
723
+ declare namespace Title {
724
+ var displayName: string;
725
+ }
726
+
727
+
728
+ declare namespace Description {
729
+ var displayName: string;
730
+ }
731
+
732
+
733
+ declare namespace Root {
734
+ var displayName: string;
735
+ }
736
+
737
+
738
+ declare namespace Header {
739
+ var displayName: string;
740
+ }
741
+
742
+
743
+ declare namespace Body {
744
+ var displayName: string;
745
+ }
746
+
747
+
748
+ declare namespace Footer {
749
+ var displayName: string;
750
+ }
751
+
752
+
753
+ declare namespace Row {
754
+ var displayName: string;
755
+ }
756
+
757
+
758
+ declare namespace Head {
759
+ var displayName: string;
760
+ }
761
+
762
+
763
+ declare namespace Cell {
764
+ var displayName: string;
765
+ }
766
+
767
+
768
+ declare namespace Caption {
769
+ var displayName: string;
770
+ }
771
+
772
+
773
+ declare namespace Provider {
774
+ var displayName: string;
775
+ }
776
+
777
+
778
+ declare namespace Root {
779
+ var displayName: string;
780
+ }
781
+
782
+
783
+ declare namespace Trigger {
784
+ var displayName: string;
785
+ }
786
+
787
+
788
+ declare namespace Content {
789
+ var displayName: string;
790
+ }
791
+
792
+
793
+ declare namespace Root {
794
+ var displayName: string;
795
+ }
796
+
797
+
798
+ declare namespace Header {
799
+ var displayName: string;
800
+ }
801
+
802
+
803
+ declare namespace Content {
804
+ var displayName: string;
805
+ }
806
+
807
+
808
+ declare namespace SelectRoot {
809
+ var displayName: string;
810
+ }
811
+
812
+
813
+ declare namespace SelectTrigger {
814
+ var displayName: string;
815
+ }
816
+
817
+
818
+ declare namespace SelectValue {
819
+ var displayName: string;
820
+ }
821
+
822
+
823
+ declare namespace SelectContent {
824
+ var displayName: string;
825
+ }
826
+
827
+
828
+ declare namespace SelectItem {
829
+ var displayName: string;
830
+ }
831
+
832
+
833
+ declare namespace SelectGroup {
834
+ var displayName: string;
835
+ }
836
+
837
+
838
+ declare namespace SelectGroupLabel {
839
+ var displayName: string;
840
+ }
841
+
842
+
843
+ declare namespace SelectSeparator {
844
+ var displayName: string;
845
+ }
846
+
847
+
848
+ declare namespace Root {
849
+ var displayName: string;
850
+ }
851
+
852
+
853
+ declare namespace Trigger {
854
+ var displayName: string;
855
+ }
856
+
857
+
858
+ declare namespace Close {
859
+ var displayName: string;
860
+ }
861
+
862
+
863
+ declare namespace Content {
864
+ var displayName: string;
865
+ }
866
+
867
+
868
+ declare namespace Header {
869
+ var displayName: string;
870
+ }
871
+
872
+
873
+ declare namespace Footer {
874
+ var displayName: string;
875
+ }
876
+
877
+
878
+ declare namespace Title {
879
+ var displayName: string;
880
+ }
881
+
882
+
883
+ declare namespace Description {
884
+ var displayName: string;
885
+ }
886
+
887
+
888
+ declare namespace ComboboxRoot {
889
+ var displayName: string;
890
+ }
891
+
892
+
893
+ declare namespace ComboboxInput {
894
+ var displayName: string;
895
+ }
896
+
897
+
898
+ declare namespace ComboboxTrigger {
899
+ var displayName: string;
900
+ }
901
+
902
+
903
+ declare namespace ComboboxInputGroup {
904
+ var displayName: string;
905
+ }
906
+
907
+
908
+ declare namespace ComboboxContent {
909
+ var displayName: string;
910
+ }
911
+
912
+
913
+ declare namespace ComboboxList {
914
+ var displayName: string;
915
+ }
916
+
917
+
918
+ declare namespace ComboboxItem {
919
+ var displayName: string;
920
+ }
921
+
922
+
923
+ declare namespace ComboboxEmpty {
924
+ var displayName: string;
925
+ }
926
+
927
+
928
+ declare namespace ComboboxGroup {
929
+ var displayName: string;
930
+ }
931
+
932
+
933
+ declare namespace ComboboxGroupLabel {
934
+ var displayName: string;
935
+ }
936
+
937
+
938
+ declare namespace ComboboxClear {
939
+ var displayName: string;
940
+ }
941
+
942
+
943
+ declare namespace ComboboxChips {
944
+ var displayName: string;
945
+ }
946
+
947
+
948
+ declare namespace ComboboxChip {
949
+ var displayName: string;
950
+ }
951
+
952
+
953
+ declare namespace ComboboxChipRemove {
954
+ var displayName: string;
955
+ }
956
+
957
+
958
+ declare namespace ComboboxValue {
959
+ var displayName: string;
960
+ }
961
+
962
+
963
+ declare namespace ComboboxStatus {
964
+ var displayName: string;
965
+ }
966
+
967
+
968
+ declare namespace ComboboxCollection {
969
+ var displayName: string;
970
+ }
971
+
972
+
973
+ declare namespace Root {
974
+ var displayName: string;
975
+ }
976
+
977
+
978
+ declare namespace Label {
979
+ var displayName: string;
980
+ }
981
+
982
+
983
+ declare namespace Control {
984
+ var displayName: string;
985
+ }
986
+
987
+
988
+ declare namespace Description {
989
+ var displayName: string;
990
+ }
991
+
992
+
993
+ declare namespace Error {
994
+ var displayName: string;
995
+ }
996
+
997
+
998
+ declare namespace Validity {
999
+ var displayName: string;
1000
+ }
1001
+
1002
+
1003
+ declare namespace AutocompleteRoot {
1004
+ var displayName: string;
1005
+ }
1006
+
1007
+
1008
+ declare namespace AutocompleteValue {
1009
+ var displayName: string;
1010
+ }
1011
+
1012
+
1013
+ declare namespace AutocompleteInput {
1014
+ var displayName: string;
1015
+ }
1016
+
1017
+
1018
+ declare namespace AutocompleteTrigger {
1019
+ var displayName: string;
1020
+ }
1021
+
1022
+
1023
+ declare namespace AutocompleteInputGroup {
1024
+ var displayName: string;
1025
+ }
1026
+
1027
+
1028
+ declare namespace AutocompleteContent {
1029
+ var displayName: string;
1030
+ }
1031
+
1032
+
1033
+ declare namespace AutocompleteList {
1034
+ var displayName: string;
1035
+ }
1036
+
1037
+
1038
+ declare namespace AutocompleteItem {
1039
+ var displayName: string;
1040
+ }
1041
+
1042
+
1043
+ declare namespace AutocompleteEmpty {
1044
+ var displayName: string;
1045
+ }
1046
+
1047
+
1048
+ declare namespace AutocompleteClear {
1049
+ var displayName: string;
1050
+ }
1051
+
1052
+
1053
+ declare namespace AutocompleteGroup {
1054
+ var displayName: string;
1055
+ }
1056
+
1057
+
1058
+ declare namespace AutocompleteGroupLabel {
1059
+ var displayName: string;
1060
+ }
1061
+
1062
+
1063
+ declare namespace AutocompleteCollection {
1064
+ var displayName: string;
1065
+ }
1066
+
1067
+
1068
+ declare namespace AutocompleteStatus {
1069
+ var displayName: string;
1070
+ }
1071
+
1072
+
1073
+ declare namespace AutocompleteStandalone {
1074
+ var displayName: string;
1075
+ }
1076
+
1077
+
1078
+ declare namespace AutocompleteAsyncStandalone {
1079
+ var displayName: string;
1080
+ }
1081
+
1082
+
1083
+ declare namespace Root {
1084
+ var displayName: string;
1085
+ }
1086
+
1087
+
1088
+ declare namespace Legend {
1089
+ var displayName: string;
1090
+ }
1091
+
1092
+
1093
+ declare namespace DataTableRoot {
1094
+ var displayName: string;
1095
+ }
1096
+
1097
+
1098
+ declare namespace DataTableTable {
1099
+ var displayName: string;
1100
+ }
1101
+
1102
+
1103
+ declare namespace DataTableFooter {
1104
+ var displayName: string;
1105
+ }
1106
+
1107
+
1108
+ declare namespace Root {
1109
+ var displayName: string;
1110
+ }
1111
+
1112
+
1113
+ declare namespace Items {
1114
+ var displayName: string;
1115
+ }
1116
+
1117
+
1118
+ declare namespace Item {
1119
+ var displayName: string;
1120
+ }
1121
+
1122
+
1123
+ declare namespace DataTableToolbar {
1124
+ var displayName: string;
1125
+ }
1126
+
1127
+
1128
+ declare namespace DataTableFilters {
1129
+ var displayName: string;
1130
+ }
1131
+
1132
+
1133
+ declare namespace AsyncErrorState {
1134
+ var displayName: string;
1135
+ }
1136
+
1137
+
1138
+ declare namespace DataTableColumnSettings {
1139
+ var displayName: string;
1140
+ }