@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
package/dist/login.d.mts CHANGED
@@ -10,6 +10,10 @@ interface LoginProps extends Omit<ComponentPropsWithoutRef<"form">, "onSubmit" |
10
10
  ctaLabel?: string;
11
11
  initialEmail?: string;
12
12
  isSubmitting?: boolean;
13
+ /** Primary color for buttons */
14
+ primaryColor?: string;
15
+ /** Secondary color for borders/accents */
16
+ secondaryColor?: string;
13
17
  /**
14
18
  * Called when user submits email. Return { showVerification: false } to prevent
15
19
  * showing the verification code form (e.g., for SAML redirect).
package/dist/login.d.ts CHANGED
@@ -10,6 +10,10 @@ interface LoginProps extends Omit<ComponentPropsWithoutRef<"form">, "onSubmit" |
10
10
  ctaLabel?: string;
11
11
  initialEmail?: string;
12
12
  isSubmitting?: boolean;
13
+ /** Primary color for buttons */
14
+ primaryColor?: string;
15
+ /** Secondary color for borders/accents */
16
+ secondaryColor?: string;
13
17
  /**
14
18
  * Called when user submits email. Return { showVerification: false } to prevent
15
19
  * showing the verification code form (e.g., for SAML redirect).
package/dist/login.js CHANGED
@@ -62,6 +62,9 @@ var Button = react.forwardRef(
62
62
  }
63
63
  );
64
64
  Button.displayName = "Button";
65
+
66
+ // src/utils/constants.ts
67
+ var DEFAULT_PRIMARY_COLOR = "#4f46e5";
65
68
  var Login = react.forwardRef(
66
69
  ({
67
70
  logo,
@@ -72,6 +75,8 @@ var Login = react.forwardRef(
72
75
  ctaLabel = "Continue with email \u2192",
73
76
  initialEmail = "",
74
77
  isSubmitting = false,
78
+ primaryColor,
79
+ secondaryColor,
75
80
  onContinue,
76
81
  onVerifyCode,
77
82
  redirectPath = "/",
@@ -142,15 +147,18 @@ var Login = react.forwardRef(
142
147
  {
143
148
  ref,
144
149
  className: [
145
- "w-full max-w-xl rounded-3xl border-2 border-gray-900 bg-white p-12 shadow-xl",
150
+ "w-full max-w-xl rounded-3xl border-2 bg-white p-12 shadow-xl",
146
151
  "text-gray-900 transition-shadow",
147
152
  className
148
153
  ].filter(Boolean).join(" "),
154
+ style: {
155
+ borderColor: secondaryColor || "#111827"
156
+ },
149
157
  onSubmit: handleSubmit,
150
158
  ...props,
151
159
  children: [
152
160
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-6 text-center", children: [
153
- logo ?? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-blue-500 to-violet-500 text-lg font-semibold leading-tight text-white", children: "EP" }),
161
+ logo,
154
162
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
155
163
  /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-3xl font-bold tracking-tight text-gray-900", children: title }),
156
164
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-base text-gray-600", children: description })
@@ -206,7 +214,11 @@ var Login = react.forwardRef(
206
214
  {
207
215
  type: "submit",
208
216
  size: "lg",
209
- className: "w-full justify-center rounded-xl bg-indigo-600 text-white hover:bg-indigo-700",
217
+ className: "w-full justify-center rounded-xl text-white transition-[filter] hover:brightness-90",
218
+ style: {
219
+ backgroundColor: primaryColor || DEFAULT_PRIMARY_COLOR,
220
+ borderColor: primaryColor || DEFAULT_PRIMARY_COLOR
221
+ },
210
222
  disabled,
211
223
  isLoading: disabled,
212
224
  children: ctaLabel
@@ -243,7 +255,11 @@ var Login = react.forwardRef(
243
255
  {
244
256
  type: "button",
245
257
  size: "lg",
246
- className: "w-full justify-center rounded-xl bg-indigo-600 text-white hover:bg-indigo-700",
258
+ className: "w-full justify-center rounded-xl text-white transition-[filter] hover:brightness-90",
259
+ style: {
260
+ backgroundColor: primaryColor || DEFAULT_PRIMARY_COLOR,
261
+ borderColor: primaryColor || DEFAULT_PRIMARY_COLOR
262
+ },
247
263
  disabled: verificationCode.length !== 12 || verifying,
248
264
  isLoading: verifying,
249
265
  onClick: handleVerify,
package/dist/login.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/button.tsx","../src/components/login.tsx"],"names":["jsx","forwardRef","jsxs","useState","useMemo"],"mappings":";;;;;;;;;;AASA,IAAM,aAAA,GAA+C;AAAA,EACnD,OAAA,EACE,mFAAA;AAAA,EACF,SAAA,EACE,8FAAA;AAAA,EACF,KAAA,EACE,+EAAA;AAAA,EACF,WAAA,EACE;AACJ,CAAA;AAEA,IAAM,UAAA,GAAyC;AAAA,EAC7C,EAAA,EAAI,kBAAA;AAAA,EACJ,EAAA,EAAI,mBAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAEA,IAAM,cAAA,GACJ,oOAAA;AAEF,IAAM,OAAA,GAAU,sBACdA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,oEACd,QAAA,kBAAAA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mEAAA,EAAoE,CAAA,EACtF,CAAA;AAcF,IAAM,gBAAA,GAAmB,IACpB,MAAA,KACQ,MAAA,CAAO,OAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AAMrC,IAAM,MAAA,GAASC,gBAAA;AAAA,EACpB,CACE;AAAA,IACE,OAAA,GAAU,SAAA;AAAA,IACV,IAAA,GAAO,IAAA;AAAA,IACP,IAAA,GAAO,QAAA;AAAA,IACP,SAAA,GAAY,KAAA;AAAA,IACZ,WAAA;AAAA,IACA,YAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,eAAA,GAAkB,SAAA,mBAAYD,cAAA,CAAC,OAAA,EAAA,EAAQ,CAAA,GAAK,WAAA;AAClD,IAAA,MAAM,mBAAmB,QAAA,IAAY,SAAA;AAErC,IAAA,uBACEE,eAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,IAAA;AAAA,QACA,SAAA,EAAW,gBAAA;AAAA,UACT,cAAA;AAAA,UACA,cAAc,OAAO,CAAA;AAAA,UACrB,WAAW,IAAI,CAAA;AAAA,UACf;AAAA,SACF;AAAA,QACA,aAAW,SAAA,IAAa,MAAA;AAAA,QACxB,QAAA,EAAU,gBAAA;AAAA,QACT,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,eAAA,kCACE,MAAA,EAAA,EAAK,aAAA,EAAY,QAAO,SAAA,EAAU,aAAA,EAChC,2BACH,CAAA,GACE,IAAA;AAAA,0BACJF,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0BAAA,EAA4B,QAAA,EAAS,CAAA;AAAA,UACpD,YAAA,kCACE,MAAA,EAAA,EAAK,aAAA,EAAY,QAAO,SAAA,EAAU,aAAA,EAChC,wBACH,CAAA,GACE;AAAA;AAAA;AAAA,KACN;AAAA,EAEJ;AACF,CAAA;AAEA,MAAA,CAAO,WAAA,GAAc,QAAA;AC3Dd,IAAM,KAAA,GAAQC,gBAAAA;AAAA,EACnB,CACE;AAAA,IACE,IAAA;AAAA,IACA,KAAA,GAAQ,wCAAA;AAAA,IACR,WAAA,GAAc,gDAAA;AAAA,IACd,KAAA,GAAQ,oBAAA;AAAA,IACR,WAAA,GAAc,iBAAA;AAAA,IACd,QAAA,GAAW,4BAAA;AAAA,IACX,YAAA,GAAe,EAAA;AAAA,IACf,YAAA,GAAe,KAAA;AAAA,IACf,UAAA;AAAA,IACA,YAAA;AAAA,IACA,YAAA,GAAe,GAAA;AAAA,IACf,SAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIE,eAA6B,OAAO,CAAA;AAC5D,IAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAS,YAAY,CAAA;AAC/C,IAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIA,eAAS,YAAY,CAAA;AACjE,IAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAIA,eAAS,EAAE,CAAA;AAC3D,IAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,eAAS,KAAK,CAAA;AAChD,IAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,eAAS,KAAK,CAAA;AAC5C,IAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAIA,cAAA;AAAA,MAChD;AAAA,KACF;AAEA,IAAA,MAAM,YAAA,GAAe,OAAO,KAAA,KAAsC;AAChE,MAAA,KAAA,CAAM,cAAA,EAAe;AACrB,MAAA,IAAI,CAAC,UAAA,IAAc,IAAA,KAAS,OAAA,EAAS;AACnC,QAAA;AAAA,MACF;AAEA,MAAA,IAAI;AACF,QAAA,UAAA,CAAW,IAAI,CAAA;AACf,QAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,KAAK,CAAA;AAIrC,QAAA,IAAI,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,IAAY,sBAAsB,MAAA,IAAU,MAAA,CAAO,qBAAqB,KAAA,EAAO;AAE7G,UAAA;AAAA,QACF;AAGA,QAAA,iBAAA,CAAkB,KAAK,CAAA;AACvB,QAAA,mBAAA,CAAoB,EAAE,CAAA;AACtB,QAAA,oBAAA,CAAqB,IAAI,CAAA;AACzB,QAAA,OAAA,CAAQ,QAAQ,CAAA;AAAA,MAClB,CAAA,SAAE;AACA,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,QAAA,GAAW,IAAA,KAAS,OAAA,KAAY,YAAA,IAAgB,OAAA,CAAA;AACtD,IAAA,MAAM,mBAAA,GAAsBC,cAAQ,MAAM;AACxC,MAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,OAAO,8BAA8B,cAAc,CAAA,0CAAA,CAAA;AAAA,IACrD,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAEnB,IAAA,MAAM,eAAe,YAAY;AAC/B,MAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,gBAAA,EAAkB;AACtC,QAAA;AAAA,MACF;AACA,MAAA,IAAI;AACF,QAAA,oBAAA,CAAqB,IAAI,CAAA;AACzB,QAAA,YAAA,CAAa,IAAI,CAAA;AACjB,QAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,gBAAA,EAAkB,YAAY,CAAA;AAChE,QAAA,IACE,MAAA,IACA,OAAO,MAAA,KAAW,QAAA,IAClB,aAAa,MAAA,IACZ,MAAA,CAAiC,YAAY,KAAA,EAC9C;AACA,UAAA,MAAM,OAAA,GACH,OAAgC,OAAA,IACjC,mCAAA;AACF,UAAA,oBAAA,CAAqB,OAAO,CAAA;AAC5B,UAAA;AAAA,QACF;AACA,QAAA,mBAAA,CAAoB,EAAE,CAAA;AAAA,MACxB,SAAS,KAAA,EAAO;AACd,QAAA,IACE,OAAO,KAAA,KAAU,QAAA,IACjB,KAAA,KAAU,IAAA,IACV,aAAa,KAAA,IACb,OAAQ,KAAA,CAAgC,OAAA,KAAY,QAAA,EACpD;AACA,UAAA,oBAAA,CAAsB,MAA8B,OAAO,CAAA;AAAA,QAC7D,CAAA,MAAO;AACL,UAAA,oBAAA,CAAqB,mCAAmC,CAAA;AAAA,QAC1D;AAAA,MACF,CAAA,SAAE;AACA,QAAA,YAAA,CAAa,KAAK,CAAA;AAAA,MACpB;AAAA,IACF,CAAA;AAEA,IAAA,uBACEF,eAAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAW;AAAA,UACT,8EAAA;AAAA,UACA,iCAAA;AAAA,UACA;AAAA,SACF,CACG,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AAAA,QACX,QAAA,EAAU,YAAA;AAAA,QACT,GAAG,KAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAAA,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8CAAA,EACZ,QAAA,EAAA;AAAA,YAAA,IAAA,oBACCF,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uJAAsJ,QAAA,EAAA,IAAA,EAErK,CAAA;AAAA,4BAEFE,gBAAC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,8BAAAF,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,iDAAA,EACX,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,8BACAA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,gCAAgC,QAAA,EAAA,WAAA,EAAY;AAAA,aAAA,EAC3D;AAAA,WAAA,EACF,CAAA;AAAA,UACC,SAAS,OAAA,mBACRE,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,iBAAA,EACb,QAAA,EAAA;AAAA,4BAAAF,cAAAA;AAAA,cAAC,OAAA;AAAA,cAAA;AAAA,gBACC,OAAA,EAAQ,aAAA;AAAA,gBACR,SAAA,EAAU,yCAAA;AAAA,gBAET,QAAA,EAAA;AAAA;AAAA,aACH;AAAA,4BACAE,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,UAAA,EACb,QAAA,EAAA;AAAA,8BAAAF,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sEAAA,EACb,QAAA,kBAAAA,cAAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAU,uBAAA;AAAA,kBACV,IAAA,EAAK,MAAA;AAAA,kBACL,OAAA,EAAQ,WAAA;AAAA,kBACR,MAAA,EAAO,cAAA;AAAA,kBAEP,QAAA,kBAAAA,cAAAA;AAAA,oBAAC,MAAA;AAAA,oBAAA;AAAA,sBACC,aAAA,EAAc,OAAA;AAAA,sBACd,cAAA,EAAe,OAAA;AAAA,sBACf,WAAA,EAAa,CAAA;AAAA,sBACb,CAAA,EAAE;AAAA;AAAA;AACJ;AAAA,eACF,EACF,CAAA;AAAA,8BACAA,cAAAA;AAAA,gBAAC,OAAA;AAAA,gBAAA;AAAA,kBACC,EAAA,EAAG,aAAA;AAAA,kBACH,IAAA,EAAK,OAAA;AAAA,kBACL,SAAA,EAAU,OAAA;AAAA,kBACV,YAAA,EAAa,OAAA;AAAA,kBACb,WAAA;AAAA,kBACA,KAAA,EAAO,KAAA;AAAA,kBACP,UAAU,CAAC,KAAA,KAAU,QAAA,CAAS,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,kBAChD,SAAA,EAAU,yCAAA;AAAA,kBACV,KAAA,EAAO,EAAE,WAAA,EAAa,MAAA,EAAO;AAAA,kBAC7B,QAAA;AAAA,kBACA,QAAA,EAAQ;AAAA;AAAA;AACV,aAAA,EACF,CAAA;AAAA,4BACAA,cAAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,IAAA,EAAK,IAAA;AAAA,gBACL,SAAA,EAAU,+EAAA;AAAA,gBACV,QAAA;AAAA,gBACA,SAAA,EAAW,QAAA;AAAA,gBAEV,QAAA,EAAA;AAAA;AAAA;AACH,WAAA,EACF,CAAA,mBAEAE,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,iBAAA,EACb,QAAA,EAAA;AAAA,4BAAAA,gBAAC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,8BAAAF,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,qCAAA,EAAsC,QAAA,EAAA,mBAAA,EAEnD,CAAA;AAAA,cACC,sCACCA,cAAAA,CAAC,OAAE,SAAA,EAAU,4BAAA,EAA8B,+BAAoB,CAAA,GAC7D,IAAA;AAAA,cACH,oCACCA,cAAAA,CAAC,OAAE,SAAA,EAAU,uCAAA,EACV,6BACH,CAAA,GACE;AAAA,aAAA,EACN,CAAA;AAAA,4BACAA,cAAAA;AAAA,cAAC,OAAA;AAAA,cAAA;AAAA,gBACC,OAAA,EAAQ,YAAA;AAAA,gBACR,SAAA,EAAU,yCAAA;AAAA,gBACX,QAAA,EAAA;AAAA;AAAA,aAED;AAAA,4BACAA,cAAAA;AAAA,cAAC,OAAA;AAAA,cAAA;AAAA,gBACC,EAAA,EAAG,YAAA;AAAA,gBACH,SAAA,EAAU,SAAA;AAAA,gBACV,SAAA,EAAW,EAAA;AAAA,gBACX,WAAA,EAAY,qBAAA;AAAA,gBACZ,SAAA,EAAU,yCAAA;AAAA,gBACV,KAAA,EAAO,gBAAA;AAAA,gBACP,UAAU,CAAC,KAAA,KAAU,mBAAA,CAAoB,KAAA,CAAM,OAAO,KAAK;AAAA;AAAA,aAC7D;AAAA,4BACAA,cAAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,IAAA,EAAK,IAAA;AAAA,gBACL,SAAA,EAAU,+EAAA;AAAA,gBACV,QAAA,EAAU,gBAAA,CAAiB,MAAA,KAAW,EAAA,IAAM,SAAA;AAAA,gBAC5C,SAAA,EAAW,SAAA;AAAA,gBACX,OAAA,EAAS,YAAA;AAAA,gBACV,QAAA,EAAA;AAAA;AAAA;AAED,WAAA,EACF;AAAA;AAAA;AAAA,KAEJ;AAAA,EAEJ;AACF;AAEA,KAAA,CAAM,WAAA,GAAc,OAAA","file":"login.js","sourcesContent":["import {\n forwardRef,\n type ComponentPropsWithoutRef,\n type ReactNode\n} from \"react\";\n\nconst buttonVariants = [\"primary\", \"secondary\", \"ghost\", \"destructive\"] as const;\nconst buttonSizes = [\"sm\", \"md\", \"lg\"] as const;\n\nconst variantStyles: Record<ButtonVariant, string> = {\n primary:\n \"bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-primary\",\n secondary:\n \"bg-secondary/20 text-secondary-foreground hover:bg-secondary/30 focus-visible:ring-secondary\",\n ghost:\n \"bg-transparent text-primary hover:bg-primary/10 focus-visible:ring-primary/60\",\n destructive:\n \"bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger\"\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n sm: \"h-8 px-3 text-sm\",\n md: \"h-10 px-4 text-sm\",\n lg: \"h-12 px-6 text-base\"\n};\n\nconst inlineFlexBase =\n \"inline-flex items-center justify-center gap-2 rounded-md font-medium tracking-tight transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-60\";\n\nconst Spinner = () => (\n <span className=\"inline-flex h-3.5 w-3.5 animate-spin items-center justify-center\">\n <span className=\"h-3 w-3 rounded-full border-2 border-transparent border-t-current\" />\n </span>\n);\n\nexport type ButtonVariant = (typeof buttonVariants)[number];\nexport type ButtonSize = (typeof buttonSizes)[number];\n\nexport interface ButtonProps extends ComponentPropsWithoutRef<\"button\"> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n isLoading?: boolean;\n leadingIcon?: ReactNode;\n trailingIcon?: ReactNode;\n}\n\nconst composeClassName = (\n ...values: Array<string | undefined | false>\n): string => values.filter(Boolean).join(\" \");\n\n/**\n * Button is the primary interactive primitive for triggering portal actions.\n * It is theme aware via CSS variables generated from portal tokens.\n */\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = \"primary\",\n size = \"md\",\n type = \"button\",\n isLoading = false,\n leadingIcon,\n trailingIcon,\n disabled,\n className,\n children,\n ...props\n },\n ref\n ) => {\n const computedLeading = isLoading ? <Spinner /> : leadingIcon;\n const computedDisabled = disabled ?? isLoading;\n\n return (\n <button\n ref={ref}\n type={type}\n className={composeClassName(\n inlineFlexBase,\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n aria-busy={isLoading || undefined}\n disabled={computedDisabled}\n {...props}\n >\n {computedLeading ? (\n <span aria-hidden=\"true\" className=\"inline-flex\">\n {computedLeading}\n </span>\n ) : null}\n <span className=\"flex-1 whitespace-nowrap\">{children}</span>\n {trailingIcon ? (\n <span aria-hidden=\"true\" className=\"inline-flex\">\n {trailingIcon}\n </span>\n ) : null}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n","'use client';\n\nimport {\n forwardRef,\n useMemo,\n useState,\n type ComponentPropsWithoutRef,\n type FormEvent,\n type ReactNode\n} from \"react\";\n\nimport { Button } from \"./button\";\n\nexport interface LoginProps\n extends Omit<ComponentPropsWithoutRef<\"form\">, \"onSubmit\" | \"children\"> {\n logo?: ReactNode;\n title?: string;\n description?: string;\n label?: string;\n placeholder?: string;\n ctaLabel?: string;\n initialEmail?: string;\n isSubmitting?: boolean;\n /** \n * Called when user submits email. Return { showVerification: false } to prevent\n * showing the verification code form (e.g., for SAML redirect).\n */\n onContinue?: (email: string) => Promise<void | { showVerification: boolean }> | void | { showVerification: boolean };\n onVerifyCode?: (\n code: string,\n redirectPath: string\n ) => Promise<\n | void\n | { success: true }\n | { success: false; message?: string }\n >;\n redirectPath?: string;\n}\n\n/**\n * Login renders a compact form card tailored for portal authentication flows.\n * The component keeps styling self-contained so it can be dropped into the\n * local Next.js template without additional wrappers.\n */\nexport const Login = forwardRef<HTMLFormElement, LoginProps>(\n (\n {\n logo,\n title = \"Enterprise Factory Installation Portal\",\n description = \"Sign in to manage your enterprise installation\",\n label = \"Work email address\",\n placeholder = \"you@company.com\",\n ctaLabel = \"Continue with email →\",\n initialEmail = \"\",\n isSubmitting = false,\n onContinue,\n onVerifyCode,\n redirectPath = \"/\",\n className,\n ...props\n },\n ref\n ) => {\n const [mode, setMode] = useState<\"email\" | \"verify\">(\"email\");\n const [email, setEmail] = useState(initialEmail);\n const [submittedEmail, setSubmittedEmail] = useState(initialEmail);\n const [verificationCode, setVerificationCode] = useState(\"\");\n const [verifying, setVerifying] = useState(false);\n const [pending, setPending] = useState(false);\n const [verificationError, setVerificationError] = useState<string | null>(\n null\n );\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!onContinue || mode !== \"email\") {\n return;\n }\n\n try {\n setPending(true);\n const result = await onContinue(email);\n \n // Check if we should show verification form\n // If result is { showVerification: false }, don't show it (e.g., SAML redirect)\n if (result && typeof result === \"object\" && \"showVerification\" in result && result.showVerification === false) {\n // Don't transition to verify mode - caller is handling redirect\n return;\n }\n \n // Show verification code form\n setSubmittedEmail(email);\n setVerificationCode(\"\");\n setVerificationError(null);\n setMode(\"verify\");\n } finally {\n setPending(false);\n }\n };\n\n const disabled = mode === \"email\" && (isSubmitting || pending);\n const verificationMessage = useMemo(() => {\n if (!submittedEmail) {\n return null;\n }\n return `If there is an account for ${submittedEmail}, an email will be sent with a login code.`;\n }, [submittedEmail]);\n\n const handleVerify = async () => {\n if (!onVerifyCode || !verificationCode) {\n return;\n }\n try {\n setVerificationError(null);\n setVerifying(true);\n const result = await onVerifyCode(verificationCode, redirectPath);\n if (\n result &&\n typeof result === \"object\" &&\n \"success\" in result &&\n (result as { success?: unknown }).success === false\n ) {\n const message =\n (result as { message?: string }).message ??\n \"Unable to verify code. Try again.\";\n setVerificationError(message);\n return;\n }\n setVerificationCode(\"\");\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof (error as { message?: unknown }).message === \"string\"\n ) {\n setVerificationError((error as { message: string }).message);\n } else {\n setVerificationError(\"Unable to verify code. Try again.\");\n }\n } finally {\n setVerifying(false);\n }\n };\n\n return (\n <form\n ref={ref}\n className={[\n \"w-full max-w-xl rounded-3xl border-2 border-gray-900 bg-white p-12 shadow-xl\",\n \"text-gray-900 transition-shadow\",\n className\n ]\n .filter(Boolean)\n .join(\" \")}\n onSubmit={handleSubmit}\n {...props}\n >\n <div className=\"flex flex-col items-center gap-6 text-center\">\n {logo ?? (\n <div className=\"flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-blue-500 to-violet-500 text-lg font-semibold leading-tight text-white\">\n EP\n </div>\n )}\n <div>\n <h1 className=\"text-3xl font-bold tracking-tight text-gray-900\">\n {title}\n </h1>\n <p className=\"mt-3 text-base text-gray-600\">{description}</p>\n </div>\n </div>\n {mode === \"email\" ? (\n <div className=\"mt-10 space-y-4\">\n <label\n htmlFor=\"login-email\"\n className=\"block text-sm font-medium text-gray-700\"\n >\n {label}\n </label>\n <div className=\"relative\">\n <div className=\"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-4\">\n <svg\n className=\"h-5 w-5 text-gray-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\"\n />\n </svg>\n </div>\n <input\n id=\"login-email\"\n type=\"email\"\n inputMode=\"email\"\n autoComplete=\"email\"\n placeholder={placeholder}\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n className=\"portal-input w-full py-4 pr-4 text-base\"\n style={{ paddingLeft: '3rem' }}\n disabled={disabled}\n required\n />\n </div>\n <Button\n type=\"submit\"\n size=\"lg\"\n className=\"w-full justify-center rounded-xl bg-indigo-600 text-white hover:bg-indigo-700\"\n disabled={disabled}\n isLoading={disabled}\n >\n {ctaLabel}\n </Button>\n </div>\n ) : (\n <div className=\"mt-10 space-y-4\">\n <div>\n <p className=\"text-sm font-semibold text-gray-900\">\n Verification Code\n </p>\n {verificationMessage ? (\n <p className=\"mt-2 text-sm text-gray-600\">{verificationMessage}</p>\n ) : null}\n {verificationError ? (\n <p className=\"mt-2 text-sm font-medium text-red-600\">\n {verificationError}\n </p>\n ) : null}\n </div>\n <label\n htmlFor=\"login-code\"\n className=\"block text-sm font-medium text-gray-700\"\n >\n One-time code\n </label>\n <input\n id=\"login-code\"\n inputMode=\"numeric\"\n maxLength={12}\n placeholder=\"Enter 12 digit code\"\n className=\"portal-input w-full px-5 py-4 text-base\"\n value={verificationCode}\n onChange={(event) => setVerificationCode(event.target.value)}\n />\n <Button\n type=\"button\"\n size=\"lg\"\n className=\"w-full justify-center rounded-xl bg-indigo-600 text-white hover:bg-indigo-700\"\n disabled={verificationCode.length !== 12 || verifying}\n isLoading={verifying}\n onClick={handleVerify}\n >\n Verify code\n </Button>\n </div>\n )}\n </form>\n );\n }\n);\n\nLogin.displayName = \"Login\";\n"]}
1
+ {"version":3,"sources":["../src/components/button.tsx","../src/utils/constants.ts","../src/components/login.tsx"],"names":["jsx","forwardRef","jsxs","useState","useMemo"],"mappings":"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","file":"login.js","sourcesContent":["import {\n forwardRef,\n type ComponentPropsWithoutRef,\n type ReactNode\n} from \"react\";\n\nconst buttonVariants = [\"primary\", \"secondary\", \"ghost\", \"destructive\"] as const;\nconst buttonSizes = [\"sm\", \"md\", \"lg\"] as const;\n\nconst variantStyles: Record<ButtonVariant, string> = {\n primary:\n \"bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-primary\",\n secondary:\n \"bg-secondary/20 text-secondary-foreground hover:bg-secondary/30 focus-visible:ring-secondary\",\n ghost:\n \"bg-transparent text-primary hover:bg-primary/10 focus-visible:ring-primary/60\",\n destructive:\n \"bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger\"\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n sm: \"h-8 px-3 text-sm\",\n md: \"h-10 px-4 text-sm\",\n lg: \"h-12 px-6 text-base\"\n};\n\nconst inlineFlexBase =\n \"inline-flex items-center justify-center gap-2 rounded-md font-medium tracking-tight transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-60\";\n\nconst Spinner = () => (\n <span className=\"inline-flex h-3.5 w-3.5 animate-spin items-center justify-center\">\n <span className=\"h-3 w-3 rounded-full border-2 border-transparent border-t-current\" />\n </span>\n);\n\nexport type ButtonVariant = (typeof buttonVariants)[number];\nexport type ButtonSize = (typeof buttonSizes)[number];\n\nexport interface ButtonProps extends ComponentPropsWithoutRef<\"button\"> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n isLoading?: boolean;\n leadingIcon?: ReactNode;\n trailingIcon?: ReactNode;\n}\n\nconst composeClassName = (\n ...values: Array<string | undefined | false>\n): string => values.filter(Boolean).join(\" \");\n\n/**\n * Button is the primary interactive primitive for triggering portal actions.\n * It is theme aware via CSS variables generated from portal tokens.\n */\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = \"primary\",\n size = \"md\",\n type = \"button\",\n isLoading = false,\n leadingIcon,\n trailingIcon,\n disabled,\n className,\n children,\n ...props\n },\n ref\n ) => {\n const computedLeading = isLoading ? <Spinner /> : leadingIcon;\n const computedDisabled = disabled ?? isLoading;\n\n return (\n <button\n ref={ref}\n type={type}\n className={composeClassName(\n inlineFlexBase,\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n aria-busy={isLoading || undefined}\n disabled={computedDisabled}\n {...props}\n >\n {computedLeading ? (\n <span aria-hidden=\"true\" className=\"inline-flex\">\n {computedLeading}\n </span>\n ) : null}\n <span className=\"flex-1 whitespace-nowrap\">{children}</span>\n {trailingIcon ? (\n <span aria-hidden=\"true\" className=\"inline-flex\">\n {trailingIcon}\n </span>\n ) : null}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n","/**\n * Default globe favicon matching the CiGlobe icon (Circum Icons)\n * Used as fallback when custom branding doesn't provide a favicon\n */\nexport 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\";\n\n/**\n * Default primary brand color\n */\nexport const DEFAULT_PRIMARY_COLOR = \"#4f46e5\";\n\n/**\n * Default secondary brand color\n */\nexport const DEFAULT_SECONDARY_COLOR = \"#6366f1\";\n\n/**\n * Check if the API origin is HTTP (used for repldev environments)\n * This determines cookie security settings for cross-origin iframes\n * @returns true if the API origin starts with http:// (not https://)\n */\nexport const isHttpApiOrigin = (): boolean => {\n return process.env.REPLICATED_APP_ORIGIN?.startsWith('http://') || false;\n};\n","'use client';\n\nimport {\n forwardRef,\n useMemo,\n useState,\n type ComponentPropsWithoutRef,\n type FormEvent,\n type ReactNode\n} from \"react\";\n\nimport { Button } from \"./button\";\nimport { DEFAULT_PRIMARY_COLOR } from \"../utils/constants\";\n\nexport interface LoginProps\n extends Omit<ComponentPropsWithoutRef<\"form\">, \"onSubmit\" | \"children\"> {\n logo?: ReactNode;\n title?: string;\n description?: string;\n label?: string;\n placeholder?: string;\n ctaLabel?: string;\n initialEmail?: string;\n isSubmitting?: boolean;\n /** Primary color for buttons */\n primaryColor?: string;\n /** Secondary color for borders/accents */\n secondaryColor?: string;\n /** \n * Called when user submits email. Return { showVerification: false } to prevent\n * showing the verification code form (e.g., for SAML redirect).\n */\n onContinue?: (email: string) => Promise<void | { showVerification: boolean }> | void | { showVerification: boolean };\n onVerifyCode?: (\n code: string,\n redirectPath: string\n ) => Promise<\n | void\n | { success: true }\n | { success: false; message?: string }\n >;\n redirectPath?: string;\n}\n\n/**\n * Login renders a compact form card tailored for portal authentication flows.\n * The component keeps styling self-contained so it can be dropped into the\n * local Next.js template without additional wrappers.\n */\nexport const Login = forwardRef<HTMLFormElement, LoginProps>(\n (\n {\n logo,\n title = \"Enterprise Factory Installation Portal\",\n description = \"Sign in to manage your enterprise installation\",\n label = \"Work email address\",\n placeholder = \"you@company.com\",\n ctaLabel = \"Continue with email →\",\n initialEmail = \"\",\n isSubmitting = false,\n primaryColor,\n secondaryColor,\n onContinue,\n onVerifyCode,\n redirectPath = \"/\",\n className,\n ...props\n },\n ref\n ) => {\n const [mode, setMode] = useState<\"email\" | \"verify\">(\"email\");\n const [email, setEmail] = useState(initialEmail);\n const [submittedEmail, setSubmittedEmail] = useState(initialEmail);\n const [verificationCode, setVerificationCode] = useState(\"\");\n const [verifying, setVerifying] = useState(false);\n const [pending, setPending] = useState(false);\n const [verificationError, setVerificationError] = useState<string | null>(\n null\n );\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!onContinue || mode !== \"email\") {\n return;\n }\n\n try {\n setPending(true);\n const result = await onContinue(email);\n \n // Check if we should show verification form\n // If result is { showVerification: false }, don't show it (e.g., SAML redirect)\n if (result && typeof result === \"object\" && \"showVerification\" in result && result.showVerification === false) {\n // Don't transition to verify mode - caller is handling redirect\n return;\n }\n \n // Show verification code form\n setSubmittedEmail(email);\n setVerificationCode(\"\");\n setVerificationError(null);\n setMode(\"verify\");\n } finally {\n setPending(false);\n }\n };\n\n const disabled = mode === \"email\" && (isSubmitting || pending);\n const verificationMessage = useMemo(() => {\n if (!submittedEmail) {\n return null;\n }\n return `If there is an account for ${submittedEmail}, an email will be sent with a login code.`;\n }, [submittedEmail]);\n\n const handleVerify = async () => {\n if (!onVerifyCode || !verificationCode) {\n return;\n }\n try {\n setVerificationError(null);\n setVerifying(true);\n const result = await onVerifyCode(verificationCode, redirectPath);\n if (\n result &&\n typeof result === \"object\" &&\n \"success\" in result &&\n (result as { success?: unknown }).success === false\n ) {\n const message =\n (result as { message?: string }).message ??\n \"Unable to verify code. Try again.\";\n setVerificationError(message);\n return;\n }\n setVerificationCode(\"\");\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof (error as { message?: unknown }).message === \"string\"\n ) {\n setVerificationError((error as { message: string }).message);\n } else {\n setVerificationError(\"Unable to verify code. Try again.\");\n }\n } finally {\n setVerifying(false);\n }\n };\n\n return (\n <form\n ref={ref}\n className={[\n \"w-full max-w-xl rounded-3xl border-2 bg-white p-12 shadow-xl\",\n \"text-gray-900 transition-shadow\",\n className\n ]\n .filter(Boolean)\n .join(\" \")}\n style={{\n borderColor: secondaryColor || '#111827',\n }}\n onSubmit={handleSubmit}\n {...props}\n >\n <div className=\"flex flex-col items-center gap-6 text-center\">\n {logo}\n <div>\n <h1 className=\"text-3xl font-bold tracking-tight text-gray-900\">\n {title}\n </h1>\n <p className=\"mt-3 text-base text-gray-600\">{description}</p>\n </div>\n </div>\n {mode === \"email\" ? (\n <div className=\"mt-10 space-y-4\">\n <label\n htmlFor=\"login-email\"\n className=\"block text-sm font-medium text-gray-700\"\n >\n {label}\n </label>\n <div className=\"relative\">\n <div className=\"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-4\">\n <svg\n className=\"h-5 w-5 text-gray-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\"\n />\n </svg>\n </div>\n <input\n id=\"login-email\"\n type=\"email\"\n inputMode=\"email\"\n autoComplete=\"email\"\n placeholder={placeholder}\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n className=\"portal-input w-full py-4 pr-4 text-base\"\n style={{ paddingLeft: '3rem' }}\n disabled={disabled}\n required\n />\n </div>\n <Button\n type=\"submit\"\n size=\"lg\"\n className=\"w-full justify-center rounded-xl text-white transition-[filter] hover:brightness-90\"\n style={{\n backgroundColor: primaryColor || DEFAULT_PRIMARY_COLOR,\n borderColor: primaryColor || DEFAULT_PRIMARY_COLOR,\n }}\n disabled={disabled}\n isLoading={disabled}\n >\n {ctaLabel}\n </Button>\n </div>\n ) : (\n <div className=\"mt-10 space-y-4\">\n <div>\n <p className=\"text-sm font-semibold text-gray-900\">\n Verification Code\n </p>\n {verificationMessage ? (\n <p className=\"mt-2 text-sm text-gray-600\">{verificationMessage}</p>\n ) : null}\n {verificationError ? (\n <p className=\"mt-2 text-sm font-medium text-red-600\">\n {verificationError}\n </p>\n ) : null}\n </div>\n <label\n htmlFor=\"login-code\"\n className=\"block text-sm font-medium text-gray-700\"\n >\n One-time code\n </label>\n <input\n id=\"login-code\"\n inputMode=\"numeric\"\n maxLength={12}\n placeholder=\"Enter 12 digit code\"\n className=\"portal-input w-full px-5 py-4 text-base\"\n value={verificationCode}\n onChange={(event) => setVerificationCode(event.target.value)}\n />\n <Button\n type=\"button\"\n size=\"lg\"\n className=\"w-full justify-center rounded-xl text-white transition-[filter] hover:brightness-90\"\n style={{\n backgroundColor: primaryColor || DEFAULT_PRIMARY_COLOR,\n borderColor: primaryColor || DEFAULT_PRIMARY_COLOR,\n }}\n disabled={verificationCode.length !== 12 || verifying}\n isLoading={verifying}\n onClick={handleVerify}\n >\n Verify code\n </Button>\n </div>\n )}\n </form>\n );\n }\n);\n\nLogin.displayName = \"Login\";\n"]}
@@ -0,0 +1,13 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ /**
4
+ * Shared middleware for enterprise portal applications.
5
+ *
6
+ * Handles:
7
+ * - Expired session redirects (deletes cookie and redirects to root)
8
+ * - App slug prefix redirects (/{appSlug}/path → /path)
9
+ * - Respects NEXT_PUBLIC_BASE_PATH for reverse proxy scenarios
10
+ */
11
+ declare function portalMiddleware(request: NextRequest): NextResponse<unknown>;
12
+
13
+ export { portalMiddleware };
@@ -0,0 +1,13 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ /**
4
+ * Shared middleware for enterprise portal applications.
5
+ *
6
+ * Handles:
7
+ * - Expired session redirects (deletes cookie and redirects to root)
8
+ * - App slug prefix redirects (/{appSlug}/path → /path)
9
+ * - Respects NEXT_PUBLIC_BASE_PATH for reverse proxy scenarios
10
+ */
11
+ declare function portalMiddleware(request: NextRequest): NextResponse<unknown>;
12
+
13
+ export { portalMiddleware };
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ var server = require('next/server');
4
+
5
+ /**
6
+ * Enterprise Portal Components
7
+ * This file is generated by tsup. Do not edit manually.
8
+ */
9
+
10
+ function portalMiddleware(request) {
11
+ const url = request.nextUrl;
12
+ const pathname = url.pathname;
13
+ if (pathname === "/" && url.searchParams.get("expired") === "1") {
14
+ const basePath = process.env.NEXT_PUBLIC_BASE_PATH;
15
+ const redirectUrl = new URL(basePath || "/", request.url);
16
+ const response = server.NextResponse.redirect(redirectUrl);
17
+ response.cookies.delete("portal_session");
18
+ return response;
19
+ }
20
+ const appSlug = process.env.PORTAL_APP_SLUG;
21
+ if (appSlug && (pathname === `/${appSlug}` || pathname.startsWith(`/${appSlug}/`))) {
22
+ const basePath = process.env.NEXT_PUBLIC_BASE_PATH;
23
+ const newPathname = pathname.slice(appSlug.length + 1) || "/";
24
+ const fullPath = basePath ? `${basePath}${newPathname}` : newPathname;
25
+ const normalizedPath = fullPath.length > 1 ? fullPath.replace(/\/$/, "") : fullPath;
26
+ const newUrl = new URL(normalizedPath, request.url);
27
+ newUrl.search = url.search;
28
+ return server.NextResponse.redirect(newUrl);
29
+ }
30
+ return server.NextResponse.next();
31
+ }
32
+
33
+ exports.portalMiddleware = portalMiddleware;
34
+ //# sourceMappingURL=middleware.js.map
35
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware.ts"],"names":["NextResponse"],"mappings":";;;;;;;;;AAWO,SAAS,iBAAiB,OAAA,EAAsB;AACrD,EAAA,MAAM,MAAM,OAAA,CAAQ,OAAA;AACpB,EAAA,MAAM,WAAW,GAAA,CAAI,QAAA;AAGrB,EAAA,IAAI,aAAa,GAAA,IAAO,GAAA,CAAI,aAAa,GAAA,CAAI,SAAS,MAAM,GAAA,EAAK;AAE/D,IAAA,MAAM,QAAA,GAAW,QAAQ,GAAA,CAAI,qBAAA;AAC7B,IAAA,MAAM,cAAc,IAAI,GAAA,CAAI,QAAA,IAAY,GAAA,EAAK,QAAQ,GAAG,CAAA;AACxD,IAAA,MAAM,QAAA,GAAWA,mBAAA,CAAa,QAAA,CAAS,WAAW,CAAA;AAGlD,IAAA,QAAA,CAAS,OAAA,CAAQ,OAAO,gBAAgB,CAAA;AAExC,IAAA,OAAO,QAAA;AAAA,EACT;AAIA,EAAA,MAAM,OAAA,GAAU,QAAQ,GAAA,CAAI,eAAA;AAC5B,EAAA,IAAI,OAAA,KAAY,QAAA,KAAa,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,IAAM,SAAS,UAAA,CAAW,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,CAAG,CAAA,CAAA,EAAI;AAElF,IAAA,MAAM,QAAA,GAAW,QAAQ,GAAA,CAAI,qBAAA;AAC7B,IAAA,MAAM,cAAc,QAAA,CAAS,KAAA,CAAM,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA,IAAK,GAAA;AAC1D,IAAA,MAAM,WAAW,QAAA,GAAW,CAAA,EAAG,QAAQ,CAAA,EAAG,WAAW,CAAA,CAAA,GAAK,WAAA;AAE1D,IAAA,MAAM,cAAA,GAAiB,SAAS,MAAA,GAAS,CAAA,GAAI,SAAS,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,GAAI,QAAA;AAC3E,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,cAAA,EAAgB,QAAQ,GAAG,CAAA;AAClD,IAAA,MAAA,CAAO,SAAS,GAAA,CAAI,MAAA;AACpB,IAAA,OAAOA,mBAAA,CAAa,SAAS,MAAM,CAAA;AAAA,EACrC;AAEA,EAAA,OAAOA,oBAAa,IAAA,EAAK;AAC3B","file":"middleware.js","sourcesContent":["import { NextResponse } from \"next/server\";\nimport type { NextRequest } from \"next/server\";\n\n/**\n * Shared middleware for enterprise portal applications.\n * \n * Handles:\n * - Expired session redirects (deletes cookie and redirects to root)\n * - App slug prefix redirects (/{appSlug}/path → /path)\n * - Respects NEXT_PUBLIC_BASE_PATH for reverse proxy scenarios\n */\nexport function portalMiddleware(request: NextRequest) {\n const url = request.nextUrl;\n const pathname = url.pathname;\n\n // Check if this is a logout/expired session redirect\n if (pathname === \"/\" && url.searchParams.get(\"expired\") === \"1\") {\n // Redirect to the app's root (respecting basePath for proxied scenarios)\n const basePath = process.env.NEXT_PUBLIC_BASE_PATH;\n const redirectUrl = new URL(basePath || \"/\", request.url);\n const response = NextResponse.redirect(redirectUrl);\n \n // Delete the expired session cookie\n response.cookies.delete(\"portal_session\");\n \n return response;\n }\n\n // Handle app slug prefix: /{appSlug}/... → /...\n // Redirect to remove the app slug prefix from the URL (respecting basePath for proxied scenarios)\n const appSlug = process.env.PORTAL_APP_SLUG;\n if (appSlug && (pathname === `/${appSlug}` || pathname.startsWith(`/${appSlug}/`))) {\n // Redirect /{appSlug} → /, /{appSlug}/invite → /invite, etc.\n const basePath = process.env.NEXT_PUBLIC_BASE_PATH;\n const newPathname = pathname.slice(appSlug.length + 1) || \"/\";\n const fullPath = basePath ? `${basePath}${newPathname}` : newPathname;\n // Remove trailing slash unless it's the root path\n const normalizedPath = fullPath.length > 1 ? fullPath.replace(/\\/$/, '') : fullPath;\n const newUrl = new URL(normalizedPath, request.url);\n newUrl.search = url.search;\n return NextResponse.redirect(newUrl);\n }\n\n return NextResponse.next();\n}\n\n/**\n * Note: The middleware config matcher cannot be exported from this module.\n * Next.js requires it to be defined as a static object literal in each\n * template's middleware.ts file for build-time analysis.\n * \n * Recommended config for templates:\n * \n * export const config = {\n * matcher: [\n * \"/((?!api|_next/static|_next/image|favicon.ico).*)\",\n * ],\n * };\n */\n"]}
@@ -1,7 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { Instance } from './install-actions.mjs';
3
- import { C as ChannelRelease, I as InstallOptions, S as SecurityReleaseImage, G as GetSecurityInfoDiffResult } from './index-BAiVrSSR.mjs';
3
+ import { C as ChannelRelease, I as InstallOptions, S as SecurityReleaseImage, G as GetSecurityInfoDiffResult } from './index-DyzJ0yKD.mjs';
4
+ import './fetch-license-iTyF7_GY.mjs';
4
5
  import './actions/change-team.mjs';
