@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
@@ -0,0 +1,42 @@
1
+ import { Link, useLocation } from 'react-router';
2
+ import { useConfig } from '../config/useConfig';
3
+ import { getLegalDocuments } from './legalDocuments';
4
+ import { LegalDocumentContent } from './LegalDocumentContent';
5
+ import urls from '../../constants/urls';
6
+
7
+ export const LegalDocumentView = () => {
8
+ const { config } = useConfig();
9
+ const location = useLocation();
10
+ const legalDocuments = getLegalDocuments(config);
11
+ const selectedDocument = legalDocuments.find((item) => item.path === location.pathname);
12
+
13
+ if (!selectedDocument) {
14
+ return (
15
+ <main className="mx-auto w-full max-w-4xl p-6">
16
+ <h1
17
+ className="text-2xl font-semibold"
18
+ style={{ fontFamily: 'var(--heading-font-family, inherit)' }}
19
+ >
20
+ Legal documents
21
+ </h1>
22
+ <p className="mt-2 text-sm text-muted-foreground">
23
+ No legal document is configured for this page.
24
+ </p>
25
+ </main>
26
+ );
27
+ }
28
+
29
+ return (
30
+ <main className="mx-auto w-full max-w-4xl p-6">
31
+ <div className="mb-4">
32
+ <Link
33
+ to={urls.login}
34
+ className="text-sm text-primary hover:underline"
35
+ >
36
+ Back to login
37
+ </Link>
38
+ </div>
39
+ <LegalDocumentContent document={selectedDocument} />
40
+ </main>
41
+ );
42
+ };
@@ -0,0 +1,51 @@
1
+ import { Link } from 'react-router';
2
+ import urls from '../../constants/urls';
3
+ import { useConfig } from '../config/useConfig';
4
+ import { getLegalDocuments } from './legalDocuments';
5
+
6
+ export const LegalDocumentsIndexView = () => {
7
+ const { config } = useConfig();
8
+ const legalDocuments = getLegalDocuments(config);
9
+
10
+ return (
11
+ <main className="mx-auto w-full max-w-4xl p-6">
12
+ <div className="space-y-2">
13
+ <h1
14
+ className="text-2xl font-semibold tracking-tight"
15
+ style={{ fontFamily: 'var(--heading-font-family, inherit)' }}
16
+ >
17
+ Legal documents
18
+ </h1>
19
+ <p className="text-sm text-muted-foreground">Select a document to view its full content.</p>
20
+ </div>
21
+
22
+ {legalDocuments.length === 0 ? (
23
+ <p className="mt-6 text-sm text-muted-foreground">
24
+ No legal document is currently configured.
25
+ </p>
26
+ ) : (
27
+ <ul className="mt-6 space-y-2">
28
+ {legalDocuments.map((document) => (
29
+ <li key={document.path}>
30
+ <Link
31
+ to={document.path}
32
+ className="text-sm font-medium text-primary underline-offset-4 hover:underline"
33
+ >
34
+ {document.title}
35
+ </Link>
36
+ </li>
37
+ ))}
38
+ </ul>
39
+ )}
40
+
41
+ <div className="mt-8">
42
+ <Link
43
+ to={urls.login}
44
+ className="text-sm text-primary hover:underline"
45
+ >
46
+ Back to login
47
+ </Link>
48
+ </div>
49
+ </main>
50
+ );
51
+ };
@@ -0,0 +1,29 @@
1
+ import { Link } from 'react-router';
2
+ import { useConfig } from '../config/useConfig';
3
+ import { getLegalDocuments } from './legalDocuments';
4
+
5
+ export const LegalDocumentsLinks = () => {
6
+ const { config } = useConfig();
7
+ const legalDocuments = getLegalDocuments(config);
8
+
9
+ if (legalDocuments.length === 0) {
10
+ return null;
11
+ }
12
+
13
+ return (
14
+ <nav
15
+ aria-label="Legal links"
16
+ className="flex flex-wrap gap-x-4 gap-y-2 text-xs text-muted-foreground"
17
+ >
18
+ {legalDocuments.map((document) => (
19
+ <Link
20
+ key={document.path}
21
+ to={document.path}
22
+ className="hover:text-foreground hover:underline"
23
+ >
24
+ {document.title}
25
+ </Link>
26
+ ))}
27
+ </nav>
28
+ );
29
+ };
@@ -0,0 +1,62 @@
1
+ import type { ShellUIConfig } from '../config/types';
2
+ import urls from '../../constants/urls';
3
+
4
+ export type LegalDocumentKey =
5
+ | 'privacyPolicy'
6
+ | 'termsOfService'
7
+ | 'legalNotice'
8
+ | 'dataProcessingAgreement';
9
+
10
+ export type LegalDocumentDescriptor = {
11
+ key: LegalDocumentKey;
12
+ title: string;
13
+ path: string;
14
+ filename: string;
15
+ content: string;
16
+ };
17
+
18
+ type LegalDocumentDefinition = Omit<LegalDocumentDescriptor, 'content'>;
19
+
20
+ const LEGAL_DOCUMENT_DEFINITIONS: LegalDocumentDefinition[] = [
21
+ {
22
+ key: 'privacyPolicy',
23
+ title: 'Privacy Policy',
24
+ path: urls.legalPrivacyPolicy,
25
+ filename: 'privacy-policy.md',
26
+ },
27
+ {
28
+ key: 'termsOfService',
29
+ title: 'Terms of Service',
30
+ path: urls.legalTermsOfService,
31
+ filename: 'terms-of-service.md',
32
+ },
33
+ {
34
+ key: 'legalNotice',
35
+ title: 'Legal Notice',
36
+ path: urls.legalNotice,
37
+ filename: 'legal-notice.md',
38
+ },
39
+ {
40
+ key: 'dataProcessingAgreement',
41
+ title: 'Data Processing Agreement',
42
+ path: urls.legalDataProcessingAgreement,
43
+ filename: 'data-processing-agreement.md',
44
+ },
45
+ ];
46
+
47
+ export const getLegalDocuments = (config: ShellUIConfig): LegalDocumentDescriptor[] => {
48
+ const legalConfig = config.legalDocuments;
49
+ if (!legalConfig) return [];
50
+ const documents: LegalDocumentDescriptor[] = [];
51
+ for (const definition of LEGAL_DOCUMENT_DEFINITIONS) {
52
+ const content = legalConfig[definition.key];
53
+ if (typeof content !== 'string') continue;
54
+ const trimmedContent = content.trim();
55
+ if (!trimmedContent) continue;
56
+ documents.push({
57
+ ...definition,
58
+ content: trimmedContent,
59
+ });
60
+ }
61
+ return documents;
62
+ };
@@ -450,3 +450,23 @@ export const PackageIcon = () => (
450
450
  <path d="M12 22V12" />
451
451
  </svg>
452
452
  );
453
+
454
+ export const FileTextIcon = () => (
455
+ <svg
456
+ xmlns="http://www.w3.org/2000/svg"
457
+ width="16"
458
+ height="16"
459
+ viewBox="0 0 24 24"
460
+ fill="none"
461
+ stroke="currentColor"
462
+ strokeWidth="2"
463
+ strokeLinecap="round"
464
+ strokeLinejoin="round"
465
+ >
466
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
467
+ <path d="M14 2v6h6" />
468
+ <path d="M16 13H8" />
469
+ <path d="M16 17H8" />
470
+ <path d="M10 9H8" />
471
+ </svg>
472
+ );