@replicated/portal-components 0.0.27 → 0.0.29

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 (154) hide show
  1. package/components/metadata/registry.json +2 -2
  2. package/components/metadata/registry.md +2 -2
  3. package/dist/actions/branding-actions.d.mts +1 -1
  4. package/dist/actions/branding-actions.d.ts +1 -1
  5. package/dist/actions/branding-actions.js +15 -5
  6. package/dist/actions/branding-actions.js.map +1 -1
  7. package/dist/actions/change-team.js +13 -3
  8. package/dist/actions/change-team.js.map +1 -1
  9. package/dist/actions/index.d.mts +1 -1
  10. package/dist/actions/index.d.ts +1 -1
  11. package/dist/actions/index.js +16 -15
  12. package/dist/actions/index.js.map +1 -1
  13. package/dist/actions/install-actions.d.mts +1 -1
  14. package/dist/actions/install-actions.d.ts +1 -1
  15. package/dist/actions/install-actions.js +13 -3
  16. package/dist/actions/install-actions.js.map +1 -1
  17. package/dist/actions/invite-actions.js +13 -3
  18. package/dist/actions/invite-actions.js.map +1 -1
  19. package/dist/actions/magic-link-actions.d.mts +1 -1
  20. package/dist/actions/magic-link-actions.d.ts +1 -1
  21. package/dist/actions/magic-link-actions.js +15 -5
  22. package/dist/actions/magic-link-actions.js.map +1 -1
  23. package/dist/actions/service-account.d.mts +1 -1
  24. package/dist/actions/service-account.d.ts +1 -1
  25. package/dist/actions/service-account.js +13 -3
  26. package/dist/actions/service-account.js.map +1 -1
  27. package/dist/actions/support-bundles.d.mts +1 -1
  28. package/dist/actions/support-bundles.d.ts +1 -1
  29. package/dist/actions/support-bundles.js +13 -3
  30. package/dist/actions/support-bundles.js.map +1 -1
  31. package/dist/actions/team-settings.d.mts +1 -1
  32. package/dist/actions/team-settings.d.ts +1 -1
  33. package/dist/actions/team-settings.js +13 -3
  34. package/dist/actions/team-settings.js.map +1 -1
  35. package/dist/actions/trial-signup-actions.js +13 -3
  36. package/dist/actions/trial-signup-actions.js.map +1 -1
  37. package/dist/actions/trial-signup.js +13 -3
  38. package/dist/actions/trial-signup.js.map +1 -1
  39. package/dist/actions/user-settings.d.mts +1 -1
  40. package/dist/actions/user-settings.d.ts +1 -1
  41. package/dist/actions/user-settings.js +13 -3
  42. package/dist/actions/user-settings.js.map +1 -1
  43. package/dist/airgap-instances.d.mts +1 -1
  44. package/dist/airgap-instances.d.ts +1 -1
  45. package/dist/api/saml.js +13 -3
  46. package/dist/api/saml.js.map +1 -1
  47. package/dist/api/support-bundles.js +13 -3
  48. package/dist/api/support-bundles.js.map +1 -1
  49. package/dist/{branding-DmsrDTNE.d.mts → branding-C5H0L6Vi.d.mts} +13 -1
  50. package/dist/{branding-DmsrDTNE.d.ts → branding-C5H0L6Vi.d.ts} +13 -1
  51. package/dist/esm/actions/branding-actions.js +15 -5
  52. package/dist/esm/actions/branding-actions.js.map +1 -1
  53. package/dist/esm/actions/change-team.js +13 -3
  54. package/dist/esm/actions/change-team.js.map +1 -1
  55. package/dist/esm/actions/index.js +16 -15
  56. package/dist/esm/actions/index.js.map +1 -1
  57. package/dist/esm/actions/install-actions.js +13 -3
  58. package/dist/esm/actions/install-actions.js.map +1 -1
  59. package/dist/esm/actions/invite-actions.js +13 -3
  60. package/dist/esm/actions/invite-actions.js.map +1 -1
  61. package/dist/esm/actions/magic-link-actions.js +15 -5
  62. package/dist/esm/actions/magic-link-actions.js.map +1 -1
  63. package/dist/esm/actions/service-account.js +13 -3
  64. package/dist/esm/actions/service-account.js.map +1 -1
  65. package/dist/esm/actions/support-bundles.js +13 -3
  66. package/dist/esm/actions/support-bundles.js.map +1 -1
  67. package/dist/esm/actions/team-settings.js +13 -3
  68. package/dist/esm/actions/team-settings.js.map +1 -1
  69. package/dist/esm/actions/trial-signup-actions.js +13 -3
  70. package/dist/esm/actions/trial-signup-actions.js.map +1 -1
  71. package/dist/esm/actions/trial-signup.js +13 -3
  72. package/dist/esm/actions/trial-signup.js.map +1 -1
  73. package/dist/esm/actions/user-settings.js +13 -3
  74. package/dist/esm/actions/user-settings.js.map +1 -1
  75. package/dist/esm/api/saml.js +13 -3
  76. package/dist/esm/api/saml.js.map +1 -1
  77. package/dist/esm/api/support-bundles.js +13 -3
  78. package/dist/esm/api/support-bundles.js.map +1 -1
  79. package/dist/esm/helm-install-wizard.js +13 -3
  80. package/dist/esm/helm-install-wizard.js.map +1 -1
  81. package/dist/esm/index.js +51 -9
  82. package/dist/esm/index.js.map +1 -1
  83. package/dist/esm/install-actions.js +13 -3
  84. package/dist/esm/install-actions.js.map +1 -1
  85. package/dist/esm/license-details.js +13 -3
  86. package/dist/esm/license-details.js.map +1 -1
  87. package/dist/esm/linux-install-wizard.js +13 -3
  88. package/dist/esm/linux-install-wizard.js.map +1 -1
  89. package/dist/esm/support-card.js +13 -3
  90. package/dist/esm/support-card.js.map +1 -1
  91. package/dist/esm/top-nav.js +34 -7
  92. package/dist/esm/top-nav.js.map +1 -1
  93. package/dist/esm/update-layout.js +34 -7
  94. package/dist/esm/update-layout.js.map +1 -1
  95. package/dist/esm/use-verify-magic-link.js +4 -3
  96. package/dist/esm/use-verify-magic-link.js.map +1 -1
  97. package/dist/esm/user-menu-dropdown.js +6 -3
  98. package/dist/esm/user-menu-dropdown.js.map +1 -1
  99. package/dist/esm/utils/index.js +44 -5
  100. package/dist/esm/utils/index.js.map +1 -1
  101. package/dist/helm-install-wizard.d.mts +2 -2
  102. package/dist/helm-install-wizard.d.ts +2 -2
  103. package/dist/helm-install-wizard.js +13 -3
  104. package/dist/helm-install-wizard.js.map +1 -1
  105. package/dist/{index-Bcp17Mf3.d.ts → index-7ibNULXY.d.ts} +3 -1
  106. package/dist/{index-DaH1bSuO.d.mts → index-CITwEYtK.d.mts} +3 -1
  107. package/dist/index.d.mts +3 -3
  108. package/dist/index.d.ts +3 -3
  109. package/dist/index.js +51 -8
  110. package/dist/index.js.map +1 -1
  111. package/dist/install-actions.d.mts +2 -2
  112. package/dist/install-actions.d.ts +2 -2
  113. package/dist/install-actions.js +13 -3
  114. package/dist/install-actions.js.map +1 -1
  115. package/dist/instance-card.d.mts +1 -1
  116. package/dist/instance-card.d.ts +1 -1
  117. package/dist/license-details.js +13 -3
  118. package/dist/license-details.js.map +1 -1
  119. package/dist/linux-install-wizard.d.mts +2 -2
  120. package/dist/linux-install-wizard.d.ts +2 -2
  121. package/dist/linux-install-wizard.js +13 -3
  122. package/dist/linux-install-wizard.js.map +1 -1
  123. package/dist/online-instance-list.d.mts +1 -1
  124. package/dist/online-instance-list.d.ts +1 -1
  125. package/dist/pending-installations.d.mts +1 -1
  126. package/dist/pending-installations.d.ts +1 -1
  127. package/dist/security-card.d.mts +1 -1
  128. package/dist/security-card.d.ts +1 -1
  129. package/dist/styles.css +16 -0
  130. package/dist/support-bundles-card.d.mts +1 -1
  131. package/dist/support-bundles-card.d.ts +1 -1
  132. package/dist/support-card.js +13 -3
  133. package/dist/support-card.js.map +1 -1
  134. package/dist/{top-nav-8f2U69MF.d.ts → top-nav-B2FVC4rl.d.ts} +1 -1
  135. package/dist/{top-nav-B2yA3PC7.d.mts → top-nav-Cf8zMq1A.d.mts} +1 -1
  136. package/dist/top-nav.d.mts +2 -2
  137. package/dist/top-nav.d.ts +2 -2
  138. package/dist/top-nav.js +34 -7
  139. package/dist/top-nav.js.map +1 -1
  140. package/dist/update-layout.js +34 -7
  141. package/dist/update-layout.js.map +1 -1
  142. package/dist/use-verify-magic-link.d.mts +3 -2
  143. package/dist/use-verify-magic-link.d.ts +3 -2
  144. package/dist/use-verify-magic-link.js +4 -3
  145. package/dist/use-verify-magic-link.js.map +1 -1
  146. package/dist/user-menu-dropdown.d.mts +2 -1
  147. package/dist/user-menu-dropdown.d.ts +2 -1
  148. package/dist/user-menu-dropdown.js +6 -3
  149. package/dist/user-menu-dropdown.js.map +1 -1
  150. package/dist/utils/index.d.mts +2 -2
  151. package/dist/utils/index.d.ts +2 -2
  152. package/dist/utils/index.js +44 -4
  153. package/dist/utils/index.js.map +1 -1
  154. package/package.json +1 -1