6
+ import './actions/trial-signup.mjs';
5
7
 
6
8
  interface OnlineInstanceListProps {
7
9
  instances?: Instance[];
@@ -1,7 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { Instance } from './install-actions.js';
3
- import { C as ChannelRelease, I as InstallOptions, S as SecurityReleaseImage, G as GetSecurityInfoDiffResult } from './index-DWt-N5od.js';
3
+ import { C as ChannelRelease, I as InstallOptions, S as SecurityReleaseImage, G as GetSecurityInfoDiffResult } from './index-sMbq94M7.js';
4
+ import './fetch-license-iTyF7_GY.js';
4
5
  import './actions/change-team.js';
6
+ import './actions/trial-signup.js';
5
7
 
6
8
  interface OnlineInstanceListProps {
7
9
  instances?: Instance[];
@@ -3,100 +3,43 @@
3
3
 
4
4
  var react = require('react');
5
5
  var Link = require('next/link');
6
+ var cx = require('classnames');
6
7
  var jsxRuntime = require('react/jsx-runtime');
7
8
 
8
9
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
10
 
10
11
  var Link__default = /*#__PURE__*/_interopDefault(Link);
12
+ var cx__default = /*#__PURE__*/_interopDefault(cx);
11
13
 
12
14
  /**
13
15
  * Enterprise Portal Components
14
16
  * This file is generated by tsup. Do not edit manually.
15
17
  */
16
- var __create = Object.create;
17
- var __defProp = Object.defineProperty;
18
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
19
- var __getOwnPropNames = Object.getOwnPropertyNames;
20
- var __getProtoOf = Object.getPrototypeOf;
21
- var __hasOwnProp = Object.prototype.hasOwnProperty;
22
- var __commonJS = (cb, mod) => function __require() {
23
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
24
- };
25
- var __copyProps = (to, from, except, desc) => {
26
- if (from && typeof from === "object" || typeof from === "function") {
27
- for (let key of __getOwnPropNames(from))
28
- if (!__hasOwnProp.call(to, key) && key !== except)
29
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
30
- }
31
- return to;
32
- };
33
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
34
- // If the importer is in node compatibility mode or this is not an ESM
35
- // file that has been converted to a CommonJS file using a Babel-
36
- // compatible transform (i.e. "__esModule" has not been set), then set
37
- // "default" to the CommonJS "module.exports" for node compatibility.
38
- !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
39
- mod
40
- ));
41
18
 
