@cobaltcore-dev/aurora 0.20.3 → 0.22.0

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 (91) hide show
  1. package/dist/client/AuthProvider-p1e1DuKU.mjs +69 -0
  2. package/dist/client/AuthProvider-p1e1DuKU.mjs.map +1 -0
  3. package/dist/client/{ContentHeader-CIAzorGI.mjs → ContentHeader-BIScbvb4.mjs} +3 -2
  4. package/dist/client/{ContentHeader-CIAzorGI.mjs.map → ContentHeader-BIScbvb4.mjs.map} +1 -1
  5. package/dist/client/DeleteFlavorModal-lFMExcq_.mjs +713 -0
  6. package/dist/client/DeleteFlavorModal-lFMExcq_.mjs.map +1 -0
  7. package/dist/client/{DeletePcaModal-YUlNw8cw.mjs → DeletePcaModal-Dg9dej-H.mjs} +2 -2
  8. package/dist/client/{DeletePcaModal-YUlNw8cw.mjs.map → DeletePcaModal-Dg9dej-H.mjs.map} +1 -1
  9. package/dist/client/{DetailsInfo-Cv3oke-R.mjs → DetailsInfo-DwCo9P1o.mjs} +2 -2
  10. package/dist/client/{DetailsInfo-Cv3oke-R.mjs.map → DetailsInfo-DwCo9P1o.mjs.map} +1 -1
  11. package/dist/client/{FloatingIpActionModals-PLN6CWZ9.mjs → FloatingIpActionModals-CDF8LVtX.mjs} +2 -2
  12. package/dist/client/{FloatingIpActionModals-PLN6CWZ9.mjs.map → FloatingIpActionModals-CDF8LVtX.mjs.map} +1 -1
  13. package/dist/client/{ImageToastNotifications-BQM7HOyE.mjs → ImageToastNotifications-Dzq6jNTm.mjs} +2 -2
  14. package/dist/client/{ImageToastNotifications-BQM7HOyE.mjs.map → ImageToastNotifications-Dzq6jNTm.mjs.map} +1 -1
  15. package/dist/client/Slot-CWb612-_.mjs +28 -0
  16. package/dist/client/Slot-CWb612-_.mjs.map +1 -0
  17. package/dist/client/{_auth-BtRCgHQe.mjs → _auth-Dut7CaMR.mjs} +2 -2
  18. package/dist/client/{_auth-BtRCgHQe.mjs.map → _auth-Dut7CaMR.mjs.map} +1 -1
  19. package/dist/client/{_flavorId-BaNJ1CDY.mjs → _flavorId-BMJcnI7H.mjs} +2 -2
  20. package/dist/client/{_flavorId-BaNJ1CDY.mjs.map → _flavorId-BMJcnI7H.mjs.map} +1 -1
  21. package/dist/client/{_flavorId-BMX239RH.mjs → _flavorId-DUWdFEMH.mjs} +13 -14
  22. package/dist/client/{_flavorId-BMX239RH.mjs.map → _flavorId-DUWdFEMH.mjs.map} +1 -1
  23. package/dist/client/{_floatingIpId-DQFtZNeg.mjs → _floatingIpId-CjQLzpC5.mjs} +2 -2
  24. package/dist/client/{_floatingIpId-DQFtZNeg.mjs.map → _floatingIpId-CjQLzpC5.mjs.map} +1 -1
  25. package/dist/client/{_floatingIpId-E6x99cmW.mjs → _floatingIpId-KcWWq9ZW2.mjs} +4 -4
  26. package/dist/client/_floatingIpId-KcWWq9ZW2.mjs.map +1 -0
  27. package/dist/client/{_imageId-C2662dZr.mjs → _imageId-BkEpwbCr.mjs} +3 -3
  28. package/dist/client/{_imageId-C2662dZr.mjs.map → _imageId-BkEpwbCr.mjs.map} +1 -1
  29. package/dist/client/{_pcaId-CNbmhUF8.mjs → _pcaId-BcwGho7g.mjs} +4 -4
  30. package/dist/client/{_pcaId-CNbmhUF8.mjs.map → _pcaId-BcwGho7g.mjs.map} +1 -1
  31. package/dist/client/{_projectId-B4ScifQf.mjs → _projectId-CoMD6nq6.mjs} +3 -3
  32. package/dist/client/{_projectId-B4ScifQf.mjs.map → _projectId-CoMD6nq6.mjs.map} +1 -1
  33. package/dist/client/{_projectId-CYq4KZXB.mjs → _projectId-D8FHe0gr.mjs} +3 -3
  34. package/dist/client/{_projectId-CYq4KZXB.mjs.map → _projectId-D8FHe0gr.mjs.map} +1 -1
  35. package/dist/client/{_projectId-DxgPaiA7.mjs → _projectId-MjFv839t.mjs} +2 -2
  36. package/dist/client/{_projectId-DxgPaiA7.mjs.map → _projectId-MjFv839t.mjs.map} +1 -1
  37. package/dist/client/{_projectId-DJLjspKf.mjs → _projectId-hMtrqW6m.mjs} +24 -23
  38. package/dist/client/{_projectId-DJLjspKf.mjs.map → _projectId-hMtrqW6m.mjs.map} +1 -1
  39. package/dist/client/{_securityGroupId-ju2ZSIYe.mjs → _securityGroupId-B5-gJe1u.mjs} +3 -3
  40. package/dist/client/{_securityGroupId-ju2ZSIYe.mjs.map → _securityGroupId-B5-gJe1u.mjs.map} +1 -1
  41. package/dist/client/{_securityGroupId-a46ExjsA.mjs → _securityGroupId-fPJWtDPU.mjs} +2 -2
  42. package/dist/client/{_securityGroupId-a46ExjsA.mjs.map → _securityGroupId-fPJWtDPU.mjs.map} +1 -1
  43. package/dist/client/{_storageType-BkhbKG_G.mjs → _storageType-CI5f4CsI.mjs} +2 -2
  44. package/dist/client/{_storageType-BkhbKG_G.mjs.map → _storageType-CI5f4CsI.mjs.map} +1 -1
  45. package/dist/client/{_storageType-ByLL106s.mjs → _storageType-DePX1Aah.mjs} +3 -3
  46. package/dist/client/{_storageType-ByLL106s.mjs.map → _storageType-DePX1Aah.mjs.map} +1 -1
  47. package/dist/client/{aurora-Owys0YMN.mjs → aurora-Dp_NPGe8.mjs} +2 -2
  48. package/dist/client/{aurora-Owys0YMN.mjs.map → aurora-Dp_NPGe8.mjs.map} +1 -1
  49. package/dist/client/components/Auth/LoginForm.d.ts +1 -0
  50. package/dist/client/{flavors-C7PVJUqZ.mjs → flavors-DLxUiBhE.mjs} +2 -2
  51. package/dist/client/{flavors-C7PVJUqZ.mjs.map → flavors-DLxUiBhE.mjs.map} +1 -1
  52. package/dist/client/{flavors-Bwjig3k2.mjs → flavors-DkGuWvge.mjs} +11 -12
  53. package/dist/client/{flavors-Bwjig3k2.mjs.map → flavors-DkGuWvge.mjs.map} +1 -1
  54. package/dist/client/{floatingips-D98DrjA0.mjs → floatingips-DC5OrR8h.mjs} +3 -3
  55. package/dist/client/{floatingips-D98DrjA0.mjs.map → floatingips-DC5OrR8h.mjs.map} +1 -1
  56. package/dist/client/{hooks-BsbKkpZc.mjs → hooks-D0wGUhRF.mjs} +2 -2
  57. package/dist/client/{hooks-BsbKkpZc.mjs.map → hooks-D0wGUhRF.mjs.map} +1 -1
  58. package/dist/client/{images-CfBrglGJ.mjs → images-D9nfOtSC.mjs} +5 -5
  59. package/dist/client/{images-CfBrglGJ.mjs.map → images-D9nfOtSC.mjs.map} +1 -1
  60. package/dist/client/{images-CD7DNwru.mjs → images-h9i7S4LN.mjs} +2 -2
  61. package/dist/client/{images-CD7DNwru.mjs.map → images-h9i7S4LN.mjs.map} +1 -1
  62. package/dist/client/index.js +302 -502
  63. package/dist/client/index.js.map +1 -1
  64. package/dist/client/{objects-CEBrL7k-.mjs → objects-B3Z8h4RU.mjs} +2 -2
  65. package/dist/client/{objects-CEBrL7k-.mjs.map → objects-B3Z8h4RU.mjs.map} +1 -1
  66. package/dist/client/{objects-DvIxpzGI.mjs → objects-CGOfO00N.mjs} +3 -3
  67. package/dist/client/{objects-DvIxpzGI.mjs.map → objects-CGOfO00N.mjs.map} +1 -1
  68. package/dist/client/{pca-ZgGU0UPF.mjs → pca-C7cMT8fW.mjs} +2 -2
  69. package/dist/client/{pca-ZgGU0UPF.mjs.map → pca-C7cMT8fW.mjs.map} +1 -1
  70. package/dist/client/{pca-CpMqoF00.mjs → pca-Nppb8aVa.mjs} +5 -5
  71. package/dist/client/{pca-CpMqoF00.mjs.map → pca-Nppb8aVa.mjs.map} +1 -1
  72. package/dist/client/routeInfo-CdTRlSxv.mjs +32 -0
  73. package/dist/client/routeInfo-CdTRlSxv.mjs.map +1 -0
  74. package/dist/client/routes-Bz4zb2H4.mjs +10 -0
  75. package/dist/client/routes-Bz4zb2H4.mjs.map +1 -0
  76. package/dist/client/routes-CaqfgBYu.mjs +112 -0
  77. package/dist/client/routes-CaqfgBYu.mjs.map +1 -0
  78. package/dist/client/{securitygroups-BwhVyNmZ.mjs → securitygroups-JMvcJLpb.mjs} +2 -2
  79. package/dist/client/{securitygroups-BwhVyNmZ.mjs.map → securitygroups-JMvcJLpb.mjs.map} +1 -1
  80. package/dist/client/store/AuthProvider.d.ts +10 -11
  81. package/dist/server/index.js +1 -10
  82. package/package.json +1 -2
  83. package/dist/client/AuthProvider-Cj_Btfnc.mjs +0 -56
  84. package/dist/client/AuthProvider-Cj_Btfnc.mjs.map +0 -1
  85. package/dist/client/DeleteFlavorModal-Dwm0Hh84.mjs +0 -638
  86. package/dist/client/DeleteFlavorModal-Dwm0Hh84.mjs.map +0 -1
  87. package/dist/client/_floatingIpId-E6x99cmW.mjs.map +0 -1
  88. package/dist/client/routeInfo-Ct5r4Gen.mjs +0 -56
  89. package/dist/client/routeInfo-Ct5r4Gen.mjs.map +0 -1
  90. package/dist/client/useErrorTranslation-Dc0eE8Zt.mjs +0 -83
  91. package/dist/client/useErrorTranslation-Dc0eE8Zt.mjs.map +0 -1
