@cobaltcore-dev/aurora 0.6.0 → 0.8.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 (102) hide show
  1. package/README.md +160 -20
  2. package/dist/client/AuroraApp.d.ts +38 -0
  3. package/dist/client/{ContentHeader-kx1Th5Sq.mjs → ContentHeader-DqsGNvtD.mjs} +17 -17
  4. package/dist/client/{ContentHeader-kx1Th5Sq.mjs.map → ContentHeader-DqsGNvtD.mjs.map} +1 -1
  5. package/dist/client/{DeleteFlavorModal-C3cb7YiJ.mjs → DeleteFlavorModal-C3m7bQJu.mjs} +163 -163
  6. package/dist/client/{DeleteFlavorModal-C3cb7YiJ.mjs.map → DeleteFlavorModal-C3m7bQJu.mjs.map} +1 -1
  7. package/dist/client/{EditSecurityGroupModal-CpP54WIK.mjs → EditSecurityGroupModal-DKusxfta.mjs} +18 -18
  8. package/dist/client/{EditSecurityGroupModal-CpP54WIK.mjs.map → EditSecurityGroupModal-DKusxfta.mjs.map} +1 -1
  9. package/dist/client/{FiltersInput-DxcyR6Bp.mjs → FiltersInput-GzR4D0q6.mjs} +21 -21
  10. package/dist/client/{FiltersInput-DxcyR6Bp.mjs.map → FiltersInput-GzR4D0q6.mjs.map} +1 -1
  11. package/dist/client/{FloatingIpActionModals-BP8RWHbu.mjs → FloatingIpActionModals-CRvROJ3H.mjs} +51 -51
  12. package/dist/client/{FloatingIpActionModals-BP8RWHbu.mjs.map → FloatingIpActionModals-CRvROJ3H.mjs.map} +1 -1
  13. package/dist/client/{ImageToastNotifications-TZ3EfQg-.mjs → ImageToastNotifications-BuDXpTkl.mjs} +344 -344
  14. package/dist/client/{ImageToastNotifications-TZ3EfQg-.mjs.map → ImageToastNotifications-BuDXpTkl.mjs.map} +1 -1
  15. package/dist/client/{RouteError-QSV7qOoJ.mjs → RouteError-DVAiT0mT.mjs} +2 -2
  16. package/dist/client/{RouteError-QSV7qOoJ.mjs.map → RouteError-DVAiT0mT.mjs.map} +1 -1
  17. package/dist/client/{SortInput-CYv2_Pur.mjs → SortInput-VK7IYqQv.mjs} +6 -6
  18. package/dist/client/{SortInput-CYv2_Pur.mjs.map → SortInput-VK7IYqQv.mjs.map} +1 -1
  19. package/dist/client/_auth-DXJkv9QO.mjs.map +1 -1
  20. package/dist/client/{_flavorId-C2x43-6S.mjs → _flavorId-B9Vqkraj.mjs} +8 -8
  21. package/dist/client/{_flavorId-C2x43-6S.mjs.map → _flavorId-B9Vqkraj.mjs.map} +1 -1
  22. package/dist/client/{_flavorId-CR8ZUI-P.mjs → _flavorId-CFpNGz52.mjs} +62 -62
  23. package/dist/client/{_flavorId-CR8ZUI-P.mjs.map → _flavorId-CFpNGz52.mjs.map} +1 -1
  24. package/dist/client/{_floatingIpId-BCk41_Lb.mjs → _floatingIpId-B5GMSLeQ.mjs} +2 -2
  25. package/dist/client/{_floatingIpId-BCk41_Lb.mjs.map → _floatingIpId-B5GMSLeQ.mjs.map} +1 -1
  26. package/dist/client/{_floatingIpId-BGrOAmPT.mjs → _floatingIpId-C2-BeRmF.mjs} +27 -27
  27. package/dist/client/{_floatingIpId-BGrOAmPT.mjs.map → _floatingIpId-C2-BeRmF.mjs.map} +1 -1
  28. package/dist/client/_imageId-9NZytfNs.mjs +534 -0
  29. package/dist/client/{_imageId-CvfD832b.mjs.map → _imageId-9NZytfNs.mjs.map} +1 -1
  30. package/dist/client/_pcaId-BwTvJJgh.mjs +479 -0
  31. package/dist/client/_pcaId-BwTvJJgh.mjs.map +1 -0
  32. package/dist/client/{_pcaId-DOHycvCf.mjs → _pcaId-DUHQd0rB.mjs} +2 -2
  33. package/dist/client/{_pcaId-DOHycvCf.mjs.map → _pcaId-DUHQd0rB.mjs.map} +1 -1
  34. package/dist/client/{_projectId-DOgwFiqD.mjs → _projectId-B_2sZKk-.mjs} +2 -2
  35. package/dist/client/{_projectId-DOgwFiqD.mjs.map → _projectId-B_2sZKk-.mjs.map} +1 -1
  36. package/dist/client/{_projectId-MxcHrXW4.mjs → _projectId-CLgClx24.mjs} +3 -3
  37. package/dist/client/{_projectId-MxcHrXW4.mjs.map → _projectId-CLgClx24.mjs.map} +1 -1
  38. package/dist/client/_projectId-cW9aQ4Ag.mjs +271 -0
  39. package/dist/client/_projectId-cW9aQ4Ag.mjs.map +1 -0
  40. package/dist/client/{_securityGroupId-KKw4RPdH.mjs → _securityGroupId-DYxmXUOP.mjs} +319 -319
  41. package/dist/client/{_securityGroupId-KKw4RPdH.mjs.map → _securityGroupId-DYxmXUOP.mjs.map} +1 -1
  42. package/dist/client/{_securityGroupId-CJJanWiY.mjs → _securityGroupId-fhK1CuZh.mjs} +2 -2
  43. package/dist/client/{_securityGroupId-CJJanWiY.mjs.map → _securityGroupId-fhK1CuZh.mjs.map} +1 -1
  44. package/dist/client/{_storageType-DYjo-6ej.mjs → _storageType-2_fau4B5.mjs} +698 -698
  45. package/dist/client/{_storageType-DYjo-6ej.mjs.map → _storageType-2_fau4B5.mjs.map} +1 -1
  46. package/dist/client/{_storageType-4wSxI__0.mjs → _storageType-dRTFMKG3.mjs} +2 -2
  47. package/dist/client/{_storageType-4wSxI__0.mjs.map → _storageType-dRTFMKG3.mjs.map} +1 -1
  48. package/dist/client/{about-Bo9vxGHy.mjs → about-Nsxkyh9U.mjs} +2 -2
  49. package/dist/client/{about-Bo9vxGHy.mjs.map → about-Nsxkyh9U.mjs.map} +1 -1
  50. package/dist/client/{build-DeJcDjPi.mjs → build-BdRRmNf5.mjs} +3290 -3274
  51. package/dist/client/{build-DeJcDjPi.mjs.map → build-BdRRmNf5.mjs.map} +1 -1
  52. package/dist/client/{constants-BmcGYeR-.mjs → constants-J5nm9hbP.mjs} +15 -15
  53. package/dist/client/{constants-BmcGYeR-.mjs.map → constants-J5nm9hbP.mjs.map} +1 -1
  54. package/dist/client/{flavors-BxFVqgnb.mjs → flavors-_P7R-CeT.mjs} +2 -2
  55. package/dist/client/{flavors-BxFVqgnb.mjs.map → flavors-_P7R-CeT.mjs.map} +1 -1
  56. package/dist/client/{flavors-CfdgjsZY.mjs → flavors-m1qDHzeS.mjs} +238 -221
  57. package/dist/client/flavors-m1qDHzeS.mjs.map +1 -0
  58. package/dist/client/{floatingips-ByRb82wS.mjs → floatingips-Dq4DXQYb.mjs} +90 -90
  59. package/dist/client/{floatingips-ByRb82wS.mjs.map → floatingips-Dq4DXQYb.mjs.map} +1 -1
  60. package/dist/client/{images-CenluYV8.mjs → images-CpM-T_jM.mjs} +2 -2
  61. package/dist/client/{images-CenluYV8.mjs.map → images-CpM-T_jM.mjs.map} +1 -1
  62. package/dist/client/images-DHmVgQAh2.mjs +1890 -0
  63. package/dist/client/images-DHmVgQAh2.mjs.map +1 -0
  64. package/dist/client/{images-C_dX7nY6.mjs → images-Dbjo4yKn.mjs} +2 -2
  65. package/dist/client/{images-C_dX7nY6.mjs.map → images-Dbjo4yKn.mjs.map} +1 -1
  66. package/dist/client/index.d.ts +1 -1
  67. package/dist/client/index.js +390 -356
  68. package/dist/client/index.js.map +1 -1
  69. package/dist/client/{objects-gxSjvbvF.mjs → objects-DKWp9RtR.mjs} +2 -2
  70. package/dist/client/{objects-gxSjvbvF.mjs.map → objects-DKWp9RtR.mjs.map} +1 -1
  71. package/dist/client/{objects-BJM6YeuF.mjs → objects-DaCuy_CB.mjs} +1156 -1156
  72. package/dist/client/{objects-BJM6YeuF.mjs.map → objects-DaCuy_CB.mjs.map} +1 -1
  73. package/dist/client/{pca-Bl8NmoVZ.mjs → pca-C8zWTSSt.mjs} +2 -2
  74. package/dist/client/{pca-Bl8NmoVZ.mjs.map → pca-C8zWTSSt.mjs.map} +1 -1
  75. package/dist/client/pca-CK5-j7Kk.mjs +202 -0
  76. package/dist/client/pca-CK5-j7Kk.mjs.map +1 -0
  77. package/dist/client/{projects-pe2_dCnV.mjs → projects-CHYn7L5e.mjs} +2 -2
  78. package/dist/client/{projects-pe2_dCnV.mjs.map → projects-CHYn7L5e.mjs.map} +1 -1
  79. package/dist/client/{projects-D2iewAzu.mjs → projects-CeLhtLvf.mjs} +2 -2
  80. package/dist/client/{projects-D2iewAzu.mjs.map → projects-CeLhtLvf.mjs.map} +1 -1
  81. package/dist/client/{projects-CgclWI16.mjs → projects-ClViaUuv.mjs} +11 -11
  82. package/dist/client/{projects-CgclWI16.mjs.map → projects-ClViaUuv.mjs.map} +1 -1
  83. package/dist/client/{_projectId-BDSWnMGj.mjs → routeInfo-DlDJZnpg.mjs} +34 -8
  84. package/dist/client/routeInfo-DlDJZnpg.mjs.map +1 -0
  85. package/dist/client/{securitygroups-DahZkVYQ.mjs → securitygroups-CNFLu9zS.mjs} +112 -112
  86. package/dist/client/{securitygroups-DahZkVYQ.mjs.map → securitygroups-CNFLu9zS.mjs.map} +1 -1
  87. package/dist/client/{useListWithFiltering-DaYcu5AB.mjs → useListWithFiltering-v2A0-SZb.mjs} +9 -9
  88. package/dist/client/{useListWithFiltering-DaYcu5AB.mjs.map → useListWithFiltering-v2A0-SZb.mjs.map} +1 -1
  89. package/dist/server/index.d.ts +576 -2
  90. package/dist/server/index.js +59 -217
  91. package/package.json +4 -5
  92. package/dist/client/_imageId-CvfD832b.mjs +0 -534
  93. package/dist/client/_pcaId-BxBt5DXi.mjs +0 -459
  94. package/dist/client/_pcaId-BxBt5DXi.mjs.map +0 -1
  95. package/dist/client/_projectId-BDSWnMGj.mjs.map +0 -1
  96. package/dist/client/_projectId-DS4nR59B.mjs +0 -299
  97. package/dist/client/_projectId-DS4nR59B.mjs.map +0 -1
  98. package/dist/client/flavors-CfdgjsZY.mjs.map +0 -1
  99. package/dist/client/images-CKqIXUq52.mjs +0 -1873
  100. package/dist/client/images-CKqIXUq52.mjs.map +0 -1
  101. package/dist/client/pca-RSiWpJs9.mjs +0 -182
  102. package/dist/client/pca-RSiWpJs9.mjs.map +0 -1
