@shellui/core 0.2.0 → 0.3.0-beta.1

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 (111) hide show
  1. package/package.json +9 -4
  2. package/src/app.tsx +12 -9
  3. package/src/components/ui/badge.tsx +35 -0
  4. package/src/components/ui/dropdown-menu.tsx +94 -0
  5. package/src/components/ui/sidebar.tsx +1 -1
  6. package/src/constants/urls.ts +8 -0
  7. package/src/features/admin/AdminView.tsx +154 -0
  8. package/src/features/admin/components/AdminForbiddenAccess.tsx +10 -0
  9. package/src/features/auth/AuthProvider.tsx +464 -0
  10. package/src/features/auth/backends/index.ts +41 -0
  11. package/src/features/auth/backends/shellui.ts +278 -0
  12. package/src/features/auth/backends/supabase.ts +300 -0
  13. package/src/features/auth/backends/types.ts +30 -0
  14. package/src/features/auth/components/LoginButton.tsx +360 -0
  15. package/src/features/auth/components/LoginButtonIcons.tsx +48 -0
  16. package/src/features/auth/components/LoginView.tsx +721 -0
  17. package/src/features/auth/components/OAuthCallbackView.tsx +119 -0
  18. package/src/features/auth/hooks/useAuth.tsx +37 -0
  19. package/src/features/auth/types.ts +51 -0
  20. package/src/features/auth/utils/buildSessionFromParams.spec.ts +61 -0
  21. package/src/features/auth/utils/buildSessionFromParams.ts +79 -0
  22. package/src/features/auth/utils/clearStoredAuthSession.spec.ts +23 -0
  23. package/src/features/auth/utils/clearStoredAuthSession.ts +10 -0
  24. package/src/features/auth/utils/clientLoginContext.spec.ts +83 -0
  25. package/src/features/auth/utils/clientLoginContext.ts +89 -0
  26. package/src/features/auth/utils/decodeJwtPayload.spec.ts +17 -0
  27. package/src/features/auth/utils/decodeJwtPayload.ts +24 -0
  28. package/src/features/auth/utils/formatProviderLabel.spec.ts +19 -0
  29. package/src/features/auth/utils/formatProviderLabel.ts +11 -0
  30. package/src/features/auth/utils/getOAuthProviderCandidates.spec.ts +16 -0
  31. package/src/features/auth/utils/getOAuthProviderCandidates.ts +15 -0
  32. package/src/features/auth/utils/getPreferredBackendProvider.spec.ts +15 -0
  33. package/src/features/auth/utils/getPreferredBackendProvider.ts +10 -0
  34. package/src/features/auth/utils/getProviderVisual.spec.ts +30 -0
  35. package/src/features/auth/utils/getProviderVisual.ts +83 -0
  36. package/src/features/auth/utils/getUserFromSdkSettings.spec.ts +32 -0
  37. package/src/features/auth/utils/getUserFromSdkSettings.ts +13 -0
  38. package/src/features/auth/utils/index.ts +21 -0
  39. package/src/features/auth/utils/isLoginMethod.spec.ts +18 -0
  40. package/src/features/auth/utils/isLoginMethod.ts +5 -0
  41. package/src/features/auth/utils/isSessionExpired.spec.ts +23 -0
  42. package/src/features/auth/utils/isSessionExpired.ts +5 -0
  43. package/src/features/auth/utils/normalizeAuthSettings.spec.ts +60 -0
  44. package/src/features/auth/utils/normalizeAuthSettings.ts +71 -0
  45. package/src/features/auth/utils/normalizeNextPath.spec.ts +21 -0
  46. package/src/features/auth/utils/normalizeNextPath.ts +12 -0
  47. package/src/features/auth/utils/normalizeRedirectPath.spec.ts +12 -0
  48. package/src/features/auth/utils/normalizeRedirectPath.ts +3 -0
  49. package/src/features/auth/utils/persistAuthSession.spec.ts +35 -0
  50. package/src/features/auth/utils/persistAuthSession.ts +12 -0
  51. package/src/features/auth/utils/readStoredAuthSession.spec.ts +34 -0
  52. package/src/features/auth/utils/readStoredAuthSession.ts +14 -0
  53. package/src/features/auth/utils/toAuthSessionFromSettingsUser.spec.ts +76 -0
  54. package/src/features/auth/utils/toAuthSessionFromSettingsUser.ts +36 -0
  55. package/src/features/config/types.ts +55 -0
  56. package/src/features/layouts/AppLayout.tsx +8 -6
  57. package/src/features/layouts/appbar/AppBarLayout.tsx +42 -23
  58. package/src/features/layouts/fullscreen/FullscreenLayout.tsx +3 -2
  59. package/src/features/layouts/sidebar/SidebarInner.tsx +7 -5
  60. package/src/features/layouts/sidebar/SidebarLayout.tsx +16 -3
  61. package/src/features/layouts/utils.ts +54 -0
  62. package/src/features/layouts/windows/WindowsLayout.tsx +22 -4
  63. package/src/features/legal/LegalDocumentContent.tsx +102 -0
  64. package/src/features/legal/LegalDocumentView.tsx +42 -0
  65. package/src/features/legal/LegalDocumentsIndexView.tsx +51 -0
  66. package/src/features/legal/LegalDocumentsLinks.tsx +29 -0
  67. package/src/features/legal/legalDocuments.ts +62 -0
  68. package/src/features/settings/SettingsIcons.tsx +20 -0
  69. package/src/features/settings/SettingsProvider.tsx +347 -245
  70. package/src/features/settings/SettingsRoutes.tsx +8 -0
  71. package/src/features/settings/SettingsView.tsx +43 -8
  72. package/src/features/settings/components/Develop.tsx +2 -2
  73. package/src/features/settings/components/LegalDocumentsPanel.tsx +46 -0
  74. package/src/features/settings/components/UserIcon.tsx +20 -0
  75. package/src/features/settings/components/UserSettingsPanel.tsx +438 -0
  76. package/src/features/settings/components/createUserSettingsRoute.tsx +43 -0
  77. package/src/features/settings/utils/buildSettingsForPropagation.spec.ts +167 -0
  78. package/src/features/settings/utils/buildSettingsForPropagation.ts +61 -0
  79. package/src/features/settings/utils/flattenNavigationItems.spec.ts +17 -0
  80. package/src/features/settings/utils/flattenNavigationItems.ts +12 -0
  81. package/src/features/settings/utils/getAvailableThemesForSettings.spec.ts +15 -0
  82. package/src/features/settings/utils/getAvailableThemesForSettings.ts +16 -0
  83. package/src/features/settings/utils/getBrowserTimezone.spec.ts +11 -0
  84. package/src/features/settings/utils/getBrowserTimezone.ts +7 -0
  85. package/src/features/settings/utils/getPreferenceSnapshot.spec.ts +35 -0
  86. package/src/features/settings/utils/getPreferenceSnapshot.ts +10 -0
  87. package/src/features/settings/utils/getResolvedAppearanceForSettings.spec.ts +97 -0
  88. package/src/features/settings/utils/getResolvedAppearanceForSettings.ts +48 -0
  89. package/src/features/settings/utils/index.ts +12 -0
  90. package/src/features/settings/utils/isSameUser.spec.ts +35 -0
  91. package/src/features/settings/utils/isSameUser.ts +17 -0
  92. package/src/features/settings/utils/mergePreferencesIntoSettings.spec.ts +108 -0
  93. package/src/features/settings/utils/mergePreferencesIntoSettings.ts +47 -0
  94. package/src/features/settings/utils/resolveColorMode.spec.ts +29 -0
  95. package/src/features/settings/utils/resolveColorMode.ts +6 -0
  96. package/src/features/settings/utils/resolveLabel.spec.ts +17 -0
  97. package/src/features/settings/utils/resolveLabel.ts +7 -0
  98. package/src/features/settings/utils/toAbsoluteFontUrls.spec.ts +26 -0
  99. package/src/features/settings/utils/toAbsoluteFontUrls.ts +15 -0
  100. package/src/features/settings/utils/toSettingsUser.spec.ts +49 -0
  101. package/src/features/settings/utils/toSettingsUser.ts +15 -0
  102. package/src/i18n/translations/en/common.json +14 -0
  103. package/src/i18n/translations/en/settings.json +45 -0
  104. package/src/i18n/translations/fr/common.json +14 -0
  105. package/src/i18n/translations/fr/settings.json +45 -0
  106. package/src/index.css +37 -0
  107. package/src/index.ts +6 -0
  108. package/src/routes/components/NavigationItemRoute.tsx +32 -1
  109. package/src/routes/components/NotFoundView.tsx +13 -3
  110. package/src/routes/hooks/useNavigationItems.ts +19 -4
  111. package/src/routes/routes.tsx +87 -0
