@judo/app-shell 0.1.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 (81) hide show
  1. package/LICENSE +277 -0
  2. package/README.md +186 -0
  3. package/dist/AppShell.d.ts +15 -0
  4. package/dist/AppShell.d.ts.map +1 -0
  5. package/dist/actors/ActorSelector.d.ts +8 -0
  6. package/dist/actors/ActorSelector.d.ts.map +1 -0
  7. package/dist/errors/AppErrorBoundary.d.ts +20 -0
  8. package/dist/errors/AppErrorBoundary.d.ts.map +1 -0
  9. package/dist/hooks/use-navigation-badge.d.ts +8 -0
  10. package/dist/hooks/use-navigation-badge.d.ts.map +1 -0
  11. package/dist/hooks/use-theme.d.ts +33 -0
  12. package/dist/hooks/use-theme.d.ts.map +1 -0
  13. package/dist/index.d.ts +38 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +2068 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/layout/AppBar.d.ts +19 -0
  18. package/dist/layout/AppBar.d.ts.map +1 -0
  19. package/dist/layout/AppShellLayout.d.ts +14 -0
  20. package/dist/layout/AppShellLayout.d.ts.map +1 -0
  21. package/dist/layout/Breadcrumbs.d.ts +8 -0
  22. package/dist/layout/Breadcrumbs.d.ts.map +1 -0
  23. package/dist/layout/Footer.d.ts +9 -0
  24. package/dist/layout/Footer.d.ts.map +1 -0
  25. package/dist/layout/PageDialogHost.d.ts +9 -0
  26. package/dist/layout/PageDialogHost.d.ts.map +1 -0
  27. package/dist/layout/layout-constants.d.ts +8 -0
  28. package/dist/layout/layout-constants.d.ts.map +1 -0
  29. package/dist/locale/LocaleSwitcher.d.ts +16 -0
  30. package/dist/locale/LocaleSwitcher.d.ts.map +1 -0
  31. package/dist/navigation/HorizontalNavigation.d.ts +14 -0
  32. package/dist/navigation/HorizontalNavigation.d.ts.map +1 -0
  33. package/dist/navigation/HorizontalNavigationItem.d.ts +20 -0
  34. package/dist/navigation/HorizontalNavigationItem.d.ts.map +1 -0
  35. package/dist/navigation/NavigationDrawer.d.ts +13 -0
  36. package/dist/navigation/NavigationDrawer.d.ts.map +1 -0
  37. package/dist/navigation/NavigationItemRenderer.d.ts +19 -0
  38. package/dist/navigation/NavigationItemRenderer.d.ts.map +1 -0
  39. package/dist/navigation/dashboard-utils.d.ts +8 -0
  40. package/dist/navigation/dashboard-utils.d.ts.map +1 -0
  41. package/dist/navigation/navigation-utils.d.ts +41 -0
  42. package/dist/navigation/navigation-utils.d.ts.map +1 -0
  43. package/dist/navigation/use-menu-operation-dispatch.d.ts +26 -0
  44. package/dist/navigation/use-menu-operation-dispatch.d.ts.map +1 -0
  45. package/dist/routes/DefaultGuestPage.d.ts +10 -0
  46. package/dist/routes/DefaultGuestPage.d.ts.map +1 -0
  47. package/dist/routes/DefaultSettingsPage.d.ts +9 -0
  48. package/dist/routes/DefaultSettingsPage.d.ts.map +1 -0
  49. package/dist/routes/PageRoute.d.ts +13 -0
  50. package/dist/routes/PageRoute.d.ts.map +1 -0
  51. package/dist/routes/RedirectPage.d.ts +12 -0
  52. package/dist/routes/RedirectPage.d.ts.map +1 -0
  53. package/dist/routes/generate-routes.d.ts +24 -0
  54. package/dist/routes/generate-routes.d.ts.map +1 -0
  55. package/dist/runtime/DefaultErrorScreen.d.ts +11 -0
  56. package/dist/runtime/DefaultErrorScreen.d.ts.map +1 -0
  57. package/dist/runtime/DefaultLoadingScreen.d.ts +5 -0
  58. package/dist/runtime/DefaultLoadingScreen.d.ts.map +1 -0
  59. package/dist/runtime/JudoRuntime.d.ts +27 -0
  60. package/dist/runtime/JudoRuntime.d.ts.map +1 -0
  61. package/dist/runtime/PrincipalBridge.d.ts +14 -0
  62. package/dist/runtime/PrincipalBridge.d.ts.map +1 -0
  63. package/dist/runtime/index.d.ts +5 -0
  64. package/dist/runtime/index.d.ts.map +1 -0
  65. package/dist/runtime/types.d.ts +308 -0
  66. package/dist/runtime/types.d.ts.map +1 -0
  67. package/dist/theme/ThemeProvider.d.ts +21 -0
  68. package/dist/theme/ThemeProvider.d.ts.map +1 -0
  69. package/dist/theme/ThemeToggle.d.ts +11 -0
  70. package/dist/theme/ThemeToggle.d.ts.map +1 -0
  71. package/dist/theme/density.d.ts +19 -0
  72. package/dist/theme/density.d.ts.map +1 -0
  73. package/dist/theme/judo-theme-factory.d.ts +29 -0
  74. package/dist/theme/judo-theme-factory.d.ts.map +1 -0
  75. package/dist/theme/presets.d.ts +51 -0
  76. package/dist/theme/presets.d.ts.map +1 -0
  77. package/dist/user/DefaultHeroComponent.d.ts +11 -0
  78. package/dist/user/DefaultHeroComponent.d.ts.map +1 -0
  79. package/dist/user/UserMenu.d.ts +8 -0
  80. package/dist/user/UserMenu.d.ts.map +1 -0
  81. package/package.json +99 -0
