@thunderid/react 1.8.0 → 1.9.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 (200) hide show
  1. package/dist/cjs/components/account/UserProfile/BaseUserProfile.cjs +1 -1
  2. package/dist/cjs/components/admin/AgentDetails/AgentDetails.cjs +13 -2
  3. package/dist/cjs/components/admin/AgentDetails/AgentDetails.cjs.map +1 -1
  4. package/dist/cjs/components/admin/AgentDetails/BaseAgentDetails.cjs +25 -7
  5. package/dist/cjs/components/admin/AgentDetails/BaseAgentDetails.cjs.map +1 -1
  6. package/dist/cjs/components/admin/ApplicationDetails/ApplicationDetails.cjs +15 -2
  7. package/dist/cjs/components/admin/ApplicationDetails/ApplicationDetails.cjs.map +1 -1
  8. package/dist/cjs/components/admin/ApplicationDetails/BaseApplicationDetails.cjs +24 -7
  9. package/dist/cjs/components/admin/ApplicationDetails/BaseApplicationDetails.cjs.map +1 -1
  10. package/dist/cjs/components/admin/GroupMembers/GroupMembers.cjs +2 -1
  11. package/dist/cjs/components/admin/GroupMembers/GroupMembers.cjs.map +1 -1
  12. package/dist/cjs/components/admin/RoleAssignments/RoleAssignments.cjs +2 -1
  13. package/dist/cjs/components/admin/RoleAssignments/RoleAssignments.cjs.map +1 -1
  14. package/dist/cjs/components/admin/UserDetails/BaseUserDetails.cjs +32 -14
  15. package/dist/cjs/components/admin/UserDetails/BaseUserDetails.cjs.map +1 -1
  16. package/dist/cjs/components/admin/UserDetails/UserDetails.cjs +14 -2
  17. package/dist/cjs/components/admin/UserDetails/UserDetails.cjs.map +1 -1
  18. package/dist/cjs/components/admin/shared/AccountLifecycleParts.cjs +105 -0
  19. package/dist/cjs/components/admin/shared/AccountLifecycleParts.cjs.map +1 -0
  20. package/dist/cjs/components/admin/shared/ApplicationFormFields.cjs +1 -1
  21. package/dist/cjs/components/auth/AcceptInvite/BaseAcceptInvite.cjs +4 -5
  22. package/dist/cjs/components/auth/AcceptInvite/BaseAcceptInvite.cjs.map +1 -1
  23. package/dist/cjs/components/auth/SignIn/SignIn.cjs +5 -5
  24. package/dist/cjs/components/auth/SignIn/SignIn.cjs.map +1 -1
  25. package/dist/cjs/components/auth/flow/AuthOptionFactory.cjs +4 -5
  26. package/dist/cjs/components/auth/flow/AuthOptionFactory.cjs.map +1 -1
  27. package/dist/cjs/components/auth/flow/Consent.cjs +53 -28
  28. package/dist/cjs/components/auth/flow/Consent.cjs.map +1 -1
  29. package/dist/cjs/components/auth/flow/ConsentAuthorizationDetail.cjs +104 -0
  30. package/dist/cjs/components/auth/flow/ConsentAuthorizationDetail.cjs.map +1 -0
  31. package/dist/cjs/components/auth/flow/ConsentAuthorizationDetail.styles.cjs +59 -0
  32. package/dist/cjs/components/auth/flow/ConsentAuthorizationDetail.styles.cjs.map +1 -0
  33. package/dist/cjs/components/auth/flow/ConsentDetailField.cjs +171 -0
  34. package/dist/cjs/components/auth/flow/ConsentDetailField.cjs.map +1 -0
  35. package/dist/cjs/components/auth/flow/ConsentDetailField.styles.cjs +85 -0
  36. package/dist/cjs/components/auth/flow/ConsentDetailField.styles.cjs.map +1 -0
  37. package/dist/cjs/components/auth/flow/ConsentDetailText.cjs +63 -0
  38. package/dist/cjs/components/auth/flow/ConsentDetailText.cjs.map +1 -0
  39. package/dist/cjs/components/auth/flow/ConsentDetailText.styles.cjs +83 -0
  40. package/dist/cjs/components/auth/flow/ConsentDetailText.styles.cjs.map +1 -0
  41. package/dist/cjs/components/auth/flow/FieldFactory.cjs +1 -1
  42. package/dist/cjs/components/auth/flow/resolveConsentText.cjs +25 -0
  43. package/dist/cjs/components/auth/flow/resolveConsentText.cjs.map +1 -0
  44. package/dist/cjs/components/primitives/KeyValueInput/KeyValueInput.cjs +1 -1
  45. package/dist/cjs/components/primitives/MultiInput/MultiInput.cjs +1 -1
  46. package/dist/cjs/components/primitives/PasswordField/PasswordField.cjs +1 -1
  47. package/dist/cjs/contexts/Theme/ThemeProvider.cjs +36 -6
  48. package/dist/cjs/contexts/Theme/ThemeProvider.cjs.map +1 -1
  49. package/dist/cjs/contexts/Theme/ThemeRootContext.cjs +12 -0
  50. package/dist/cjs/contexts/Theme/ThemeRootContext.cjs.map +1 -0
  51. package/dist/cjs/hooks/auth/useConsentDetailField.cjs +357 -0
  52. package/dist/cjs/hooks/auth/useConsentDetailField.cjs.map +1 -0
  53. package/dist/cjs/hooks/management/useAccountLifecycle.cjs +59 -0
  54. package/dist/cjs/hooks/management/useAccountLifecycle.cjs.map +1 -0
  55. package/dist/cjs/index.cjs +66 -1
  56. package/dist/cjs/utils/formatConsentDetailValue.cjs +26 -0
  57. package/dist/cjs/utils/formatConsentDetailValue.cjs.map +1 -0
  58. package/dist/cjs/utils/getConsentDetailLayout.cjs +44 -0
  59. package/dist/cjs/utils/getConsentDetailLayout.cjs.map +1 -0
  60. package/dist/cjs/utils/getConsentDetailListDisplay.cjs +30 -0
  61. package/dist/cjs/utils/getConsentDetailListDisplay.cjs.map +1 -0
  62. package/dist/cjs/utils/isConsentApprovalBlocked.cjs +41 -0
  63. package/dist/cjs/utils/isConsentApprovalBlocked.cjs.map +1 -0
  64. package/dist/cjs/utils/isConsentDetailPlainList.cjs +24 -0
  65. package/dist/cjs/utils/isConsentDetailPlainList.cjs.map +1 -0
  66. package/dist/cjs/utils/isConsentDetailStructured.cjs +15 -0
  67. package/dist/cjs/utils/isConsentDetailStructured.cjs.map +1 -0
  68. package/dist/cjs/utils/isConsentDetailTextClamped.cjs +25 -0
  69. package/dist/cjs/utils/isConsentDetailTextClamped.cjs.map +1 -0
  70. package/dist/components/account/UserProfile/BaseUserProfile.js +1 -1
  71. package/dist/components/admin/AgentDetails/AgentDetails.d.ts +8 -1
  72. package/dist/components/admin/AgentDetails/AgentDetails.d.ts.map +1 -1
  73. package/dist/components/admin/AgentDetails/AgentDetails.js +13 -2
  74. package/dist/components/admin/AgentDetails/AgentDetails.js.map +1 -1
  75. package/dist/components/admin/AgentDetails/BaseAgentDetails.d.ts +21 -1
  76. package/dist/components/admin/AgentDetails/BaseAgentDetails.d.ts.map +1 -1
  77. package/dist/components/admin/AgentDetails/BaseAgentDetails.js +25 -7
  78. package/dist/components/admin/AgentDetails/BaseAgentDetails.js.map +1 -1
  79. package/dist/components/admin/ApplicationDetails/ApplicationDetails.d.ts +15 -1
  80. package/dist/components/admin/ApplicationDetails/ApplicationDetails.d.ts.map +1 -1
  81. package/dist/components/admin/ApplicationDetails/ApplicationDetails.js +15 -2
  82. package/dist/components/admin/ApplicationDetails/ApplicationDetails.js.map +1 -1
  83. package/dist/components/admin/ApplicationDetails/BaseApplicationDetails.d.ts +20 -1
  84. package/dist/components/admin/ApplicationDetails/BaseApplicationDetails.d.ts.map +1 -1
  85. package/dist/components/admin/ApplicationDetails/BaseApplicationDetails.js +24 -7
  86. package/dist/components/admin/ApplicationDetails/BaseApplicationDetails.js.map +1 -1
  87. package/dist/components/admin/GroupMembers/GroupMembers.d.ts +7 -0
  88. package/dist/components/admin/GroupMembers/GroupMembers.d.ts.map +1 -1
  89. package/dist/components/admin/GroupMembers/GroupMembers.js +2 -1
  90. package/dist/components/admin/GroupMembers/GroupMembers.js.map +1 -1
  91. package/dist/components/admin/RoleAssignments/RoleAssignments.d.ts +7 -0
  92. package/dist/components/admin/RoleAssignments/RoleAssignments.d.ts.map +1 -1
  93. package/dist/components/admin/RoleAssignments/RoleAssignments.js +2 -1
  94. package/dist/components/admin/RoleAssignments/RoleAssignments.js.map +1 -1
  95. package/dist/components/admin/UserDetails/BaseUserDetails.d.ts +22 -1
  96. package/dist/components/admin/UserDetails/BaseUserDetails.d.ts.map +1 -1
  97. package/dist/components/admin/UserDetails/BaseUserDetails.js +32 -14
  98. package/dist/components/admin/UserDetails/BaseUserDetails.js.map +1 -1
  99. package/dist/components/admin/UserDetails/UserDetails.d.ts +15 -1
  100. package/dist/components/admin/UserDetails/UserDetails.d.ts.map +1 -1
  101. package/dist/components/admin/UserDetails/UserDetails.js +14 -2
  102. package/dist/components/admin/UserDetails/UserDetails.js.map +1 -1
  103. package/dist/components/admin/shared/AccountLifecycleParts.d.ts +32 -0
  104. package/dist/components/admin/shared/AccountLifecycleParts.d.ts.map +1 -0
  105. package/dist/components/admin/shared/AccountLifecycleParts.js +101 -0
  106. package/dist/components/admin/shared/AccountLifecycleParts.js.map +1 -0
  107. package/dist/components/admin/shared/ApplicationFormFields.js +1 -1
  108. package/dist/components/auth/AcceptInvite/BaseAcceptInvite.d.ts.map +1 -1
  109. package/dist/components/auth/AcceptInvite/BaseAcceptInvite.js +5 -6
  110. package/dist/components/auth/AcceptInvite/BaseAcceptInvite.js.map +1 -1
  111. package/dist/components/auth/SignIn/SignIn.d.ts.map +1 -1
  112. package/dist/components/auth/SignIn/SignIn.js +6 -6
  113. package/dist/components/auth/SignIn/SignIn.js.map +1 -1
  114. package/dist/components/auth/flow/AuthOptionFactory.d.ts.map +1 -1
  115. package/dist/components/auth/flow/AuthOptionFactory.js +5 -6
  116. package/dist/components/auth/flow/AuthOptionFactory.js.map +1 -1
  117. package/dist/components/auth/flow/Consent.d.ts +6 -0
  118. package/dist/components/auth/flow/Consent.d.ts.map +1 -1
  119. package/dist/components/auth/flow/Consent.js +54 -29
  120. package/dist/components/auth/flow/Consent.js.map +1 -1
  121. package/dist/components/auth/flow/ConsentAuthorizationDetail.d.ts +68 -0
  122. package/dist/components/auth/flow/ConsentAuthorizationDetail.d.ts.map +1 -0
  123. package/dist/components/auth/flow/ConsentAuthorizationDetail.js +100 -0
  124. package/dist/components/auth/flow/ConsentAuthorizationDetail.js.map +1 -0
  125. package/dist/components/auth/flow/ConsentAuthorizationDetail.styles.d.ts +10 -0
  126. package/dist/components/auth/flow/ConsentAuthorizationDetail.styles.d.ts.map +1 -0
  127. package/dist/components/auth/flow/ConsentAuthorizationDetail.styles.js +57 -0
  128. package/dist/components/auth/flow/ConsentAuthorizationDetail.styles.js.map +1 -0
  129. package/dist/components/auth/flow/ConsentDetailField.d.ts +39 -0
  130. package/dist/components/auth/flow/ConsentDetailField.d.ts.map +1 -0
  131. package/dist/components/auth/flow/ConsentDetailField.js +168 -0
  132. package/dist/components/auth/flow/ConsentDetailField.js.map +1 -0
  133. package/dist/components/auth/flow/ConsentDetailField.styles.d.ts +11 -0
  134. package/dist/components/auth/flow/ConsentDetailField.styles.d.ts.map +1 -0
  135. package/dist/components/auth/flow/ConsentDetailField.styles.js +83 -0
  136. package/dist/components/auth/flow/ConsentDetailField.styles.js.map +1 -0
  137. package/dist/components/auth/flow/ConsentDetailText.d.ts +53 -0
  138. package/dist/components/auth/flow/ConsentDetailText.d.ts.map +1 -0
  139. package/dist/components/auth/flow/ConsentDetailText.js +58 -0
  140. package/dist/components/auth/flow/ConsentDetailText.js.map +1 -0
  141. package/dist/components/auth/flow/ConsentDetailText.styles.d.ts +20 -0
  142. package/dist/components/auth/flow/ConsentDetailText.styles.d.ts.map +1 -0
  143. package/dist/components/auth/flow/ConsentDetailText.styles.js +80 -0
  144. package/dist/components/auth/flow/ConsentDetailText.styles.js.map +1 -0
  145. package/dist/components/auth/flow/FieldFactory.js +1 -1
  146. package/dist/components/auth/flow/resolveConsentText.d.ts +13 -0
  147. package/dist/components/auth/flow/resolveConsentText.d.ts.map +1 -0
  148. package/dist/components/auth/flow/resolveConsentText.js +23 -0
  149. package/dist/components/auth/flow/resolveConsentText.js.map +1 -0
  150. package/dist/components/primitives/KeyValueInput/KeyValueInput.js +1 -1
  151. package/dist/components/primitives/MultiInput/MultiInput.js +1 -1
  152. package/dist/components/primitives/PasswordField/PasswordField.js +1 -1
  153. package/dist/contexts/Theme/ThemeProvider.d.ts +2 -1
  154. package/dist/contexts/Theme/ThemeProvider.d.ts.map +1 -1
  155. package/dist/contexts/Theme/ThemeProvider.js +37 -7
  156. package/dist/contexts/Theme/ThemeProvider.js.map +1 -1
  157. package/dist/contexts/Theme/ThemeRootContext.d.ts +11 -0
  158. package/dist/contexts/Theme/ThemeRootContext.d.ts.map +1 -0
  159. package/dist/contexts/Theme/ThemeRootContext.js +10 -0
  160. package/dist/contexts/Theme/ThemeRootContext.js.map +1 -0
  161. package/dist/hooks/auth/useConsentDetailField.d.ts +130 -0
  162. package/dist/hooks/auth/useConsentDetailField.d.ts.map +1 -0
  163. package/dist/hooks/auth/useConsentDetailField.js +354 -0
  164. package/dist/hooks/auth/useConsentDetailField.js.map +1 -0
  165. package/dist/hooks/management/useAccountLifecycle.d.ts +49 -0
  166. package/dist/hooks/management/useAccountLifecycle.d.ts.map +1 -0
  167. package/dist/hooks/management/useAccountLifecycle.js +56 -0
  168. package/dist/hooks/management/useAccountLifecycle.js.map +1 -0
  169. package/dist/index.d.ts +16 -4
  170. package/dist/index.d.ts.map +1 -1
  171. package/dist/index.js +11 -3
  172. package/dist/utils/formatConsentDetailValue.d.ts +16 -0
  173. package/dist/utils/formatConsentDetailValue.d.ts.map +1 -0
  174. package/dist/utils/formatConsentDetailValue.js +25 -0
  175. package/dist/utils/formatConsentDetailValue.js.map +1 -0
  176. package/dist/utils/getConsentDetailLayout.d.ts +32 -0
  177. package/dist/utils/getConsentDetailLayout.d.ts.map +1 -0
  178. package/dist/utils/getConsentDetailLayout.js +43 -0
  179. package/dist/utils/getConsentDetailLayout.js.map +1 -0
  180. package/dist/utils/getConsentDetailListDisplay.d.ts +30 -0
  181. package/dist/utils/getConsentDetailListDisplay.d.ts.map +1 -0
  182. package/dist/utils/getConsentDetailListDisplay.js +30 -0
  183. package/dist/utils/getConsentDetailListDisplay.js.map +1 -0
  184. package/dist/utils/isConsentApprovalBlocked.d.ts +17 -0
  185. package/dist/utils/isConsentApprovalBlocked.d.ts.map +1 -0
  186. package/dist/utils/isConsentApprovalBlocked.js +39 -0
  187. package/dist/utils/isConsentApprovalBlocked.js.map +1 -0
  188. package/dist/utils/isConsentDetailPlainList.d.ts +15 -0
  189. package/dist/utils/isConsentDetailPlainList.d.ts.map +1 -0
  190. package/dist/utils/isConsentDetailPlainList.js +23 -0
  191. package/dist/utils/isConsentDetailPlainList.js.map +1 -0
  192. package/dist/utils/isConsentDetailStructured.d.ts +10 -0
  193. package/dist/utils/isConsentDetailStructured.d.ts.map +1 -0
  194. package/dist/utils/isConsentDetailStructured.js +14 -0
  195. package/dist/utils/isConsentDetailStructured.js.map +1 -0
  196. package/dist/utils/isConsentDetailTextClamped.d.ts +20 -0
  197. package/dist/utils/isConsentDetailTextClamped.d.ts.map +1 -0
  198. package/dist/utils/isConsentDetailTextClamped.js +24 -0
  199. package/dist/utils/isConsentDetailTextClamped.js.map +1 -0
  200. package/package.json +2 -2
