@thunderid/react 1.12.0 → 1.14.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.
- package/dist/api/auth/executeEmbeddedSelfFlow.d.ts +36 -0
- package/dist/api/auth/executeEmbeddedSelfFlow.d.ts.map +1 -0
- package/dist/api/auth/executeEmbeddedSelfFlow.js +30 -0
- package/dist/api/auth/executeEmbeddedSelfFlow.js.map +1 -0
- package/dist/cjs/api/auth/executeEmbeddedSelfFlow.cjs +32 -0
- package/dist/cjs/api/auth/executeEmbeddedSelfFlow.cjs.map +1 -0
- package/dist/cjs/components/account/UserProfile/BaseUserProfile.cjs +195 -46
- package/dist/cjs/components/account/UserProfile/BaseUserProfile.cjs.map +1 -1
- package/dist/cjs/components/account/UserProfile/BaseUserProfile.styles.cjs +57 -4
- package/dist/cjs/components/account/UserProfile/BaseUserProfile.styles.cjs.map +1 -1
- package/dist/cjs/components/account/UserProfile/UserProfile.cjs +13 -1
- package/dist/cjs/components/account/UserProfile/UserProfile.cjs.map +1 -1
- package/dist/cjs/components/account/VerifyAttribute/BaseVerifyAttribute.cjs +358 -0
- package/dist/cjs/components/account/VerifyAttribute/BaseVerifyAttribute.cjs.map +1 -0
- package/dist/cjs/components/account/VerifyAttribute/BaseVerifyAttribute.styles.cjs +84 -0
- package/dist/cjs/components/account/VerifyAttribute/BaseVerifyAttribute.styles.cjs.map +1 -0
- package/dist/cjs/components/account/VerifyAttribute/VerifyAttribute.cjs +94 -0
- package/dist/cjs/components/account/VerifyAttribute/VerifyAttribute.cjs.map +1 -0
- package/dist/cjs/components/auth/flow/AuthOptionFactory.cjs +26 -3
- package/dist/cjs/components/auth/flow/AuthOptionFactory.cjs.map +1 -1
- package/dist/cjs/components/auth/flow/FieldFactory.cjs +2 -1
- package/dist/cjs/components/auth/flow/FieldFactory.cjs.map +1 -1
- package/dist/cjs/components/primitives/OtpField/OtpField.cjs +10 -5
- package/dist/cjs/components/primitives/OtpField/OtpField.cjs.map +1 -1
- package/dist/cjs/components/primitives/OtpField/OtpField.styles.cjs +16 -8
- package/dist/cjs/components/primitives/OtpField/OtpField.styles.cjs.map +1 -1
- package/dist/cjs/contexts/ComponentRenderer/ComponentRendererContext.cjs.map +1 -1
- package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs +14 -0
- package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs.map +1 -1
- package/dist/cjs/index.cjs +30 -0
- package/dist/components/account/UserProfile/BaseUserProfile.d.ts +27 -1
- package/dist/components/account/UserProfile/BaseUserProfile.d.ts.map +1 -1
- package/dist/components/account/UserProfile/BaseUserProfile.js +197 -48
- package/dist/components/account/UserProfile/BaseUserProfile.js.map +1 -1
- package/dist/components/account/UserProfile/BaseUserProfile.styles.d.ts.map +1 -1
- package/dist/components/account/UserProfile/BaseUserProfile.styles.js +57 -4
- package/dist/components/account/UserProfile/BaseUserProfile.styles.js.map +1 -1
- package/dist/components/account/UserProfile/UserProfile.d.ts +7 -1
- package/dist/components/account/UserProfile/UserProfile.d.ts.map +1 -1
- package/dist/components/account/UserProfile/UserProfile.js +14 -2
- package/dist/components/account/UserProfile/UserProfile.js.map +1 -1
- package/dist/components/account/VerifyAttribute/BaseVerifyAttribute.d.ts +113 -0
- package/dist/components/account/VerifyAttribute/BaseVerifyAttribute.d.ts.map +1 -0
- package/dist/components/account/VerifyAttribute/BaseVerifyAttribute.js +354 -0
- package/dist/components/account/VerifyAttribute/BaseVerifyAttribute.js.map +1 -0
- package/dist/components/account/VerifyAttribute/BaseVerifyAttribute.styles.d.ts +10 -0
- package/dist/components/account/VerifyAttribute/BaseVerifyAttribute.styles.d.ts.map +1 -0
- package/dist/components/account/VerifyAttribute/BaseVerifyAttribute.styles.js +82 -0
- package/dist/components/account/VerifyAttribute/BaseVerifyAttribute.styles.js.map +1 -0
- package/dist/components/account/VerifyAttribute/VerifyAttribute.d.ts +41 -0
- package/dist/components/account/VerifyAttribute/VerifyAttribute.d.ts.map +1 -0
- package/dist/components/account/VerifyAttribute/VerifyAttribute.js +90 -0
- package/dist/components/account/VerifyAttribute/VerifyAttribute.js.map +1 -0
- package/dist/components/auth/flow/AuthOptionFactory.d.ts +5 -1
- package/dist/components/auth/flow/AuthOptionFactory.d.ts.map +1 -1
- package/dist/components/auth/flow/AuthOptionFactory.js +26 -4
- package/dist/components/auth/flow/AuthOptionFactory.js.map +1 -1
- package/dist/components/auth/flow/FieldFactory.d.ts +4 -0
- package/dist/components/auth/flow/FieldFactory.d.ts.map +1 -1
- package/dist/components/auth/flow/FieldFactory.js +2 -1
- package/dist/components/auth/flow/FieldFactory.js.map +1 -1
- package/dist/components/primitives/OtpField/OtpField.d.ts +4 -0
- package/dist/components/primitives/OtpField/OtpField.d.ts.map +1 -1
- package/dist/components/primitives/OtpField/OtpField.js +11 -6
- package/dist/components/primitives/OtpField/OtpField.js.map +1 -1
- package/dist/components/primitives/OtpField/OtpField.styles.d.ts +1 -1
- package/dist/components/primitives/OtpField/OtpField.styles.d.ts.map +1 -1
- package/dist/components/primitives/OtpField/OtpField.styles.js +16 -8
- package/dist/components/primitives/OtpField/OtpField.styles.js.map +1 -1
- package/dist/contexts/ComponentRenderer/ComponentRendererContext.d.ts +1 -1
- package/dist/contexts/ComponentRenderer/ComponentRendererContext.d.ts.map +1 -1
- package/dist/contexts/ComponentRenderer/ComponentRendererContext.js.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDProvider.d.ts.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDProvider.js +14 -0
- package/dist/contexts/ThunderID/ThunderIDProvider.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/package.json +2 -2
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { EmbeddedSelfFlowResponse, ExecuteEmbeddedSelfFlowConfig as BaseExecuteEmbeddedSelfFlowConfig } from '@thunderid/browser';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the executeEmbeddedSelfFlow request (React-specific)
|
|
4
|
+
*/
|
|
5
|
+
export interface ExecuteEmbeddedSelfFlowConfig extends Omit<BaseExecuteEmbeddedSelfFlowConfig, 'fetcher'> {
|
|
6
|
+
/**
|
|
7
|
+
* Optional custom fetcher function. If not provided, the ThunderID SPA client's httpClient is used,
|
|
8
|
+
* which attaches the signed-in user's access token.
|
|
9
|
+
*/
|
|
10
|
+
fetcher?: (url: string, config: RequestInit) => Promise<Response>;
|
|
11
|
+
/**
|
|
12
|
+
* Optional instance ID for multi-instance support. Defaults to 0.
|
|
13
|
+
*/
|
|
14
|
+
instanceId?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Executes one step of a `SELF` flow for the signed-in user. Uses the ThunderID SPA
|
|
18
|
+
* client's httpClient by default, which attaches the access token the flow identifies the user by.
|
|
19
|
+
*
|
|
20
|
+
* @param config - Configuration object with URL, payload and optional request config.
|
|
21
|
+
* @returns A promise that resolves with the flow step.
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const step = await executeEmbeddedSelfFlow({
|
|
25
|
+
* baseUrl: "https://localhost:8090",
|
|
26
|
+
* payload: {
|
|
27
|
+
* flowType: EmbeddedFlowType.Self,
|
|
28
|
+
* handle: "default-self-attribute-verification-flow",
|
|
29
|
+
* inputs: {attribute: "email"},
|
|
30
|
+
* },
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
declare const executeEmbeddedSelfFlow: ({ fetcher, instanceId, ...requestConfig }: ExecuteEmbeddedSelfFlowConfig) => Promise<EmbeddedSelfFlowResponse>;
|
|
35
|
+
export default executeEmbeddedSelfFlow;
|
|
36
|
+
//# sourceMappingURL=executeEmbeddedSelfFlow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executeEmbeddedSelfFlow.d.ts","sourceRoot":"","sources":["../../../src/api/auth/executeEmbeddedSelfFlow.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,wBAAwB,EAGxB,6BAA6B,IAAI,iCAAiC,EACnE,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,MAAM,WAAW,6BAA8B,SAAQ,IAAI,CAAC,iCAAiC,EAAE,SAAS,CAAC;IACvG;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,uBAAuB,GAAU,2CAIpC,6BAA6B,KAAG,OAAO,CAAC,wBAAwB,CAI/D,CAAC;AAEL,eAAe,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createHttpClientFetcher, executeEmbeddedSelfFlow } from "@thunderid/browser";
|
|
2
|
+
|
|
3
|
+
//#region src/api/auth/executeEmbeddedSelfFlow.ts
|
|
4
|
+
/**
|
|
5
|
+
* Executes one step of a `SELF` flow for the signed-in user. Uses the ThunderID SPA
|
|
6
|
+
* client's httpClient by default, which attaches the access token the flow identifies the user by.
|
|
7
|
+
*
|
|
8
|
+
* @param config - Configuration object with URL, payload and optional request config.
|
|
9
|
+
* @returns A promise that resolves with the flow step.
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const step = await executeEmbeddedSelfFlow({
|
|
13
|
+
* baseUrl: "https://localhost:8090",
|
|
14
|
+
* payload: {
|
|
15
|
+
* flowType: EmbeddedFlowType.Self,
|
|
16
|
+
* handle: "default-self-attribute-verification-flow",
|
|
17
|
+
* inputs: {attribute: "email"},
|
|
18
|
+
* },
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
const executeEmbeddedSelfFlow$1 = async ({ fetcher, instanceId = 0,...requestConfig }) => executeEmbeddedSelfFlow({
|
|
23
|
+
...requestConfig,
|
|
24
|
+
fetcher: fetcher ?? createHttpClientFetcher(instanceId)
|
|
25
|
+
});
|
|
26
|
+
var executeEmbeddedSelfFlow_default = executeEmbeddedSelfFlow$1;
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
export { executeEmbeddedSelfFlow_default as default };
|
|
30
|
+
//# sourceMappingURL=executeEmbeddedSelfFlow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executeEmbeddedSelfFlow.js","names":["executeEmbeddedSelfFlow","baseExecuteEmbeddedSelfFlow"],"sources":["../../../src/api/auth/executeEmbeddedSelfFlow.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n EmbeddedSelfFlowResponse,\n createHttpClientFetcher,\n executeEmbeddedSelfFlow as baseExecuteEmbeddedSelfFlow,\n ExecuteEmbeddedSelfFlowConfig as BaseExecuteEmbeddedSelfFlowConfig,\n} from '@thunderid/browser';\n\n/**\n * Configuration for the executeEmbeddedSelfFlow request (React-specific)\n */\nexport interface ExecuteEmbeddedSelfFlowConfig extends Omit<BaseExecuteEmbeddedSelfFlowConfig, 'fetcher'> {\n /**\n * Optional custom fetcher function. If not provided, the ThunderID SPA client's httpClient is used,\n * which attaches the signed-in user's access token.\n */\n fetcher?: (url: string, config: RequestInit) => Promise<Response>;\n /**\n * Optional instance ID for multi-instance support. Defaults to 0.\n */\n instanceId?: number;\n}\n\n/**\n * Executes one step of a `SELF` flow for the signed-in user. Uses the ThunderID SPA\n * client's httpClient by default, which attaches the access token the flow identifies the user by.\n *\n * @param config - Configuration object with URL, payload and optional request config.\n * @returns A promise that resolves with the flow step.\n * @example\n * ```typescript\n * const step = await executeEmbeddedSelfFlow({\n * baseUrl: \"https://localhost:8090\",\n * payload: {\n * flowType: EmbeddedFlowType.Self,\n * handle: \"default-self-attribute-verification-flow\",\n * inputs: {attribute: \"email\"},\n * },\n * });\n * ```\n */\nconst executeEmbeddedSelfFlow = async ({\n fetcher,\n instanceId = 0,\n ...requestConfig\n}: ExecuteEmbeddedSelfFlowConfig): Promise<EmbeddedSelfFlowResponse> =>\n baseExecuteEmbeddedSelfFlow({\n ...requestConfig,\n fetcher: fetcher ?? createHttpClientFetcher(instanceId),\n });\n\nexport default executeEmbeddedSelfFlow;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA2CA,MAAMA,4BAA0B,OAAO,EACrC,SACA,aAAa,EACb,GAAG,oBAEHC,wBAA4B;CAC1B,GAAG;CACH,SAAS,WAAW,wBAAwB,WAAW;CACxD,CAAC;AAEJ,sCAAeD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let __thunderid_browser = require("@thunderid/browser");
|
|
3
|
+
__thunderid_browser = require_rolldown_runtime.__toESM(__thunderid_browser);
|
|
4
|
+
|
|
5
|
+
//#region src/api/auth/executeEmbeddedSelfFlow.ts
|
|
6
|
+
/**
|
|
7
|
+
* Executes one step of a `SELF` flow for the signed-in user. Uses the ThunderID SPA
|
|
8
|
+
* client's httpClient by default, which attaches the access token the flow identifies the user by.
|
|
9
|
+
*
|
|
10
|
+
* @param config - Configuration object with URL, payload and optional request config.
|
|
11
|
+
* @returns A promise that resolves with the flow step.
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const step = await executeEmbeddedSelfFlow({
|
|
15
|
+
* baseUrl: "https://localhost:8090",
|
|
16
|
+
* payload: {
|
|
17
|
+
* flowType: EmbeddedFlowType.Self,
|
|
18
|
+
* handle: "default-self-attribute-verification-flow",
|
|
19
|
+
* inputs: {attribute: "email"},
|
|
20
|
+
* },
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
const executeEmbeddedSelfFlow = async ({ fetcher, instanceId = 0,...requestConfig }) => (0, __thunderid_browser.executeEmbeddedSelfFlow)({
|
|
25
|
+
...requestConfig,
|
|
26
|
+
fetcher: fetcher ?? (0, __thunderid_browser.createHttpClientFetcher)(instanceId)
|
|
27
|
+
});
|
|
28
|
+
var executeEmbeddedSelfFlow_default = executeEmbeddedSelfFlow;
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
exports.default = executeEmbeddedSelfFlow_default;
|
|
32
|
+
//# sourceMappingURL=executeEmbeddedSelfFlow.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executeEmbeddedSelfFlow.cjs","names":[],"sources":["../../../../src/api/auth/executeEmbeddedSelfFlow.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n EmbeddedSelfFlowResponse,\n createHttpClientFetcher,\n executeEmbeddedSelfFlow as baseExecuteEmbeddedSelfFlow,\n ExecuteEmbeddedSelfFlowConfig as BaseExecuteEmbeddedSelfFlowConfig,\n} from '@thunderid/browser';\n\n/**\n * Configuration for the executeEmbeddedSelfFlow request (React-specific)\n */\nexport interface ExecuteEmbeddedSelfFlowConfig extends Omit<BaseExecuteEmbeddedSelfFlowConfig, 'fetcher'> {\n /**\n * Optional custom fetcher function. If not provided, the ThunderID SPA client's httpClient is used,\n * which attaches the signed-in user's access token.\n */\n fetcher?: (url: string, config: RequestInit) => Promise<Response>;\n /**\n * Optional instance ID for multi-instance support. Defaults to 0.\n */\n instanceId?: number;\n}\n\n/**\n * Executes one step of a `SELF` flow for the signed-in user. Uses the ThunderID SPA\n * client's httpClient by default, which attaches the access token the flow identifies the user by.\n *\n * @param config - Configuration object with URL, payload and optional request config.\n * @returns A promise that resolves with the flow step.\n * @example\n * ```typescript\n * const step = await executeEmbeddedSelfFlow({\n * baseUrl: \"https://localhost:8090\",\n * payload: {\n * flowType: EmbeddedFlowType.Self,\n * handle: \"default-self-attribute-verification-flow\",\n * inputs: {attribute: \"email\"},\n * },\n * });\n * ```\n */\nconst executeEmbeddedSelfFlow = async ({\n fetcher,\n instanceId = 0,\n ...requestConfig\n}: ExecuteEmbeddedSelfFlowConfig): Promise<EmbeddedSelfFlowResponse> =>\n baseExecuteEmbeddedSelfFlow({\n ...requestConfig,\n fetcher: fetcher ?? createHttpClientFetcher(instanceId),\n });\n\nexport default executeEmbeddedSelfFlow;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA2CA,MAAM,0BAA0B,OAAO,EACrC,SACA,aAAa,EACb,GAAG,qEAEyB;CAC1B,GAAG;CACH,SAAS,4DAAmC,WAAW;CACxD,CAAC;AAEJ,sCAAe"}
|
|
@@ -5,6 +5,8 @@ const require_useTranslation = require('../../../hooks/useTranslation.cjs');
|
|
|
5
5
|
const require_Button = require('../../primitives/Button/Button.cjs');
|
|
6
6
|
const require_Typography = require('../../primitives/Typography/Typography.cjs');
|
|
7
7
|
const require_Card = require('../../primitives/Card/Card.cjs');
|
|
8
|
+
const require_CircleAlert = require('../../primitives/Icons/CircleAlert.cjs');
|
|
9
|
+
const require_CircleCheck = require('../../primitives/Icons/CircleCheck.cjs');
|
|
8
10
|
const require_Alert = require('../../primitives/Alert/Alert.cjs');
|
|
9
11
|
const require_TextField = require('../../primitives/TextField/TextField.cjs');
|
|
10
12
|
const require_Checkbox = require('../../primitives/Checkbox/Checkbox.cjs');
|
|
@@ -46,7 +48,8 @@ const fieldsToSkip = [
|
|
|
46
48
|
"attributes",
|
|
47
49
|
"picture",
|
|
48
50
|
"isReadOnly",
|
|
49
|
-
"isReadonly"
|
|
51
|
+
"isReadonly",
|
|
52
|
+
__thunderid_browser.AttributeVerificationConstants.VERIFIED_ATTRIBUTES_KEY
|
|
50
53
|
];
|
|
51
54
|
const readonlyFields = [
|
|
52
55
|
"attributes",
|
|
@@ -56,12 +59,44 @@ const readonlyFields = [
|
|
|
56
59
|
"username",
|
|
57
60
|
"sub"
|
|
58
61
|
];
|
|
59
|
-
const
|
|
62
|
+
const isStatusType = (type) => !!type && __thunderid_browser.AttributeVerificationConstants.VERIFIABLE_ATTRIBUTE_TYPES.includes(type.toLowerCase());
|
|
63
|
+
const isVerifiedAfterSave = (type) => !!type && __thunderid_browser.AttributeVerificationConstants.VERIFY_AFTER_SAVE_ATTRIBUTE_TYPES.includes(type.toLowerCase());
|
|
64
|
+
const BaseUserProfile = ({ fallback = null, className = "", cardLayout = true, profile, flattenedProfile, userSchema, mode = "inline", title, attributeMapping = {}, editable = true, onOpenChange, onUpdate, open = false, error = null, isLoading = false, preferences, showFields = [], hideFields = [], displayNameAttributes = [], renderVerification = void 0 }) => {
|
|
60
65
|
const { theme, colorScheme } = require_useTheme.default();
|
|
61
66
|
const [editedUser, setEditedUser] = (0, react.useState)(flattenedProfile || profile);
|
|
62
67
|
const [editingFields, setEditingFields] = (0, react.useState)({});
|
|
63
68
|
const [fieldErrors, setFieldErrors] = (0, react.useState)({});
|
|
64
|
-
const
|
|
69
|
+
const [verifyingField, setVerifyingField] = (0, react.useState)(null);
|
|
70
|
+
const [verifiedNotice, setVerifiedNotice] = (0, react.useState)(null);
|
|
71
|
+
const [pendingVerification, setPendingVerification] = (0, react.useState)(null);
|
|
72
|
+
const [savingFields, setSavingFields] = (0, react.useState)({});
|
|
73
|
+
const { t, currentLanguage } = require_useTranslation.default(preferences?.i18n);
|
|
74
|
+
const reportedVerifiedAttributes = (0, react.useMemo)(() => (0, __thunderid_browser.getVerifiedAttributes)(profile ?? flattenedProfile), [profile, flattenedProfile]);
|
|
75
|
+
const supportsVerification = reportedVerifiedAttributes !== void 0;
|
|
76
|
+
const verifiedAttributes = (0, react.useMemo)(() => reportedVerifiedAttributes ?? {}, [reportedVerifiedAttributes]);
|
|
77
|
+
(0, react.useEffect)(() => {
|
|
78
|
+
if (!pendingVerification) return;
|
|
79
|
+
if (error) {
|
|
80
|
+
setPendingVerification(null);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const { name, previousValue } = pendingVerification;
|
|
84
|
+
const storedUser = flattenedProfile ?? profile;
|
|
85
|
+
const storedValue = (storedUser?.["attributes"])?.[name] ?? storedUser?.[name];
|
|
86
|
+
if (storedValue === previousValue) return;
|
|
87
|
+
if (supportsVerification && typeof storedValue === "string" && storedValue.trim() !== "" && !verifiedAttributes[name]) {
|
|
88
|
+
setVerifiedNotice(null);
|
|
89
|
+
setVerifyingField(name);
|
|
90
|
+
}
|
|
91
|
+
setPendingVerification(null);
|
|
92
|
+
}, [
|
|
93
|
+
pendingVerification,
|
|
94
|
+
flattenedProfile,
|
|
95
|
+
profile,
|
|
96
|
+
error,
|
|
97
|
+
verifiedAttributes,
|
|
98
|
+
supportsVerification
|
|
99
|
+
]);
|
|
65
100
|
(0, react.useEffect)(() => {
|
|
66
101
|
const nextUser = flattenedProfile ?? profile;
|
|
67
102
|
if (!nextUser) return;
|
|
@@ -116,6 +151,7 @@ const BaseUserProfile = ({ fallback = null, className = "", cardLayout = true, p
|
|
|
116
151
|
}, [t]);
|
|
117
152
|
const formatLabel = (0, react.useCallback)((key) => key.split(/(?=[A-Z])|_/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" "), []);
|
|
118
153
|
const styles = require_BaseUserProfile_styles.default(theme, colorScheme);
|
|
154
|
+
const verificationStyles = styles;
|
|
119
155
|
const ObjectDisplay = ({ data }) => {
|
|
120
156
|
if (!data || typeof data !== "object") return null;
|
|
121
157
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("table", {
|
|
@@ -176,15 +212,32 @@ const BaseUserProfile = ({ fallback = null, className = "", cardLayout = true, p
|
|
|
176
212
|
});
|
|
177
213
|
let payload = {};
|
|
178
214
|
set(payload, fieldName, fieldValue);
|
|
179
|
-
|
|
215
|
+
setSavingFields((prev) => ({
|
|
216
|
+
...prev,
|
|
217
|
+
[fieldName]: true
|
|
218
|
+
}));
|
|
219
|
+
Promise.resolve(onUpdate(payload)).catch(() => setPendingVerification(null)).finally(() => setSavingFields((prev) => {
|
|
220
|
+
const next = { ...prev };
|
|
221
|
+
delete next[fieldName];
|
|
222
|
+
return next;
|
|
223
|
+
}));
|
|
180
224
|
toggleFieldEdit(fieldName);
|
|
225
|
+
const savedUser = flattenedProfile ?? profile;
|
|
226
|
+
const storedValue = (savedUser?.["attributes"])?.[fieldName] ?? savedUser?.[fieldName];
|
|
227
|
+
if (renderVerification && isVerifiedAfterSave(schema.type) && (0, __thunderid_browser.isVerifiableAttribute)(userSchema, fieldName) && typeof fieldValue === "string" && fieldValue.trim() !== "" && fieldValue !== storedValue) setPendingVerification({
|
|
228
|
+
name: fieldName,
|
|
229
|
+
previousValue: storedValue
|
|
230
|
+
});
|
|
231
|
+
else setPendingVerification(null);
|
|
181
232
|
}, [
|
|
182
233
|
editedUser,
|
|
183
234
|
flattenedProfile,
|
|
184
235
|
profile,
|
|
185
236
|
onUpdate,
|
|
186
237
|
toggleFieldEdit,
|
|
187
|
-
t
|
|
238
|
+
t,
|
|
239
|
+
renderVerification,
|
|
240
|
+
userSchema
|
|
188
241
|
]);
|
|
189
242
|
const handleFieldCancel = (0, react.useCallback)((fieldName) => {
|
|
190
243
|
const currentUser$1 = flattenedProfile || profile;
|
|
@@ -363,53 +416,142 @@ const BaseUserProfile = ({ fallback = null, className = "", cardLayout = true, p
|
|
|
363
416
|
}) : displayValue
|
|
364
417
|
})] });
|
|
365
418
|
};
|
|
419
|
+
const renderVerificationStatus = (schema) => {
|
|
420
|
+
const verification = verifiedAttributes[schema.name];
|
|
421
|
+
let verifiedAtTitle;
|
|
422
|
+
if (verification?.verifiedAt) {
|
|
423
|
+
const verifiedAt = new Date(verification.verifiedAt);
|
|
424
|
+
verifiedAtTitle = t("user.verification.status.verified_at", { date: Number.isNaN(verifiedAt.getTime()) ? verification.verifiedAt : verifiedAt.toLocaleString(currentLanguage) });
|
|
425
|
+
}
|
|
426
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
427
|
+
className: require_emotion.cx((0, __thunderid_browser.withVendorCSSClassPrefix)((0, __thunderid_browser.bem)("user-profile", "verification-status")), (0, __thunderid_browser.withVendorCSSClassPrefix)((0, __thunderid_browser.bem)("user-profile", "verification-status", verification ? "verified" : "unverified")), verificationStyles["verificationStatus"], verification ? verificationStyles["verified"] : verificationStyles["unverified"]),
|
|
428
|
+
title: verifiedAtTitle,
|
|
429
|
+
"data-testid": `thunderid-verification-status-${schema.name}`,
|
|
430
|
+
children: [
|
|
431
|
+
verification ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_CircleCheck.default, {
|
|
432
|
+
width: 12,
|
|
433
|
+
height: 12,
|
|
434
|
+
"aria-hidden": "true"
|
|
435
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_CircleAlert.default, {
|
|
436
|
+
width: 12,
|
|
437
|
+
height: 12,
|
|
438
|
+
"aria-hidden": "true"
|
|
439
|
+
}),
|
|
440
|
+
verification ? t("user.verification.status.verified") : t("user.verification.status.unverified"),
|
|
441
|
+
verifiedAtTitle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
442
|
+
className: verificationStyles["visuallyHidden"],
|
|
443
|
+
children: ` (${verifiedAtTitle})`
|
|
444
|
+
})
|
|
445
|
+
]
|
|
446
|
+
});
|
|
447
|
+
};
|
|
448
|
+
const renderVerificationPanel = (schema) => {
|
|
449
|
+
if (!renderVerification || !schema.name || verifyingField !== schema.name) return null;
|
|
450
|
+
const attributeDisplayName = schema.displayName ?? (0, __thunderid_browser.startCase)(schema.name);
|
|
451
|
+
const panel = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
452
|
+
className: require_emotion.cx((0, __thunderid_browser.withVendorCSSClassPrefix)((0, __thunderid_browser.bem)("user-profile", "verification")), verificationStyles["verification"], mode === "popup" ? verificationStyles["verificationInline"] : ""),
|
|
453
|
+
children: renderVerification({
|
|
454
|
+
attribute: schema.name,
|
|
455
|
+
attributeDisplayName,
|
|
456
|
+
onCancel: () => setVerifyingField(null),
|
|
457
|
+
onComplete: () => {
|
|
458
|
+
setVerifyingField(null);
|
|
459
|
+
setVerifiedNotice(attributeDisplayName);
|
|
460
|
+
}
|
|
461
|
+
})
|
|
462
|
+
});
|
|
463
|
+
if (mode === "popup") return panel;
|
|
464
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Dialog.default, {
|
|
465
|
+
open: true,
|
|
466
|
+
onOpenChange: (isOpen) => {
|
|
467
|
+
if (!isOpen) setVerifyingField(null);
|
|
468
|
+
},
|
|
469
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Dialog.default.Content, {
|
|
470
|
+
"aria-label": t("user.verification.heading", { attribute: attributeDisplayName }),
|
|
471
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
472
|
+
className: verificationStyles["verificationDialog"],
|
|
473
|
+
children: panel
|
|
474
|
+
})
|
|
475
|
+
})
|
|
476
|
+
});
|
|
477
|
+
};
|
|
366
478
|
const renderUserInfo = (schema) => {
|
|
367
479
|
if (!schema?.name) return null;
|
|
368
480
|
const hasValue = schema.value !== void 0 && schema.value !== "" && schema.value !== null;
|
|
369
481
|
const isFieldEditing = editingFields[schema.name];
|
|
370
482
|
const isReadonlyField = readonlyFields.includes(schema.name);
|
|
371
483
|
if (!(hasValue || isFieldEditing || editable && schema.mutability === "READ_WRITE")) return null;
|
|
484
|
+
const storedUser = flattenedProfile ?? profile;
|
|
485
|
+
const storedValue = (storedUser?.["attributes"])?.[schema.name] ?? storedUser?.[schema.name];
|
|
486
|
+
const showsVerificationStatus = supportsVerification && !!hasValue && !isFieldEditing && !savingFields[schema.name] && schema.value === storedValue && isStatusType(schema.type);
|
|
487
|
+
const canVerify = editable && !!renderVerification && showsVerificationStatus && !verifiedAttributes[schema.name] && verifyingField !== schema.name && (0, __thunderid_browser.isVerifiableAttribute)(userSchema, schema.name) && typeof schema.value === "string";
|
|
372
488
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
373
489
|
className: styles.field,
|
|
374
|
-
children: [
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
490
|
+
children: [
|
|
491
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
492
|
+
className: styles.fieldInner,
|
|
493
|
+
children: [
|
|
494
|
+
renderSchemaField(schema, isFieldEditing, (value) => {
|
|
495
|
+
const tempEditedUser = { ...editedUser };
|
|
496
|
+
tempEditedUser[schema.name] = value;
|
|
497
|
+
setEditedUser(tempEditedUser);
|
|
498
|
+
}, () => toggleFieldEdit(schema.name)),
|
|
499
|
+
showsVerificationStatus && renderVerificationStatus(schema),
|
|
500
|
+
fieldErrors[schema.name] && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
501
|
+
style: {
|
|
502
|
+
color: "#d32f2f",
|
|
503
|
+
fontSize: "0.8rem",
|
|
504
|
+
marginTop: "4px",
|
|
505
|
+
fontWeight: 500
|
|
506
|
+
},
|
|
507
|
+
children: fieldErrors[schema.name]
|
|
508
|
+
})
|
|
509
|
+
]
|
|
510
|
+
}),
|
|
511
|
+
canVerify && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
512
|
+
className: verificationStyles["fieldActions"],
|
|
513
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.default, {
|
|
514
|
+
size: "small",
|
|
515
|
+
color: "primary",
|
|
516
|
+
variant: "outline",
|
|
517
|
+
onClick: () => {
|
|
518
|
+
setVerifiedNotice(null);
|
|
519
|
+
setVerifyingField(schema.name);
|
|
520
|
+
},
|
|
521
|
+
className: (0, __thunderid_browser.withVendorCSSClassPrefix)((0, __thunderid_browser.bem)("user-profile", "verify-button")),
|
|
522
|
+
"data-testid": `thunderid-verify-${schema.name}`,
|
|
523
|
+
children: t("user.verification.buttons.verify.text")
|
|
524
|
+
})
|
|
525
|
+
}),
|
|
526
|
+
editable && schema.mutability !== "READ_ONLY" && !isReadonlyField && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
527
|
+
className: styles.fieldActions,
|
|
528
|
+
children: [isFieldEditing && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.default, {
|
|
529
|
+
size: "small",
|
|
530
|
+
color: "primary",
|
|
531
|
+
variant: "solid",
|
|
532
|
+
onClick: () => handleFieldSave(schema),
|
|
533
|
+
children: "Save"
|
|
534
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.default, {
|
|
535
|
+
size: "small",
|
|
536
|
+
color: "secondary",
|
|
537
|
+
variant: "solid",
|
|
538
|
+
onClick: () => handleFieldCancel(schema.name),
|
|
539
|
+
children: "Cancel"
|
|
540
|
+
})] }), !isFieldEditing && hasValue && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.default, {
|
|
541
|
+
size: "small",
|
|
542
|
+
color: "tertiary",
|
|
543
|
+
variant: "icon",
|
|
544
|
+
onClick: () => {
|
|
545
|
+
if (verifyingField === schema.name) setVerifyingField(null);
|
|
546
|
+
setVerifiedNotice(null);
|
|
547
|
+
toggleFieldEdit(schema.name);
|
|
548
|
+
},
|
|
549
|
+
title: "Edit",
|
|
550
|
+
className: styles.editButton,
|
|
551
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PencilIcon, {})
|
|
552
|
+
})]
|
|
553
|
+
})
|
|
554
|
+
]
|
|
413
555
|
});
|
|
414
556
|
};
|
|
415
557
|
if (!profile && !flattenedProfile) return fallback;
|
|
@@ -448,6 +590,13 @@ const BaseUserProfile = ({ fallback = null, className = "", cardLayout = true, p
|
|
|
448
590
|
};
|
|
449
591
|
});
|
|
450
592
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
593
|
+
verifiedNotice && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Alert.default, {
|
|
594
|
+
variant: "success",
|
|
595
|
+
role: "status",
|
|
596
|
+
className: require_emotion.cx((0, __thunderid_browser.withVendorCSSClassPrefix)((0, __thunderid_browser.bem)("user-profile", "verification-notice")), verificationStyles["alert"]),
|
|
597
|
+
"data-testid": "thunderid-verification-notice",
|
|
598
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Alert.default.Description, { children: t("user.verification.success", { attribute: verifiedNotice }) })
|
|
599
|
+
}),
|
|
451
600
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
452
601
|
className: styles.profileSummary,
|
|
453
602
|
children: [
|
|
@@ -471,9 +620,9 @@ const BaseUserProfile = ({ fallback = null, className = "", cardLayout = true, p
|
|
|
471
620
|
]
|
|
472
621
|
}),
|
|
473
622
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Divider.default, {}),
|
|
474
|
-
schemaItems.map((schemaWithValue) => /* @__PURE__ */ (0, react_jsx_runtime.
|
|
623
|
+
schemaItems.map((schemaWithValue) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
475
624
|
className: styles.info,
|
|
476
|
-
children: renderUserInfo(schemaWithValue)
|
|
625
|
+
children: [renderUserInfo(schemaWithValue), renderVerificationPanel(schemaWithValue)]
|
|
477
626
|
}, schemaWithValue.name))
|
|
478
627
|
] });
|
|
479
628
|
};
|