@replicated/portal-components 0.0.19 → 0.0.21

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 (244) hide show
  1. package/components/metadata/registry.json +2 -2
  2. package/components/metadata/registry.md +2 -2
  3. package/dist/actions/change-team.js +66 -7
  4. package/dist/actions/change-team.js.map +1 -1
  5. package/dist/actions/index.d.mts +3 -1
  6. package/dist/actions/index.d.ts +3 -1
  7. package/dist/actions/index.js +182 -465
  8. package/dist/actions/index.js.map +1 -1
  9. package/dist/actions/install-actions.d.mts +3 -1
  10. package/dist/actions/install-actions.d.ts +3 -1
  11. package/dist/actions/install-actions.js +58 -5
  12. package/dist/actions/install-actions.js.map +1 -1
  13. package/dist/actions/service-account.d.mts +3 -1
  14. package/dist/actions/service-account.d.ts +3 -1
  15. package/dist/actions/service-account.js +58 -5
  16. package/dist/actions/service-account.js.map +1 -1
  17. package/dist/actions/support-bundles.d.mts +3 -1
  18. package/dist/actions/support-bundles.d.ts +3 -1
  19. package/dist/actions/support-bundles.js +58 -5
  20. package/dist/actions/support-bundles.js.map +1 -1
  21. package/dist/actions/team-settings.d.mts +3 -1
  22. package/dist/actions/team-settings.d.ts +3 -1
  23. package/dist/actions/team-settings.js +91 -27
  24. package/dist/actions/team-settings.js.map +1 -1
  25. package/dist/actions/trial-signup.d.mts +24 -0
  26. package/dist/actions/trial-signup.d.ts +24 -0
  27. package/dist/actions/trial-signup.js +482 -0
  28. package/dist/actions/trial-signup.js.map +1 -0
  29. package/dist/actions/user-settings.d.mts +3 -1
  30. package/dist/actions/user-settings.d.ts +3 -1
  31. package/dist/actions/user-settings.js +58 -5
  32. package/dist/actions/user-settings.js.map +1 -1
  33. package/dist/airgap-instances.d.mts +3 -1
  34. package/dist/airgap-instances.d.ts +3 -1
  35. package/dist/airgap-instances.js +41 -112
  36. package/dist/airgap-instances.js.map +1 -1
  37. package/dist/branding-BsMSywts.d.mts +36 -0
  38. package/dist/branding-BsMSywts.d.ts +36 -0
  39. package/dist/error-page.js +10 -2
  40. package/dist/error-page.js.map +1 -1
  41. package/dist/error.js +10 -2
  42. package/dist/error.js.map +1 -1
  43. package/dist/esm/actions/change-team.js +66 -7
  44. package/dist/esm/actions/change-team.js.map +1 -1
  45. package/dist/esm/actions/index.js +181 -462
  46. package/dist/esm/actions/index.js.map +1 -1
  47. package/dist/esm/actions/install-actions.js +58 -5
  48. package/dist/esm/actions/install-actions.js.map +1 -1
  49. package/dist/esm/actions/service-account.js +58 -5
  50. package/dist/esm/actions/service-account.js.map +1 -1
  51. package/dist/esm/actions/support-bundles.js +58 -5
  52. package/dist/esm/actions/support-bundles.js.map +1 -1
  53. package/dist/esm/actions/team-settings.js +91 -27
  54. package/dist/esm/actions/team-settings.js.map +1 -1
  55. package/dist/esm/actions/trial-signup.js +478 -0
  56. package/dist/esm/actions/trial-signup.js.map +1 -0
  57. package/dist/esm/actions/user-settings.js +58 -5
  58. package/dist/esm/actions/user-settings.js.map +1 -1
  59. package/dist/esm/airgap-instances.js +40 -112
  60. package/dist/esm/airgap-instances.js.map +1 -1
  61. package/dist/esm/error-page.js +10 -2
  62. package/dist/esm/error-page.js.map +1 -1
  63. package/dist/esm/error.js +10 -2
  64. package/dist/esm/error.js.map +1 -1
  65. package/dist/esm/helm-install-wizard.js +118 -79
  66. package/dist/esm/helm-install-wizard.js.map +1 -1
  67. package/dist/esm/index.js +706 -438
  68. package/dist/esm/index.js.map +1 -1
  69. package/dist/esm/install-actions.js +40 -5
  70. package/dist/esm/install-actions.js.map +1 -1
  71. package/dist/esm/install-card.js +9 -6
  72. package/dist/esm/install-card.js.map +1 -1
  73. package/dist/esm/install-targets.js +9 -2
  74. package/dist/esm/install-targets.js.map +1 -1
  75. package/dist/esm/instance-card.js +39 -111
  76. package/dist/esm/instance-card.js.map +1 -1
  77. package/dist/esm/join-team.js +9 -3
  78. package/dist/esm/join-team.js.map +1 -1
  79. package/dist/esm/license-card.js +24 -22
  80. package/dist/esm/license-card.js.map +1 -1
  81. package/dist/esm/license-details.js +128 -334
  82. package/dist/esm/license-details.js.map +1 -1
  83. package/dist/esm/linux-install-wizard.js +95 -41
  84. package/dist/esm/linux-install-wizard.js.map +1 -1
  85. package/dist/esm/login.js +20 -4
  86. package/dist/esm/login.js.map +1 -1
  87. package/dist/esm/middleware.js +33 -0
  88. package/dist/esm/middleware.js.map +1 -0
  89. package/dist/esm/online-instance-list.js +40 -112
  90. package/dist/esm/online-instance-list.js.map +1 -1
  91. package/dist/esm/release-history-panel.js +27 -14
  92. package/dist/esm/release-history-panel.js.map +1 -1
  93. package/dist/esm/saml-callback-client.js +82 -0
  94. package/dist/esm/saml-callback-client.js.map +1 -0
  95. package/dist/esm/saml-handlers.js +138 -0
  96. package/dist/esm/saml-handlers.js.map +1 -0
  97. package/dist/esm/security-card.js +53 -38
  98. package/dist/esm/security-card.js.map +1 -1
  99. package/dist/esm/service-accounts-tab.js +800 -0
  100. package/dist/esm/service-accounts-tab.js.map +1 -0
  101. package/dist/esm/support-bundle-collection-card.js +48 -24
  102. package/dist/esm/support-bundle-collection-card.js.map +1 -1
  103. package/dist/esm/support-bundles-card.js +10 -5
  104. package/dist/esm/support-bundles-card.js.map +1 -1
  105. package/dist/esm/support-card.js +37 -5
  106. package/dist/esm/support-card.js.map +1 -1
  107. package/dist/esm/team-selection.js +5 -1
  108. package/dist/esm/team-selection.js.map +1 -1
  109. package/dist/esm/team-settings-card.js +5 -2
  110. package/dist/esm/team-settings-card.js.map +1 -1
  111. package/dist/esm/team-settings.js +7 -2
  112. package/dist/esm/team-settings.js.map +1 -1
  113. package/dist/esm/top-nav-user-menu.js +5 -1
  114. package/dist/esm/top-nav-user-menu.js.map +1 -1
  115. package/dist/esm/top-nav.js +175 -62
  116. package/dist/esm/top-nav.js.map +1 -1
  117. package/dist/esm/trial-signup.js +256 -0
  118. package/dist/esm/trial-signup.js.map +1 -0
  119. package/dist/esm/update-layout.js +175 -62
  120. package/dist/esm/update-layout.js.map +1 -1
  121. package/dist/esm/updates-card.js +15 -4
  122. package/dist/esm/updates-card.js.map +1 -1
  123. package/dist/esm/upload-support-bundle-modal.js +9 -4
  124. package/dist/esm/upload-support-bundle-modal.js.map +1 -1
  125. package/dist/esm/user-settings-card.js +5 -2
  126. package/dist/esm/user-settings-card.js.map +1 -1
  127. package/dist/esm/user-settings.js +12 -6
  128. package/dist/esm/user-settings.js.map +1 -1
  129. package/dist/esm/utils/index.js +204 -13
  130. package/dist/esm/utils/index.js.map +1 -1
  131. package/dist/fetch-license-iTyF7_GY.d.mts +81 -0
  132. package/dist/fetch-license-iTyF7_GY.d.ts +81 -0
  133. package/dist/helm-install-wizard.d.mts +11 -3
  134. package/dist/helm-install-wizard.d.ts +11 -3
  135. package/dist/helm-install-wizard.js +118 -79
  136. package/dist/helm-install-wizard.js.map +1 -1
  137. package/dist/{index-BAiVrSSR.d.mts → index-DyzJ0yKD.d.mts} +48 -50
  138. package/dist/{index-DWt-N5od.d.ts → index-sMbq94M7.d.ts} +48 -50
  139. package/dist/index.d.mts +8 -2
  140. package/dist/index.d.ts +8 -2
  141. package/dist/index.js +726 -438
  142. package/dist/index.js.map +1 -1
  143. package/dist/install-actions.d.mts +4 -2
  144. package/dist/install-actions.d.ts +4 -2
  145. package/dist/install-actions.js +40 -5
  146. package/dist/install-actions.js.map +1 -1
  147. package/dist/install-card.d.mts +2 -3
  148. package/dist/install-card.d.ts +2 -3
  149. package/dist/install-card.js +9 -6
  150. package/dist/install-card.js.map +1 -1
  151. package/dist/install-targets.js +9 -2
  152. package/dist/install-targets.js.map +1 -1
  153. package/dist/instance-card.d.mts +3 -1
  154. package/dist/instance-card.d.ts +3 -1
  155. package/dist/instance-card.js +40 -111
  156. package/dist/instance-card.js.map +1 -1
  157. package/dist/join-team.js +9 -3
  158. package/dist/join-team.js.map +1 -1
  159. package/dist/license-card.d.mts +2 -3
  160. package/dist/license-card.d.ts +2 -3
  161. package/dist/license-card.js +24 -22
  162. package/dist/license-card.js.map +1 -1
  163. package/dist/license-details.js +128 -334
  164. package/dist/license-details.js.map +1 -1
  165. package/dist/linux-install-wizard.d.mts +9 -3
  166. package/dist/linux-install-wizard.d.ts +9 -3
  167. package/dist/linux-install-wizard.js +95 -41
  168. package/dist/linux-install-wizard.js.map +1 -1
  169. package/dist/login.d.mts +4 -0
  170. package/dist/login.d.ts +4 -0
  171. package/dist/login.js +20 -4
  172. package/dist/login.js.map +1 -1
  173. package/dist/middleware.d.mts +13 -0
  174. package/dist/middleware.d.ts +13 -0
  175. package/dist/middleware.js +35 -0
  176. package/dist/middleware.js.map +1 -0
  177. package/dist/online-instance-list.d.mts +3 -1
  178. package/dist/online-instance-list.d.ts +3 -1
  179. package/dist/online-instance-list.js +41 -112
  180. package/dist/online-instance-list.js.map +1 -1
  181. package/dist/pending-installations.d.mts +3 -1
  182. package/dist/pending-installations.d.ts +3 -1
  183. package/dist/release-history-panel.js +27 -14
  184. package/dist/release-history-panel.js.map +1 -1
  185. package/dist/saml-callback-client.d.mts +36 -0
  186. package/dist/saml-callback-client.d.ts +36 -0
  187. package/dist/saml-callback-client.js +88 -0
  188. package/dist/saml-callback-client.js.map +1 -0
  189. package/dist/saml-handlers.d.mts +50 -0
  190. package/dist/saml-handlers.d.ts +50 -0
  191. package/dist/saml-handlers.js +141 -0
  192. package/dist/saml-handlers.js.map +1 -0
  193. package/dist/security-card.d.mts +3 -1
  194. package/dist/security-card.d.ts +3 -1
  195. package/dist/security-card.js +53 -38
  196. package/dist/security-card.js.map +1 -1
  197. package/dist/service-accounts-tab.d.mts +51 -0
  198. package/dist/service-accounts-tab.d.ts +51 -0
  199. package/dist/service-accounts-tab.js +802 -0
  200. package/dist/service-accounts-tab.js.map +1 -0
  201. package/dist/styles.css +375 -127
  202. package/dist/support-bundle-collection-card.d.mts +1 -1
  203. package/dist/support-bundle-collection-card.d.ts +1 -1
  204. package/dist/support-bundle-collection-card.js +47 -23
  205. package/dist/support-bundle-collection-card.js.map +1 -1
  206. package/dist/support-bundles-card.d.mts +4 -2
  207. package/dist/support-bundles-card.d.ts +4 -2
  208. package/dist/support-bundles-card.js +10 -5
  209. package/dist/support-bundles-card.js.map +1 -1
  210. package/dist/support-card.js +37 -5
  211. package/dist/support-card.js.map +1 -1
  212. package/dist/team-selection.js +5 -1
  213. package/dist/team-selection.js.map +1 -1
  214. package/dist/team-settings-card.js +5 -2
  215. package/dist/team-settings-card.js.map +1 -1
  216. package/dist/team-settings.js +7 -2
  217. package/dist/team-settings.js.map +1 -1
  218. package/dist/{top-nav-IRIn66wS.d.ts → top-nav-BUQAGoG1.d.mts} +14 -2
  219. package/dist/{top-nav-IRIn66wS.d.mts → top-nav-CEqw0KpO.d.ts} +14 -2
  220. package/dist/top-nav-user-menu.js +5 -1
  221. package/dist/top-nav-user-menu.js.map +1 -1
  222. package/dist/top-nav.d.mts +2 -1
  223. package/dist/top-nav.d.ts +2 -1
  224. package/dist/top-nav.js +175 -62
  225. package/dist/top-nav.js.map +1 -1
  226. package/dist/trial-signup.d.mts +31 -0
  227. package/dist/trial-signup.d.ts +31 -0
  228. package/dist/trial-signup.js +258 -0
  229. package/dist/trial-signup.js.map +1 -0
  230. package/dist/update-layout.js +175 -62
  231. package/dist/update-layout.js.map +1 -1
  232. package/dist/updates-card.js +15 -4
  233. package/dist/updates-card.js.map +1 -1
  234. package/dist/upload-support-bundle-modal.js +9 -4
  235. package/dist/upload-support-bundle-modal.js.map +1 -1
  236. package/dist/user-settings-card.js +5 -2
  237. package/dist/user-settings-card.js.map +1 -1
  238. package/dist/user-settings.js +12 -6
  239. package/dist/user-settings.js.map +1 -1
  240. package/dist/utils/index.d.mts +74 -16
  241. package/dist/utils/index.d.ts +74 -16
  242. package/dist/utils/index.js +215 -12
  243. package/dist/utils/index.js.map +1 -1
  244. package/package.json +37 -2