@@ -10,7 +10,8 @@ import { useRouter } from 'next/navigation';
10
10
  function useVerifyMagicLink({
11
11
  verifyAction,
12
12
  onSuccess,
13
- redirectUrl = "/"
13
+ redirectUrl = "/",
14
+ isPreview
14
15
  }) {
15
16
  const router = useRouter();
16
17
  const [state, setState] = useState({ status: "verifying" });
@@ -35,7 +36,7 @@ function useVerifyMagicLink({
35
36
  }
36
37
  if (verifyingRef.current) return;
37
38
  verifyingRef.current = true;
38
- verifyAction(code).then((result) => {
39
+ verifyAction(code, isPreview).then((result) => {
39
40
  if (result.success) {
40
41
  setState({
41
42
  status: "success",
@@ -65,7 +66,7 @@ function useVerifyMagicLink({
65
66
  message: "An unexpected error occurred. Please try again."
66
67
  });
67
68
  });
68
- }, [verifyAction, router, redirectUrl, onSuccess]);
69
+ }, [verifyAction, router, redirectUrl, onSuccess, isPreview]);
69
70
  return state;
70
71
  }
71
72
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/use-verify-magic-link.ts"],"names":[],"mappings":";;;;;;;;AAiCO,SAAS,kBAAA,CAAmB;AAAA,EACjC,YAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA,GAAc;AAChB,CAAA,EAA8B;AAC5B,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,CAAC,OAAO,QAAQ,CAAA,GAAI,SAAsB,EAAE,MAAA,EAAQ,aAAa,CAAA;AACvE,EAAA,MAAM,YAAA,GAAe,OAAO,KAAK,CAAA;AAEjC,EAAA,SAAA,CAAU,MAAM;AAEd,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEnC,IAAA,MAAM,IAAA,GAAO,OAAO,QAAA,CAAS,IAAA;AAE7B,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,MAAA,IAAU,CAAA,EAAG;AAC7B,MAAA,QAAA,CAAS;AAAA,QACP,MAAA,EAAQ,OAAA;AAAA,QACR,OAAA,EAAS;AAAA,OACV,CAAA;AACD,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,IAAA,EAAK,IAAK,EAAA;AAExD,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,QAAA,CAAS;AAAA,QACP,MAAA,EAAQ,OAAA;AAAA,QACR,OAAA,EAAS;AAAA,OACV,CAAA;AACD,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,aAAa,OAAA,EAAS;AAC1B,IAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AAGvB,IAAA,YAAA,CAAa,IAAI,CAAA,CACd,IAAA,CAAK,CAAC,MAAA,KAAW;AAChB,MAAA,IAAI,OAAO,OAAA,EAAS;AAClB,QAAA,QAAA,CAAS;AAAA,UACP,MAAA,EAAQ,SAAA;AAAA,UACR,OAAA,EAAS;AAAA,SACV,CAAA;AAGD,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,SAAA,EAAU;AAAA,QACZ;AAGA,QAAA,UAAA,CAAW,MAAM;AACf,UAAA,MAAA,CAAO,KAAK,WAAW,CAAA;AAAA,QACzB,GAAG,IAAI,CAAA;AAAA,MACT,CAAA,MAAA,IAAW,OAAO,SAAA,EAAW;AAC3B,QAAA,QAAA,CAAS;AAAA,UACP,MAAA,EAAQ,SAAA;AAAA,UACR,OAAA,EAAS,OAAO,OAAA,IAAW;AAAA,SAC5B,CAAA;AAAA,MACH,CAAA,MAAO;AACL,QAAA,QAAA,CAAS;AAAA,UACP,MAAA,EAAQ,OAAA;AAAA,UACR,OAAA,EAAS,OAAO,OAAA,IAAW;AAAA,SAC5B,CAAA;AAAA,MACH;AAAA,IACF,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,GAAA,KAAQ;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,6CAA6C,GAAG,CAAA;AAC9D,MAAA,QAAA,CAAS;AAAA,QACP,MAAA,EAAQ,OAAA;AAAA,QACR,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACL,GAAG,CAAC,YAAA,EAAc,MAAA,EAAQ,WAAA,EAAa,SAAS,CAAC,CAAA;AAEjD,EAAA,OAAO,KAAA;AACT","file":"use-verify-magic-link.js","sourcesContent":["\"use client\";\n\nimport { useEffect, useState, useRef } from \"react\";\nimport { useRouter } from \"next/navigation\";\n\nexport type VerifyState = \n | { status: \"verifying\" }\n | { status: \"success\"; message: string }\n | { status: \"expired\"; message: string }\n | { status: \"error\"; message: string };\n\nexport interface VerifyActionResult {\n success: boolean;\n message?: string;\n isExpired?: boolean;\n}\n\nexport type VerifyAction = (code: string) => Promise<VerifyActionResult>;\n\nexport interface UseVerifyMagicLinkOptions {\n verifyAction: VerifyAction;\n onSuccess?: () => void;\n redirectUrl?: string;\n}\n\n/**\n * Shared hook for magic link and trial signup verification.\n * Extracts the code from URL hash, calls the verification action,\n * handles all error states, and redirects on success.\n * \n * Note: The verifyAction should be selected based on the verification type\n * (regular magic link vs trial signup) before calling this hook.\n */\nexport function useVerifyMagicLink({\n verifyAction,\n onSuccess,\n redirectUrl = \"/\"\n}: UseVerifyMagicLinkOptions) {\n const router = useRouter();\n const [state, setState] = useState<VerifyState>({ status: \"verifying\" });\n const verifyingRef = useRef(false);\n\n useEffect(() => {\n // Extract code from URL hash\n if (typeof window === \"undefined\") return;\n\n const hash = window.location.hash;\n \n if (!hash || hash.length <= 1) {\n setState({ \n status: \"error\", \n message: \"No verification code found. Please use the link from your email.\" \n });\n return;\n }\n\n // Remove the # and any trailing path segments, trim whitespace\n const code = hash.substring(1).split(\"/\")[0]?.trim() || \"\";\n \n if (!code) {\n setState({ \n status: \"error\", \n message: \"Invalid verification code. Please use the link from your email.\" \n });\n return;\n }\n\n // Prevent duplicate verification attempts\n if (verifyingRef.current) return;\n verifyingRef.current = true;\n\n // Auto-verify on mount\n verifyAction(code)\n .then((result) => {\n if (result.success) {\n setState({ \n status: \"success\", \n message: \"Verified! Redirecting to the portal...\" \n });\n \n // Call success callback if provided\n if (onSuccess) {\n onSuccess();\n }\n \n // Redirect to dashboard after a short delay\n setTimeout(() => {\n router.push(redirectUrl);\n }, 1500);\n } else if (result.isExpired) {\n setState({ \n status: \"expired\", \n message: result.message || \"Magic link has expired. A new link has been sent to your email.\" \n });\n } else {\n setState({ \n status: \"error\", \n message: result.message || \"Failed to verify. Please try again.\" \n });\n }\n })\n .catch((err) => {\n console.error(\"[use-verify-magic-link] Unexpected error:\", err);\n setState({ \n status: \"error\", \n message: \"An unexpected error occurred. Please try again.\" \n });\n });\n }, [verifyAction, router, redirectUrl, onSuccess]);\n\n return state;\n}\n"]}
1
+ {"version":3,"sources":["../../src/hooks/use-verify-magic-link.ts"],"names":[],"mappings":";;;;;;;;AAkCO,SAAS,kBAAA,CAAmB;AAAA,EACjC,YAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA,GAAc,GAAA;AAAA,EACd;AACF,CAAA,EAA8B;AAC5B,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,CAAC,OAAO,QAAQ,CAAA,GAAI,SAAsB,EAAE,MAAA,EAAQ,aAAa,CAAA;AACvE,EAAA,MAAM,YAAA,GAAe,OAAO,KAAK,CAAA;AAEjC,EAAA,SAAA,CAAU,MAAM;AAEd,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAEnC,IAAA,MAAM,IAAA,GAAO,OAAO,QAAA,CAAS,IAAA;AAE7B,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,MAAA,IAAU,CAAA,EAAG;AAC7B,MAAA,QAAA,CAAS;AAAA,QACP,MAAA,EAAQ,OAAA;AAAA,QACR,OAAA,EAAS;AAAA,OACV,CAAA;AACD,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,IAAA,EAAK,IAAK,EAAA;AAExD,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,QAAA,CAAS;AAAA,QACP,MAAA,EAAQ,OAAA;AAAA,QACR,OAAA,EAAS;AAAA,OACV,CAAA;AACD,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,aAAa,OAAA,EAAS;AAC1B,IAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AAGvB,IAAA,YAAA,CAAa,IAAA,EAAM,SAAS,CAAA,CACzB,IAAA,CAAK,CAAC,MAAA,KAAW;AAChB,MAAA,IAAI,OAAO,OAAA,EAAS;AAClB,QAAA,QAAA,CAAS;AAAA,UACP,MAAA,EAAQ,SAAA;AAAA,UACR,OAAA,EAAS;AAAA,SACV,CAAA;AAGD,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,SAAA,EAAU;AAAA,QACZ;AAGA,QAAA,UAAA,CAAW,MAAM;AACf,UAAA,MAAA,CAAO,KAAK,WAAW,CAAA;AAAA,QACzB,GAAG,IAAI,CAAA;AAAA,MACT,CAAA,MAAA,IAAW,OAAO,SAAA,EAAW;AAC3B,QAAA,QAAA,CAAS;AAAA,UACP,MAAA,EAAQ,SAAA;AAAA,UACR,OAAA,EAAS,OAAO,OAAA,IAAW;AAAA,SAC5B,CAAA;AAAA,MACH,CAAA,MAAO;AACL,QAAA,QAAA,CAAS;AAAA,UACP,MAAA,EAAQ,OAAA;AAAA,UACR,OAAA,EAAS,OAAO,OAAA,IAAW;AAAA,SAC5B,CAAA;AAAA,MACH;AAAA,IACF,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,GAAA,KAAQ;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,6CAA6C,GAAG,CAAA;AAC9D,MAAA,QAAA,CAAS;AAAA,QACP,MAAA,EAAQ,OAAA;AAAA,QACR,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACL,GAAG,CAAC,YAAA,EAAc,QAAQ,WAAA,EAAa,SAAA,EAAW,SAAS,CAAC,CAAA;AAE5D,EAAA,OAAO,KAAA;AACT","file":"use-verify-magic-link.js","sourcesContent":["\"use client\";\n\nimport { useEffect, useState, useRef } from \"react\";\nimport { useRouter } from \"next/navigation\";\n\nexport type VerifyState = \n | { status: \"verifying\" }\n | { status: \"success\"; message: string }\n | { status: \"expired\"; message: string }\n | { status: \"error\"; message: string };\n\nexport interface VerifyActionResult {\n success: boolean;\n message?: string;\n isExpired?: boolean;\n}\n\nexport type VerifyAction = (code: string, isPreview?: boolean) => Promise<VerifyActionResult>;\n\nexport interface UseVerifyMagicLinkOptions {\n verifyAction: VerifyAction;\n onSuccess?: () => void;\n redirectUrl?: string;\n isPreview?: boolean;\n}\n\n/**\n * Shared hook for magic link and trial signup verification.\n * Extracts the code from URL hash, calls the verification action,\n * handles all error states, and redirects on success.\n * \n * Note: The verifyAction should be selected based on the verification type\n * (regular magic link vs trial signup) before calling this hook.\n */\nexport function useVerifyMagicLink({\n verifyAction,\n onSuccess,\n redirectUrl = \"/\",\n isPreview\n}: UseVerifyMagicLinkOptions) {\n const router = useRouter();\n const [state, setState] = useState<VerifyState>({ status: \"verifying\" });\n const verifyingRef = useRef(false);\n\n useEffect(() => {\n // Extract code from URL hash\n if (typeof window === \"undefined\") return;\n\n const hash = window.location.hash;\n \n if (!hash || hash.length <= 1) {\n setState({ \n status: \"error\", \n message: \"No verification code found. Please use the link from your email.\" \n });\n return;\n }\n\n // Remove the # and any trailing path segments, trim whitespace\n const code = hash.substring(1).split(\"/\")[0]?.trim() || \"\";\n \n if (!code) {\n setState({ \n status: \"error\", \n message: \"Invalid verification code. Please use the link from your email.\" \n });\n return;\n }\n\n // Prevent duplicate verification attempts\n if (verifyingRef.current) return;\n verifyingRef.current = true;\n\n // Auto-verify on mount\n verifyAction(code, isPreview)\n .then((result) => {\n if (result.success) {\n setState({ \n status: \"success\", \n message: \"Verified! Redirecting to the portal...\" \n });\n \n // Call success callback if provided\n if (onSuccess) {\n onSuccess();\n }\n \n // Redirect to dashboard after a short delay\n setTimeout(() => {\n router.push(redirectUrl);\n }, 1500);\n } else if (result.isExpired) {\n setState({ \n status: \"expired\", \n message: result.message || \"Magic link has expired. A new link has been sent to your email.\" \n });\n } else {\n setState({ \n status: \"error\", \n message: result.message || \"Failed to verify. Please try again.\" \n });\n }\n })\n .catch((err) => {\n console.error(\"[use-verify-magic-link] Unexpected error:\", err);\n setState({ \n status: \"error\", \n message: \"An unexpected error occurred. Please try again.\" \n });\n });\n }, [verifyAction, router, redirectUrl, onSuccess, isPreview]);\n\n return state;\n}\n"]}
@@ -10,10 +10,13 @@ import Link from 'next/link';
10
10
  function UserMenuDropdown({
11
11
  displayLabel,
12
12
  children,
13
- className = ""
13
+ className = "",
14
+ dark = false
14
15
  }) {
16
+ const summaryClass = dark ? "flex cursor-pointer items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white/90 hover:bg-white/10 transition-colors list-none border border-transparent hover:border-white/20" : "flex cursor-pointer items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors list-none border border-transparent hover:border-gray-200";
17
+ const chevronClass = dark ? "h-4 w-4 text-white/50 transition-transform group-open:rotate-180" : "h-4 w-4 text-gray-500 transition-transform group-open:rotate-180";
15
18
  return /* @__PURE__ */ jsxs("details", { className: `group relative ${className}`, children: [
16
- /* @__PURE__ */ jsxs("summary", { className: "flex cursor-pointer items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors list-none border border-transparent hover:border-gray-200", children: [
19
+ /* @__PURE__ */ jsxs("summary", { className: summaryClass, children: [
17
20
  /* @__PURE__ */ jsx(User, { className: "h-4 w-4" }),
18
21
  /* @__PURE__ */ jsx("span", { children: displayLabel }),
19
22
  /* @__PURE__ */ jsx(
@@ -28,7 +31,7 @@ function UserMenuDropdown({
28
31
  strokeWidth: "2",
29
32
  strokeLinecap: "round",
30
33
  strokeLinejoin: "round",
31
- className: "h-4 w-4 text-gray-500 transition-transform group-open:rotate-180",
34
+ className: chevronClass,
32
35
  children: /* @__PURE__ */ jsx("polyline", { points: "6 9 12 15 18 9" })
33
36
  }
34
37
  )
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/user-menu-dropdown.tsx","../../src/components/user-menu-item.tsx"],"names":["jsx"],"mappings":";;;;;;;;;AAaO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,YAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,GAAY;AACd,CAAA,EAA0B;AACxB,EAAA,uBACE,IAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAW,CAAA,eAAA,EAAkB,SAAS,CAAA,CAAA,EAC7C,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,SAAA,EAAA,EAAQ,WAAU,4LAAA,EACjB,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,WAAU,SAAA,EAAU,CAAA;AAAA,sBAC1B,GAAA,CAAC,UAAM,QAAA,EAAA,YAAA,EAAa,CAAA;AAAA,sBACpB,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAM,4BAAA;AAAA,UACN,KAAA,EAAM,IAAA;AAAA,UACN,MAAA,EAAO,IAAA;AAAA,UACP,OAAA,EAAQ,WAAA;AAAA,UACR,IAAA,EAAK,MAAA;AAAA,UACL,MAAA,EAAO,cAAA;AAAA,UACP,WAAA,EAAY,GAAA;AAAA,UACZ,aAAA,EAAc,OAAA;AAAA,UACd,cAAA,EAAe,OAAA;AAAA,UACf,SAAA,EAAU,kEAAA;AAAA,UAEV,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAS,MAAA,EAAO,gBAAA,EAAiB;AAAA;AAAA;AACpC,KAAA,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6FAAA,EACZ,QAAA,EACH;AAAA,GAAA,EACF,CAAA;AAEJ;AC/BO,SAAS,YAAA,CAAa,EAAE,IAAA,EAAM,QAAA,EAAS,EAAsB;AAClE,EAAA,uBACEA,GAAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,SAAA,EAAU,mFAAA;AAAA,MAET;AAAA;AAAA,GACH;AAEJ","file":"user-menu-dropdown.js","sourcesContent":["import type { ReactNode } from \"react\";\nimport { User } from \"lucide-react\";\n\nexport interface UserMenuDropdownProps {\n displayLabel: string;\n children: ReactNode;\n className?: string;\n}\n\n/**\n * Reusable user menu dropdown component using HTML details element.\n * Works with TopNavMenuClose for click-away behavior.\n */\nexport function UserMenuDropdown({ \n displayLabel, \n children, \n className = \"\" \n}: UserMenuDropdownProps) {\n return (\n <details className={`group relative ${className}`}>\n <summary className=\"flex cursor-pointer items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors list-none border border-transparent hover:border-gray-200\">\n <User className=\"h-4 w-4\" />\n <span>{displayLabel}</span>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"h-4 w-4 text-gray-500 transition-transform group-open:rotate-180\"\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </summary>\n <div className=\"absolute right-0 mt-2 w-52 rounded-lg border border-gray-200 bg-white py-1.5 shadow-xl z-50\">\n {children}\n </div>\n </details>\n );\n}\n","import type { ReactNode } from \"react\";\nimport Link from \"next/link\";\n\nexport interface UserMenuItemProps {\n href: string;\n children: ReactNode;\n}\n\n/**\n * Styled menu item for use within UserMenuDropdown.\n * Provides consistent styling across all portal templates.\n */\nexport function UserMenuItem({ href, children }: UserMenuItemProps) {\n return (\n <Link\n href={href}\n className=\"block w-full px-4 py-2.5 text-sm text-gray-700 hover:bg-gray-50 transition-colors\"\n >\n {children}\n </Link>\n );\n}\n"]}
1
+ {"version":3,"sources":["../../src/components/user-menu-dropdown.tsx","../../src/components/user-menu-item.tsx"],"names":["jsx"],"mappings":";;;;;;;;;AAcO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,YAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,IAAA,GAAO;AACT,CAAA,EAA0B;AACxB,EAAA,MAAM,YAAA,GAAe,OACjB,6LAAA,GACA,4LAAA;AACJ,EAAA,MAAM,YAAA,GAAe,OACjB,kEAAA,GACA,kEAAA;AAEJ,EAAA,uBACE,IAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAW,CAAA,eAAA,EAAkB,SAAS,CAAA,CAAA,EAC7C,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,SAAA,EAAA,EAAQ,WAAW,YAAA,EAClB,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,WAAU,SAAA,EAAU,CAAA;AAAA,sBAC1B,GAAA,CAAC,UAAM,QAAA,EAAA,YAAA,EAAa,CAAA;AAAA,sBACpB,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAM,4BAAA;AAAA,UACN,KAAA,EAAM,IAAA;AAAA,UACN,MAAA,EAAO,IAAA;AAAA,UACP,OAAA,EAAQ,WAAA;AAAA,UACR,IAAA,EAAK,MAAA;AAAA,UACL,MAAA,EAAO,cAAA;AAAA,UACP,WAAA,EAAY,GAAA;AAAA,UACZ,aAAA,EAAc,OAAA;AAAA,UACd,cAAA,EAAe,OAAA;AAAA,UACf,SAAA,EAAW,YAAA;AAAA,UAEX,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAS,MAAA,EAAO,gBAAA,EAAiB;AAAA;AAAA;AACpC,KAAA,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6FAAA,EACZ,QAAA,EACH;AAAA,GAAA,EACF,CAAA;AAEJ;ACxCO,SAAS,YAAA,CAAa,EAAE,IAAA,EAAM,QAAA,EAAS,EAAsB;AAClE,EAAA,uBACEA,GAAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,SAAA,EAAU,mFAAA;AAAA,MAET;AAAA;AAAA,GACH;AAEJ","file":"user-menu-dropdown.js","sourcesContent":["import type { ReactNode } from \"react\";\nimport { User } from \"lucide-react\";\n\nexport interface UserMenuDropdownProps {\n displayLabel: string;\n children: ReactNode;\n className?: string;\n dark?: boolean;\n}\n\n/**\n * Reusable user menu dropdown component using HTML details element.\n * Works with TopNavMenuClose for click-away behavior.\n */\nexport function UserMenuDropdown({\n displayLabel,\n children,\n className = \"\",\n dark = false\n}: UserMenuDropdownProps) {\n const summaryClass = dark\n ? \"flex cursor-pointer items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white/90 hover:bg-white/10 transition-colors list-none border border-transparent hover:border-white/20\"\n : \"flex cursor-pointer items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors list-none border border-transparent hover:border-gray-200\";\n const chevronClass = dark\n ? \"h-4 w-4 text-white/50 transition-transform group-open:rotate-180\"\n : \"h-4 w-4 text-gray-500 transition-transform group-open:rotate-180\";\n\n return (\n <details className={`group relative ${className}`}>\n <summary className={summaryClass}>\n <User className=\"h-4 w-4\" />\n <span>{displayLabel}</span>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={chevronClass}\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </summary>\n <div className=\"absolute right-0 mt-2 w-52 rounded-lg border border-gray-200 bg-white py-1.5 shadow-xl z-50\">\n {children}\n </div>\n </details>\n );\n}\n","import type { ReactNode } from \"react\";\nimport Link from \"next/link\";\n\nexport interface UserMenuItemProps {\n href: string;\n children: ReactNode;\n}\n\n/**\n * Styled menu item for use within UserMenuDropdown.\n * Provides consistent styling across all portal templates.\n */\nexport function UserMenuItem({ href, children }: UserMenuItemProps) {\n return (\n <Link\n href={href}\n className=\"block w-full px-4 py-2.5 text-sm text-gray-700 hover:bg-gray-50 transition-colors\"\n >\n {children}\n </Link>\n );\n}\n"]}
@@ -130,6 +130,21 @@ var sanitizeUrlForCss = (url) => {
130
130
  const escaped = trimmed.replace(/\\/g, "\\\\").replace(/\)/g, "\\)").replace(/"/g, '\\"').replace(/'/g, "\\'").replace(/[\x00-\x1F\x7F]/g, "");
131
131
  return escaped;
132
132
  };
133
+ var isDarkColor = (hex) => {
134
+ if (!hex) return false;
135
+ const normalized = normalizeColor(hex);
136
+ if (!normalized) return false;
137
+ let h = normalized.replace("#", "");
138
+ if (h.length === 3) {
139
+ h = h.charAt(0) + h.charAt(0) + h.charAt(1) + h.charAt(1) + h.charAt(2) + h.charAt(2);
140
+ }
141
+ const r = parseInt(h.substring(0, 2), 16) / 255;
142
+ const g = parseInt(h.substring(2, 4), 16) / 255;
143
+ const b = parseInt(h.substring(4, 6), 16) / 255;
144
+ const toLinear = (c) => c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
145
+ const luminance = 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
146
+ return luminance < 0.5;
147
+ };
133
148
  var decodeBranding = ({ brandingData }) => {
134
149
  if (!brandingData || typeof brandingData !== "string") {
135
150
  return {
@@ -155,6 +170,13 @@ var decodeBranding = ({ brandingData }) => {
155
170
  const backgroundImage = sanitizeUrlForCss(parsed.backgroundImage);
156
171
  const backgroundGradientStart = normalizeColor(parsed.customColor1);
157
172
  const backgroundGradientEnd = normalizeColor(parsed.customColor2);
173
+ const headerColor = normalizeColor(parsed.headerColor);
174
+ const headerGradientEnd = normalizeColor(parsed.headerGradientEnd);
175
+ const sidebarColor = normalizeColor(parsed.sidebarColor);
176
+ const sidebarGradientEnd = normalizeColor(parsed.sidebarGradientEnd);
177
+ const contentBackgroundColor = normalizeColor(parsed.contentBackgroundColor);
178
+ const contentBackgroundGradientEnd = normalizeColor(parsed.contentBackgroundGradientEnd);
179
+ const customCSS = typeof parsed.customCSS === "string" ? parsed.customCSS : void 0;
158
180
  return {
159
181
  logo,
160
182
  title,
@@ -166,7 +188,14 @@ var decodeBranding = ({ brandingData }) => {
166
188
  background,
167
189
  backgroundImage,
168
190
  backgroundGradientStart,
169
- backgroundGradientEnd
191
+ backgroundGradientEnd,
192
+ headerColor,
193
+ headerGradientEnd,
194
+ sidebarColor,
195
+ sidebarGradientEnd,
196
+ contentBackgroundColor,
197
+ contentBackgroundGradientEnd,
198
+ customCSS
170
199
  };
171
200
  } catch (error) {
172
201
  console.debug("[portal-components] unable to parse branding JSON", error);
@@ -181,14 +210,17 @@ var decodeBranding = ({ brandingData }) => {
181
210
  var getApiOrigin = () => {
182
211
  return (process.env.REPLICATED_APP_ORIGIN || "https://replicated.app").replace(/\/+$/, "");
183
212
  };
184
- var fetchCustomBrandingImpl = async () => {
213
+ var fetchCustomBrandingImpl = async (version) => {
185
214
  const appSlug = process.env.PORTAL_APP_SLUG;
186
215
  if (!appSlug) {
187
216
  throw new Error("PORTAL_APP_SLUG is not configured");
188
217
  }
189
- const url = `${getApiOrigin()}/enterprise-portal/public/branding?app_slug=${encodeURIComponent(
218
+ let url = `${getApiOrigin()}/enterprise-portal/public/branding?app_slug=${encodeURIComponent(
190
219
  appSlug
191
220
  )}`;
221
+ if (version) {
222
+ url += `&version=${encodeURIComponent(version)}`;
223
+ }
192
224
  if (process.env.NODE_ENV !== "production") {
193
225
  console.debug(
194
226
  "[portal-components] fetching custom branding via %s (Enterprise Portal API)",
@@ -217,7 +249,14 @@ var fetchCustomBrandingImpl = async () => {
217
249
  background: payload.background,
218
250
  backgroundImage: payload.backgroundImage,
219
251
  customColor1: payload.customColor1,
220
- customColor2: payload.customColor2
252
+ customColor2: payload.customColor2,
253
+ headerColor: payload.headerColor,
254
+ headerGradientEnd: payload.headerGradientEnd,
255
+ sidebarColor: payload.sidebarColor,
256
+ sidebarGradientEnd: payload.sidebarGradientEnd,
257
+ contentBackgroundColor: payload.contentBackgroundColor,
258
+ contentBackgroundGradientEnd: payload.contentBackgroundGradientEnd,
259
+ customCSS: payload.customCSS
221
260
  };
222
261
  const brandingData = Buffer.from(JSON.stringify(brandingObject)).toString("base64");
223
262
  return {
@@ -440,6 +479,6 @@ async function uploadSupportBundleWithProgress(file, appId, onProgress, signal)
440
479
  });
441
480
  }
442
481
 
443
- export { DEFAULT_FAVICON, DEFAULT_PRIMARY_COLOR, DEFAULT_SECONDARY_COLOR, UnauthorizedError, authenticatedFetch, convertToReleaseEntry, decodeBranding, formatBytes, formatDate, formatDateShort, formatDateTime, formatDateTimeLocal, isHttpApiOrigin, isRedirectError, normalizeColor, sanitizeUrlForCss, uploadSupportBundleWithProgress, validateSession };
482
+ export { DEFAULT_FAVICON, DEFAULT_PRIMARY_COLOR, DEFAULT_SECONDARY_COLOR, UnauthorizedError, authenticatedFetch, convertToReleaseEntry, decodeBranding, formatBytes, formatDate, formatDateShort, formatDateTime, formatDateTimeLocal, isDarkColor, isHttpApiOrigin, isRedirectError, normalizeColor, sanitizeUrlForCss, uploadSupportBundleWithProgress, validateSession };
444
483
  //# sourceMappingURL=index.js.map
445
484
  //# sourceMappingURL=index.js.map