@umituz/web-dashboard 5.0.1 → 6.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 (120) hide show
  1. package/package.json +19 -17
  2. package/src/domains/onboarding/calc/calc.test.ts +181 -0
  3. package/src/domains/onboarding/calc/card-stack-motion-curve.ts +33 -0
  4. package/src/domains/onboarding/calc/count-with-locale.ts +16 -0
  5. package/src/domains/onboarding/calc/duration-equal-split.ts +24 -0
  6. package/src/domains/onboarding/calc/elapsed-millis.ts +12 -0
  7. package/src/domains/onboarding/calc/index.ts +36 -0
  8. package/src/domains/onboarding/calc/progress-percentage.ts +37 -0
  9. package/src/domains/onboarding/calc/slider-value-bounds.ts +44 -0
  10. package/src/domains/onboarding/calc/step-index-clamp.ts +28 -0
  11. package/src/domains/onboarding/calc/swipe-gesture-curve.ts +67 -0
  12. package/src/domains/onboarding/components/OnboardingFlow.test.tsx +481 -0
  13. package/src/domains/onboarding/components/OnboardingFlow.tsx +361 -0
  14. package/src/domains/onboarding/components/OnboardingIntl.tsx +108 -0
  15. package/src/domains/onboarding/components/hooks/index.ts +7 -0
  16. package/src/domains/onboarding/components/hooks/useOnboardingAnalytics.test.tsx +74 -0
  17. package/src/domains/onboarding/components/hooks/useOnboardingAnalytics.ts +62 -0
  18. package/src/domains/onboarding/components/hooks/useOnboardingProgress.test.tsx +150 -0
  19. package/src/domains/onboarding/components/hooks/useOnboardingProgress.ts +260 -0
  20. package/src/domains/onboarding/components/hooks/usePermissionPriming.ts +52 -0
  21. package/src/domains/onboarding/components/hooks/useReducedMotion.ts +24 -0
  22. package/src/domains/onboarding/components/screens/AccountGateScreen.tsx +89 -0
  23. package/src/domains/onboarding/components/screens/AppDemoScreen.tsx +39 -0
  24. package/src/domains/onboarding/components/screens/ComparisonScreen.tsx +59 -0
  25. package/src/domains/onboarding/components/screens/GoalQuestionScreen.tsx +56 -0
  26. package/src/domains/onboarding/components/screens/PainPointsScreen.tsx +65 -0
  27. package/src/domains/onboarding/components/screens/PaywallScreen.tsx +138 -0
  28. package/src/domains/onboarding/components/screens/PermissionPrimingScreen.tsx +113 -0
  29. package/src/domains/onboarding/components/screens/PersonalizedSolutionScreen.tsx +53 -0
  30. package/src/domains/onboarding/components/screens/PreferencesScreen.tsx +194 -0
  31. package/src/domains/onboarding/components/screens/ProcessingScreen.tsx +79 -0
  32. package/src/domains/onboarding/components/screens/SocialProofScreen.tsx +116 -0
  33. package/src/domains/onboarding/components/screens/TinderCardsScreen.tsx +108 -0
  34. package/src/domains/onboarding/components/screens/ValueDeliveryScreen.tsx +85 -0
  35. package/src/domains/onboarding/components/screens/WelcomeScreen.tsx +52 -0
  36. package/src/domains/onboarding/components/screens/index.ts +28 -0
  37. package/src/domains/onboarding/components/shared/AnimationWrapper.tsx +73 -0
  38. package/src/domains/onboarding/components/shared/OnboardingErrorBoundary.tsx +81 -0
  39. package/src/domains/onboarding/components/shared/OptionCard.tsx +73 -0
  40. package/src/domains/onboarding/components/shared/PrimaryButton.tsx +58 -0
  41. package/src/domains/onboarding/components/shared/ProgressBar.tsx +51 -0
  42. package/src/domains/onboarding/components/shared/QuestionWrapper.tsx +36 -0
  43. package/src/domains/onboarding/components/shared/ScreenContainer.tsx +29 -0
  44. package/src/domains/onboarding/components/shared/SwipeCard.test.tsx +51 -0
  45. package/src/domains/onboarding/components/shared/SwipeCard.tsx +106 -0
  46. package/src/domains/onboarding/components/shared/index.ts +16 -0
  47. package/src/domains/onboarding/components/shared/renderBundledIcon.tsx +20 -0
  48. package/src/domains/onboarding/index.ts +182 -0
  49. package/src/domains/onboarding/onboarding.css +1 -0
  50. package/src/domains/onboarding/predicates/has-handler.ts +25 -0
  51. package/src/domains/onboarding/predicates/icon-name-resolves.ts +113 -0
  52. package/src/domains/onboarding/predicates/index.ts +26 -0
  53. package/src/domains/onboarding/predicates/permission-granted.ts +26 -0
  54. package/src/domains/onboarding/predicates/permission-supports.ts +66 -0
  55. package/src/domains/onboarding/predicates/predicates.test.ts +202 -0
  56. package/src/domains/onboarding/predicates/screen-emits-data.ts +17 -0
  57. package/src/domains/onboarding/predicates/storage-available.ts +22 -0
  58. package/src/domains/onboarding/templates/TemplateDemoFallback.tsx +112 -0
  59. package/src/domains/onboarding/templates/art-onboarding.ts +81 -0
  60. package/src/domains/onboarding/templates/health-onboarding.ts +97 -0
  61. package/src/domains/onboarding/templates/index.ts +6 -0
  62. package/src/domains/onboarding/templates/platform-onboarding.ts +210 -0
  63. package/src/domains/onboarding/templates/video-onboarding.ts +100 -0
  64. package/src/domains/onboarding/test/setup.ts +30 -0
  65. package/src/domains/onboarding/theme/cn.ts +10 -0
  66. package/src/domains/onboarding/theme/index.css +131 -0
  67. package/src/domains/onboarding/theme/index.ts +12 -0
  68. package/src/domains/onboarding/theme/tokens.ts +122 -0
  69. package/src/domains/onboarding/types/config.ts +68 -0
  70. package/src/domains/onboarding/types/index.ts +10 -0
  71. package/src/domains/onboarding/types/labels.ts +83 -0
  72. package/src/domains/onboarding/types/screens.ts +193 -0
  73. package/src/domains/onboarding/utils/analytics-dispatch.test.ts +93 -0
  74. package/src/domains/onboarding/utils/analytics-dispatch.ts +92 -0
  75. package/src/domains/onboarding/utils/default-storage-key.ts +2 -0
  76. package/src/domains/onboarding/utils/index.ts +13 -0
  77. package/src/domains/onboarding/utils/local-storage-bridge.test.ts +93 -0
  78. package/src/domains/onboarding/utils/local-storage-bridge.ts +104 -0
  79. package/src/domains/onboarding/utils/permission-bridge.test.ts +64 -0
  80. package/src/domains/onboarding/utils/permission-bridge.ts +95 -0
  81. package/src/domains/onboarding/validation/flow-structure-check.ts +28 -0
  82. package/src/domains/onboarding/validation/index.ts +9 -0
  83. package/src/domains/onboarding/validation/permission-status-check.ts +23 -0
  84. package/src/domains/onboarding/validation/screen-config-check.ts +105 -0
  85. package/src/domains/onboarding/validation/stored-progress-check.ts +68 -0
  86. package/src/domains/onboarding/validation/validation.test.ts +175 -0
  87. package/src/index.ts +0 -10
  88. package/src/styles/dashboard.contract.test.ts +1 -0
  89. package/src/styles/dashboard.css +0 -460
  90. package/src/domains/auth/components/AuthLayout.tsx +0 -99
  91. package/src/domains/auth/components/ForgotPasswordForm.tsx +0 -167
  92. package/src/domains/auth/components/LoginForm.tsx +0 -222
  93. package/src/domains/auth/components/RegisterForm.tsx +0 -281
  94. package/src/domains/auth/components/ResetPasswordForm.tsx +0 -173
  95. package/src/domains/auth/components/index.ts +0 -11
  96. package/src/domains/auth/components/shared/AuthErrorBanner.tsx +0 -25
  97. package/src/domains/auth/components/shared/EmailInput.tsx +0 -73
  98. package/src/domains/auth/components/shared/PasswordInput.tsx +0 -100
  99. package/src/domains/auth/components/shared/PasswordStrengthIndicator.tsx +0 -63
  100. package/src/domains/auth/components/shared/SocialLoginButtons.tsx +0 -44
  101. package/src/domains/auth/components/shared/SocialProviderIcons.tsx +0 -48
  102. package/src/domains/auth/components/shared/index.ts +0 -20
  103. package/src/domains/auth/hooks/index.ts +0 -8
  104. package/src/domains/auth/hooks/useAuth.ts +0 -230
  105. package/src/domains/auth/index.ts +0 -62
  106. package/src/domains/auth/types/auth.ts +0 -302
  107. package/src/domains/auth/types/index.ts +0 -25
  108. package/src/domains/auth/utils/auth.test.ts +0 -188
  109. package/src/domains/auth/utils/auth.ts +0 -221
  110. package/src/domains/auth/utils/i18nKeys.ts +0 -109
  111. package/src/domains/auth/utils/index.ts +0 -29
  112. package/src/domains/auth/utils/secureToken.ts +0 -33
  113. package/src/domains/auth/utils/validationKeys.ts +0 -23
  114. package/src/domains/session/DemoLogin.tsx +0 -42
  115. package/src/domains/session/OrgSwitcher.tsx +0 -102
  116. package/src/domains/session/SessionContext.tsx +0 -150
  117. package/src/domains/session/inMemoryAuthAdapter.ts +0 -53
  118. package/src/domains/session/index.ts +0 -18
  119. package/src/domains/session/types.ts +0 -47
  120. package/src/domains/session/utils/i18nKeys.ts +0 -12