@@ -1,3 +1,11 @@
1
+ export { d as decodeBranding, n as normalizeColor, s as sanitizeUrlForCss } from '../branding-BsMSywts.js';
2
+ import { a1 as DownloadPortalRelease } from '../index-sMbq94M7.js';
3
+ import { ReleaseEntry } from '../release-history-panel.js';
4
+ import '../fetch-license-iTyF7_GY.js';
5
+ import '../actions/change-team.js';
6
+ import '../actions/trial-signup.js';
7
+ import 'react/jsx-runtime';
8
+
1
9
  /**
2
10
  * Centralized API client utility for handling authenticated requests
3
11
  * with automatic 401 detection, cookie deletion, and redirect.
@@ -25,21 +33,6 @@ declare function isRedirectError(error: unknown): boolean;
25
33
  */
26
34
  declare function authenticatedFetch(url: string, options?: ApiFetchOptions): Promise<Response>;
27
35
 
28
- interface RawBranding {
29
- brandingData?: string;
30
- }
31
- declare const decodeBranding: ({ brandingData }: RawBranding) => {
32
- logo?: undefined;
33
- title?: undefined;
34
- customColor1?: undefined;
35
- customColor2?: undefined;
36
- } | {
37
- logo: string | undefined;
38
- title: string | undefined;
39
- customColor1: string | undefined;
40
- customColor2: string | undefined;
41
- };
42
-
43
36
  /**
44
37
  * Session validation utilities for handling authentication tokens.
45
38
  */
