@replicated/portal-components 0.0.25 → 0.0.26

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 (168) hide show
  1. package/components/metadata/registry.json +2 -2
  2. package/components/metadata/registry.md +2 -2
  3. package/dist/actions/branding-actions.js +6 -4
  4. package/dist/actions/branding-actions.js.map +1 -1
  5. package/dist/actions/change-team.js +1 -0
  6. package/dist/actions/change-team.js.map +1 -1
  7. package/dist/actions/index.d.mts +1 -1
  8. package/dist/actions/index.d.ts +1 -1
  9. package/dist/actions/index.js +1 -50
  10. package/dist/actions/index.js.map +1 -1
  11. package/dist/actions/install-actions.d.mts +1 -1
  12. package/dist/actions/install-actions.d.ts +1 -1
  13. package/dist/actions/install-actions.js +1 -0
  14. package/dist/actions/install-actions.js.map +1 -1
  15. package/dist/actions/invite-actions.js +6 -5
  16. package/dist/actions/invite-actions.js.map +1 -1
  17. package/dist/actions/magic-link-actions.js +6 -5
  18. package/dist/actions/magic-link-actions.js.map +1 -1
  19. package/dist/actions/service-account.d.mts +1 -1
  20. package/dist/actions/service-account.d.ts +1 -1
  21. package/dist/actions/service-account.js +1 -0
  22. package/dist/actions/service-account.js.map +1 -1
  23. package/dist/actions/support-bundles.d.mts +1 -1
  24. package/dist/actions/support-bundles.d.ts +1 -1
  25. package/dist/actions/support-bundles.js +1 -50
  26. package/dist/actions/support-bundles.js.map +1 -1
  27. package/dist/actions/team-settings.d.mts +1 -1
  28. package/dist/actions/team-settings.d.ts +1 -1
  29. package/dist/actions/team-settings.js +1 -0
  30. package/dist/actions/team-settings.js.map +1 -1
  31. package/dist/actions/trial-signup-actions.js +6 -5
  32. package/dist/actions/trial-signup-actions.js.map +1 -1
  33. package/dist/actions/trial-signup.js +6 -5
  34. package/dist/actions/trial-signup.js.map +1 -1
  35. package/dist/actions/user-settings.d.mts +1 -1
  36. package/dist/actions/user-settings.d.ts +1 -1
  37. package/dist/actions/user-settings.js +1 -0
  38. package/dist/actions/user-settings.js.map +1 -1
  39. package/dist/airgap-instances.d.mts +1 -1
  40. package/dist/airgap-instances.d.ts +1 -1
  41. package/dist/airgap-instances.js +25 -25
  42. package/dist/airgap-instances.js.map +1 -1
  43. package/dist/{saml-handlers.d.mts → api/saml.d.mts} +2 -2
  44. package/dist/{saml-handlers.d.ts → api/saml.d.ts} +2 -2
  45. package/dist/{saml-handlers.js → api/saml.js} +4 -3
  46. package/dist/api/saml.js.map +1 -0
  47. package/dist/api/support-bundles.d.mts +22 -0
  48. package/dist/api/support-bundles.d.ts +22 -0
  49. package/dist/api/support-bundles.js +245 -0
  50. package/dist/api/support-bundles.js.map +1 -0
  51. package/dist/{branding-BsMSywts.d.mts → branding-DmsrDTNE.d.mts} +2 -1
  52. package/dist/{branding-BsMSywts.d.ts → branding-DmsrDTNE.d.ts} +2 -1
  53. package/dist/esm/actions/branding-actions.js +6 -4
  54. package/dist/esm/actions/branding-actions.js.map +1 -1
  55. package/dist/esm/actions/change-team.js +1 -0
  56. package/dist/esm/actions/change-team.js.map +1 -1
  57. package/dist/esm/actions/index.js +2 -50
  58. package/dist/esm/actions/index.js.map +1 -1
  59. package/dist/esm/actions/install-actions.js +1 -0
  60. package/dist/esm/actions/install-actions.js.map +1 -1
  61. package/dist/esm/actions/invite-actions.js +6 -5
  62. package/dist/esm/actions/invite-actions.js.map +1 -1
  63. package/dist/esm/actions/magic-link-actions.js +6 -5
  64. package/dist/esm/actions/magic-link-actions.js.map +1 -1
  65. package/dist/esm/actions/service-account.js +1 -0
  66. package/dist/esm/actions/service-account.js.map +1 -1
  67. package/dist/esm/actions/support-bundles.js +2 -50
  68. package/dist/esm/actions/support-bundles.js.map +1 -1
  69. package/dist/esm/actions/team-settings.js +1 -0
  70. package/dist/esm/actions/team-settings.js.map +1 -1
  71. package/dist/esm/actions/trial-signup-actions.js +6 -5
  72. package/dist/esm/actions/trial-signup-actions.js.map +1 -1
  73. package/dist/esm/actions/trial-signup.js +6 -5
  74. package/dist/esm/actions/trial-signup.js.map +1 -1
  75. package/dist/esm/actions/user-settings.js +1 -0
  76. package/dist/esm/actions/user-settings.js.map +1 -1
  77. package/dist/esm/airgap-instances.js +25 -25
  78. package/dist/esm/airgap-instances.js.map +1 -1
  79. package/dist/esm/{saml-handlers.js → api/saml.js} +4 -3
  80. package/dist/esm/api/saml.js.map +1 -0
  81. package/dist/esm/api/support-bundles.js +243 -0
  82. package/dist/esm/api/support-bundles.js.map +1 -0
  83. package/dist/esm/helm-install-wizard.js +1 -0
  84. package/dist/esm/helm-install-wizard.js.map +1 -1
  85. package/dist/esm/index.js +262 -215
  86. package/dist/esm/index.js.map +1 -1
  87. package/dist/esm/install-actions.js +1 -0
  88. package/dist/esm/install-actions.js.map +1 -1
  89. package/dist/esm/instance-card.js +25 -25
  90. package/dist/esm/instance-card.js.map +1 -1
  91. package/dist/esm/license-details.js +1 -0
  92. package/dist/esm/license-details.js.map +1 -1
  93. package/dist/esm/linux-install-wizard.js +1 -0
  94. package/dist/esm/linux-install-wizard.js.map +1 -1
  95. package/dist/esm/online-instance-list.js +25 -25
  96. package/dist/esm/online-instance-list.js.map +1 -1
  97. package/dist/esm/saml-callback-client.js.map +1 -1
  98. package/dist/esm/support-card.js +1 -0
  99. package/dist/esm/support-card.js.map +1 -1
  100. package/dist/esm/top-nav.js +82 -79
  101. package/dist/esm/top-nav.js.map +1 -1
  102. package/dist/esm/update-layout.js +82 -79
  103. package/dist/esm/update-layout.js.map +1 -1
  104. package/dist/esm/upload-support-bundle-modal.js +46 -16
  105. package/dist/esm/upload-support-bundle-modal.js.map +1 -1
  106. package/dist/esm/utils/index.js +48 -1
  107. package/dist/esm/utils/index.js.map +1 -1
  108. package/dist/helm-install-wizard.d.mts +2 -2
  109. package/dist/helm-install-wizard.d.ts +2 -2
  110. package/dist/helm-install-wizard.js +1 -0
  111. package/dist/helm-install-wizard.js.map +1 -1
  112. package/dist/{index-DXy7RxOX.d.ts → index-Bcp17Mf3.d.ts} +1 -16
  113. package/dist/{index-JX9-CIMA.d.mts → index-DaH1bSuO.d.mts} +1 -16
  114. package/dist/index.d.mts +5 -4
  115. package/dist/index.d.ts +5 -4
  116. package/dist/index.js +262 -214
  117. package/dist/index.js.map +1 -1
  118. package/dist/install-actions.d.mts +2 -2
  119. package/dist/install-actions.d.ts +2 -2
  120. package/dist/install-actions.js +1 -0
  121. package/dist/install-actions.js.map +1 -1
  122. package/dist/instance-card.d.mts +1 -1
  123. package/dist/instance-card.d.ts +1 -1
  124. package/dist/instance-card.js +25 -25
  125. package/dist/instance-card.js.map +1 -1
  126. package/dist/license-details.js +1 -0
  127. package/dist/license-details.js.map +1 -1
  128. package/dist/linux-install-wizard.d.mts +2 -2
  129. package/dist/linux-install-wizard.d.ts +2 -2
  130. package/dist/linux-install-wizard.js +1 -0
  131. package/dist/linux-install-wizard.js.map +1 -1
  132. package/dist/online-instance-list.d.mts +1 -1
  133. package/dist/online-instance-list.d.ts +1 -1
  134. package/dist/online-instance-list.js +25 -25
  135. package/dist/online-instance-list.js.map +1 -1
  136. package/dist/pending-installations.d.mts +1 -1
  137. package/dist/pending-installations.d.ts +1 -1
  138. package/dist/saml-callback-client.d.mts +1 -1
  139. package/dist/saml-callback-client.d.ts +1 -1
  140. package/dist/saml-callback-client.js.map +1 -1
  141. package/dist/security-card.d.mts +1 -1
  142. package/dist/security-card.d.ts +1 -1
  143. package/dist/styles.css +4 -0
  144. package/dist/support-bundles-card.d.mts +1 -1
  145. package/dist/support-bundles-card.d.ts +1 -1
  146. package/dist/support-card.js +1 -0
  147. package/dist/support-card.js.map +1 -1
  148. package/dist/{top-nav-CEqw0KpO.d.ts → top-nav-8f2U69MF.d.ts} +1 -1
  149. package/dist/{top-nav-BUQAGoG1.d.mts → top-nav-B2yA3PC7.d.mts} +1 -1
  150. package/dist/top-nav.d.mts +2 -2
  151. package/dist/top-nav.d.ts +2 -2
  152. package/dist/top-nav.js +82 -79
  153. package/dist/top-nav.js.map +1 -1
  154. package/dist/update-layout.js +82 -79
  155. package/dist/update-layout.js.map +1 -1
  156. package/dist/upload-support-bundle-modal.d.mts +9 -9
  157. package/dist/upload-support-bundle-modal.d.ts +9 -9
  158. package/dist/upload-support-bundle-modal.js +46 -16
  159. package/dist/upload-support-bundle-modal.js.map +1 -1
  160. package/dist/upload-with-progress-D760HthX.d.mts +35 -0
  161. package/dist/upload-with-progress-D760HthX.d.ts +35 -0
  162. package/dist/utils/index.d.mts +3 -2
  163. package/dist/utils/index.d.ts +3 -2
  164. package/dist/utils/index.js +48 -0
  165. package/dist/utils/index.js.map +1 -1
  166. package/package.json +10 -5
  167. package/dist/esm/saml-handlers.js.map +0 -1
  168. package/dist/saml-handlers.js.map +0 -1