@@ -1,21 +1,31 @@
1
1
  import { useMemo } from 'react';
2
2
  import { useConfig } from '../../features/config/useConfig';
3
+ import { useAuth } from '../../features/auth/hooks/useAuth';
3
4
  import {
5
+ filterNavigationForAuthState,
4
6
  flattenNavigationItems,
5
7
  getBaseUrlWithoutHash,
6
8
  getHashPathFromUrl,
7
9
  getNavPathPrefix,
8
10
  isHashRouterNavItem,
9
11
  } from '../../features/layouts/utils';
12
+ import { useSettings } from '../../features/settings/hooks/useSettings';
10
13
  import { useLocation } from 'react-router';
11
14
 
12
15
  export function useNavigationItems() {
13
16
  const { config } = useConfig();
17
+ const { isAuthenticated } = useAuth();
18
+ const { settings } = useSettings();
14
19
  const location = useLocation();
15
20
 
16
21
  const navigationItems = useMemo(() => {
17
- return flattenNavigationItems(config?.navigation ?? []);
18
- }, [config]);
22
+ const authAndDevFilteredNavigation = filterNavigationForAuthState(
23
+ config?.navigation ?? [],
24
+ isAuthenticated,
25
+ settings.developerFeatures.enabled,
26
+ );
27
+ return flattenNavigationItems(authAndDevFilteredNavigation);
28
+ }, [config?.navigation, isAuthenticated, settings.developerFeatures.enabled]);
19
29
 