@@ -67,4 +60,69 @@ declare function validateSession(token: string): Promise<boolean>;
67
60
  */
68
61
  declare function deleteSessionCookie(): Promise<void>;
69
62
 
70
- export { UnauthorizedError, authenticatedFetch, decodeBranding, deleteSessionCookie, isRedirectError, validateSession };
63
+ /**
64
+ * Format bytes to human-readable string
65
+ * @param bytes - Number of bytes
66
+ * @param decimals - Number of decimal places (default: 1)
67
+ * @returns Formatted string (e.g., "1.5 MB")
68
+ */
69
+ declare function formatBytes(bytes: number, decimals?: number): string;
70
+ /**
71
+ * Format date string to short numeric date (no time)
72
+ * @param dateString - ISO date string or null/undefined
73
+ * @returns Formatted string (e.g., "01/27/2026") or "Never" if no date
74
+ */
75
+ declare function formatDateShort(dateString?: string | null): string;
76
+ /**
77
+ * Format date string to human-readable local timestamp
78
+ * @param dateString - ISO date string or null/undefined
79
+ * @returns Formatted string (e.g., "Jan 27, 2026, 10:32 PM") or "Never" if no date
80
+ */
81
+ declare function formatDate(dateString?: string | null): string;
82
+ /**
83
+ * Format date string to human-readable UTC timestamp
84
+ * @param dateString - ISO date string
85
+ * @returns Formatted string (e.g., "01/27/2026, 22:32:39 UTC")
86
+ */
87
+ declare function formatDateTime(dateString: string): string;
88
+ /**
89
+ * Format date string to user-friendly local timestamp with 12-hour time
90
+ * @param dateString - ISO date string or null/undefined
91
+ * @returns Formatted string (e.g., "1/27/2026, 10:32 PM") or "N/A" if not provided
92
+ */
93
+ declare function formatDateTimeLocal(dateString?: string | null): string;
94
+
95
+ type ReleaseNotesMode = "markdown" | "items";
96
+ interface ConvertToReleaseEntryOptions {
97
+ releaseNotesMode: ReleaseNotesMode;
98
+ }
99
+ /**
100
+ * Converts a DownloadPortalRelease to a ReleaseEntry for display
101
+ * @param release - The release data from the API
102
+ * @param channelName - The channel name for display
103
+ * @param options - Options for how to format the release entry
104
+ * @returns A ReleaseEntry ready for display
105
+ */
106
+ declare function convertToReleaseEntry(release: DownloadPortalRelease, channelName: string, options: ConvertToReleaseEntryOptions): ReleaseEntry;
107
+
108
+ /**
109
+ * Default globe favicon matching the CiGlobe icon (Circum Icons)
110
+ * Used as fallback when custom branding doesn't provide a favicon
111
+ */
112
+ declare const DEFAULT_FAVICON = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='1.5'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cellipse cx='12' cy='12' rx='4' ry='10'/%3E%3Cpath d='M2 12h20'/%3E%3C/svg%3E";
113
+ /**
114
+ * Default primary brand color
115
+ */
116
+ declare const DEFAULT_PRIMARY_COLOR = "#4f46e5";
117
+ /**
118
+ * Default secondary brand color
119
+ */
120
+ declare const DEFAULT_SECONDARY_COLOR = "#6366f1";
121
+ /**
122
+ * Check if the API origin is HTTP (used for repldev environments)
123
+ * This determines cookie security settings for cross-origin iframes
124
+ * @returns true if the API origin starts with http:// (not https://)
125
+ */
126
+ declare const isHttpApiOrigin: () => boolean;
127
+
128
+ export { type ConvertToReleaseEntryOptions, DEFAULT_FAVICON, DEFAULT_PRIMARY_COLOR, DEFAULT_SECONDARY_COLOR, type ReleaseNotesMode, UnauthorizedError, authenticatedFetch, convertToReleaseEntry, deleteSessionCookie, formatBytes, formatDate, formatDateShort, formatDateTime, formatDateTimeLocal, isHttpApiOrigin, isRedirectError, validateSession };
@@ -7,6 +7,18 @@ var react = require('react');
7
7
  * Enterprise Portal Components
