@cedros/login-react 0.0.29 → 0.0.31

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 (177) hide show
  1. package/README.md +2 -0
  2. package/dist/{AdminDepositList-CyT4VBH8.js → AdminDepositList-BUm_ZcAW.js} +1 -1
  3. package/dist/{AdminDepositList-CyT4VBH8.js.map → AdminDepositList-BUm_ZcAW.js.map} +1 -1
  4. package/dist/{AdminDepositList-b2AXtLg0.cjs → AdminDepositList-B_z6x3j5.cjs} +1 -1
  5. package/dist/{AdminDepositList-b2AXtLg0.cjs.map → AdminDepositList-B_z6x3j5.cjs.map} +1 -1
  6. package/dist/{AdminWithdrawalHistory-DL9zbu2b.cjs → AdminWithdrawalHistory-B2EY2ZmH.cjs} +1 -1
  7. package/dist/{AdminWithdrawalHistory-DL9zbu2b.cjs.map → AdminWithdrawalHistory-B2EY2ZmH.cjs.map} +1 -1
  8. package/dist/{AdminWithdrawalHistory-Cud-yuWy.js → AdminWithdrawalHistory-C76bkbjX.js} +1 -1
  9. package/dist/{AdminWithdrawalHistory-Cud-yuWy.js.map → AdminWithdrawalHistory-C76bkbjX.js.map} +1 -1
  10. package/dist/{AuthenticationSettings-D6GvSw3g.cjs → AuthenticationSettings-C-aYDXNH.cjs} +1 -1
  11. package/dist/{AuthenticationSettings-D6GvSw3g.cjs.map → AuthenticationSettings-C-aYDXNH.cjs.map} +1 -1
  12. package/dist/AuthenticationSettings-CoTic-d_.cjs +1 -0
  13. package/dist/AuthenticationSettings-CoTic-d_.cjs.map +1 -0
  14. package/dist/{AuthenticationSettings-rb4Fksw5.js → AuthenticationSettings-CsPbxwP7.js} +1 -1
  15. package/dist/{AuthenticationSettings-rb4Fksw5.js.map → AuthenticationSettings-CsPbxwP7.js.map} +1 -1
  16. package/dist/AuthenticationSettings-DIVk0OP8.js +712 -0
  17. package/dist/AuthenticationSettings-DIVk0OP8.js.map +1 -0
  18. package/dist/AutosaveStatus-DGNI4lXn.cjs +1 -0
  19. package/dist/AutosaveStatus-DGNI4lXn.cjs.map +1 -0
  20. package/dist/{AutosaveStatus-vkJxtuEw.js → AutosaveStatus-f-jw25Ay.js} +141 -93
  21. package/dist/AutosaveStatus-f-jw25Ay.js.map +1 -0
  22. package/dist/{CreditSystemSettings-ChA_lbef.cjs → CreditSystemSettings-BNkvsgsk.cjs} +1 -1
  23. package/dist/{CreditSystemSettings-ChA_lbef.cjs.map → CreditSystemSettings-BNkvsgsk.cjs.map} +1 -1
  24. package/dist/{CreditSystemSettings-DsRipb2R.js → CreditSystemSettings-C6ed3yp7.js} +1 -1
  25. package/dist/{CreditSystemSettings-DsRipb2R.js.map → CreditSystemSettings-C6ed3yp7.js.map} +1 -1
  26. package/dist/{CreditSystemSettings-r3gnGjiU.cjs → CreditSystemSettings-DM9ep1TF.cjs} +1 -1
  27. package/dist/{CreditSystemSettings-r3gnGjiU.cjs.map → CreditSystemSettings-DM9ep1TF.cjs.map} +1 -1
  28. package/dist/{CreditSystemSettings-a31pqSYS.js → CreditSystemSettings-uinhzoha.js} +1 -1
  29. package/dist/{CreditSystemSettings-a31pqSYS.js.map → CreditSystemSettings-uinhzoha.js.map} +1 -1
  30. package/dist/{DepositsSection-DD9MKUFt.js → DepositsSection-Bb4ISzvE.js} +1 -1
  31. package/dist/{DepositsSection-DD9MKUFt.js.map → DepositsSection-Bb4ISzvE.js.map} +1 -1
  32. package/dist/{DepositsSection-BkKUS4vk.cjs → DepositsSection-uQUdGeVb.cjs} +1 -1
  33. package/dist/{DepositsSection-BkKUS4vk.cjs.map → DepositsSection-uQUdGeVb.cjs.map} +1 -1
  34. package/dist/EmailRegisterForm-B_TiJkD6.cjs +1 -0
  35. package/dist/EmailRegisterForm-B_TiJkD6.cjs.map +1 -0
  36. package/dist/EmailRegisterForm-CCEuQA-w.js +773 -0
  37. package/dist/EmailRegisterForm-CCEuQA-w.js.map +1 -0
  38. package/dist/{EmailSettings-BVJ4vz0Y.js → EmailSettings-BAuQtEfM.js} +1 -1
  39. package/dist/{EmailSettings-BVJ4vz0Y.js.map → EmailSettings-BAuQtEfM.js.map} +1 -1
  40. package/dist/{EmailSettings-Dg2SAiHj.cjs → EmailSettings-BC0f1PCI.cjs} +1 -1
  41. package/dist/{EmailSettings-Dg2SAiHj.cjs.map → EmailSettings-BC0f1PCI.cjs.map} +1 -1
  42. package/dist/{EmailSettings-CM5l8qqK.cjs → EmailSettings-BF5EiPl9.cjs} +1 -1
  43. package/dist/{EmailSettings-CM5l8qqK.cjs.map → EmailSettings-BF5EiPl9.cjs.map} +1 -1
  44. package/dist/{EmailSettings-xtVl4kXD.js → EmailSettings-BKuXy8sc.js} +1 -1
  45. package/dist/{EmailSettings-xtVl4kXD.js.map → EmailSettings-BKuXy8sc.js.map} +1 -1
  46. package/dist/{EmbeddedWalletSettings-Bmx8x21f.cjs → EmbeddedWalletSettings-BRjt2PAj.cjs} +1 -1
  47. package/dist/{EmbeddedWalletSettings-Bmx8x21f.cjs.map → EmbeddedWalletSettings-BRjt2PAj.cjs.map} +1 -1
  48. package/dist/{EmbeddedWalletSettings-BuDgqv-K.js → EmbeddedWalletSettings-C27X9He2.js} +1 -1
  49. package/dist/{EmbeddedWalletSettings-BuDgqv-K.js.map → EmbeddedWalletSettings-C27X9He2.js.map} +1 -1
  50. package/dist/{EmbeddedWalletSettings-BXN9VbNJ.cjs → EmbeddedWalletSettings-CJY39UZN.cjs} +1 -1
  51. package/dist/{EmbeddedWalletSettings-BXN9VbNJ.cjs.map → EmbeddedWalletSettings-CJY39UZN.cjs.map} +1 -1
  52. package/dist/{EmbeddedWalletSettings-DY5iJhS0.js → EmbeddedWalletSettings-Dmi-EQ7W.js} +1 -1
  53. package/dist/{EmbeddedWalletSettings-DY5iJhS0.js.map → EmbeddedWalletSettings-Dmi-EQ7W.js.map} +1 -1
  54. package/dist/GoogleLoginButton-BwiL1o6U.cjs +1 -0
  55. package/dist/GoogleLoginButton-BwiL1o6U.cjs.map +1 -0
  56. package/dist/GoogleLoginButton-CFlqxvU-.js +217 -0
  57. package/dist/GoogleLoginButton-CFlqxvU-.js.map +1 -0
  58. package/dist/LoadingSpinner-6vml-zwr.js.map +1 -1
  59. package/dist/LoadingSpinner-d6sSxgQN.cjs.map +1 -1
  60. package/dist/{PermissionsSection-BPbE-hNx.cjs → PermissionsSection-DEMVp7X3.cjs} +1 -1
  61. package/dist/PermissionsSection-DEMVp7X3.cjs.map +1 -0
  62. package/dist/{PermissionsSection-CighC1p6.js → PermissionsSection-DNzOL1xW.js} +27 -25
  63. package/dist/PermissionsSection-DNzOL1xW.js.map +1 -0
  64. package/dist/{ServerSettings-BAstMKHS.js → ServerSettings-BT9weFPz.js} +1 -1
  65. package/dist/{ServerSettings-BAstMKHS.js.map → ServerSettings-BT9weFPz.js.map} +1 -1
  66. package/dist/{ServerSettings-LIIP5TPz.cjs → ServerSettings-CKfiLfXi.cjs} +1 -1
  67. package/dist/{ServerSettings-LIIP5TPz.cjs.map → ServerSettings-CKfiLfXi.cjs.map} +1 -1
  68. package/dist/{ServerSettings-9Q091f3o.js → ServerSettings-CZfBdMxG.js} +1 -1
  69. package/dist/{ServerSettings-9Q091f3o.js.map → ServerSettings-CZfBdMxG.js.map} +1 -1
  70. package/dist/{ServerSettings-PH7T8JKI.cjs → ServerSettings-rHrVN8O8.cjs} +1 -1
  71. package/dist/{ServerSettings-PH7T8JKI.cjs.map → ServerSettings-rHrVN8O8.cjs.map} +1 -1
  72. package/dist/SolanaLoginButton-DHsiug1Y.js +195 -0
  73. package/dist/SolanaLoginButton-DHsiug1Y.js.map +1 -0
  74. package/dist/SolanaLoginButton-DNEcSSF_.cjs +1 -0
  75. package/dist/SolanaLoginButton-DNEcSSF_.cjs.map +1 -0
  76. package/dist/{TeamSection-BIECkp7g.js → TeamSection-CoMXyFtz.js} +2 -2
  77. package/dist/{TeamSection-BIECkp7g.js.map → TeamSection-CoMXyFtz.js.map} +1 -1
  78. package/dist/{TeamSection-BOH9pv_E.cjs → TeamSection-DopbZClq.cjs} +1 -1
  79. package/dist/{TeamSection-BOH9pv_E.cjs.map → TeamSection-DopbZClq.cjs.map} +1 -1
  80. package/dist/{UsersSection-t-zm0jZW.js → UsersSection--PAE1XRh.js} +1 -1
  81. package/dist/{UsersSection-t-zm0jZW.js.map → UsersSection--PAE1XRh.js.map} +1 -1
  82. package/dist/{UsersSection-e6q7FHzx.cjs → UsersSection-C7aRNkK2.cjs} +1 -1
  83. package/dist/{UsersSection-e6q7FHzx.cjs.map → UsersSection-C7aRNkK2.cjs.map} +1 -1
  84. package/dist/{WebhookSettings-D0F8ESlB.js → WebhookSettings-Bgld6D_T.js} +1 -1
  85. package/dist/{WebhookSettings-D0F8ESlB.js.map → WebhookSettings-Bgld6D_T.js.map} +1 -1
  86. package/dist/{WebhookSettings-2p9abGm5.cjs → WebhookSettings-DXjnq-c7.cjs} +1 -1
  87. package/dist/{WebhookSettings-2p9abGm5.cjs.map → WebhookSettings-DXjnq-c7.cjs.map} +1 -1
  88. package/dist/{WebhookSettings-CdFM7_V-.cjs → WebhookSettings-DnLk97Mr.cjs} +1 -1
  89. package/dist/{WebhookSettings-CdFM7_V-.cjs.map → WebhookSettings-DnLk97Mr.cjs.map} +1 -1
  90. package/dist/{WebhookSettings-CXMBju7N.js → WebhookSettings-ufiGTmbG.js} +1 -1
  91. package/dist/{WebhookSettings-CXMBju7N.js.map → WebhookSettings-ufiGTmbG.js.map} +1 -1
  92. package/dist/{WithdrawalsSection-yRDTVFsb.js → WithdrawalsSection-BN-FjTEV.js} +1 -1
  93. package/dist/{WithdrawalsSection-yRDTVFsb.js.map → WithdrawalsSection-BN-FjTEV.js.map} +1 -1
  94. package/dist/{WithdrawalsSection-sljIyeaz.cjs → WithdrawalsSection-BhuCwFat.cjs} +1 -1
  95. package/dist/{WithdrawalsSection-sljIyeaz.cjs.map → WithdrawalsSection-BhuCwFat.cjs.map} +1 -1
  96. package/dist/admin-only.cjs +1 -1
  97. package/dist/admin-only.js +1 -1
  98. package/dist/email-only.cjs +1 -1
  99. package/dist/email-only.d.ts +17 -1
  100. package/dist/email-only.js +3 -3
  101. package/dist/google-only.cjs +1 -1
  102. package/dist/google-only.d.ts +16 -0
  103. package/dist/google-only.js +3 -3
  104. package/dist/index.cjs +12 -12
  105. package/dist/index.cjs.map +1 -1
  106. package/dist/index.d.ts +248 -12
  107. package/dist/index.js +3433 -2562
  108. package/dist/index.js.map +1 -1
  109. package/dist/login-react.css +1 -1
  110. package/dist/{plugin-DbkijwEV.js → plugin-BbExid4E.js} +1 -1
  111. package/dist/{plugin-DbkijwEV.js.map → plugin-BbExid4E.js.map} +1 -1
  112. package/dist/{plugin-PU2vAozn.cjs → plugin-Xca67fp7.cjs} +1 -1
  113. package/dist/{plugin-PU2vAozn.cjs.map → plugin-Xca67fp7.cjs.map} +1 -1
  114. package/dist/{shamir-CiBczzDN.cjs → shamir-DBpHm7WN.cjs} +1 -1
  115. package/dist/{shamir-CiBczzDN.cjs.map → shamir-DBpHm7WN.cjs.map} +1 -1
  116. package/dist/{shamir-OAB2zD9Y.js → shamir-R8ddesFt.js} +1 -1
  117. package/dist/{shamir-OAB2zD9Y.js.map → shamir-R8ddesFt.js.map} +1 -1
  118. package/dist/{silentWalletEnroll-FqXS7Rvh.js → silentWalletEnroll-Dp1GTeNr.js} +3 -3
  119. package/dist/{silentWalletEnroll-FqXS7Rvh.js.map → silentWalletEnroll-Dp1GTeNr.js.map} +1 -1
  120. package/dist/{silentWalletEnroll-wnkcB9HP.cjs → silentWalletEnroll-HPvsbd2J.cjs} +1 -1
  121. package/dist/{silentWalletEnroll-wnkcB9HP.cjs.map → silentWalletEnroll-HPvsbd2J.cjs.map} +1 -1
  122. package/dist/solana-only.cjs +1 -1
  123. package/dist/solana-only.d.ts +18 -2
  124. package/dist/solana-only.js +3 -3
  125. package/dist/{useAdminDeposits-BTSyeAfg.js → useAdminDeposits-C76B2Q_8.js} +1 -1
  126. package/dist/{useAdminDeposits-BTSyeAfg.js.map → useAdminDeposits-C76B2Q_8.js.map} +1 -1
  127. package/dist/{useAdminDeposits-BkkCwHWp.cjs → useAdminDeposits-CpLd68oP.cjs} +1 -1
  128. package/dist/{useAdminDeposits-BkkCwHWp.cjs.map → useAdminDeposits-CpLd68oP.cjs.map} +1 -1
  129. package/dist/{useAuth-m5Hf89v8.js → useAuth-CVLv2oKA.js} +547 -545
  130. package/dist/useAuth-CVLv2oKA.js.map +1 -0
  131. package/dist/useAuth-XZaciuLg.cjs +1 -0
  132. package/dist/useAuth-XZaciuLg.cjs.map +1 -0
  133. package/dist/useCedrosLogin-CFfID-0i.js +228 -0
  134. package/dist/useCedrosLogin-CFfID-0i.js.map +1 -0
  135. package/dist/useCedrosLogin-DtJorrE7.cjs +1 -0
  136. package/dist/useCedrosLogin-DtJorrE7.cjs.map +1 -0
  137. package/dist/{useOrgs-C3pzMA9h.js → useOrgs-C90KT9KP.js} +1 -1
  138. package/dist/{useOrgs-C3pzMA9h.js.map → useOrgs-C90KT9KP.js.map} +1 -1
  139. package/dist/{useOrgs-DDVRCaVi.cjs → useOrgs-CNqfn-fk.cjs} +1 -1
  140. package/dist/{useOrgs-DDVRCaVi.cjs.map → useOrgs-CNqfn-fk.cjs.map} +1 -1
  141. package/dist/{useSystemSettings-DRrreszl.cjs → useSystemSettings-B2jY51ob.cjs} +1 -1
  142. package/dist/{useSystemSettings-DRrreszl.cjs.map → useSystemSettings-B2jY51ob.cjs.map} +1 -1
  143. package/dist/{useSystemSettings-DBlAMjFi.js → useSystemSettings-rgskaDqP.js} +1 -1
  144. package/dist/{useSystemSettings-DBlAMjFi.js.map → useSystemSettings-rgskaDqP.js.map} +1 -1
  145. package/dist/{useUsersStatsSummary-NjEFvWuz.js → useUsersStatsSummary-5DJwzntC.js} +2 -2
  146. package/dist/{useUsersStatsSummary-NjEFvWuz.js.map → useUsersStatsSummary-5DJwzntC.js.map} +1 -1
  147. package/dist/{useUsersStatsSummary-8qY7iP4G.cjs → useUsersStatsSummary-DgKaUIfs.cjs} +1 -1
  148. package/dist/{useUsersStatsSummary-8qY7iP4G.cjs.map → useUsersStatsSummary-DgKaUIfs.cjs.map} +1 -1
  149. package/package.json +1 -1
  150. package/dist/AuthenticationSettings-C9f5MKgj.cjs +0 -1
  151. package/dist/AuthenticationSettings-C9f5MKgj.cjs.map +0 -1
  152. package/dist/AuthenticationSettings-DC64o_J6.js +0 -525
  153. package/dist/AuthenticationSettings-DC64o_J6.js.map +0 -1
  154. package/dist/AutosaveStatus-BFj5GIab.cjs +0 -1
  155. package/dist/AutosaveStatus-BFj5GIab.cjs.map +0 -1
  156. package/dist/AutosaveStatus-vkJxtuEw.js.map +0 -1
  157. package/dist/EmailRegisterForm-B1DB-bqe.cjs +0 -1
  158. package/dist/EmailRegisterForm-B1DB-bqe.cjs.map +0 -1
  159. package/dist/EmailRegisterForm-BAX_uBIt.js +0 -927
  160. package/dist/EmailRegisterForm-BAX_uBIt.js.map +0 -1
  161. package/dist/GoogleLoginButton-B6qnNMZp.js +0 -230
  162. package/dist/GoogleLoginButton-B6qnNMZp.js.map +0 -1
  163. package/dist/GoogleLoginButton-D7CoMXLq.cjs +0 -1
  164. package/dist/GoogleLoginButton-D7CoMXLq.cjs.map +0 -1
  165. package/dist/PermissionsSection-BPbE-hNx.cjs.map +0 -1
  166. package/dist/PermissionsSection-CighC1p6.js.map +0 -1
  167. package/dist/mobileWalletAdapter-B6ELaZp1.cjs +0 -1
  168. package/dist/mobileWalletAdapter-B6ELaZp1.cjs.map +0 -1
  169. package/dist/mobileWalletAdapter-Cm_AUXhg.js +0 -191
  170. package/dist/mobileWalletAdapter-Cm_AUXhg.js.map +0 -1
  171. package/dist/useAuth-X6Ds6WW4.cjs +0 -1
  172. package/dist/useAuth-X6Ds6WW4.cjs.map +0 -1
  173. package/dist/useAuth-m5Hf89v8.js.map +0 -1
  174. package/dist/useCedrosLogin-C9MrcZvh.cjs +0 -1
  175. package/dist/useCedrosLogin-C9MrcZvh.cjs.map +0 -1
  176. package/dist/useCedrosLogin-_94MmGGq.js +0 -216
  177. package/dist/useCedrosLogin-_94MmGGq.js.map +0 -1