package/README.md CHANGED
@@ -52,29 +52,76 @@ export function App() {
52
52
 
53
53
  ### `createServer(config)`
54
54
 
55
- | Option | Type | Required | Default | Description |
56
- | --------------------------------- | --------- | -------- | -------------------------- | ---------------------------------------------------------------- |
57
- | `identityEndpoint` | `string` | yes | — | OpenStack Keystone v3 URL |
58
- | `policyDir` | `string` | yes | — | Absolute path to a directory of OpenStack policy YAML files |
59
- | `bffEndpoint` | `string` | no | `"/polaris-bff"` | URL prefix for all tRPC routes |
60
- | `viteRoot` | `string` | no | — | Directory that contains `dist/client/` in production |
61
- | `defaultEndpointInterface` | `string` | no | `"public"` | OpenStack service catalog interface |
62
- | `proxyUrl` | `string` | no | — | HTTP proxy for OpenStack calls (dev only, ignored in production) |
63
- | `cephRegion` | `string` | no | — | Ceph RGW region for S3 operations |
64
- | `imageMetadataExcludedProperties` | `string` | no | — | Comma-separated image metadata keys to hide in the UI |
65
- | `cookieName` | `string` | no | `"dashboard-session-auth"` | Override the session cookie name |
66
- | `crossDomainCookie` | `boolean` | no | `true` | Share cookie across subdomains |
67
- | `insecureCookies` | `boolean` | no | `false` | Disable `Secure` flag — only for HTTP-only local dev |
55
+ | Option | Type | Required | Default | Description |
56
+ | --------------------------------- | ------------- | -------- | -------------------------- | ---------------------------------------------------------------- |
57
+ | `identityEndpoint` | `string` | yes | — | OpenStack Keystone v3 URL |
58
+ | `policyDir` | `string` | yes | — | Absolute path to a directory of OpenStack policy YAML files |
59
+ | `bffEndpoint` | `string` | no | `"/polaris-bff"` | URL prefix for all tRPC routes |
60
+ | `viteRoot` | `string` | no | — | Directory that contains `dist/client/` in production |
61
+ | `defaultEndpointInterface` | `string` | no | `"public"` | OpenStack service catalog interface |
62
+ | `proxyUrl` | `string` | no | — | HTTP proxy for OpenStack calls (dev only, ignored in production) |
63
+ | `cephRegion` | `string` | no | — | Ceph RGW region for S3 operations |
64
+ | `imageMetadataExcludedProperties` | `string` | no | — | Comma-separated image metadata keys to hide in the UI |
65
+ | `cookieName` | `string` | no | `"dashboard-session-auth"` | Override the session cookie name |
66
+ | `crossDomainCookie` | `boolean` | no | `true` | Share cookie across subdomains |
67
+ | `insecureCookies` | `boolean` | no | `false` | Disable `Secure` flag — only for HTTP-only local dev |
68
+ | `routers` | `AnyRouter[]` | no | `[]` | Additional tRPC routers — see [Custom routers](#custom-routers) |
69
+
70
+ ## Custom routers
71
+
72
+ `createServer` accepts a `routers` option so consumers can add their own tRPC procedures that run alongside the built-in Aurora routes, sharing the same Fastify request context (session, cookies, OpenStack client).
73
+
74
+ ### Requirements
75
+
76
+ Routers passed via `routers` **must** be created with the `auroraRouter` function exported from `@cobaltcore-dev/aurora/server`. Using a different `initTRPC` instance produces an incompatible context type and will cause runtime failures when procedures access `ctx.openstack`, `ctx.validateSession`, etc.
77
+
78
+ For the full list of exported procedure builders and router utilities, see [`src/server/index.ts`](./src/server/index.ts).
79
+
80
+ ### Example
81
+
82
+ ```ts
83
+ import { z } from "zod"
84
+ import { auroraRouter, protectedProcedure, createServer } from "@cobaltcore-dev/aurora/server"
85
+
86
+ const customRouter = auroraRouter({
87
+ feedback: protectedProcedure.input(z.object({ message: z.string() })).mutation(async ({ input }) => {
88
+ // ctx.validateSession(), ctx.openstack — all available here
89
+ return { status: "received" }
90
+ }),
91
+ })
92
+
93
+ const server = await createServer({
94
+ identityEndpoint: "https://keystone.example.com/v3/",
95
+ policyDir: path.resolve(__dirname, "../policies"),
96
+ routers: [customRouter],
97
+ })
98
+ ```
99
+
100
+ The procedure above is reachable at `POST <bffEndpoint>/feedback` via the tRPC client.
101
+
102
+ ### Registering additional Fastify plugins
103
+
104
+ `createServer` returns the `FastifyInstance` before `.listen()` is called. You can register any Fastify plugin — metrics, tracing, custom middleware — on the returned instance before starting the server:
105
+
106
+ ```ts
107
+ const server = await createServer({ ... })
108
+
109
+ server.register(MyPlugin, { ... })
110
+ server.get("/healthz", async () => ({ ok: true }))
111
+
112
+ await server.listen({ host: "0.0.0.0", port: 4000 })
113
+ ```
68
114
 
69
115
  ### `<AuroraApp />`
70
116
 
71
- | Prop | Type | Default | Description |
72
- | --------------- | ------------------------------- | ---------------- | -------------------------------------------------- |
73
- | `bffEndpoint` | `string` | `"/polaris-bff"` | Must match the server's `bffEndpoint` |
74
- | `theme` | `"theme-light" \| "theme-dark"` | `"theme-light"` | Initial theme |
75
- | `onThemeChange` | `(theme) => void` | — | Called when the user toggles the theme |
76
- | `appName` | `string` | `"Aurora"` | App name shown in the header breadcrumb and logo |
77
- | `slots` | `Slots` | — | Optional UI extension points — see [Slots](#slots) |
117
+ | Prop | Type | Default | Description |
118
+ | --------------- | ------------------------------- | ---------------- | ----------------------------------------------------------------------- |
119
+ | `bffEndpoint` | `string` | `"/polaris-bff"` | Must match the server's `bffEndpoint` |
120
+ | `theme` | `"theme-light" \| "theme-dark"` | `"theme-light"` | Initial theme |
121
+ | `onThemeChange` | `(theme) => void` | — | Called when the user toggles the theme |
122
+ | `appName` | `string` | `"Aurora"` | App name shown in the header breadcrumb and logo |
123
+ | `slots` | `Slots` | — | Optional UI extension points — see [Slots](#slots) |
124
+ | `onTrackEvent` | `OnTrackEventCallback` | — | Called on user interactions for analytics — see [Analytics](#analytics) |
78
125
 
79
126
  ## Slots
80
127
 
@@ -132,6 +179,99 @@ function MyBanner(_props: SlotProps) {
132
179
  }
133
180
  ```
134
181
 
182
+ ## Analytics
183
+
184
+ Aurora provides an optional `onTrackEvent` callback to track user interactions and feature usage. The API is source-agnostic, supporting various event types like navigation, link clicks, modals, and more.
185
+
186
+ ### Basic usage
187
+
188
+ ```tsx
189
+ import { AuroraApp, type TrackEventPayload } from "@cobaltcore-dev/aurora/client"
190
+
191
+ function trackEvent(payload: TrackEventPayload) {
192
+ // Router navigation example:
193
+ // payload.source = "router"
194
+ // payload.action = "/_auth/projects/$projectId/compute/images"
195
+ // payload.metadata = { pathname: "/projects/abc/compute/images", search: "?tab=details", section: "compute", service: "images" }
196
+
197
+ sendAnalytics("user-interaction", {
198
+ source: payload.source,
199
+ action: payload.action,
200
+ ...payload.metadata,
201
+ timestamp: Date.now(),
202
+ })
203
+ }
204
+
205
+ ;<AuroraApp bffEndpoint="/polaris-bff" onTrackEvent={trackEvent} />
206
+ ```
207
+
208
+ ### TrackEventPayload
209
+
210
+ The callback receives a `TrackEventPayload` object with the following fields:
211
+
212
+ | Field | Type | Description |
213
+ | ---------- | ---------------------------------------------------------- | ------------------------------------------------------------------------ |
214
+ | `source` | `string` | Event source (e.g., "router", "external-link", "modal") |
215
+ | `action` | `string` | Action identifier (e.g., route ID, button name, link URL) |
216
+ | `metadata` | `Record<string, string \| number \| boolean \| undefined>` | Source-specific context (pathname, section, service, href, target, etc.) |
217
+
218
+ ### Built-in tracking sources
219
+
220
+ #### Router navigation (`source: "router"`)
221
+
222
+ Automatically tracked when users navigate between routes. Fires on every route change via TanStack Router's `onResolved` event.
223
+
224
+ - **`action`**: Route ID (e.g., `"/_auth/projects/$projectId/compute/images"`)
225
+ - **`metadata`**: Always includes `pathname`; includes `search` (query string) when present; optionally includes `section` and `service` if the route defines them in `staticData`
226
+
227
+ **Example event:**
228
+
229
+ ```javascript
230
+ {
231
+ source: "router",
232
+ action: "/_auth/projects/$projectId/compute/images",
233
+ metadata: {
234
+ pathname: "/projects/my-project/compute/images",
235
+ search: "?memberStatus=accepted", // Query string, undefined if empty
236
+ section: "compute", // Optional: from route staticData
237
+ service: "images" // Optional: from route staticData
238
+ }
239
+ }
240
+ ```
241
+
242
+ ### Extending with custom tracking
243
+
244
+ The `onTrackEvent` callback is available in the router context, allowing any component to track custom interactions:
245
+
246
+ ```tsx
247
+ import { useRouteContext } from "@tanstack/react-router"
248
+
249
+ function MyComponent() {
250
+ const { onTrackEvent } = useRouteContext()
251
+
252
+ const handleExternalLinkClick = (href: string) => {
253
+ onTrackEvent?.({
254
+ source: "external-link",
255
+ action: href,
256
+ metadata: { target: "_blank" },
257
+ })
258
+ }
259
+
260
+ return (
261
+ <a href="https://docs.example.com" onClick={() => handleExternalLinkClick("https://docs.example.com")}>
262
+ Docs
263
+ </a>
264
+ )
265
+ }
266
+ ```
267
+
268
+ ### Implementation notes
269
+
270
+ - Router events are tracked via subscription to TanStack Router's `onResolved` event
271
+ - Automatic deduplication - fires once per navigation
272
+ - Errors in your callback are caught and logged to prevent breaking the app
273
+ - The callback executes **after** navigation completes
274
+
135
275
  ## License
136
276
 
137
277
  Apache-2.0
@@ -16,6 +16,23 @@ export type Slots = {
16
16
  /** Replaces the default page footer. Renders outside shadow DOM — inherits page styles. */
17
17
  pageFooter?: FC<SlotProps>;
18
18
  };
19
+ /**
20
+ * Payload for analytics tracking events.
21
+ * Generic structure that supports multiple event sources (router, links, modals, etc.)
22
+ */
23
+ export type TrackEventPayload = {
24
+ /** Source of the event (e.g., "router", "external-link", "modal", "button") */
25
+ source: string;
26
+ /** Action identifier describing what happened (e.g., route ID, button name, link URL) */
27
+ action: string;
28
+ /** Additional context specific to the source. For router: pathname, section, service. For links: href, target. */
29
+ metadata?: Record<string, string | number | boolean | undefined>;
30
+ };
31
+ /**
32
+ * Callback invoked when users interact with trackable features.
33
+ * Use this to send analytics data about feature usage patterns.
34
+ */
35
+ export type OnTrackEventCallback = (payload: TrackEventPayload) => void;
19
36
  /** Props for the top-level `<AuroraApp />` component. */
20
37
  export type AuroraAppProps = {
21
38
  /** Initial theme. Defaults to `"theme-light"`. */
@@ -28,5 +45,26 @@ export type AuroraAppProps = {
28
45
  slots?: Slots;
29
46
  /** App name shown in the header breadcrumb and as the default logo title. Defaults to `"Aurora"`. */
30
47
  appName?: string;
48
+ /**
49
+ * Analytics callback for tracking user interactions and feature usage.
50
+ * Called for various user actions like navigation, external link clicks, etc.
51
+ *
52
+ * @example
53
+ * ```tsx
54
+ * function trackEvent(payload: TrackEventPayload) {
55
+ * // Router navigation: payload.action = "/_auth/projects/$projectId/compute/images"
56
+ * // External link: payload.action = "https://docs.example.com"
57
+ * sendAnalytics('user-interaction', {
58
+ * action: payload.action,
59
+ * source: payload.source,
60
+ * ...payload.metadata,
61
+ * timestamp: Date.now()
62
+ * })
63
+ * }
64
+ *
65
+ * <AuroraApp onTrackEvent={trackEvent} />
66
+ * ```
67
+ */
68
+ onTrackEvent?: OnTrackEventCallback;
31
69
  };
32
70
  export declare const AuroraApp: FC<AuroraAppProps>;
@@ -1,59 +1,59 @@
1
- import { D as e, Q as t, _ as n, l as r, nt as i, q as a, st as o } from "./build-DeJcDjPi.mjs";
1
+ import { A as e, C as t, Q as n, Y as r, c as i, o as a, st as o } from "./build-BdRRmNf5.mjs";
2
2
  import { jsx as s, jsxs as c } from "react/jsx-runtime";
3
3
  import { useState as l } from "react";
4
4
  import { Trans as u, useLingui as d } from "@lingui/react";
5
5
  //#region src/client/components/ClipboardText.tsx
6
- var f = ({ text: e, tooltipContent: a, className: u, truncateAt: f, showTooltip: p = !0, ...m }) => {
7
- let { i18n: h, _: g } = d(), [_, v] = l(!1), [y, b] = l(!1), x = `copyableTooltip inline-flex items-center ${u || ""}`, S = async (t) => {
8
- t.preventDefault(), t.stopPropagation();
6
+ var f = ({ text: n, tooltipContent: o, className: u, truncateAt: f, showTooltip: p = !0, ...m }) => {
7
+ let { i18n: h, _: g } = d(), [_, v] = l(!1), [y, b] = l(!1), x = `copyableTooltip inline-flex items-center ${u || ""}`, S = async (e) => {
8
+ e.preventDefault(), e.stopPropagation();
9
9
  try {
10
- await navigator.clipboard.writeText(e), v(!0), b(!1), setTimeout(() => v(!1), 2e3);
10
+ await navigator.clipboard.writeText(n), v(!0), b(!1), setTimeout(() => v(!1), 2e3);
11
11
  } catch (e) {
12
12
  console.error("Failed to copy text:", e);
13
13
  }
14
- }, C = f && e.length > f ? `${e.slice(0, f)}...` : e, w = () => _ ? a || h._({ id: "u+VWhB" }) : h._({ id: "he3ygx" }), T = _ && p || y && p;
14
+ }, C = f && n.length > f ? `${n.slice(0, f)}...` : n, w = () => _ ? o || h._({ id: "u+VWhB" }) : h._({ id: "he3ygx" }), T = _ && p || y && p;
15
15
  return /*#__PURE__*/ s("div", {
16
16
  ...m,
17
17
  className: x,
18
- children: /*#__PURE__*/ c(o, {
18
+ children: /*#__PURE__*/ c(e, {
19
19
  open: T,
20
- children: [/*#__PURE__*/ s(n, {
20
+ children: [/*#__PURE__*/ s(a, {
21
21
  onClick: S,
22
22
  onMouseEnter: () => !_ && b(!0),
23
23
  onMouseLeave: () => b(!1),
24
24
  "aria-label": h._({
25
25
  id: "Wbg1jv",
26
- values: { text: e }
26
+ values: { text: n }
27
27
  }),
28
28
  className: "cursor-pointer",
29
29
  asChild: !0,
30
30
  "data-testid": "clipboard-copy-trigger",
31
31
  children: /*#__PURE__*/ s("div", {
32
32
  className: "group",
33
- children: /*#__PURE__*/ c(t, {
33
+ children: /*#__PURE__*/ c(r, {
34
34
  direction: "horizontal",
35
35
  gap: "1",
36
36
  className: "items-center hover:underline",
37
37
  children: [/*#__PURE__*/ s("span", {
38
38
  className: "select-none",
39
39
  children: C
40
- }), /*#__PURE__*/ s(r, {
40
+ }), /*#__PURE__*/ s(i, {
41
41
  icon: _ ? "check" : "contentCopy",
42
42
  size: "18"
43
43
  })]
44
44
  })
45
45
  })
46
- }), /*#__PURE__*/ s(i, { children: w() })]
46
+ }), /*#__PURE__*/ s(t, { children: w() })]
47
47
  })
48
48
  });
49
49
  };
50
50
  //#endregion
51
51
  //#region src/client/components/ContentHeader/ContentHeader.tsx
52
- function p({ title: t, projectId: n, actions: r }) {
52
+ function p({ title: e, projectId: t, actions: r }) {
53
53
  return /*#__PURE__*/ c("header", { children: [
54
54
  /*#__PURE__*/ c("div", {
55
55
  className: "flex flex-col sm:flex-row sm:items-center sm:justify-between",
56
- children: [/*#__PURE__*/ s(a, { children: t }), /*#__PURE__*/ c("div", {
56
+ children: [/*#__PURE__*/ s(n, { children: e }), /*#__PURE__*/ c("div", {
57
57
  className: "text-theme-light flex items-center gap-1 text-sm",
58
58
  children: [/*#__PURE__*/ c("span", {
59
59
  className: "font-semibold",
@@ -63,12 +63,12 @@ function p({ title: t, projectId: n, actions: r }) {
63
63
  " "
64
64
  ]
65
65
  }), /*#__PURE__*/ s(f, {
66
- text: n,
66
+ text: t,
67
67
  truncateAt: 15
68
68
  })]
69
69
  })]
70
70
  }),
71
- /*#__PURE__*/ s(e, { className: "mt-4" }),
71
+ /*#__PURE__*/ s(o, { className: "mt-4" }),
72
72
  r && /*#__PURE__*/ s("div", {
73
73
  className: "mt-3 flex justify-end",
74
74
  children: r
@@ -78,4 +78,4 @@ function p({ title: t, projectId: n, actions: r }) {
78
78
  //#endregion
79
79
  export { f as n, p as t };
80
80
 
81
- //# sourceMappingURL=ContentHeader-kx1Th5Sq.mjs.map
81
+ //# sourceMappingURL=ContentHeader-DqsGNvtD.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContentHeader-kx1Th5Sq.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","ClipboardText","ContentHeader","title","projectId","actions","header","div","className","span","text","truncateAt"],"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 ClipboardText from \"../ClipboardText\"\n\ninterface ContentHeaderProps {\n title: string\n projectId: string\n actions?: ReactNode\n}\n\nexport function ContentHeader({ title, projectId, actions }: ContentHeaderProps) {\n return (\n <header>\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <ContentHeading>{title}</ContentHeading>\n <div className=\"text-theme-light flex 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 <Divider className=\"mt-4\" />\n {actions && <div className=\"mt-3 flex justify-end\">{actions}</div>}\n </header>\n )\n}\n"],"mappings":";;;;;AAYA,IAAMO,KAA+C,EACnDC,SACAC,mBACAC,cACAC,eACAC,iBAAc,IACd,GAAGC,QACJ;CACC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACR,CAACC,GAAQC,KAAaf,EAAS,EAAA,GAC/B,CAACgB,GAAYC,KAAiBjB,EAAS,EAAA,GAEvCkB,IAAoB,6CAA6CT,KAAa,MAE9EU,IAAa,OAAOC,MAAAA;EAExBA,AADAA,EAAEC,eAAc,GAChBD,EAAEE,gBAAe;EAEjB,IAAI;GAIFI,AAHA,MAAMH,UAAUC,UAAUC,UAAUlB,CAAAA,GACpCQ,EAAU,EAAA,GACVE,EAAc,EAAA,GACdS,iBAAiBX,EAAU,EAAA,GAAQ,GAAA;EACrC,SAASY,GAAK;GACZC,QAAQC,MAAM,wBAAwBF,CAAAA;EACxC;CACF,GAEMG,IAAcpB,KAAcH,EAAKwB,SAASrB,IAAa,GAAGH,EAAKyB,MAAM,GAAGtB,CAAAA,EAAY,OAAOH,GAG3F0B,UACAnB,IACKN,KAAkB0B,EAAAA,EAAC,EAAA,IAAA,SAAqB,CAAA,IAE1CA,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA,GAGTC,IAAgB,KAAWxB,KAAiBK,KAAcL;CAEhE,OACE,gBAACyB,OAAAA;EAAK,GAAGxB;EAAOH,WAAWS;YACzB,gBAACjB,GAAAA;GAAQoC,MAAMF;cACb,gBAACjC,GAAAA;IACCoC,SAASnB;IACToB,oBAAoB,CAACzB,KAAUG,EAAc,EAAA;IAC7CuB,oBAAoBvB,EAAc,EAAA;IAClCwB,cAAYP,EAAAA,EAAC;;eAAQ3B,QAAAA;IAAkB,CAAA;IACvCE,WAAU;IACViC,SAAO;IACPC,eAAY;cAEZ,gBAACP,OAAAA;KAAI3B,WAAU;eACb,gBAACJ,GAAAA;MAAMuC,WAAU;MAAaC,KAAI;MAAIpC,WAAU;iBAC9C,gBAACqC,QAAAA;OAAKrC,WAAU;iBAAeqB;UAC/B,gBAAC1B,GAAAA;OAAK2C,MAAMjC,IAAS,UAAU;OAAekC,MAAK;;;;OAIzD,gBAAC7C,GAAAA,EAAAA,UAAgB8B,EAAAA,EAAAA,CAAAA,CAAAA;;;AAIzB;;;AChEA,SAAgBmB,EAAc,EAAEC,UAAOC,cAAWC,cAA6B;CAC7E,OACE,gBAACC,UAAAA,EAAAA,UAAAA;EACC,gBAACC,OAAAA;GAAIC,WAAU;cACb,gBAACR,GAAAA,EAAAA,UAAgBG,EAAAA,CAAAA,GACjB,gBAACI,OAAAA;IAAIC,WAAU;eACb,gBAACC,QAAAA;KAAKD,WAAU;;MACd,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;MAAyB;MAAE;;QAE7B,gBAACP,GAAAA;KAAcS,MAAMN;KAAWO,YAAY;;;;EAGhD,gBAACZ,GAAAA,EAAQS,WAAU,OAAA,CAAA;EAClBH,KAAW,gBAACE,OAAAA;GAAIC,WAAU;aAAyBH;;;AAG1D"}
1
+ {"version":3,"file":"ContentHeader-DqsGNvtD.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","ClipboardText","ContentHeader","title","projectId","actions","header","div","className","span","text","truncateAt"],"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 ClipboardText from \"../ClipboardText\"\n\ninterface ContentHeaderProps {\n title: string\n projectId: string\n actions?: ReactNode\n}\n\nexport function ContentHeader({ title, projectId, actions }: ContentHeaderProps) {\n return (\n <header>\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <ContentHeading>{title}</ContentHeading>\n <div className=\"text-theme-light flex 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 <Divider className=\"mt-4\" />\n {actions && <div className=\"mt-3 flex justify-end\">{actions}</div>}\n </header>\n )\n}\n"],"mappings":";;;;;AAYA,IAAMO,KAA+C,EACnDC,SACAC,mBACAC,cACAC,eACAC,iBAAc,IACd,GAAGC,QACJ;CACC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACR,CAACC,GAAQC,KAAaf,EAAS,EAAA,GAC/B,CAACgB,GAAYC,KAAiBjB,EAAS,EAAA,GAEvCkB,IAAoB,6CAA6CT,KAAa,MAE9EU,IAAa,OAAOC,MAAAA;EAExBA,AADAA,EAAEC,eAAc,GAChBD,EAAEE,gBAAe;EAEjB,IAAI;GAIFI,AAHA,MAAMH,UAAUC,UAAUC,UAAUlB,CAAAA,GACpCQ,EAAU,EAAA,GACVE,EAAc,EAAA,GACdS,iBAAiBX,EAAU,EAAA,GAAQ,GAAA;EACrC,SAASY,GAAK;GACZC,QAAQC,MAAM,wBAAwBF,CAAAA;EACxC;CACF,GAEMG,IAAcpB,KAAcH,EAAKwB,SAASrB,IAAa,GAAGH,EAAKyB,MAAM,GAAGtB,CAAAA,EAAY,OAAOH,GAG3F0B,UACAnB,IACKN,KAAkB0B,EAAAA,EAAC,EAAA,IAAA,SAAqB,CAAA,IAE1CA,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA,GAGTC,IAAgB,KAAWxB,KAAiBK,KAAcL;CAEhE,OACE,gBAACyB,OAAAA;EAAK,GAAGxB;EAAOH,WAAWS;YACzB,gBAACjB,GAAAA;GAAQoC,MAAMF;cACb,gBAACjC,GAAAA;IACCoC,SAASnB;IACToB,oBAAoB,CAACzB,KAAUG,EAAc,EAAA;IAC7CuB,oBAAoBvB,EAAc,EAAA;IAClCwB,cAAYP,EAAAA,EAAC;;eAAQ3B,QAAAA;IAAkB,CAAA;IACvCE,WAAU;IACViC,SAAO;IACPC,eAAY;cAEZ,gBAACP,OAAAA;KAAI3B,WAAU;eACb,gBAACJ,GAAAA;MAAMuC,WAAU;MAAaC,KAAI;MAAIpC,WAAU;iBAC9C,gBAACqC,QAAAA;OAAKrC,WAAU;iBAAeqB;UAC/B,gBAAC1B,GAAAA;OAAK2C,MAAMjC,IAAS,UAAU;OAAekC,MAAK;;;;OAIzD,gBAAC7C,GAAAA,EAAAA,UAAgB8B,EAAAA,EAAAA,CAAAA,CAAAA;;;AAIzB;;;AChEA,SAAgBmB,EAAc,EAAEC,UAAOC,cAAWC,cAA6B;CAC7E,OACE,gBAACC,UAAAA,EAAAA,UAAAA;EACC,gBAACC,OAAAA;GAAIC,WAAU;cACb,gBAACR,GAAAA,EAAAA,UAAgBG,EAAAA,CAAAA,GACjB,gBAACI,OAAAA;IAAIC,WAAU;eACb,gBAACC,QAAAA;KAAKD,WAAU;;MACd,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;MAAyB;MAAE;;QAE7B,gBAACP,GAAAA;KAAcS,MAAMN;KAAWO,YAAY;;;;EAGhD,gBAACZ,GAAAA,EAAQS,WAAU,OAAA,CAAA;EAClBH,KAAW,gBAACE,OAAAA;GAAIC,WAAU;aAAyBH;;;AAG1D"}