@@ -0,0 +1,308 @@
1
+ import { CustomizationsConfig, MenuLayout } from '@judo/model-api';
2
+ import { ReactNode } from 'react';
3
+ /**
4
+ * Model loading configuration.
5
+ */
6
+ export interface ModelConfig {
7
+ /**
8
+ * Model source - URL path, full URL, or async loader function.
9
+ * @example '/models/app.model'
10
+ * @example 'https://api.example.com/model'
11
+ * @example () => fetch('/api/model').then(r => r.text())
12
+ */
13
+ source?: string | (() => Promise<string>);
14
+ /**
15
+ * Initial application to activate (by name).
16
+ * Defaults to first application in model.
17
+ */
18
+ initialApplication?: string;
19
+ }
20
+ /**
21
+ * Authentication configuration.
22
+ */
23
+ export interface AuthConfig {
24
+ /**
25
+ * Skip authentication entirely.
26
+ * Useful for development without OIDC server.
27
+ * @default false
28
+ */
29
+ skip?: boolean;
30
+ /**
31
+ * OIDC provider configuration.
32
+ * Only `issuerUrl` is required — all other fields have sensible defaults.
33
+ */
34
+ oidc?: {
35
+ /**
36
+ * OIDC issuer URL (e.g., Keycloak base URL).
37
+ * The realm path is appended automatically from the model's Authentication.realm.
38
+ * The client ID is derived from the active actor's Application.name.
39
+ *
40
+ * @example 'https://sso.example.com'
41
+ * @example 'http://localhost:8080'
42
+ */
43
+ issuerUrl: string;
44
+ /** OAuth scopes. @default 'openid profile email' */
45
+ scope?: string;
46
+ /** Redirect URI after login. @default window.location.origin */
47
+ redirectUri?: string;
48
+ /** Redirect URI after logout. @default window.location.origin */
49
+ postLogoutRedirectUri?: string;
50
+ };
51
+ }
52
+ /**
53
+ * Backend API configuration.
54
+ */
55
+ export interface ApiConfig {
56
+ /** Base URL for REST API calls */
57
+ baseUrl?: string;
58
+ /** Request timeout in milliseconds */
59
+ timeout?: number;
60
+ /** Custom headers to include in all requests */
61
+ headers?: Record<string, string>;
62
+ }
63
+ /**
64
+ * Theme configuration.
65
+ */
66
+ export interface ThemeConfig {
67
+ /**
68
+ * Default color mode.
69
+ * @default 'system'
70
+ */
71
+ defaultMode?: "light" | "dark" | "system";
72
+ /**
73
+ * LocalStorage key for persisting theme preference.
74
+ * Set to null to disable persistence.
75
+ * @default 'judo-theme-mode'
76
+ */
77
+ persistKey?: string | null;
78
+ /**
79
+ * Primary color override.
80
+ * @deprecated Use muiThemeOptions.palette.primary instead
81
+ */
82
+ primaryColor?: string;
83
+ /**
84
+ * Secondary color override.
85
+ * @deprecated Use muiThemeOptions.palette.secondary instead
86
+ */
87
+ secondaryColor?: string;
88
+ /**
89
+ * MUI theme options to merge with defaults.
90
+ * Provides full access to MUI's createTheme() API including typography,
91
+ * components, spacing, shape, transitions, and more.
92
+ *
93
+ * @see https://mui.com/material-ui/customization/theming/
94
+ */
95
+ muiThemeOptions?: Record<string, unknown>;
96
+ /**
97
+ * UI density preset controlling spacing, font sizes, and component sizes.
98
+ *
99
+ * - `compact` — tight spacing, smaller controls; ideal for data-heavy views.
100
+ * - `comfortable` — default MUI sizing (no density overrides applied).
101
+ * - `standard` — generous spacing, larger touch targets.
102
+ *
103
+ * Density options are applied as a base layer; `muiThemeOptions` can still
104
+ * override individual values.
105
+ *
106
+ * @default 'comfortable'
107
+ */
108
+ density?: "compact" | "comfortable" | "standard";
109
+ /**
110
+ * Named theme preset providing curated primary/secondary color pairs and
111
+ * background tints for a polished, modern look.
112
+ *
113
+ * Built-in presets: `'corporate'`, `'ocean'`, `'slate'`, `'indigo'`, `'forest'`, `'royal'`.
114
+ *
115
+ * Explicit `primaryColor`/`secondaryColor` override the preset values.
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * { preset: 'corporate' }
120
+ * { preset: 'ocean', primaryColor: '#custom' } // keeps ocean secondary
121
+ * ```
122
+ */
123
+ preset?: "corporate" | "ocean" | "slate" | "indigo" | "forest" | "royal" | (string & {});
124
+ }
125
+ /**
126
+ * Feature toggles.
127
+ */
128
+ export interface FeaturesConfig {
129
+ /**
130
+ * Enable navigation guards (unsaved changes, session timeout).
131
+ * @default true
132
+ */
133
+ guards?: boolean;
134
+ /**
135
+ * Force showTotalCount for all lazy (non-eager) tables.
136
+ * When enabled, all lazy tables will request total row count from backend,
137
+ * overriding individual table's showTotalCount setting.
138
+ * @default false
139
+ */
140
+ forceShowTotalCountForLazyTables?: boolean;
141
+ /**
142
+ * Enable inline header filters in DataGrid tables.
143
+ * Requires MUI X Pro license (`muiProLicenseKey` must be set).
144
+ * When enabled, each column header shows an inline filter input,
145
+ * replacing the standalone filter panel for a more streamlined UX.
146
+ * @default false
147
+ */
148
+ headerFilters?: boolean;
149
+ }
150
+ /**
151
+ * Internationalization configuration.
152
+ */
153
+ export interface I18nConfig {
154
+ /**
155
+ * Supported locales. Keys are ISO locale codes, values are display labels.
156
+ * If not provided, a single "en-US" locale is assumed.
157
+ *
158
+ * @example { "en-US": "English", "hu-HU": "Magyar" }
159
+ */
160
+ locales?: Record<string, string>;
161
+ /**
162
+ * Async locale loader function.
163
+ * Called with the active locale code; must return a flat key→value translation map
164
+ * compatible with i18next resource format.
165
+ *
166
+ * If not provided, translations are skipped and model labels are used as-is.
167
+ *
168
+ * @example
169
+ * ```ts
170
+ * localeLoader: (locale) =>
171
+ * fetch(`/locales/${locale}.json`).then(r => r.json())
172
+ * ```
173
+ */
174
+ localeLoader?: (locale: string) => Promise<Record<string, string>>;
175
+ /**
176
+ * Translation key map: maps element sourceId (xmi:id) to human-readable
177
+ * translation key path.
178
+ *
179
+ * Generated by `@judo/codegen` as `TRANSLATION_KEY_MAP` in
180
+ * `_translation-key-map.ts`. When provided, `useModelLabel()` uses
181
+ * these tree-path keys (e.g., `"PageName.container.input"`) instead
182
+ * of the legacy `"elementType.sourceId.property"` format.
183
+ */
184
+ translationKeyMap?: Record<string, string>;
185
+ /**
186
+ * When true, the selected locale is persisted to localStorage and
187
+ * restored automatically on subsequent visits.
188
+ *
189
+ * @default false
190
+ */
191
+ persistLocale?: boolean;
192
+ }
193
+ /**
194
+ * Router configuration.
195
+ */
196
+ export interface RouterConfig {
197
+ /**
198
+ * Router type to use.
199
+ * @default 'browser'
200
+ */
201
+ type?: "browser" | "hash" | "memory";
202
+ /**
203
+ * Base path for all routes.
204
+ * @default '/'
205
+ */
206
+ basePath?: string;
207
+ }
208
+ /**
209
+ * Complete runtime configuration.
210
+ * All properties are optional with sensible defaults.
211
+ */
212
+ export interface JudoRuntimeConfig {
213
+ /** Model loading configuration */
214
+ model?: ModelConfig;
215
+ /** Authentication configuration */
216
+ auth?: AuthConfig;
217
+ /** Backend API configuration */
218
+ api?: ApiConfig;
219
+ /** Theme configuration */
220
+ theme?: ThemeConfig;
221
+ /** Feature toggles */
222
+ features?: FeaturesConfig;
223
+ /** Internationalization configuration */
224
+ i18n?: I18nConfig;
225
+ /** Router configuration */
226
+ router?: RouterConfig;
227
+ /**
228
+ * MUI X Pro license key.
229
+ * When set, the runtime will activate MUI Pro and automatically provide
230
+ * Pro variants of MUI X components (DataGridPro, DatePickerPro, etc.).
231
+ * Requires `@mui/x-data-grid-pro` and `@mui/x-license` packages to be installed.
232
+ */
233
+ muiProLicenseKey?: string;
234
+ /**
235
+ * Menu layout override.
236
+ * When set, overrides the Application model's `defaultMenuLayout`.
237
+ * @default undefined (uses model value, falling back to VERTICAL)
238
+ */
239
+ menuLayout?: MenuLayout;
240
+ }
241
+ /**
242
+ * JudoRuntime component props.
243
+ */
244
+ export interface JudoRuntimeProps {
245
+ /**
246
+ * Runtime configuration object.
247
+ * Can also pass modelSource directly as shorthand.
248
+ */
249
+ config?: JudoRuntimeConfig;
250
+ /**
251
+ * Shorthand for config.model.source.
252
+ * Use this for minimal setup.
253
+ */
254
+ modelSource?: string | (() => Promise<string>);
255
+ /**
256
+ * Custom logo component for app bar.
257
+ */
258
+ logo?: ReactNode;
259
+ /**
260
+ * Additional content for app bar (right side).
261
+ */
262
+ appBarExtra?: ReactNode;
263
+ /**
264
+ * Loading component shown during model load.
265
+ * @default Built-in loading screen
266
+ */
267
+ loadingComponent?: ReactNode;
268
+ /**
269
+ * Error component shown on load failure.
270
+ * @default Built-in error screen with retry
271
+ */
272
+ errorComponent?: ReactNode | ((error: Error, retry: () => void) => ReactNode);
273
+ /**
274
+ * Children to render instead of default routes.
275
+ * Advanced: only use if you need custom routing.
276
+ */
277
+ children?: ReactNode;
278
+ /**
279
+ * Customizations configuration for extensibility.
280
+ * Provides custom component implementations, action lifecycle overrides,
281
+ * and visual property overrides.
282
+ *
283
+ * Use the generated createCustomizations() factory for type-safe bindings,
284
+ * or build CustomizationsConfig manually.
285
+ *
286
+ * @example
287
+ * ```tsx
288
+ * import { createCustomizations } from './generated';
289
+ *
290
+ * <JudoRuntime
291
+ * modelSource="/models/app.model"
292
+ * customizations={createCustomizations({
293
+ * pages: { UserListPage: useUserListPageActions },
294
+ * components: { OrderSummary: OrderSummaryWidget },
295
+ * })}
296
+ * />
297
+ * ```
298
+ */
299
+ customizations?: CustomizationsConfig;
300
+ }
301
+ /**
302
+ * Internal state for JudoRuntime.
303
+ */
304
+ export interface JudoRuntimeState {
305
+ phase: "initializing" | "loading" | "ready" | "error";
306
+ error: Error | null;
307
+ }
308
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { ReactNode } from 'react';
2
+ export interface ThemeProviderProps {
3
+ children: ReactNode;
4
+ }
5
+ /**
6
+ * Theme provider that creates MUI theme from service configuration.
7
+ *
8
+ * Theme merge order (each layer overrides the previous):
9
+ * 1. JUDO theme factory — modern component overrides based on primary/secondary colors
10
+ * 2. Density options — spacing/sizing adjustments for compact/comfortable/standard
11
+ * 3. User-supplied muiThemeOptions — final overrides for full customization
12
+ *
13
+ * All layers are merged as raw ThemeOptions **before** calling `createTheme()`
14
+ * once. This is critical because `createTheme` converts primitive values like
15
+ * `spacing: 8` into functions (`theme.spacing()`). Passing multiple args to
16
+ * `createTheme()` deep-merges subsequent args into the *processed* theme,
17
+ * which can replace those functions with plain primitives and break MUI
18
+ * components that call e.g. `theme.spacing(2)`.
19
+ */
20
+ export declare function ThemeProvider({ children }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
21
+ //# sourceMappingURL=ThemeProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/theme/ThemeProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,MAAM,WAAW,kBAAkB;IAClC,QAAQ,EAAE,SAAS,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE,kBAAkB,2CAkD7D"}
@@ -0,0 +1,11 @@
1
+ export interface ThemeToggleProps {
2
+ className?: string;
3
+ }
4
+ /**
5
+ * Theme toggle button cycling through light/dark/system modes.
6
+ * - Light: Forces light mode
7
+ * - Dark: Forces dark mode
8
+ * - System: Follows OS/browser preference
9
+ */
10
+ export declare function ThemeToggle({ className }: ThemeToggleProps): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=ThemeToggle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeToggle.d.ts","sourceRoot":"","sources":["../../src/theme/ThemeToggle.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE,gBAAgB,2CA6C1D"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Density levels for semantic spacing/sizing.
3
+ *
4
+ * - `compact` — Tight spacing, smaller font sizes; optimized for data-heavy views.
5
+ * - `comfortable` — Default MUI sizing; balanced between readability and density.
6
+ * - `standard` — Generous spacing, slightly larger touch targets; relaxed feel.
7
+ */
8
+ export type DensityLevel = "compact" | "comfortable" | "standard";
9
+ /**
10
+ * Returns MUI `ThemeOptions` that implement the requested density level.
11
+ *
12
+ * The returned options cover spacing factor, default component props (size/margin),
13
+ * and typography scaling so that a single `density` knob adjusts the whole UI.
14
+ *
15
+ * Merge the result as a **base** layer — caller-supplied `muiThemeOptions` should
16
+ * be applied on top so they can override individual values.
17
+ */
18
+ export declare function createDensityThemeOptions(density: DensityLevel): Record<string, unknown>;
19
+ //# sourceMappingURL=density.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"density.d.ts","sourceRoot":"","sources":["../../src/theme/density.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,aAAa,GAAG,UAAU,CAAC;AAElE;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkGxF"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * JUDO Theme Factory
3
+ *
4
+ * Creates polished MUI `ThemeOptions` from primary + secondary colors.
5
+ * The result is designed for enterprise/ERP UIs: information-dense, modern,
6
+ * and driven by the two supplied brand colors.
7
+ *
8
+ * This function does NOT call `createTheme()` — it returns a plain options
9
+ * object that the ThemeProvider merges with density and user overrides.
10
+ */
11
+ export interface JudoThemeFactoryOptions {
12
+ primaryColor: string;
13
+ secondaryColor: string;
14
+ mode: "light" | "dark";
15
+ lightBackground?: string;
16
+ darkBackground?: string;
17
+ }
18
+ /**
19
+ * Build modern MUI ThemeOptions driven by primary & secondary colors.
20
+ *
21
+ * Design goals:
22
+ * - Compact but not cramped — enterprise users need information density
23
+ * - Modern aesthetic: subtle shadows, refined border-radius, crisp typography
24
+ * - Primary color drives AppBar, buttons, active states
25
+ * - Secondary color provides accent on FABs, toggles, highlights
26
+ * - Clean separation of surfaces with subtle elevation
27
+ */
28
+ export declare function createJudoThemeOptions(options: JudoThemeFactoryOptions): Record<string, unknown>;
29
+ //# sourceMappingURL=judo-theme-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judo-theme-factory.d.ts","sourceRoot":"","sources":["../../src/theme/judo-theme-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,MAAM,WAAW,uBAAuB;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkdhG"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Theme presets for JUDO UI applications.
3
+ *
4
+ * Each preset defines a primary and secondary color pair that drives the
5
+ * entire visual identity. Presets can be used as-is or as starting points
6
+ * for further customization via `muiThemeOptions`.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { themePresets } from '@judo/app-shell';
11
+ *
12
+ * <JudoRuntime config={{
13
+ * theme: {
14
+ * preset: 'corporate',
15
+ * // or override specific colors:
16
+ * // primaryColor: '#custom',
17
+ * }
18
+ * }} />
19
+ * ```
20
+ */
21
+ export interface ThemePreset {
22
+ /** Human-readable preset name */
23
+ name: string;
24
+ /** Primary brand color (hex) */
25
+ primaryColor: string;
26
+ /** Secondary accent color (hex) */
27
+ secondaryColor: string;
28
+ /** Optional background tint for light mode */
29
+ lightBackground?: string;
30
+ /** Optional background tint for dark mode */
31
+ darkBackground?: string;
32
+ }
33
+ /**
34
+ * Built-in theme presets.
35
+ *
36
+ * All presets are designed for enterprise/ERP contexts:
37
+ * - High contrast for readability
38
+ * - Professional color combinations
39
+ * - Suitable for both light and dark modes
40
+ */
41
+ /**
42
+ * Built-in theme preset names.
43
+ * The `(string & {})` allows custom preset names while preserving autocomplete for built-ins.
44
+ */
45
+ export type ThemePresetName = "corporate" | "ocean" | "slate" | "indigo" | "forest" | "royal";
46
+ export declare const themePresets: Record<ThemePresetName, ThemePreset>;
47
+ /**
48
+ * Resolve a preset by name. Returns `undefined` if not found.
49
+ */
50
+ export declare function resolvePreset(presetName: string): ThemePreset | undefined;
51
+ //# sourceMappingURL=presets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/theme/presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,WAAW;IAC3B,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE9F,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,eAAe,EAAE,WAAW,CAwEpD,CAAC;AAEX;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEzE"}
@@ -0,0 +1,11 @@
1
+ import { HeroComponentProps } from '@judo/model-api';
2
+ /**
3
+ * Default hero component rendered in the AppBar for authenticated actors.
4
+ *
5
+ * Displays the principal's avatar button that opens a dropdown with
6
+ * profile info and sign-out.
7
+ *
8
+ * Can be replaced via `CustomizationsConfig.heroComponent`.
9
+ */
10
+ export declare function DefaultHeroComponent({ principal, actorName: _actorName, signOut, onNavigateToProfile, onNavigateToSettings, profilePictureUrl, }: HeroComponentProps): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=DefaultHeroComponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultHeroComponent.d.ts","sourceRoot":"","sources":["../../src/user/DefaultHeroComponent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAmB1D;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,EACpC,SAAS,EACT,SAAS,EAAE,UAAU,EACrB,OAAO,EACP,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,GACjB,EAAE,kBAAkB,2CA+EpB"}
@@ -0,0 +1,8 @@
1
+ export interface UserMenuProps {
2
+ className?: string;
3
+ }
4
+ /**
5
+ * User menu with profile info and logout action.
6
+ */
7
+ export declare function UserMenu({ className }: UserMenuProps): import("react/jsx-runtime").JSX.Element | null;
8
+ //# sourceMappingURL=UserMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserMenu.d.ts","sourceRoot":"","sources":["../../src/user/UserMenu.tsx"],"names":[],"mappings":"AAkBA,MAAM,WAAW,aAAa;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,kDAyEpD"}
package/package.json ADDED
@@ -0,0 +1,99 @@
1
+ {
2
+ "name": "@judo/app-shell",
3
+ "version": "0.1.0",
4
+ "license": "EPL-2.0",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/BlackBeltTechnology/judo-frontend-runtime.git",
8
+ "directory": "packages/app-shell"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "LICENSE",
13
+ "README.md"
14
+ ],
15
+ "type": "module",
16
+ "sideEffects": false,
17
+ "main": "./dist/index.js",
18
+ "module": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js"
24
+ }
25
+ },
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "dependencies": {
30
+ "@judo/actions": "0.1.0",
31
+ "@judo/auth": "0.1.0",
32
+ "@judo/components": "0.1.0",
33
+ "@judo/core": "0.1.0",
34
+ "@judo/feedback": "0.1.0",
35
+ "@judo/guards": "0.1.0",
36
+ "@judo/expressions": "0.1.0",
37
+ "@judo/i18n": "0.1.0",
38
+ "@judo/model-api": "0.1.0",
39
+ "@judo/model-loader": "0.1.0",
40
+ "@judo/test-ids": "0.1.0"
41
+ },
42
+ "devDependencies": {
43
+ "@testing-library/react": "^16.3.2",
44
+ "@testing-library/user-event": "^14.6.1",
45
+ "@types/react": "^19.2.14",
46
+ "react": "^19.2.4",
47
+ "react-dom": "^19.2.4",
48
+ "react-router": "^7.13.0",
49
+ "typescript": "^5.9.3",
50
+ "vitest": "^4.0.18",
51
+ "@judo/actions": "0.1.0",
52
+ "@judo/auth": "0.1.0",
53
+ "@judo/components": "0.1.0",
54
+ "@judo/core": "0.1.0",
55
+ "@judo/feedback": "0.1.0",
56
+ "@judo/guards": "0.1.0",
57
+ "@judo/expressions": "0.1.0",
58
+ "@judo/model-api": "0.1.0",
59
+ "@judo/model-loader": "0.1.0",
60
+ "@judo/i18n": "0.1.0",
61
+ "@judo/test-ids": "0.1.0",
62
+ "@judo/testing": "0.1.0"
63
+ },
64
+ "peerDependencies": {
65
+ "@emotion/react": "^11.14.0",
66
+ "@emotion/styled": "^11.14.0",
67
+ "@mui/icons-material": "^7.0.0",
68
+ "@mui/material": "^7.0.0",
69
+ "@mui/utils": "^7.0.0",
70
+ "@mui/x-data-grid-pro": "^8.0.0",
71
+ "@mui/x-license": "^8.0.0",
72
+ "react": "^19.0.0",
73
+ "react-router": "^7.0.0",
74
+ "@judo/actions": "0.1.0",
75
+ "@judo/auth": "0.1.0",
76
+ "@judo/core": "0.1.0",
77
+ "@judo/feedback": "0.1.0",
78
+ "@judo/i18n": "0.1.0",
79
+ "@judo/guards": "0.1.0",
80
+ "@judo/model-api": "0.1.0",
81
+ "@judo/test-ids": "0.1.0",
82
+ "@judo/model-loader": "0.1.0",
83
+ "@judo/components": "0.1.0"
84
+ },
85
+ "peerDependenciesMeta": {
86
+ "@mui/x-data-grid-pro": {
87
+ "optional": true
88
+ },
89
+ "@mui/x-license": {
90
+ "optional": true
91
+ }
92
+ },
93
+ "scripts": {
94
+ "build": "vite build",
95
+ "test": "vitest run",
96
+ "test:watch": "vitest watch",
97
+ "test:coverage": "vitest run --coverage"
98
+ }
99
+ }