@@ -0,0 +1,69 @@
1
+ import { n as e } from "./trpcClient-BxcNKnhv.mjs";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ import n, { useEffect as r, useState as i } from "react";
4
+ //#region src/client/store/AuthProvider.tsx
5
+ var a = /*#__PURE__*/ n.createContext(null);
6
+ function o({ children: n }) {
7
+ let [o, s] = i(null), [c, l] = i(!0), [u, d] = i(null), [f, p] = i(null), m = (e = !1) => {
8
+ if (window.location.pathname !== "/") {
9
+ let t = e ? `/?redirect=${encodeURIComponent(window.location.pathname + window.location.search)}` : "/";
10
+ window.location.href = t;
11
+ }
12
+ }, h = () => {
13
+ s(null), p(null);
14
+ };
15
+ return r(() => {
16
+ e.auth.getCurrentUserSession.query().then((e) => {
17
+ e && (s(e.user), p(e.expires_at));
18
+ }).catch((e) => {
19
+ d(e instanceof Error ? e.message : "Could not load session");
20
+ }).finally(() => l(!1));
21
+ }, []), r(() => {
22
+ if (!o || !f) return;
23
+ let e = new Date(f).getTime() - Date.now(), t = () => {
24
+ h(), m(!0);
25
+ };
26
+ if (e <= 0) {
27
+ t();
28
+ return;
29
+ }
30
+ let n = setTimeout(t, e);
31
+ return () => clearTimeout(n);
32
+ }, [o, f]), /*#__PURE__*/ t(a.Provider, {
33
+ value: {
34
+ user: o,
35
+ isAuthenticated: !!o,
36
+ isLoading: c,
37
+ error: u,
38
+ login: async ({ domain: t, user: n, password: r }) => {
39
+ d(null), l(!0);
40
+ try {
41
+ let i = await e.auth.createUserSession.mutate({
42
+ domainName: t,
43
+ user: n,
44
+ password: r
45
+ });
46
+ return s(i.user), p(i.expires_at), { success: !0 };
47
+ } catch (e) {
48
+ return d(e instanceof Error ? e.message : `Could not create session: ${e}`), { success: !1 };
49
+ } finally {
50
+ l(!1);
51
+ }
52
+ },
53
+ logout: async () => {
54
+ l(!0), await e.auth.terminateUserSession.mutate().catch(() => {}), h(), m(!1), window.location.pathname === "/" && l(!1);
55
+ },
56
+ expiresAt: f ? new Date(f) : void 0
57
+ },
58
+ children: n
59
+ });
60
+ }
61
+ function s() {
62
+ let e = n.useContext(a);
63
+ if (!e) throw Error("useAuth must be used within an AuthProvider");
64
+ return e;
65
+ }
66
+ //#endregion
67
+ export { s as n, o as t };
68
+
69
+ //# sourceMappingURL=AuthProvider-p1e1DuKU.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthProvider-p1e1DuKU.mjs","names":["React","useEffect","useState","trpcClient","AuthContext","createContext","AuthProvider","children","user","setUser","isLoading","setIsLoading","error","setError","expiresAt","setExpiresAt","redirectToLogin","saveReturnUrl","window","location","pathname","returnUrl","encodeURIComponent","search","href","clearLocalSession","auth","getCurrentUserSession","query","then","session","expires_at","catch","err","Error","message","finally","timeUntilExpiry","Date","getTime","now","handleExpiry","timer","setTimeout","clearTimeout","login","domain","password","createUserSession","mutate","domainName","success","logout","terminateUserSession","Provider","value","isAuthenticated","undefined","useAuth","context","useContext"],"sources":["../../src/client/store/AuthProvider.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\"\nimport { TokenData } from \"../../server/Authentication/types/models\"\nimport { trpcClient } from \"../trpcClient\"\n\nexport type User = TokenData[\"user\"] | null\n\nexport interface AuthContext {\n isAuthenticated: boolean\n isLoading: boolean\n error: string | null\n login: (credentials: { domain: string; user: string; password: string }) => Promise<{ success: boolean }>\n logout: () => Promise<void>\n user?: User\n expiresAt?: Date\n}\n\nconst AuthContext = React.createContext<AuthContext | null>(null)\n\nexport function AuthProvider({ children }: { children: React.ReactNode }) {\n const [user, setUser] = useState<User | null>(null)\n const [isLoading, setIsLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [expiresAt, setExpiresAt] = useState<string | null>(null)\n\n // Redirect to login, optionally with return URL\n const redirectToLogin = (saveReturnUrl: boolean = false) => {\n if (window.location.pathname !== \"/\") {\n const returnUrl = saveReturnUrl\n ? `/?redirect=${encodeURIComponent(window.location.pathname + window.location.search)}`\n : \"/\"\n window.location.href = returnUrl\n }\n }\n\n // Clear local session state\n const clearLocalSession = () => {\n setUser(null)\n setExpiresAt(null)\n }\n\n // Get current session on mount\n useEffect(() => {\n trpcClient.auth.getCurrentUserSession\n .query()\n .then((session) => {\n if (session) {\n setUser(session.user)\n setExpiresAt(session.expires_at)\n }\n })\n .catch((err) => {\n setError(err instanceof Error ? err.message : \"Could not load session\")\n })\n .finally(() => setIsLoading(false))\n }, [])\n\n // Auto-logout when session expires\n useEffect(() => {\n if (!user || !expiresAt) return\n\n const timeUntilExpiry = new Date(expiresAt).getTime() - Date.now()\n\n const handleExpiry = () => {\n clearLocalSession()\n redirectToLogin(true)\n }\n\n if (timeUntilExpiry <= 0) {\n handleExpiry()\n return\n }\n\n const timer = setTimeout(handleExpiry, timeUntilExpiry)\n return () => clearTimeout(timer)\n }, [user, expiresAt])\n\n const login = async ({ domain, user, password }: { domain: string; user: string; password: string }) => {\n setError(null)\n setIsLoading(true)\n try {\n const session = await trpcClient.auth.createUserSession.mutate({ domainName: domain, user, password })\n setUser(session.user)\n setExpiresAt(session.expires_at)\n return { success: true }\n } catch (err) {\n setError(err instanceof Error ? err.message : `Could not create session: ${err}`)\n return { success: false }\n } finally {\n setIsLoading(false)\n }\n }\n\n const logout = async () => {\n setIsLoading(true)\n await trpcClient.auth.terminateUserSession.mutate().catch(() => {})\n clearLocalSession()\n redirectToLogin(false) // Don't save return URL on manual logout\n // If already on login page, no redirect happens - reset loading state\n if (window.location.pathname === \"/\") {\n setIsLoading(false)\n }\n }\n\n return (\n <AuthContext.Provider\n value={{\n user,\n isAuthenticated: !!user,\n isLoading,\n error,\n login,\n logout,\n expiresAt: expiresAt ? new Date(expiresAt) : undefined,\n }}\n >\n {children}\n </AuthContext.Provider>\n )\n}\n\nexport function useAuth() {\n const context = React.useContext(AuthContext)\n if (!context) {\n throw new Error(\"useAuth must be used within an AuthProvider\")\n }\n return context\n}\n"],"mappings":";;;;AAgBA,IAAMI,IAAcJ,gBAAMK,cAAkC,IAAA;AAE5D,SAAgBC,EAAa,EAAEC,eAAyC;CACtE,IAAM,CAACC,GAAMC,KAAWP,EAAsB,IAAA,GACxC,CAACQ,GAAWC,KAAgBT,EAAS,EAAA,GACrC,CAACU,GAAOC,KAAYX,EAAwB,IAAA,GAC5C,CAACY,GAAWC,KAAgBb,EAAwB,IAAA,GAGpDc,KAAmBC,IAAyB,OAAK;EACrD,IAAIC,OAAOC,SAASC,aAAa,KAAK;GACpC,IAAMC,IAAYJ,IACd,cAAcK,mBAAmBJ,OAAOC,SAASC,WAAWF,OAAOC,SAASI,MAAM,MAClF;GACJL,OAAOC,SAASK,OAAOH;EACzB;CACF,GAGMI,UAAoB;EAExBV,AADAN,EAAQ,IAAA,GACRM,EAAa,IAAA;CACf;CAiEA,OA9DAd,QAAU;EACRE,EAAWuB,KAAKC,sBACbC,MAAK,EACLC,MAAMC,MAAAA;GACL,AAAIA,MACFrB,EAAQqB,EAAQtB,IAAI,GACpBO,EAAae,EAAQC,UAAU;EAEnC,CAAA,EACCC,OAAOC,MAAAA;GACNpB,EAASoB,aAAeC,QAAQD,EAAIE,UAAU,wBAAA;EAChD,CAAA,EACCC,cAAczB,EAAa,EAAA,CAAA;CAChC,GAAG,CAAA,CAAE,GAGLV,QAAU;EACR,IAAI,CAACO,KAAQ,CAACM,GAAW;EAEzB,IAAMuB,IAAkB,IAAIC,KAAKxB,CAAAA,EAAWyB,QAAO,IAAKD,KAAKE,IAAG,GAE1DC,UAAe;GAEnBzB,AADAS,EAAAA,GACAT,EAAgB,EAAA;EAClB;EAEA,IAAIqB,KAAmB,GAAG;GACxBI,EAAAA;GACA;EACF;EAEA,IAAMC,IAAQC,WAAWF,GAAcJ,CAAAA;EACvC,aAAaO,aAAaF,CAAAA;CAC5B,GAAG,CAAClC,GAAMM,CAAAA,CAAU,GA8BlB,gBAACV,EAAYkD,UAAQ;EACnBC,OAAO;GACL/C;GACAgD,iBAAiB,CAAC,CAAChD;GACnBE;GACAE;GACAiC,cAlCe,EAAEC,WAAQtC,SAAMuC,kBAA8D;IAEjGpC,AADAE,EAAS,IAAA,GACTF,EAAa,EAAA;IACb,IAAI;KACF,IAAMmB,IAAU,MAAM3B,EAAWuB,KAAKsB,kBAAkBC,OAAO;MAAEC,YAAYJ;MAAQtC;MAAMuC;KAAS,CAAA;KAGpG,OAFAtC,EAAQqB,EAAQtB,IAAI,GACpBO,EAAae,EAAQC,UAAU,GACxB,EAAEoB,SAAS,GAAK;IACzB,SAASlB,GAAK;KAEZ,OADApB,EAASoB,aAAeC,QAAQD,EAAIE,UAAU,6BAA6BF,GAAK,GACzE,EAAEkB,SAAS,GAAM;IAC1B,UAAU;KACRxC,EAAa,EAAA;IACf;GACF;GAqBMyC,oBAnBS;IAMb,AALAzC,EAAa,EAAA,GACb,MAAMR,EAAWuB,KAAK2B,qBAAqBJ,OAAM,EAAGjB,YAAM,CAAO,CAAA,GACjEP,EAAAA,GACAT,EAAgB,EAAA,GAEZE,OAAOC,SAASC,aAAa,OAC/BT,EAAa,EAAA;GAEjB;GAWMG,WAAWA,IAAY,IAAIwB,KAAKxB,CAAAA,IAAa2C,KAAAA;EAC/C;EAEClD;;AAGP;AAEA,SAAgBmD,IAAAA;CACd,IAAMC,IAAU3D,EAAM4D,WAAWxD,CAAAA;CACjC,IAAI,CAACuD,GACH,MAAUzB,MAAM,6CAAA;CAElB,OAAOyB;AACT"}
@@ -1,5 +1,6 @@
1
1
  import { Y as e, f as t, j as n, l as r, ot as i, s as a, tt as o } from "./build-DgeVmENN.mjs";
