@stokr/components-library 3.0.76 → 3.1.0-alpha.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.
- package/README.md +177 -177
- package/dist/components/Input/InputPassword.js +3 -5
- package/dist/components/Input/OtpInput.js +1 -3
- package/dist/components/MenuNav/MenuNav.styles.js +1 -2
- package/dist/components/Modal/Modal.js +6 -3
- package/dist/components/Modal/Modal.styles.js +2 -3
- package/dist/components/Modal/SuccessModal/SuccessModal.js +6 -3
- package/dist/components/Newsletter/Newsletter.js +1 -3
- package/dist/components/NotificationCounter/NotificationCounter.styles.js +1 -2
- package/dist/components/SmartLink/SmartLink.js +0 -2
- package/dist/components/StepController/StepController.js +3 -5
- package/dist/components/StepController/StepController.styles.js +102 -1
- package/dist/components/StepController/StepControllerProgress.js +1 -1
- package/dist/components/Switch/Switch.js +1 -3
- package/dist/components/ToDoList/ToDoListTask.js +15 -3
- package/dist/components/taxId/register-taxid.js +7 -5
- package/dist/index.js +67 -141
- package/dist/manifest.json +25 -25
- package/dist/robots.txt +3 -3
- package/dist/runtime-config.js +5 -71
- package/dist/static/fonts/icomoon/icomoon.eot +0 -0
- package/dist/static/fonts/icomoon/icomoon.svg +52 -52
- package/dist/static/fonts/icomoon/icomoon.ttf +0 -0
- package/dist/static/fonts/icomoon/icomoon.woff +0 -0
- package/dist/static/fonts/icomoon/selection.json +0 -0
- package/dist/static/fonts/icomoon/style.css +0 -0
- package/dist/static/images/Glassess.svg +5 -5
- package/dist/static/images/add-folder-icon.svg +4 -4
- package/dist/static/images/arrow-down-black.svg +21 -21
- package/dist/static/images/check-icon.svg +3 -3
- package/dist/static/images/checkmark-circle-icon.svg +3 -3
- package/dist/static/images/close-circle-icon.svg +2 -2
- package/dist/static/images/copy_icon.svg +4 -4
- package/dist/static/images/cross-icon.svg +3 -3
- package/dist/static/images/currency/eth.svg +10 -10
- package/dist/static/images/currency/eth_logo.svg +8 -8
- package/dist/static/images/currency/eur.svg +4 -4
- package/dist/static/images/currency/eur.svg.js +1 -1
- package/dist/static/images/currency/usd.svg +4 -4
- package/dist/static/images/currency/usd.svg.js +1 -1
- package/dist/static/images/currency/usdc-logo.svg +5 -5
- package/dist/static/images/doc-icon.svg +3 -3
- package/dist/static/images/download_icon.svg +3 -3
- package/dist/static/images/external-link-icon.svg +3 -3
- package/dist/static/images/filter-icon.svg +6 -6
- package/dist/static/images/globe.svg +15 -15
- package/dist/static/images/mangopay.svg +20 -20
- package/dist/static/images/numbers/number_eight.svg +3 -3
- package/dist/static/images/numbers/number_five.svg +4 -4
- package/dist/static/images/numbers/number_four.svg +3 -3
- package/dist/static/images/numbers/number_nine.svg +4 -4
- package/dist/static/images/numbers/number_one.svg +4 -4
- package/dist/static/images/numbers/number_seven.svg +4 -4
- package/dist/static/images/numbers/number_six.svg +4 -4
- package/dist/static/images/numbers/number_three.svg +3 -3
- package/dist/static/images/numbers/number_two.svg +4 -4
- package/dist/static/images/numbers/number_zero.svg +3 -3
- package/dist/static/images/plus-icon.svg +4 -4
- package/dist/static/images/prof-inv.svg +3 -3
- package/dist/static/images/search-icon.svg +3 -3
- package/dist/static/images/transfer-icon.svg +10 -10
- package/dist/static/images/trash.svg +16 -16
- package/dist/static/images/upload.svg +5 -5
- package/dist/static/images/warning-filled.svg +3 -3
- package/dist/styles/global.js +1 -2
- package/dist/utils/check-todo-status.js +1 -2
- package/package.json +137 -143
- package/dist/api/authenticationApi.js +0 -13
- package/dist/auth/index.js +0 -34
- package/dist/components/2FA/Connect2FA.js +0 -58
- package/dist/components/2FA/EnterCode.js +0 -74
- package/dist/components/2FA/InstallAuthApp.js +0 -68
- package/dist/components/2FA/ResetCode.js +0 -34
- package/dist/components/2FA/Sucess2FA.js +0 -63
- package/dist/components/2FA/disable-2fa-flow.js +0 -104
- package/dist/components/2FA/enable-2fa-flow.js +0 -167
- package/dist/components/2FA/login-with-otp-flow.js +0 -262
- package/dist/components/2FA/main-flow.js +0 -273
- package/dist/components/Footer/Footer.js +0 -69
- package/dist/components/Footer/Footer.styles.js +0 -277
- package/dist/components/Footer/FooterLayout.js +0 -150
- package/dist/components/Footer/FooterMenu.js +0 -107
- package/dist/components/Footer/FooterMenu.styles.js +0 -334
- package/dist/components/ForgotPasswordModal/ForgotPasswordModal.js +0 -121
- package/dist/components/Header/Header.js +0 -441
- package/dist/components/Header/Header.styles.js +0 -568
- package/dist/components/Layout/Layout.js +0 -76
- package/dist/components/LoginModal/LoginModal.js +0 -165
- package/dist/components/MainMenu/DynamicMainMenu.js +0 -38
- package/dist/components/MainMenu/MainMenu.js +0 -220
- package/dist/components/MainMenu/MainMenu.styles.js +0 -362
- package/dist/components/Modal/NewVentureModal/NewVentureModal.js +0 -273
- package/dist/components/RegisterConfirmModal/RegisterConfirmModal.js +0 -74
- package/dist/components/RegisterConfirmModal/RegisterConfirmModal.styles.js +0 -20
- package/dist/components/RegisterModal/RegisterModal.js +0 -278
- package/dist/components/ResetConfirmModal/ResetConfirmModal.js +0 -40
- package/dist/components/ResetConfirmModal/ResetConfirmModal.styles.js +0 -41
- package/dist/components/ResetPasswordModal/ResetPasswordModal.js +0 -145
- package/dist/components/StepsProgress/StepIndicator.js +0 -40
- package/dist/components/StepsProgress/StepIndicator.styles.js +0 -69
- package/dist/components/StepsProgress/StepsProgress.js +0 -67
- package/dist/components/StepsProgress/StepsProgress.styles.js +0 -105
- package/dist/components/TermsModal/TermsModal.js +0 -145
- package/dist/components/TermsModal/_styles.js +0 -313
- package/dist/components/VerifyEmailModal/VerifyEmailModal.js +0 -122
- package/dist/components/headerHo/HeaderHo.js +0 -707
- package/dist/config.js +0 -33
- package/dist/context/Auth.js +0 -423
- package/dist/context/AuthContext.js +0 -1016
- package/dist/firebase-config.js +0 -56
- package/dist/hooks/useNewVentureForm.js +0 -235
- package/dist/static/images/background3.png.js +0 -4
- package/dist/static/images/google_auth.png.js +0 -4
- package/dist/static/images/iso27001-black.svg.js +0 -4
- package/dist/static/images/mangopay.svg.js +0 -4
- package/dist/static/images/social/Facebook_Logo.png.js +0 -4
- package/dist/static/images/social/LI-In-Bug.png.js +0 -4
- package/dist/static/images/social/Telegram-Logo.png.js +0 -4
- package/dist/static/images/social/X-logo-black.png.js +0 -4
- package/dist/static/images/social/youtube_social_circle_red.png.js +0 -4
- package/dist/utils/show-account-locked-modal.js +0 -23
- package/dist/utils/user-identity.js +0 -10
- package/dist/utils/withRouter.js +0 -26
package/README.md
CHANGED
|
@@ -1,177 +1,177 @@
|
|
|
1
|
-
# @stokr/components-library
|
|
2
|
-
|
|
3
|
-
React UI library for STOKR apps: modals, forms, navigation, tables, auth context, styles.
|
|
4
|
-
|
|
5
|
-
## Contents
|
|
6
|
-
|
|
7
|
-
- [Quick start](#quick-start) — install, router, `AuthProvider`, styles
|
|
8
|
-
- [Configuration reference](#runtime-config) — `config` keys & helpers
|
|
9
|
-
- [AuthProvider & AuthContext](#authprovider-optional-props)
|
|
10
|
-
- [Troubleshooting](#troubleshooting)
|
|
11
|
-
- [Development](#development--publishing)
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## Quick start
|
|
16
|
-
|
|
17
|
-
**Install**
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
npm install @stokr/components-library
|
|
21
|
-
npm install react react-dom styled-components react-router-dom
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Peers: React 18+/19+, styled-components 6.x, react-router-dom 6.x when you use routing-driven components (`HeaderHo`, `MainMenu`, …).
|
|
25
|
-
|
|
26
|
-
**1. Router** — Navigation helpers need a React Router:
|
|
27
|
-
|
|
28
|
-
```jsx
|
|
29
|
-
import { BrowserRouter } from 'react-router-dom'
|
|
30
|
-
import { RouterWrapper } from '@stokr/components-library'
|
|
31
|
-
|
|
32
|
-
// Normal app
|
|
33
|
-
root.render(
|
|
34
|
-
<BrowserRouter>
|
|
35
|
-
<App />
|
|
36
|
-
</BrowserRouter>,
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
// Outside a Router: RouterWrapper wraps children in BrowserRouter once.
|
|
40
|
-
// Inside an existing Router: it renders children only (no nested BrowserRouter).
|
|
41
|
-
root.render(
|
|
42
|
-
<RouterWrapper>
|
|
43
|
-
<App />
|
|
44
|
-
</RouterWrapper>,
|
|
45
|
-
)
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
**2. Auth & runtime config (required when consuming via npm)** — Vite freezes `import.meta.env` inside pre-built deps, so push your `.env` at runtime via `config`:
|
|
49
|
-
|
|
50
|
-
```jsx
|
|
51
|
-
import { AuthProvider } from '@stokr/components-library'
|
|
52
|
-
|
|
53
|
-
export default function App() {
|
|
54
|
-
return (
|
|
55
|
-
<AuthProvider
|
|
56
|
-
config={{
|
|
57
|
-
apiUrl: import.meta.env.VITE_API_URL,
|
|
58
|
-
baseUrlPublic: import.meta.env.VITE_BASE_URL_PUBLIC,
|
|
59
|
-
cookieDomain: import.meta.env.VITE_COOKIE_DOMAIN,
|
|
60
|
-
websiteDomain: import.meta.env.VITE_WEBSITE_DOMAIN,
|
|
61
|
-
onboardingUrl: import.meta.env.VITE_ONBOARDING_URL,
|
|
62
|
-
dashboardUrl: import.meta.env.VITE_DASHBOARD_URL,
|
|
63
|
-
adminUrl: import.meta.env.VITE_ADMIN_URL,
|
|
64
|
-
registerUrl: import.meta.env.VITE_REGISTER_URL,
|
|
65
|
-
firebase: {
|
|
66
|
-
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
|
|
67
|
-
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
|
|
68
|
-
projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
|
|
69
|
-
storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
|
|
70
|
-
messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
|
|
71
|
-
appId: import.meta.env.VITE_FIREBASE_APP_ID,
|
|
72
|
-
measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,
|
|
73
|
-
},
|
|
74
|
-
}}>
|
|
75
|
-
{/* app */}
|
|
76
|
-
</AuthProvider>
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
**3. Earlier config** (e.g. analytics before mount): `import { configure } from '@stokr/components-library'` with the same shape as `config`.
|
|
82
|
-
|
|
83
|
-
**4. Icons / fonts** — Optional: `<IoniconsStyles />` at root, or rely on lazy injection when a component uses icons; for Layout / Open Sans: `import '@stokr/components-library/styles.css'`.
|
|
84
|
-
|
|
85
|
-
**5. Imports** — `import { ConfirmModal, Button, … } from '@stokr/components-library'`.
|
|
86
|
-
|
|
87
|
-
Full URL env example:
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
VITE_WEBSITE_DOMAIN=example.com
|
|
91
|
-
VITE_ONBOARDING_URL=https://signup.example.com
|
|
92
|
-
VITE_DASHBOARD_URL=https://dashboard.example.com
|
|
93
|
-
VITE_ADMIN_URL=https://admin.example.com
|
|
94
|
-
VITE_REGISTER_URL=https://example.com/signup
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## Configuration reference {#runtime-config}
|
|
100
|
-
|
|
101
|
-
| `config` key | Typical `VITE_*` | Role |
|
|
102
|
-
| ----------------- | -------------------------- | ----------------------------------------- |
|
|
103
|
-
| `apiUrl` | `VITE_API_URL` | Authenticated REST base |
|
|
104
|
-
| `baseUrlPublic` | `VITE_BASE_URL_PUBLIC` | Public API base |
|
|
105
|
-
| `cookieDomain` | `VITE_COOKIE_DOMAIN` | Auth cookie `domain` attribute |
|
|
106
|
-
| `websiteDomain` | `VITE_WEBSITE_DOMAIN` | Bare host → links / `getPlatformURL()` |
|
|
107
|
-
| `onboardingUrl` | `VITE_ONBOARDING_URL` | Full signup/sign-in app URL |
|
|
108
|
-
| `dashboardUrl` | `VITE_DASHBOARD_URL` | Investor dashboard URL |
|
|
109
|
-
| `adminUrl` | `VITE_ADMIN_URL` | Venture / admin dashboard URL |
|
|
110
|
-
| `registerUrl` | `VITE_REGISTER_URL` | Public registration entry |
|
|
111
|
-
| `firebase` | `VITE_FIREBASE_*` | Firebase client config |
|
|
112
|
-
|
|
113
|
-
**Helpers:** `getConfig('…')` for any key above; `getPlatformURL()` → `https://{websiteDomain}`; `getAnalyticsIngestUrl()`, `getBackofficeAppUrl(path)`; **`getFooterGroups()`** replaces static footer URL lists.
|
|
114
|
-
|
|
115
|
-
**Auth-only HTTP:** `authenticationApi.post(segment, body)` for `auth/*`; default axios stays the main API client after login.
|
|
116
|
-
|
|
117
|
-
Missing overrides may trigger a **one-time** warning listing unresolved `VITE_*` expectations.
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
## AuthProvider & AuthContext {#authprovider-optional-props}
|
|
122
|
-
|
|
123
|
-
`AuthProvider` is wrapped with **`withRouter`** — mount it inside a **`Router`** so redirects work.
|
|
124
|
-
|
|
125
|
-
### Optional provider props
|
|
126
|
-
|
|
127
|
-
- **`inactivityTimeMs`** — Idle timeout before auto-logout + session modal (default 5 min).
|
|
128
|
-
- **`inactivityWarningBeforeMs`** — How long before that timeout to show the **“session about to expire”** warning modal (default 30 s). See [Inactivity auto-logout](#inactivity-auto-logout).
|
|
129
|
-
- **`accessTokenExpiryMs`** — Cookie TTL when **`Auth.setAccessToken`** runs (default **`DEFAULT_TOKEN_EXPIRY_MS`** = 1 h); not extended by **`getUser`** alone.
|
|
130
|
-
- **`hideInactivityModal`** — Suppress both built-in inactivity modals (warning + session expired).
|
|
131
|
-
- **`onSessionExpiredLoginClick`** — Called when the user clicks **Log in** on the session-expired modal.
|
|
132
|
-
- **`customValidateGetUser(user)`** — Hook after **`user/get`** succeeds (see `src/context/AuthContext.js`).
|
|
133
|
-
|
|
134
|
-
### Inactivity auto-logout {#inactivity-auto-logout}
|
|
135
|
-
|
|
136
|
-
When a user is logged in, `AuthProvider` resets an idle timer on mouse, keyboard, click, scroll, and touch events.
|
|
137
|
-
|
|
138
|
-
1. **Warning modal** — Shown **`inactivityWarningBeforeMs`** before the idle deadline (default: 30 s before the 5 min timeout). The user can click **To continue, press here** to reset the idle timer, or close the modal (logout still happens at the deadline). Any activity also resets the timer and closes the warning.
|
|
139
|
-
2. **Session expired modal** — Shown when the idle deadline is reached (existing behaviour). The warning modal closes automatically at the same moment.
|
|
140
|
-
|
|
141
|
-
Neither modal is shown when the user is not logged in. Both are skipped when **`hideInactivityModal`** is set.
|
|
142
|
-
|
|
143
|
-
**Storybook:** `Authentication / Auto-logout (inactivity)` → **With warning modal** (20 s idle, warning at 10 s).
|
|
144
|
-
|
|
145
|
-
### AuthContext consumer {#authcontext-usecontext}
|
|
146
|
-
|
|
147
|
-
`import { AuthContext } from '…'` then `useContext(AuthContext)`.
|
|
148
|
-
|
|
149
|
-
- **Invalid Firebase guard:** value is **`{ user: null, isFetchingUser: false }`** only (no methods).
|
|
150
|
-
- **State (grouped):** `user` / `firebaseUser`, `isFetchingUser`, `avatar`; MFA (`waitingFor2fa`, `userMfaEnrollment`, `firebaseError`); verify-email (`verifyEmailError`, `isVerifyingEmail`); session UX (`loggedOutDueToInactivity`, `loggedOutDueToCookieExpiry`, `sessionExpiryPendingReason`, `showInactivityWarningModal`).
|
|
151
|
-
- **Actions (grouped):** `userRef`, `loginUser`, `logoutUser`, `getUser`, `setUser`, `updateUser`, `refreshIdToken`; `checkUserIsValid`, `checkTokenIsValid`; `uploadPhoto`, `deletePhoto`, `checkUserPhoto`; MFA enroll / verify / unenroll + `reset2faFlow`; subscription/onboarding helpers; password & email (`handleResetPassword`, `handleVerifyEmail`, `requestUpdateEmail`, …); wallets / PoA (`uploaProofOfAddress` keeps the source spelling); **`dismissSessionExpiryModal`**, **`extendSessionFromInactivityWarning`**, **`dismissInactivityWarningModal`**.
|
|
152
|
-
|
|
153
|
-
Use **`AuthConsumer`** for the render-prop pattern.
|
|
154
|
-
|
|
155
|
-
---
|
|
156
|
-
|
|
157
|
-
## Troubleshooting {#troubleshooting}
|
|
158
|
-
|
|
159
|
-
**`useNavigate` / Router**
|
|
160
|
-
|
|
161
|
-
Add `BrowserRouter` (or **`RouterWrapper`** from this package where the shell has no router). Install `react-router-dom`.
|
|
162
|
-
|
|
163
|
-
**Invalid hook call / duplicated React**
|
|
164
|
-
|
|
165
|
-
Dedupe peers in Vite: `resolve: { dedupe: ['react', 'react-dom', 'styled-components'] }`.
|
|
166
|
-
|
|
167
|
-
---
|
|
168
|
-
|
|
169
|
-
## Development {#development--publishing}
|
|
170
|
-
|
|
171
|
-
| Command | Meaning |
|
|
172
|
-
| -------------------- | -------------------------------- |
|
|
173
|
-
| `npm run storybook` | Local docs / stories |
|
|
174
|
-
| `npm run build:dist` | Library build + static copy |
|
|
175
|
-
| `npm run pub` | Build then publish (`npm login`) |
|
|
176
|
-
|
|
177
|
-
Release: changelog entry → `npm version` → `npm run pub`. Details: [CHANGELOG.md](CHANGELOG.md).
|
|
1
|
+
# @stokr/components-library
|
|
2
|
+
|
|
3
|
+
React UI library for STOKR apps: modals, forms, navigation, tables, auth context, styles.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- [Quick start](#quick-start) — install, router, `AuthProvider`, styles
|
|
8
|
+
- [Configuration reference](#runtime-config) — `config` keys & helpers
|
|
9
|
+
- [AuthProvider & AuthContext](#authprovider-optional-props)
|
|
10
|
+
- [Troubleshooting](#troubleshooting)
|
|
11
|
+
- [Development](#development--publishing)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
**Install**
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @stokr/components-library
|
|
21
|
+
npm install react react-dom styled-components react-router-dom
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Peers: React 18+/19+, styled-components 6.x, react-router-dom 6.x when you use routing-driven components (`HeaderHo`, `MainMenu`, …).
|
|
25
|
+
|
|
26
|
+
**1. Router** — Navigation helpers need a React Router:
|
|
27
|
+
|
|
28
|
+
```jsx
|
|
29
|
+
import { BrowserRouter } from 'react-router-dom'
|
|
30
|
+
import { RouterWrapper } from '@stokr/components-library'
|
|
31
|
+
|
|
32
|
+
// Normal app
|
|
33
|
+
root.render(
|
|
34
|
+
<BrowserRouter>
|
|
35
|
+
<App />
|
|
36
|
+
</BrowserRouter>,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
// Outside a Router: RouterWrapper wraps children in BrowserRouter once.
|
|
40
|
+
// Inside an existing Router: it renders children only (no nested BrowserRouter).
|
|
41
|
+
root.render(
|
|
42
|
+
<RouterWrapper>
|
|
43
|
+
<App />
|
|
44
|
+
</RouterWrapper>,
|
|
45
|
+
)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**2. Auth & runtime config (required when consuming via npm)** — Vite freezes `import.meta.env` inside pre-built deps, so push your `.env` at runtime via `config`:
|
|
49
|
+
|
|
50
|
+
```jsx
|
|
51
|
+
import { AuthProvider } from '@stokr/components-library'
|
|
52
|
+
|
|
53
|
+
export default function App() {
|
|
54
|
+
return (
|
|
55
|
+
<AuthProvider
|
|
56
|
+
config={{
|
|
57
|
+
apiUrl: import.meta.env.VITE_API_URL,
|
|
58
|
+
baseUrlPublic: import.meta.env.VITE_BASE_URL_PUBLIC,
|
|
59
|
+
cookieDomain: import.meta.env.VITE_COOKIE_DOMAIN,
|
|
60
|
+
websiteDomain: import.meta.env.VITE_WEBSITE_DOMAIN,
|
|
61
|
+
onboardingUrl: import.meta.env.VITE_ONBOARDING_URL,
|
|
62
|
+
dashboardUrl: import.meta.env.VITE_DASHBOARD_URL,
|
|
63
|
+
adminUrl: import.meta.env.VITE_ADMIN_URL,
|
|
64
|
+
registerUrl: import.meta.env.VITE_REGISTER_URL,
|
|
65
|
+
firebase: {
|
|
66
|
+
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
|
|
67
|
+
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
|
|
68
|
+
projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
|
|
69
|
+
storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
|
|
70
|
+
messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
|
|
71
|
+
appId: import.meta.env.VITE_FIREBASE_APP_ID,
|
|
72
|
+
measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,
|
|
73
|
+
},
|
|
74
|
+
}}>
|
|
75
|
+
{/* app */}
|
|
76
|
+
</AuthProvider>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**3. Earlier config** (e.g. analytics before mount): `import { configure } from '@stokr/components-library'` with the same shape as `config`.
|
|
82
|
+
|
|
83
|
+
**4. Icons / fonts** — Optional: `<IoniconsStyles />` at root, or rely on lazy injection when a component uses icons; for Layout / Open Sans: `import '@stokr/components-library/styles.css'`.
|
|
84
|
+
|
|
85
|
+
**5. Imports** — `import { ConfirmModal, Button, … } from '@stokr/components-library'`.
|
|
86
|
+
|
|
87
|
+
Full URL env example:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
VITE_WEBSITE_DOMAIN=example.com
|
|
91
|
+
VITE_ONBOARDING_URL=https://signup.example.com
|
|
92
|
+
VITE_DASHBOARD_URL=https://dashboard.example.com
|
|
93
|
+
VITE_ADMIN_URL=https://admin.example.com
|
|
94
|
+
VITE_REGISTER_URL=https://example.com/signup
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Configuration reference {#runtime-config}
|
|
100
|
+
|
|
101
|
+
| `config` key | Typical `VITE_*` | Role |
|
|
102
|
+
| ----------------- | -------------------------- | ----------------------------------------- |
|
|
103
|
+
| `apiUrl` | `VITE_API_URL` | Authenticated REST base |
|
|
104
|
+
| `baseUrlPublic` | `VITE_BASE_URL_PUBLIC` | Public API base |
|
|
105
|
+
| `cookieDomain` | `VITE_COOKIE_DOMAIN` | Auth cookie `domain` attribute |
|
|
106
|
+
| `websiteDomain` | `VITE_WEBSITE_DOMAIN` | Bare host → links / `getPlatformURL()` |
|
|
107
|
+
| `onboardingUrl` | `VITE_ONBOARDING_URL` | Full signup/sign-in app URL |
|
|
108
|
+
| `dashboardUrl` | `VITE_DASHBOARD_URL` | Investor dashboard URL |
|
|
109
|
+
| `adminUrl` | `VITE_ADMIN_URL` | Venture / admin dashboard URL |
|
|
110
|
+
| `registerUrl` | `VITE_REGISTER_URL` | Public registration entry |
|
|
111
|
+
| `firebase` | `VITE_FIREBASE_*` | Firebase client config |
|
|
112
|
+
|
|
113
|
+
**Helpers:** `getConfig('…')` for any key above; `getPlatformURL()` → `https://{websiteDomain}`; `getAnalyticsIngestUrl()`, `getBackofficeAppUrl(path)`; **`getFooterGroups()`** replaces static footer URL lists.
|
|
114
|
+
|
|
115
|
+
**Auth-only HTTP:** `authenticationApi.post(segment, body)` for `auth/*`; default axios stays the main API client after login.
|
|
116
|
+
|
|
117
|
+
Missing overrides may trigger a **one-time** warning listing unresolved `VITE_*` expectations.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## AuthProvider & AuthContext {#authprovider-optional-props}
|
|
122
|
+
|
|
123
|
+
`AuthProvider` is wrapped with **`withRouter`** — mount it inside a **`Router`** so redirects work.
|
|
124
|
+
|
|
125
|
+
### Optional provider props
|
|
126
|
+
|
|
127
|
+
- **`inactivityTimeMs`** — Idle timeout before auto-logout + session modal (default 5 min).
|
|
128
|
+
- **`inactivityWarningBeforeMs`** — How long before that timeout to show the **“session about to expire”** warning modal (default 30 s). See [Inactivity auto-logout](#inactivity-auto-logout).
|
|
129
|
+
- **`accessTokenExpiryMs`** — Cookie TTL when **`Auth.setAccessToken`** runs (default **`DEFAULT_TOKEN_EXPIRY_MS`** = 1 h); not extended by **`getUser`** alone.
|
|
130
|
+
- **`hideInactivityModal`** — Suppress both built-in inactivity modals (warning + session expired).
|
|
131
|
+
- **`onSessionExpiredLoginClick`** — Called when the user clicks **Log in** on the session-expired modal.
|
|
132
|
+
- **`customValidateGetUser(user)`** — Hook after **`user/get`** succeeds (see `src/context/AuthContext.js`).
|
|
133
|
+
|
|
134
|
+
### Inactivity auto-logout {#inactivity-auto-logout}
|
|
135
|
+
|
|
136
|
+
When a user is logged in, `AuthProvider` resets an idle timer on mouse, keyboard, click, scroll, and touch events.
|
|
137
|
+
|
|
138
|
+
1. **Warning modal** — Shown **`inactivityWarningBeforeMs`** before the idle deadline (default: 30 s before the 5 min timeout). The user can click **To continue, press here** to reset the idle timer, or close the modal (logout still happens at the deadline). Any activity also resets the timer and closes the warning.
|
|
139
|
+
2. **Session expired modal** — Shown when the idle deadline is reached (existing behaviour). The warning modal closes automatically at the same moment.
|
|
140
|
+
|
|
141
|
+
Neither modal is shown when the user is not logged in. Both are skipped when **`hideInactivityModal`** is set.
|
|
142
|
+
|
|
143
|
+
**Storybook:** `Authentication / Auto-logout (inactivity)` → **With warning modal** (20 s idle, warning at 10 s).
|
|
144
|
+
|
|
145
|
+
### AuthContext consumer {#authcontext-usecontext}
|
|
146
|
+
|
|
147
|
+
`import { AuthContext } from '…'` then `useContext(AuthContext)`.
|
|
148
|
+
|
|
149
|
+
- **Invalid Firebase guard:** value is **`{ user: null, isFetchingUser: false }`** only (no methods).
|
|
150
|
+
- **State (grouped):** `user` / `firebaseUser`, `isFetchingUser`, `avatar`; MFA (`waitingFor2fa`, `userMfaEnrollment`, `firebaseError`); verify-email (`verifyEmailError`, `isVerifyingEmail`); session UX (`loggedOutDueToInactivity`, `loggedOutDueToCookieExpiry`, `sessionExpiryPendingReason`, `showInactivityWarningModal`).
|
|
151
|
+
- **Actions (grouped):** `userRef`, `loginUser`, `logoutUser`, `getUser`, `setUser`, `updateUser`, `refreshIdToken`; `checkUserIsValid`, `checkTokenIsValid`; `uploadPhoto`, `deletePhoto`, `checkUserPhoto`; MFA enroll / verify / unenroll + `reset2faFlow`; subscription/onboarding helpers; password & email (`handleResetPassword`, `handleVerifyEmail`, `requestUpdateEmail`, …); wallets / PoA (`uploaProofOfAddress` keeps the source spelling); **`dismissSessionExpiryModal`**, **`extendSessionFromInactivityWarning`**, **`dismissInactivityWarningModal`**.
|
|
152
|
+
|
|
153
|
+
Use **`AuthConsumer`** for the render-prop pattern.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Troubleshooting {#troubleshooting}
|
|
158
|
+
|
|
159
|
+
**`useNavigate` / Router**
|
|
160
|
+
|
|
161
|
+
Add `BrowserRouter` (or **`RouterWrapper`** from this package where the shell has no router). Install `react-router-dom`.
|
|
162
|
+
|
|
163
|
+
**Invalid hook call / duplicated React**
|
|
164
|
+
|
|
165
|
+
Dedupe peers in Vite: `resolve: { dedupe: ['react', 'react-dom', 'styled-components'] }`.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Development {#development--publishing}
|
|
170
|
+
|
|
171
|
+
| Command | Meaning |
|
|
172
|
+
| -------------------- | -------------------------------- |
|
|
173
|
+
| `npm run storybook` | Local docs / stories |
|
|
174
|
+
| `npm run build:dist` | Library build + static copy |
|
|
175
|
+
| `npm run pub` | Build then publish (`npm login`) |
|
|
176
|
+
|
|
177
|
+
Release: changelog entry → `npm version` → `npm run pub`. Details: [CHANGELOG.md](CHANGELOG.md).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
|
-
import stdin_default
|
|
4
|
+
import stdin_default from "../SvgIcons/CapsLockSvg.js";
|
|
5
5
|
import { InfoIcon } from "../InfoIcon/InfoIcon.js";
|
|
6
6
|
import { Wrapper, Label, InputWrap } from "./Input.styles.js";
|
|
7
7
|
import { getPasswordEntropy, ENTROPY_WEAK, ENTROPY_MEDIUM } from "../../utils/password-validation.js";
|
|
@@ -105,7 +105,7 @@ const InputPassword = (props) => {
|
|
|
105
105
|
// )
|
|
106
106
|
/* @__PURE__ */ jsx(Fragment, {})
|
|
107
107
|
),
|
|
108
|
-
/* @__PURE__ */ jsx(CapslockIndicator, { children: isCapslockOn && /* @__PURE__ */ jsx(stdin_default
|
|
108
|
+
/* @__PURE__ */ jsx(CapslockIndicator, { children: isCapslockOn && /* @__PURE__ */ jsx(stdin_default, {}) })
|
|
109
109
|
] })
|
|
110
110
|
] });
|
|
111
111
|
};
|
|
@@ -124,9 +124,7 @@ InputPassword.propTypes = {
|
|
|
124
124
|
autoComplete: PropTypes.string,
|
|
125
125
|
toggleDataCy: PropTypes.string
|
|
126
126
|
};
|
|
127
|
-
var stdin_default = InputPassword;
|
|
128
127
|
export {
|
|
129
128
|
InputPassword,
|
|
130
|
-
PasswordStrength
|
|
131
|
-
stdin_default as default
|
|
129
|
+
PasswordStrength
|
|
132
130
|
};
|
|
@@ -18,7 +18,8 @@ const Modal = ({
|
|
|
18
18
|
background,
|
|
19
19
|
maxHeight,
|
|
20
20
|
boxStyles,
|
|
21
|
-
maxWidth
|
|
21
|
+
maxWidth,
|
|
22
|
+
hideCloseButton = false
|
|
22
23
|
}) => {
|
|
23
24
|
const [isVisible, setIsVisible] = useState(false);
|
|
24
25
|
const [shouldRender, setShouldRender] = useState(false);
|
|
@@ -80,7 +81,7 @@ const Modal = ({
|
|
|
80
81
|
maxHeight,
|
|
81
82
|
maxWidth,
|
|
82
83
|
children: [
|
|
83
|
-
/* @__PURE__ */ jsx(ModalClose, { onClick: onClose }),
|
|
84
|
+
!hideCloseButton && /* @__PURE__ */ jsx(ModalClose, { onClick: onClose }),
|
|
84
85
|
children
|
|
85
86
|
]
|
|
86
87
|
}
|
|
@@ -101,7 +102,9 @@ Modal.propTypes = {
|
|
|
101
102
|
boxStyle: PropTypes.object,
|
|
102
103
|
maxHeight: PropTypes.string,
|
|
103
104
|
/** Max width limit in pixels (e.g., '1200px'). Uses min(percentage, maxWidth) */
|
|
104
|
-
maxWidth: PropTypes.string
|
|
105
|
+
maxWidth: PropTypes.string,
|
|
106
|
+
/** Hides the (X) close button — for flows where the modal is dismissed only via its own actions. */
|
|
107
|
+
hideCloseButton: PropTypes.bool
|
|
105
108
|
};
|
|
106
109
|
export {
|
|
107
110
|
Modal,
|
|
@@ -393,7 +393,7 @@ const ModalLink = styled(Link)`
|
|
|
393
393
|
}
|
|
394
394
|
}
|
|
395
395
|
`;
|
|
396
|
-
|
|
396
|
+
styled.div`
|
|
397
397
|
display: flex;
|
|
398
398
|
flex-direction: column;
|
|
399
399
|
height: 100%;
|
|
@@ -453,6 +453,5 @@ export {
|
|
|
453
453
|
ModalLink,
|
|
454
454
|
ModalLinkWrap,
|
|
455
455
|
ModalRoot,
|
|
456
|
-
ModalScroll
|
|
457
|
-
ModalWrapper
|
|
456
|
+
ModalScroll
|
|
458
457
|
};
|
|
@@ -18,7 +18,8 @@ const SuccessModalComponent = ({
|
|
|
18
18
|
segment,
|
|
19
19
|
speed = 1,
|
|
20
20
|
modalProps = {},
|
|
21
|
-
maxWidth = "800px"
|
|
21
|
+
maxWidth = "800px",
|
|
22
|
+
hideAnimation = false
|
|
22
23
|
}) => {
|
|
23
24
|
useEffect(() => {
|
|
24
25
|
if (!isOpen) return;
|
|
@@ -40,7 +41,7 @@ const SuccessModalComponent = ({
|
|
|
40
41
|
maxWidth,
|
|
41
42
|
...modalProps,
|
|
42
43
|
children: /* @__PURE__ */ jsxs(SuccessModalContent, { children: [
|
|
43
|
-
/* @__PURE__ */ jsx(AnimationContainer, { children: /* @__PURE__ */ jsx(
|
|
44
|
+
!hideAnimation && /* @__PURE__ */ jsx(AnimationContainer, { children: /* @__PURE__ */ jsx(
|
|
44
45
|
LottieAnimation,
|
|
45
46
|
{
|
|
46
47
|
variant,
|
|
@@ -72,7 +73,9 @@ SuccessModalComponent.propTypes = {
|
|
|
72
73
|
segment: PropTypes.arrayOf(PropTypes.number),
|
|
73
74
|
speed: PropTypes.number,
|
|
74
75
|
modalProps: PropTypes.object,
|
|
75
|
-
maxWidth: PropTypes.string
|
|
76
|
+
maxWidth: PropTypes.string,
|
|
77
|
+
/** Skips the animation container entirely (e.g. a plain form step with no success/progress state). */
|
|
78
|
+
hideAnimation: PropTypes.bool
|
|
76
79
|
};
|
|
77
80
|
let successContainer = null;
|
|
78
81
|
let successRoot = null;
|
|
@@ -2,7 +2,7 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
import { Transition } from "../../utils/transition.js";
|
|
4
4
|
import React__default, { PureComponent, Fragment } from "react";
|
|
5
|
-
import stdin_default
|
|
5
|
+
import stdin_default from "./StepControllerProgress.js";
|
|
6
6
|
import { StepsProgressContainer, StepContainer } from "./StepController.styles.js";
|
|
7
7
|
const timeout = 300;
|
|
8
8
|
const getTransitionStyles = {
|
|
@@ -30,7 +30,7 @@ class StepController extends PureComponent {
|
|
|
30
30
|
const { children, stepsProgressList, currentStep, activeStepIndex, doneStepsIndexes, touchedStepsIndexes } = this.props;
|
|
31
31
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
32
32
|
/* @__PURE__ */ jsx(StepsProgressContainer, { children: /* @__PURE__ */ jsx(
|
|
33
|
-
stdin_default
|
|
33
|
+
stdin_default,
|
|
34
34
|
{
|
|
35
35
|
activeStepIndex,
|
|
36
36
|
doneStepsIndexes,
|
|
@@ -77,8 +77,6 @@ StepController.propTypes = {
|
|
|
77
77
|
doneStepsIndexes: PropTypes.arrayOf(PropTypes.number).isRequired,
|
|
78
78
|
changeStep: PropTypes.func.isRequired
|
|
79
79
|
};
|
|
80
|
-
var stdin_default = StepController;
|
|
81
80
|
export {
|
|
82
|
-
StepController
|
|
83
|
-
stdin_default as default
|
|
81
|
+
StepController
|
|
84
82
|
};
|
|
@@ -1,6 +1,103 @@
|
|
|
1
1
|
import styled from "styled-components";
|
|
2
2
|
import rwd from "../../styles/rwd.js";
|
|
3
3
|
import theme from "../../styles/theme.js";
|
|
4
|
+
import { colors } from "../../styles/colors.js";
|
|
5
|
+
const Container = styled.div`
|
|
6
|
+
display: block;
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 100%;
|
|
9
|
+
`;
|
|
10
|
+
const Wrap = styled.div`
|
|
11
|
+
display: block;
|
|
12
|
+
margin: 0 auto;
|
|
13
|
+
`;
|
|
14
|
+
const Items = styled.div`
|
|
15
|
+
display: flex;
|
|
16
|
+
height: 100%;
|
|
17
|
+
font-size: 0;
|
|
18
|
+
flex-direction: row;
|
|
19
|
+
flex-wrap: nowrap;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
margin: 0 -6px;
|
|
22
|
+
text-align: center;
|
|
23
|
+
|
|
24
|
+
${rwd.Medium`
|
|
25
|
+
display: block;
|
|
26
|
+
`}
|
|
27
|
+
`;
|
|
28
|
+
const Item = styled.div.withConfig({
|
|
29
|
+
shouldForwardProp: (props) => !["isDone", "isActive"].includes(props)
|
|
30
|
+
})`
|
|
31
|
+
position: relative;
|
|
32
|
+
display: inline-block;
|
|
33
|
+
vertical-align: middle;
|
|
34
|
+
padding: 0;
|
|
35
|
+
flex: 1;
|
|
36
|
+
margin: 0 4px;
|
|
37
|
+
height: 32px;
|
|
38
|
+
max-width: 32px;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
|
|
41
|
+
&:before {
|
|
42
|
+
z-index: 0;
|
|
43
|
+
content: '';
|
|
44
|
+
display: block;
|
|
45
|
+
width: 100%;
|
|
46
|
+
height: 4px;
|
|
47
|
+
position: absolute;
|
|
48
|
+
top: 14px;
|
|
49
|
+
left: 0;
|
|
50
|
+
border-radius: 3px;
|
|
51
|
+
box-shadow: inset 0 1px 3px 0 rgba(0, 0, 0, 0.05);
|
|
52
|
+
background-color: ${colors.lightGrey};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&:after {
|
|
56
|
+
z-index: 1;
|
|
57
|
+
content: '';
|
|
58
|
+
display: block;
|
|
59
|
+
width: 100%;
|
|
60
|
+
height: 4px;
|
|
61
|
+
position: absolute;
|
|
62
|
+
top: 14px;
|
|
63
|
+
left: 0;
|
|
64
|
+
border-radius: 3px;
|
|
65
|
+
background-color: transparent;
|
|
66
|
+
transition: background-color 0.2s;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
&:focus {
|
|
70
|
+
outline: none;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
&:hover:after {
|
|
74
|
+
background-color: ${colors.black};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
${(props) => props.isDone && `
|
|
78
|
+
&:after {
|
|
79
|
+
background-color: ${colors.progressGreen};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
&:hover:after {
|
|
83
|
+
background-color: ${colors.black};
|
|
84
|
+
}
|
|
85
|
+
`}
|
|
86
|
+
|
|
87
|
+
${(props) => props.isActive && `
|
|
88
|
+
&:after {
|
|
89
|
+
background-color: ${colors.grey2};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
&:hover:after {
|
|
93
|
+
background-color: ${colors.black};
|
|
94
|
+
}
|
|
95
|
+
`}
|
|
96
|
+
|
|
97
|
+
${rwd.Medium`
|
|
98
|
+
width: 32px;
|
|
99
|
+
`}
|
|
100
|
+
`;
|
|
4
101
|
const StepsProgressContainer = styled.div`
|
|
5
102
|
position: relative;
|
|
6
103
|
width: 100%;
|
|
@@ -29,6 +126,10 @@ const StepContainer = styled.div.withConfig({
|
|
|
29
126
|
`}
|
|
30
127
|
`;
|
|
31
128
|
export {
|
|
129
|
+
Container,
|
|
130
|
+
Item,
|
|
131
|
+
Items,
|
|
32
132
|
StepContainer,
|
|
33
|
-
StepsProgressContainer
|
|
133
|
+
StepsProgressContainer,
|
|
134
|
+
Wrap
|
|
34
135
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
|
-
import { Container, Wrap, Items, Item } from "
|
|
4
|
+
import { Container, Wrap, Items, Item } from "./StepController.styles.js";
|
|
5
5
|
const StepControllerProgress = ({
|
|
6
6
|
touchedStepsIndexes,
|
|
7
7
|
doneStepsIndexes,
|