8
8
  * This file is generated by tsup. Do not edit manually.
9
9
  */
10
+ var __defProp = Object.defineProperty;
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+
16
+ // datadog/tracer.ts
17
+ var tracer_exports = {};
18
+ __export(tracer_exports, {
19
+ default: () => tracer_default
20
+ });
21
+ var tracer_default;
10
22
 
11
23
  // src/utils/api-client.ts
12
24
  var UnauthorizedError = class extends Error {
@@ -40,8 +52,17 @@ async function handle401() {
40
52
  const { redirect } = await import('next/navigation');
41
53
  return redirect("/?expired=1");
42
54
  }
55
+ function isErrorPage(url) {
56
+ try {
57
+ const urlObj = new URL(url);
58
+ return urlObj.pathname === "/error";
59
+ } catch {
60
+ return url === "/error" || url.startsWith("/error?");
61
+ }
62
+ }
43
63
  async function handleServerError(statusCode) {
44
64
  const { redirect } = await import('next/navigation');
65
+ const { cookies } = await import('next/headers');
45
66
  let sourceUrl;
46
67
  try {
47
68
  const { headers } = await import('next/headers');
@@ -49,12 +70,20 @@ async function handleServerError(statusCode) {
49
70
  const referer = headersList.get("referer");
50
71
  const host = headersList.get("host");
51
72
  const pathname = headersList.get("x-invoke-path") || headersList.get("x-forwarded-path");
52
- if (referer) {
73
+ if (referer && !isErrorPage(referer)) {
53
74
  sourceUrl = referer;
54
75
  } else if (host && pathname) {
55
76
  const protocol = headersList.get("x-forwarded-proto") || "https";
56
77
  sourceUrl = `${protocol}://${host}${pathname}`;
57
78
  }
79
+ if (!sourceUrl || isErrorPage(sourceUrl)) {
80
+ const cookieStore = await cookies();
81
+ const preservedSource = cookieStore.get("portal_error_source");
82
+ if (preservedSource?.value) {
83
+ sourceUrl = decodeURIComponent(preservedSource.value);
84
+ cookieStore.delete("portal_error_source");
85
+ }
86
+ }
58
87
  } catch (error) {
59
88
  console.debug("[portal-components] Could not determine source URL", error);
60
89
  }
@@ -64,6 +93,16 @@ async function handleServerError(statusCode) {
64
93
  }
65
94
  return redirect(`/error?${params.toString()}`);
66
95
  }
96
+
97
+ // src/utils/constants.ts
98
+ var DEFAULT_FAVICON = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='1.5'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cellipse cx='12' cy='12' rx='4' ry='10'/%3E%3Cpath d='M2 12h20'/%3E%3C/svg%3E";
99
+ var DEFAULT_PRIMARY_COLOR = "#4f46e5";
100
+ var DEFAULT_SECONDARY_COLOR = "#6366f1";
101
+ var isHttpApiOrigin = () => {
102
+ return process.env.REPLICATED_APP_ORIGIN?.startsWith("http://") || false;
103
+ };
104
+
105
+ // src/utils/branding.ts
67
106
  var normalizeColor = (color) => {
68
107
  if (!color || typeof color !== "string") {
69
108
  return void 0;
@@ -72,11 +111,33 @@ var normalizeColor = (color) => {
72
111
  if (/^#?[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/.test(trimmed)) {
73
112
  return trimmed.startsWith("#") ? trimmed : `#${trimmed}`;
74
113
  }
75
- return trimmed;
114
+ console.debug("[portal-components] Invalid color format rejected (only hex supported):", trimmed);
115
+ return void 0;
116
+ };
117
+ var sanitizeUrlForCss = (url) => {
118
+ if (!url || typeof url !== "string") {
119
+ return void 0;
120
+ }
121
+ const trimmed = url.trim();
122
+ try {
123
+ const urlObj = new URL(trimmed);
124
+ if (!["http:", "https:", "data:"].includes(urlObj.protocol)) {
125
+ console.debug("[portal-components] Invalid URL protocol for background image:", urlObj.protocol);
126
+ return void 0;
127
+ }
128
+ } catch {
129
+ console.debug("[portal-components] Invalid URL format for background image:", trimmed);
130
+ return void 0;
131
+ }
132
+ const escaped = trimmed.replace(/\\/g, "\\\\").replace(/\)/g, "\\)").replace(/"/g, '\\"').replace(/'/g, "\\'").replace(/[\x00-\x1F\x7F]/g, "");
133
+ return escaped;
76
134
  };
77
135
  var decodeBranding = ({ brandingData }) => {
78
136
  if (!brandingData || typeof brandingData !== "string") {
79
- return {};
137
+ return {
138
+ primaryColor: DEFAULT_PRIMARY_COLOR,
139
+ secondaryColor: DEFAULT_SECONDARY_COLOR
140
+ };
80
141
  }
81
142
  try {
82
143
  const decoded = buffer.Buffer.from(brandingData, "base64").toString("utf-8");
@@ -84,19 +145,39 @@ var decodeBranding = ({ brandingData }) => {
84
145
  const logo = typeof parsed.logo === "string" ? parsed.logo : void 0;
85
146
  const titleRaw = typeof parsed.title === "string" ? parsed.title.trim() : "";
86
147
  const title = titleRaw ? titleRaw : void 0;
87
- const customColor1 = normalizeColor(parsed.customColor1);
88
- const customColor2 = normalizeColor(parsed.customColor2);
148
+ const favicon = typeof parsed.favicon === "string" ? parsed.favicon : void 0;
149
+ const primaryColorRaw = parsed.primaryColor ?? parsed.primary_color;
150
+ const secondaryColorRaw = parsed.secondaryColor ?? parsed.secondary_color;
151
+ const primaryColor = normalizeColor(primaryColorRaw);
152
+ const secondaryColor = normalizeColor(secondaryColorRaw);
153
+ const supportPortalLink = typeof parsed.supportPortalLink === "string" ? parsed.supportPortalLink : void 0;
154
+ const backgroundRaw = parsed.background;
155
+ const background = backgroundRaw === "minimal" || backgroundRaw === "custom" || backgroundRaw === "image" ? backgroundRaw : void 0;
156
+ const backgroundImage = sanitizeUrlForCss(parsed.backgroundImage);
157
+ const backgroundGradientStart = normalizeColor(parsed.customColor1);
158
+ const backgroundGradientEnd = normalizeColor(parsed.customColor2);
89
159
  return {
90
160
  logo,
91
161
  title,
92
- customColor1,
93
- customColor2
162
+ favicon,
163
+ primaryColor: primaryColor || DEFAULT_PRIMARY_COLOR,
164
+ secondaryColor: secondaryColor || DEFAULT_SECONDARY_COLOR,
165
+ supportPortalLink,
166
+ background,
167
+ backgroundImage,
168
+ backgroundGradientStart,
169
+ backgroundGradientEnd
94
170
  };
95
171
  } catch (error) {
96
172
  console.debug("[portal-components] unable to parse branding JSON", error);
97
- return {};
173
+ return {
174
+ primaryColor: DEFAULT_PRIMARY_COLOR,
175
+ secondaryColor: DEFAULT_SECONDARY_COLOR
176
+ };
98
177
  }
99
178
  };
179
+
180
+ // src/actions/index.ts
100
181
  var getApiOrigin = () => {
101
182
  return (process.env.REPLICATED_APP_ORIGIN || "https://replicated.app").replace(/\/+$/, "");
102
183
  };
@@ -127,11 +208,15 @@ var fetchCustomBrandingImpl = async () => {
127
208
  const payload = await response.json();
128
209
  const brandingObject = {
129
210
  logo: payload.logoUrl,
130
- title: payload.appName,
131
- customColor1: payload.primaryColor,
132
- customColor2: payload.secondaryColor,
211
+ title: payload.title,
212
+ primaryColor: payload.primaryColor,
213
+ secondaryColor: payload.secondaryColor,
133
214
  favicon: payload.faviconUrl,
134
- supportPortalLink: payload.supportPortalLink || ""
215
+ supportPortalLink: payload.supportPortalLink || "",
216
+ background: payload.background,
217
+ backgroundImage: payload.backgroundImage,
218
+ customColor1: payload.customColor1,
219
+ customColor2: payload.customColor2
135
220
  };
136
221
  const brandingData = buffer.Buffer.from(JSON.stringify(brandingObject)).toString("base64");
137
222
  return {
@@ -172,11 +257,129 @@ async function deleteSessionCookie() {
172
257
  cookieStore.delete("portal_session");
173
258
  }
174
259
 
260
+ // src/utils/format.ts
261
+ function formatBytes(bytes, decimals = 1) {
262
+ if (bytes === 0) return "0 Bytes";
263
+ const k = 1024;
264
+ const dm = decimals < 0 ? 0 : decimals;
265
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
266
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
267
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
268
+ }
269
+ function formatDateShort(dateString) {
270
+ if (!dateString) return "Never";
271
+ const date = new Date(dateString);
272
+ if (isNaN(date.getTime())) {
273
+ return dateString;
274
+ }
275
+ return date.toLocaleDateString("en-US", {
276
+ year: "numeric",
277
+ month: "2-digit",
278
+ day: "2-digit"
279
+ });
280
+ }
281
+ function formatDate(dateString) {
282
+ if (!dateString) return "Never";
283
+ const date = new Date(dateString);
284
+ if (isNaN(date.getTime())) {
285
+ return dateString;
286
+ }
287
+ return date.toLocaleDateString("en-US", {
288
+ month: "short",
289
+ day: "numeric",
290
+ year: "numeric",
291
+ hour: "numeric",
292
+ minute: "2-digit",
293
+ hour12: true
294
+ });
295
+ }
296
+ function formatDateTime(dateString) {
297
+ const date = new Date(dateString);
298
+ if (isNaN(date.getTime())) {
299
+ return dateString;
300
+ }
301
+ return date.toLocaleString("en-US", {
302
+ timeZone: "UTC",
303
+ year: "numeric",
304
+ month: "2-digit",
305
+ day: "2-digit",
306
+ hour: "2-digit",
307
+ minute: "2-digit",
308
+ second: "2-digit",
309
+ hour12: false
310
+ }) + " UTC";
311
+ }
312
+ function formatDateTimeLocal(dateString) {
313
+ if (!dateString) return "N/A";
314
+ try {
315
+ const date = new Date(dateString);
316
+ if (isNaN(date.getTime())) {
317
+ return dateString;
318
+ }
319
+ return date.toLocaleDateString("en-US", {
320
+ month: "numeric",
321
+ day: "numeric",
322
+ year: "numeric",
323
+ hour: "numeric",
324
+ minute: "2-digit",
325
+ hour12: true
326
+ });
327
+ } catch {
328
+ return "N/A";
329
+ }
330
+ }
331
+
332
+ // src/utils/release-helpers.ts
333
+ function convertToReleaseEntry(release, channelName, options) {
334
+ const sections = [];
335
+ if (release.release_notes && release.release_notes.trim().length > 0) {
336
+ if (options.releaseNotesMode === "markdown") {
337
+ sections.push({
338
+ title: "Release Notes",
339
+ description: release.release_notes
340
+ });
341
+ } else {
342
+ const releaseNotesItems = release.release_notes.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
343
+ sections.push({
344
+ title: "Release Notes",
345
+ description: releaseNotesItems.length === 0 ? release.release_notes : void 0,
346
+ items: releaseNotesItems.length > 0 ? releaseNotesItems : void 0
347
+ });
348
+ }
349
+ }
350
+ const charts = release.helm_charts ? release.helm_charts.filter((chart) => !chart.is_kots_installer_only).map((chart) => `${chart.name} v${chart.version}`) : [];
351
+ if (charts.length > 0) {
352
+ sections.push({
353
+ title: "Helm Charts",
354
+ items: charts,
355
+ description: "Latest chart versions included in this release."
356
+ });
357
+ }
358
+ return {
359
+ version: release.label || `Release ${release.release_sequence}`,
360
+ channel: channelName || `Channel ${release.channel_sequence}`,
361
+ releasedAt: release.release_date,
362
+ sections
363
+ };
364
+ }
365
+
366
+ exports.DEFAULT_FAVICON = DEFAULT_FAVICON;
367
+ exports.DEFAULT_PRIMARY_COLOR = DEFAULT_PRIMARY_COLOR;
368
+ exports.DEFAULT_SECONDARY_COLOR = DEFAULT_SECONDARY_COLOR;
175
369
  exports.UnauthorizedError = UnauthorizedError;
176
370
  exports.authenticatedFetch = authenticatedFetch;
371
+ exports.convertToReleaseEntry = convertToReleaseEntry;
177
372
  exports.decodeBranding = decodeBranding;
178
373
  exports.deleteSessionCookie = deleteSessionCookie;
374
+ exports.formatBytes = formatBytes;
375
+ exports.formatDate = formatDate;
376
+ exports.formatDateShort = formatDateShort;
377
+ exports.formatDateTime = formatDateTime;
378
+ exports.formatDateTimeLocal = formatDateTimeLocal;
379
+ exports.isHttpApiOrigin = isHttpApiOrigin;
179
380
  exports.isRedirectError = isRedirectError;
381
+ exports.normalizeColor = normalizeColor;
382
+ exports.sanitizeUrlForCss = sanitizeUrlForCss;
180
383
  exports.validateSession = validateSession;
181
384
  //# sourceMappingURL=index.js.map
182
385
  //# sourceMappingURL=index.js.map