package/dist/esm/index.js CHANGED
@@ -121,7 +121,7 @@ var init_tracer = __esm({
121
121
 
122
122
  // package.json
123
123
  var package_default = {
124
- version: "0.0.25"};
124
+ version: "0.0.26"};
125
125
 
126
126
  // src/tokens/index.ts
127
127
  var baseTokens = {
@@ -444,218 +444,6 @@ async function fetchLicenseCore() {
444
444
  var fetchLicenseImpl = cache(fetchLicenseCore);
445
445
  var fetchLicense = fetchLicenseImpl;
446
446
 
447
- // src/utils/constants.ts
448
- 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";
449
- var DEFAULT_PRIMARY_COLOR = "#4f46e5";
450
- var DEFAULT_SECONDARY_COLOR = "#6366f1";
451
- var isHttpApiOrigin = () => {
452
- return process.env.REPLICATED_APP_ORIGIN?.startsWith("http://") || false;
453
- };
454
-
455
- // src/utils/branding.ts
456
- var normalizeColor = (color) => {
457
- if (!color || typeof color !== "string") {
458
- return void 0;
459
- }
460
- const trimmed = color.trim();
461
- if (/^#?[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/.test(trimmed)) {
462
- return trimmed.startsWith("#") ? trimmed : `#${trimmed}`;
463
- }
464
- console.debug("[portal-components] Invalid color format rejected (only hex supported):", trimmed);
465
- return void 0;
466
- };
467
- var sanitizeUrlForCss = (url) => {
468
- if (!url || typeof url !== "string") {
469
- return void 0;
470
- }
471
- const trimmed = url.trim();
472
- try {
473
- const urlObj = new URL(trimmed);
474
- if (!["http:", "https:", "data:"].includes(urlObj.protocol)) {
475
- console.debug("[portal-components] Invalid URL protocol for background image:", urlObj.protocol);
476
- return void 0;
477
- }
478
- } catch {
479
- console.debug("[portal-components] Invalid URL format for background image:", trimmed);
480
- return void 0;
481
- }
482
- const escaped = trimmed.replace(/\\/g, "\\\\").replace(/\)/g, "\\)").replace(/"/g, '\\"').replace(/'/g, "\\'").replace(/[\x00-\x1F\x7F]/g, "");
483
- return escaped;
484
- };
485
- var decodeBranding = ({ brandingData }) => {
486
- if (!brandingData || typeof brandingData !== "string") {
487
- return {
488
- primaryColor: DEFAULT_PRIMARY_COLOR,
489
- secondaryColor: DEFAULT_SECONDARY_COLOR
490
- };
491
- }
492
- try {
493
- const decoded = Buffer.from(brandingData, "base64").toString("utf-8");
494
- const parsed = JSON.parse(decoded);
495
- const logo = typeof parsed.logo === "string" ? parsed.logo : void 0;
496
- const titleRaw = typeof parsed.title === "string" ? parsed.title.trim() : "";
497
- const title = titleRaw ? titleRaw : void 0;
498
- const favicon = typeof parsed.favicon === "string" ? parsed.favicon : void 0;
499
- const primaryColorRaw = parsed.primaryColor ?? parsed.primary_color;
500
- const secondaryColorRaw = parsed.secondaryColor ?? parsed.secondary_color;
501
- const primaryColor = normalizeColor(primaryColorRaw);
502
- const secondaryColor = normalizeColor(secondaryColorRaw);
503
- const supportPortalLink = typeof parsed.supportPortalLink === "string" ? parsed.supportPortalLink : void 0;
504
- const backgroundRaw = parsed.background;
505
- const background = backgroundRaw === "minimal" || backgroundRaw === "custom" || backgroundRaw === "image" ? backgroundRaw : void 0;
506
- const backgroundImage = sanitizeUrlForCss(parsed.backgroundImage);
507
- const backgroundGradientStart = normalizeColor(parsed.customColor1);
508
- const backgroundGradientEnd = normalizeColor(parsed.customColor2);
509
- return {
510
- logo,
511
- title,
512
- favicon,
513
- primaryColor: primaryColor || DEFAULT_PRIMARY_COLOR,
514
- secondaryColor: secondaryColor || DEFAULT_SECONDARY_COLOR,
515
- supportPortalLink,
516
- background,
517
- backgroundImage,
518
- backgroundGradientStart,
519
- backgroundGradientEnd
520
- };
521
- } catch (error) {
522
- console.debug("[portal-components] unable to parse branding JSON", error);
523
- return {
524
- primaryColor: DEFAULT_PRIMARY_COLOR,
525
- secondaryColor: DEFAULT_SECONDARY_COLOR
526
- };
527
- }
528
- };
529
-
530
- // src/utils/session.ts
531
- async function validateSession(token) {
532
- if (!token || typeof token !== "string" || !token.trim()) {
533
- return false;
534
- }
535
- const endpoint = `${getApiOrigin()}/enterprise-portal/user`;
536
- const response = await fetch(endpoint, {
537
- method: "GET",
538
- headers: {
539
- authorization: `Bearer ${token}`
540
- },
541
- // Short timeout for validation
542
- signal: AbortSignal.timeout(5e3)
543
- });
544
- if (response.status === 401) {
545
- return false;
546
- }
547
- if (!response.ok) {
548
- throw new Error(`Session validation failed with status ${response.status}`);
549
- }
550
- return true;
551
- }
552
-
553
- // src/utils/format.ts
554
- function formatBytes(bytes, decimals = 1) {
555
- if (bytes === 0) return "0 Bytes";
556
- const k = 1024;
557
- const dm = decimals < 0 ? 0 : decimals;
558
- const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
559
- const i = Math.floor(Math.log(bytes) / Math.log(k));
560
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
561
- }
562
- function formatDateShort(dateString) {
563
- if (!dateString) return "Never";
564
- const date = new Date(dateString);
565
- if (isNaN(date.getTime())) {
566
- return dateString;
567
- }
568
- return date.toLocaleDateString("en-US", {
569
- year: "numeric",
570
- month: "2-digit",
571
- day: "2-digit"
572
- });
573
- }
574
- function formatDate(dateString) {
575
- if (!dateString) return "Never";
576
- const date = new Date(dateString);
577
- if (isNaN(date.getTime())) {
578
- return dateString;
579
- }
580
- return date.toLocaleDateString("en-US", {
581
- month: "short",
582
- day: "numeric",
583
- year: "numeric",
584
- hour: "numeric",
585
- minute: "2-digit",
586
- hour12: true
587
- });
588
- }
589
- function formatDateTime(dateString) {
590
- const date = new Date(dateString);
591
- if (isNaN(date.getTime())) {
592
- return dateString;
593
- }
594
- return date.toLocaleString("en-US", {
595
- timeZone: "UTC",
596
- year: "numeric",
597
- month: "2-digit",
598
- day: "2-digit",
599
- hour: "2-digit",
600
- minute: "2-digit",
601
- second: "2-digit",
602
- hour12: false
603
- }) + " UTC";
604
- }
605
- function formatDateTimeLocal(dateString) {
606
- if (!dateString) return "N/A";
607
- try {
608
- const date = new Date(dateString);
609
- if (isNaN(date.getTime())) {
610
- return dateString;
611
- }
612
- return date.toLocaleDateString("en-US", {
613
- month: "numeric",
614
- day: "numeric",
615
- year: "numeric",
616
- hour: "numeric",
617
- minute: "2-digit",
618
- hour12: true
619
- });
620
- } catch {
621
- return "N/A";
622
- }
623
- }
624
-
625
- // src/utils/release-helpers.ts
626
- function convertToReleaseEntry(release, channelName, options) {
627
- const sections = [];
628
- if (release.release_notes && release.release_notes.trim().length > 0) {
629
- if (options.releaseNotesMode === "markdown") {
630
- sections.push({
631
- title: "Release Notes",
632
- description: release.release_notes
633
- });
634
- } else {
635
- const releaseNotesItems = release.release_notes.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
636
- sections.push({
637
- title: "Release Notes",
638
- description: releaseNotesItems.length === 0 ? release.release_notes : void 0,
639
- items: releaseNotesItems.length > 0 ? releaseNotesItems : void 0
640
- });
641
- }
642
- }
643
- const charts = release.helm_charts ? release.helm_charts.filter((chart) => !chart.is_kots_installer_only).map((chart) => `${chart.name} v${chart.version}`) : [];
644
- if (charts.length > 0) {
645
- sections.push({
646
- title: "Helm Charts",
647
- items: charts,
648
- description: "Latest chart versions included in this release."
649
- });
650
- }
651
- return {
652
- version: release.label || `Release ${release.release_sequence}`,
653
- channel: channelName || `Channel ${release.channel_sequence}`,
654
- releasedAt: release.release_date,
655
- sections
656
- };
657
- }
658
-
659
447
  // src/actions/index.ts
660
448
  var getApiOrigin = () => {
661
449
  return (process.env.REPLICATED_APP_ORIGIN || "https://replicated.app").replace(/\/+$/, "");
@@ -798,6 +586,7 @@ var fetchCustomBrandingImpl = async () => {
798
586
  title: payload.title,
799
587
  primaryColor: payload.primaryColor,
800
588
  secondaryColor: payload.secondaryColor,
589
+ contact: payload.contact,
801
590
  favicon: payload.faviconUrl,
802
591
  supportPortalLink: payload.supportPortalLink || "",
803
592
  background: payload.background,
@@ -1740,6 +1529,91 @@ var LicenseDetails = async ({
1740
1529
  ] })
1741
1530
  ] });
