@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,26 @@
1
+
2
+ //#region src/utils/formatConsentDetailValue.ts
3
+ /**
4
+ * Formats an authorization detail field value for display. Strings are shown as-is, a list of
5
+ * plain values comma-separated, and any other JSON value as JSON, compact unless `indent` is given.
6
+ *
7
+ * @param value - Field value.
8
+ * @param indent - Spaces to indent structured JSON by, so it reads as a block rather than one long line.
9
+ * @returns Display text.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * formatConsentDetailValue(['initiate', 'status']) // returns 'initiate, status'
14
+ * ```
15
+ */
16
+ const formatConsentDetailValue = (value, indent) => {
17
+ if (value === null || value === void 0) return "";
18
+ if (typeof value === "string") return value;
19
+ if (Array.isArray(value) && value.every((item) => typeof item !== "object" || item === null)) return value.map((item) => String(item)).join(", ");
20
+ return JSON.stringify(value, null, indent);
21
+ };
22
+ var formatConsentDetailValue_default = formatConsentDetailValue;
23
+
24
+ //#endregion
25
+ exports.default = formatConsentDetailValue_default;
26
+ //# sourceMappingURL=formatConsentDetailValue.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatConsentDetailValue.cjs","names":[],"sources":["../../../src/utils/formatConsentDetailValue.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Formats an authorization detail field value for display. Strings are shown as-is, a list of\n * plain values comma-separated, and any other JSON value as JSON, compact unless `indent` is given.\n *\n * @param value - Field value.\n * @param indent - Spaces to indent structured JSON by, so it reads as a block rather than one long line.\n * @returns Display text.\n *\n * @example\n * ```typescript\n * formatConsentDetailValue(['initiate', 'status']) // returns 'initiate, status'\n * ```\n */\nconst formatConsentDetailValue = (value: unknown, indent?: number): string => {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string') return value;\n if (Array.isArray(value) && value.every((item: unknown) => typeof item !== 'object' || item === null)) {\n return value.map((item: unknown) => String(item)).join(', ');\n }\n return JSON.stringify(value, null, indent);\n};\n\nexport default formatConsentDetailValue;\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,MAAM,4BAA4B,OAAgB,WAA4B;AAC5E,KAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,KAAI,MAAM,QAAQ,MAAM,IAAI,MAAM,OAAO,SAAkB,OAAO,SAAS,YAAY,SAAS,KAAK,CACnG,QAAO,MAAM,KAAK,SAAkB,OAAO,KAAK,CAAC,CAAC,KAAK,KAAK;AAE9D,QAAO,KAAK,UAAU,OAAO,MAAM,OAAO;;AAG5C,uCAAe"}
@@ -0,0 +1,44 @@
1
+ const require_formatConsentDetailValue = require('./formatConsentDetailValue.cjs');
2
+ const require_isConsentDetailStructured = require('./isConsentDetailStructured.cjs');
3
+
4
+ //#region src/utils/getConsentDetailLayout.ts
5
+ /**
6
+ * Limits a consent screen applies to authorization detail content so that a long or large value never
7
+ * crowds the layout. Text longer than a `*Chars` limit is clamped to its `*Lines` limit behind a toggle,
8
+ * and a list longer than `listItems` shows that many items behind a toggle.
9
+ */
10
+ const CONSENT_DETAIL_DISPLAY_LIMITS = Object.freeze({
11
+ inlineLabelChars: 32,
12
+ inlineValueChars: 32,
13
+ listItems: 8,
14
+ structuredLines: 8,
15
+ summaryChars: 160,
16
+ summaryLines: 3,
17
+ valueChars: 160,
18
+ valueLines: 4
19
+ });
20
+ /**
21
+ * Chooses how a consent screen lays out one authorization detail field. A short label and a short value
22
+ * sit side by side; a long label, a long value, a long list or a structured value is stacked, the label
23
+ * above the value, so neither squeezes the other.
24
+ *
25
+ * @param row - Field to lay out.
26
+ * @returns `inline` or `stacked`.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * getConsentDetailLayout({label: 'Pay to', path: 'creditorName', value: 'Merchant A'}) // returns 'inline'
31
+ * ```
32
+ */
33
+ const getConsentDetailLayout = (row) => {
34
+ if ((row.label || row.path).length > CONSENT_DETAIL_DISPLAY_LIMITS.inlineLabelChars || require_isConsentDetailStructured.default(row.value)) return "stacked";
35
+ const items = Array.isArray(row.value) ? [...row.value] : [row.value];
36
+ if (row.modification === "addItems" && Array.isArray(row.options)) items.push(...row.options);
37
+ return require_formatConsentDetailValue.default(items).length > CONSENT_DETAIL_DISPLAY_LIMITS.inlineValueChars ? "stacked" : "inline";
38
+ };
39
+ var getConsentDetailLayout_default = getConsentDetailLayout;
40
+
41
+ //#endregion
42
+ exports.CONSENT_DETAIL_DISPLAY_LIMITS = CONSENT_DETAIL_DISPLAY_LIMITS;
43
+ exports.default = getConsentDetailLayout_default;
44
+ //# sourceMappingURL=getConsentDetailLayout.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getConsentDetailLayout.cjs","names":["CONSENT_DETAIL_DISPLAY_LIMITS: Readonly<{\n inlineLabelChars: number;\n inlineValueChars: number;\n listItems: number;\n structuredLines: number;\n summaryChars: number;\n summaryLines: number;\n valueChars: number;\n valueLines: number;\n}>","isConsentDetailStructured","items: unknown[]","formatConsentDetailValue"],"sources":["../../../src/utils/getConsentDetailLayout.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {type ConsentDetailRow} from '@thunderid/browser';\nimport formatConsentDetailValue from './formatConsentDetailValue';\nimport isConsentDetailStructured from './isConsentDetailStructured';\n\n/**\n * Limits a consent screen applies to authorization detail content so that a long or large value never\n * crowds the layout. Text longer than a `*Chars` limit is clamped to its `*Lines` limit behind a toggle,\n * and a list longer than `listItems` shows that many items behind a toggle.\n */\nexport const CONSENT_DETAIL_DISPLAY_LIMITS: Readonly<{\n inlineLabelChars: number;\n inlineValueChars: number;\n listItems: number;\n structuredLines: number;\n summaryChars: number;\n summaryLines: number;\n valueChars: number;\n valueLines: number;\n}> = Object.freeze({\n inlineLabelChars: 32,\n inlineValueChars: 32,\n listItems: 8,\n structuredLines: 8,\n summaryChars: 160,\n summaryLines: 3,\n valueChars: 160,\n valueLines: 4,\n});\n\n/**\n * Chooses how a consent screen lays out one authorization detail field. A short label and a short value\n * sit side by side; a long label, a long value, a long list or a structured value is stacked, the label\n * above the value, so neither squeezes the other.\n *\n * @param row - Field to lay out.\n * @returns `inline` or `stacked`.\n *\n * @example\n * ```typescript\n * getConsentDetailLayout({label: 'Pay to', path: 'creditorName', value: 'Merchant A'}) // returns 'inline'\n * ```\n */\nconst getConsentDetailLayout = (row: ConsentDetailRow): 'inline' | 'stacked' => {\n const label: string = row.label || row.path;\n if (label.length > CONSENT_DETAIL_DISPLAY_LIMITS.inlineLabelChars || isConsentDetailStructured(row.value)) {\n return 'stacked';\n }\n\n const items: unknown[] = Array.isArray(row.value) ? [...(row.value as unknown[])] : [row.value];\n if (row.modification === 'addItems' && Array.isArray(row.options)) {\n items.push(...row.options);\n }\n const text: string = formatConsentDetailValue(items);\n\n return text.length > CONSENT_DETAIL_DISPLAY_LIMITS.inlineValueChars ? 'stacked' : 'inline';\n};\n\nexport default getConsentDetailLayout;\n"],"mappings":";;;;;;;;;AAYA,MAAaA,gCASR,OAAO,OAAO;CACjB,kBAAkB;CAClB,kBAAkB;CAClB,WAAW;CACX,iBAAiB;CACjB,cAAc;CACd,cAAc;CACd,YAAY;CACZ,YAAY;CACb,CAAC;;;;;;;;;;;;;;AAeF,MAAM,0BAA0B,QAAgD;AAE9E,MADsB,IAAI,SAAS,IAAI,MAC7B,SAAS,8BAA8B,oBAAoBC,0CAA0B,IAAI,MAAM,CACvG,QAAO;CAGT,MAAMC,QAAmB,MAAM,QAAQ,IAAI,MAAM,GAAG,CAAC,GAAI,IAAI,MAAoB,GAAG,CAAC,IAAI,MAAM;AAC/F,KAAI,IAAI,iBAAiB,cAAc,MAAM,QAAQ,IAAI,QAAQ,CAC/D,OAAM,KAAK,GAAG,IAAI,QAAQ;AAI5B,QAFqBC,yCAAyB,MAAM,CAExC,SAAS,8BAA8B,mBAAmB,YAAY;;AAGpF,qCAAe"}
@@ -0,0 +1,30 @@
1
+ const require_getConsentDetailLayout = require('./getConsentDetailLayout.cjs');
2
+
3
+ //#region src/utils/getConsentDetailListDisplay.ts
4
+ /**
5
+ * Tells how many items of an authorization detail list a consent screen shows. A list longer than
6
+ * `CONSENT_DETAIL_DISPLAY_LIMITS.listItems` shows that many items while collapsed, the rest behind a toggle.
7
+ *
8
+ * @param itemCount - Number of items in the list.
9
+ * @param expanded - Whether the user expanded the list.
10
+ * @returns The items to show and hide.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * getConsentDetailListDisplay(10, false) // returns {hiddenCount: 2, isCollapsible: true, visibleCount: 8}
15
+ * ```
16
+ */
17
+ const getConsentDetailListDisplay = (itemCount, expanded) => {
18
+ const isCollapsible = itemCount > require_getConsentDetailLayout.CONSENT_DETAIL_DISPLAY_LIMITS.listItems;
19
+ const visibleCount = isCollapsible && !expanded ? require_getConsentDetailLayout.CONSENT_DETAIL_DISPLAY_LIMITS.listItems : itemCount;
20
+ return {
21
+ hiddenCount: itemCount - visibleCount,
22
+ isCollapsible,
23
+ visibleCount
24
+ };
25
+ };
26
+ var getConsentDetailListDisplay_default = getConsentDetailListDisplay;
27
+
28
+ //#endregion
29
+ exports.default = getConsentDetailListDisplay_default;
30
+ //# sourceMappingURL=getConsentDetailListDisplay.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getConsentDetailListDisplay.cjs","names":["isCollapsible: boolean","CONSENT_DETAIL_DISPLAY_LIMITS","visibleCount: number"],"sources":["../../../src/utils/getConsentDetailListDisplay.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {CONSENT_DETAIL_DISPLAY_LIMITS} from './getConsentDetailLayout';\n\n/**\n * How a consent screen shows a list of authorization detail items, given the\n * `CONSENT_DETAIL_DISPLAY_LIMITS.listItems` limit.\n *\n * @experimental This interface may change in future versions\n */\nexport interface ConsentDetailListDisplay {\n /** Number of items hidden behind the toggle; `0` while expanded or when the list fits. */\n hiddenCount: number;\n /** Whether the list is longer than the limit, so it is shown behind a toggle. */\n isCollapsible: boolean;\n /** Number of items to show. */\n visibleCount: number;\n}\n\n/**\n * Tells how many items of an authorization detail list a consent screen shows. A list longer than\n * `CONSENT_DETAIL_DISPLAY_LIMITS.listItems` shows that many items while collapsed, the rest behind a toggle.\n *\n * @param itemCount - Number of items in the list.\n * @param expanded - Whether the user expanded the list.\n * @returns The items to show and hide.\n *\n * @example\n * ```typescript\n * getConsentDetailListDisplay(10, false) // returns {hiddenCount: 2, isCollapsible: true, visibleCount: 8}\n * ```\n */\nconst getConsentDetailListDisplay = (itemCount: number, expanded: boolean): ConsentDetailListDisplay => {\n const isCollapsible: boolean = itemCount > CONSENT_DETAIL_DISPLAY_LIMITS.listItems;\n const visibleCount: number = isCollapsible && !expanded ? CONSENT_DETAIL_DISPLAY_LIMITS.listItems : itemCount;\n\n return {hiddenCount: itemCount - visibleCount, isCollapsible, visibleCount};\n};\n\nexport default getConsentDetailListDisplay;\n"],"mappings":";;;;;;;;;;;;;;;;AAiCA,MAAM,+BAA+B,WAAmB,aAAgD;CACtG,MAAMA,gBAAyB,YAAYC,6DAA8B;CACzE,MAAMC,eAAuB,iBAAiB,CAAC,WAAWD,6DAA8B,YAAY;AAEpG,QAAO;EAAC,aAAa,YAAY;EAAc;EAAe;EAAa;;AAG7E,0CAAe"}
@@ -0,0 +1,41 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ const require_ConsentCheckboxList = require('../components/auth/flow/ConsentCheckboxList.cjs');
3
+ let __thunderid_browser = require("@thunderid/browser");
4
+ __thunderid_browser = require_rolldown_runtime.__toESM(__thunderid_browser);
5
+
6
+ //#region src/utils/isConsentApprovalBlocked.ts
7
+ /**
8
+ * Reports whether any field the user may modify on an authorization detail element shows text that cannot
9
+ * be submitted. The element must not be approved while this holds, since its decision would not carry what
10
+ * the user sees.
11
+ *
12
+ * @param purposeId - The identifier of the consent purpose the element belongs to.
13
+ * @param element - The authorization detail element.
14
+ * @param inputs - Form values, holding the invalid marker of each field under its invalid key.
15
+ * @returns Whether a field of the element is invalid.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * hasInvalidConsentModification('p1', element, {'__consent_invalid__p1__d-1__amount': 'true'}) // returns true
20
+ * ```
21
+ */
22
+ const hasInvalidConsentModification = (purposeId, element, inputs) => (element.rows ?? []).some((row) => Boolean(row.modification) && inputs[(0, __thunderid_browser.getConsentInvalidKey)(purposeId, element.name, row.path)] === "true");
23
+ /**
24
+ * Reports whether the consent cannot be approved yet: an authorization detail the user has not declined
25
+ * shows, in a field the user may modify, text that cannot be submitted. Denying stays possible.
26
+ *
27
+ * @param purposes - The consent purposes on the screen.
28
+ * @param formValues - Form values, holding each element's approval and each field's invalid marker.
29
+ * @returns Whether approval must wait until the user corrects the field.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * isConsentApprovalBlocked(purposes, {'__consent_invalid__p1__d-1__amount': 'true'}) // returns true
34
+ * ```
35
+ */
36
+ const isConsentApprovalBlocked = (purposes, formValues) => purposes.some((purpose) => (purpose.optional ?? []).some((element) => formValues[require_ConsentCheckboxList.getConsentOptionalKey(purpose.purposeId, element.name)] !== "false" && hasInvalidConsentModification(purpose.purposeId, element, formValues)));
37
+ var isConsentApprovalBlocked_default = isConsentApprovalBlocked;
38
+
39
+ //#endregion
40
+ exports.default = isConsentApprovalBlocked_default;
41
+ //# sourceMappingURL=isConsentApprovalBlocked.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isConsentApprovalBlocked.cjs","names":["getConsentOptionalKey"],"sources":["../../../src/utils/isConsentApprovalBlocked.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n type ConsentDetailRow,\n type ConsentPurposeData,\n getConsentInvalidKey,\n type PromptElement,\n} from '@thunderid/browser';\nimport {getConsentOptionalKey} from '../components/auth/flow/ConsentCheckboxList';\n\n/**\n * Reports whether any field the user may modify on an authorization detail element shows text that cannot\n * be submitted. The element must not be approved while this holds, since its decision would not carry what\n * the user sees.\n *\n * @param purposeId - The identifier of the consent purpose the element belongs to.\n * @param element - The authorization detail element.\n * @param inputs - Form values, holding the invalid marker of each field under its invalid key.\n * @returns Whether a field of the element is invalid.\n *\n * @example\n * ```typescript\n * hasInvalidConsentModification('p1', element, {'__consent_invalid__p1__d-1__amount': 'true'}) // returns true\n * ```\n */\nconst hasInvalidConsentModification = (\n purposeId: string,\n element: PromptElement,\n inputs: Record<string, unknown>,\n): boolean =>\n (element.rows ?? []).some(\n (row: ConsentDetailRow) =>\n Boolean(row.modification) && inputs[getConsentInvalidKey(purposeId, element.name, row.path)] === 'true',\n );\n\n/**\n * Reports whether the consent cannot be approved yet: an authorization detail the user has not declined\n * shows, in a field the user may modify, text that cannot be submitted. Denying stays possible.\n *\n * @param purposes - The consent purposes on the screen.\n * @param formValues - Form values, holding each element's approval and each field's invalid marker.\n * @returns Whether approval must wait until the user corrects the field.\n *\n * @example\n * ```typescript\n * isConsentApprovalBlocked(purposes, {'__consent_invalid__p1__d-1__amount': 'true'}) // returns true\n * ```\n */\nconst isConsentApprovalBlocked = (purposes: ConsentPurposeData[], formValues: Record<string, unknown>): boolean =>\n purposes.some((purpose: ConsentPurposeData) =>\n (purpose.optional ?? []).some(\n (element: PromptElement) =>\n formValues[getConsentOptionalKey(purpose.purposeId, element.name)] !== 'false' &&\n hasInvalidConsentModification(purpose.purposeId, element, formValues),\n ),\n );\n\nexport default isConsentApprovalBlocked;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,iCACJ,WACA,SACA,YAEC,QAAQ,QAAQ,EAAE,EAAE,MAClB,QACC,QAAQ,IAAI,aAAa,IAAI,qDAA4B,WAAW,QAAQ,MAAM,IAAI,KAAK,MAAM,OACpG;;;;;;;;;;;;;;AAeH,MAAM,4BAA4B,UAAgC,eAChE,SAAS,MAAM,aACZ,QAAQ,YAAY,EAAE,EAAE,MACtB,YACC,WAAWA,kDAAsB,QAAQ,WAAW,QAAQ,KAAK,MAAM,WACvE,8BAA8B,QAAQ,WAAW,SAAS,WAAW,CACxE,CACF;AAEH,uCAAe"}
@@ -0,0 +1,24 @@
1
+
2
+ //#region src/utils/isConsentDetailPlainList.ts
3
+ /**
4
+ * Whether a field value is a list of plain values, strings, numbers or booleans, which a consent screen shows
5
+ * as a list rather than as structured JSON.
6
+ *
7
+ * @param value - Field value.
8
+ * @returns `true` when the value is a list of plain values.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * isConsentDetailPlainList(['initiate', 'status']) // returns true
13
+ * ```
14
+ */
15
+ const isConsentDetailPlainList = (value) => Array.isArray(value) && value.every((item) => [
16
+ "string",
17
+ "number",
18
+ "boolean"
19
+ ].includes(typeof item));
20
+ var isConsentDetailPlainList_default = isConsentDetailPlainList;
21
+
22
+ //#endregion
23
+ exports.default = isConsentDetailPlainList_default;
24
+ //# sourceMappingURL=isConsentDetailPlainList.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isConsentDetailPlainList.cjs","names":[],"sources":["../../../src/utils/isConsentDetailPlainList.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Whether a field value is a list of plain values, strings, numbers or booleans, which a consent screen shows\n * as a list rather than as structured JSON.\n *\n * @param value - Field value.\n * @returns `true` when the value is a list of plain values.\n *\n * @example\n * ```typescript\n * isConsentDetailPlainList(['initiate', 'status']) // returns true\n * ```\n */\nconst isConsentDetailPlainList = (value: unknown): value is (string | number | boolean)[] =>\n Array.isArray(value) && value.every((item: unknown) => ['string', 'number', 'boolean'].includes(typeof item));\n\nexport default isConsentDetailPlainList;\n"],"mappings":";;;;;;;;;;;;;;AAeA,MAAM,4BAA4B,UAChC,MAAM,QAAQ,MAAM,IAAI,MAAM,OAAO,SAAkB;CAAC;CAAU;CAAU;CAAU,CAAC,SAAS,OAAO,KAAK,CAAC;AAE/G,uCAAe"}
@@ -0,0 +1,15 @@
1
+
2
+ //#region src/utils/isConsentDetailStructured.ts
3
+ /**
4
+ * Whether a field value is structured JSON, an object or a list holding objects, rather than a plain
5
+ * value or a list of plain values.
6
+ *
7
+ * @param value - Field value.
8
+ * @returns `true` when the value is shown as a formatted JSON block.
9
+ */
10
+ const isConsentDetailStructured = (value) => typeof value === "object" && value !== null && !Array.isArray(value) || Array.isArray(value) && value.some((item) => typeof item === "object" && item !== null);
11
+ var isConsentDetailStructured_default = isConsentDetailStructured;
12
+
13
+ //#endregion
14
+ exports.default = isConsentDetailStructured_default;
15
+ //# sourceMappingURL=isConsentDetailStructured.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isConsentDetailStructured.cjs","names":[],"sources":["../../../src/utils/isConsentDetailStructured.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Whether a field value is structured JSON, an object or a list holding objects, rather than a plain\n * value or a list of plain values.\n *\n * @param value - Field value.\n * @returns `true` when the value is shown as a formatted JSON block.\n */\nconst isConsentDetailStructured = (value: unknown): boolean =>\n (typeof value === 'object' && value !== null && !Array.isArray(value)) ||\n (Array.isArray(value) && value.some((item: unknown) => typeof item === 'object' && item !== null));\n\nexport default isConsentDetailStructured;\n"],"mappings":";;;;;;;;;AAUA,MAAM,6BAA6B,UAChC,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM,IACpE,MAAM,QAAQ,MAAM,IAAI,MAAM,MAAM,SAAkB,OAAO,SAAS,YAAY,SAAS,KAAK;AAEnG,wCAAe"}
@@ -0,0 +1,25 @@
1
+
2
+ //#region src/utils/isConsentDetailTextClamped.ts
3
+ /**
4
+ * Whether authorization detail text is long enough to be clamped behind a toggle: longer than `maxChars`, or
5
+ * spanning more than `maxLines` lines.
6
+ *
7
+ * @param text - Text to show.
8
+ * @param maxChars - Number of characters above which the text is clamped, such as
9
+ * `CONSENT_DETAIL_DISPLAY_LIMITS.valueChars`.
10
+ * @param maxLines - Number of lines above which the text is clamped, such as
11
+ * `CONSENT_DETAIL_DISPLAY_LIMITS.valueLines`.
12
+ * @returns `true` when the text is clamped while collapsed.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * isConsentDetailTextClamped('Merchant A', CONSENT_DETAIL_DISPLAY_LIMITS.valueChars, CONSENT_DETAIL_DISPLAY_LIMITS.valueLines)
17
+ * // returns false
18
+ * ```
19
+ */
20
+ const isConsentDetailTextClamped = (text, maxChars, maxLines) => text.length > maxChars || text.split("\n").length > maxLines;
21
+ var isConsentDetailTextClamped_default = isConsentDetailTextClamped;
22
+
23
+ //#endregion
24
+ exports.default = isConsentDetailTextClamped_default;
25
+ //# sourceMappingURL=isConsentDetailTextClamped.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isConsentDetailTextClamped.cjs","names":[],"sources":["../../../src/utils/isConsentDetailTextClamped.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Whether authorization detail text is long enough to be clamped behind a toggle: longer than `maxChars`, or\n * spanning more than `maxLines` lines.\n *\n * @param text - Text to show.\n * @param maxChars - Number of characters above which the text is clamped, such as\n * `CONSENT_DETAIL_DISPLAY_LIMITS.valueChars`.\n * @param maxLines - Number of lines above which the text is clamped, such as\n * `CONSENT_DETAIL_DISPLAY_LIMITS.valueLines`.\n * @returns `true` when the text is clamped while collapsed.\n *\n * @example\n * ```typescript\n * isConsentDetailTextClamped('Merchant A', CONSENT_DETAIL_DISPLAY_LIMITS.valueChars, CONSENT_DETAIL_DISPLAY_LIMITS.valueLines)\n * // returns false\n * ```\n */\nconst isConsentDetailTextClamped = (text: string, maxChars: number, maxLines: number): boolean =>\n text.length > maxChars || text.split('\\n').length > maxLines;\n\nexport default isConsentDetailTextClamped;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoBA,MAAM,8BAA8B,MAAc,UAAkB,aAClE,KAAK,SAAS,YAAY,KAAK,MAAM,KAAK,CAAC,SAAS;AAEtD,yCAAe"}
@@ -5,9 +5,9 @@ import Button_default from "../../primitives/Button/Button.js";
5
5
  import Typography_default from "../../primitives/Typography/Typography.js";