@@ -0,0 +1,58 @@
1
+ import { cx } from "../../../styles/emotion.js";
2
+ import useTheme_default from "../../../contexts/Theme/useTheme.js";
3
+ import Typography_default from "../../primitives/Typography/Typography.js";
4
+ import ConsentDetailText_styles_default, { useToggleStyles } from "./ConsentDetailText.styles.js";
5
+ import resolveConsentText_default from "./resolveConsentText.js";
6
+ import isConsentDetailTextClamped_default from "../../../utils/isConsentDetailTextClamped.js";
7
+ import { bem, withVendorCSSClassPrefix } from "@thunderid/browser";
8
+ import { useState } from "react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+
11
+ //#region src/components/auth/flow/ConsentDetailText.tsx
12
+ /**
13
+ * Button that expands or collapses long authorization detail content.
14
+ */
15
+ const ConsentDetailToggle = ({ controls = void 0, expanded, hiddenCount = void 0, onToggle, t = void 0 }) => {
16
+ const { theme, colorScheme } = useTheme_default();
17
+ const styles = useToggleStyles(theme, colorScheme);
18
+ let label = resolveConsentText_default(t, "consent.authorization_details.show_less");
19
+ if (!expanded) label = hiddenCount === void 0 ? resolveConsentText_default(t, "consent.authorization_details.show_more") : resolveConsentText_default(t, "consent.authorization_details.more_items", { count: hiddenCount });
20
+ return /* @__PURE__ */ jsx("button", {
21
+ type: "button",
22
+ className: cx(withVendorCSSClassPrefix(bem("consent-detail-text", "toggle")), styles["toggle"]),
23
+ "aria-controls": controls,
24
+ "aria-expanded": expanded,
25
+ onClick: () => onToggle(!expanded),
26
+ children: label
27
+ });
28
+ };
29
+ /**
30
+ * Shows authorization detail text that wraps anywhere, so a long unbroken token such as an IBAN or a
31
+ * URL never overflows. Text longer than its limit is clamped behind a toggle.
32
+ */
33
+ const ConsentDetailText = ({ align = "left", className = void 0, fontWeight = void 0, id = void 0, maxChars, maxLines, monospace = false, t = void 0, text, variant = "body2" }) => {
34
+ const [expanded, setExpanded] = useState(false);
35
+ const { theme, colorScheme } = useTheme_default();
36
+ const styles = ConsentDetailText_styles_default(theme, colorScheme, align, monospace, maxLines);
37
+ const long = isConsentDetailTextClamped_default(text, maxChars, maxLines);
38
+ return /* @__PURE__ */ jsxs("div", {
39
+ className: cx(withVendorCSSClassPrefix(bem("consent-detail-text")), styles["container"]),
40
+ children: [/* @__PURE__ */ jsx(Typography_default, {
41
+ id,
42
+ variant,
43
+ fontWeight,
44
+ className: cx(withVendorCSSClassPrefix(bem("consent-detail-text", "text")), styles["text"], monospace && withVendorCSSClassPrefix(bem("consent-detail-text", "text", "monospace")), monospace && styles["monospace"], long && !expanded && styles["clamp"], className),
45
+ children: text
46
+ }), long && /* @__PURE__ */ jsx(ConsentDetailToggle, {
47
+ controls: id,
48
+ expanded,
49
+ onToggle: setExpanded,
50
+ t
51
+ })]
52
+ });
53
+ };
54
+ var ConsentDetailText_default = ConsentDetailText;
55
+
56
+ //#endregion
57
+ export { ConsentDetailToggle, ConsentDetailText_default as default };
58
+ //# sourceMappingURL=ConsentDetailText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsentDetailText.js","names":["ConsentDetailToggle: FC<ConsentDetailToggleProps>","useTheme","styles: Record<string, string>","label: string","resolveConsentText","ConsentDetailText: FC<ConsentDetailTextProps>","useStyles","long: boolean","isConsentDetailTextClamped","Typography"],"sources":["../../../../src/components/auth/flow/ConsentDetailText.tsx"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {bem, withVendorCSSClassPrefix} from '@thunderid/browser';\nimport {FC, ReactElement, useState} from 'react';\nimport useStyles, {useToggleStyles} from './ConsentDetailText.styles';\nimport resolveConsentText from './resolveConsentText';\nimport useTheme from '../../../contexts/Theme/useTheme';\nimport {UseTranslation} from '../../../hooks/useTranslation';\nimport {cx} from '../../../styles/emotion';\nimport isConsentDetailTextClamped from '../../../utils/isConsentDetailTextClamped';\nimport Typography from '../../primitives/Typography/Typography';\n\n/**\n * Props for the ConsentDetailToggle component.\n */\nexport interface ConsentDetailToggleProps {\n /** Id of the element the toggle shows more or less of. */\n controls?: string;\n /** Whether everything is shown. */\n expanded: boolean;\n /** Number of items hidden while collapsed. When given, the collapsed label counts them. */\n hiddenCount?: number;\n /** Callback invoked with the next expanded state. */\n onToggle: (expanded: boolean) => void;\n /** translation data */\n t?: UseTranslation['t'];\n}\n\n/**\n * Button that expands or collapses long authorization detail content.\n */\nexport const ConsentDetailToggle: FC<ConsentDetailToggleProps> = ({\n controls = undefined,\n expanded,\n hiddenCount = undefined,\n onToggle,\n t = undefined,\n}: ConsentDetailToggleProps): ReactElement => {\n const {theme, colorScheme}: ReturnType<typeof useTheme> = useTheme();\n const styles: Record<string, string> = useToggleStyles(theme, colorScheme);\n\n let label: string = resolveConsentText(t, 'consent.authorization_details.show_less');\n if (!expanded) {\n label =\n hiddenCount === undefined\n ? resolveConsentText(t, 'consent.authorization_details.show_more')\n : resolveConsentText(t, 'consent.authorization_details.more_items', {count: hiddenCount});\n }\n\n return (\n <button\n type=\"button\"\n className={cx(withVendorCSSClassPrefix(bem('consent-detail-text', 'toggle')), styles['toggle'])}\n aria-controls={controls}\n aria-expanded={expanded}\n onClick={(): void => onToggle(!expanded)}\n >\n {label}\n </button>\n );\n};\n\n/**\n * Props for the ConsentDetailText component.\n */\nexport interface ConsentDetailTextProps {\n /** Alignment of the text. */\n align?: 'left' | 'right';\n /** Class name applied to the text. */\n className?: string;\n /** Weight of the text. */\n fontWeight?: 'normal' | 'medium' | 'semibold' | 'bold';\n /** Id of the text element. */\n id?: string;\n /** Number of characters above which the text is clamped. */\n maxChars: number;\n /** Number of lines the text is clamped to. */\n maxLines: number;\n /** Shows the text as a preformatted monospace block, for structured JSON. */\n monospace?: boolean;\n /** translation data */\n t?: UseTranslation['t'];\n /** Text to show. */\n text: string;\n /** Typography variant of the text. */\n variant?: 'body2' | 'subtitle2';\n}\n\n/**\n * Shows authorization detail text that wraps anywhere, so a long unbroken token such as an IBAN or a\n * URL never overflows. Text longer than its limit is clamped behind a toggle.\n */\nconst ConsentDetailText: FC<ConsentDetailTextProps> = ({\n align = 'left',\n className = undefined,\n fontWeight = undefined,\n id = undefined,\n maxChars,\n maxLines,\n monospace = false,\n t = undefined,\n text,\n variant = 'body2',\n}: ConsentDetailTextProps): ReactElement => {\n const [expanded, setExpanded] = useState<boolean>(false);\n const {theme, colorScheme}: ReturnType<typeof useTheme> = useTheme();\n const styles: Record<string, string> = useStyles(theme, colorScheme, align, monospace, maxLines);\n const long: boolean = isConsentDetailTextClamped(text, maxChars, maxLines);\n\n return (\n <div className={cx(withVendorCSSClassPrefix(bem('consent-detail-text')), styles['container'])}>\n <Typography\n id={id}\n variant={variant}\n fontWeight={fontWeight}\n className={cx(\n withVendorCSSClassPrefix(bem('consent-detail-text', 'text')),\n styles['text'],\n monospace && withVendorCSSClassPrefix(bem('consent-detail-text', 'text', 'monospace')),\n monospace && styles['monospace'],\n long && !expanded && styles['clamp'],\n className,\n )}\n >\n {text}\n </Typography>\n {long && <ConsentDetailToggle controls={id} expanded={expanded} onToggle={setExpanded} t={t} />}\n </div>\n );\n};\n\nexport default ConsentDetailText;\n"],"mappings":";;;;;;;;;;;;;;AAgCA,MAAaA,uBAAqD,EAChE,WAAW,QACX,UACA,cAAc,QACd,UACA,IAAI,aACwC;CAC5C,MAAM,EAAC,OAAO,gBAA4CC,kBAAU;CACpE,MAAMC,SAAiC,gBAAgB,OAAO,YAAY;CAE1E,IAAIC,QAAgBC,2BAAmB,GAAG,0CAA0C;AACpF,KAAI,CAAC,SACH,SACE,gBAAgB,SACZA,2BAAmB,GAAG,0CAA0C,GAChEA,2BAAmB,GAAG,4CAA4C,EAAC,OAAO,aAAY,CAAC;AAG/F,QACE,oBAAC;EACC,MAAK;EACL,WAAW,GAAG,yBAAyB,IAAI,uBAAuB,SAAS,CAAC,EAAE,OAAO,UAAU;EAC/F,iBAAe;EACf,iBAAe;EACf,eAAqB,SAAS,CAAC,SAAS;YAEvC;GACM;;;;;;AAkCb,MAAMC,qBAAiD,EACrD,QAAQ,QACR,YAAY,QACZ,aAAa,QACb,KAAK,QACL,UACA,UACA,YAAY,OACZ,IAAI,QACJ,MACA,UAAU,cACgC;CAC1C,MAAM,CAAC,UAAU,eAAe,SAAkB,MAAM;CACxD,MAAM,EAAC,OAAO,gBAA4CJ,kBAAU;CACpE,MAAMC,SAAiCI,iCAAU,OAAO,aAAa,OAAO,WAAW,SAAS;CAChG,MAAMC,OAAgBC,mCAA2B,MAAM,UAAU,SAAS;AAE1E,QACE,qBAAC;EAAI,WAAW,GAAG,yBAAyB,IAAI,sBAAsB,CAAC,EAAE,OAAO,aAAa;aAC3F,oBAACC;GACK;GACK;GACG;GACZ,WAAW,GACT,yBAAyB,IAAI,uBAAuB,OAAO,CAAC,EAC5D,OAAO,SACP,aAAa,yBAAyB,IAAI,uBAAuB,QAAQ,YAAY,CAAC,EACtF,aAAa,OAAO,cACpB,QAAQ,CAAC,YAAY,OAAO,UAC5B,UACD;aAEA;IACU,EACZ,QAAQ,oBAAC;GAAoB,UAAU;GAAc;GAAU,UAAU;GAAgB;IAAK;GAC3F;;AAIV,gCAAe"}
@@ -0,0 +1,20 @@
1
+ import { Theme } from '@thunderid/browser';
2
+ /**
3
+ * Creates styles for the ConsentDetailToggle component.
4
+ * @param theme - The theme object containing design tokens
5
+ * @param colorScheme - The current color scheme (used for memoization)
6
+ * @returns Object containing CSS class names for component styling
7
+ */
8
+ export declare const useToggleStyles: (theme: Theme, colorScheme: string) => Record<string, string>;
9
+ /**
10
+ * Creates styles for the ConsentDetailText component.
11
+ * @param theme - The theme object containing design tokens
12
+ * @param colorScheme - The current color scheme (used for memoization)
13
+ * @param align - Alignment of the text
14
+ * @param monospace - Whether the text is shown as a preformatted monospace block
15
+ * @param maxLines - Number of lines the text is clamped to
16
+ * @returns Object containing CSS class names for component styling
17
+ */
18
+ declare const useStyles: (theme: Theme, colorScheme: string, align: "left" | "right", monospace: boolean, maxLines: number) => Record<string, string>;
19
+ export default useStyles;
20
+ //# sourceMappingURL=ConsentDetailText.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsentDetailText.styles.d.ts","sourceRoot":"","sources":["../../../../src/components/auth/flow/ConsentDetailText.styles.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,KAAK,EAAC,MAAM,oBAAoB,CAAC;AAIzC;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,KAAK,EAAE,aAAa,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAiBtF,CAAC;AAEJ;;;;;;;;GAQG;AACH,QAAA,MAAM,SAAS,GACb,OAAO,KAAK,EACZ,aAAa,MAAM,EACnB,OAAO,MAAM,GAAG,OAAO,EACvB,WAAW,OAAO,EAClB,UAAU,MAAM,KACf,MAAM,CAAC,MAAM,EAAE,MAAM,CAsCrB,CAAC;AAEJ,eAAe,SAAS,CAAC"}
@@ -0,0 +1,80 @@
1
+ import { css } from "../../../styles/emotion.js";
2
+ import { useMemo } from "react";
3
+
4
+ //#region src/components/auth/flow/ConsentDetailText.styles.ts
5
+ /**
6
+ * Creates styles for the ConsentDetailToggle component.
7
+ * @param theme - The theme object containing design tokens
8
+ * @param colorScheme - The current color scheme (used for memoization)
9
+ * @returns Object containing CSS class names for component styling
10
+ */
11
+ const useToggleStyles = (theme, colorScheme) => useMemo(() => ({ toggle: css({
12
+ background: "transparent",
13
+ border: "none",
14
+ borderRadius: "4px",
15
+ color: theme.vars.colors.primary.main,
16
+ cursor: "pointer",
17
+ font: "inherit",
18
+ fontSize: "0.8125rem",
19
+ padding: "2px 4px",
20
+ "&:hover": { textDecoration: "underline" },
21
+ "&:focus-visible": {
22
+ outline: `2px solid ${theme.vars.colors.primary.main}`,
23
+ outlineOffset: "1px"
24
+ }
25
+ }) }), [theme, colorScheme]);
26
+ /**
27
+ * Creates styles for the ConsentDetailText component.
28
+ * @param theme - The theme object containing design tokens
29
+ * @param colorScheme - The current color scheme (used for memoization)
30
+ * @param align - Alignment of the text
31
+ * @param monospace - Whether the text is shown as a preformatted monospace block
32
+ * @param maxLines - Number of lines the text is clamped to
33
+ * @returns Object containing CSS class names for component styling
34
+ */
35
+ const useStyles = (theme, colorScheme, align, monospace, maxLines) => useMemo(() => ({
36
+ clamp: css({
37
+ display: "-webkit-box",
38
+ overflow: "hidden",
39
+ WebkitBoxOrient: "vertical",
40
+ WebkitLineClamp: maxLines
41
+ }),
42
+ container: css({
43
+ alignItems: align === "right" ? "flex-end" : "flex-start",
44
+ display: "flex",
45
+ flexDirection: "column",
46
+ gap: "2px",
47
+ maxWidth: "100%",
48
+ minWidth: 0
49
+ }),
50
+ monospace: css({
51
+ background: theme.vars.colors.action.hover,
52
+ border: `1px solid ${theme.vars.colors.border}`,
53
+ borderRadius: "4px",
54
+ boxSizing: "border-box",
55
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
56
+ fontSize: "0.75rem",
57
+ padding: "6px 8px",
58
+ width: "100%"
59
+ }),
60
+ text: css({
61
+ lineHeight: 1.45,
62
+ margin: 0,
63
+ maxWidth: "100%",
64
+ overflowWrap: "anywhere",
65
+ textAlign: align,
66
+ whiteSpace: monospace ? "pre-wrap" : "normal",
67
+ wordBreak: "normal"
68
+ })
69
+ }), [
70
+ theme,
71
+ colorScheme,
72
+ align,
73
+ monospace,
74
+ maxLines
75
+ ]);
76
+ var ConsentDetailText_styles_default = useStyles;
77
+
78
+ //#endregion
79
+ export { ConsentDetailText_styles_default as default, useToggleStyles };
80
+ //# sourceMappingURL=ConsentDetailText.styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsentDetailText.styles.js","names":[],"sources":["../../../../src/components/auth/flow/ConsentDetailText.styles.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {Theme} from '@thunderid/browser';\nimport {useMemo} from 'react';\nimport {css} from '../../../styles/emotion';\n\n/**\n * Creates styles for the ConsentDetailToggle component.\n * @param theme - The theme object containing design tokens\n * @param colorScheme - The current color scheme (used for memoization)\n * @returns Object containing CSS class names for component styling\n */\nexport const useToggleStyles = (theme: Theme, colorScheme: string): Record<string, string> =>\n useMemo(\n () => ({\n toggle: css({\n background: 'transparent',\n border: 'none',\n borderRadius: '4px',\n color: theme.vars.colors.primary.main,\n cursor: 'pointer',\n font: 'inherit',\n fontSize: '0.8125rem',\n padding: '2px 4px',\n '&:hover': {textDecoration: 'underline'},\n '&:focus-visible': {outline: `2px solid ${theme.vars.colors.primary.main}`, outlineOffset: '1px'},\n }),\n }),\n [theme, colorScheme],\n );\n\n/**\n * Creates styles for the ConsentDetailText component.\n * @param theme - The theme object containing design tokens\n * @param colorScheme - The current color scheme (used for memoization)\n * @param align - Alignment of the text\n * @param monospace - Whether the text is shown as a preformatted monospace block\n * @param maxLines - Number of lines the text is clamped to\n * @returns Object containing CSS class names for component styling\n */\nconst useStyles = (\n theme: Theme,\n colorScheme: string,\n align: 'left' | 'right',\n monospace: boolean,\n maxLines: number,\n): Record<string, string> =>\n useMemo(\n () => ({\n clamp: css({\n display: '-webkit-box',\n overflow: 'hidden',\n WebkitBoxOrient: 'vertical',\n WebkitLineClamp: maxLines,\n }),\n container: css({\n alignItems: align === 'right' ? 'flex-end' : 'flex-start',\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n maxWidth: '100%',\n minWidth: 0,\n }),\n monospace: css({\n background: theme.vars.colors.action.hover,\n border: `1px solid ${theme.vars.colors.border}`,\n borderRadius: '4px',\n boxSizing: 'border-box',\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',\n fontSize: '0.75rem',\n padding: '6px 8px',\n width: '100%',\n }),\n text: css({\n lineHeight: 1.45,\n margin: 0,\n maxWidth: '100%',\n overflowWrap: 'anywhere',\n textAlign: align,\n whiteSpace: monospace ? 'pre-wrap' : 'normal',\n wordBreak: 'normal',\n }),\n }),\n [theme, colorScheme, align, monospace, maxLines],\n );\n\nexport default useStyles;\n"],"mappings":";;;;;;;;;;AAaA,MAAa,mBAAmB,OAAc,gBAC5C,eACS,EACL,QAAQ,IAAI;CACV,YAAY;CACZ,QAAQ;CACR,cAAc;CACd,OAAO,MAAM,KAAK,OAAO,QAAQ;CACjC,QAAQ;CACR,MAAM;CACN,UAAU;CACV,SAAS;CACT,WAAW,EAAC,gBAAgB,aAAY;CACxC,mBAAmB;EAAC,SAAS,aAAa,MAAM,KAAK,OAAO,QAAQ;EAAQ,eAAe;EAAM;CAClG,CAAC,EACH,GACD,CAAC,OAAO,YAAY,CACrB;;;;;;;;;;AAWH,MAAM,aACJ,OACA,aACA,OACA,WACA,aAEA,eACS;CACL,OAAO,IAAI;EACT,SAAS;EACT,UAAU;EACV,iBAAiB;EACjB,iBAAiB;EAClB,CAAC;CACF,WAAW,IAAI;EACb,YAAY,UAAU,UAAU,aAAa;EAC7C,SAAS;EACT,eAAe;EACf,KAAK;EACL,UAAU;EACV,UAAU;EACX,CAAC;CACF,WAAW,IAAI;EACb,YAAY,MAAM,KAAK,OAAO,OAAO;EACrC,QAAQ,aAAa,MAAM,KAAK,OAAO;EACvC,cAAc;EACd,WAAW;EACX,YAAY;EACZ,UAAU;EACV,SAAS;EACT,OAAO;EACR,CAAC;CACF,MAAM,IAAI;EACR,YAAY;EACZ,QAAQ;EACR,UAAU;EACV,cAAc;EACd,WAAW;EACX,YAAY,YAAY,aAAa;EACrC,WAAW;EACZ,CAAC;CACH,GACD;CAAC;CAAO;CAAa;CAAO;CAAW;CAAS,CACjD;AAEH,uCAAe"}
@@ -1,7 +1,7 @@
1
+ import TextField_default from "../../primitives/TextField/TextField.js";
1
2
  import Checkbox_default from "../../primitives/Checkbox/Checkbox.js";