@@ -0,0 +1,217 @@
1
+ import { jsxs as C, jsx as u } from "react/jsx-runtime";
2
+ import { useState as m, useRef as w, useMemo as G, useEffect as y, useCallback as p } from "react";
3
+ import { u as S, A as _, h as T } from "./useCedrosLogin-CFfID-0i.js";
4
+ import { L as P } from "./LoadingSpinner-6vml-zwr.js";
5
+ const z = {
6
+ loading: !1,
7
+ loaded: !1,
8
+ error: null,
9
+ callbacks: [],
10
+ load() {
11
+ return typeof window > "u" || typeof document > "u" ? Promise.reject(new Error("Google Sign-In script loader cannot run in SSR")) : this.loaded ? Promise.resolve() : this.loading ? new Promise((e, i) => {
12
+ this.callbacks.push({ resolve: e, reject: i });
13
+ }) : (this.loading = !0, new Promise((e, i) => {
14
+ this.callbacks.push({ resolve: e, reject: i });
15
+ const d = document.getElementById("google-gsi-script");
16
+ if (d) {
17
+ window.google?.accounts?.id ? (this.loaded = !0, this.loading = !1, this.callbacks.forEach((o) => o.resolve()), this.callbacks = []) : d.addEventListener("load", () => {
18
+ this.loaded = !0, this.loading = !1, this.callbacks.forEach((o) => o.resolve()), this.callbacks = [];
19
+ });
20
+ return;
21
+ }
22
+ const n = document.createElement("script");
23
+ n.src = "https://accounts.google.com/gsi/client", n.async = !0, n.defer = !0, n.id = "google-gsi-script", n.onload = () => {
24
+ this.loaded = !0, this.loading = !1, this.callbacks.forEach((o) => o.resolve()), this.callbacks = [];
25
+ }, n.onerror = () => {
26
+ this.loading = !1, n.remove();
27
+ const o = new Error("Failed to load Google Sign-In script");
28
+ this.callbacks.forEach((g) => g.reject(o)), this.callbacks = [];
29
+ }, document.head.appendChild(n);
30
+ }));
31
+ },
32
+ /**
33
+ * Reset singleton state for test isolation (F-08)
34
+ * @internal - Only use in test setup/teardown
35
+ */
36
+ _reset() {
37
+ this.loading = !1, this.loaded = !1, this.error = null, this.callbacks = [];
38
+ }
39
+ };
40
+ function O() {
41
+ const { config: e, _internal: i } = S(), [d, n] = m(!1), [o, g] = m(!1), [b, s] = m(null), [k, h] = m(null), a = w(null), E = w(e), c = w(null), f = G(
42
+ () => new _({
43
+ baseUrl: e.serverUrl,
44
+ timeoutMs: e.requestTimeout,
45
+ retryAttempts: e.retryAttempts
46
+ }),
47
+ [e.serverUrl, e.requestTimeout, e.retryAttempts]
48
+ );
49
+ y(() => {
50
+ E.current = e;
51
+ }, [e]);
52
+ const I = p(
53
+ async (t) => {
54
+ const r = a.current;
55
+ if (r) {
56
+ if (t.error) {
57
+ const l = {
58
+ code: "SERVER_ERROR",
59
+ message: t.error === "access_denied" ? "Google sign-in was cancelled." : "Unable to sign in with Google. Please try again."
60
+ };
61
+ s(l), n(!1), a.current = null, r.reject(l);
62
+ return;
63
+ }
64
+ try {
65
+ const l = await f.post("/google", {
66
+ accessToken: t.access_token
67
+ });
68
+ E.current.callbacks?.onLoginSuccess?.(l.user, "google"), i?.handleLoginSuccess(l.user, l.tokens), n(!1), r.resolve(l);
69
+ } catch (l) {
70
+ const R = T(l, "Unable to sign in with Google. Please try again.");
71
+ R.code === "ACCOUNT_LINK_REQUIRED" && h(t.access_token ?? null), s(R), n(!1), r.reject(R);
72
+ } finally {
73
+ a.current = null;
74
+ }
75
+ }
76
+ },
77
+ [f, i]
78
+ );
79
+ y(() => {
80
+ if (!e.googleClientId)
81
+ return;
82
+ let t = !0;
83
+ return z.load().then(() => {
84
+ if (!t) return;
85
+ const r = window.google?.accounts?.oauth2?.initTokenClient({
86
+ client_id: e.googleClientId,
87
+ scope: "openid email profile",
88
+ callback: I
89
+ });
90
+ r && (c.current = r, g(!0));
91
+ }).catch(() => {
92
+ t && s({
93
+ code: "SERVER_ERROR",
94
+ message: "Unable to load Google sign-in. Please refresh and try again."
95
+ });
96
+ }), () => {
97
+ t = !1, c.current = null;
98
+ };
99
+ }, [e.googleClientId, I]);
100
+ const A = p(async () => {
101
+ if (!e.googleClientId) {
102
+ const t = {
103
+ code: "VALIDATION_ERROR",
104
+ message: "Google Client ID not configured"
105
+ };
106
+ throw s(t), t;
107
+ }
108
+ if (!o) {
109
+ const t = {
110
+ code: "VALIDATION_ERROR",
111
+ message: "Google sign-in is not ready yet. Please wait a moment and try again."
112
+ };
113
+ throw s(t), t;
114
+ }
115
+ if (a.current) {
116
+ const t = {
117
+ code: "VALIDATION_ERROR",
118
+ message: "Google sign-in is already in progress."
119
+ };
120
+ throw s(t), t;
121
+ }
122
+ return n(!0), s(null), new Promise((t, r) => {
123
+ a.current = { resolve: t, reject: r }, c.current?.requestAccessToken();
124
+ });
125
+ }, [e.googleClientId, o]), L = p(() => s(null), []), v = p(() => h(null), []);
126
+ return {
127
+ signIn: A,
128
+ isLoading: d,
129
+ isInitialized: o,
130
+ error: b,
131
+ clearError: L,
132
+ pendingLinkIdToken: k,
133
+ clearPendingLink: v
134
+ };
135
+ }
136
+ function V({
137
+ onSuccess: e,
138
+ onError: i,
139
+ className: d = "",
140
+ variant: n = "default",
141
+ size: o = "md",
142
+ disabled: g = !1
143
+ }) {
144
+ const { signIn: b, isLoading: s, isInitialized: k } = O(), h = async () => {
145
+ try {
146
+ await b(), e?.();
147
+ } catch (c) {
148
+ const f = c instanceof Error ? c : new Error(String(c));
149
+ i?.(f);
150
+ }
151
+ }, a = {
152
+ sm: "cedros-button-sm",
153
+ md: "cedros-button-md",
154
+ lg: "cedros-button-lg"
155
+ };
156
+ return /* @__PURE__ */ C(
157
+ "button",
158
+ {
159
+ type: "button",
160
+ className: `cedros-button ${{
161
+ default: "cedros-button-social",
162
+ outline: "cedros-button-social-outline"
163
+ }[n]} ${a[o]} ${d}`,
164
+ onClick: h,
165
+ disabled: g || !k || s,
166
+ "aria-label": "Sign in with Google",
167
+ children: [
168
+ s ? /* @__PURE__ */ u(P, { size: "sm" }) : /* @__PURE__ */ C(
169
+ "svg",
170
+ {
171
+ className: "cedros-button-icon",
172
+ width: "18",
173
+ height: "18",
174
+ viewBox: "0 0 18 18",
175
+ fill: "none",
176
+ "aria-hidden": "true",
177
+ children: [
178
+ /* @__PURE__ */ u(
179
+ "path",
180
+ {
181
+ d: "M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z",
182
+ fill: "#4285F4"
183
+ }
184
+ ),
185
+ /* @__PURE__ */ u(
186
+ "path",
187
+ {
188
+ d: "M9.003 18c2.43 0 4.467-.806 5.956-2.18l-2.909-2.26c-.806.54-1.836.86-3.047.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332A8.997 8.997 0 0 0 9.003 18z",
189
+ fill: "#34A853"
190
+ }
191
+ ),
192
+ /* @__PURE__ */ u(
193
+ "path",
194
+ {
195
+ d: "M3.964 10.712A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.96A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.96 4.042l3.004-2.33z",
196
+ fill: "#FBBC05"
197
+ }
198
+ ),
199
+ /* @__PURE__ */ u(
200
+ "path",
201
+ {
202
+ d: "M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.428 0 9.002 0A8.997 8.997 0 0 0 .96 4.958l3.005 2.332c.708-2.127 2.692-3.71 5.036-3.71z",
203
+ fill: "#EA4335"
204
+ }
205
+ )
206
+ ]
207
+ }
208
+ ),
209
+ /* @__PURE__ */ u("span", { children: "Continue with Google" })
210
+ ]
211
+ }
212
+ );
213
+ }
214
+ export {
215
+ V as G,
216
+ O as u
217
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GoogleLoginButton-CFlqxvU-.js","sources":["../src/hooks/useGoogleAuth.ts","../src/components/google/GoogleLoginButton.tsx"],"sourcesContent":["import { useState, useCallback, useEffect, useRef, useMemo } from 'react';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { ApiClient, handleApiError } from '../utils/apiClient';\nimport type { AuthResponse, AuthError } from '../types';\n\n/**\n * Module-level singleton for Google script loading (P-01)\n *\n * Prevents race conditions when multiple components mount simultaneously.\n * Uses a promise queue pattern to ensure the script is only loaded once.\n *\n * ## SSR Limitations (F-08)\n *\n * This singleton persists across the module lifecycle. In SSR environments:\n * - Module state persists between requests (potential cross-request leakage)\n * - Google Sign-In requires browser APIs (document, window)\n * - The hook guards against SSR with `googleClientId` checks\n *\n * For SSR frameworks (Next.js, Remix), ensure this hook is only used\n * in client-side components.\n *\n * ## Test Isolation\n *\n * For test isolation, call `scriptLoader._reset()` in test setup/teardown.\n *\n * @internal\n */\nconst scriptLoader = {\n loading: false,\n loaded: false,\n error: null as Error | null,\n callbacks: [] as Array<{ resolve: () => void; reject: (err: Error) => void }>,\n\n load(): Promise<void> {\n // SSR guard: avoid touching browser globals when running in Node/SSR.\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return Promise.reject(new Error('Google Sign-In script loader cannot run in SSR'));\n }\n\n // Already loaded\n if (this.loaded) {\n return Promise.resolve();\n }\n\n // Loading in progress - queue callback\n if (this.loading) {\n return new Promise((resolve, reject) => {\n this.callbacks.push({ resolve, reject });\n });\n }\n\n // Start loading\n this.loading = true;\n return new Promise((resolve, reject) => {\n this.callbacks.push({ resolve, reject });\n\n // Check if script already exists (from previous session or SSR)\n const existingScript = document.getElementById('google-gsi-script');\n if (existingScript) {\n if (window.google?.accounts?.id) {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n } else {\n existingScript.addEventListener('load', () => {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n });\n }\n return;\n }\n\n const script = document.createElement('script');\n script.src = 'https://accounts.google.com/gsi/client';\n script.async = true;\n script.defer = true;\n script.id = 'google-gsi-script';\n\n script.onload = () => {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n };\n\n script.onerror = () => {\n this.loading = false;\n // M-02: Remove failed script from DOM to allow retry on next load() call.\n // Without removal, retry finds existingScript and waits for a load event\n // that will never fire on an already-failed script.\n script.remove();\n const error = new Error('Failed to load Google Sign-In script');\n this.callbacks.forEach((cb) => cb.reject(error));\n this.callbacks = [];\n };\n\n document.head.appendChild(script);\n });\n },\n\n /**\n * Reset singleton state for test isolation (F-08)\n * @internal - Only use in test setup/teardown\n */\n _reset(): void {\n this.loading = false;\n this.loaded = false;\n this.error = null;\n this.callbacks = [];\n },\n};\n\n/** @internal */\nexport const _internalGoogleScriptLoader = scriptLoader;\n\nexport interface UseGoogleAuthReturn {\n signIn: () => Promise<AuthResponse>;\n isLoading: boolean;\n isInitialized: boolean;\n error: AuthError | null;\n clearError: () => void;\n /** ID token saved when ACCOUNT_LINK_REQUIRED is returned. Pass to POST /auth/link-oauth with the user's password. */\n pendingLinkIdToken: string | null;\n /** Clear the pending link state */\n clearPendingLink: () => void;\n}\n\ninterface PromiseCallbacks {\n resolve: (value: AuthResponse) => void;\n reject: (error: AuthError) => void;\n}\n\n/**\n * Hook for Google OAuth authentication.\n *\n * @example\n * ```tsx\n * function GoogleButton() {\n * const { signIn, isLoading, isInitialized, error } = useGoogleAuth();\n *\n * return (\n * <button onClick={signIn} disabled={!isInitialized || isLoading}>\n * {isLoading ? 'Signing in...' : 'Sign in with Google'}\n * </button>\n * );\n * }\n * ```\n */\nexport function useGoogleAuth(): UseGoogleAuthReturn {\n const { config, _internal } = useCedrosLogin();\n const [isLoading, setIsLoading] = useState(false);\n const [isInitialized, setIsInitialized] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n\n const [pendingLinkIdToken, setPendingLinkIdToken] = useState<string | null>(null);\n\n const promiseCallbacksRef = useRef<PromiseCallbacks | null>(null);\n const configRef = useRef(config);\n const tokenClientRef = useRef<GoogleTokenClient | null>(null);\n\n const apiClient = useMemo(\n () =>\n new ApiClient({\n baseUrl: config.serverUrl,\n timeoutMs: config.requestTimeout,\n retryAttempts: config.retryAttempts,\n }),\n [config.serverUrl, config.requestTimeout, config.retryAttempts]\n );\n\n // Keep config ref in sync\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n // Handle access token from OAuth popup (initTokenClient flow)\n const handleTokenResponse = useCallback(\n async (response: GoogleTokenResponse) => {\n const callbacks = promiseCallbacksRef.current;\n if (!callbacks) return;\n\n if (response.error) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: response.error === 'access_denied'\n ? 'Google sign-in was cancelled.'\n : 'Unable to sign in with Google. Please try again.',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n callbacks.reject(err);\n return;\n }\n\n try {\n const data = await apiClient.post<AuthResponse>('/google', {\n accessToken: response.access_token,\n });\n configRef.current.callbacks?.onLoginSuccess?.(data.user, 'google');\n _internal?.handleLoginSuccess(data.user, data.tokens);\n setIsLoading(false);\n callbacks.resolve(data);\n } catch (err) {\n const authError = handleApiError(err, 'Unable to sign in with Google. Please try again.');\n if (authError.code === 'ACCOUNT_LINK_REQUIRED') {\n setPendingLinkIdToken(response.access_token ?? null);\n }\n setError(authError);\n setIsLoading(false);\n callbacks.reject(authError);\n } finally {\n promiseCallbacksRef.current = null;\n }\n },\n [apiClient, _internal]\n );\n\n // P-01: Initialize Google OAuth token client using singleton loader.\n // Uses initTokenClient (OAuth popup) instead of One Tap prompt() which\n // has exponential cooldown after dismissal and is blocked by Brave.\n useEffect(() => {\n if (!config.googleClientId) {\n return;\n }\n\n let isMounted = true;\n\n scriptLoader\n .load()\n .then(() => {\n if (!isMounted) return;\n\n const client = window.google?.accounts?.oauth2?.initTokenClient({\n client_id: config.googleClientId!,\n scope: 'openid email profile',\n callback: handleTokenResponse,\n });\n\n if (client) {\n tokenClientRef.current = client;\n setIsInitialized(true);\n }\n })\n .catch(() => {\n if (isMounted) {\n setError({\n code: 'SERVER_ERROR',\n message: 'Unable to load Google sign-in. Please refresh and try again.',\n });\n }\n });\n\n return () => {\n isMounted = false;\n tokenClientRef.current = null;\n };\n }, [config.googleClientId, handleTokenResponse]);\n\n const signIn = useCallback(async (): Promise<AuthResponse> => {\n if (!config.googleClientId) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Client ID not configured',\n };\n setError(err);\n throw err;\n }\n\n if (!isInitialized) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google sign-in is not ready yet. Please wait a moment and try again.',\n };\n setError(err);\n throw err;\n }\n\n if (promiseCallbacksRef.current) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google sign-in is already in progress.',\n };\n setError(err);\n throw err;\n }\n\n setIsLoading(true);\n setError(null);\n\n return new Promise<AuthResponse>((resolve, reject) => {\n promiseCallbacksRef.current = { resolve, reject };\n\n // Open the Google OAuth popup via initTokenClient.\n // This avoids One Tap's exponential cooldown after dismissal and works\n // in browsers that block One Tap (e.g., Brave).\n tokenClientRef.current?.requestAccessToken();\n });\n }, [config.googleClientId, isInitialized]);\n\n const clearError = useCallback(() => setError(null), []);\n const clearPendingLink = useCallback(() => setPendingLinkIdToken(null), []);\n\n return {\n signIn,\n isLoading,\n isInitialized,\n error,\n clearError,\n pendingLinkIdToken,\n clearPendingLink,\n };\n}\n\n/** Response from Google's initTokenClient callback */\ninterface GoogleTokenResponse {\n access_token?: string;\n error?: string;\n error_description?: string;\n}\n\n/** Token client returned by google.accounts.oauth2.initTokenClient */\ninterface GoogleTokenClient {\n requestAccessToken: () => void;\n}\n\n// Type declaration for Google Identity Services\ndeclare global {\n interface Window {\n google?: {\n accounts?: {\n /** Used only to detect if the GIS script has loaded */\n id?: object;\n oauth2?: {\n initTokenClient: (config: {\n client_id: string;\n scope: string;\n callback: (response: GoogleTokenResponse) => void;\n }) => GoogleTokenClient;\n };\n };\n };\n }\n}\n","import { useGoogleAuth } from '../../hooks/useGoogleAuth';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\n\nexport interface GoogleLoginButtonProps {\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n className?: string;\n variant?: 'default' | 'outline';\n size?: 'sm' | 'md' | 'lg';\n disabled?: boolean;\n}\n\n/**\n * Google OAuth login button\n */\nexport function GoogleLoginButton({\n onSuccess,\n onError,\n className = '',\n variant = 'default',\n size = 'md',\n disabled = false,\n}: GoogleLoginButtonProps) {\n const { signIn, isLoading, isInitialized } = useGoogleAuth();\n\n const handleClick = async () => {\n try {\n await signIn();\n onSuccess?.();\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n onError?.(error);\n }\n };\n\n const sizeClasses = {\n sm: 'cedros-button-sm',\n md: 'cedros-button-md',\n lg: 'cedros-button-lg',\n };\n\n const variantClasses = {\n default: 'cedros-button-social',\n outline: 'cedros-button-social-outline',\n };\n\n return (\n <button\n type=\"button\"\n className={`cedros-button ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}\n onClick={handleClick}\n disabled={disabled || !isInitialized || isLoading}\n aria-label=\"Sign in with Google\"\n >\n {isLoading ? (\n <LoadingSpinner size=\"sm\" />\n ) : (\n <svg\n className=\"cedros-button-icon\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z\"\n fill=\"#4285F4\"\n />\n <path\n d=\"M9.003 18c2.43 0 4.467-.806 5.956-2.18l-2.909-2.26c-.806.54-1.836.86-3.047.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332A8.997 8.997 0 0 0 9.003 18z\"\n fill=\"#34A853\"\n />\n <path\n d=\"M3.964 10.712A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.96A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.96 4.042l3.004-2.33z\"\n fill=\"#FBBC05\"\n />\n <path\n d=\"M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.428 0 9.002 0A8.997 8.997 0 0 0 .96 4.958l3.005 2.332c.708-2.127 2.692-3.71 5.036-3.71z\"\n fill=\"#EA4335\"\n />\n </svg>\n )}\n <span>Continue with Google</span>\n </button>\n );\n}\n"],"names":["scriptLoader","resolve","reject","existingScript","cb","script","error","useGoogleAuth","config","_internal","useCedrosLogin","isLoading","setIsLoading","useState","isInitialized","setIsInitialized","setError","pendingLinkIdToken","setPendingLinkIdToken","promiseCallbacksRef","useRef","configRef","tokenClientRef","apiClient","useMemo","ApiClient","useEffect","handleTokenResponse","useCallback","response","callbacks","err","data","authError","handleApiError","isMounted","client","signIn","clearError","clearPendingLink","GoogleLoginButton","onSuccess","onError","className","variant","size","disabled","handleClick","sizeClasses","jsxs","jsx","LoadingSpinner"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"LoadingSpinner-6vml-zwr.js","sources":["../src/context/CedrosLoginContext.ts","../src/components/shared/LoadingSpinner.tsx"],"sourcesContent":["import { createContext } from 'react';\nimport type { CedrosLoginConfig, AuthUser, AuthState, AuthError, TokenPair } from '../types';\n\n/**\n * Internal helpers for auth hooks (not part of public API)\n */\nexport interface CedrosLoginInternalAPI {\n handleLoginSuccess: (user: AuthUser, tokens?: TokenPair) => void;\n getAccessToken: () => string | null;\n}\n\n/**\n * Auth state context — changes only on login/logout/token refresh.\n *\n * Subscribing to this context alone avoids re-renders from UI state\n * changes (modal open/close, error display).\n */\nexport interface AuthStateContextValue {\n config: CedrosLoginConfig;\n user: AuthUser | null;\n authState: AuthState;\n logout: () => Promise<void>;\n refreshUser: () => Promise<void>;\n _internal?: CedrosLoginInternalAPI;\n}\n\n/**\n * UI state context — changes on modal/error state changes.\n *\n * Subscribing to this context alone avoids re-renders from auth state\n * changes (login, token refresh).\n */\nexport interface AuthUIContextValue {\n error: AuthError | null;\n isModalOpen: boolean;\n openModal: () => void;\n closeModal: () => void;\n}\n\n/**\n * Combined context value (backward-compatible with existing consumers)\n */\nexport interface CedrosLoginContextValue extends AuthStateContextValue, AuthUIContextValue {}\n\nexport const AuthStateContext = createContext<AuthStateContextValue | null>(null);\nexport const AuthUIContext = createContext<AuthUIContextValue | null>(null);\n\n/**\n * @deprecated Use AuthStateContext + AuthUIContext directly for better performance.\n * Kept for backward compatibility with useCedrosLogin.\n */\nexport const CedrosLoginContext = createContext<CedrosLoginContextValue | null>(null);\n","import { memo, type CSSProperties } from 'react';\n\nexport interface LoadingSpinnerProps {\n size?: 'sm' | 'md' | 'lg' | 'xl';\n className?: string;\n style?: CSSProperties;\n /** Custom label for screen readers (default: \"Loading\") */\n label?: string;\n /** If true, announce the loading state to screen readers */\n announce?: boolean;\n}\n\nconst sizeMap = {\n sm: 16,\n md: 24,\n lg: 32,\n xl: 48, // H-04: Added for WalletUnlock component\n};\n\n/**\n * Accessible loading spinner component.\n * Announces loading state to screen readers when announce prop is true.\n * Wrapped with React.memo to prevent unnecessary re-renders.\n */\nexport const LoadingSpinner = memo(function LoadingSpinner({\n size = 'md',\n className = '',\n style,\n label = 'Loading',\n announce = false,\n}: LoadingSpinnerProps) {\n const dimension = sizeMap[size];\n\n const spinner = (\n <svg\n className={`cedros-spinner ${className}`}\n width={dimension}\n height={dimension}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n style={style}\n aria-label={label}\n role=\"status\"\n aria-hidden={announce ? 'true' : undefined}\n >\n <circle\n className=\"cedros-spinner-track\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeOpacity=\"0.25\"\n />\n <circle\n className=\"cedros-spinner-head\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeDasharray=\"31.4 31.4\"\n transform=\"rotate(-90 12 12)\"\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 12 12\"\n to=\"360 12 12\"\n dur=\"1s\"\n repeatCount=\"indefinite\"\n />\n </circle>\n </svg>\n );\n\n // Wrap in aria-live region if announce is true\n if (announce) {\n return (\n <span aria-live=\"polite\" aria-busy=\"true\">\n {spinner}\n <span className=\"cedros-sr-only\">{label}</span>\n </span>\n );\n }\n\n return spinner;\n});\n"],"names":["AuthStateContext","createContext","AuthUIContext","CedrosLoginContext","sizeMap","LoadingSpinner","memo","size","className","style","label","announce","dimension","spinner","jsxs","jsx"],"mappings":";;AA4CO,MAAMA,IAAmBC,EAA4C,IAAI,GACnEC,IAAgBD,EAAyC,IAAI,GAM7DE,IAAqBF,EAA8C,IAAI,GCvC9EG,IAAU;AAAA,EACd,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA;AACN,GAOaC,IAAiBC,EAAK,SAAwB;AAAA,EACzD,MAAAC,IAAO;AAAA,EACP,WAAAC,IAAY;AAAA,EACZ,OAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,UAAAC,IAAW;AACb,GAAwB;AACtB,QAAMC,IAAYR,EAAQG,CAAI,GAExBM,IACJ,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,kBAAkBN,CAAS;AAAA,MACtC,OAAOI;AAAA,MACP,QAAQA;AAAA,MACR,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,OAAAH;AAAA,MACA,cAAYC;AAAA,MACZ,MAAK;AAAA,MACL,eAAaC,IAAW,SAAS;AAAA,MAEjC,UAAA;AAAA,QAAA,gBAAAI;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,IAAG;AAAA,YACH,IAAG;AAAA,YACH,GAAE;AAAA,YACF,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAc;AAAA,UAAA;AAAA,QAAA;AAAA,QAEhB,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,IAAG;AAAA,YACH,IAAG;AAAA,YACH,GAAE;AAAA,YACF,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAc;AAAA,YACd,iBAAgB;AAAA,YAChB,WAAU;AAAA,YAEV,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL,IAAG;AAAA,gBACH,KAAI;AAAA,gBACJ,aAAY;AAAA,cAAA;AAAA,YAAA;AAAA,UACd;AAAA,QAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAAA;AAKJ,SAAIJ,IAEA,gBAAAG,EAAC,QAAA,EAAK,aAAU,UAAS,aAAU,QAChC,UAAA;AAAA,IAAAD;AAAA,IACD,gBAAAE,EAAC,QAAA,EAAK,WAAU,kBAAkB,UAAAL,EAAA,CAAM;AAAA,EAAA,GAC1C,IAIGG;AACT,CAAC;"}
1
+ {"version":3,"file":"LoadingSpinner-6vml-zwr.js","sources":["../src/context/CedrosLoginContext.ts","../src/components/shared/LoadingSpinner.tsx"],"sourcesContent":["import { createContext } from 'react';\nimport type { CedrosLoginConfig, AuthUser, AuthState, AuthError, TokenPair } from '../types';\n\n/**\n * Internal helpers for auth hooks (not part of public API)\n */\nexport interface CedrosLoginInternalAPI {\n handleLoginSuccess: (user: AuthUser, tokens?: TokenPair) => void;\n getAccessToken: () => string | null;\n}\n\n/**\n * Auth state context — changes only on login/logout/token refresh.\n *\n * Subscribing to this context alone avoids re-renders from UI state\n * changes (modal open/close, error display).\n */\nexport interface AuthStateContextValue {\n config: CedrosLoginConfig;\n user: AuthUser | null;\n authState: AuthState;\n logout: () => Promise<void>;\n refreshUser: () => Promise<void>;\n /** Display order for social login buttons (from server auto-discovery). */\n socialButtonOrder?: string[];\n _internal?: CedrosLoginInternalAPI;\n}\n\n/**\n * UI state context — changes on modal/error state changes.\n *\n * Subscribing to this context alone avoids re-renders from auth state\n * changes (login, token refresh).\n */\nexport interface AuthUIContextValue {\n error: AuthError | null;\n isModalOpen: boolean;\n openModal: () => void;\n closeModal: () => void;\n}\n\n/**\n * Combined context value (backward-compatible with existing consumers)\n */\nexport interface CedrosLoginContextValue extends AuthStateContextValue, AuthUIContextValue {}\n\nexport const AuthStateContext = createContext<AuthStateContextValue | null>(null);\nexport const AuthUIContext = createContext<AuthUIContextValue | null>(null);\n\n/**\n * @deprecated Use AuthStateContext + AuthUIContext directly for better performance.\n * Kept for backward compatibility with useCedrosLogin.\n */\nexport const CedrosLoginContext = createContext<CedrosLoginContextValue | null>(null);\n","import { memo, type CSSProperties } from 'react';\n\nexport interface LoadingSpinnerProps {\n size?: 'sm' | 'md' | 'lg' | 'xl';\n className?: string;\n style?: CSSProperties;\n /** Custom label for screen readers (default: \"Loading\") */\n label?: string;\n /** If true, announce the loading state to screen readers */\n announce?: boolean;\n}\n\nconst sizeMap = {\n sm: 16,\n md: 24,\n lg: 32,\n xl: 48, // H-04: Added for WalletUnlock component\n};\n\n/**\n * Accessible loading spinner component.\n * Announces loading state to screen readers when announce prop is true.\n * Wrapped with React.memo to prevent unnecessary re-renders.\n */\nexport const LoadingSpinner = memo(function LoadingSpinner({\n size = 'md',\n className = '',\n style,\n label = 'Loading',\n announce = false,\n}: LoadingSpinnerProps) {\n const dimension = sizeMap[size];\n\n const spinner = (\n <svg\n className={`cedros-spinner ${className}`}\n width={dimension}\n height={dimension}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n style={style}\n aria-label={label}\n role=\"status\"\n aria-hidden={announce ? 'true' : undefined}\n >\n <circle\n className=\"cedros-spinner-track\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeOpacity=\"0.25\"\n />\n <circle\n className=\"cedros-spinner-head\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeDasharray=\"31.4 31.4\"\n transform=\"rotate(-90 12 12)\"\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 12 12\"\n to=\"360 12 12\"\n dur=\"1s\"\n repeatCount=\"indefinite\"\n />\n </circle>\n </svg>\n );\n\n // Wrap in aria-live region if announce is true\n if (announce) {\n return (\n <span aria-live=\"polite\" aria-busy=\"true\">\n {spinner}\n <span className=\"cedros-sr-only\">{label}</span>\n </span>\n );\n }\n\n return spinner;\n});\n"],"names":["AuthStateContext","createContext","AuthUIContext","CedrosLoginContext","sizeMap","LoadingSpinner","memo","size","className","style","label","announce","dimension","spinner","jsxs","jsx"],"mappings":";;AA8CO,MAAMA,IAAmBC,EAA4C,IAAI,GACnEC,IAAgBD,EAAyC,IAAI,GAM7DE,IAAqBF,EAA8C,IAAI,GCzC9EG,IAAU;AAAA,EACd,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA;AACN,GAOaC,IAAiBC,EAAK,SAAwB;AAAA,EACzD,MAAAC,IAAO;AAAA,EACP,WAAAC,IAAY;AAAA,EACZ,OAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,UAAAC,IAAW;AACb,GAAwB;AACtB,QAAMC,IAAYR,EAAQG,CAAI,GAExBM,IACJ,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,kBAAkBN,CAAS;AAAA,MACtC,OAAOI;AAAA,MACP,QAAQA;AAAA,MACR,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,OAAAH;AAAA,MACA,cAAYC;AAAA,MACZ,MAAK;AAAA,MACL,eAAaC,IAAW,SAAS;AAAA,MAEjC,UAAA;AAAA,QAAA,gBAAAI;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,IAAG;AAAA,YACH,IAAG;AAAA,YACH,GAAE;AAAA,YACF,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAc;AAAA,UAAA;AAAA,QAAA;AAAA,QAEhB,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,IAAG;AAAA,YACH,IAAG;AAAA,YACH,GAAE;AAAA,YACF,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAc;AAAA,YACd,iBAAgB;AAAA,YAChB,WAAU;AAAA,YAEV,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL,IAAG;AAAA,gBACH,KAAI;AAAA,gBACJ,aAAY;AAAA,cAAA;AAAA,YAAA;AAAA,UACd;AAAA,QAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAAA;AAKJ,SAAIJ,IAEA,gBAAAG,EAAC,QAAA,EAAK,aAAU,UAAS,aAAU,QAChC,UAAA;AAAA,IAAAD;AAAA,IACD,gBAAAE,EAAC,QAAA,EAAK,WAAU,kBAAkB,UAAAL,EAAA,CAAM;AAAA,EAAA,GAC1C,IAIGG;AACT,CAAC;"}
@@ -1 +1 @@
1
- {"version":3,"file":"LoadingSpinner-d6sSxgQN.cjs","sources":["../src/context/CedrosLoginContext.ts","../src/components/shared/LoadingSpinner.tsx"],"sourcesContent":["import { createContext } from 'react';\nimport type { CedrosLoginConfig, AuthUser, AuthState, AuthError, TokenPair } from '../types';\n\n/**\n * Internal helpers for auth hooks (not part of public API)\n */\nexport interface CedrosLoginInternalAPI {\n handleLoginSuccess: (user: AuthUser, tokens?: TokenPair) => void;\n getAccessToken: () => string | null;\n}\n\n/**\n * Auth state context — changes only on login/logout/token refresh.\n *\n * Subscribing to this context alone avoids re-renders from UI state\n * changes (modal open/close, error display).\n */\nexport interface AuthStateContextValue {\n config: CedrosLoginConfig;\n user: AuthUser | null;\n authState: AuthState;\n logout: () => Promise<void>;\n refreshUser: () => Promise<void>;\n _internal?: CedrosLoginInternalAPI;\n}\n\n/**\n * UI state context — changes on modal/error state changes.\n *\n * Subscribing to this context alone avoids re-renders from auth state\n * changes (login, token refresh).\n */\nexport interface AuthUIContextValue {\n error: AuthError | null;\n isModalOpen: boolean;\n openModal: () => void;\n closeModal: () => void;\n}\n\n/**\n * Combined context value (backward-compatible with existing consumers)\n */\nexport interface CedrosLoginContextValue extends AuthStateContextValue, AuthUIContextValue {}\n\nexport const AuthStateContext = createContext<AuthStateContextValue | null>(null);\nexport const AuthUIContext = createContext<AuthUIContextValue | null>(null);\n\n/**\n * @deprecated Use AuthStateContext + AuthUIContext directly for better performance.\n * Kept for backward compatibility with useCedrosLogin.\n */\nexport const CedrosLoginContext = createContext<CedrosLoginContextValue | null>(null);\n","import { memo, type CSSProperties } from 'react';\n\nexport interface LoadingSpinnerProps {\n size?: 'sm' | 'md' | 'lg' | 'xl';\n className?: string;\n style?: CSSProperties;\n /** Custom label for screen readers (default: \"Loading\") */\n label?: string;\n /** If true, announce the loading state to screen readers */\n announce?: boolean;\n}\n\nconst sizeMap = {\n sm: 16,\n md: 24,\n lg: 32,\n xl: 48, // H-04: Added for WalletUnlock component\n};\n\n/**\n * Accessible loading spinner component.\n * Announces loading state to screen readers when announce prop is true.\n * Wrapped with React.memo to prevent unnecessary re-renders.\n */\nexport const LoadingSpinner = memo(function LoadingSpinner({\n size = 'md',\n className = '',\n style,\n label = 'Loading',\n announce = false,\n}: LoadingSpinnerProps) {\n const dimension = sizeMap[size];\n\n const spinner = (\n <svg\n className={`cedros-spinner ${className}`}\n width={dimension}\n height={dimension}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n style={style}\n aria-label={label}\n role=\"status\"\n aria-hidden={announce ? 'true' : undefined}\n >\n <circle\n className=\"cedros-spinner-track\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeOpacity=\"0.25\"\n />\n <circle\n className=\"cedros-spinner-head\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeDasharray=\"31.4 31.4\"\n transform=\"rotate(-90 12 12)\"\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 12 12\"\n to=\"360 12 12\"\n dur=\"1s\"\n repeatCount=\"indefinite\"\n />\n </circle>\n </svg>\n );\n\n // Wrap in aria-live region if announce is true\n if (announce) {\n return (\n <span aria-live=\"polite\" aria-busy=\"true\">\n {spinner}\n <span className=\"cedros-sr-only\">{label}</span>\n </span>\n );\n }\n\n return spinner;\n});\n"],"names":["AuthStateContext","createContext","AuthUIContext","CedrosLoginContext","sizeMap","LoadingSpinner","memo","size","className","style","label","announce","dimension","spinner","jsxs","jsx"],"mappings":"qEA4CaA,EAAmBC,EAAAA,cAA4C,IAAI,EACnEC,EAAgBD,EAAAA,cAAyC,IAAI,EAM7DE,EAAqBF,EAAAA,cAA8C,IAAI,ECvC9EG,EAAU,CACd,GAAI,GACJ,GAAI,GACJ,GAAI,GACJ,GAAI,EACN,EAOaC,EAAiBC,EAAAA,KAAK,SAAwB,CACzD,KAAAC,EAAO,KACP,UAAAC,EAAY,GACZ,MAAAC,EACA,MAAAC,EAAQ,UACR,SAAAC,EAAW,EACb,EAAwB,CACtB,MAAMC,EAAYR,EAAQG,CAAI,EAExBM,EACJC,EAAAA,KAAC,MAAA,CACC,UAAW,kBAAkBN,CAAS,GACtC,MAAOI,EACP,OAAQA,EACR,QAAQ,YACR,KAAK,OACL,MAAAH,EACA,aAAYC,EACZ,KAAK,SACL,cAAaC,EAAW,OAAS,OAEjC,SAAA,CAAAI,EAAAA,IAAC,SAAA,CACC,UAAU,uBACV,GAAG,KACH,GAAG,KACH,EAAE,KACF,OAAO,eACP,YAAY,IACZ,cAAc,MAAA,CAAA,EAEhBA,EAAAA,IAAC,SAAA,CACC,UAAU,sBACV,GAAG,KACH,GAAG,KACH,EAAE,KACF,OAAO,eACP,YAAY,IACZ,cAAc,QACd,gBAAgB,YAChB,UAAU,oBAEV,SAAAA,EAAAA,IAAC,mBAAA,CACC,cAAc,YACd,KAAK,SACL,KAAK,UACL,GAAG,YACH,IAAI,KACJ,YAAY,YAAA,CAAA,CACd,CAAA,CACF,CAAA,CAAA,EAKJ,OAAIJ,EAEAG,EAAAA,KAAC,OAAA,CAAK,YAAU,SAAS,YAAU,OAChC,SAAA,CAAAD,EACDE,EAAAA,IAAC,OAAA,CAAK,UAAU,iBAAkB,SAAAL,CAAA,CAAM,CAAA,EAC1C,EAIGG,CACT,CAAC"}
1
+ {"version":3,"file":"LoadingSpinner-d6sSxgQN.cjs","sources":["../src/context/CedrosLoginContext.ts","../src/components/shared/LoadingSpinner.tsx"],"sourcesContent":["import { createContext } from 'react';\nimport type { CedrosLoginConfig, AuthUser, AuthState, AuthError, TokenPair } from '../types';\n\n/**\n * Internal helpers for auth hooks (not part of public API)\n */\nexport interface CedrosLoginInternalAPI {\n handleLoginSuccess: (user: AuthUser, tokens?: TokenPair) => void;\n getAccessToken: () => string | null;\n}\n\n/**\n * Auth state context — changes only on login/logout/token refresh.\n *\n * Subscribing to this context alone avoids re-renders from UI state\n * changes (modal open/close, error display).\n */\nexport interface AuthStateContextValue {\n config: CedrosLoginConfig;\n user: AuthUser | null;\n authState: AuthState;\n logout: () => Promise<void>;\n refreshUser: () => Promise<void>;\n /** Display order for social login buttons (from server auto-discovery). */\n socialButtonOrder?: string[];\n _internal?: CedrosLoginInternalAPI;\n}\n\n/**\n * UI state context — changes on modal/error state changes.\n *\n * Subscribing to this context alone avoids re-renders from auth state\n * changes (login, token refresh).\n */\nexport interface AuthUIContextValue {\n error: AuthError | null;\n isModalOpen: boolean;\n openModal: () => void;\n closeModal: () => void;\n}\n\n/**\n * Combined context value (backward-compatible with existing consumers)\n */\nexport interface CedrosLoginContextValue extends AuthStateContextValue, AuthUIContextValue {}\n\nexport const AuthStateContext = createContext<AuthStateContextValue | null>(null);\nexport const AuthUIContext = createContext<AuthUIContextValue | null>(null);\n\n/**\n * @deprecated Use AuthStateContext + AuthUIContext directly for better performance.\n * Kept for backward compatibility with useCedrosLogin.\n */\nexport const CedrosLoginContext = createContext<CedrosLoginContextValue | null>(null);\n","import { memo, type CSSProperties } from 'react';\n\nexport interface LoadingSpinnerProps {\n size?: 'sm' | 'md' | 'lg' | 'xl';\n className?: string;\n style?: CSSProperties;\n /** Custom label for screen readers (default: \"Loading\") */\n label?: string;\n /** If true, announce the loading state to screen readers */\n announce?: boolean;\n}\n\nconst sizeMap = {\n sm: 16,\n md: 24,\n lg: 32,\n xl: 48, // H-04: Added for WalletUnlock component\n};\n\n/**\n * Accessible loading spinner component.\n * Announces loading state to screen readers when announce prop is true.\n * Wrapped with React.memo to prevent unnecessary re-renders.\n */\nexport const LoadingSpinner = memo(function LoadingSpinner({\n size = 'md',\n className = '',\n style,\n label = 'Loading',\n announce = false,\n}: LoadingSpinnerProps) {\n const dimension = sizeMap[size];\n\n const spinner = (\n <svg\n className={`cedros-spinner ${className}`}\n width={dimension}\n height={dimension}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n style={style}\n aria-label={label}\n role=\"status\"\n aria-hidden={announce ? 'true' : undefined}\n >\n <circle\n className=\"cedros-spinner-track\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeOpacity=\"0.25\"\n />\n <circle\n className=\"cedros-spinner-head\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeDasharray=\"31.4 31.4\"\n transform=\"rotate(-90 12 12)\"\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 12 12\"\n to=\"360 12 12\"\n dur=\"1s\"\n repeatCount=\"indefinite\"\n />\n </circle>\n </svg>\n );\n\n // Wrap in aria-live region if announce is true\n if (announce) {\n return (\n <span aria-live=\"polite\" aria-busy=\"true\">\n {spinner}\n <span className=\"cedros-sr-only\">{label}</span>\n </span>\n );\n }\n\n return spinner;\n});\n"],"names":["AuthStateContext","createContext","AuthUIContext","CedrosLoginContext","sizeMap","LoadingSpinner","memo","size","className","style","label","announce","dimension","spinner","jsxs","jsx"],"mappings":"qEA8CaA,EAAmBC,EAAAA,cAA4C,IAAI,EACnEC,EAAgBD,EAAAA,cAAyC,IAAI,EAM7DE,EAAqBF,EAAAA,cAA8C,IAAI,ECzC9EG,EAAU,CACd,GAAI,GACJ,GAAI,GACJ,GAAI,GACJ,GAAI,EACN,EAOaC,EAAiBC,EAAAA,KAAK,SAAwB,CACzD,KAAAC,EAAO,KACP,UAAAC,EAAY,GACZ,MAAAC,EACA,MAAAC,EAAQ,UACR,SAAAC,EAAW,EACb,EAAwB,CACtB,MAAMC,EAAYR,EAAQG,CAAI,EAExBM,EACJC,EAAAA,KAAC,MAAA,CACC,UAAW,kBAAkBN,CAAS,GACtC,MAAOI,EACP,OAAQA,EACR,QAAQ,YACR,KAAK,OACL,MAAAH,EACA,aAAYC,EACZ,KAAK,SACL,cAAaC,EAAW,OAAS,OAEjC,SAAA,CAAAI,EAAAA,IAAC,SAAA,CACC,UAAU,uBACV,GAAG,KACH,GAAG,KACH,EAAE,KACF,OAAO,eACP,YAAY,IACZ,cAAc,MAAA,CAAA,EAEhBA,EAAAA,IAAC,SAAA,CACC,UAAU,sBACV,GAAG,KACH,GAAG,KACH,EAAE,KACF,OAAO,eACP,YAAY,IACZ,cAAc,QACd,gBAAgB,YAChB,UAAU,oBAEV,SAAAA,EAAAA,IAAC,mBAAA,CACC,cAAc,YACd,KAAK,SACL,KAAK,UACL,GAAG,YACH,IAAI,KACJ,YAAY,YAAA,CAAA,CACd,CAAA,CACF,CAAA,CAAA,EAKJ,OAAIJ,EAEAG,EAAAA,KAAC,OAAA,CAAK,YAAU,SAAS,YAAU,OAChC,SAAA,CAAAD,EACDE,EAAAA,IAAC,OAAA,CAAK,UAAU,iBAAkB,SAAAL,CAAA,CAAM,CAAA,EAC1C,EAIGG,CACT,CAAC"}
@@ -1 +1 @@
1
- "use strict";const e=require("react/jsx-runtime"),r=require("react"),k=require("./LoadingSpinner-d6sSxgQN.cjs"),$=require("./ErrorMessage-CHbYbVi2.cjs"),D=require("./sanitization-Bo_tn-L2.cjs"),F=require("./validation-BuGQrA-K.cjs"),A=require("./useCedrosLogin-C9MrcZvh.cjs"),P=require("./useOrgs-DDVRCaVi.cjs"),q=require("./useSystemSettings-DRrreszl.cjs"),U=["owner","admin","member"];function z({members:s,currentUserId:t,isLoading:a=!1,error:i,canManage:n=!1,canChangeRoles:o=!1,onUpdateRole:f,onRemove:m,className:h=""}){const[l,j]=r.useState("name"),[d,y]=r.useState("asc"),p=u=>{l===u?y(d==="asc"?"desc":"asc"):(j(u),y("asc"))},c=r.useMemo(()=>{const u={owner:0,admin:1,member:2};return[...s].sort((g,b)=>{let S,w;switch(l){case"name":S=(g.user.name||g.user.email||"").toLowerCase(),w=(b.user.name||b.user.email||"").toLowerCase();break;case"role":S=u[g.role]??99,w=u[b.role]??99;break;case"joinedAt":S=new Date(g.joinedAt).getTime(),w=new Date(b.joinedAt).getTime();break;default:return 0}return S<w?d==="asc"?-1:1:S>w?d==="asc"?1:-1:0})},[s,l,d]);return a&&s.length===0?e.jsxs("div",{className:`cedros-member-list cedros-member-list-loading ${h}`,children:[e.jsx(k.LoadingSpinner,{}),e.jsx("span",{children:"Loading members..."})]}):i?e.jsx("div",{className:`cedros-member-list ${h}`,children:e.jsx($.ErrorMessage,{error:i})}):s.length===0?e.jsx("div",{className:`cedros-member-list cedros-member-list-empty ${h}`,children:e.jsx("p",{children:"No members found."})}):e.jsx("div",{className:`cedros-member-list ${h}`,children:e.jsxs("table",{className:"cedros-member-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:e.jsxs("button",{type:"button",className:`cedros-admin-sort-button ${l==="name"?"cedros-admin-sort-active":""}`,onClick:()=>p("name"),children:["Member"," ",e.jsx("span",{className:"cedros-admin-sort-icon",children:l==="name"?d==="asc"?"↑":"↓":"↕"})]})}),e.jsx("th",{children:e.jsxs("button",{type:"button",className:`cedros-admin-sort-button ${l==="role"?"cedros-admin-sort-active":""}`,onClick:()=>p("role"),children:["Role"," ",e.jsx("span",{className:"cedros-admin-sort-icon",children:l==="role"?d==="asc"?"↑":"↓":"↕"})]})}),e.jsx("th",{children:e.jsxs("button",{type:"button",className:`cedros-admin-sort-button ${l==="joinedAt"?"cedros-admin-sort-active":""}`,onClick:()=>p("joinedAt"),children:["Joined"," ",e.jsx("span",{className:"cedros-admin-sort-icon",children:l==="joinedAt"?d==="asc"?"↑":"↓":"↕"})]})}),(n||o)&&e.jsx("th",{children:"Actions"})]})}),e.jsx("tbody",{children:c.map(u=>e.jsx(B,{member:u,isCurrentUser:u.userId===t,canManage:n,canChangeRoles:o,onUpdateRole:f,onRemove:m},u.id))})]})})}function B({member:s,isCurrentUser:t,canManage:a,canChangeRoles:i,onUpdateRole:n,onRemove:o}){const[f,m]=r.useState(!1),[h,l]=r.useState(s.role),j=r.useCallback(async c=>{if(!(!n||c===s.role)){m(!0);try{await n(s.userId,c),l(c)}catch{l(s.role)}finally{m(!1)}}},[s.userId,s.role,n]),d=r.useCallback(async()=>{if(!(!o||!window.confirm(`Are you sure you want to remove ${s.user.name||s.user.email} from this organization?`))){m(!0);try{await o(s.userId)}finally{m(!1)}}},[s.userId,s.user.name,s.user.email,o]),y=s.role==="owner",p=!t&&!y;return e.jsxs("tr",{className:`cedros-member-row ${t?"cedros-member-row-current":""}`,children:[e.jsxs("td",{className:"cedros-member-info",children:[e.jsx(W,{user:s.user}),e.jsxs("div",{className:"cedros-member-details",children:[e.jsxs("span",{className:"cedros-member-name",children:[s.user.name||"Unknown",t&&e.jsx("span",{className:"cedros-member-you",children:"(you)"})]}),e.jsx("span",{className:"cedros-member-email",children:s.user.email})]})]}),e.jsx("td",{className:"cedros-member-role",children:i&&p&&n?e.jsx("select",{value:h,onChange:c=>j(c.target.value),disabled:f,className:"cedros-role-select",children:U.map(c=>e.jsx("option",{value:c,children:c.charAt(0).toUpperCase()+c.slice(1)},c))}):e.jsx("span",{className:`cedros-role-badge cedros-role-badge-${s.role}`,children:s.role.charAt(0).toUpperCase()+s.role.slice(1)})}),e.jsx("td",{className:"cedros-member-joined",children:H(s.joinedAt)}),(a||i)&&e.jsx("td",{className:"cedros-member-actions",children:a&&p&&o&&e.jsx("button",{type:"button",className:"cedros-button cedros-button-danger cedros-button-sm",onClick:d,disabled:f,"aria-label":`Remove ${s.user.name||s.user.email}`,children:f?e.jsx(k.LoadingSpinner,{size:"sm"}):"Remove"})})]})}function W({user:s}){const t=D.sanitizeImageUrl(s.picture);if(t)return e.jsx("img",{src:t,alt:s.name||s.email||"Member",className:"cedros-member-avatar",referrerPolicy:"no-referrer"});const a=(s.name?.[0]||s.email?.[0]||"?").toUpperCase();return e.jsx("div",{className:"cedros-member-avatar-placeholder",children:a})}function H(s){return new Date(s).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}const V=["admin","member"];function K({onSubmit:s,isLoading:t=!1,error:a,availableRoles:i=V,defaultRole:n="member",className:o=""}){const[f,m]=r.useState(""),[h,l]=r.useState(n),[j,d]=r.useState(null),[y,p]=r.useState(!1),c=r.useRef(null),u=r.useRef(!0);r.useEffect(()=>(u.current=!0,()=>{u.current=!1,c.current!==null&&(window.clearTimeout(c.current),c.current=null)}),[]);const g=r.useCallback(async b=>{b.preventDefault(),d(null),p(!1);const S=f.trim();if(!S){d("Email is required");return}if(!F.validateEmail(S)){d("Please enter a valid email address");return}try{await s(S,h),m(""),l(n),p(!0),c.current!==null&&window.clearTimeout(c.current),c.current=window.setTimeout(()=>{u.current&&p(!1),c.current=null},3e3)}catch{}},[f,h,n,s]);return e.jsxs("form",{className:`cedros-invite-form ${o}`,onSubmit:g,children:[(a||j)&&e.jsx($.ErrorMessage,{error:j??a??null}),y&&e.jsxs("div",{className:"cedros-invite-success",role:"status",children:[e.jsx(G,{}),e.jsx("span",{children:"Invitation sent successfully!"})]}),e.jsxs("div",{className:"cedros-invite-form-row",children:[e.jsxs("div",{className:"cedros-form-group cedros-invite-email-group",children:[e.jsx("label",{htmlFor:"invite-email",className:"cedros-form-label",children:"Email Address"}),e.jsx("input",{id:"invite-email",type:"email",className:"cedros-form-input",value:f,onChange:b=>m(b.target.value),placeholder:"colleague@example.com",disabled:t,autoComplete:"email"})]}),e.jsxs("div",{className:"cedros-form-group cedros-invite-role-group",children:[e.jsx("label",{htmlFor:"invite-role",className:"cedros-form-label",children:"Role"}),e.jsx("select",{id:"invite-role",className:"cedros-form-select",value:h,onChange:b=>l(b.target.value),disabled:t,children:i.map(b=>e.jsx("option",{value:b,children:b.charAt(0).toUpperCase()+b.slice(1)},b))})]}),e.jsx("button",{type:"submit",className:"cedros-button cedros-button-primary cedros-invite-submit",disabled:t||!f.trim(),children:t?e.jsx(k.LoadingSpinner,{size:"sm"}):"Send Invite"})]}),e.jsx("p",{className:"cedros-form-hint",children:"The invited user will receive an email with a link to join your organization."})]})}function G(){return e.jsx("svg",{className:"cedros-invite-check",width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:e.jsx("path",{d:"M3 8L6 11L13 5",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function J({invites:s,isLoading:t=!1,error:a,canManage:i=!1,onCancel:n,onResend:o,className:f=""}){return t&&s.length===0?e.jsxs("div",{className:`cedros-invite-list cedros-invite-list-loading ${f}`,children:[e.jsx(k.LoadingSpinner,{}),e.jsx("span",{children:"Loading invites..."})]}):a?e.jsx("div",{className:`cedros-invite-list ${f}`,children:e.jsx($.ErrorMessage,{error:a})}):s.length===0?e.jsx("div",{className:`cedros-invite-list cedros-invite-list-empty ${f}`,children:e.jsx("p",{children:"No pending invites."})}):e.jsx("div",{className:`cedros-invite-list ${f}`,children:e.jsx("ul",{className:"cedros-invite-items",children:s.map(m=>e.jsx(Y,{invite:m,canManage:i,onCancel:n,onResend:o},m.id))})})}function Y({invite:s,canManage:t,onCancel:a,onResend:i}){const[n,o]=r.useState(!1),[f,m]=r.useState(!1),h=r.useRef(null),l=new Date(s.expiresAt)<new Date,j=r.useCallback(async()=>{if(!(!a||!window.confirm(`Are you sure you want to cancel the invite for ${s.email}?`))){o(!0);try{await a(s.id)}finally{o(!1)}}},[s.id,s.email,a]),d=r.useCallback(async()=>{if(i){o(!0),m(!1);try{await i(s.id),m(!0),h.current!==null&&window.clearTimeout(h.current),h.current=window.setTimeout(()=>{m(!1),h.current=null},3e3)}finally{o(!1)}}},[s.id,i]);return r.useEffect(()=>()=>{h.current!==null&&(window.clearTimeout(h.current),h.current=null)},[]),e.jsxs("li",{className:`cedros-invite-item ${l?"cedros-invite-item-expired":""}`,children:[e.jsxs("div",{className:"cedros-invite-item-info",children:[e.jsxs("div",{className:"cedros-invite-item-main",children:[e.jsx("span",{className:"cedros-invite-item-email",children:s.email}),e.jsx("span",{className:`cedros-role-badge cedros-role-badge-${s.role}`,children:s.role.charAt(0).toUpperCase()+s.role.slice(1)}),l&&e.jsx("span",{className:"cedros-invite-expired-badge",children:"Expired"})]}),e.jsxs("div",{className:"cedros-invite-item-meta",children:[e.jsxs("span",{className:"cedros-invite-item-date",children:["Invited ",M(s.createdAt)]}),!l&&e.jsxs("span",{className:"cedros-invite-item-expires",children:["Expires ",Q(s.expiresAt)]})]})]}),t&&e.jsxs("div",{className:"cedros-invite-item-actions",children:[f&&e.jsx("span",{className:"cedros-invite-resend-success",children:"Sent!"}),i&&!l&&e.jsx("button",{type:"button",className:"cedros-button cedros-button-outline cedros-button-sm",onClick:d,disabled:n,"aria-label":`Resend invite to ${s.email}`,children:n?e.jsx(k.LoadingSpinner,{size:"sm"}):"Resend"}),a&&e.jsx("button",{type:"button",className:"cedros-button cedros-button-danger cedros-button-sm",onClick:j,disabled:n,"aria-label":`Cancel invite for ${s.email}`,children:"Cancel"})]})]})}function M(s){return new Date(s).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}function Q(s){const t=new Date(s),a=new Date,i=t.getTime()-a.getTime(),n=Math.ceil(i/(1e3*60*60*24));return n<0?"expired":n===0?"today":n===1?"tomorrow":n<7?`in ${n} days`:M(s)}class X{client;constructor(t,a,i,n){this.client=new A.ApiClient({baseUrl:t,timeoutMs:a,retryAttempts:i,getAccessToken:n})}async listMembers(t,a=50,i=0){try{const n=await this.client.get(`/orgs/${t}/members?limit=${a}&offset=${i}`);return{members:n.members.map(o=>({id:o.id,userId:o.userId,orgId:t,role:o.role,joinedAt:o.joinedAt,user:{id:o.userId,email:o.email,name:o.name}})),total:n.total}}catch(n){throw A.handleApiError(n,"Failed to list members")}}async updateMemberRole(t,a,i){try{return await this.client.patch(`/orgs/${t}/members/${a}`,i)}catch(n){throw A.handleApiError(n,"Failed to update member role")}}async removeMember(t,a){try{await this.client.delete(`/orgs/${t}/members/${a}`)}catch(i){throw A.handleApiError(i,"Failed to remove member")}}}function Z(s){const{config:t,authState:a,_internal:i}=A.useCedrosLogin(),[n,o]=r.useState([]),[f,m]=r.useState(0),[h,l]=r.useState(!1),[j,d]=r.useState(null),y=r.useRef(void 0),p=r.useRef(0),c=r.useMemo(()=>new X(t.serverUrl,t.requestTimeout,t.retryAttempts,i?.getAccessToken),[t.serverUrl,t.requestTimeout,t.retryAttempts,i]),u=r.useRef(c);u.current=c;const g=r.useCallback(async w=>{if(!s||a!=="authenticated"){o([]),m(0);return}l(!0),d(null);const x=++p.current;try{const{limit:v=50,offset:N=0}=w??{},C=await u.current.listMembers(s,v,N);if(x!==p.current)return;o(C.members),m(C.total)}catch(v){if(x!==p.current)return;d(v)}finally{x===p.current&&l(!1)}},[s,a]);r.useEffect(()=>{if(a!=="authenticated"){y.current=void 0;return}s!==y.current&&(y.current=s,g())},[s,a,g]);const b=r.useCallback(async(w,x)=>{if(!s)throw new Error("No organization selected");l(!0),d(null);try{await u.current.updateMemberRole(s,w,{role:x}),await g()}catch(v){throw d(v),v}finally{l(!1)}},[s,g]),S=r.useCallback(async w=>{if(!s)throw new Error("No organization selected");l(!0),d(null);try{await u.current.removeMember(s,w),await g()}catch(x){throw d(x),x}finally{l(!1)}},[s,g]);return{members:n,total:f,isLoading:h,error:j,fetchMembers:g,updateMemberRole:b,removeMember:S}}class ee{client;constructor(t,a,i,n){this.client=new A.ApiClient({baseUrl:t,timeoutMs:a,retryAttempts:i,getAccessToken:n})}async listInvites(t,a=50,i=0){try{const n=await this.client.get(`/orgs/${t}/invites?limit=${a}&offset=${i}`);return{invites:n.invites.map(o=>({id:o.id,orgId:o.orgId,email:o.email,role:o.role,invitedBy:o.invitedBy,createdAt:o.createdAt,expiresAt:o.expiresAt})),total:n.total}}catch(n){throw A.handleApiError(n,"Failed to list invites")}}async createInvite(t,a){try{return await this.client.post(`/orgs/${t}/invites`,a)}catch(i){throw A.handleApiError(i,"Failed to create invite")}}async cancelInvite(t,a){try{await this.client.delete(`/orgs/${t}/invites/${a}`)}catch(i){throw A.handleApiError(i,"Failed to cancel invite")}}async resendInvite(t,a){try{await this.client.post(`/orgs/${t}/invites/${a}/resend`,{})}catch(i){throw A.handleApiError(i,"Failed to resend invite")}}async acceptInvite(t){try{return await this.client.post("/invites/accept",t)}catch(a){throw A.handleApiError(a,"Failed to accept invite")}}}function se(s){const{config:t,authState:a,_internal:i}=A.useCedrosLogin(),[n,o]=r.useState([]),[f,m]=r.useState(0),[h,l]=r.useState(!1),[j,d]=r.useState(null),y=r.useRef(void 0),p=r.useRef(0),c=r.useMemo(()=>new ee(t.serverUrl,t.requestTimeout,t.retryAttempts,i?.getAccessToken),[t.serverUrl,t.requestTimeout,t.retryAttempts,i]),u=r.useRef(c);u.current=c;const g=r.useCallback(async v=>{if(!s||a!=="authenticated"){o([]),m(0);return}l(!0),d(null);const N=++p.current;try{const{limit:C=50,offset:O=0}=v??{},L=await u.current.listInvites(s,C,O);if(N!==p.current)return;o(L.invites),m(L.total)}catch(C){if(N!==p.current)return;d(C)}finally{N===p.current&&l(!1)}},[s,a]);r.useEffect(()=>{if(a!=="authenticated"){y.current=void 0;return}s!==y.current&&(y.current=s,g())},[s,a,g]);const b=r.useCallback(async(v,N="member")=>{if(!s)throw new Error("No organization selected");l(!0),d(null);try{await u.current.createInvite(s,{email:v,role:N}),await g()}catch(C){throw d(C),C}finally{l(!1)}},[s,g]),S=r.useCallback(async v=>{if(!s)throw new Error("No organization selected");l(!0),d(null);try{await u.current.cancelInvite(s,v),await g()}catch(N){throw d(N),N}finally{l(!1)}},[s,g]),w=r.useCallback(async v=>{if(!s)throw new Error("No organization selected");l(!0),d(null);try{await u.current.resendInvite(s,v)}catch(N){throw d(N),N}finally{l(!1)}},[s]),x=r.useCallback(async v=>{l(!0),d(null);try{return await u.current.acceptInvite({token:v})}catch(N){throw d(N),N}finally{l(!1)}},[]);return{invites:n,total:f,isLoading:h,error:j,fetchInvites:g,createInvite:b,cancelInvite:S,resendInvite:w,acceptInvite:x}}const te={organizations:!1,sso:!1,mfa:!1,walletSigning:!1,credits:!1,userWithdrawals:!1,cedrosPay:!1};function I(){const{settings:s,isLoading:t,error:a,fetchSettings:i,getValue:n}=q.useSystemSettings(),[o,f]=r.useState(!1);r.useEffect(()=>{o||(i(),f(!0))},[i,o]);const m=r.useCallback(d=>d===void 0?!1:d==="true"||d==="1",[]),h=r.useMemo(()=>Object.keys(s).length===0?te:{organizations:m(n("feature_organizations")),sso:m(n("feature_sso")),mfa:m(n("feature_mfa")),walletSigning:m(n("feature_wallet_signing")),credits:m(n("feature_credits")),userWithdrawals:m(n("feature_user_withdrawals")),cedrosPay:m(n("feature_cedros_pay"))},[s,n,m]),l=r.useCallback(async()=>{await i()},[i]),j=r.useCallback(d=>h[d],[h]);return{features:h,isLoading:t,error:a,refetch:l,isEnabled:j}}const re=["users","team","deposits","withdrawals","settings-wallet","settings-auth","settings-messaging","settings-credits","settings-server"],ne=["pay-products","pay-subscriptions","pay-transactions","pay-coupons","pay-refunds","pay-storefront","pay-ai","pay-payment","pay-messaging","pay-settings"],E={users:"Users",team:"Team",deposits:"Deposits",withdrawals:"Withdrawals","settings-wallet":"Wallet Settings","settings-auth":"Auth Settings","settings-messaging":"Messages Settings","settings-credits":"Credits Settings","settings-server":"Server Settings","pay-products":"Products","pay-subscriptions":"Subscriptions","pay-transactions":"Transactions","pay-coupons":"Coupons","pay-refunds":"Refunds","pay-storefront":"Storefront","pay-ai":"Store AI","pay-payment":"Payment Options","pay-messaging":"Store Messages","pay-settings":"Store Server"},R={admin:{users:!0,team:!0,deposits:!0,withdrawals:!0,"settings-wallet":!0,"settings-auth":!0,"settings-messaging":!0,"settings-credits":!0,"settings-server":!0,"pay-products":!0,"pay-subscriptions":!0,"pay-transactions":!0,"pay-coupons":!0,"pay-refunds":!0,"pay-storefront":!0,"pay-ai":!0,"pay-payment":!0,"pay-messaging":!0,"pay-settings":!0},member:{users:!1,team:!0,deposits:!1,withdrawals:!1,"settings-wallet":!1,"settings-auth":!1,"settings-messaging":!1,"settings-credits":!1,"settings-server":!1,"pay-products":!1,"pay-subscriptions":!1,"pay-transactions":!1,"pay-coupons":!1,"pay-refunds":!1,"pay-storefront":!1,"pay-ai":!1,"pay-payment":!1,"pay-messaging":!1,"pay-settings":!1}};function _(){const{config:s,authState:t,_internal:a}=A.useCedrosLogin(),{activeOrg:i,role:n}=P.useOrgs(),[o,f]=r.useState(R),[m,h]=r.useState(!1),[l,j]=r.useState(!1),[d,y]=r.useState(null),p=r.useRef(0),c=r.useMemo(()=>new A.ApiClient({baseUrl:s.serverUrl,timeoutMs:s.requestTimeout,retryAttempts:s.retryAttempts,getAccessToken:a?.getAccessToken}),[s.serverUrl,s.requestTimeout,s.retryAttempts,a]),u=r.useRef(c);u.current=c;const g=r.useCallback(async()=>{if(t!=="authenticated"||!i){f(R);return}h(!0),y(null);const w=++p.current;try{const x=await u.current.get("/admin/dashboard-permissions");if(w!==p.current)return;f(x.permissions)}catch(x){if(w!==p.current)return;if(x instanceof Error&&x.message.includes("404"))f(R);else{const v=x instanceof Error?x.message:"Failed to fetch permissions";y({code:"NETWORK_ERROR",message:v}),f(R)}}finally{w===p.current&&h(!1)}},[t,i]),b=r.useCallback(async w=>{if(t!=="authenticated"||!i)throw new Error("Not authenticated");if(n!=="owner")throw new Error("Only owners can modify dashboard permissions");j(!0),y(null);try{await u.current.request({method:"PUT",path:"/admin/dashboard-permissions",body:w}),f(w)}catch(x){const v=x instanceof Error?x.message:"Failed to update permissions";throw y({code:"NETWORK_ERROR",message:v}),new Error(v)}finally{j(!1)}},[t,i,n]),S=r.useCallback(w=>!i||!n||n==="owner"?!0:o[n]?.[w]??!1,[i,n,o]);return r.useEffect(()=>{i?.id&&g()},[i?.id,g]),{permissions:o,canAccess:S,updatePermissions:b,isLoading:m,isUpdating:l,error:d,fetchPermissions:g}}function T({checked:s,onChange:t,disabled:a,label:i}){return e.jsx("button",{type:"button",role:"switch","aria-checked":s,"aria-label":i,disabled:a,className:`cedros-toggle cedros-toggle-sm ${s?"cedros-toggle-on":"cedros-toggle-off"} ${a?"cedros-toggle-disabled":""}`,onClick:()=>!a&&t(!s),children:e.jsx("span",{className:"cedros-toggle-track",children:e.jsx("span",{className:"cedros-toggle-thumb"})})})}function ae({userRole:s}){const{permissions:t,updatePermissions:a,isLoading:i,isUpdating:n,error:o}=_(),{features:f,isLoading:m}=I(),h=r.useRef(null),l=r.useRef(null),j=s==="owner",d=f.cedrosPay,y=r.useCallback(c=>{l.current=c,h.current&&clearTimeout(h.current),h.current=setTimeout(()=>{l.current&&(a(l.current).catch(()=>{}),l.current=null)},500)},[a]);r.useEffect(()=>()=>{h.current&&clearTimeout(h.current)},[]);const p=r.useCallback((c,u,g)=>{const b={...t,[c]:{...t[c],[u]:g}};y(b)},[t,y]);return i||m?e.jsx("div",{className:"cedros-dashboard__section",children:e.jsx("div",{className:"cedros-dashboard__loading",children:"Loading permissions..."})}):j?e.jsxs("div",{className:"cedros-dashboard__section cedros-permissions-section",children:[e.jsxs("div",{className:"cedros-permissions-header",children:[e.jsx("p",{className:"cedros-permissions-description",children:"Configure which dashboard sections each role can access. Owners always have full access."}),o&&e.jsx("div",{className:"cedros-permissions-error",children:o.message}),n&&e.jsx("span",{className:"cedros-permissions-saving",children:"Saving..."})]}),e.jsx("div",{className:"cedros-permissions-matrix",children:e.jsx("table",{className:"cedros-permissions-table",children:e.jsxs("tbody",{children:[e.jsxs("tr",{className:"cedros-permissions-group-header",children:[e.jsx("th",{className:"cedros-permissions-section-header",children:"Cedros Login"}),e.jsx("th",{className:"cedros-permissions-role-header",children:"Admin"}),e.jsx("th",{className:"cedros-permissions-role-header",children:"Member"})]}),re.map(c=>e.jsxs("tr",{className:"cedros-permissions-row",children:[e.jsx("td",{className:"cedros-permissions-section-label",children:E[c]}),e.jsx("td",{className:"cedros-permissions-toggle-cell",children:e.jsx(T,{checked:t.admin[c]??!1,onChange:u=>p("admin",c,u),disabled:n,label:`Admin access to ${E[c]}`})}),e.jsx("td",{className:"cedros-permissions-toggle-cell",children:e.jsx(T,{checked:t.member[c]??!1,onChange:u=>p("member",c,u),disabled:n,label:`Member access to ${E[c]}`})})]},c)),d&&e.jsxs(e.Fragment,{children:[e.jsxs("tr",{className:"cedros-permissions-group-header",children:[e.jsx("th",{className:"cedros-permissions-section-header",children:"Cedros Pay"}),e.jsx("th",{className:"cedros-permissions-role-header",children:"Admin"}),e.jsx("th",{className:"cedros-permissions-role-header",children:"Member"})]}),ne.map(c=>e.jsxs("tr",{className:"cedros-permissions-row",children:[e.jsx("td",{className:"cedros-permissions-section-label",children:E[c]}),e.jsx("td",{className:"cedros-permissions-toggle-cell",children:e.jsx(T,{checked:t.admin[c]??!1,onChange:u=>p("admin",c,u),disabled:n,label:`Admin access to ${E[c]}`})}),e.jsx("td",{className:"cedros-permissions-toggle-cell",children:e.jsx(T,{checked:t.member[c]??!1,onChange:u=>p("member",c,u),disabled:n,label:`Member access to ${E[c]}`})})]},c))]})]})})})]}):e.jsx("div",{className:"cedros-dashboard__section",children:e.jsx("div",{className:"cedros-dashboard__empty",children:"Only organization owners can configure dashboard permissions."})})}exports.InviteForm=K;exports.InviteList=J;exports.MemberList=z;exports.PermissionsSection=ae;exports.useDashboardPermissions=_;exports.useInvites=se;exports.useMembers=Z;exports.useServerFeatures=I;
1
+ "use strict";const e=require("react/jsx-runtime"),r=require("react"),k=require("./LoadingSpinner-d6sSxgQN.cjs"),$=require("./ErrorMessage-CHbYbVi2.cjs"),D=require("./sanitization-Bo_tn-L2.cjs"),q=require("./validation-BuGQrA-K.cjs"),A=require("./useCedrosLogin-DtJorrE7.cjs"),F=require("./useOrgs-CNqfn-fk.cjs"),P=require("./useSystemSettings-B2jY51ob.cjs"),U=["owner","admin","member"];function z({members:s,currentUserId:t,isLoading:a=!1,error:i,canManage:n=!1,canChangeRoles:o=!1,onUpdateRole:h,onRemove:m,className:f=""}){const[l,j]=r.useState("name"),[d,y]=r.useState("asc"),p=u=>{l===u?y(d==="asc"?"desc":"asc"):(j(u),y("asc"))},c=r.useMemo(()=>{const u={owner:0,admin:1,member:2};return[...s].sort((g,b)=>{let S,w;switch(l){case"name":S=(g.user.name||g.user.email||"").toLowerCase(),w=(b.user.name||b.user.email||"").toLowerCase();break;case"role":S=u[g.role]??99,w=u[b.role]??99;break;case"joinedAt":S=new Date(g.joinedAt).getTime(),w=new Date(b.joinedAt).getTime();break;default:return 0}return S<w?d==="asc"?-1:1:S>w?d==="asc"?1:-1:0})},[s,l,d]);return a&&s.length===0?e.jsxs("div",{className:`cedros-member-list cedros-member-list-loading ${f}`,children:[e.jsx(k.LoadingSpinner,{}),e.jsx("span",{children:"Loading members..."})]}):i?e.jsx("div",{className:`cedros-member-list ${f}`,children:e.jsx($.ErrorMessage,{error:i})}):s.length===0?e.jsx("div",{className:`cedros-member-list cedros-member-list-empty ${f}`,children:e.jsx("p",{children:"No members found."})}):e.jsx("div",{className:`cedros-member-list ${f}`,children:e.jsxs("table",{className:"cedros-member-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:e.jsxs("button",{type:"button",className:`cedros-admin-sort-button ${l==="name"?"cedros-admin-sort-active":""}`,onClick:()=>p("name"),children:["Member"," ",e.jsx("span",{className:"cedros-admin-sort-icon",children:l==="name"?d==="asc"?"↑":"↓":"↕"})]})}),e.jsx("th",{children:e.jsxs("button",{type:"button",className:`cedros-admin-sort-button ${l==="role"?"cedros-admin-sort-active":""}`,onClick:()=>p("role"),children:["Role"," ",e.jsx("span",{className:"cedros-admin-sort-icon",children:l==="role"?d==="asc"?"↑":"↓":"↕"})]})}),e.jsx("th",{children:e.jsxs("button",{type:"button",className:`cedros-admin-sort-button ${l==="joinedAt"?"cedros-admin-sort-active":""}`,onClick:()=>p("joinedAt"),children:["Joined"," ",e.jsx("span",{className:"cedros-admin-sort-icon",children:l==="joinedAt"?d==="asc"?"↑":"↓":"↕"})]})}),(n||o)&&e.jsx("th",{children:"Actions"})]})}),e.jsx("tbody",{children:c.map(u=>e.jsx(B,{member:u,isCurrentUser:u.userId===t,canManage:n,canChangeRoles:o,onUpdateRole:h,onRemove:m},u.id))})]})})}function B({member:s,isCurrentUser:t,canManage:a,canChangeRoles:i,onUpdateRole:n,onRemove:o}){const[h,m]=r.useState(!1),[f,l]=r.useState(s.role),j=r.useCallback(async c=>{if(!(!n||c===s.role)){m(!0);try{await n(s.userId,c),l(c)}catch{l(s.role)}finally{m(!1)}}},[s.userId,s.role,n]),d=r.useCallback(async()=>{if(!(!o||!window.confirm(`Are you sure you want to remove ${s.user.name||s.user.email} from this organization?`))){m(!0);try{await o(s.userId)}finally{m(!1)}}},[s.userId,s.user.name,s.user.email,o]),y=s.role==="owner",p=!t&&!y;return e.jsxs("tr",{className:`cedros-member-row ${t?"cedros-member-row-current":""}`,children:[e.jsxs("td",{className:"cedros-member-info",children:[e.jsx(W,{user:s.user}),e.jsxs("div",{className:"cedros-member-details",children:[e.jsxs("span",{className:"cedros-member-name",children:[s.user.name||"Unknown",t&&e.jsx("span",{className:"cedros-member-you",children:"(you)"})]}),e.jsx("span",{className:"cedros-member-email",children:s.user.email})]})]}),e.jsx("td",{className:"cedros-member-role",children:i&&p&&n?e.jsx("select",{value:f,onChange:c=>j(c.target.value),disabled:h,className:"cedros-role-select",children:U.map(c=>e.jsx("option",{value:c,children:c.charAt(0).toUpperCase()+c.slice(1)},c))}):e.jsx("span",{className:`cedros-role-badge cedros-role-badge-${s.role}`,children:s.role.charAt(0).toUpperCase()+s.role.slice(1)})}),e.jsx("td",{className:"cedros-member-joined",children:H(s.joinedAt)}),(a||i)&&e.jsx("td",{className:"cedros-member-actions",children:a&&p&&o&&e.jsx("button",{type:"button",className:"cedros-button cedros-button-danger cedros-button-sm",onClick:d,disabled:h,"aria-label":`Remove ${s.user.name||s.user.email}`,children:h?e.jsx(k.LoadingSpinner,{size:"sm"}):"Remove"})})]})}function W({user:s}){const t=D.sanitizeImageUrl(s.picture);if(t)return e.jsx("img",{src:t,alt:s.name||s.email||"Member",className:"cedros-member-avatar",referrerPolicy:"no-referrer"});const a=(s.name?.[0]||s.email?.[0]||"?").toUpperCase();return e.jsx("div",{className:"cedros-member-avatar-placeholder",children:a})}function H(s){return new Date(s).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}const V=["admin","member"];function K({onSubmit:s,isLoading:t=!1,error:a,availableRoles:i=V,defaultRole:n="member",className:o=""}){const[h,m]=r.useState(""),[f,l]=r.useState(n),[j,d]=r.useState(null),[y,p]=r.useState(!1),c=r.useRef(null),u=r.useRef(!0);r.useEffect(()=>(u.current=!0,()=>{u.current=!1,c.current!==null&&(window.clearTimeout(c.current),c.current=null)}),[]);const g=r.useCallback(async b=>{b.preventDefault(),d(null),p(!1);const S=h.trim();if(!S){d("Email is required");return}if(!q.validateEmail(S)){d("Please enter a valid email address");return}try{await s(S,f),m(""),l(n),p(!0),c.current!==null&&window.clearTimeout(c.current),c.current=window.setTimeout(()=>{u.current&&p(!1),c.current=null},3e3)}catch{}},[h,f,n,s]);return e.jsxs("form",{className:`cedros-invite-form ${o}`,onSubmit:g,children:[(a||j)&&e.jsx($.ErrorMessage,{error:j??a??null}),y&&e.jsxs("div",{className:"cedros-invite-success",role:"status",children:[e.jsx(G,{}),e.jsx("span",{children:"Invitation sent successfully!"})]}),e.jsxs("div",{className:"cedros-invite-form-row",children:[e.jsxs("div",{className:"cedros-form-group cedros-invite-email-group",children:[e.jsx("label",{htmlFor:"invite-email",className:"cedros-form-label",children:"Email Address"}),e.jsx("input",{id:"invite-email",type:"email",className:"cedros-form-input",value:h,onChange:b=>m(b.target.value),placeholder:"colleague@example.com",disabled:t,autoComplete:"email"})]}),e.jsxs("div",{className:"cedros-form-group cedros-invite-role-group",children:[e.jsx("label",{htmlFor:"invite-role",className:"cedros-form-label",children:"Role"}),e.jsx("select",{id:"invite-role",className:"cedros-form-select",value:f,onChange:b=>l(b.target.value),disabled:t,children:i.map(b=>e.jsx("option",{value:b,children:b.charAt(0).toUpperCase()+b.slice(1)},b))})]}),e.jsx("button",{type:"submit",className:"cedros-button cedros-button-primary cedros-invite-submit",disabled:t||!h.trim(),children:t?e.jsx(k.LoadingSpinner,{size:"sm"}):"Send Invite"})]}),e.jsx("p",{className:"cedros-form-hint",children:"The invited user will receive an email with a link to join your organization."})]})}function G(){return e.jsx("svg",{className:"cedros-invite-check",width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:e.jsx("path",{d:"M3 8L6 11L13 5",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function J({invites:s,isLoading:t=!1,error:a,canManage:i=!1,onCancel:n,onResend:o,className:h=""}){return t&&s.length===0?e.jsxs("div",{className:`cedros-invite-list cedros-invite-list-loading ${h}`,children:[e.jsx(k.LoadingSpinner,{}),e.jsx("span",{children:"Loading invites..."})]}):a?e.jsx("div",{className:`cedros-invite-list ${h}`,children:e.jsx($.ErrorMessage,{error:a})}):s.length===0?e.jsx("div",{className:`cedros-invite-list cedros-invite-list-empty ${h}`,children:e.jsx("p",{children:"No pending invites."})}):e.jsx("div",{className:`cedros-invite-list ${h}`,children:e.jsx("ul",{className:"cedros-invite-items",children:s.map(m=>e.jsx(Y,{invite:m,canManage:i,onCancel:n,onResend:o},m.id))})})}function Y({invite:s,canManage:t,onCancel:a,onResend:i}){const[n,o]=r.useState(!1),[h,m]=r.useState(!1),f=r.useRef(null),l=new Date(s.expiresAt)<new Date,j=r.useCallback(async()=>{if(!(!a||!window.confirm(`Are you sure you want to cancel the invite for ${s.email}?`))){o(!0);try{await a(s.id)}finally{o(!1)}}},[s.id,s.email,a]),d=r.useCallback(async()=>{if(i){o(!0),m(!1);try{await i(s.id),m(!0),f.current!==null&&window.clearTimeout(f.current),f.current=window.setTimeout(()=>{m(!1),f.current=null},3e3)}finally{o(!1)}}},[s.id,i]);return r.useEffect(()=>()=>{f.current!==null&&(window.clearTimeout(f.current),f.current=null)},[]),e.jsxs("li",{className:`cedros-invite-item ${l?"cedros-invite-item-expired":""}`,children:[e.jsxs("div",{className:"cedros-invite-item-info",children:[e.jsxs("div",{className:"cedros-invite-item-main",children:[e.jsx("span",{className:"cedros-invite-item-email",children:s.email}),e.jsx("span",{className:`cedros-role-badge cedros-role-badge-${s.role}`,children:s.role.charAt(0).toUpperCase()+s.role.slice(1)}),l&&e.jsx("span",{className:"cedros-invite-expired-badge",children:"Expired"})]}),e.jsxs("div",{className:"cedros-invite-item-meta",children:[e.jsxs("span",{className:"cedros-invite-item-date",children:["Invited ",M(s.createdAt)]}),!l&&e.jsxs("span",{className:"cedros-invite-item-expires",children:["Expires ",Q(s.expiresAt)]})]})]}),t&&e.jsxs("div",{className:"cedros-invite-item-actions",children:[h&&e.jsx("span",{className:"cedros-invite-resend-success",children:"Sent!"}),i&&!l&&e.jsx("button",{type:"button",className:"cedros-button cedros-button-outline cedros-button-sm",onClick:d,disabled:n,"aria-label":`Resend invite to ${s.email}`,children:n?e.jsx(k.LoadingSpinner,{size:"sm"}):"Resend"}),a&&e.jsx("button",{type:"button",className:"cedros-button cedros-button-danger cedros-button-sm",onClick:j,disabled:n,"aria-label":`Cancel invite for ${s.email}`,children:"Cancel"})]})]})}function M(s){return new Date(s).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}function Q(s){const t=new Date(s),a=new Date,i=t.getTime()-a.getTime(),n=Math.ceil(i/(1e3*60*60*24));return n<0?"expired":n===0?"today":n===1?"tomorrow":n<7?`in ${n} days`:M(s)}class X{client;constructor(t,a,i,n){this.client=new A.ApiClient({baseUrl:t,timeoutMs:a,retryAttempts:i,getAccessToken:n})}async listMembers(t,a=50,i=0){try{const n=await this.client.get(`/orgs/${t}/members?limit=${a}&offset=${i}`);return{members:n.members.map(o=>({id:o.id,userId:o.userId,orgId:t,role:o.role,joinedAt:o.joinedAt,user:{id:o.userId,email:o.email,name:o.name}})),total:n.total}}catch(n){throw A.handleApiError(n,"Failed to list members")}}async updateMemberRole(t,a,i){try{return await this.client.patch(`/orgs/${t}/members/${a}`,i)}catch(n){throw A.handleApiError(n,"Failed to update member role")}}async removeMember(t,a){try{await this.client.delete(`/orgs/${t}/members/${a}`)}catch(i){throw A.handleApiError(i,"Failed to remove member")}}}function Z(s){const{config:t,authState:a,_internal:i}=A.useCedrosLogin(),[n,o]=r.useState([]),[h,m]=r.useState(0),[f,l]=r.useState(!1),[j,d]=r.useState(null),y=r.useRef(void 0),p=r.useRef(0),c=r.useMemo(()=>new X(t.serverUrl,t.requestTimeout,t.retryAttempts,i?.getAccessToken),[t.serverUrl,t.requestTimeout,t.retryAttempts,i]),u=r.useRef(c);u.current=c;const g=r.useCallback(async w=>{if(!s||a!=="authenticated"){o([]),m(0);return}l(!0),d(null);const x=++p.current;try{const{limit:v=50,offset:N=0}=w??{},C=await u.current.listMembers(s,v,N);if(x!==p.current)return;o(C.members),m(C.total)}catch(v){if(x!==p.current)return;d(v)}finally{x===p.current&&l(!1)}},[s,a]);r.useEffect(()=>{if(a!=="authenticated"){y.current=void 0;return}s!==y.current&&(y.current=s,g())},[s,a,g]);const b=r.useCallback(async(w,x)=>{if(!s)throw new Error("No organization selected");l(!0),d(null);try{await u.current.updateMemberRole(s,w,{role:x}),await g()}catch(v){throw d(v),v}finally{l(!1)}},[s,g]),S=r.useCallback(async w=>{if(!s)throw new Error("No organization selected");l(!0),d(null);try{await u.current.removeMember(s,w),await g()}catch(x){throw d(x),x}finally{l(!1)}},[s,g]);return{members:n,total:h,isLoading:f,error:j,fetchMembers:g,updateMemberRole:b,removeMember:S}}class ee{client;constructor(t,a,i,n){this.client=new A.ApiClient({baseUrl:t,timeoutMs:a,retryAttempts:i,getAccessToken:n})}async listInvites(t,a=50,i=0){try{const n=await this.client.get(`/orgs/${t}/invites?limit=${a}&offset=${i}`);return{invites:n.invites.map(o=>({id:o.id,orgId:o.orgId,email:o.email,role:o.role,invitedBy:o.invitedBy,createdAt:o.createdAt,expiresAt:o.expiresAt})),total:n.total}}catch(n){throw A.handleApiError(n,"Failed to list invites")}}async createInvite(t,a){try{return await this.client.post(`/orgs/${t}/invites`,a)}catch(i){throw A.handleApiError(i,"Failed to create invite")}}async cancelInvite(t,a){try{await this.client.delete(`/orgs/${t}/invites/${a}`)}catch(i){throw A.handleApiError(i,"Failed to cancel invite")}}async resendInvite(t,a){try{await this.client.post(`/orgs/${t}/invites/${a}/resend`,{})}catch(i){throw A.handleApiError(i,"Failed to resend invite")}}async acceptInvite(t){try{return await this.client.post("/invites/accept",t)}catch(a){throw A.handleApiError(a,"Failed to accept invite")}}}function se(s){const{config:t,authState:a,_internal:i}=A.useCedrosLogin(),[n,o]=r.useState([]),[h,m]=r.useState(0),[f,l]=r.useState(!1),[j,d]=r.useState(null),y=r.useRef(void 0),p=r.useRef(0),c=r.useMemo(()=>new ee(t.serverUrl,t.requestTimeout,t.retryAttempts,i?.getAccessToken),[t.serverUrl,t.requestTimeout,t.retryAttempts,i]),u=r.useRef(c);u.current=c;const g=r.useCallback(async v=>{if(!s||a!=="authenticated"){o([]),m(0);return}l(!0),d(null);const N=++p.current;try{const{limit:C=50,offset:O=0}=v??{},L=await u.current.listInvites(s,C,O);if(N!==p.current)return;o(L.invites),m(L.total)}catch(C){if(N!==p.current)return;d(C)}finally{N===p.current&&l(!1)}},[s,a]);r.useEffect(()=>{if(a!=="authenticated"){y.current=void 0;return}s!==y.current&&(y.current=s,g())},[s,a,g]);const b=r.useCallback(async(v,N="member")=>{if(!s)throw new Error("No organization selected");l(!0),d(null);try{await u.current.createInvite(s,{email:v,role:N}),await g()}catch(C){throw d(C),C}finally{l(!1)}},[s,g]),S=r.useCallback(async v=>{if(!s)throw new Error("No organization selected");l(!0),d(null);try{await u.current.cancelInvite(s,v),await g()}catch(N){throw d(N),N}finally{l(!1)}},[s,g]),w=r.useCallback(async v=>{if(!s)throw new Error("No organization selected");l(!0),d(null);try{await u.current.resendInvite(s,v)}catch(N){throw d(N),N}finally{l(!1)}},[s]),x=r.useCallback(async v=>{l(!0),d(null);try{return await u.current.acceptInvite({token:v})}catch(N){throw d(N),N}finally{l(!1)}},[]);return{invites:n,total:h,isLoading:f,error:j,fetchInvites:g,createInvite:b,cancelInvite:S,resendInvite:w,acceptInvite:x}}const te={organizations:!1,sso:!1,mfa:!1,mfaRequired:!1,walletSigning:!1,credits:!1,userWithdrawals:!1,cedrosPay:!1};function _(){const{settings:s,isLoading:t,error:a,fetchSettings:i,getValue:n}=P.useSystemSettings(),[o,h]=r.useState(!1);r.useEffect(()=>{o||(i(),h(!0))},[i,o]);const m=r.useCallback(d=>d===void 0?!1:d==="true"||d==="1",[]),f=r.useMemo(()=>Object.keys(s).length===0?te:{organizations:m(n("feature_organizations")),sso:m(n("feature_sso")),mfa:m(n("feature_mfa")),mfaRequired:m(n("security_require_mfa")),walletSigning:m(n("feature_wallet_signing")),credits:m(n("feature_credits")),userWithdrawals:m(n("feature_user_withdrawals")),cedrosPay:m(n("feature_cedros_pay"))},[s,n,m]),l=r.useCallback(async()=>{await i()},[i]),j=r.useCallback(d=>f[d],[f]);return{features:f,isLoading:t,error:a,refetch:l,isEnabled:j}}const re=["users","team","deposits","withdrawals","settings-wallet","settings-auth","settings-messaging","settings-credits","settings-server"],ne=["pay-products","pay-subscriptions","pay-transactions","pay-coupons","pay-refunds","pay-storefront","pay-ai","pay-payment","pay-messaging","pay-settings"],E={users:"Users",team:"Team",deposits:"Deposits",withdrawals:"Withdrawals","settings-wallet":"Wallet Settings","settings-auth":"Auth Settings","settings-messaging":"Messages Settings","settings-credits":"Credits Settings","settings-server":"Server Settings","pay-products":"Products","pay-subscriptions":"Subscriptions","pay-transactions":"Transactions","pay-coupons":"Coupons","pay-refunds":"Refunds","pay-storefront":"Storefront","pay-ai":"Store AI","pay-payment":"Payment Options","pay-messaging":"Store Messages","pay-settings":"Store Server"},R={admin:{users:!0,team:!0,deposits:!0,withdrawals:!0,"settings-wallet":!0,"settings-auth":!0,"settings-messaging":!0,"settings-credits":!0,"settings-server":!0,"pay-products":!0,"pay-subscriptions":!0,"pay-transactions":!0,"pay-coupons":!0,"pay-refunds":!0,"pay-storefront":!0,"pay-ai":!0,"pay-payment":!0,"pay-messaging":!0,"pay-settings":!0},member:{users:!1,team:!0,deposits:!1,withdrawals:!1,"settings-wallet":!1,"settings-auth":!1,"settings-messaging":!1,"settings-credits":!1,"settings-server":!1,"pay-products":!1,"pay-subscriptions":!1,"pay-transactions":!1,"pay-coupons":!1,"pay-refunds":!1,"pay-storefront":!1,"pay-ai":!1,"pay-payment":!1,"pay-messaging":!1,"pay-settings":!1}};function I(){const{config:s,authState:t,_internal:a}=A.useCedrosLogin(),{activeOrg:i,role:n}=F.useOrgs(),[o,h]=r.useState(R),[m,f]=r.useState(!1),[l,j]=r.useState(!1),[d,y]=r.useState(null),p=r.useRef(0),c=r.useMemo(()=>new A.ApiClient({baseUrl:s.serverUrl,timeoutMs:s.requestTimeout,retryAttempts:s.retryAttempts,getAccessToken:a?.getAccessToken}),[s.serverUrl,s.requestTimeout,s.retryAttempts,a]),u=r.useRef(c);u.current=c;const g=r.useCallback(async()=>{if(t!=="authenticated"||!i){h(R);return}f(!0),y(null);const w=++p.current;try{const x=await u.current.get("/admin/dashboard-permissions");if(w!==p.current)return;h(x.permissions)}catch(x){if(w!==p.current)return;if(x instanceof Error&&x.message.includes("404"))h(R);else{const v=x instanceof Error?x.message:"Failed to fetch permissions";y({code:"NETWORK_ERROR",message:v}),h(R)}}finally{w===p.current&&f(!1)}},[t,i]),b=r.useCallback(async w=>{if(t!=="authenticated"||!i)throw new Error("Not authenticated");if(n!=="owner")throw new Error("Only owners can modify dashboard permissions");j(!0),y(null);try{await u.current.request({method:"PUT",path:"/admin/dashboard-permissions",body:w}),h(w)}catch(x){const v=x instanceof Error?x.message:"Failed to update permissions";throw y({code:"NETWORK_ERROR",message:v}),new Error(v)}finally{j(!1)}},[t,i,n]),S=r.useCallback(w=>!i||!n||n==="owner"?!0:o[n]?.[w]??!1,[i,n,o]);return r.useEffect(()=>{i?.id&&g()},[i?.id,g]),{permissions:o,canAccess:S,updatePermissions:b,isLoading:m,isUpdating:l,error:d,fetchPermissions:g}}function T({checked:s,onChange:t,disabled:a,label:i}){return e.jsx("button",{type:"button",role:"switch","aria-checked":s,"aria-label":i,disabled:a,className:`cedros-toggle cedros-toggle-sm ${s?"cedros-toggle-on":"cedros-toggle-off"} ${a?"cedros-toggle-disabled":""}`,onClick:()=>!a&&t(!s),children:e.jsx("span",{className:"cedros-toggle-track",children:e.jsx("span",{className:"cedros-toggle-thumb"})})})}function ae({userRole:s}){const{permissions:t,updatePermissions:a,isLoading:i,isUpdating:n,error:o}=I(),{features:h,isLoading:m}=_(),f=r.useRef(null),l=r.useRef(null),j=s==="owner",d=h.cedrosPay,y=r.useCallback(c=>{l.current=c,f.current&&clearTimeout(f.current),f.current=setTimeout(()=>{l.current&&(a(l.current).catch(()=>{}),l.current=null)},500)},[a]);r.useEffect(()=>()=>{f.current&&clearTimeout(f.current)},[]);const p=r.useCallback((c,u,g)=>{const b={...t,[c]:{...t[c],[u]:g}};y(b)},[t,y]);return i||m?e.jsx("div",{className:"cedros-dashboard__section",children:e.jsx("div",{className:"cedros-dashboard__loading",children:"Loading permissions..."})}):j?e.jsxs("div",{className:"cedros-dashboard__section cedros-permissions-section",children:[e.jsxs("div",{className:"cedros-permissions-header",children:[e.jsx("p",{className:"cedros-permissions-description",children:"Configure which dashboard sections each role can access. Owners always have full access."}),o&&e.jsx("div",{className:"cedros-permissions-error",children:o.message}),n&&e.jsx("span",{className:"cedros-permissions-saving",children:"Saving..."})]}),e.jsx("div",{className:"cedros-permissions-matrix",children:e.jsx("table",{className:"cedros-permissions-table",children:e.jsxs("tbody",{children:[e.jsxs("tr",{className:"cedros-permissions-group-header",children:[e.jsx("th",{className:"cedros-permissions-section-header",children:"Cedros Login"}),e.jsx("th",{className:"cedros-permissions-role-header",children:"Admin"}),e.jsx("th",{className:"cedros-permissions-role-header",children:"Member"})]}),re.map(c=>e.jsxs("tr",{className:"cedros-permissions-row",children:[e.jsx("td",{className:"cedros-permissions-section-label",children:E[c]}),e.jsx("td",{className:"cedros-permissions-toggle-cell",children:e.jsx(T,{checked:t.admin[c]??!1,onChange:u=>p("admin",c,u),disabled:n,label:`Admin access to ${E[c]}`})}),e.jsx("td",{className:"cedros-permissions-toggle-cell",children:e.jsx(T,{checked:t.member[c]??!1,onChange:u=>p("member",c,u),disabled:n,label:`Member access to ${E[c]}`})})]},c)),d&&e.jsxs(e.Fragment,{children:[e.jsxs("tr",{className:"cedros-permissions-group-header",children:[e.jsx("th",{className:"cedros-permissions-section-header",children:"Cedros Pay"}),e.jsx("th",{className:"cedros-permissions-role-header",children:"Admin"}),e.jsx("th",{className:"cedros-permissions-role-header",children:"Member"})]}),ne.map(c=>e.jsxs("tr",{className:"cedros-permissions-row",children:[e.jsx("td",{className:"cedros-permissions-section-label",children:E[c]}),e.jsx("td",{className:"cedros-permissions-toggle-cell",children:e.jsx(T,{checked:t.admin[c]??!1,onChange:u=>p("admin",c,u),disabled:n,label:`Admin access to ${E[c]}`})}),e.jsx("td",{className:"cedros-permissions-toggle-cell",children:e.jsx(T,{checked:t.member[c]??!1,onChange:u=>p("member",c,u),disabled:n,label:`Member access to ${E[c]}`})})]},c))]})]})})})]}):e.jsx("div",{className:"cedros-dashboard__section",children:e.jsx("div",{className:"cedros-dashboard__empty",children:"Only organization owners can configure dashboard permissions."})})}exports.InviteForm=K;exports.InviteList=J;exports.MemberList=z;exports.PermissionsSection=ae;exports.useDashboardPermissions=I;exports.useInvites=se;exports.useMembers=Z;exports.useServerFeatures=_;