2
- import { n as s, t as c } from "./routeInfo-Ct5r4Gen.mjs";
2
+ import { t as s } from "./Slot-CWb612-_.mjs";
3
+ import { t as c } from "./routeInfo-CdTRlSxv.mjs";
3
4
  import { jsx as l, jsxs as u } from "react/jsx-runtime";
4
5
  import { useState as d } from "react";
5
6
  import { useMatches as f, useParams as p, useRouteContext as m } from "@tanstack/react-router";
@@ -110,4 +111,4 @@ function v({ title: t, projectId: r, description: i, actions: a, badges: o }) {
110
111
  //#endregion
111
112
  export { _ as n, v as t };
112
113
 
113
- //# sourceMappingURL=ContentHeader-CIAzorGI.mjs.map
114
+ //# sourceMappingURL=ContentHeader-BIScbvb4.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContentHeader-CIAzorGI.mjs","names":["React","useState","Tooltip","TooltipTrigger","TooltipContent","Icon","Stack","ClipboardText","text","tooltipContent","className","truncateAt","showTooltip","props","useLingui","copied","setCopied","isHovering","setIsHovering","combinedClassName","handleCopy","e","preventDefault","stopPropagation","navigator","clipboard","writeText","setTimeout","err","console","error","displayText","length","slice","getTooltipContent","t","tooltipIsOpen","div","open","onClick","onMouseEnter","onMouseLeave","aria-label","asChild","data-testid","direction","gap","span","icon","size","Divider","ContentHeading","useRouteContext","useMatches","useParams","ClipboardText","Slot","isRouteInfo","ContentHeader","title","projectId","description","actions","badges","slots","strict","matches","provider","activeMatch","reverse","find","m","staticData","routeService","service","undefined","currentService","slotActions","servicePageActions","component","useShadowDOM","serviceBanner","projectOverviewBanner","header","className","div","span","text","truncateAt","p"],"sources":["../../src/client/components/ClipboardText.tsx","../../src/client/components/ContentHeader/ContentHeader.tsx"],"sourcesContent":["import React, { useState } from \"react\"\nimport { Tooltip, TooltipTrigger, TooltipContent, Icon, Stack } from \"@cloudoperators/juno-ui-components\"\nimport { useLingui } from \"@lingui/react/macro\"\n\nexport interface ClipboardTextProps extends React.HTMLAttributes<HTMLDivElement> {\n tooltipContent?: string\n text: string\n className?: string\n truncateAt?: number\n showTooltip?: boolean\n}\n\nconst ClipboardText: React.FC<ClipboardTextProps> = ({\n text,\n tooltipContent,\n className,\n truncateAt,\n showTooltip = true,\n ...props\n}) => {\n const { t } = useLingui()\n const [copied, setCopied] = useState(false)\n const [isHovering, setIsHovering] = useState(false)\n\n const combinedClassName = `copyableTooltip inline-flex items-center ${className || \"\"}`\n\n const handleCopy = async (e: React.MouseEvent) => {\n e.preventDefault()\n e.stopPropagation()\n\n try {\n await navigator.clipboard.writeText(text)\n setCopied(true)\n setIsHovering(false)\n setTimeout(() => setCopied(false), 2000)\n } catch (err) {\n console.error(\"Failed to copy text:\", err)\n }\n }\n\n const displayText = truncateAt && text.length > truncateAt ? `${text.slice(0, truncateAt)}...` : text\n\n // Determine tooltip content based on state\n const getTooltipContent = () => {\n if (copied) {\n return tooltipContent || t`Copied to clipboard!`\n }\n return t`Copy`\n }\n\n const tooltipIsOpen = (copied && showTooltip) || (isHovering && showTooltip)\n\n return (\n <div {...props} className={combinedClassName}>\n <Tooltip open={tooltipIsOpen}>\n <TooltipTrigger\n onClick={handleCopy}\n onMouseEnter={() => !copied && setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n aria-label={t`Copy ${text} to clipboard`}\n className=\"cursor-pointer\"\n asChild\n data-testid=\"clipboard-copy-trigger\"\n >\n <div className=\"group\">\n <Stack direction=\"horizontal\" gap=\"1\" className=\"items-center hover:underline\">\n <span className=\"select-none\">{displayText}</span>\n <Icon icon={copied ? \"check\" : \"contentCopy\"} size=\"18\" />\n </Stack>\n </div>\n </TooltipTrigger>\n <TooltipContent>{getTooltipContent()}</TooltipContent>\n </Tooltip>\n </div>\n )\n}\n\nexport default ClipboardText\n","import type { ReactNode } from \"react\"\nimport { Divider, ContentHeading } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { useRouteContext, useMatches, useParams } from \"@tanstack/react-router\"\nimport ClipboardText from \"../ClipboardText\"\nimport { Slot } from \"../Slot\"\nimport { isRouteInfo } from \"@/client/routes/routeInfo\"\n\ninterface ContentHeaderProps {\n title: string\n projectId: string\n description?: string | null\n actions?: ReactNode\n badges?: ReactNode\n}\n\nexport function ContentHeader({ title, projectId, description, actions, badges }: ContentHeaderProps) {\n const { slots } = useRouteContext({ strict: false })\n const matches = useMatches()\n const { provider } = useParams({ strict: false }) as { provider?: string }\n\n const activeMatch = [...matches].reverse().find((m) => isRouteInfo(m.staticData))\n const routeService = activeMatch && isRouteInfo(activeMatch.staticData) ? activeMatch.staticData.service : undefined\n\n // Storage routes share service: \"containers\" for both Swift and Ceph.\n // Distinguish them by the $provider param.\n const currentService = routeService === \"containers\" && provider === \"ceph\" ? \"ceph-containers\" : routeService\n\n const slotActions =\n slots?.servicePageActions && currentService ? (\n <Slot component={slots.servicePageActions} useShadowDOM={false} currentService={currentService} />\n ) : null\n\n const serviceBanner =\n slots?.serviceBanner && currentService ? (\n <Slot component={slots.serviceBanner} useShadowDOM={false} currentService={currentService} />\n ) : null\n\n const projectOverviewBanner =\n slots?.projectOverviewBanner && !currentService ? (\n <Slot component={slots.projectOverviewBanner} useShadowDOM={false} />\n ) : null\n\n return (\n <header className=\"mb-8\">\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-center gap-3\">\n <ContentHeading>{title}</ContentHeading>\n {slotActions}\n </div>\n <div className=\"text-theme-light flex shrink-0 items-center gap-1 text-sm\">\n <span className=\"font-semibold\">\n <Trans>Project ID</Trans>:{\" \"}\n </span>\n <ClipboardText text={projectId} truncateAt={15} />\n </div>\n </div>\n {description && <p className=\"text-sm font-normal\">{description}</p>}\n {serviceBanner}\n {projectOverviewBanner}\n <Divider className=\"mt-4\" />\n {(badges || actions) && (\n <div className=\"mt-3 flex items-start justify-between\">\n <div className=\"flex items-center gap-2\">{badges} </div>\n {actions && <div className=\"flex gap-2\">{actions}</div>}\n </div>\n )}\n </header>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ContentHeader-BIScbvb4.mjs","names":["React","useState","Tooltip","TooltipTrigger","TooltipContent","Icon","Stack","ClipboardText","text","tooltipContent","className","truncateAt","showTooltip","props","useLingui","copied","setCopied","isHovering","setIsHovering","combinedClassName","handleCopy","e","preventDefault","stopPropagation","navigator","clipboard","writeText","setTimeout","err","console","error","displayText","length","slice","getTooltipContent","t","tooltipIsOpen","div","open","onClick","onMouseEnter","onMouseLeave","aria-label","asChild","data-testid","direction","gap","span","icon","size","Divider","ContentHeading","useRouteContext","useMatches","useParams","ClipboardText","Slot","isRouteInfo","ContentHeader","title","projectId","description","actions","badges","slots","strict","matches","provider","activeMatch","reverse","find","m","staticData","routeService","service","undefined","currentService","slotActions","servicePageActions","component","useShadowDOM","serviceBanner","projectOverviewBanner","header","className","div","span","text","truncateAt","p"],"sources":["../../src/client/components/ClipboardText.tsx","../../src/client/components/ContentHeader/ContentHeader.tsx"],"sourcesContent":["import React, { useState } from \"react\"\nimport { Tooltip, TooltipTrigger, TooltipContent, Icon, Stack } from \"@cloudoperators/juno-ui-components\"\nimport { useLingui } from \"@lingui/react/macro\"\n\nexport interface ClipboardTextProps extends React.HTMLAttributes<HTMLDivElement> {\n tooltipContent?: string\n text: string\n className?: string\n truncateAt?: number\n showTooltip?: boolean\n}\n\nconst ClipboardText: React.FC<ClipboardTextProps> = ({\n text,\n tooltipContent,\n className,\n truncateAt,\n showTooltip = true,\n ...props\n}) => {\n const { t } = useLingui()\n const [copied, setCopied] = useState(false)\n const [isHovering, setIsHovering] = useState(false)\n\n const combinedClassName = `copyableTooltip inline-flex items-center ${className || \"\"}`\n\n const handleCopy = async (e: React.MouseEvent) => {\n e.preventDefault()\n e.stopPropagation()\n\n try {\n await navigator.clipboard.writeText(text)\n setCopied(true)\n setIsHovering(false)\n setTimeout(() => setCopied(false), 2000)\n } catch (err) {\n console.error(\"Failed to copy text:\", err)\n }\n }\n\n const displayText = truncateAt && text.length > truncateAt ? `${text.slice(0, truncateAt)}...` : text\n\n // Determine tooltip content based on state\n const getTooltipContent = () => {\n if (copied) {\n return tooltipContent || t`Copied to clipboard!`\n }\n return t`Copy`\n }\n\n const tooltipIsOpen = (copied && showTooltip) || (isHovering && showTooltip)\n\n return (\n <div {...props} className={combinedClassName}>\n <Tooltip open={tooltipIsOpen}>\n <TooltipTrigger\n onClick={handleCopy}\n onMouseEnter={() => !copied && setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n aria-label={t`Copy ${text} to clipboard`}\n className=\"cursor-pointer\"\n asChild\n data-testid=\"clipboard-copy-trigger\"\n >\n <div className=\"group\">\n <Stack direction=\"horizontal\" gap=\"1\" className=\"items-center hover:underline\">\n <span className=\"select-none\">{displayText}</span>\n <Icon icon={copied ? \"check\" : \"contentCopy\"} size=\"18\" />\n </Stack>\n </div>\n </TooltipTrigger>\n <TooltipContent>{getTooltipContent()}</TooltipContent>\n </Tooltip>\n </div>\n )\n}\n\nexport default ClipboardText\n","import type { ReactNode } from \"react\"\nimport { Divider, ContentHeading } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { useRouteContext, useMatches, useParams } from \"@tanstack/react-router\"\nimport ClipboardText from \"../ClipboardText\"\nimport { Slot } from \"../Slot\"\nimport { isRouteInfo } from \"@/client/routes/routeInfo\"\n\ninterface ContentHeaderProps {\n title: string\n projectId: string\n description?: string | null\n actions?: ReactNode\n badges?: ReactNode\n}\n\nexport function ContentHeader({ title, projectId, description, actions, badges }: ContentHeaderProps) {\n const { slots } = useRouteContext({ strict: false })\n const matches = useMatches()\n const { provider } = useParams({ strict: false }) as { provider?: string }\n\n const activeMatch = [...matches].reverse().find((m) => isRouteInfo(m.staticData))\n const routeService = activeMatch && isRouteInfo(activeMatch.staticData) ? activeMatch.staticData.service : undefined\n\n // Storage routes share service: \"containers\" for both Swift and Ceph.\n // Distinguish them by the $provider param.\n const currentService = routeService === \"containers\" && provider === \"ceph\" ? \"ceph-containers\" : routeService\n\n const slotActions =\n slots?.servicePageActions && currentService ? (\n <Slot component={slots.servicePageActions} useShadowDOM={false} currentService={currentService} />\n ) : null\n\n const serviceBanner =\n slots?.serviceBanner && currentService ? (\n <Slot component={slots.serviceBanner} useShadowDOM={false} currentService={currentService} />\n ) : null\n\n const projectOverviewBanner =\n slots?.projectOverviewBanner && !currentService ? (\n <Slot component={slots.projectOverviewBanner} useShadowDOM={false} />\n ) : null\n\n return (\n <header className=\"mb-8\">\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-center gap-3\">\n <ContentHeading>{title}</ContentHeading>\n {slotActions}\n </div>\n <div className=\"text-theme-light flex shrink-0 items-center gap-1 text-sm\">\n <span className=\"font-semibold\">\n <Trans>Project ID</Trans>:{\" \"}\n </span>\n <ClipboardText text={projectId} truncateAt={15} />\n </div>\n </div>\n {description && <p className=\"text-sm font-normal\">{description}</p>}\n {serviceBanner}\n {projectOverviewBanner}\n <Divider className=\"mt-4\" />\n {(badges || actions) && (\n <div className=\"mt-3 flex items-start justify-between\">\n <div className=\"flex items-center gap-2\">{badges} </div>\n {actions && <div className=\"flex gap-2\">{actions}</div>}\n </div>\n )}\n </header>\n )\n}\n"],"mappings":"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"}