2
3
  import DatePicker_default from "../../primitives/DatePicker/DatePicker.js";
3
4
  import OtpField_default from "../../primitives/OtpField/OtpField.js";
4
- import TextField_default from "../../primitives/TextField/TextField.js";
5
5
  import PasswordField_default from "../../primitives/PasswordField/PasswordField.js";
6
6
  import Select_default from "../../primitives/Select/Select.js";
7
7
  import { FieldType } from "@thunderid/browser";
@@ -0,0 +1,13 @@
1
+ import { UseTranslation } from '../../../hooks/useTranslation';
2
+ /**
3
+ * Resolves a consent screen string through the given translator, falling back to the SDK's default
4
+ * bundle when there is no translator or it has no entry for the key.
5
+ *
6
+ * @param t - Translator, when the screen has one.
7
+ * @param key - Translation key.
8
+ * @param params - Values to substitute into the text.
9
+ * @returns The resolved text.
10
+ */
11
+ declare const resolveConsentText: (t: UseTranslation["t"] | undefined, key: string, params?: Record<string, string | number>) => string;
12
+ export default resolveConsentText;
13
+ //# sourceMappingURL=resolveConsentText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveConsentText.d.ts","sourceRoot":"","sources":["../../../../src/components/auth/flow/resolveConsentText.ts"],"names":[],"mappings":"AASA,OAAO,EAAC,cAAc,EAAC,MAAM,+BAA+B,CAAC;AAE7D;;;;;;;;GAQG;AACH,QAAA,MAAM,kBAAkB,GACtB,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,SAAS,EAClC,KAAK,MAAM,EACX,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KACvC,MASF,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { TranslationBundleConstants, getDefaultI18nBundles, substituteTranslationParams } from "@thunderid/browser";
2
+
3
+ //#region src/components/auth/flow/resolveConsentText.ts
4
+ /**
5
+ * Resolves a consent screen string through the given translator, falling back to the SDK's default
6
+ * bundle when there is no translator or it has no entry for the key.
7
+ *
8
+ * @param t - Translator, when the screen has one.
9
+ * @param key - Translation key.
10
+ * @param params - Values to substitute into the text.
11
+ * @returns The resolved text.
12
+ */
13
+ const resolveConsentText = (t, key, params) => {
14
+ const translated = t?.(key, params);
15
+ if (translated && translated !== key) return translated;
16
+ const fallback = getDefaultI18nBundles()[TranslationBundleConstants.FALLBACK_LOCALE]?.translations[key];
17
+ return substituteTranslationParams(fallback ?? key, params);
18
+ };
19
+ var resolveConsentText_default = resolveConsentText;
20
+
21
+ //#endregion
22
+ export { resolveConsentText_default as default };
23
+ //# sourceMappingURL=resolveConsentText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveConsentText.js","names":["translated: string | undefined","fallback: string | undefined"],"sources":["../../../../src/components/auth/flow/resolveConsentText.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n getDefaultI18nBundles,\n I18nBundle,\n substituteTranslationParams,\n TranslationBundleConstants,\n} from '@thunderid/browser';\nimport {UseTranslation} from '../../../hooks/useTranslation';\n\n/**\n * Resolves a consent screen string through the given translator, falling back to the SDK's default\n * bundle when there is no translator or it has no entry for the key.\n *\n * @param t - Translator, when the screen has one.\n * @param key - Translation key.\n * @param params - Values to substitute into the text.\n * @returns The resolved text.\n */\nconst resolveConsentText = (\n t: UseTranslation['t'] | undefined,\n key: string,\n params?: Record<string, string | number>,\n): string => {\n const translated: string | undefined = t?.(key, params);\n if (translated && translated !== key) {\n return translated;\n }\n const bundle: I18nBundle | undefined = getDefaultI18nBundles()[TranslationBundleConstants.FALLBACK_LOCALE];\n const fallback: string | undefined = bundle?.translations[key as keyof I18nBundle['translations']];\n\n return substituteTranslationParams(fallback ?? key, params);\n};\n\nexport default resolveConsentText;\n"],"mappings":";;;;;;;;;;;;AAoBA,MAAM,sBACJ,GACA,KACA,WACW;CACX,MAAMA,aAAiC,IAAI,KAAK,OAAO;AACvD,KAAI,cAAc,eAAe,IAC/B,QAAO;CAGT,MAAMC,WADiC,uBAAuB,CAAC,2BAA2B,kBAC7C,aAAa;AAE1D,QAAO,4BAA4B,YAAY,KAAK,OAAO;;AAG7D,iCAAe"}
@@ -1,8 +1,8 @@
1
1
  import { cx } from "../../../styles/emotion.js";