1742
1531
  };
1532
+
1533
+ // src/utils/constants.ts
1534
+ 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";
1535
+ var DEFAULT_PRIMARY_COLOR = "#4f46e5";
1536
+ var DEFAULT_SECONDARY_COLOR = "#6366f1";
1537
+ var isHttpApiOrigin = () => {
1538
+ return process.env.REPLICATED_APP_ORIGIN?.startsWith("http://") || false;
1539
+ };
1540
+
1541
+ // src/utils/branding.ts
1542
+ var normalizeColor = (color) => {
1543
+ if (!color || typeof color !== "string") {
1544
+ return void 0;
1545
+ }
1546
+ const trimmed = color.trim();
1547
+ if (/^#?[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/.test(trimmed)) {
1548
+ return trimmed.startsWith("#") ? trimmed : `#${trimmed}`;
1549
+ }
1550
+ console.debug("[portal-components] Invalid color format rejected (only hex supported):", trimmed);
1551
+ return void 0;
1552
+ };
1553
+ var sanitizeUrlForCss = (url) => {
1554
+ if (!url || typeof url !== "string") {
1555
+ return void 0;
1556
+ }
1557
+ const trimmed = url.trim();
1558
+ try {
1559
+ const urlObj = new URL(trimmed);
1560
+ if (!["http:", "https:", "data:"].includes(urlObj.protocol)) {
1561
+ console.debug("[portal-components] Invalid URL protocol for background image:", urlObj.protocol);
1562
+ return void 0;
1563
+ }
1564
+ } catch {
1565
+ console.debug("[portal-components] Invalid URL format for background image:", trimmed);
1566
+ return void 0;
1567
+ }
1568
+ const escaped = trimmed.replace(/\\/g, "\\\\").replace(/\)/g, "\\)").replace(/"/g, '\\"').replace(/'/g, "\\'").replace(/[\x00-\x1F\x7F]/g, "");
1569
+ return escaped;
1570
+ };
1571
+ var decodeBranding = ({ brandingData }) => {
1572
+ if (!brandingData || typeof brandingData !== "string") {
1573
+ return {
1574
+ primaryColor: DEFAULT_PRIMARY_COLOR,
1575
+ secondaryColor: DEFAULT_SECONDARY_COLOR
1576
+ };
1577
+ }
1578
+ try {
1579
+ const decoded = Buffer.from(brandingData, "base64").toString("utf-8");
1580
+ const parsed = JSON.parse(decoded);
1581
+ const logo = typeof parsed.logo === "string" ? parsed.logo : void 0;
1582
+ const titleRaw = typeof parsed.title === "string" ? parsed.title.trim() : "";
1583
+ const title = titleRaw ? titleRaw : void 0;
1584
+ const favicon = typeof parsed.favicon === "string" ? parsed.favicon : void 0;
1585
+ const primaryColorRaw = parsed.primaryColor ?? parsed.primary_color;
1586
+ const secondaryColorRaw = parsed.secondaryColor ?? parsed.secondary_color;
1587
+ const primaryColor = normalizeColor(primaryColorRaw);
1588
+ const secondaryColor = normalizeColor(secondaryColorRaw);
1589
+ const contact = typeof parsed.contact === "string" ? parsed.contact : void 0;
1590
+ const supportPortalLink = typeof parsed.supportPortalLink === "string" ? parsed.supportPortalLink : void 0;
1591
+ const backgroundRaw = parsed.background;
1592
+ const background = backgroundRaw === "minimal" || backgroundRaw === "custom" || backgroundRaw === "image" ? backgroundRaw : void 0;
1593
+ const backgroundImage = sanitizeUrlForCss(parsed.backgroundImage);
1594
+ const backgroundGradientStart = normalizeColor(parsed.customColor1);
1595
+ const backgroundGradientEnd = normalizeColor(parsed.customColor2);
1596
+ return {
1597
+ logo,
1598
+ title,
1599
+ favicon,
1600
+ primaryColor: primaryColor || DEFAULT_PRIMARY_COLOR,
1601
+ secondaryColor: secondaryColor || DEFAULT_SECONDARY_COLOR,
1602
+ contact,
1603
+ supportPortalLink,
1604
+ background,
1605
+ backgroundImage,
1606
+ backgroundGradientStart,
1607
+ backgroundGradientEnd
1608
+ };
1609
+ } catch (error) {
1610
+ console.debug("[portal-components] unable to parse branding JSON", error);
1611
+ return {
1612
+ primaryColor: DEFAULT_PRIMARY_COLOR,
1613
+ secondaryColor: DEFAULT_SECONDARY_COLOR
1614
+ };
1615
+ }
1616
+ };
1743
1617
  function UserMenuDropdown({
1744
1618
  displayLabel,
1745
1619
  children,
@@ -2668,7 +2542,180 @@ var UpdateLayout = ({ children }) => {
2668
2542
  };
2669
2543
  UpdateLayout.displayName = "UpdateLayout";
2670
2544
 
2671
- // src/saml-handlers.ts
2545
+ // src/utils/session.ts
2546
+ async function validateSession(token) {
2547
+ if (!token || typeof token !== "string" || !token.trim()) {
2548
+ return false;
2549
+ }
2550
+ const endpoint = `${getApiOrigin()}/enterprise-portal/user`;
2551
+ const response = await fetch(endpoint, {
2552
+ method: "GET",
2553
+ headers: {
2554
+ authorization: `Bearer ${token}`
2555
+ },
2556
+ // Short timeout for validation
2557
+ signal: AbortSignal.timeout(5e3)
2558
+ });
2559
+ if (response.status === 401) {
2560
+ return false;
2561
+ }
2562
+ if (!response.ok) {
2563
+ throw new Error(`Session validation failed with status ${response.status}`);
2564
+ }
2565
+ return true;
2566
+ }
2567
+
2568
+ // src/utils/format.ts
2569
+ function formatBytes(bytes, decimals = 1) {
2570
+ if (bytes === 0) return "0 Bytes";
2571
+ const k = 1024;
2572
+ const dm = decimals < 0 ? 0 : decimals;
2573
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
2574
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
2575
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
2576
+ }
2577
+ function formatDateShort(dateString) {
2578
+ if (!dateString) return "Never";
2579
+ const date = new Date(dateString);
2580
+ if (isNaN(date.getTime())) {
2581
+ return dateString;
2582
+ }
2583
+ return date.toLocaleDateString("en-US", {
2584
+ year: "numeric",
2585
+ month: "2-digit",
2586
+ day: "2-digit"
2587
+ });
2588
+ }
2589
+ function formatDate(dateString) {
2590
+ if (!dateString) return "Never";
2591
+ const date = new Date(dateString);
2592
+ if (isNaN(date.getTime())) {
2593
+ return dateString;
2594
+ }
2595
+ return date.toLocaleDateString("en-US", {
2596
+ month: "short",
2597
+ day: "numeric",
2598
+ year: "numeric",
2599
+ hour: "numeric",
2600
+ minute: "2-digit",
2601
+ hour12: true
2602
+ });
2603
+ }
2604
+ function formatDateTime(dateString) {
2605
+ const date = new Date(dateString);
2606
+ if (isNaN(date.getTime())) {
2607
+ return dateString;
2608
+ }
2609
+ return date.toLocaleString("en-US", {
2610
+ timeZone: "UTC",
2611
+ year: "numeric",
2612
+ month: "2-digit",
2613
+ day: "2-digit",
2614
+ hour: "2-digit",
2615
+ minute: "2-digit",
2616
+ second: "2-digit",
2617
+ hour12: false
2618
+ }) + " UTC";
2619
+ }
2620
+ function formatDateTimeLocal(dateString) {
2621
+ if (!dateString) return "N/A";
2622
+ try {
2623
+ const date = new Date(dateString);
2624
+ if (isNaN(date.getTime())) {
2625
+ return dateString;
2626
+ }
2627
+ return date.toLocaleDateString("en-US", {
2628
+ month: "numeric",
2629
+ day: "numeric",
2630
+ year: "numeric",
2631
+ hour: "numeric",
2632
+ minute: "2-digit",
2633
+ hour12: true
2634
+ });
2635
+ } catch {
2636
+ return "N/A";
2637
+ }
2638
+ }
2639
+
2640
+ // src/utils/release-helpers.ts
2641
+ function convertToReleaseEntry(release, channelName, options) {
2642
+ const sections = [];
2643
+ if (release.release_notes && release.release_notes.trim().length > 0) {
2644
+ if (options.releaseNotesMode === "markdown") {
2645
+ sections.push({
2646
+ title: "Release Notes",
2647
+ description: release.release_notes
2648
+ });
2649
+ } else {
2650
+ const releaseNotesItems = release.release_notes.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
2651
+ sections.push({
2652
+ title: "Release Notes",
2653
+ description: releaseNotesItems.length === 0 ? release.release_notes : void 0,
2654
+ items: releaseNotesItems.length > 0 ? releaseNotesItems : void 0
2655
+ });
2656
+ }
2657
+ }
2658
+ const charts = release.helm_charts ? release.helm_charts.filter((chart) => !chart.is_kots_installer_only).map((chart) => `${chart.name} v${chart.version}`) : [];
2659
+ if (charts.length > 0) {
2660
+ sections.push({
2661
+ title: "Helm Charts",
2662
+ items: charts,
2663
+ description: "Latest chart versions included in this release."
2664
+ });
2665
+ }
2666
+ return {
2667
+ version: release.label || `Release ${release.release_sequence}`,
2668
+ channel: channelName || `Channel ${release.channel_sequence}`,
2669
+ releasedAt: release.release_date,
2670
+ sections
2671
+ };
2672
+ }
2673
+
2674
+ // src/utils/upload-with-progress.ts
2675
+ async function uploadSupportBundleWithProgress(file, appId, onProgress, signal) {
2676
+ return new Promise((resolve, reject) => {
2677
+ const xhr = new XMLHttpRequest();
2678
+ xhr.upload.addEventListener("progress", (e) => {
2679
+ if (e.lengthComputable) {
2680
+ const percent = Math.round(e.loaded / e.total * 100);
2681
+ onProgress(percent);
2682
+ }
2683
+ });
2684
+ xhr.addEventListener("load", () => {
2685
+ if (xhr.status === 200) {
2686
+ try {
2687
+ const response = JSON.parse(xhr.responseText);
2688
+ resolve(response);
2689
+ } catch (err) {
2690
+ reject(new Error("Failed to parse server response"));
2691
+ }
2692
+ } else {
2693
+ try {
2694
+ const response = JSON.parse(xhr.responseText);
2695
+ reject(new Error(response.error || `Upload failed: ${xhr.status}`));
2696
+ } catch {
2697
+ reject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`));
2698
+ }
2699
+ }
2700
+ });
2701
+ xhr.addEventListener("error", () => {
2702
+ reject(new Error("Network error. Please check your connection."));
2703
+ });
2704
+ xhr.addEventListener("abort", () => {
2705
+ reject(new Error("Upload cancelled"));
2706
+ });
2707
+ signal.addEventListener("abort", () => {
2708
+ xhr.abort();
2709
+ });
2710
+ const basePath = process.env.NEXT_PUBLIC_BASE_PATH || "";
2711
+ const uploadUrl = `${basePath}/api/support-bundles/upload?appId=${encodeURIComponent(appId)}`;
2712
+ xhr.open("POST", uploadUrl, true);
2713
+ xhr.setRequestHeader("Content-Type", "application/gzip");
2714
+ xhr.send(file);
2715
+ });
2716
+ }
2717
+
2718
+ // src/api/saml.ts
2672
2719
  async function setSamlSessionImpl(token) {
2673
2720
  try {
2674
2721
  if (!token) {
@@ -2736,6 +2783,6 @@ async function handleSamlAcs(request) {
2736
2783
  // src/index.ts
2737
2784
  var portalComponentsVersion = package_default.version;
2738
2785
 
2739
- export { Button, DEFAULT_FAVICON, DEFAULT_PRIMARY_COLOR, DEFAULT_SECONDARY_COLOR, LicenseDetails, SupportCard, TeamSettingsCard, TopNav, UnauthorizedError, UpdateLayout, UpdatesCard, UserSettings, UserSettingsCard, authenticatedFetch, convertToReleaseEntry, createPortalTheme, decodeBranding, decodeJwtPayload, defaultTopNavLinks, defineServerAction, deleteSupportBundle, downloadSecuritySBOM, downloadSupportBundle, fetchCurrentUser, fetchCustomBranding, fetchDashboardComposite, fetchLicense, fetchNotifications, formatBytes, formatDate, formatDateShort, formatDateTime, formatDateTimeLocal, getCustomerIdFromToken, getSecurityInfo, getSecurityInfoDiff, getSecurityInfoSBOM, getSupportBundleUploadUrl, handleSamlAcs, initiateLogin, isHttpApiOrigin, isRedirectError, listReleases, listSupportBundles, normalizeColor, portalComponentsVersion, portalThemeTokens, sanitizeUrlForCss, setSamlSessionImpl, updateNotifications, updateUser, uploadSupportBundle, validateSession, verifyMagicLink };
2786
+ export { Button, DEFAULT_FAVICON, DEFAULT_PRIMARY_COLOR, DEFAULT_SECONDARY_COLOR, LicenseDetails, SupportCard, TeamSettingsCard, TopNav, UnauthorizedError, UpdateLayout, UpdatesCard, UserSettings, UserSettingsCard, authenticatedFetch, convertToReleaseEntry, createPortalTheme, decodeBranding, decodeJwtPayload, defaultTopNavLinks, defineServerAction, deleteSupportBundle, downloadSecuritySBOM, downloadSupportBundle, fetchCurrentUser, fetchCustomBranding, fetchDashboardComposite, fetchLicense, fetchNotifications, formatBytes, formatDate, formatDateShort, formatDateTime, formatDateTimeLocal, getCustomerIdFromToken, getSecurityInfo, getSecurityInfoDiff, getSecurityInfoSBOM, getSupportBundleUploadUrl, handleSamlAcs, initiateLogin, isHttpApiOrigin, isRedirectError, listReleases, listSupportBundles, normalizeColor, portalComponentsVersion, portalThemeTokens, sanitizeUrlForCss, setSamlSessionImpl, updateNotifications, updateUser, uploadSupportBundle, uploadSupportBundleWithProgress, validateSession, verifyMagicLink };
2740
2787
  //# sourceMappingURL=index.js.map
2741
2788
  //# sourceMappingURL=index.js.map