@@ -1,150 +0,0 @@
1
- /**
2
- * Session context — user + active tenant state over an injected
3
- * AuthAdapter. Restores the current user on mount, exposes
4
- * login/logout/demoLogin, loads tenants for the user and keeps an
5
- * `activeTenant` the OrgSwitcher drives via `switchTenant`.
6
- */
7
-
8
- import {
9
- createContext,
10
- useCallback,
11
- useContext,
12
- useEffect,
13
- useMemo,
14
- useState,
15
- type ReactNode,
16
- } from "react";
17
- import type {
18
- AuthAdapter,
19
- LoginCredentials,
20
- SessionStatus,
21
- SessionUser,
22
- Tenant,
23
- } from "./types";
24
-
25
- export interface SessionProviderProps {
26
- adapter: AuthAdapter;
27
- children: ReactNode;
28
- }
29
-
30
- interface SessionContextValue {
31
- user: SessionUser | null;
32
- tenants: Tenant[];
33
- activeTenant: Tenant | null;
34
- status: SessionStatus;
35
- login: (credentials: LoginCredentials) => Promise<SessionUser>;
36
- logout: () => Promise<void>;
37
- demoLogin: (userId: string) => Promise<SessionUser>;
38
- switchTenant: (tenantId: string) => void;
39
- }
40
-
41
- const SessionContext = createContext<SessionContextValue | null>(null);
42
-
43
- export const SessionProvider = ({ adapter, children }: SessionProviderProps) => {
44
- const [user, setUser] = useState<SessionUser | null>(null);
45
- const [tenants, setTenants] = useState<Tenant[]>([]);
46
- const [activeTenantId, setActiveTenantId] = useState<string | null>(null);
47
- const [status, setStatus] = useState<SessionStatus>("loading");
48
-
49
- // Restore the session once on mount.
50
- useEffect(() => {
51
- let cancelled = false;
52
- adapter
53
- .current()
54
- .then((current) => {
55
- if (cancelled) return;
56
- setUser(current);
57
- setStatus(current ? "authenticated" : "anonymous");
58
- })
59
- .catch(() => {
60
- if (!cancelled) setStatus("anonymous");
61
- });
62
- return () => {
63
- cancelled = true;
64
- };
65
- }, [adapter]);
66
-
67
- // Load tenants whenever the authenticated user changes.
68
- useEffect(() => {
69
- if (!user || !adapter.listTenants) {
70
- setTenants([]);
71
- setActiveTenantId(null);
72
- return;
73
- }
74
- let cancelled = false;
75
- adapter
76
- .listTenants(user.id)
77
- .then((list) => {
78
- if (cancelled) return;
79
- setTenants(list);
80
- setActiveTenantId((prev) =>
81
- prev && list.some((tenant) => tenant.id === prev) ? prev : (list[0]?.id ?? null),
82
- );
83
- })
84
- .catch(() => {
85
- if (!cancelled) setTenants([]);
86
- });
87
- return () => {
88
- cancelled = true;
89
- };
90
- }, [adapter, user]);
91
-
92
- const login = useCallback(
93
- async (credentials: LoginCredentials) => {
94
- const next = await adapter.login(credentials);
95
- setUser(next);
96
- setStatus("authenticated");
97
- return next;
98
- },
99
- [adapter],
100
- );
101
-
102
- const logout = useCallback(async () => {
103
- await adapter.logout();
104
- setUser(null);
105
- setStatus("anonymous");
106
- }, [adapter]);
107
-
108
- const demoLogin = useCallback(
109
- async (userId: string) => {
110
- if (!adapter.demoLogin) {
111
- throw new Error("AuthAdapter does not support demoLogin");
112
- }
113
- const next = await adapter.demoLogin(userId);
114
- setUser(next);
115
- setStatus("authenticated");
116
- return next;
117
- },
118
- [adapter],
119
- );
120
-
121
- const switchTenant = useCallback((tenantId: string) => {
122
- setActiveTenantId(tenantId);
123
- }, []);
124
-
125
- const value = useMemo<SessionContextValue>(
126
- () => ({
127
- user,
128
- tenants,
129
- activeTenant: tenants.find((tenant) => tenant.id === activeTenantId) ?? null,
130
- status,
131
- login,
132
- logout,
133
- demoLogin,
134
- switchTenant,
135
- }),
136
- [user, tenants, activeTenantId, status, login, logout, demoLogin, switchTenant],
137
- );
138
-
139
- return (
140
- <SessionContext.Provider value={value}>{children}</SessionContext.Provider>
141
- );
142
- };
143
-
144
- export const useSession = (): SessionContextValue => {
145
- const context = useContext(SessionContext);
146
- if (!context) {
147
- throw new Error("useSession requires a <SessionProvider> ancestor");
148
- }
149
- return context;
150
- };
@@ -1,53 +0,0 @@
1
- /**
2
- * In-memory auth adapter — zero-dependency default for demos,
3
- * Storybook-style setups and tests. Credentials are NOT checked
4
- * (any password logs in); demo accounts log in by user id.
5
- */
6
-
7
- import type {
8
- AuthAdapter,
9
- LoginCredentials,
10
- SessionUser,
11
- } from "./types";
12
-
13
- export interface InMemoryAuthAdapterOptions {
14
- /** Users available for login/demo. */
15
- users: readonly SessionUser[];
16
- }
17
-
18
- export const createInMemoryAuthAdapter = ({
19
- users,
20
- }: InMemoryAuthAdapterOptions): AuthAdapter => {
21
- let currentUser: SessionUser | null = null;
22
-
23
- const findByEmail = (email: string): SessionUser | undefined =>
24
- users.find((user) => user.email === email);
25
-
26
- return {
27
- async login({ email }: LoginCredentials): Promise<SessionUser> {
28
- const user = findByEmail(email);
29
- if (!user) {
30
- throw new Error(`No user with email ${email}`);
31
- }
32
- currentUser = user;
33
- return user;
34
- },
35
-
36
- async logout(): Promise<void> {
37
- currentUser = null;
38
- },
39
-
40
- async current(): Promise<SessionUser | null> {
41
- return currentUser;
42
- },
43
-
44
- async demoLogin(userId: string): Promise<SessionUser> {
45
- const user = users.find((candidate) => candidate.id === userId);
46
- if (!user) {
47
- throw new Error(`No demo user with id ${userId}`);
48
- }
49
- currentUser = user;
50
- return user;
51
- },
52
- };
53
- };
@@ -1,18 +0,0 @@
1
- export {
2
- SessionProvider,
3
- useSession,
4
- type SessionProviderProps,
5
- } from "./SessionContext";
6
- export { OrgSwitcher, type OrgSwitcherProps } from "./OrgSwitcher";
7
- export { DemoLogin, type DemoLoginProps } from "./DemoLogin";
8
- export { createInMemoryAuthAdapter, type InMemoryAuthAdapterOptions } from "./inMemoryAuthAdapter";
9
- export {
10
- SESSION_KEYS,
11
- } from "./utils/i18nKeys";
12
- export type {
13
- AuthAdapter,
14
- LoginCredentials,
15
- SessionStatus,
16
- SessionUser,
17
- Tenant,
18
- } from "./types";
@@ -1,47 +0,0 @@
1
- /**
2
- * Session model — the host-facing auth contract.
3
- *
4
- * The package performs no authentication itself; hosts adapt their
5
- * provider (Firebase, Supabase, NEON-backed REST, mock...) to this
6
- * interface and hand it to <SessionProvider>.
7
- */
8
-
9
- /** Authenticated user as the dashboard presents it. */
10
- export interface SessionUser {
11
- id: string;
12
- name: string;
13
- email: string;
14
- /** Host role key — pairs with the permissions matrix. */
15
- role: string;
16
- avatarUrl?: string;
17
- }
18
-
19
- /** Tenant/organization the user may switch between. */
20
- export interface Tenant {
21
- id: string;
22
- name: string;
23
- /** Short initials for avatar-style rendering. */
24
- initials?: string;
25
- /** Optional plan badge (e.g. "starter" | "growth" | "enterprise"). */
26
- plan?: string;
27
- }
28
-
29
- export interface LoginCredentials {
30
- email: string;
31
- password: string;
32
- }
33
-
34
- /**
35
- * Auth adapter seam. `login`/`logout`/`current` are required;
36
- * `listTenants` and `demoLogin` power the multi-tenant switcher and
37
- * one-click demo entry when the host supports them.
38
- */
39
- export interface AuthAdapter {
40
- login(credentials: LoginCredentials): Promise<SessionUser>;
41
- logout(): Promise<void>;
42
- current(): Promise<SessionUser | null>;
43
- listTenants?(userId: string): Promise<Tenant[]>;
44
- demoLogin?(userId: string): Promise<SessionUser>;
45
- }
46
-
47
- export type SessionStatus = "loading" | "authenticated" | "anonymous";
@@ -1,12 +0,0 @@
1
- /**
2
- * Session domain i18n keys — the documented string contract.
3
- */
4
-
5
- export const SESSION_KEYS = {
6
- orgSwitcher: {
7
- label: "session.orgSwitcher.label",
8
- },
9
- demoLogin: {
10
- action: "session.demoLogin.action",
11
- },
12
- } as const;