2
2
  import useTheme_default from "../../../contexts/Theme/useTheme.js";
3
+ import TextField_default from "../TextField/TextField.js";
3
4
  import Plus_default from "../Icons/Plus.js";
4
5
  import X_default from "../Icons/X.js";
5
- import TextField_default from "../TextField/TextField.js";
6
6
  import KeyValueInput_styles_default from "./KeyValueInput.styles.js";
7
7
  import { bem, withVendorCSSClassPrefix } from "@thunderid/browser";
8
8
  import { useCallback, useState } from "react";
@@ -2,9 +2,9 @@ import { cx } from "../../../styles/emotion.js";
2
2
  import useTheme_default from "../../../contexts/Theme/useTheme.js";
3
3
  import FormControl_default from "../FormControl/FormControl.js";
4
4
  import InputLabel_default from "../InputLabel/InputLabel.js";
5
+ import TextField_default from "../TextField/TextField.js";
5
6
  import Checkbox_default from "../Checkbox/Checkbox.js";
6
7
  import DatePicker_default from "../DatePicker/DatePicker.js";
7
- import TextField_default from "../TextField/TextField.js";
8
8
  import MultiInput_styles_default from "./MultiInput.styles.js";
9
9
  import { bem, withVendorCSSClassPrefix } from "@thunderid/browser";