20
30
  const navigationItem = useMemo(() => {
21
31
  return navigationItems.find((item) => {
@@ -29,6 +39,10 @@ export function useNavigationItems() {
29
39
  () => navigationItems.find((item) => item.path === '' || item.path === '/'),
30
40
  [navigationItems],
31
41
  );
42
+ const isRootFallback = useMemo(
43
+ () => !navigationItem && Boolean(rootItem) && location.pathname !== '/',
44
+ [navigationItem, rootItem, location.pathname],
45
+ );
32
46
 
33
47
  /**
34
48
  * Constructs the final URL for the iframe based on the navigation item and the pathname.
@@ -39,7 +53,7 @@ export function useNavigationItems() {
39
53
  const url = useMemo(() => {
40
54
  const pathname = location.pathname;
41
55
 
42
- const useRootFallback = !navigationItem && rootItem && pathname !== '/';
56
+ const useRootFallback = isRootFallback;
43
57
  const actualNavItem = navigationItem ?? (useRootFallback ? rootItem : null);
44
58
 
45
59
  if (!actualNavItem) {
@@ -72,7 +86,7 @@ export function useNavigationItems() {
72
86
  }
73
87
  }
74
88
  return finalUrl;
75
- }, [navigationItem, rootItem, location.pathname]);
89
+ }, [navigationItem, rootItem, location.pathname, isRootFallback]);
76
90
 
77
91
  return {
78
92
  url: url,
@@ -80,5 +94,6 @@ export function useNavigationItems() {
80
94
  currentItem: navigationItem || rootItem,
81
95
  navigationItem: navigationItem || rootItem,
82
96
  navigationItems: navigationItems,
97
+ isRootFallback,
83
98
  };
84
99
  }
@@ -16,6 +16,25 @@ const CookiePreferencesView = lazy(() =>
16
16
  default: m.CookiePreferencesView,
17
17
  })),
18
18
  );
19
+ const LoginView = lazy(() =>
20
+ import('../features/auth/components/LoginView').then((m) => ({ default: m.LoginView })),
21
+ );
22
+ const OAuthCallbackView = lazy(() =>
23
+ import('../features/auth/components/OAuthCallbackView').then((m) => ({
24
+ default: m.OAuthCallbackView,
25
+ })),
26
+ );
27
+ const AdminView = lazy(() =>
28
+ import('../features/admin/AdminView').then((m) => ({ default: m.AdminView })),
29
+ );
30
+ const LegalDocumentView = lazy(() =>
31
+ import('../features/legal/LegalDocumentView').then((m) => ({ default: m.LegalDocumentView })),
32
+ );
33
+ const LegalDocumentsIndexView = lazy(() =>
34
+ import('../features/legal/LegalDocumentsIndexView').then((m) => ({
35
+ default: m.LegalDocumentsIndexView,
36
+ })),
37
+ );
19
38
  const NavigationItemRoute = lazy(() =>
20
39
  import('./components/NavigationItemRoute').then((m) => ({ default: m.NavigationItemRoute })),
21
40
  );
@@ -27,6 +46,11 @@ const NotFoundView = lazy(() =>
27
46
  );
28
47
 
29
48
  export const createRoutes = (config: ShellUIConfig): RouteObject[] => {
49
+ const configuredAdminPathname = config.backend?.adminPathname?.trim();
50
+ const adminPath =
51
+ configuredAdminPathname && configuredAdminPathname.startsWith('/')
52
+ ? configuredAdminPathname
53
+ : urls.admin;
30
54
  const routes: RouteObject[] = [
31
55
  {
32
56
  path: '/',
@@ -51,6 +75,69 @@ export const createRoutes = (config: ShellUIConfig): RouteObject[] => {
51
75
  </Suspense>
52
76
  ),
53
77
  },
78
+ {
79
+ // Login route
80
+ path: urls.login.replace(/^\//, ''),
81
+ element: (
82
+ <Suspense fallback={<RouteFallback />}>
83
+ <LoginView />
84
+ </Suspense>
85
+ ),
86
+ },
87
+ {
88
+ // OAuth callback route (frontend receives code, then exchanges via backend).
89
+ path: urls.loginCallback.replace(/^\//, ''),
90
+ element: (
91
+ <Suspense fallback={<RouteFallback />}>
92
+ <OAuthCallbackView />
93
+ </Suspense>
94
+ ),
95
+ },
96
+ {
97
+ path: urls.legalDocuments.replace(/^\//, ''),
98
+ element: (
99
+ <Suspense fallback={<RouteFallback />}>
100
+ <LegalDocumentsIndexView />
101
+ </Suspense>
102
+ ),
103
+ },
104
+ {
105
+ path: urls.legalPrivacyPolicy.replace(/^\//, ''),
106
+ element: (
107
+ <Suspense fallback={<RouteFallback />}>
108
+ <LegalDocumentView />
109
+ </Suspense>
110
+ ),
111
+ },
112
+ {
113
+ path: urls.legalTermsOfService.replace(/^\//, ''),
114
+ element: (
115
+ <Suspense fallback={<RouteFallback />}>
116
+ <LegalDocumentView />
117
+ </Suspense>
118
+ ),
119
+ },
120
+ {
121
+ path: urls.legalNotice.replace(/^\//, ''),
122
+ element: (
123
+ <Suspense fallback={<RouteFallback />}>
124
+ <LegalDocumentView />
125
+ </Suspense>
126
+ ),
127
+ },
128
+ {
129
+ path: urls.legalDataProcessingAgreement.replace(/^\//, ''),
130
+ element: (
131
+ <Suspense fallback={<RouteFallback />}>
132
+ <LegalDocumentView />
133
+ </Suspense>
134
+ ),
135
+ },
136
+ {
137
+ // Admin route
138
+ path: `${adminPath.replace(/^\//, '')}/*`,
139
+ element: <AdminView />,
140
+ },
54
141
  {
55
142
  // Catch-all route
56
143
  path: '*',