6
6
  import Alert_default from "../../primitives/Alert/Alert.js";
7
7
  import Card_default from "../../primitives/Card/Card.js";
8
+ import TextField_default from "../../primitives/TextField/TextField.js";
8
9
  import Checkbox_default from "../../primitives/Checkbox/Checkbox.js";
9
10
  import DatePicker_default from "../../primitives/DatePicker/DatePicker.js";
10
- import TextField_default from "../../primitives/TextField/TextField.js";
11
11
  import Divider_default from "../../primitives/Divider/Divider.js";
12
12
  import BaseUserProfile_styles_default from "./BaseUserProfile.styles.js";
13
13
  import getMappedUserProfileValue_default from "../../../utils/getMappedUserProfileValue.js";
@@ -1,12 +1,19 @@
1
1
  import { FC } from 'react';
2
2
  import { BaseAgentDetailsProps } from './BaseAgentDetails';
3
- export type AgentDetailsProps = Omit<BaseAgentDetailsProps, 'agent' | 'error' | 'groups' | 'isDeleting' | 'isLoading' | 'onDelete' | 'roles'> & {
3
+ export type AgentDetailsProps = Omit<BaseAgentDetailsProps, 'agent' | 'error' | 'groups' | 'isDeleting' | 'isLoading' | 'isRunningLifecycleAction' | 'lifecycleActions' | 'onDelete' | 'onLifecycleAction' | 'roles'> & {
4
4
  agentId: string;
5
5
  /**
6
6
  * Whether the agent can be deleted from this view.
7
7
  * @default false
8
8
  */
9
9
  deletable?: boolean;
10
+ /**
11
+ * Whether the agent can be suspended, unsuspended and unlocked from this view. Each action runs through its
12
+ * administration flow and is offered only when the server configures that flow. Reading the configured
13
+ * flows needs a token that may read the server configuration.
14
+ * @default false
15
+ */
16
+ lifecycleActions?: boolean;
10
17
  /**
11
18
  * Called after the agent has been deleted.
12
19
  */
@@ -1 +1 @@
1
- {"version":3,"file":"AgentDetails.d.ts","sourceRoot":"","sources":["../../../../src/components/admin/AgentDetails/AgentDetails.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAC,EAAE,EAAe,MAAM,OAAO,CAAC;AACvC,OAAyB,EAAC,qBAAqB,EAAC,MAAM,oBAAoB,CAAC;AAM3E,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,qBAAqB,EACrB,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,YAAY,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,CACjF,GAAG;IACF,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB,CAAC;AAEF;;;;;;;;GAQG;AACH,QAAA,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CA8CvC,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"AgentDetails.d.ts","sourceRoot":"","sources":["../../../../src/components/admin/AgentDetails/AgentDetails.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAC,EAAE,EAAe,MAAM,OAAO,CAAC;AACvC,OAAyB,EAAC,qBAAqB,EAAC,MAAM,oBAAoB,CAAC;AAO3E,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,qBAAqB,EACnB,OAAO,GACP,OAAO,GACP,QAAQ,GACR,YAAY,GACZ,WAAW,GACX,0BAA0B,GAC1B,kBAAkB,GAClB,UAAU,GACV,mBAAmB,GACnB,OAAO,CACV,GAAG;IACF,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB,CAAC;AAEF;;;;;;;;GAQG;AACH,QAAA,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CA4DvC,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -2,6 +2,7 @@ import useTranslation_default from "../../../hooks/useTranslation.js";
2
2
  import useManagementEndpoint_default from "../../../hooks/management/useManagementEndpoint.js";
3
3
  import useResourceQuery_default from "../../../hooks/management/useResourceQuery.js";
4
4
  import useResourceMutation_default from "../../../hooks/management/useResourceMutation.js";
5
+ import useAccountLifecycle_default from "../../../hooks/management/useAccountLifecycle.js";
5
6
  import BaseAgentDetails_default from "./BaseAgentDetails.js";
6
7
  import { AgentQueryKeys, GroupQueryKeys, RoleQueryKeys, deleteAgent, getAgent, getAgentGroups, getAgentRoles, toManagementErrorMessage } from "@thunderid/browser";
7
8
  import { jsx } from "react/jsx-runtime";
@@ -16,7 +17,7 @@ import { jsx } from "react/jsx-runtime";
16
17
  * <AgentDetails agentId={agentId} deletable onDeleted={() => navigate('/agents')} />
17
18
  * ```
18
19
  */
19
- const AgentDetails = ({ agentId, deletable = false, onDeleted, preferences,...rest }) => {
20
+ const AgentDetails = ({ agentId, deletable = false, lifecycleActions = false, onDeleted, preferences,...rest }) => {
20
21
  const { t } = useTranslation_default(preferences?.i18n);
21
22
  const endpoint = useManagementEndpoint_default("agents");
22
23
  const agent = useResourceQuery_default([AgentQueryKeys.AGENT, agentId], (fetcher) => getAgent({
@@ -51,14 +52,24 @@ const AgentDetails = ({ agentId, deletable = false, onDeleted, preferences,...re
51
52
  agentId: id,
52
53
  fetcher
53
54
  }), () => [[AgentQueryKeys.AGENTS]], { onSuccess: onDeleted });
55
+ const lifecycle = useAccountLifecycle_default({
56
+ enabled: lifecycleActions,
57
+ invalidatedKeys: [[AgentQueryKeys.AGENT, agentId], [AgentQueryKeys.AGENTS]],
58
+ kind: "agent",
59
+ status: agent.data?.status?.value,
60
+ subject: agentId
61
+ });
54
62
  return /* @__PURE__ */ jsx(BaseAgentDetails_default, {
55
63
  agent: agent.data,
56
64
  groups: groups.data?.groups,
57
65
  roles: roles.data?.roles,
58
66
  isLoading: agent.isLoading,
59
- error: toManagementErrorMessage(t, agent.error, "admin.agents.details.error") ?? toManagementErrorMessage(t, deletion.error, "admin.agents.details.delete.error"),
67
+ error: toManagementErrorMessage(t, agent.error, "admin.agents.details.error") ?? toManagementErrorMessage(t, deletion.error, "admin.agents.details.delete.error") ?? toManagementErrorMessage(t, lifecycle.error, "admin.common.lifecycle.error") ?? toManagementErrorMessage(t, lifecycle.loadError, "admin.common.lifecycle.load_error"),
60
68
  isDeleting: deletion.isLoading,
61
69
  onDelete: deletable ? () => void deletion.mutate(agentId) : void 0,
70
+ lifecycleActions: lifecycle.actions,
71
+ isRunningLifecycleAction: lifecycle.isRunning,
72
+ onLifecycleAction: lifecycleActions ? lifecycle.run : void 0,
62
73
  preferences,
63
74
  ...rest
64
75
  });
@@ -1 +1 @@
1
- {"version":3,"file":"AgentDetails.js","names":["AgentDetails: FC<AgentDetailsProps>","useTranslation","endpoint: ManagementEndpoint","useManagementEndpoint","agent: ResourceQueryResult<Agent>","useResourceQuery","groups: ResourceQueryResult<MembershipGroupListResponse>","roles: ResourceQueryResult<AgentRoleListResponse>","deletion: ResourceMutationResult<void, string>","useResourceMutation","BaseAgentDetails"],"sources":["../../../../src/components/admin/AgentDetails/AgentDetails.tsx"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n Agent,\n AgentQueryKeys,\n AgentRoleListResponse,\n GroupQueryKeys,\n MembershipGroupListResponse,\n RoleQueryKeys,\n deleteAgent,\n getAgent,\n getAgentGroups,\n getAgentRoles,\n toManagementErrorMessage,\n} from '@thunderid/browser';\nimport {FC, ReactElement} from 'react';\nimport BaseAgentDetails, {BaseAgentDetailsProps} from './BaseAgentDetails';\nimport useManagementEndpoint, {ManagementEndpoint} from '../../../hooks/management/useManagementEndpoint';\nimport useResourceMutation, {ResourceMutationResult} from '../../../hooks/management/useResourceMutation';\nimport useResourceQuery, {ResourceQueryResult} from '../../../hooks/management/useResourceQuery';\nimport useTranslation from '../../../hooks/useTranslation';\n\nexport type AgentDetailsProps = Omit<\n BaseAgentDetailsProps,\n 'agent' | 'error' | 'groups' | 'isDeleting' | 'isLoading' | 'onDelete' | 'roles'\n> & {\n agentId: string;\n /**\n * Whether the agent can be deleted from this view.\n * @default false\n */\n deletable?: boolean;\n /**\n * Called after the agent has been deleted.\n */\n onDeleted?: () => void;\n};\n\n/**\n * Shows an agent with the groups and roles it holds, and optionally lets the signed-in user delete\n * it.\n *\n * @example\n * ```tsx\n * <AgentDetails agentId={agentId} deletable onDeleted={() => navigate('/agents')} />\n * ```\n */\nconst AgentDetails: FC<AgentDetailsProps> = ({\n agentId,\n deletable = false,\n onDeleted,\n preferences,\n ...rest\n}: AgentDetailsProps): ReactElement => {\n const {t} = useTranslation(preferences?.i18n);\n const endpoint: ManagementEndpoint = useManagementEndpoint('agents');\n const agent: ResourceQueryResult<Agent> = useResourceQuery(\n [AgentQueryKeys.AGENT, agentId],\n (fetcher) => getAgent({...endpoint, agentId, fetcher}),\n {enabled: Boolean(agentId)},\n );\n const groups: ResourceQueryResult<MembershipGroupListResponse> = useResourceQuery(\n [GroupQueryKeys.MEMBERSHIPS, 'agent', agentId, {limit: 100}],\n (fetcher) => getAgentGroups({...endpoint, agentId, fetcher, limit: 100}),\n {enabled: Boolean(agentId)},\n );\n const roles: ResourceQueryResult<AgentRoleListResponse> = useResourceQuery(\n [RoleQueryKeys.ROLE_ASSIGNMENTS, 'agent', agentId, {limit: 100}],\n (fetcher) => getAgentRoles({...endpoint, agentId, fetcher, limit: 100}),\n {enabled: Boolean(agentId)},\n );\n const deletion: ResourceMutationResult<void, string> = useResourceMutation(\n (id: string, fetcher) => deleteAgent({...endpoint, agentId: id, fetcher}),\n () => [[AgentQueryKeys.AGENTS]],\n {onSuccess: onDeleted},\n );\n\n return (\n <BaseAgentDetails\n agent={agent.data}\n groups={groups.data?.groups}\n roles={roles.data?.roles}\n isLoading={agent.isLoading}\n error={\n toManagementErrorMessage(t, agent.error, 'admin.agents.details.error') ??\n toManagementErrorMessage(t, deletion.error, 'admin.agents.details.delete.error')\n }\n isDeleting={deletion.isLoading}\n onDelete={deletable ? (): void => void deletion.mutate(agentId) : undefined}\n preferences={preferences}\n {...rest}\n />\n );\n};\n\nexport default AgentDetails;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAgDA,MAAMA,gBAAuC,EAC3C,SACA,YAAY,OACZ,WACA,YACA,GAAG,WACkC;CACrC,MAAM,EAAC,MAAKC,uBAAe,aAAa,KAAK;CAC7C,MAAMC,WAA+BC,8BAAsB,SAAS;CACpE,MAAMC,QAAoCC,yBACxC,CAAC,eAAe,OAAO,QAAQ,GAC9B,YAAY,SAAS;EAAC,GAAG;EAAU;EAAS;EAAQ,CAAC,EACtD,EAAC,SAAS,QAAQ,QAAQ,EAAC,CAC5B;CACD,MAAMC,SAA2DD,yBAC/D;EAAC,eAAe;EAAa;EAAS;EAAS,EAAC,OAAO,KAAI;EAAC,GAC3D,YAAY,eAAe;EAAC,GAAG;EAAU;EAAS;EAAS,OAAO;EAAI,CAAC,EACxE,EAAC,SAAS,QAAQ,QAAQ,EAAC,CAC5B;CACD,MAAME,QAAoDF,yBACxD;EAAC,cAAc;EAAkB;EAAS;EAAS,EAAC,OAAO,KAAI;EAAC,GAC/D,YAAY,cAAc;EAAC,GAAG;EAAU;EAAS;EAAS,OAAO;EAAI,CAAC,EACvE,EAAC,SAAS,QAAQ,QAAQ,EAAC,CAC5B;CACD,MAAMG,WAAiDC,6BACpD,IAAY,YAAY,YAAY;EAAC,GAAG;EAAU,SAAS;EAAI;EAAQ,CAAC,QACnE,CAAC,CAAC,eAAe,OAAO,CAAC,EAC/B,EAAC,WAAW,WAAU,CACvB;AAED,QACE,oBAACC;EACC,OAAO,MAAM;EACb,QAAQ,OAAO,MAAM;EACrB,OAAO,MAAM,MAAM;EACnB,WAAW,MAAM;EACjB,OACE,yBAAyB,GAAG,MAAM,OAAO,6BAA6B,IACtE,yBAAyB,GAAG,SAAS,OAAO,oCAAoC;EAElF,YAAY,SAAS;EACrB,UAAU,kBAAwB,KAAK,SAAS,OAAO,QAAQ,GAAG;EACrD;EACb,GAAI;GACJ;;AAIN,2BAAe"}
1
+ {"version":3,"file":"AgentDetails.js","names":["AgentDetails: FC<AgentDetailsProps>","useTranslation","endpoint: ManagementEndpoint","useManagementEndpoint","agent: ResourceQueryResult<Agent>","useResourceQuery","groups: ResourceQueryResult<MembershipGroupListResponse>","roles: ResourceQueryResult<AgentRoleListResponse>","deletion: ResourceMutationResult<void, string>","useResourceMutation","lifecycle: AccountLifecycleState","useAccountLifecycle","BaseAgentDetails"],"sources":["../../../../src/components/admin/AgentDetails/AgentDetails.tsx"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n Agent,\n AgentQueryKeys,\n AgentRoleListResponse,\n GroupQueryKeys,\n MembershipGroupListResponse,\n RoleQueryKeys,\n deleteAgent,\n getAgent,\n getAgentGroups,\n getAgentRoles,\n toManagementErrorMessage,\n} from '@thunderid/browser';\nimport {FC, ReactElement} from 'react';\nimport BaseAgentDetails, {BaseAgentDetailsProps} from './BaseAgentDetails';\nimport useAccountLifecycle, {AccountLifecycleState} from '../../../hooks/management/useAccountLifecycle';\nimport useManagementEndpoint, {ManagementEndpoint} from '../../../hooks/management/useManagementEndpoint';\nimport useResourceMutation, {ResourceMutationResult} from '../../../hooks/management/useResourceMutation';\nimport useResourceQuery, {ResourceQueryResult} from '../../../hooks/management/useResourceQuery';\nimport useTranslation from '../../../hooks/useTranslation';\n\nexport type AgentDetailsProps = Omit<\n BaseAgentDetailsProps,\n | 'agent'\n | 'error'\n | 'groups'\n | 'isDeleting'\n | 'isLoading'\n | 'isRunningLifecycleAction'\n | 'lifecycleActions'\n | 'onDelete'\n | 'onLifecycleAction'\n | 'roles'\n> & {\n agentId: string;\n /**\n * Whether the agent can be deleted from this view.\n * @default false\n */\n deletable?: boolean;\n /**\n * Whether the agent can be suspended, unsuspended and unlocked from this view. Each action runs through its\n * administration flow and is offered only when the server configures that flow. Reading the configured\n * flows needs a token that may read the server configuration.\n * @default false\n */\n lifecycleActions?: boolean;\n /**\n * Called after the agent has been deleted.\n */\n onDeleted?: () => void;\n};\n\n/**\n * Shows an agent with the groups and roles it holds, and optionally lets the signed-in user delete\n * it.\n *\n * @example\n * ```tsx\n * <AgentDetails agentId={agentId} deletable onDeleted={() => navigate('/agents')} />\n * ```\n */\nconst AgentDetails: FC<AgentDetailsProps> = ({\n agentId,\n deletable = false,\n lifecycleActions = false,\n onDeleted,\n preferences,\n ...rest\n}: AgentDetailsProps): ReactElement => {\n const {t} = useTranslation(preferences?.i18n);\n const endpoint: ManagementEndpoint = useManagementEndpoint('agents');\n const agent: ResourceQueryResult<Agent> = useResourceQuery(\n [AgentQueryKeys.AGENT, agentId],\n (fetcher) => getAgent({...endpoint, agentId, fetcher}),\n {enabled: Boolean(agentId)},\n );\n const groups: ResourceQueryResult<MembershipGroupListResponse> = useResourceQuery(\n [GroupQueryKeys.MEMBERSHIPS, 'agent', agentId, {limit: 100}],\n (fetcher) => getAgentGroups({...endpoint, agentId, fetcher, limit: 100}),\n {enabled: Boolean(agentId)},\n );\n const roles: ResourceQueryResult<AgentRoleListResponse> = useResourceQuery(\n [RoleQueryKeys.ROLE_ASSIGNMENTS, 'agent', agentId, {limit: 100}],\n (fetcher) => getAgentRoles({...endpoint, agentId, fetcher, limit: 100}),\n {enabled: Boolean(agentId)},\n );\n const deletion: ResourceMutationResult<void, string> = useResourceMutation(\n (id: string, fetcher) => deleteAgent({...endpoint, agentId: id, fetcher}),\n () => [[AgentQueryKeys.AGENTS]],\n {onSuccess: onDeleted},\n );\n\n const lifecycle: AccountLifecycleState = useAccountLifecycle({\n enabled: lifecycleActions,\n invalidatedKeys: [[AgentQueryKeys.AGENT, agentId], [AgentQueryKeys.AGENTS]],\n kind: 'agent',\n status: agent.data?.status?.value,\n subject: agentId,\n });\n\n return (\n <BaseAgentDetails\n agent={agent.data}\n groups={groups.data?.groups}\n roles={roles.data?.roles}\n isLoading={agent.isLoading}\n error={\n toManagementErrorMessage(t, agent.error, 'admin.agents.details.error') ??\n toManagementErrorMessage(t, deletion.error, 'admin.agents.details.delete.error') ??\n toManagementErrorMessage(t, lifecycle.error, 'admin.common.lifecycle.error') ??\n toManagementErrorMessage(t, lifecycle.loadError, 'admin.common.lifecycle.load_error')\n }\n isDeleting={deletion.isLoading}\n onDelete={deletable ? (): void => void deletion.mutate(agentId) : undefined}\n lifecycleActions={lifecycle.actions}\n isRunningLifecycleAction={lifecycle.isRunning}\n onLifecycleAction={lifecycleActions ? lifecycle.run : undefined}\n preferences={preferences}\n {...rest}\n />\n );\n};\n\nexport default AgentDetails;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAiEA,MAAMA,gBAAuC,EAC3C,SACA,YAAY,OACZ,mBAAmB,OACnB,WACA,YACA,GAAG,WACkC;CACrC,MAAM,EAAC,MAAKC,uBAAe,aAAa,KAAK;CAC7C,MAAMC,WAA+BC,8BAAsB,SAAS;CACpE,MAAMC,QAAoCC,yBACxC,CAAC,eAAe,OAAO,QAAQ,GAC9B,YAAY,SAAS;EAAC,GAAG;EAAU;EAAS;EAAQ,CAAC,EACtD,EAAC,SAAS,QAAQ,QAAQ,EAAC,CAC5B;CACD,MAAMC,SAA2DD,yBAC/D;EAAC,eAAe;EAAa;EAAS;EAAS,EAAC,OAAO,KAAI;EAAC,GAC3D,YAAY,eAAe;EAAC,GAAG;EAAU;EAAS;EAAS,OAAO;EAAI,CAAC,EACxE,EAAC,SAAS,QAAQ,QAAQ,EAAC,CAC5B;CACD,MAAME,QAAoDF,yBACxD;EAAC,cAAc;EAAkB;EAAS;EAAS,EAAC,OAAO,KAAI;EAAC,GAC/D,YAAY,cAAc;EAAC,GAAG;EAAU;EAAS;EAAS,OAAO;EAAI,CAAC,EACvE,EAAC,SAAS,QAAQ,QAAQ,EAAC,CAC5B;CACD,MAAMG,WAAiDC,6BACpD,IAAY,YAAY,YAAY;EAAC,GAAG;EAAU,SAAS;EAAI;EAAQ,CAAC,QACnE,CAAC,CAAC,eAAe,OAAO,CAAC,EAC/B,EAAC,WAAW,WAAU,CACvB;CAED,MAAMC,YAAmCC,4BAAoB;EAC3D,SAAS;EACT,iBAAiB,CAAC,CAAC,eAAe,OAAO,QAAQ,EAAE,CAAC,eAAe,OAAO,CAAC;EAC3E,MAAM;EACN,QAAQ,MAAM,MAAM,QAAQ;EAC5B,SAAS;EACV,CAAC;AAEF,QACE,oBAACC;EACC,OAAO,MAAM;EACb,QAAQ,OAAO,MAAM;EACrB,OAAO,MAAM,MAAM;EACnB,WAAW,MAAM;EACjB,OACE,yBAAyB,GAAG,MAAM,OAAO,6BAA6B,IACtE,yBAAyB,GAAG,SAAS,OAAO,oCAAoC,IAChF,yBAAyB,GAAG,UAAU,OAAO,+BAA+B,IAC5E,yBAAyB,GAAG,UAAU,WAAW,oCAAoC;EAEvF,YAAY,SAAS;EACrB,UAAU,kBAAwB,KAAK,SAAS,OAAO,QAAQ,GAAG;EAClE,kBAAkB,UAAU;EAC5B,0BAA0B,UAAU;EACpC,mBAAmB,mBAAmB,UAAU,MAAM;EACzC;EACb,GAAI;GACJ;;AAIN,2BAAe"}
@@ -1,4 +1,4 @@
1
- import { Agent, MembershipGroup, Preferences } from '@thunderid/browser';
1
+ import { AccountLifecycleAction, Agent, MembershipGroup, Preferences } from '@thunderid/browser';
2
2
  import { FC, ReactNode } from 'react';
3
3
  /**
4
4
  * What {@link BaseAgentDetails} hands its `children` render function, so the agent can be shown with any UI.
@@ -9,10 +9,19 @@ export interface BaseAgentDetailsRenderProps {
9
9
  groups: MembershipGroup[];
10
10
  isDeleting: boolean;
11
11
  isLoading: boolean;
12
+ isRunningLifecycleAction: boolean;
13
+ /**
14
+ * The account lifecycle actions offered for the agent. Empty when none is allowed.
15
+ */
16
+ lifecycleActions: AccountLifecycleAction[];
12
17
  /**
13
18
  * Deletes the agent. Undefined when deletion is not allowed, including for read-only agents.
14
19
  */
15
20
  onDelete?: () => void;
21
+ /**
22
+ * Runs an account lifecycle action, with the operator's note on a suspension. Undefined when none is allowed.
23
+ */
24
+ onLifecycleAction?: (action: AccountLifecycleAction, operatorNote?: string) => void;
16
25
  roles: string[];
17
26
  }
18
27
  export interface BaseAgentDetailsProps {
@@ -34,10 +43,21 @@ export interface BaseAgentDetailsProps {
34
43
  groups?: MembershipGroup[];
35
44
  isDeleting?: boolean;
36
45
  isLoading?: boolean;
46
+ isRunningLifecycleAction?: boolean;
47
+ /**
48
+ * The account lifecycle actions to offer (suspend, unsuspend, unlock), shown only with `onLifecycleAction`. They change
49
+ * only runtime state, so they apply to read-only agents too.
50
+ */
51
+ lifecycleActions?: AccountLifecycleAction[];
37
52
  /**
38
53
  * Deletes the agent. The delete action is hidden when omitted.
39
54
  */
40
55
  onDelete?: () => void;
56
+ /**
57
+ * Runs an account lifecycle action. Suspending and unsuspending ask for confirmation first, and a
58
+ * suspension takes an optional operator note.
59
+ */
60
+ onLifecycleAction?: (action: AccountLifecycleAction, operatorNote?: string) => void;
41
61
  preferences?: Preferences;
42
62
  /**
43
63
  * The names of the roles the agent holds, directly or through its groups.
@@ -1 +1 @@
1
- {"version":3,"file":"BaseAgentDetails.d.ts","sourceRoot":"","sources":["../../../../src/components/admin/AgentDetails/BaseAgentDetails.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAC,KAAK,EAAE,eAAe,EAAE,WAAW,EAAC,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAC,EAAE,EAAgB,SAAS,EAAC,MAAM,OAAO,CAAC;AASlD;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,SAAS,CAAC;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;OAEG;IACH,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,QAAA,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CA4G/C,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"BaseAgentDetails.d.ts","sourceRoot":"","sources":["../../../../src/components/admin/AgentDetails/BaseAgentDetails.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAC,sBAAsB,EAAE,KAAK,EAAE,eAAe,EAAE,WAAW,EAAC,MAAM,oBAAoB,CAAC;AAC/F,OAAO,EAAC,EAAE,EAAgB,SAAS,EAAC,MAAM,OAAO,CAAC;AAUlD;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,wBAAwB,EAAE,OAAO,CAAC;IAClC;;OAEG;IACH,gBAAgB,EAAE,sBAAsB,EAAE,CAAC;IAC3C;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpF,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,SAAS,CAAC;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;OAEG;IACH,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,sBAAsB,EAAE,CAAC;IAC5C;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpF,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,QAAA,MAAM,gBAAgB,EAAE,EAAE,CAAC,qBAAqB,CA+H/C,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -4,6 +4,7 @@ import Alert_default from "../../primitives/Alert/Alert.js";
4
4
  import CopyableText_default from "../../primitives/CopyableText/CopyableText.js";
5
5
  import useAdminPartStyles_default from "../shared/useAdminPartStyles.js";
6
6
  import AdminSection_default from "../shared/AdminSection.js";
7
+ import { AccessStatusBadge, AccountLifecycleButtons } from "../shared/AccountLifecycleParts.js";
7
8
  import { ChipList, ConfirmButton, DetailList, Panel } from "../shared/AdminParts.js";
8
9
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
10
 
@@ -12,7 +13,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
13
  * Shows an agent's type, owner, client and the groups and roles it holds. Holds no data of its own:
13
14
  * pass the agent and handle deletion.
14
15
  */
15
- const BaseAgentDetails = ({ actions, agent, children, className, error = null, groups = [], isDeleting = false, isLoading = false, onDelete, preferences, roles = [] }) => {
16
+ const BaseAgentDetails = ({ actions, agent, children, className, error = null, groups = [], isDeleting = false, isLoading = false, isRunningLifecycleAction = false, lifecycleActions = [], onDelete, onLifecycleAction, preferences, roles = [] }) => {
16
17
  const { t } = useTranslation_default(preferences?.i18n);
17
18
  const styles = useAdminPartStyles_default();
18
19
  if (children) return /* @__PURE__ */ jsx("div", {
@@ -23,7 +24,10 @@ const BaseAgentDetails = ({ actions, agent, children, className, error = null, g
23
24
  groups,
24
25
  isDeleting,
25
26
  isLoading,
27
+ isRunningLifecycleAction,
28
+ lifecycleActions: onLifecycleAction && agent ? lifecycleActions : [],
26
29
  onDelete: agent && !agent.isReadOnly ? onDelete : void 0,
30
+ onLifecycleAction: agent ? onLifecycleAction : void 0,
27
31
  roles
28
32
  })
29
33
  });
@@ -65,6 +69,10 @@ const BaseAgentDetails = ({ actions, agent, children, className, error = null, g
65
69
  value: agent.ouHandle ?? agent.ouId
66
70
  }
67
71
  ];
72
+ if (agent.status) details.push({
73
+ label: t("admin.common.columns.status"),
74
+ value: /* @__PURE__ */ jsx(AccessStatusBadge, { status: agent.status.value })
75
+ });
68
76
  if (agent.clientId) details.push({
69
77
  label: t("admin.agents.list.columns.client_id"),
70
78
  value: /* @__PURE__ */ jsx(CopyableText_default, { value: agent.clientId })
@@ -75,12 +83,22 @@ const BaseAgentDetails = ({ actions, agent, children, className, error = null, g
75
83
  title: agent.name,
76
84
  description: agent.description,
77
85
  preferences,
78
- actions: /* @__PURE__ */ jsxs(Fragment, { children: [actions, onDelete && !agent.isReadOnly && /* @__PURE__ */ jsx(ConfirmButton, {
79
- confirmText: t("admin.agents.details.delete.confirm", { name: agent.name }),
80
- isLoading: isDeleting,
81
- onConfirm: onDelete,
82
- children: t("admin.agents.details.delete.action")
83
- })] }),
86
+ actions: /* @__PURE__ */ jsxs(Fragment, { children: [
87
+ actions,
88
+ onLifecycleAction && /* @__PURE__ */ jsx(AccountLifecycleButtons, {
89
+ actions: lifecycleActions,
90
+ collectsOperatorNote: true,
91
+ isRunning: isRunningLifecycleAction,
92
+ name: agent.name,
93
+ onAction: onLifecycleAction
94
+ }),
95
+ onDelete && !agent.isReadOnly && /* @__PURE__ */ jsx(ConfirmButton, {
96
+ confirmText: t("admin.agents.details.delete.confirm", { name: agent.name }),
97
+ isLoading: isDeleting,
98
+ onConfirm: onDelete,
99
+ children: t("admin.agents.details.delete.action")
100
+ })
101
+ ] }),
84
102
  children: [
85
103
  error && /* @__PURE__ */ jsx(Alert_default, {
86
104
  variant: "error",
@@ -1 +1 @@
1
- {"version":3,"file":"BaseAgentDetails.js","names":["BaseAgentDetails: FC<BaseAgentDetailsProps>","useTranslation","styles: Record<string, string>","useAdminPartStyles","AdminSection","Spinner","Alert","details: {label: string; value: ReactNode}[]","CopyableText"],"sources":["../../../../src/components/admin/AgentDetails/BaseAgentDetails.tsx"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {Agent, MembershipGroup, Preferences} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode} from 'react';\nimport useTranslation from '../../../hooks/useTranslation';\nimport Alert from '../../primitives/Alert/Alert';\nimport CopyableText from '../../primitives/CopyableText/CopyableText';\nimport Spinner from '../../primitives/Spinner/Spinner';\nimport {ChipList, ConfirmButton, DetailList, Panel} from '../shared/AdminParts';\nimport AdminSection from '../shared/AdminSection';\nimport useAdminPartStyles from '../shared/useAdminPartStyles';\n\n/**\n * What {@link BaseAgentDetails} hands its `children` render function, so the agent can be shown with any UI.\n */\nexport interface BaseAgentDetailsRenderProps {\n agent?: Agent;\n error: string | null;\n groups: MembershipGroup[];\n isDeleting: boolean;\n isLoading: boolean;\n /**\n * Deletes the agent. Undefined when deletion is not allowed, including for read-only agents.\n */\n onDelete?: () => void;\n roles: string[];\n}\n\nexport interface BaseAgentDetailsProps {\n /**\n * Controls rendered next to the agent's name.\n */\n actions?: ReactNode;\n agent?: Agent;\n /**\n * Renders custom UI in place of the default view. Receives the agent, its groups and roles, the\n * loading and error state, and the delete handler.\n */\n children?: (props: BaseAgentDetailsRenderProps) => ReactNode;\n className?: string;\n error?: string | null;\n /**\n * The groups the agent belongs to.\n */\n groups?: MembershipGroup[];\n isDeleting?: boolean;\n isLoading?: boolean;\n /**\n * Deletes the agent. The delete action is hidden when omitted.\n */\n onDelete?: () => void;\n preferences?: Preferences;\n /**\n * The names of the roles the agent holds, directly or through its groups.\n */\n roles?: string[];\n}\n\n/**\n * Shows an agent's type, owner, client and the groups and roles it holds. Holds no data of its own:\n * pass the agent and handle deletion.\n */\nconst BaseAgentDetails: FC<BaseAgentDetailsProps> = ({\n actions,\n agent,\n children,\n className,\n error = null,\n groups = [],\n isDeleting = false,\n isLoading = false,\n onDelete,\n preferences,\n roles = [],\n}: BaseAgentDetailsProps): ReactElement => {\n const {t} = useTranslation(preferences?.i18n);\n const styles: Record<string, string> = useAdminPartStyles();\n\n if (children) {\n return (\n <div className={className}>\n {children({\n agent,\n error,\n groups,\n isDeleting,\n isLoading,\n onDelete: agent && !agent.isReadOnly ? onDelete : undefined,\n roles,\n })}\n </div>\n );\n }\n\n if (isLoading && !agent) {\n return (\n <AdminSection block=\"agent-details\" className={className} preferences={preferences}>\n <span className={styles['muted']} role=\"status\">\n <Spinner size=\"small\" /> {t('admin.common.loading')}\n </span>\n </AdminSection>\n );\n }\n\n if (!agent) {\n return (\n <AdminSection block=\"agent-details\" className={className} preferences={preferences}>\n <Alert variant=\"error\" role=\"alert\">\n {error ?? t('admin.common.errors.not_found')}\n </Alert>\n </AdminSection>\n );\n }\n\n const details: {label: string; value: ReactNode}[] = [\n {label: t('admin.agents.details.type'), value: agent.type},\n {label: t('admin.agents.details.owner'), value: agent.owner ?? t('admin.agents.details.no_owner')},\n {label: t('admin.common.columns.organization_unit'), value: agent.ouHandle ?? agent.ouId},\n ];\n\n if (agent.clientId) {\n details.push({label: t('admin.agents.list.columns.client_id'), value: <CopyableText value={agent.clientId} />});\n }\n\n return (\n <AdminSection\n block=\"agent-details\"\n className={className}\n title={agent.name}\n description={agent.description}\n preferences={preferences}\n actions={\n <>\n {actions}\n {onDelete && !agent.isReadOnly && (\n <ConfirmButton\n confirmText={t('admin.agents.details.delete.confirm', {name: agent.name})}\n isLoading={isDeleting}\n onConfirm={onDelete}\n >\n {t('admin.agents.details.delete.action')}\n </ConfirmButton>\n )}\n </>\n }\n >\n {error && (\n <Alert variant=\"error\" role=\"alert\">\n {error}\n </Alert>\n )}\n <Panel title={t('admin.agents.details.overview')}>\n <DetailList items={details} />\n </Panel>\n <Panel title={t('admin.agents.details.groups')}>\n <ChipList\n label={t('admin.agents.details.groups')}\n emptyText={t('admin.agents.details.no_groups')}\n items={groups.map((group: MembershipGroup) => ({id: group.id, label: group.name}))}\n />\n </Panel>\n <Panel title={t('admin.agents.details.roles')}>\n <ChipList\n label={t('admin.agents.details.roles')}\n emptyText={t('admin.agents.details.no_roles')}\n items={roles.map((role: string) => ({id: role, label: role}))}\n />\n </Panel>\n </AdminSection>\n );\n};\n\nexport default BaseAgentDetails;\n"],"mappings":";;;;;;;;;;;;;;AA+DA,MAAMA,oBAA+C,EACnD,SACA,OACA,UACA,WACA,QAAQ,MACR,SAAS,EAAE,EACX,aAAa,OACb,YAAY,OACZ,UACA,aACA,QAAQ,EAAE,OAC+B;CACzC,MAAM,EAAC,MAAKC,uBAAe,aAAa,KAAK;CAC7C,MAAMC,SAAiCC,4BAAoB;AAE3D,KAAI,SACF,QACE,oBAAC;EAAe;YACb,SAAS;GACR;GACA;GACA;GACA;GACA;GACA,UAAU,SAAS,CAAC,MAAM,aAAa,WAAW;GAClD;GACD,CAAC;GACE;AAIV,KAAI,aAAa,CAAC,MAChB,QACE,oBAACC;EAAa,OAAM;EAA2B;EAAwB;YACrE,qBAAC;GAAK,WAAW,OAAO;GAAU,MAAK;;IACrC,oBAACC,mBAAQ,MAAK,UAAU;;IAAE,EAAE,uBAAuB;;IAC9C;GACM;AAInB,KAAI,CAAC,MACH,QACE,oBAACD;EAAa,OAAM;EAA2B;EAAwB;YACrE,oBAACE;GAAM,SAAQ;GAAQ,MAAK;aACzB,SAAS,EAAE,gCAAgC;IACtC;GACK;CAInB,MAAMC,UAA+C;EACnD;GAAC,OAAO,EAAE,4BAA4B;GAAE,OAAO,MAAM;GAAK;EAC1D;GAAC,OAAO,EAAE,6BAA6B;GAAE,OAAO,MAAM,SAAS,EAAE,gCAAgC;GAAC;EAClG;GAAC,OAAO,EAAE,yCAAyC;GAAE,OAAO,MAAM,YAAY,MAAM;GAAK;EAC1F;AAED,KAAI,MAAM,SACR,SAAQ,KAAK;EAAC,OAAO,EAAE,sCAAsC;EAAE,OAAO,oBAACC,wBAAa,OAAO,MAAM,WAAY;EAAC,CAAC;AAGjH,QACE,qBAACJ;EACC,OAAM;EACK;EACX,OAAO,MAAM;EACb,aAAa,MAAM;EACN;EACb,SACE,4CACG,SACA,YAAY,CAAC,MAAM,cAClB,oBAAC;GACC,aAAa,EAAE,uCAAuC,EAAC,MAAM,MAAM,MAAK,CAAC;GACzE,WAAW;GACX,WAAW;aAEV,EAAE,qCAAqC;IAC1B,IAEjB;;GAGJ,SACC,oBAACE;IAAM,SAAQ;IAAQ,MAAK;cACzB;KACK;GAEV,oBAAC;IAAM,OAAO,EAAE,gCAAgC;cAC9C,oBAAC,cAAW,OAAO,UAAW;KACxB;GACR,oBAAC;IAAM,OAAO,EAAE,8BAA8B;cAC5C,oBAAC;KACC,OAAO,EAAE,8BAA8B;KACvC,WAAW,EAAE,iCAAiC;KAC9C,OAAO,OAAO,KAAK,WAA4B;MAAC,IAAI,MAAM;MAAI,OAAO,MAAM;MAAK,EAAE;MAClF;KACI;GACR,oBAAC;IAAM,OAAO,EAAE,6BAA6B;cAC3C,oBAAC;KACC,OAAO,EAAE,6BAA6B;KACtC,WAAW,EAAE,gCAAgC;KAC7C,OAAO,MAAM,KAAK,UAAkB;MAAC,IAAI;MAAM,OAAO;MAAK,EAAE;MAC7D;KACI;;GACK;;AAInB,+BAAe"}
1
+ {"version":3,"file":"BaseAgentDetails.js","names":["BaseAgentDetails: FC<BaseAgentDetailsProps>","useTranslation","styles: Record<string, string>","useAdminPartStyles","AdminSection","Spinner","Alert","details: {label: string; value: ReactNode}[]","CopyableText"],"sources":["../../../../src/components/admin/AgentDetails/BaseAgentDetails.tsx"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {AccountLifecycleAction, Agent, MembershipGroup, Preferences} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode} from 'react';\nimport useTranslation from '../../../hooks/useTranslation';\nimport Alert from '../../primitives/Alert/Alert';\nimport CopyableText from '../../primitives/CopyableText/CopyableText';\nimport Spinner from '../../primitives/Spinner/Spinner';\nimport {AccessStatusBadge, AccountLifecycleButtons} from '../shared/AccountLifecycleParts';\nimport {ChipList, ConfirmButton, DetailList, Panel} from '../shared/AdminParts';\nimport AdminSection from '../shared/AdminSection';\nimport useAdminPartStyles from '../shared/useAdminPartStyles';\n\n/**\n * What {@link BaseAgentDetails} hands its `children` render function, so the agent can be shown with any UI.\n */\nexport interface BaseAgentDetailsRenderProps {\n agent?: Agent;\n error: string | null;\n groups: MembershipGroup[];\n isDeleting: boolean;\n isLoading: boolean;\n isRunningLifecycleAction: boolean;\n /**\n * The account lifecycle actions offered for the agent. Empty when none is allowed.\n */\n lifecycleActions: AccountLifecycleAction[];\n /**\n * Deletes the agent. Undefined when deletion is not allowed, including for read-only agents.\n */\n onDelete?: () => void;\n /**\n * Runs an account lifecycle action, with the operator's note on a suspension. Undefined when none is allowed.\n */\n onLifecycleAction?: (action: AccountLifecycleAction, operatorNote?: string) => void;\n roles: string[];\n}\n\nexport interface BaseAgentDetailsProps {\n /**\n * Controls rendered next to the agent's name.\n */\n actions?: ReactNode;\n agent?: Agent;\n /**\n * Renders custom UI in place of the default view. Receives the agent, its groups and roles, the\n * loading and error state, and the delete handler.\n */\n children?: (props: BaseAgentDetailsRenderProps) => ReactNode;\n className?: string;\n error?: string | null;\n /**\n * The groups the agent belongs to.\n */\n groups?: MembershipGroup[];\n isDeleting?: boolean;\n isLoading?: boolean;\n isRunningLifecycleAction?: boolean;\n /**\n * The account lifecycle actions to offer (suspend, unsuspend, unlock), shown only with `onLifecycleAction`. They change\n * only runtime state, so they apply to read-only agents too.\n */\n lifecycleActions?: AccountLifecycleAction[];\n /**\n * Deletes the agent. The delete action is hidden when omitted.\n */\n onDelete?: () => void;\n /**\n * Runs an account lifecycle action. Suspending and unsuspending ask for confirmation first, and a\n * suspension takes an optional operator note.\n */\n onLifecycleAction?: (action: AccountLifecycleAction, operatorNote?: string) => void;\n preferences?: Preferences;\n /**\n * The names of the roles the agent holds, directly or through its groups.\n */\n roles?: string[];\n}\n\n/**\n * Shows an agent's type, owner, client and the groups and roles it holds. Holds no data of its own:\n * pass the agent and handle deletion.\n */\nconst BaseAgentDetails: FC<BaseAgentDetailsProps> = ({\n actions,\n agent,\n children,\n className,\n error = null,\n groups = [],\n isDeleting = false,\n isLoading = false,\n isRunningLifecycleAction = false,\n lifecycleActions = [],\n onDelete,\n onLifecycleAction,\n preferences,\n roles = [],\n}: BaseAgentDetailsProps): ReactElement => {\n const {t} = useTranslation(preferences?.i18n);\n const styles: Record<string, string> = useAdminPartStyles();\n\n if (children) {\n return (\n <div className={className}>\n {children({\n agent,\n error,\n groups,\n isDeleting,\n isLoading,\n isRunningLifecycleAction,\n lifecycleActions: onLifecycleAction && agent ? lifecycleActions : [],\n onDelete: agent && !agent.isReadOnly ? onDelete : undefined,\n onLifecycleAction: agent ? onLifecycleAction : undefined,\n roles,\n })}\n </div>\n );\n }\n\n if (isLoading && !agent) {\n return (\n <AdminSection block=\"agent-details\" className={className} preferences={preferences}>\n <span className={styles['muted']} role=\"status\">\n <Spinner size=\"small\" /> {t('admin.common.loading')}\n </span>\n </AdminSection>\n );\n }\n\n if (!agent) {\n return (\n <AdminSection block=\"agent-details\" className={className} preferences={preferences}>\n <Alert variant=\"error\" role=\"alert\">\n {error ?? t('admin.common.errors.not_found')}\n </Alert>\n </AdminSection>\n );\n }\n\n const details: {label: string; value: ReactNode}[] = [\n {label: t('admin.agents.details.type'), value: agent.type},\n {label: t('admin.agents.details.owner'), value: agent.owner ?? t('admin.agents.details.no_owner')},\n {label: t('admin.common.columns.organization_unit'), value: agent.ouHandle ?? agent.ouId},\n ];\n\n if (agent.status) {\n details.push({label: t('admin.common.columns.status'), value: <AccessStatusBadge status={agent.status.value} />});\n }\n\n if (agent.clientId) {\n details.push({label: t('admin.agents.list.columns.client_id'), value: <CopyableText value={agent.clientId} />});\n }\n\n return (\n <AdminSection\n block=\"agent-details\"\n className={className}\n title={agent.name}\n description={agent.description}\n preferences={preferences}\n actions={\n <>\n {actions}\n {onLifecycleAction && (\n <AccountLifecycleButtons\n actions={lifecycleActions}\n collectsOperatorNote\n isRunning={isRunningLifecycleAction}\n name={agent.name}\n onAction={onLifecycleAction}\n />\n )}\n {onDelete && !agent.isReadOnly && (\n <ConfirmButton\n confirmText={t('admin.agents.details.delete.confirm', {name: agent.name})}\n isLoading={isDeleting}\n onConfirm={onDelete}\n >\n {t('admin.agents.details.delete.action')}\n </ConfirmButton>\n )}\n </>\n }\n >\n {error && (\n <Alert variant=\"error\" role=\"alert\">\n {error}\n </Alert>\n )}\n <Panel title={t('admin.agents.details.overview')}>\n <DetailList items={details} />\n </Panel>\n <Panel title={t('admin.agents.details.groups')}>\n <ChipList\n label={t('admin.agents.details.groups')}\n emptyText={t('admin.agents.details.no_groups')}\n items={groups.map((group: MembershipGroup) => ({id: group.id, label: group.name}))}\n />\n </Panel>\n <Panel title={t('admin.agents.details.roles')}>\n <ChipList\n label={t('admin.agents.details.roles')}\n emptyText={t('admin.agents.details.no_roles')}\n items={roles.map((role: string) => ({id: role, label: role}))}\n />\n </Panel>\n </AdminSection>\n );\n};\n\nexport default BaseAgentDetails;\n"],"mappings":";;;;;;;;;;;;;;;AAoFA,MAAMA,oBAA+C,EACnD,SACA,OACA,UACA,WACA,QAAQ,MACR,SAAS,EAAE,EACX,aAAa,OACb,YAAY,OACZ,2BAA2B,OAC3B,mBAAmB,EAAE,EACrB,UACA,mBACA,aACA,QAAQ,EAAE,OAC+B;CACzC,MAAM,EAAC,MAAKC,uBAAe,aAAa,KAAK;CAC7C,MAAMC,SAAiCC,4BAAoB;AAE3D,KAAI,SACF,QACE,oBAAC;EAAe;YACb,SAAS;GACR;GACA;GACA;GACA;GACA;GACA;GACA,kBAAkB,qBAAqB,QAAQ,mBAAmB,EAAE;GACpE,UAAU,SAAS,CAAC,MAAM,aAAa,WAAW;GAClD,mBAAmB,QAAQ,oBAAoB;GAC/C;GACD,CAAC;GACE;AAIV,KAAI,aAAa,CAAC,MAChB,QACE,oBAACC;EAAa,OAAM;EAA2B;EAAwB;YACrE,qBAAC;GAAK,WAAW,OAAO;GAAU,MAAK;;IACrC,oBAACC,mBAAQ,MAAK,UAAU;;IAAE,EAAE,uBAAuB;;IAC9C;GACM;AAInB,KAAI,CAAC,MACH,QACE,oBAACD;EAAa,OAAM;EAA2B;EAAwB;YACrE,oBAACE;GAAM,SAAQ;GAAQ,MAAK;aACzB,SAAS,EAAE,gCAAgC;IACtC;GACK;CAInB,MAAMC,UAA+C;EACnD;GAAC,OAAO,EAAE,4BAA4B;GAAE,OAAO,MAAM;GAAK;EAC1D;GAAC,OAAO,EAAE,6BAA6B;GAAE,OAAO,MAAM,SAAS,EAAE,gCAAgC;GAAC;EAClG;GAAC,OAAO,EAAE,yCAAyC;GAAE,OAAO,MAAM,YAAY,MAAM;GAAK;EAC1F;AAED,KAAI,MAAM,OACR,SAAQ,KAAK;EAAC,OAAO,EAAE,8BAA8B;EAAE,OAAO,oBAAC,qBAAkB,QAAQ,MAAM,OAAO,QAAS;EAAC,CAAC;AAGnH,KAAI,MAAM,SACR,SAAQ,KAAK;EAAC,OAAO,EAAE,sCAAsC;EAAE,OAAO,oBAACC,wBAAa,OAAO,MAAM,WAAY;EAAC,CAAC;AAGjH,QACE,qBAACJ;EACC,OAAM;EACK;EACX,OAAO,MAAM;EACb,aAAa,MAAM;EACN;EACb,SACE;GACG;GACA,qBACC,oBAAC;IACC,SAAS;IACT;IACA,WAAW;IACX,MAAM,MAAM;IACZ,UAAU;KACV;GAEH,YAAY,CAAC,MAAM,cAClB,oBAAC;IACC,aAAa,EAAE,uCAAuC,EAAC,MAAM,MAAM,MAAK,CAAC;IACzE,WAAW;IACX,WAAW;cAEV,EAAE,qCAAqC;KAC1B;MAEjB;;GAGJ,SACC,oBAACE;IAAM,SAAQ;IAAQ,MAAK;cACzB;KACK;GAEV,oBAAC;IAAM,OAAO,EAAE,gCAAgC;cAC9C,oBAAC,cAAW,OAAO,UAAW;KACxB;GACR,oBAAC;IAAM,OAAO,EAAE,8BAA8B;cAC5C,oBAAC;KACC,OAAO,EAAE,8BAA8B;KACvC,WAAW,EAAE,iCAAiC;KAC9C,OAAO,OAAO,KAAK,WAA4B;MAAC,IAAI,MAAM;MAAI,OAAO,MAAM;MAAK,EAAE;MAClF;KACI;GACR,oBAAC;IAAM,OAAO,EAAE,6BAA6B;cAC3C,oBAAC;KACC,OAAO,EAAE,6BAA6B;KACtC,WAAW,EAAE,gCAAgC;KAC7C,OAAO,MAAM,KAAK,UAAkB;MAAC,IAAI;MAAM,OAAO;MAAK,EAAE;MAC7D;KACI;;GACK;;AAInB,+BAAe"}
@@ -1,6 +1,13 @@
1
+ import { AdministrationMode } from '@thunderid/browser';
1
2
  import { FC } from 'react';
2
3
  import { BaseApplicationDetailsProps } from './BaseApplicationDetails';
3
- export type ApplicationDetailsProps = Omit<BaseApplicationDetailsProps, 'application' | 'clientSecret' | 'error' | 'isDeleting' | 'isLoading' | 'isRegeneratingSecret' | 'isUpdating' | 'onDelete' | 'onRegenerateSecret' | 'onSecretDismiss' | 'onUpdate'> & {
4
+ export type ApplicationDetailsProps = Omit<BaseApplicationDetailsProps, 'application' | 'clientSecret' | 'error' | 'isDeleting' | 'isLoading' | 'isRegeneratingSecret' | 'isRunningLifecycleAction' | 'isUpdating' | 'lifecycleActions' | 'onDelete' | 'onLifecycleAction' | 'onRegenerateSecret' | 'onSecretDismiss' | 'onUpdate'> & {
5
+ /**
6
+ * How the delete and the client secret regeneration run. `flow` runs the administration flow the server configures for it, which can revoke
7
+ * grants and end sessions first. It needs `baseUrl`.
8
+ * @default 'native'
9
+ */
10
+ administrationMode?: AdministrationMode;
4
11
  applicationId: string;
5
12
  /**
6
13
  * Whether the application can be deleted from this view.
@@ -12,6 +19,13 @@ export type ApplicationDetailsProps = Omit<BaseApplicationDetailsProps, 'applica
12
19
  * @default false
13
20
  */
14
21
  editable?: boolean;
22
+ /**
23
+ * Whether the application can be suspended and unsuspended from this view. Each action runs through its
24
+ * administration flow and is offered only when the server configures that flow. Reading the configured
25
+ * flows needs a token that may read the server configuration.
26
+ * @default false
27
+ */
28
+ lifecycleActions?: boolean;
15
29
  /**
16
30
  * Called after the application has been deleted.
17
31
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ApplicationDetails.d.ts","sourceRoot":"","sources":["../../../../src/components/admin/ApplicationDetails/ApplicationDetails.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAC,EAAE,EAAe,MAAM,OAAO,CAAC;AACvC,OAA+B,EAE7B,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAWlC,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,2BAA2B,EACzB,aAAa,GACb,cAAc,GACd,OAAO,GACP,YAAY,GACZ,WAAW,GACX,sBAAsB,GACtB,YAAY,GACZ,UAAU,GACV,oBAAoB,GACpB,iBAAiB,GACjB,UAAU,CACb,GAAG;IACF,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,QAAA,MAAM,kBAAkB,EAAE,EAAE,CAAC,uBAAuB,CAkEnD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"ApplicationDetails.d.ts","sourceRoot":"","sources":["../../../../src/components/admin/ApplicationDetails/ApplicationDetails.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,kBAAkB,EAUnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,EAAE,EAAe,MAAM,OAAO,CAAC;AACvC,OAA+B,EAE7B,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAYlC,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,2BAA2B,EACzB,aAAa,GACb,cAAc,GACd,OAAO,GACP,YAAY,GACZ,WAAW,GACX,sBAAsB,GACtB,0BAA0B,GAC1B,YAAY,GACZ,kBAAkB,GAClB,UAAU,GACV,mBAAmB,GACnB,oBAAoB,GACpB,iBAAiB,GACjB,UAAU,CACb,GAAG;IACF;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,QAAA,MAAM,kBAAkB,EAAE,EAAE,CAAC,uBAAuB,CAiFnD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}