10
10
  import { useCallback, useId, useState } from "react";
@@ -1,9 +1,9 @@
1
1
  import { cx } from "../../../styles/emotion.js";
2
2
  import useTheme_default from "../../../contexts/Theme/useTheme.js";
3
+ import TextField_default from "../TextField/TextField.js";
3
4
  import Eye_default from "../Icons/Eye.js";
4
5
  import EyeOff_default from "../Icons/EyeOff.js";
5
6
  import PasswordField_styles_default from "./PasswordField.styles.js";
6
- import TextField_default from "../TextField/TextField.js";
7
7
  import { bem, withVendorCSSClassPrefix } from "@thunderid/browser";
8
8
  import { useState } from "react";
9
9
  import { jsx } from "react/jsx-runtime";
@@ -7,7 +7,8 @@ export interface ThemeProviderProps {
7
7
  */
8
8
  designTheme?: FlowMetaTheme | null;
9
9
  /**
10
- * Initial color scheme override. Overrides the server default when provided.
10
+ * Color scheme override. Overrides the server default when provided, and the color scheme follows it
11
+ * when it changes.
11
12
  */
12
13
  mode?: ThemeMode;
13
14
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../../src/contexts/Theme/ThemeProvider.tsx"],"names":[],"mappings":"AAGA,OAAO,EAKL,aAAa,EACb,gBAAgB,EAEhB,WAAW,EACX,SAAS,EACV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,EAAE,EAAE,iBAAiB,EAAsE,MAAM,OAAO,CAAC;AAOjH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,WAAW,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACnC;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,QAAA,MAAM,aAAa,EAAE,EAAE,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAsH5D,CAAC;AAEF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../../src/contexts/Theme/ThemeProvider.tsx"],"names":[],"mappings":"AAGA,OAAO,EAKL,aAAa,EACb,gBAAgB,EAEhB,WAAW,EACX,SAAS,EACV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,EAAE,EAEF,iBAAiB,EAQlB,MAAM,OAAO,CAAC;AAQf,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,WAAW,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACnC;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,QAAA,MAAM,aAAa,EAAE,EAAE,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAwJ5D,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -1,10 +1,11 @@
1
1
  import FlowMetaContext_default from "../FlowMeta/FlowMetaContext.js";
2
2
  import ThemeContext_default from "./ThemeContext.js";
3
+ import ThemeRootContext_default from "./ThemeRootContext.js";
3
4
  import applyThemeToDOM_default from "../../utils/applyThemeToDOM.js";
4
5
  import buildThemeConfigFromFlowMeta_default from "../../utils/buildThemeConfigFromFlowMeta.js";
5
6
  import normalizeThemeConfig_default from "../../utils/normalizeThemeConfig.js";
6
7
  import { createClassObserver, createMediaQueryListener, createTheme, detectThemeMode } from "@thunderid/browser";
7
- import { useCallback, useContext, useEffect, useMemo, useState } from "react";
8
+ import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
8
9
  import { jsx } from "react/jsx-runtime";
9
10
 
10
11
  //#region src/contexts/Theme/ThemeProvider.tsx
@@ -49,6 +50,11 @@ const ThemeProvider = ({ children, designTheme = void 0, mode, theme: themeOverr
49
50
  return flowMetaTheme?.defaultColorScheme ?? "light";
50
51
  };
51
52
  const [colorScheme, setColorScheme] = useState(getInitialColorScheme);
53
+ const [seededMode, setSeededMode] = useState(mode);
54
+ if (mode !== seededMode) {
55
+ setSeededMode(mode);
56
+ if (mode !== void 0) setColorScheme(getInitialColorScheme());
57
+ }
52
58
  useEffect(() => {
53
59
  if (mode === void 0 && flowMetaTheme?.defaultColorScheme) setColorScheme(flowMetaTheme.defaultColorScheme);
54
60
  }, [mode, flowMetaTheme?.defaultColorScheme]);
@@ -99,12 +105,33 @@ const ThemeProvider = ({ children, designTheme = void 0, mode, theme: themeOverr
99
105
  ]);
100
106
  const theme = useMemo(() => createTheme(finalThemeConfig, colorScheme === "dark"), [finalThemeConfig, colorScheme]);
101
107
  const direction = flowMetaTheme?.direction ?? "ltr";
108
+ const parentRoot = useContext(ThemeRootContext_default);
109
+ const claims = useRef(0);
110
+ const applied = useRef(null);
111
+ const applyToRoot = useCallback(() => {
112
+ if (!applied.current || typeof document === "undefined") return;
113
+ applyThemeToDOM_default(applied.current.theme);
114
+ document.documentElement.dir = applied.current.direction;
115
+ }, []);
116
+ const root = useMemo(() => ({ claim: () => {
117
+ claims.current += 1;
118
+ return () => {
119
+ claims.current -= 1;
120
+ if (claims.current === 0) applyToRoot();
121
+ };
122
+ } }), [applyToRoot]);
123
+ useEffect(() => parentRoot?.claim(), [parentRoot]);
102
124
  useEffect(() => {
103
- applyThemeToDOM_default(theme);
104
- }, [theme]);
105
- useEffect(() => {
106
- if (typeof document !== "undefined") document.documentElement.dir = direction;
107
- }, [direction]);
125
+ applied.current = {
126
+ direction,
127
+ theme
128
+ };
129
+ if (claims.current === 0) applyToRoot();
130
+ }, [
131
+ applyToRoot,
132
+ direction,
133
+ theme
134
+ ]);
108
135
  const value = {
109
136
  colorScheme,
110
137
  direction,
@@ -113,7 +140,10 @@ const ThemeProvider = ({ children, designTheme = void 0, mode, theme: themeOverr
113
140
  };
114
141
  return /* @__PURE__ */ jsx(ThemeContext_default.Provider, {
115
142
  value,
116
- children
143
+ children: /* @__PURE__ */ jsx(ThemeRootContext_default.Provider, {
144
+ value: root,
145
+ children
146
+ })
117
147
  });
118
148
  };
119
149
  var ThemeProvider_default = ThemeProvider;
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.js","names":["ThemeProvider: FC<PropsWithChildren<ThemeProviderProps>>","themeOverride: RecursivePartial<ThemeConfig> | undefined","normalizeThemeConfig","flowMetaContext: FlowMetaContextValue | null","FlowMetaContext","flowMetaTheme: FlowMetaTheme | null","toggleTheme: () => void","finalThemeConfig: RecursivePartial<ThemeConfig> | undefined","metaConfig: RecursivePartial<ThemeConfig>","buildThemeConfigFromFlowMeta","theme: Theme","direction: 'ltr' | 'rtl'","value: any","ThemeContext"],"sources":["../../../src/contexts/Theme/ThemeProvider.tsx"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n createClassObserver,\n createMediaQueryListener,\n createTheme,\n detectThemeMode,\n FlowMetaTheme,\n RecursivePartial,\n Theme,\n ThemeConfig,\n ThemeMode,\n} from '@thunderid/browser';\nimport {FC, PropsWithChildren, ReactElement, useCallback, useContext, useEffect, useMemo, useState} from 'react';\nimport ThemeContext from './ThemeContext';\nimport applyThemeToDOM from '../../utils/applyThemeToDOM';\nimport buildThemeConfigFromFlowMeta from '../../utils/buildThemeConfigFromFlowMeta';\nimport normalizeThemeConfig from '../../utils/normalizeThemeConfig';\nimport FlowMetaContext, {FlowMetaContextValue} from '../FlowMeta/FlowMetaContext';\n\nexport interface ThemeProviderProps {\n /**\n * A Design theme to use instead of the one the server returns in flow meta, for example the theme an\n * app configuration names. `theme` overrides are still applied on top.\n */\n designTheme?: FlowMetaTheme | null;\n /**\n * Initial color scheme override. Overrides the server default when provided.\n */\n mode?: ThemeMode;\n\n /**\n * Optional theme overrides merged on top of the server-side flow meta theme.\n * User-supplied values take highest precedence.\n */\n theme?: RecursivePartial<ThemeConfig>;\n}\n\n/**\n * ThemeProvider is the v2 drop-in replacement for `ThemeProvider`.\n *\n * It reads the design theme from the nearest `FlowMetaContext` (provided by\n * `FlowMetaProvider`) and publishes a resolved `Theme` object through the\n * **same** `ThemeContext` that `useTheme` consumes. This means all existing\n * components that call `useTheme` continue to work without any changes.\n *\n * The `defaultColorScheme` field returned by the server is used to seed the\n * active color scheme; the user can still toggle it locally via the\n * `toggleTheme` value exposed in the context.\n *\n * @example\n * ```tsx\n * <FlowMetaProvider config={{ baseUrl, type: FlowMetaType.App, id: appId }}>\n * <ThemeProvider>\n * <App /> {/* useTheme() works here as usual *\\/}\n * </ThemeProvider>\n * </FlowMetaProvider>\n * ```\n *\n * @example\n * With user theme overrides (user values win over server values):\n * ```tsx\n * <ThemeProvider theme={{ colors: { primary: { main: '#ff0000' } } }}>\n * <App />\n * </ThemeProvider>\n * ```\n */\nconst ThemeProvider: FC<PropsWithChildren<ThemeProviderProps>> = ({\n children,\n designTheme = undefined,\n mode,\n theme: themeOverrideProp,\n}: PropsWithChildren<ThemeProviderProps>): ReactElement => {\n const themeOverride: RecursivePartial<ThemeConfig> | undefined = normalizeThemeConfig(themeOverrideProp);\n const flowMetaContext: FlowMetaContextValue | null = useContext(FlowMetaContext);\n\n const flowMetaTheme: FlowMetaTheme | null = designTheme ?? flowMetaContext?.meta?.design?.theme ?? null;\n const isLoading: boolean = flowMetaContext?.isLoading ?? false;\n const error: Error | null = flowMetaContext?.error ?? null;\n\n // Seed the color scheme: a fixed mode wins outright, 'system'/'class' detect it from the\n // environment via the same shared utilities Vue's ThemeProvider uses, and no mode falls back\n // to the server's default (unchanged pre-`mode` behavior).\n const getInitialColorScheme = (): 'light' | 'dark' => {\n if (mode === 'light' || mode === 'dark') return mode;\n if (mode === 'system' || mode === 'class') return detectThemeMode(mode);\n return flowMetaTheme?.defaultColorScheme ?? 'light';\n };\n\n const [colorScheme, setColorScheme] = useState<'light' | 'dark'>(getInitialColorScheme);\n\n // When mode is unset, sync the color scheme with the server default once flow meta loads.\n useEffect(() => {\n if (mode === undefined && flowMetaTheme?.defaultColorScheme) {\n setColorScheme(flowMetaTheme.defaultColorScheme);\n }\n }, [mode, flowMetaTheme?.defaultColorScheme]);\n\n // Set up automatic detection listeners for 'system'/'class' modes.\n useEffect(() => {\n if (mode !== 'system' && mode !== 'class') return undefined;\n\n const handleThemeChange = (isDark: boolean): void => {\n setColorScheme(isDark ? 'dark' : 'light');\n };\n\n if (mode === 'class') {\n if (typeof document === 'undefined') return undefined;\n const observer = createClassObserver(document.documentElement, handleThemeChange);\n return () => {\n observer.disconnect();\n };\n }\n\n const mediaQuery = createMediaQueryListener(handleThemeChange);\n return () => {\n mediaQuery?.disconnect();\n };\n }, [mode]);\n\n const toggleTheme: () => void = useCallback(() => {\n setColorScheme((prev: 'light' | 'dark') => (prev === 'light' ? 'dark' : 'light'));\n }, []);\n\n // Build the resolved ThemeConfig: flow meta base → user overrides on top.\n const finalThemeConfig: RecursivePartial<ThemeConfig> | undefined = useMemo(() => {\n if (!flowMetaTheme) {\n return themeOverride;\n }\n\n const metaConfig: RecursivePartial<ThemeConfig> = buildThemeConfigFromFlowMeta(flowMetaTheme, colorScheme);\n\n if (!themeOverride) {\n return metaConfig;\n }\n\n return {\n ...metaConfig,\n ...themeOverride,\n borderRadius: {\n ...metaConfig.borderRadius,\n ...themeOverride.borderRadius,\n },\n colors: {\n ...metaConfig.colors,\n ...themeOverride.colors,\n },\n ...(metaConfig.typography || themeOverride.typography\n ? {\n typography: {\n ...(metaConfig as any).typography,\n ...themeOverride.typography,\n },\n }\n : {}),\n };\n }, [flowMetaTheme, colorScheme, themeOverride]);\n\n const theme: Theme = useMemo(\n () => createTheme(finalThemeConfig, colorScheme === 'dark'),\n [finalThemeConfig, colorScheme],\n );\n\n const direction: 'ltr' | 'rtl' = flowMetaTheme?.direction ?? 'ltr';\n\n // Apply CSS variables to the document root.\n useEffect(() => {\n applyThemeToDOM(theme);\n }, [theme]);\n\n // Apply text direction to the document root.\n useEffect(() => {\n if (typeof document !== 'undefined') {\n document.documentElement.dir = direction;\n }\n }, [direction]);\n\n const value: any = {\n colorScheme,\n direction,\n theme,\n toggleTheme,\n };\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n};\n\nexport default ThemeProvider;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEA,MAAMA,iBAA4D,EAChE,UACA,cAAc,QACd,MACA,OAAO,wBACkD;CACzD,MAAMC,gBAA2DC,6BAAqB,kBAAkB;CACxG,MAAMC,kBAA+C,WAAWC,wBAAgB;CAEhF,MAAMC,gBAAsC,eAAe,iBAAiB,MAAM,QAAQ,SAAS;AACxE,kBAAiB;AAChB,kBAAiB;CAK7C,MAAM,8BAAgD;AACpD,MAAI,SAAS,WAAW,SAAS,OAAQ,QAAO;AAChD,MAAI,SAAS,YAAY,SAAS,QAAS,QAAO,gBAAgB,KAAK;AACvE,SAAO,eAAe,sBAAsB;;CAG9C,MAAM,CAAC,aAAa,kBAAkB,SAA2B,sBAAsB;AAGvF,iBAAgB;AACd,MAAI,SAAS,UAAa,eAAe,mBACvC,gBAAe,cAAc,mBAAmB;IAEjD,CAAC,MAAM,eAAe,mBAAmB,CAAC;AAG7C,iBAAgB;AACd,MAAI,SAAS,YAAY,SAAS,QAAS,QAAO;EAElD,MAAM,qBAAqB,WAA0B;AACnD,kBAAe,SAAS,SAAS,QAAQ;;AAG3C,MAAI,SAAS,SAAS;AACpB,OAAI,OAAO,aAAa,YAAa,QAAO;GAC5C,MAAM,WAAW,oBAAoB,SAAS,iBAAiB,kBAAkB;AACjF,gBAAa;AACX,aAAS,YAAY;;;EAIzB,MAAM,aAAa,yBAAyB,kBAAkB;AAC9D,eAAa;AACX,eAAY,YAAY;;IAEzB,CAAC,KAAK,CAAC;CAEV,MAAMC,cAA0B,kBAAkB;AAChD,kBAAgB,SAA4B,SAAS,UAAU,SAAS,QAAS;IAChF,EAAE,CAAC;CAGN,MAAMC,mBAA8D,cAAc;AAChF,MAAI,CAAC,cACH,QAAO;EAGT,MAAMC,aAA4CC,qCAA6B,eAAe,YAAY;AAE1G,MAAI,CAAC,cACH,QAAO;AAGT,SAAO;GACL,GAAG;GACH,GAAG;GACH,cAAc;IACZ,GAAG,WAAW;IACd,GAAG,cAAc;IAClB;GACD,QAAQ;IACN,GAAG,WAAW;IACd,GAAG,cAAc;IAClB;GACD,GAAI,WAAW,cAAc,cAAc,aACvC,EACE,YAAY;IACV,GAAI,WAAmB;IACvB,GAAG,cAAc;IAClB,EACF,GACD,EAAE;GACP;IACA;EAAC;EAAe;EAAa;EAAc,CAAC;CAE/C,MAAMC,QAAe,cACb,YAAY,kBAAkB,gBAAgB,OAAO,EAC3D,CAAC,kBAAkB,YAAY,CAChC;CAED,MAAMC,YAA2B,eAAe,aAAa;AAG7D,iBAAgB;AACd,0BAAgB,MAAM;IACrB,CAAC,MAAM,CAAC;AAGX,iBAAgB;AACd,MAAI,OAAO,aAAa,YACtB,UAAS,gBAAgB,MAAM;IAEhC,CAAC,UAAU,CAAC;CAEf,MAAMC,QAAa;EACjB;EACA;EACA;EACA;EACD;AAED,QAAO,oBAACC,qBAAa;EAAgB;EAAQ;GAAiC;;AAGhF,4BAAe"}
1
+ {"version":3,"file":"ThemeProvider.js","names":["ThemeProvider: FC<PropsWithChildren<ThemeProviderProps>>","themeOverride: RecursivePartial<ThemeConfig> | undefined","normalizeThemeConfig","flowMetaContext: FlowMetaContextValue | null","FlowMetaContext","flowMetaTheme: FlowMetaTheme | null","toggleTheme: () => void","finalThemeConfig: RecursivePartial<ThemeConfig> | undefined","metaConfig: RecursivePartial<ThemeConfig>","buildThemeConfigFromFlowMeta","theme: Theme","direction: 'ltr' | 'rtl'","parentRoot: ThemeRootContextValue | null","ThemeRootContext","claims: MutableRefObject<number>","applied: MutableRefObject<{direction: 'ltr' | 'rtl'; theme: Theme} | null>","applyToRoot: () => void","root: ThemeRootContextValue","value: any","ThemeContext"],"sources":["../../../src/contexts/Theme/ThemeProvider.tsx"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n createClassObserver,\n createMediaQueryListener,\n createTheme,\n detectThemeMode,\n FlowMetaTheme,\n RecursivePartial,\n Theme,\n ThemeConfig,\n ThemeMode,\n} from '@thunderid/browser';\nimport {\n FC,\n MutableRefObject,\n PropsWithChildren,\n ReactElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport ThemeContext from './ThemeContext';\nimport ThemeRootContext, {ThemeRootContextValue} from './ThemeRootContext';\nimport applyThemeToDOM from '../../utils/applyThemeToDOM';\nimport buildThemeConfigFromFlowMeta from '../../utils/buildThemeConfigFromFlowMeta';\nimport normalizeThemeConfig from '../../utils/normalizeThemeConfig';\nimport FlowMetaContext, {FlowMetaContextValue} from '../FlowMeta/FlowMetaContext';\n\nexport interface ThemeProviderProps {\n /**\n * A Design theme to use instead of the one the server returns in flow meta, for example the theme an\n * app configuration names. `theme` overrides are still applied on top.\n */\n designTheme?: FlowMetaTheme | null;\n /**\n * Color scheme override. Overrides the server default when provided, and the color scheme follows it\n * when it changes.\n */\n mode?: ThemeMode;\n\n /**\n * Optional theme overrides merged on top of the server-side flow meta theme.\n * User-supplied values take highest precedence.\n */\n theme?: RecursivePartial<ThemeConfig>;\n}\n\n/**\n * ThemeProvider is the v2 drop-in replacement for `ThemeProvider`.\n *\n * It reads the design theme from the nearest `FlowMetaContext` (provided by\n * `FlowMetaProvider`) and publishes a resolved `Theme` object through the\n * **same** `ThemeContext` that `useTheme` consumes. This means all existing\n * components that call `useTheme` continue to work without any changes.\n *\n * The `defaultColorScheme` field returned by the server is used to seed the\n * active color scheme; the user can still toggle it locally via the\n * `toggleTheme` value exposed in the context.\n *\n * @example\n * ```tsx\n * <FlowMetaProvider config={{ baseUrl, type: FlowMetaType.App, id: appId }}>\n * <ThemeProvider>\n * <App /> {/* useTheme() works here as usual *\\/}\n * </ThemeProvider>\n * </FlowMetaProvider>\n * ```\n *\n * @example\n * With user theme overrides (user values win over server values):\n * ```tsx\n * <ThemeProvider theme={{ colors: { primary: { main: '#ff0000' } } }}>\n * <App />\n * </ThemeProvider>\n * ```\n */\nconst ThemeProvider: FC<PropsWithChildren<ThemeProviderProps>> = ({\n children,\n designTheme = undefined,\n mode,\n theme: themeOverrideProp,\n}: PropsWithChildren<ThemeProviderProps>): ReactElement => {\n const themeOverride: RecursivePartial<ThemeConfig> | undefined = normalizeThemeConfig(themeOverrideProp);\n const flowMetaContext: FlowMetaContextValue | null = useContext(FlowMetaContext);\n\n const flowMetaTheme: FlowMetaTheme | null = designTheme ?? flowMetaContext?.meta?.design?.theme ?? null;\n const isLoading: boolean = flowMetaContext?.isLoading ?? false;\n const error: Error | null = flowMetaContext?.error ?? null;\n\n // Seed the color scheme: a fixed mode wins outright, 'system'/'class' detect it from the\n // environment via the same shared utilities Vue's ThemeProvider uses, and no mode falls back\n // to the server's default (unchanged pre-`mode` behavior).\n const getInitialColorScheme = (): 'light' | 'dark' => {\n if (mode === 'light' || mode === 'dark') return mode;\n if (mode === 'system' || mode === 'class') return detectThemeMode(mode);\n return flowMetaTheme?.defaultColorScheme ?? 'light';\n };\n\n const [colorScheme, setColorScheme] = useState<'light' | 'dark'>(getInitialColorScheme);\n\n // Follow a change of mode after mount, such as a host app's own color scheme toggle.\n const [seededMode, setSeededMode] = useState<ThemeMode | undefined>(mode);\n\n if (mode !== seededMode) {\n setSeededMode(mode);\n if (mode !== undefined) {\n setColorScheme(getInitialColorScheme());\n }\n }\n\n // When mode is unset, sync the color scheme with the server default once flow meta loads.\n useEffect(() => {\n if (mode === undefined && flowMetaTheme?.defaultColorScheme) {\n setColorScheme(flowMetaTheme.defaultColorScheme);\n }\n }, [mode, flowMetaTheme?.defaultColorScheme]);\n\n // Set up automatic detection listeners for 'system'/'class' modes.\n useEffect(() => {\n if (mode !== 'system' && mode !== 'class') return undefined;\n\n const handleThemeChange = (isDark: boolean): void => {\n setColorScheme(isDark ? 'dark' : 'light');\n };\n\n if (mode === 'class') {\n if (typeof document === 'undefined') return undefined;\n const observer = createClassObserver(document.documentElement, handleThemeChange);\n return () => {\n observer.disconnect();\n };\n }\n\n const mediaQuery = createMediaQueryListener(handleThemeChange);\n return () => {\n mediaQuery?.disconnect();\n };\n }, [mode]);\n\n const toggleTheme: () => void = useCallback(() => {\n setColorScheme((prev: 'light' | 'dark') => (prev === 'light' ? 'dark' : 'light'));\n }, []);\n\n // Build the resolved ThemeConfig: flow meta base → user overrides on top.\n const finalThemeConfig: RecursivePartial<ThemeConfig> | undefined = useMemo(() => {\n if (!flowMetaTheme) {\n return themeOverride;\n }\n\n const metaConfig: RecursivePartial<ThemeConfig> = buildThemeConfigFromFlowMeta(flowMetaTheme, colorScheme);\n\n if (!themeOverride) {\n return metaConfig;\n }\n\n return {\n ...metaConfig,\n ...themeOverride,\n borderRadius: {\n ...metaConfig.borderRadius,\n ...themeOverride.borderRadius,\n },\n colors: {\n ...metaConfig.colors,\n ...themeOverride.colors,\n },\n ...(metaConfig.typography || themeOverride.typography\n ? {\n typography: {\n ...(metaConfig as any).typography,\n ...themeOverride.typography,\n },\n }\n : {}),\n };\n }, [flowMetaTheme, colorScheme, themeOverride]);\n\n const theme: Theme = useMemo(\n () => createTheme(finalThemeConfig, colorScheme === 'dark'),\n [finalThemeConfig, colorScheme],\n );\n\n const direction: 'ltr' | 'rtl' = flowMetaTheme?.direction ?? 'ltr';\n\n // The innermost ThemeProvider owns the document root: an outer one stops writing its CSS variables\n // and text direction while a nested one is mounted, and writes them again once it unmounts.\n const parentRoot: ThemeRootContextValue | null = useContext(ThemeRootContext);\n const claims: MutableRefObject<number> = useRef<number>(0);\n const applied: MutableRefObject<{direction: 'ltr' | 'rtl'; theme: Theme} | null> = useRef(null);\n\n const applyToRoot: () => void = useCallback(() => {\n if (!applied.current || typeof document === 'undefined') return;\n applyThemeToDOM(applied.current.theme);\n document.documentElement.dir = applied.current.direction;\n }, []);\n\n const root: ThemeRootContextValue = useMemo(\n () => ({\n claim: (): (() => void) => {\n claims.current += 1;\n return (): void => {\n claims.current -= 1;\n if (claims.current === 0) applyToRoot();\n };\n },\n }),\n [applyToRoot],\n );\n\n useEffect(() => parentRoot?.claim(), [parentRoot]);\n\n useEffect(() => {\n applied.current = {direction, theme};\n if (claims.current === 0) applyToRoot();\n }, [applyToRoot, direction, theme]);\n\n const value: any = {\n colorScheme,\n direction,\n theme,\n toggleTheme,\n };\n\n return (\n <ThemeContext.Provider value={value}>\n <ThemeRootContext.Provider value={root}>{children}</ThemeRootContext.Provider>\n </ThemeContext.Provider>\n );\n};\n\nexport default ThemeProvider;\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { Context } from 'react';
2
+ export interface ThemeRootContextValue {
3
+ /**
4
+ * Hands the document root to a nested `ThemeProvider` until the returned release is called, so the
5
+ * innermost provider's CSS variables and text direction are the ones on the page.
6
+ */
7
+ claim: () => () => void;
8
+ }
9
+ declare const ThemeRootContext: Context<ThemeRootContextValue | null>;
10
+ export default ThemeRootContext;
11
+ //# sourceMappingURL=ThemeRootContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeRootContext.d.ts","sourceRoot":"","sources":["../../../src/contexts/Theme/ThemeRootContext.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,OAAO,EAAgB,MAAM,OAAO,CAAC;AAE7C,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,KAAK,EAAE,MAAM,MAAM,IAAI,CAAC;CACzB;AAED,QAAA,MAAM,gBAAgB,EAAE,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAqD,CAAC;AAIlH,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { createContext } from "react";
2
+
3
+ //#region src/contexts/Theme/ThemeRootContext.ts
4
+ const ThemeRootContext = createContext(null);
5
+ ThemeRootContext.displayName = "ThemeRootContext";
6
+ var ThemeRootContext_default = ThemeRootContext;
7
+
8
+ //#endregion
9
+ export { ThemeRootContext_default as default };
10
+ //# sourceMappingURL=ThemeRootContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeRootContext.js","names":["ThemeRootContext: Context<ThemeRootContextValue | null>"],"sources":["../../../src/contexts/Theme/ThemeRootContext.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {Context, createContext} from 'react';\n\nexport interface ThemeRootContextValue {\n /**\n * Hands the document root to a nested `ThemeProvider` until the returned release is called, so the\n * innermost provider's CSS variables and text direction are the ones on the page.\n */\n claim: () => () => void;\n}\n\nconst ThemeRootContext: Context<ThemeRootContextValue | null> = createContext<ThemeRootContextValue | null>(null);\n\nThemeRootContext.displayName = 'ThemeRootContext';\n\nexport default ThemeRootContext;\n"],"mappings":";;;AAaA,MAAMA,mBAA0D,cAA4C,KAAK;AAEjH,iBAAiB,cAAc;AAE/B,+BAAe"}
@@ -0,0 +1,130 @@
1
+ import { type ConsentDetailRow } from '@thunderid/browser';
2
+ import { type ConsentDetailListDisplay } from '../../utils/getConsentDetailListDisplay';
3
+ import { UseTranslation } from '../useTranslation';
4
+ /**
5
+ * How the user may change one field of an authorization detail on the consent screen: type a lower or
6
+ * higher `number` or `date`, or toggle items of a list whose rule is `removeItems` or `addItems`.
7
+ *
8
+ * @experimental This type may change in future versions
9
+ */
10
+ export type ConsentDetailInputKind = 'number' | 'date' | 'removeItems' | 'addItems';
11
+ /**
12
+ * Error shown for text a user entered into an authorization detail field, as a translation key and the
13
+ * values to substitute into its text.
14
+ *
15
+ * @experimental This interface may change in future versions
16
+ */
17
+ export interface ConsentDetailInputError {
18
+ /** Translation key of the message. */
19
+ key: string;
20
+ /** Values to substitute into the message: `value` is the value that was shown. */
21
+ params: Record<string, string>;
22
+ }
23
+ /**
24
+ * One item of a list field of an authorization detail, as the consent screen offers it.
25
+ *
26
+ * @experimental This interface may change in future versions
27
+ */
28
+ export interface ConsentDetailListItem {
29
+ /**
30
+ * Where the item comes from: `shown` in the requested detail, `added` by the user, or `offered` by the
31
+ * type for the user to add.
32
+ */
33
+ origin: 'shown' | 'added' | 'offered';
34
+ /** Whether the item is part of the value that would be granted. */
35
+ selected: boolean;
36
+ /** Whether the user may toggle the item. */
37
+ toggleable: boolean;
38
+ /** The item. */
39
+ value: string | number | boolean;
40
+ }
41
+ /**
42
+ * Props for the useConsentDetailField hook.
43
+ */
44
+ export interface UseConsentDetailFieldProps {
45
+ /** The identifier of the consent purpose the authorization detail belongs to. */
46
+ purposeId: string;
47
+ /** The identifier of the authorization detail the field belongs to, its consent element name. */
48
+ detailId: string;
49
+ /** Current consent form values. */
50
+ formValues: Record<string, string>;
51
+ /** Callback that writes one consent form value. */
52
+ onInputChange: (name: string, value: string) => void;
53
+ /** The field. */
54
+ row: ConsentDetailRow;
55
+ /** Translator for the error message; the SDK's default bundle is used without one. */
56
+ t?: UseTranslation['t'];
57
+ }
58
+ /**
59
+ * Error of a field, with its message resolved.
60
+ */
61
+ export interface ConsentDetailFieldError extends ConsentDetailInputError {
62
+ /** Translated message. */
63
+ message: string;
64
+ }
65
+ /**
66
+ * State and handlers of one authorization detail field, for drawing it in any UI.
67
+ */
68
+ export interface UseConsentDetailFieldResult {
69
+ /** Why the text shown cannot be submitted, absent when it can. */
70
+ error?: ConsentDetailFieldError;
71
+ /** Adds a typed item to an `addItems` list that takes typed values; returns whether it was added. */
72
+ handleAdd: (text: string) => boolean;
73
+ /** Call when the field loses focus: an empty field returns to the value that was shown. */
74
+ handleBlur: () => void;
75
+ /** Call with the text the user entered into a `number` or `date` field, or the item typed into a list. */
76
+ handleChange: (text: string) => void;
77
+ /** Expands or collapses the field's list. */
78
+ handleListToggle: (expanded: boolean) => void;
79
+ /** Toggles an item of a list field, within what its rule allows. */
80
+ handleToggle: (item: string | number | boolean) => void;
81
+ /** Identifier for the field's input element. */
82
+ inputId: string;
83
+ /** Whether the user expanded the field's list past `CONSENT_DETAIL_DISPLAY_LIMITS.listItems`. */
84
+ isListExpanded: boolean;
85
+ /** Whether the field's value is a list of plain values, shown as a list rather than as structured JSON. */
86
+ isPlainList: boolean;
87
+ /** Whether an item of a list field is part of the value that would be granted. */
88
+ isSelected: (item: string | number | boolean) => boolean;
89
+ /** Whether the user may toggle an item of a list field. */
90
+ isToggleable: (item: string | number | boolean) => boolean;
91
+ /** Whether the field takes typed items: an `addItems` list whose type offers no fixed values. */
92
+ isTypedItemAllowed: boolean;
93
+ /** Whether the field's text may be submitted. Always true for a list or a read-only field. */
94
+ isValid: boolean;
95
+ /** Items of a list field, in display order; empty for any other field. */
96
+ items: ConsentDetailListItem[];
97
+ /** How the user may change the field, or `undefined` when it is read-only. */
98
+ kind?: ConsentDetailInputKind;
99
+ /** Label of the field. */
100
+ label: string;
101
+ /**
102
+ * How many items of the field's list to show and hide: the items of a list the user may change, or the
103
+ * values of a read-only plain list. Nothing is hidden for any other field.
104
+ */
105
+ listDisplay: ConsentDetailListDisplay;
106
+ /** Upper bound of a `number` or `date` field that may be decreased. */
107
+ max?: string;
108
+ /** Lower bound of a `number` or `date` field that may be increased. */
109
+ min?: string;
110
+ /** Text to show: the typed text of a `number` or `date` field, or the item being typed into a list. */
111
+ text: string;
112
+ }
113
+ /**
114
+ * Headless state of one authorization detail field on the consent screen. A `number` or `date` field keeps
115
+ * the text the user typed, writes it to the decision only while it stays within the field's bound, and
116
+ * otherwise clears the field's modification and marks the field invalid, which blocks approval (see
117
+ * `isConsentApprovalBlocked`). A list field exposes its items and toggles them as its rule allows.
118
+ *
119
+ * @param props - The field and the consent form state.
120
+ * @returns The field's state and handlers.
121
+ *
122
+ * @example
123
+ * ```tsx
124
+ * const field = useConsentDetailField({purposeId, detailId, row, formValues, onInputChange});
125
+ * <input value={field.text} onChange={(e) => field.handleChange(e.target.value)} onBlur={field.handleBlur} />
126
+ * ```
127
+ */
128
+ declare const useConsentDetailField: ({ detailId, formValues, onInputChange, purposeId, row, t, }: UseConsentDetailFieldProps) => UseConsentDetailFieldResult;
129
+ export default useConsentDetailField;
130
+ //# sourceMappingURL=useConsentDetailField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useConsentDetailField.d.ts","sourceRoot":"","sources":["../../../src/hooks/auth/useConsentDetailField.ts"],"names":[],"mappings":"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"}