42
- // node_modules/classnames/index.js
43
- var require_classnames = __commonJS({
44
- "node_modules/classnames/index.js"(exports$1, module) {
45
- (function() {
46
- var hasOwn = {}.hasOwnProperty;
47
- function classNames() {
48
- var classes = "";
49
- for (var i = 0; i < arguments.length; i++) {
50
- var arg = arguments[i];
51
- if (arg) {
52
- classes = appendClass(classes, parseValue(arg));
53
- }
54
- }
55
- return classes;
56
- }
57
- function parseValue(arg) {
58
- if (typeof arg === "string" || typeof arg === "number") {
59
- return arg;
60
- }
61
- if (typeof arg !== "object") {
62
- return "";
63
- }
64
- if (Array.isArray(arg)) {
65
- return classNames.apply(null, arg);
66
- }
67
- if (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes("[native code]")) {
68
- return arg.toString();
69
- }
70
- var classes = "";
71
- for (var key in arg) {
72
- if (hasOwn.call(arg, key) && arg[key]) {
73
- classes = appendClass(classes, key);
74
- }
75
- }
76
- return classes;
77
- }
78
- function appendClass(value, newClass) {
79
- if (!newClass) {
80
- return value;
81
- }
82
- if (value) {
83
- return value + " " + newClass;
84
- }
85
- return value + newClass;
86
- }
87
- if (typeof module !== "undefined" && module.exports) {
88
- classNames.default = classNames;
89
- module.exports = classNames;
90
- } else if (typeof define === "function" && typeof define.amd === "object" && define.amd) {
91
- define("classnames", [], function() {
92
- return classNames;
93
- });
94
- } else {
95
- window.classNames = classNames;
96
- }
97
- })();
19
+
20
+ // src/utils/constants.ts
21
+ var DEFAULT_SECONDARY_COLOR = "#6366f1";
22
+
23
+ // src/utils/format.ts
24
+ function formatDateTimeLocal(dateString) {
25
+ if (!dateString) return "N/A";
26
+ try {
27
+ const date = new Date(dateString);
28
+ if (isNaN(date.getTime())) {
29
+ return dateString;
30
+ }
31
+ return date.toLocaleDateString("en-US", {
32
+ month: "numeric",
33
+ day: "numeric",
34
+ year: "numeric",
35
+ hour: "numeric",
36
+ minute: "2-digit",
37
+ hour12: true
38
+ });
39
+ } catch {
40
+ return "N/A";
98
41
  }
99
- });
42
+ }
100
43
 
101
44
  // src/actions/instances.ts
102
45
  var ACTIVE_INSTANCE_THRESHOLD_MS = 24 * 60 * 60 * 1e3;
@@ -156,9 +99,6 @@ function getInstanceName(instance) {
156
99
  const nameTag = instance.tags?.find((tag) => tag.key === "name");
157
100
  return nameTag?.value || instance.id.slice(0, 7);
158
101
  }
159
-
160
- // src/components/app-status-badge.tsx
161
- var import_classnames = __toESM(require_classnames());
162
102
  var toTitle = (value) => {
163
103
  const s = value.trim();
164
104
  if (!s) return s;
@@ -282,7 +222,7 @@ function AppStatusBadge({
282
222
  return /* @__PURE__ */ jsxRuntime.jsxs(
283
223
  "span",
284
224
  {
285
- className: (0, import_classnames.default)(
225
+ className: cx__default.default(
286
226
  "inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium",
287
227
  getClassNameForType(type),
288
228
  className
@@ -294,18 +234,6 @@ function AppStatusBadge({
294
234
  }
295
235
  );
296
236
  }
297
- function formatDateTime(dateString) {
298
- if (!dateString) return "N/A";
299
- const date = new Date(dateString);
300
- return date.toLocaleDateString("en-US", {
301
- month: "numeric",
302
- day: "numeric",
303
- year: "numeric",
304
- hour: "numeric",
305
- minute: "2-digit",
306
- hour12: true
307
- });
308
- }
309
237
  function UpdateBadge({ count }) {
310
238
  if (count <= 0) return null;
311
239
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1.5 inline-flex h-5 w-5 items-center justify-center rounded-full bg-rose-500 text-xs font-medium text-white", children: count });
@@ -343,7 +271,7 @@ function InstanceCard({
343
271
  channelReleases = [],
344
272
  installOptions = [],
345
273
  onUpdateClick,
346
- primaryColor = "#6366f1",
274
+ primaryColor = DEFAULT_SECONDARY_COLOR,
347
275
  securityData = {},
348
276
  securityDiffData = {},
349
277
  securityEnabled = false
@@ -443,18 +371,28 @@ function InstanceCard({
443
371
  instance.versionLabel || "Unknown",
444
372
  /* @__PURE__ */ jsxRuntime.jsx(UpdateBadge, { count: availableUpdates })
445
373
  ] }),
446
- instance.isAirgap && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-indigo-100 px-2 py-0.5 text-xs font-medium text-indigo-700", children: "air gap" }),
374
+ instance.isAirgap && /* @__PURE__ */ jsxRuntime.jsx(
375
+ "span",
376
+ {
377
+ className: "rounded-full px-2 py-0.5 text-xs font-medium",
378
+ style: {
379
+ backgroundColor: `var(--portal-branding-primary-light, ${DEFAULT_SECONDARY_COLOR}20)`,
380
+ color: `var(--portal-branding-primary, ${DEFAULT_SECONDARY_COLOR})`
381
+ },
382
+ children: "air gap"
383
+ }
384
+ ),
447
385
  installType && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-600", children: installType }),
448
386
  (instance.appStatus || instance.resourceStates && instance.resourceStates.length > 0) && /* @__PURE__ */ jsxRuntime.jsx(AppStatusBadge, { status: statusForBadge })
449
387
  ] }),
450
388
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-4", children: [
451
389
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
452
390
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500", children: "First check-in:" }),
453
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-600", children: formatDateTime(instance.firstCheckin) })
391
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-600", children: formatDateTimeLocal(instance.firstCheckin) })
454
392
  ] }),
455
393
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
456
394
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500", children: "Last check-in:" }),
457
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-600", children: formatDateTime(instance.lastCheckin) })
395
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-600", children: formatDateTimeLocal(instance.lastCheckin) })
458
396
  ] })
459
397
  ] }),
460
398
  securityEnabled && hasSecurityInfo && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
@@ -501,7 +439,7 @@ var OnlineInstanceList = ({
501
439
  channelReleases = [],
502
440
  installOptions = [],
503
441
  onUpdateClick,
504
- primaryColor = "#6366f1",
442
+ primaryColor = DEFAULT_SECONDARY_COLOR,
505
443
  securityData = {},
506
444
  securityDiffData = {},
507
445
  securityEnabled = false,
@@ -579,15 +517,6 @@ var OnlineInstanceList = ({
579
517
  ] });
580
518
  };
581
519
  OnlineInstanceList.displayName = "OnlineInstanceList";
582
- /*! Bundled license information:
583
-
584
- classnames/index.js:
585
- (*!
586
- Copyright (c) 2018 Jed Watson.
587
- Licensed under the MIT License (MIT), see
588
- http://jedwatson.github.io/classnames
589
- *)
590
- */
591
520
 
592
521
  exports.OnlineInstanceList = OnlineInstanceList;
593
522
  //# sourceMappingURL=online-instance-list.js.map