@burdenoff/microfe-devportal 2026.626.1 → 2026.626.2

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 (34) hide show
  1. package/dist/devportal/DevportalRoutes.js +38 -34
  2. package/dist/devportal/DevportalRoutes.js.map +1 -1
  3. package/dist/devportal/components/ConfirmDialog.js.map +1 -1
  4. package/dist/devportal/components/DataTable.js.map +1 -1
  5. package/dist/devportal/components/FormField.js.map +1 -1
  6. package/dist/devportal/components/GrantDelegationModal.js +2 -1
  7. package/dist/devportal/components/GrantDelegationModal.js.map +1 -1
  8. package/dist/devportal/components/LoadingState.js.map +1 -1
  9. package/dist/devportal/components/PageLayout.js.map +1 -1
  10. package/dist/devportal/components/SelectionCheckbox.js.map +1 -1
  11. package/dist/devportal/hooks/usePermission.js +2 -2
  12. package/dist/devportal/hooks/usePermission.js.map +1 -1
  13. package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
  14. package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
  15. package/dist/devportal/pages/CreateApplicationPage.js +185 -104
  16. package/dist/devportal/pages/CreateApplicationPage.js.map +1 -1
  17. package/dist/devportal/pages/CreateWebhookPage.js +6 -5
  18. package/dist/devportal/pages/CreateWebhookPage.js.map +1 -1
  19. package/dist/devportal/pages/DashboardPage.js.map +1 -1
  20. package/dist/devportal/pages/OAuthCallbackPage.js +64 -0
  21. package/dist/devportal/pages/OAuthCallbackPage.js.map +1 -0
  22. package/dist/devportal/pages/OAuthClientsPage.js.map +1 -1
  23. package/dist/devportal/pages/OrganizationDetailPage.js.map +1 -1
  24. package/dist/devportal/pages/PublishPage.js +392 -187
  25. package/dist/devportal/pages/PublishPage.js.map +1 -1
  26. package/dist/devportal/pages/ResourcesPage.js.map +1 -1
  27. package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -1
  28. package/dist/devportal/pages/WebhookDetailPage.js.map +1 -1
  29. package/dist/devportal/pages/WebhooksPage.js +1 -1
  30. package/dist/devportal/pages/WebhooksPage.js.map +1 -1
  31. package/dist/devportal/types/index.js.map +1 -1
  32. package/dist/generated/global-operations.js +260 -174
  33. package/dist/generated/global-operations.js.map +1 -1
  34. package/package.json +1 -1
@@ -26,32 +26,32 @@ function _(e, t) {
26
26
  })
27
27
  });
28
28
  }
29
- var v = s(() => import("./pages/OrganizationsPage.js").then((e) => ({ default: e.OrganizationsPage }))), y = s(() => import("./pages/OrganizationDetailPage.js").then((e) => ({ default: e.OrganizationDetailPage }))), b = s(() => import("./pages/CreateOrganizationPage.js").then((e) => ({ default: e.CreateOrganizationPage }))), x = s(() => import("./pages/OrganizationMembersPage.js").then((e) => ({ default: e.OrganizationMembersPage }))), S = s(() => import("./pages/RevenueDashboardPage.js").then((e) => ({ default: e.RevenueDashboardPage }))), C = s(() => import("./pages/ApplicationsPage.js").then((e) => ({ default: e.ApplicationsPage }))), w = s(() => import("./pages/ApplicationDetailPage.js").then((e) => ({ default: e.ApplicationDetailPage }))), T = s(() => import("./pages/CreateApplicationPage.js").then((e) => ({ default: e.CreateApplicationPage }))), E = s(() => import("./pages/EditApplicationPage.js").then((e) => ({ default: e.EditApplicationPage }))), D = s(() => import("./pages/ApplicationVersionsPage.js").then((e) => ({ default: e.ApplicationVersionsPage }))), O = s(() => import("./pages/OAuthClientsPage.js").then((e) => ({ default: e.OAuthClientsPage }))), k = s(() => import("./pages/CreateOAuthClientPage.js").then((e) => ({ default: e.CreateOAuthClientPage }))), A = s(() => import("./pages/OAuthClientDetailPage.js").then((e) => ({ default: e.OAuthClientDetailPage }))), j = s(() => import("./pages/ApiKeysPage.js").then((e) => ({ default: e.ApiKeysPage }))), M = s(() => import("./pages/CreateApiKeyPage.js").then((e) => ({ default: e.CreateApiKeyPage }))), N = s(() => import("./pages/WebhooksPage.js").then((e) => ({ default: e.WebhooksPage }))), P = s(() => import("./pages/CreateWebhookPage.js").then((e) => ({ default: e.CreateWebhookPage }))), F = s(() => import("./pages/WebhookDetailPage.js").then((e) => ({ default: e.WebhookDetailPage }))), I = s(() => import("./pages/AnalyticsDashboardPage.js").then((e) => ({ default: e.AnalyticsDashboardPage }))), L = s(() => import("./pages/DocumentationPage.js").then((e) => ({ default: e.DocumentationPage }))), R = s(() => import("./pages/ResourcesPage.js").then((e) => ({ default: e.ResourcesPage }))), z = s(() => import("./pages/SettingsPage.js").then((e) => ({ default: e.SettingsPage }))), B = s(() => import("./pages/PublishPage.js").then((e) => ({ default: e.PublishPage }))), V = s(() => import("./pages/AppLogsPage.js").then((e) => ({ default: e.AppLogsPage }))), H = s(() => import("./pages/DelegationsPage.js").then((e) => ({ default: e.DelegationsPage }))), U = s(() => import("./pages/ListingPreviewPage.js").then((e) => ({ default: e.ListingPreviewPage }))), W = s(() => import("./pages/StoreSubmissionPage.js").then((e) => ({ default: e.StoreSubmissionPage }))), G = s(() => import("./pages/PublisherProfilePage.js").then((e) => ({ default: e.PublisherProfilePage }))), K = s(() => import("./pages/SetupPage.js").then((e) => ({ default: e.SetupPage })));
30
- function q() {
31
- return /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(J, {}), /* @__PURE__ */ m(u, {})] });
32
- }
29
+ var v = s(() => import("./pages/OrganizationsPage.js").then((e) => ({ default: e.OrganizationsPage }))), y = s(() => import("./pages/OrganizationDetailPage.js").then((e) => ({ default: e.OrganizationDetailPage }))), b = s(() => import("./pages/CreateOrganizationPage.js").then((e) => ({ default: e.CreateOrganizationPage }))), x = s(() => import("./pages/OrganizationMembersPage.js").then((e) => ({ default: e.OrganizationMembersPage }))), S = s(() => import("./pages/RevenueDashboardPage.js").then((e) => ({ default: e.RevenueDashboardPage }))), C = s(() => import("./pages/ApplicationsPage.js").then((e) => ({ default: e.ApplicationsPage }))), w = s(() => import("./pages/ApplicationDetailPage.js").then((e) => ({ default: e.ApplicationDetailPage }))), T = s(() => import("./pages/CreateApplicationPage.js").then((e) => ({ default: e.CreateApplicationPage }))), E = s(() => import("./pages/EditApplicationPage.js").then((e) => ({ default: e.EditApplicationPage }))), D = s(() => import("./pages/ApplicationVersionsPage.js").then((e) => ({ default: e.ApplicationVersionsPage }))), O = s(() => import("./pages/OAuthCallbackPage.js").then((e) => ({ default: e.OAuthCallbackPage }))), k = s(() => import("./pages/OAuthClientsPage.js").then((e) => ({ default: e.OAuthClientsPage }))), A = s(() => import("./pages/CreateOAuthClientPage.js").then((e) => ({ default: e.CreateOAuthClientPage }))), j = s(() => import("./pages/OAuthClientDetailPage.js").then((e) => ({ default: e.OAuthClientDetailPage }))), M = s(() => import("./pages/ApiKeysPage.js").then((e) => ({ default: e.ApiKeysPage }))), N = s(() => import("./pages/CreateApiKeyPage.js").then((e) => ({ default: e.CreateApiKeyPage }))), P = s(() => import("./pages/WebhooksPage.js").then((e) => ({ default: e.WebhooksPage }))), F = s(() => import("./pages/CreateWebhookPage.js").then((e) => ({ default: e.CreateWebhookPage }))), I = s(() => import("./pages/WebhookDetailPage.js").then((e) => ({ default: e.WebhookDetailPage }))), L = s(() => import("./pages/AnalyticsDashboardPage.js").then((e) => ({ default: e.AnalyticsDashboardPage }))), R = s(() => import("./pages/DocumentationPage.js").then((e) => ({ default: e.DocumentationPage }))), z = s(() => import("./pages/ResourcesPage.js").then((e) => ({ default: e.ResourcesPage }))), B = s(() => import("./pages/SettingsPage.js").then((e) => ({ default: e.SettingsPage }))), V = s(() => import("./pages/PublishPage.js").then((e) => ({ default: e.PublishPage }))), H = s(() => import("./pages/AppLogsPage.js").then((e) => ({ default: e.AppLogsPage }))), U = s(() => import("./pages/DelegationsPage.js").then((e) => ({ default: e.DelegationsPage }))), W = s(() => import("./pages/ListingPreviewPage.js").then((e) => ({ default: e.ListingPreviewPage }))), G = s(() => import("./pages/StoreSubmissionPage.js").then((e) => ({ default: e.StoreSubmissionPage }))), K = s(() => import("./pages/PublisherProfilePage.js").then((e) => ({ default: e.PublisherProfilePage }))), q = s(() => import("./pages/SetupPage.js").then((e) => ({ default: e.SetupPage })));
33
30
  function J() {
31
+ return /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(Y, {}), /* @__PURE__ */ m(u, {})] });
32
+ }
33
+ function Y() {
34
34
  return /* @__PURE__ */ m("div", {
35
35
  className: "flex items-center justify-end border-b border-border-subtle bg-bg-surface/40 px-4 py-2",
36
36
  children: /* @__PURE__ */ m(i, {})
37
37
  });
38
38
  }
39
- function Y() {
40
- return /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(J, {}), /* @__PURE__ */ m(u, {})] });
41
- }
42
39
  function X() {
43
- return /* @__PURE__ */ m(u, {});
40
+ return /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(Y, {}), /* @__PURE__ */ m(u, {})] });
44
41
  }
45
42
  function Z() {
43
+ return /* @__PURE__ */ m(u, {});
44
+ }
45
+ function Q() {
46
46
  return /* @__PURE__ */ m(o, {
47
47
  fallback: /* @__PURE__ */ m(t, { message: "Loading page..." }),
48
48
  children: /* @__PURE__ */ h(f, { children: [
49
49
  /* @__PURE__ */ m(d, {
50
50
  path: "setup",
51
- element: _("setup", /* @__PURE__ */ m(K, {}))
51
+ element: _("setup", /* @__PURE__ */ m(q, {}))
52
52
  }),
53
53
  /* @__PURE__ */ h(d, {
54
- element: /* @__PURE__ */ m(q, {}),
54
+ element: /* @__PURE__ */ m(J, {}),
55
55
  children: [
56
56
  /* @__PURE__ */ m(d, {
57
57
  path: "apps/:appId",
@@ -67,40 +67,40 @@ function Z() {
67
67
  }),
68
68
  /* @__PURE__ */ m(d, {
69
69
  path: "apps/:appId/publish",
70
- element: _("apps.publish", /* @__PURE__ */ m(B, {}))
70
+ element: _("apps.publish", /* @__PURE__ */ m(V, {}))
71
71
  }),
72
72
  /* @__PURE__ */ m(d, {
73
73
  path: "apps/:appId/store-submission",
74
- element: _("apps.storeSubmission", /* @__PURE__ */ m(W, {}))
74
+ element: _("apps.storeSubmission", /* @__PURE__ */ m(G, {}))
75
75
  }),
76
76
  /* @__PURE__ */ m(d, {
77
77
  path: "apps/:appId/listing",
78
- element: _("apps.listing", /* @__PURE__ */ m(U, {}))
78
+ element: _("apps.listing", /* @__PURE__ */ m(W, {}))
79
79
  }),
80
80
  /* @__PURE__ */ m(d, {
81
81
  path: "apps/:appId/logs",
82
- element: _("apps.logs", /* @__PURE__ */ m(V, {}))
82
+ element: _("apps.logs", /* @__PURE__ */ m(H, {}))
83
83
  }),
84
84
  /* @__PURE__ */ m(d, {
85
85
  path: "apps/:appId/webhooks",
86
- element: _("apps.webhooks", /* @__PURE__ */ m(N, {}))
86
+ element: _("apps.webhooks", /* @__PURE__ */ m(P, {}))
87
87
  }),
88
88
  /* @__PURE__ */ m(d, {
89
89
  path: "apps/:appId/webhooks/new",
90
- element: _("apps.webhooks.create", /* @__PURE__ */ m(P, {}))
90
+ element: _("apps.webhooks.create", /* @__PURE__ */ m(F, {}))
91
91
  }),
92
92
  /* @__PURE__ */ m(d, {
93
93
  path: "apps/:appId/webhooks/:webhookId",
94
- element: _("apps.webhooks.detail", /* @__PURE__ */ m(F, {}))
94
+ element: _("apps.webhooks.detail", /* @__PURE__ */ m(I, {}))
95
95
  }),
96
96
  /* @__PURE__ */ m(d, {
97
97
  path: "apps/:appId/analytics",
98
- element: _("apps.analytics", /* @__PURE__ */ m(I, {}))
98
+ element: _("apps.analytics", /* @__PURE__ */ m(L, {}))
99
99
  })
100
100
  ]
101
101
  }),
102
102
  /* @__PURE__ */ h(d, {
103
- element: /* @__PURE__ */ m(Y, {}),
103
+ element: /* @__PURE__ */ m(X, {}),
104
104
  children: [
105
105
  /* @__PURE__ */ m(d, {
106
106
  index: !0,
@@ -136,19 +136,19 @@ function Z() {
136
136
  }),
137
137
  /* @__PURE__ */ m(d, {
138
138
  path: "delegations",
139
- element: _("delegations", /* @__PURE__ */ m(H, {}))
139
+ element: _("delegations", /* @__PURE__ */ m(U, {}))
140
140
  }),
141
141
  /* @__PURE__ */ m(d, {
142
142
  path: "webhooks/new",
143
- element: _("webhooks.create", /* @__PURE__ */ m(P, {}))
143
+ element: _("webhooks.create", /* @__PURE__ */ m(F, {}))
144
144
  }),
145
145
  /* @__PURE__ */ m(d, {
146
146
  path: "webhooks",
147
- element: _("webhooks", /* @__PURE__ */ m(N, {}))
147
+ element: _("webhooks", /* @__PURE__ */ m(P, {}))
148
148
  }),
149
149
  /* @__PURE__ */ m(d, {
150
150
  path: "analytics",
151
- element: _("analytics", /* @__PURE__ */ m(I, {}))
151
+ element: _("analytics", /* @__PURE__ */ m(L, {}))
152
152
  }),
153
153
  /* @__PURE__ */ m(d, {
154
154
  path: "revenue",
@@ -156,11 +156,11 @@ function Z() {
156
156
  }),
157
157
  /* @__PURE__ */ m(d, {
158
158
  path: "publisher/profile",
159
- element: _("publisher.profile", /* @__PURE__ */ m(G, {}))
159
+ element: _("publisher.profile", /* @__PURE__ */ m(K, {}))
160
160
  }),
161
161
  /* @__PURE__ */ m(d, {
162
162
  path: "settings",
163
- element: _("settings", /* @__PURE__ */ m(z, {}))
163
+ element: _("settings", /* @__PURE__ */ m(B, {}))
164
164
  }),
165
165
  /* @__PURE__ */ m(d, {
166
166
  path: "*",
@@ -169,35 +169,39 @@ function Z() {
169
169
  ]
170
170
  }),
171
171
  /* @__PURE__ */ h(d, {
172
- element: /* @__PURE__ */ m(X, {}),
172
+ element: /* @__PURE__ */ m(Z, {}),
173
173
  children: [
174
174
  /* @__PURE__ */ m(d, {
175
175
  path: "oauth",
176
- element: _("oauth", /* @__PURE__ */ m(O, {}))
176
+ element: _("oauth", /* @__PURE__ */ m(k, {}))
177
177
  }),
178
178
  /* @__PURE__ */ m(d, {
179
179
  path: "oauth/new",
180
- element: _("oauth.create", /* @__PURE__ */ m(k, {}))
180
+ element: _("oauth.create", /* @__PURE__ */ m(A, {}))
181
+ }),
182
+ /* @__PURE__ */ m(d, {
183
+ path: "oauth/callback",
184
+ element: _("oauth.callback", /* @__PURE__ */ m(O, {}))
181
185
  }),
182
186
  /* @__PURE__ */ m(d, {
183
187
  path: "oauth/:clientId",
184
- element: _("oauth.detail", /* @__PURE__ */ m(A, {}))
188
+ element: _("oauth.detail", /* @__PURE__ */ m(j, {}))
185
189
  }),
186
190
  /* @__PURE__ */ m(d, {
187
191
  path: "api-keys",
188
- element: _("apiKeys", /* @__PURE__ */ m(j, {}))
192
+ element: _("apiKeys", /* @__PURE__ */ m(M, {}))
189
193
  }),
190
194
  /* @__PURE__ */ m(d, {
191
195
  path: "api-keys/new",
192
- element: _("apiKeys.create", /* @__PURE__ */ m(M, {}))
196
+ element: _("apiKeys.create", /* @__PURE__ */ m(N, {}))
193
197
  }),
194
198
  /* @__PURE__ */ m(d, {
195
199
  path: "docs",
196
- element: _("docs", /* @__PURE__ */ m(L, {}))
200
+ element: _("docs", /* @__PURE__ */ m(R, {}))
197
201
  }),
198
202
  /* @__PURE__ */ m(d, {
199
203
  path: "resources",
200
- element: _("resources", /* @__PURE__ */ m(R, {}))
204
+ element: _("resources", /* @__PURE__ */ m(z, {}))
201
205
  })
202
206
  ]
203
207
  })
@@ -205,6 +209,6 @@ function Z() {
205
209
  });
206
210
  }
207
211
  //#endregion
208
- export { Z as DevportalRoutes };
212
+ export { Q as DevportalRoutes };
209
213
 
210
214
  //# sourceMappingURL=DevportalRoutes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DevportalRoutes.js","names":[],"sources":["../../src/devportal/DevportalRoutes.tsx"],"sourcesContent":["import { Suspense, lazy, useEffect, type ReactNode } from \"react\";\nimport { Routes, Route, Navigate, Outlet } from \"react-router-dom\";\nimport { LoadingState } from \"./components/LoadingState\";\nimport { FeatureFlaggedRoute } from \"./components/FeatureFlaggedRoute\";\nimport { TelemetryErrorBoundary } from \"./components/TelemetryErrorBoundary\";\nimport { OrgSwitcher } from \"./components/SectionNav\";\nimport { useDevportal } from \"./providers/DevportalProvider\";\n\n/**\n * Catch-all redirect target for the unmatched `*` route. Uses the\n * DevportalProvider's `basePath` and `navigate` so the redirect works\n * regardless of the integration mode (shell or standalone). Falls back to a\n * relative Navigate when neither is wired, which is the standalone/test path.\n */\nfunction CatchAllRedirect() {\n const { basePath, navigate } = useDevportal();\n useEffect(() => {\n if (basePath && navigate) {\n const target = basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n navigate(target || \"/\");\n }\n }, [basePath, navigate]);\n if (basePath && navigate) return null;\n return <Navigate to=\"..\" replace />;\n}\n\n/**\n * Wrap a page element with the per-route feature flag gate and a\n * telemetry-emitting error boundary. The flag name follows\n * `devportal.<page-slug>` convention; when disabled the user sees a\n * graceful fallback instead of a route-level crash.\n *\n * Per `dev/platform/context/feature-flags` and spec\n * `microfrontends/47-FRONTEND-EVENT-BUS.md` (error.boundary emission).\n */\nfunction gated(slug: string, element: ReactNode): ReactNode {\n return (\n <TelemetryErrorBoundary scope={slug}>\n <FeatureFlaggedRoute flag={`devportal.${slug}`}>\n {element}\n </FeatureFlaggedRoute>\n </TelemetryErrorBoundary>\n );\n}\n\n// Eager load the main dashboard page\nimport { DashboardPage } from \"./pages/DashboardPage\";\n\n// Lazy load all other pages\nconst OrganizationsPage = lazy(() =>\n import(\"./pages/OrganizationsPage\").then((m) => ({\n default: m.OrganizationsPage,\n })),\n);\nconst OrganizationDetailPage = lazy(() =>\n import(\"./pages/OrganizationDetailPage\").then((m) => ({\n default: m.OrganizationDetailPage,\n })),\n);\nconst CreateOrganizationPage = lazy(() =>\n import(\"./pages/CreateOrganizationPage\").then((m) => ({\n default: m.CreateOrganizationPage,\n })),\n);\nconst OrganizationMembersPage = lazy(() =>\n import(\"./pages/OrganizationMembersPage\").then((m) => ({\n default: m.OrganizationMembersPage,\n })),\n);\nconst RevenueDashboardPage = lazy(() =>\n import(\"./pages/RevenueDashboardPage\").then((m) => ({\n default: m.RevenueDashboardPage,\n })),\n);\nconst ApplicationsPage = lazy(() =>\n import(\"./pages/ApplicationsPage\").then((m) => ({\n default: m.ApplicationsPage,\n })),\n);\nconst ApplicationDetailPage = lazy(() =>\n import(\"./pages/ApplicationDetailPage\").then((m) => ({\n default: m.ApplicationDetailPage,\n })),\n);\nconst CreateApplicationPage = lazy(() =>\n import(\"./pages/CreateApplicationPage\").then((m) => ({\n default: m.CreateApplicationPage,\n })),\n);\nconst EditApplicationPage = lazy(() =>\n import(\"./pages/EditApplicationPage\").then((m) => ({\n default: m.EditApplicationPage,\n })),\n);\nconst ApplicationVersionsPage = lazy(() =>\n import(\"./pages/ApplicationVersionsPage\").then((m) => ({\n default: m.ApplicationVersionsPage,\n })),\n);\nconst OAuthClientsPage = lazy(() =>\n import(\"./pages/OAuthClientsPage\").then((m) => ({\n default: m.OAuthClientsPage,\n })),\n);\nconst CreateOAuthClientPage = lazy(() =>\n import(\"./pages/CreateOAuthClientPage\").then((m) => ({\n default: m.CreateOAuthClientPage,\n })),\n);\nconst OAuthClientDetailPage = lazy(() =>\n import(\"./pages/OAuthClientDetailPage\").then((m) => ({\n default: m.OAuthClientDetailPage,\n })),\n);\nconst ApiKeysPage = lazy(() =>\n import(\"./pages/ApiKeysPage\").then((m) => ({ default: m.ApiKeysPage })),\n);\nconst CreateApiKeyPage = lazy(() =>\n import(\"./pages/CreateApiKeyPage\").then((m) => ({\n default: m.CreateApiKeyPage,\n })),\n);\nconst WebhooksPage = lazy(() =>\n import(\"./pages/WebhooksPage\").then((m) => ({ default: m.WebhooksPage })),\n);\nconst CreateWebhookPage = lazy(() =>\n import(\"./pages/CreateWebhookPage\").then((m) => ({\n default: m.CreateWebhookPage,\n })),\n);\nconst WebhookDetailPage = lazy(() =>\n import(\"./pages/WebhookDetailPage\").then((m) => ({\n default: m.WebhookDetailPage,\n })),\n);\nconst AnalyticsDashboardPage = lazy(() =>\n import(\"./pages/AnalyticsDashboardPage\").then((m) => ({\n default: m.AnalyticsDashboardPage,\n })),\n);\nconst DocumentationPage = lazy(() =>\n import(\"./pages/DocumentationPage\").then((m) => ({\n default: m.DocumentationPage,\n })),\n);\nconst ResourcesPage = lazy(() =>\n import(\"./pages/ResourcesPage\").then((m) => ({ default: m.ResourcesPage })),\n);\nconst SettingsPage = lazy(() =>\n import(\"./pages/SettingsPage\").then((m) => ({ default: m.SettingsPage })),\n);\nconst PublishPage = lazy(() =>\n import(\"./pages/PublishPage\").then((m) => ({ default: m.PublishPage })),\n);\nconst AppLogsPage = lazy(() =>\n import(\"./pages/AppLogsPage\").then((m) => ({ default: m.AppLogsPage })),\n);\nconst DelegationsPage = lazy(() =>\n import(\"./pages/DelegationsPage\").then((m) => ({\n default: m.DelegationsPage,\n })),\n);\nconst ListingPreviewPage = lazy(() =>\n import(\"./pages/ListingPreviewPage\").then((m) => ({\n default: m.ListingPreviewPage,\n })),\n);\nconst StoreSubmissionPage = lazy(() =>\n import(\"./pages/StoreSubmissionPage\").then((m) => ({\n default: m.StoreSubmissionPage,\n })),\n);\nconst PublisherProfilePage = lazy(() =>\n import(\"./pages/PublisherProfilePage\").then((m) => ({\n default: m.PublisherProfilePage,\n })),\n);\nconst SetupPage = lazy(() =>\n import(\"./pages/SetupPage\").then((m) => ({ default: m.SetupPage })),\n);\n\n/** Layout for app-context routes (/apps/:appId/*) — adds the org context bar. */\nfunction AppLayout() {\n return (\n <>\n <OrgContextBar />\n <Outlet />\n </>\n );\n}\n\n/** Slim org-context bar shown above every devportal page. */\nfunction OrgContextBar() {\n return (\n <div className=\"flex items-center justify-end border-b border-border-subtle bg-bg-surface/40 px-4 py-2\">\n <OrgSwitcher />\n </div>\n );\n}\n\n/** Layout wrapping org-context devportal routes — adds the org context bar. */\nfunction GlobalLayout() {\n return (\n <>\n <OrgContextBar />\n <Outlet />\n </>\n );\n}\n\n/** Layout for pages that are not org-scoped (OAuth, API Keys, Docs, Resources). */\nfunction PlainLayout() {\n return <Outlet />;\n}\n\nexport function DevportalRoutes() {\n return (\n <Suspense fallback={<LoadingState message=\"Loading page...\" />}>\n <Routes>\n {/* Setup wizard — no SectionNav */}\n <Route path=\"setup\" element={gated(\"setup\", <SetupPage />)} />\n\n {/* App-context routes (/apps/:appId/*) — no SectionNav.\n The app-level tab bar inside ApplicationDetailPage is the nav here. */}\n <Route element={<AppLayout />}>\n <Route\n path=\"apps/:appId\"\n element={gated(\"apps.detail\", <ApplicationDetailPage />)}\n />\n <Route\n path=\"apps/:appId/edit\"\n element={gated(\"apps.edit\", <EditApplicationPage />)}\n />\n <Route\n path=\"apps/:appId/versions\"\n element={gated(\"apps.versions\", <ApplicationVersionsPage />)}\n />\n <Route\n path=\"apps/:appId/publish\"\n element={gated(\"apps.publish\", <PublishPage />)}\n />\n <Route\n path=\"apps/:appId/store-submission\"\n element={gated(\"apps.storeSubmission\", <StoreSubmissionPage />)}\n />\n <Route\n path=\"apps/:appId/listing\"\n element={gated(\"apps.listing\", <ListingPreviewPage />)}\n />\n <Route\n path=\"apps/:appId/logs\"\n element={gated(\"apps.logs\", <AppLogsPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks\"\n element={gated(\"apps.webhooks\", <WebhooksPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks/new\"\n element={gated(\"apps.webhooks.create\", <CreateWebhookPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks/:webhookId\"\n element={gated(\"apps.webhooks.detail\", <WebhookDetailPage />)}\n />\n <Route\n path=\"apps/:appId/analytics\"\n element={gated(\"apps.analytics\", <AnalyticsDashboardPage />)}\n />\n </Route>\n\n {/* All other routes — with SectionNav */}\n <Route element={<GlobalLayout />}>\n {/* Dashboard */}\n <Route index element={gated(\"dashboard\", <DashboardPage />)} />\n\n {/* Organizations */}\n <Route\n path=\"organizations\"\n element={gated(\"organizations\", <OrganizationsPage />)}\n />\n <Route\n path=\"organizations/new\"\n element={gated(\"organizations.create\", <CreateOrganizationPage />)}\n />\n <Route\n path=\"organizations/:orgId\"\n element={gated(\"organizations.detail\", <OrganizationDetailPage />)}\n />\n <Route\n path=\"organizations/:orgId/members\"\n element={gated(\n \"organizations.members\",\n <OrganizationMembersPage />,\n )}\n />\n <Route\n path=\"organizations/:orgId/revenue\"\n element={gated(\"organizations.revenue\", <RevenueDashboardPage />)}\n />\n\n {/* Applications list and create */}\n <Route path=\"apps\" element={gated(\"apps\", <ApplicationsPage />)} />\n <Route\n path=\"apps/new\"\n element={gated(\"apps.create\", <CreateApplicationPage />)}\n />\n\n {/* Delegations */}\n <Route\n path=\"delegations\"\n element={gated(\"delegations\", <DelegationsPage />)}\n />\n\n {/* Global Webhooks */}\n <Route\n path=\"webhooks/new\"\n element={gated(\"webhooks.create\", <CreateWebhookPage />)}\n />\n <Route\n path=\"webhooks\"\n element={gated(\"webhooks\", <WebhooksPage />)}\n />\n\n {/* Analytics & Revenue */}\n <Route\n path=\"analytics\"\n element={gated(\"analytics\", <AnalyticsDashboardPage />)}\n />\n <Route\n path=\"revenue\"\n element={gated(\"revenue\", <RevenueDashboardPage />)}\n />\n\n {/* Publisher */}\n <Route\n path=\"publisher/profile\"\n element={gated(\"publisher.profile\", <PublisherProfilePage />)}\n />\n\n {/* Settings */}\n <Route\n path=\"settings\"\n element={gated(\"settings\", <SettingsPage />)}\n />\n\n {/* Catch-all redirect to dashboard */}\n <Route path=\"*\" element={<CatchAllRedirect />} />\n </Route>\n\n {/* Non-org-context routes — no OrgContextBar */}\n <Route element={<PlainLayout />}>\n {/* OAuth Clients */}\n <Route path=\"oauth\" element={gated(\"oauth\", <OAuthClientsPage />)} />\n <Route\n path=\"oauth/new\"\n element={gated(\"oauth.create\", <CreateOAuthClientPage />)}\n />\n <Route\n path=\"oauth/:clientId\"\n element={gated(\"oauth.detail\", <OAuthClientDetailPage />)}\n />\n\n {/* API Keys */}\n <Route path=\"api-keys\" element={gated(\"apiKeys\", <ApiKeysPage />)} />\n <Route\n path=\"api-keys/new\"\n element={gated(\"apiKeys.create\", <CreateApiKeyPage />)}\n />\n\n {/* Documentation & Resources */}\n <Route path=\"docs\" element={gated(\"docs\", <DocumentationPage />)} />\n <Route\n path=\"resources\"\n element={gated(\"resources\", <ResourcesPage />)}\n />\n </Route>\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DevportalRoutes.js","names":[],"sources":["../../src/devportal/DevportalRoutes.tsx"],"sourcesContent":["import { Suspense, lazy, useEffect, type ReactNode } from \"react\";\nimport { Routes, Route, Navigate, Outlet } from \"react-router-dom\";\nimport { LoadingState } from \"./components/LoadingState\";\nimport { FeatureFlaggedRoute } from \"./components/FeatureFlaggedRoute\";\nimport { TelemetryErrorBoundary } from \"./components/TelemetryErrorBoundary\";\nimport { OrgSwitcher } from \"./components/SectionNav\";\nimport { useDevportal } from \"./providers/DevportalProvider\";\n\n/**\n * Catch-all redirect target for the unmatched `*` route. Uses the\n * DevportalProvider's `basePath` and `navigate` so the redirect works\n * regardless of the integration mode (shell or standalone). Falls back to a\n * relative Navigate when neither is wired, which is the standalone/test path.\n */\nfunction CatchAllRedirect() {\n const { basePath, navigate } = useDevportal();\n useEffect(() => {\n if (basePath && navigate) {\n const target = basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n navigate(target || \"/\");\n }\n }, [basePath, navigate]);\n if (basePath && navigate) return null;\n return <Navigate to=\"..\" replace />;\n}\n\n/**\n * Wrap a page element with the per-route feature flag gate and a\n * telemetry-emitting error boundary. The flag name follows\n * `devportal.<page-slug>` convention; when disabled the user sees a\n * graceful fallback instead of a route-level crash.\n *\n * Per `dev/platform/context/feature-flags` and spec\n * `microfrontends/47-FRONTEND-EVENT-BUS.md` (error.boundary emission).\n */\nfunction gated(slug: string, element: ReactNode): ReactNode {\n return (\n <TelemetryErrorBoundary scope={slug}>\n <FeatureFlaggedRoute flag={`devportal.${slug}`}>\n {element}\n </FeatureFlaggedRoute>\n </TelemetryErrorBoundary>\n );\n}\n\n// Eager load the main dashboard page\nimport { DashboardPage } from \"./pages/DashboardPage\";\n\n// Lazy load all other pages\nconst OrganizationsPage = lazy(() =>\n import(\"./pages/OrganizationsPage\").then((m) => ({\n default: m.OrganizationsPage,\n })),\n);\nconst OrganizationDetailPage = lazy(() =>\n import(\"./pages/OrganizationDetailPage\").then((m) => ({\n default: m.OrganizationDetailPage,\n })),\n);\nconst CreateOrganizationPage = lazy(() =>\n import(\"./pages/CreateOrganizationPage\").then((m) => ({\n default: m.CreateOrganizationPage,\n })),\n);\nconst OrganizationMembersPage = lazy(() =>\n import(\"./pages/OrganizationMembersPage\").then((m) => ({\n default: m.OrganizationMembersPage,\n })),\n);\nconst RevenueDashboardPage = lazy(() =>\n import(\"./pages/RevenueDashboardPage\").then((m) => ({\n default: m.RevenueDashboardPage,\n })),\n);\nconst ApplicationsPage = lazy(() =>\n import(\"./pages/ApplicationsPage\").then((m) => ({\n default: m.ApplicationsPage,\n })),\n);\nconst ApplicationDetailPage = lazy(() =>\n import(\"./pages/ApplicationDetailPage\").then((m) => ({\n default: m.ApplicationDetailPage,\n })),\n);\nconst CreateApplicationPage = lazy(() =>\n import(\"./pages/CreateApplicationPage\").then((m) => ({\n default: m.CreateApplicationPage,\n })),\n);\nconst EditApplicationPage = lazy(() =>\n import(\"./pages/EditApplicationPage\").then((m) => ({\n default: m.EditApplicationPage,\n })),\n);\nconst ApplicationVersionsPage = lazy(() =>\n import(\"./pages/ApplicationVersionsPage\").then((m) => ({\n default: m.ApplicationVersionsPage,\n })),\n);\nconst OAuthCallbackPage = lazy(() =>\n import(\"./pages/OAuthCallbackPage\").then((m) => ({\n default: m.OAuthCallbackPage,\n })),\n);\nconst OAuthClientsPage = lazy(() =>\n import(\"./pages/OAuthClientsPage\").then((m) => ({\n default: m.OAuthClientsPage,\n })),\n);\nconst CreateOAuthClientPage = lazy(() =>\n import(\"./pages/CreateOAuthClientPage\").then((m) => ({\n default: m.CreateOAuthClientPage,\n })),\n);\nconst OAuthClientDetailPage = lazy(() =>\n import(\"./pages/OAuthClientDetailPage\").then((m) => ({\n default: m.OAuthClientDetailPage,\n })),\n);\nconst ApiKeysPage = lazy(() =>\n import(\"./pages/ApiKeysPage\").then((m) => ({ default: m.ApiKeysPage })),\n);\nconst CreateApiKeyPage = lazy(() =>\n import(\"./pages/CreateApiKeyPage\").then((m) => ({\n default: m.CreateApiKeyPage,\n })),\n);\nconst WebhooksPage = lazy(() =>\n import(\"./pages/WebhooksPage\").then((m) => ({ default: m.WebhooksPage })),\n);\nconst CreateWebhookPage = lazy(() =>\n import(\"./pages/CreateWebhookPage\").then((m) => ({\n default: m.CreateWebhookPage,\n })),\n);\nconst WebhookDetailPage = lazy(() =>\n import(\"./pages/WebhookDetailPage\").then((m) => ({\n default: m.WebhookDetailPage,\n })),\n);\nconst AnalyticsDashboardPage = lazy(() =>\n import(\"./pages/AnalyticsDashboardPage\").then((m) => ({\n default: m.AnalyticsDashboardPage,\n })),\n);\nconst DocumentationPage = lazy(() =>\n import(\"./pages/DocumentationPage\").then((m) => ({\n default: m.DocumentationPage,\n })),\n);\nconst ResourcesPage = lazy(() =>\n import(\"./pages/ResourcesPage\").then((m) => ({ default: m.ResourcesPage })),\n);\nconst SettingsPage = lazy(() =>\n import(\"./pages/SettingsPage\").then((m) => ({ default: m.SettingsPage })),\n);\nconst PublishPage = lazy(() =>\n import(\"./pages/PublishPage\").then((m) => ({ default: m.PublishPage })),\n);\nconst AppLogsPage = lazy(() =>\n import(\"./pages/AppLogsPage\").then((m) => ({ default: m.AppLogsPage })),\n);\nconst DelegationsPage = lazy(() =>\n import(\"./pages/DelegationsPage\").then((m) => ({\n default: m.DelegationsPage,\n })),\n);\nconst ListingPreviewPage = lazy(() =>\n import(\"./pages/ListingPreviewPage\").then((m) => ({\n default: m.ListingPreviewPage,\n })),\n);\nconst StoreSubmissionPage = lazy(() =>\n import(\"./pages/StoreSubmissionPage\").then((m) => ({\n default: m.StoreSubmissionPage,\n })),\n);\nconst PublisherProfilePage = lazy(() =>\n import(\"./pages/PublisherProfilePage\").then((m) => ({\n default: m.PublisherProfilePage,\n })),\n);\nconst SetupPage = lazy(() =>\n import(\"./pages/SetupPage\").then((m) => ({ default: m.SetupPage })),\n);\n\n/** Layout for app-context routes (/apps/:appId/*) — adds the org context bar. */\nfunction AppLayout() {\n return (\n <>\n <OrgContextBar />\n <Outlet />\n </>\n );\n}\n\n/** Slim org-context bar shown above every devportal page. */\nfunction OrgContextBar() {\n return (\n <div className=\"flex items-center justify-end border-b border-border-subtle bg-bg-surface/40 px-4 py-2\">\n <OrgSwitcher />\n </div>\n );\n}\n\n/** Layout wrapping org-context devportal routes — adds the org context bar. */\nfunction GlobalLayout() {\n return (\n <>\n <OrgContextBar />\n <Outlet />\n </>\n );\n}\n\n/** Layout for pages that are not org-scoped (OAuth, API Keys, Docs, Resources). */\nfunction PlainLayout() {\n return <Outlet />;\n}\n\nexport function DevportalRoutes() {\n return (\n <Suspense fallback={<LoadingState message=\"Loading page...\" />}>\n <Routes>\n {/* Setup wizard — no SectionNav */}\n <Route path=\"setup\" element={gated(\"setup\", <SetupPage />)} />\n\n {/* App-context routes (/apps/:appId/*) — no SectionNav.\n The app-level tab bar inside ApplicationDetailPage is the nav here. */}\n <Route element={<AppLayout />}>\n <Route\n path=\"apps/:appId\"\n element={gated(\"apps.detail\", <ApplicationDetailPage />)}\n />\n <Route\n path=\"apps/:appId/edit\"\n element={gated(\"apps.edit\", <EditApplicationPage />)}\n />\n <Route\n path=\"apps/:appId/versions\"\n element={gated(\"apps.versions\", <ApplicationVersionsPage />)}\n />\n <Route\n path=\"apps/:appId/publish\"\n element={gated(\"apps.publish\", <PublishPage />)}\n />\n <Route\n path=\"apps/:appId/store-submission\"\n element={gated(\"apps.storeSubmission\", <StoreSubmissionPage />)}\n />\n <Route\n path=\"apps/:appId/listing\"\n element={gated(\"apps.listing\", <ListingPreviewPage />)}\n />\n <Route\n path=\"apps/:appId/logs\"\n element={gated(\"apps.logs\", <AppLogsPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks\"\n element={gated(\"apps.webhooks\", <WebhooksPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks/new\"\n element={gated(\"apps.webhooks.create\", <CreateWebhookPage />)}\n />\n <Route\n path=\"apps/:appId/webhooks/:webhookId\"\n element={gated(\"apps.webhooks.detail\", <WebhookDetailPage />)}\n />\n <Route\n path=\"apps/:appId/analytics\"\n element={gated(\"apps.analytics\", <AnalyticsDashboardPage />)}\n />\n </Route>\n\n {/* All other routes — with SectionNav */}\n <Route element={<GlobalLayout />}>\n {/* Dashboard */}\n <Route index element={gated(\"dashboard\", <DashboardPage />)} />\n\n {/* Organizations */}\n <Route\n path=\"organizations\"\n element={gated(\"organizations\", <OrganizationsPage />)}\n />\n <Route\n path=\"organizations/new\"\n element={gated(\"organizations.create\", <CreateOrganizationPage />)}\n />\n <Route\n path=\"organizations/:orgId\"\n element={gated(\"organizations.detail\", <OrganizationDetailPage />)}\n />\n <Route\n path=\"organizations/:orgId/members\"\n element={gated(\n \"organizations.members\",\n <OrganizationMembersPage />,\n )}\n />\n <Route\n path=\"organizations/:orgId/revenue\"\n element={gated(\"organizations.revenue\", <RevenueDashboardPage />)}\n />\n\n {/* Applications list and create */}\n <Route path=\"apps\" element={gated(\"apps\", <ApplicationsPage />)} />\n <Route\n path=\"apps/new\"\n element={gated(\"apps.create\", <CreateApplicationPage />)}\n />\n\n {/* Delegations */}\n <Route\n path=\"delegations\"\n element={gated(\"delegations\", <DelegationsPage />)}\n />\n\n {/* Global Webhooks */}\n <Route\n path=\"webhooks/new\"\n element={gated(\"webhooks.create\", <CreateWebhookPage />)}\n />\n <Route\n path=\"webhooks\"\n element={gated(\"webhooks\", <WebhooksPage />)}\n />\n\n {/* Analytics & Revenue */}\n <Route\n path=\"analytics\"\n element={gated(\"analytics\", <AnalyticsDashboardPage />)}\n />\n <Route\n path=\"revenue\"\n element={gated(\"revenue\", <RevenueDashboardPage />)}\n />\n\n {/* Publisher */}\n <Route\n path=\"publisher/profile\"\n element={gated(\"publisher.profile\", <PublisherProfilePage />)}\n />\n\n {/* Settings */}\n <Route\n path=\"settings\"\n element={gated(\"settings\", <SettingsPage />)}\n />\n\n {/* Catch-all redirect to dashboard */}\n <Route path=\"*\" element={<CatchAllRedirect />} />\n </Route>\n\n {/* Non-org-context routes — no OrgContextBar */}\n <Route element={<PlainLayout />}>\n {/* OAuth Clients */}\n <Route path=\"oauth\" element={gated(\"oauth\", <OAuthClientsPage />)} />\n <Route\n path=\"oauth/new\"\n element={gated(\"oauth.create\", <CreateOAuthClientPage />)}\n />\n <Route\n path=\"oauth/callback\"\n element={gated(\"oauth.callback\", <OAuthCallbackPage />)}\n />\n <Route\n path=\"oauth/:clientId\"\n element={gated(\"oauth.detail\", <OAuthClientDetailPage />)}\n />\n\n {/* API Keys */}\n <Route path=\"api-keys\" element={gated(\"apiKeys\", <ApiKeysPage />)} />\n <Route\n path=\"api-keys/new\"\n element={gated(\"apiKeys.create\", <CreateApiKeyPage />)}\n />\n\n {/* Documentation & Resources */}\n <Route path=\"docs\" element={gated(\"docs\", <DocumentationPage />)} />\n <Route\n path=\"resources\"\n element={gated(\"resources\", <ResourcesPage />)}\n />\n </Route>\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ConfirmDialog.js","names":[],"sources":["../../../src/devportal/components/ConfirmDialog.tsx"],"sourcesContent":["import { useEffect, useId, useRef, type FC, type ReactNode } from \"react\";\nimport { AlertTriangle, Info, CheckCircle, XCircle } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { cn } from \"../utils/cn\";\n\nexport interface ConfirmDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void | Promise<void>;\n title: string;\n description?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n variant?: \"default\" | \"danger\" | \"warning\" | \"success\" | \"destructive\";\n loading?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Confirmation dialog component\n */\nexport const ConfirmDialog: FC<ConfirmDialogProps> = ({\n open,\n onOpenChange,\n onConfirm,\n title,\n description,\n confirmLabel = \"Confirm\",\n cancelLabel = \"Cancel\",\n variant = \"default\",\n loading = false,\n children,\n}) => {\n const titleId = useId();\n const descriptionId = useId();\n const dialogRef = useRef<HTMLDivElement | null>(null);\n const confirmButtonRef = useRef<HTMLButtonElement | null>(null);\n const previousFocusRef = useRef<HTMLElement | null>(null);\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n useEffect(() => {\n if (!open) {\n return undefined;\n }\n\n previousFocusRef.current = document.activeElement as HTMLElement | null;\n const originalOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n const focusTarget = confirmButtonRef.current ?? dialogRef.current;\n window.requestAnimationFrame(() => {\n focusTarget?.focus();\n });\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\" && !loading) {\n event.preventDefault();\n onOpenChange(false);\n }\n };\n\n document.addEventListener(\"keydown\", onKeyDown);\n\n return () => {\n document.body.style.overflow = originalOverflow;\n document.removeEventListener(\"keydown\", onKeyDown);\n previousFocusRef.current?.focus();\n };\n }, [loading, onOpenChange, open]);\n\n if (!open) return null;\n\n // Map 'destructive' to 'danger' for internal use\n const normalizedVariant = variant === \"destructive\" ? \"danger\" : variant;\n\n const variantStyles = {\n default: {\n icon: <Info className=\"h-6 w-6 text-accent-blue\" />,\n iconBg: \"bg-status-info-bg-subtle\",\n button: \"bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90\",\n },\n danger: {\n icon: <XCircle className=\"h-6 w-6 text-status-error-text\" />,\n iconBg: \"bg-status-error-bg-subtle\",\n button: \"bg-status-error-bg text-white hover:bg-status-error-bg/90\",\n },\n warning: {\n icon: <AlertTriangle className=\"h-6 w-6 text-status-warning-text\" />,\n iconBg: \"bg-status-warning-bg-subtle\",\n button: \"bg-status-warning-bg text-white hover:bg-status-warning-bg/90\",\n },\n success: {\n icon: <CheckCircle className=\"h-6 w-6 text-status-success-text\" />,\n iconBg: \"bg-status-success-bg-subtle\",\n button: \"bg-status-success-bg text-white hover:bg-status-success-bg/90\",\n },\n };\n\n const styles = variantStyles[normalizedVariant];\n\n const handleClose = () => onOpenChange(false);\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n {/* Backdrop */}\n <button\n type=\"button\"\n aria-label=\"Close dialog backdrop\"\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={handleClose}\n />\n\n {/* Dialog */}\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n aria-describedby={description || children ? descriptionId : undefined}\n tabIndex={-1}\n className=\"relative z-10 w-full max-w-md rounded-lg bg-bg-surface p-6 shadow-xl\"\n >\n <div className=\"flex items-start gap-4\">\n <div className={cn(\"rounded-full p-2\", styles.iconBg)}>\n {styles.icon}\n </div>\n <div className=\"flex-1\">\n <h3 id={titleId} className=\"text-lg font-semibold\">\n {title}\n </h3>\n {description && (\n <p\n id={descriptionId}\n className=\"mt-2 text-sm text-text-secondary\"\n >\n {description}\n </p>\n )}\n {children && (\n <div\n className=\"mt-4\"\n id={description ? undefined : descriptionId}\n >\n {children}\n </div>\n )}\n </div>\n </div>\n\n <div className=\"mt-6 flex justify-end gap-3\">\n <button\n type=\"button\"\n onClick={handleClose}\n disabled={loading}\n className=\"rounded-md border px-4 py-2 text-sm font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {cancelLabel}\n </button>\n <button\n ref={confirmButtonRef}\n type=\"button\"\n onClick={onConfirm}\n disabled={loading}\n className={cn(\n \"rounded-md px-4 py-2 text-sm font-medium transition-colors disabled:opacity-50\",\n styles.button,\n )}\n >\n {loading\n ? tr(\"devportal.processing\", \"Processing...\")\n : confirmLabel}\n </button>\n </div>\n </div>\n </div>\n );\n};\n\n/**\n * Alert banner component\n */\nexport const Alert: FC<{\n variant?: \"info\" | \"warning\" | \"error\" | \"success\";\n title?: string;\n children: ReactNode;\n onDismiss?: () => void;\n className?: string;\n}> = ({ variant = \"info\", title, children, onDismiss, className }) => {\n const variantStyles = {\n info: \"bg-status-info-bg-subtle border-border-subtle text-status-info-text\",\n warning:\n \"bg-status-warning-bg-subtle border-border-subtle text-status-warning-text\",\n error:\n \"bg-status-error-bg-subtle border-border-subtle text-status-error-text\",\n success:\n \"bg-status-success-bg-subtle border-border-subtle text-status-success-text\",\n };\n\n const icons = {\n info: <Info className=\"h-5 w-5\" />,\n warning: <AlertTriangle className=\"h-5 w-5\" />,\n error: <XCircle className=\"h-5 w-5\" />,\n success: <CheckCircle className=\"h-5 w-5\" />,\n };\n\n return (\n <div\n className={cn(\"rounded-lg border p-4\", variantStyles[variant], className)}\n >\n <div className=\"flex items-start gap-3\">\n {icons[variant]}\n <div className=\"flex-1\">\n {title && <h4 className=\"font-medium\">{title}</h4>}\n <div className=\"text-sm\">{children}</div>\n </div>\n {onDismiss && (\n <button\n type=\"button\"\n onClick={onDismiss}\n className=\"hover:opacity-70\"\n >\n <XCircle className=\"h-5 w-5\" />\n </button>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ConfirmDialog.js","names":[],"sources":["../../../src/devportal/components/ConfirmDialog.tsx"],"sourcesContent":["import { useEffect, useId, useRef, type FC, type ReactNode } from \"react\";\nimport { AlertTriangle, Info, CheckCircle, XCircle } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { cn } from \"../utils/cn\";\n\nexport interface ConfirmDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void | Promise<void>;\n title: string;\n description?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n variant?: \"default\" | \"danger\" | \"warning\" | \"success\" | \"destructive\";\n loading?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Confirmation dialog component\n */\nexport const ConfirmDialog: FC<ConfirmDialogProps> = ({\n open,\n onOpenChange,\n onConfirm,\n title,\n description,\n confirmLabel = \"Confirm\",\n cancelLabel = \"Cancel\",\n variant = \"default\",\n loading = false,\n children,\n}) => {\n const titleId = useId();\n const descriptionId = useId();\n const dialogRef = useRef<HTMLDivElement | null>(null);\n const confirmButtonRef = useRef<HTMLButtonElement | null>(null);\n const previousFocusRef = useRef<HTMLElement | null>(null);\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n useEffect(() => {\n if (!open) {\n return undefined;\n }\n\n previousFocusRef.current = document.activeElement as HTMLElement | null;\n const originalOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n const focusTarget = confirmButtonRef.current ?? dialogRef.current;\n window.requestAnimationFrame(() => {\n focusTarget?.focus();\n });\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\" && !loading) {\n event.preventDefault();\n onOpenChange(false);\n }\n };\n\n document.addEventListener(\"keydown\", onKeyDown);\n\n return () => {\n document.body.style.overflow = originalOverflow;\n document.removeEventListener(\"keydown\", onKeyDown);\n previousFocusRef.current?.focus();\n };\n }, [loading, onOpenChange, open]);\n\n if (!open) return null;\n\n // Map 'destructive' to 'danger' for internal use\n const normalizedVariant = variant === \"destructive\" ? \"danger\" : variant;\n\n const variantStyles = {\n default: {\n icon: <Info className=\"h-6 w-6 text-accent-blue\" />,\n iconBg: \"bg-status-info-bg-subtle\",\n button:\n \"bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90\",\n },\n danger: {\n icon: <XCircle className=\"h-6 w-6 text-status-error-text\" />,\n iconBg: \"bg-status-error-bg-subtle\",\n button: \"bg-status-error-bg text-white hover:bg-status-error-bg/90\",\n },\n warning: {\n icon: <AlertTriangle className=\"h-6 w-6 text-status-warning-text\" />,\n iconBg: \"bg-status-warning-bg-subtle\",\n button: \"bg-status-warning-bg text-white hover:bg-status-warning-bg/90\",\n },\n success: {\n icon: <CheckCircle className=\"h-6 w-6 text-status-success-text\" />,\n iconBg: \"bg-status-success-bg-subtle\",\n button: \"bg-status-success-bg text-white hover:bg-status-success-bg/90\",\n },\n };\n\n const styles = variantStyles[normalizedVariant];\n\n const handleClose = () => onOpenChange(false);\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n {/* Backdrop */}\n <button\n type=\"button\"\n aria-label=\"Close dialog backdrop\"\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={handleClose}\n />\n\n {/* Dialog */}\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n aria-describedby={description || children ? descriptionId : undefined}\n tabIndex={-1}\n className=\"relative z-10 w-full max-w-md rounded-lg bg-bg-surface p-6 shadow-xl\"\n >\n <div className=\"flex items-start gap-4\">\n <div className={cn(\"rounded-full p-2\", styles.iconBg)}>\n {styles.icon}\n </div>\n <div className=\"flex-1\">\n <h3 id={titleId} className=\"text-lg font-semibold\">\n {title}\n </h3>\n {description && (\n <p\n id={descriptionId}\n className=\"mt-2 text-sm text-text-secondary\"\n >\n {description}\n </p>\n )}\n {children && (\n <div\n className=\"mt-4\"\n id={description ? undefined : descriptionId}\n >\n {children}\n </div>\n )}\n </div>\n </div>\n\n <div className=\"mt-6 flex justify-end gap-3\">\n <button\n type=\"button\"\n onClick={handleClose}\n disabled={loading}\n className=\"rounded-md border px-4 py-2 text-sm font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {cancelLabel}\n </button>\n <button\n ref={confirmButtonRef}\n type=\"button\"\n onClick={onConfirm}\n disabled={loading}\n className={cn(\n \"rounded-md px-4 py-2 text-sm font-medium transition-colors disabled:opacity-50\",\n styles.button,\n )}\n >\n {loading\n ? tr(\"devportal.processing\", \"Processing...\")\n : confirmLabel}\n </button>\n </div>\n </div>\n </div>\n );\n};\n\n/**\n * Alert banner component\n */\nexport const Alert: FC<{\n variant?: \"info\" | \"warning\" | \"error\" | \"success\";\n title?: string;\n children: ReactNode;\n onDismiss?: () => void;\n className?: string;\n}> = ({ variant = \"info\", title, children, onDismiss, className }) => {\n const variantStyles = {\n info: \"bg-status-info-bg-subtle border-border-subtle text-status-info-text\",\n warning:\n \"bg-status-warning-bg-subtle border-border-subtle text-status-warning-text\",\n error:\n \"bg-status-error-bg-subtle border-border-subtle text-status-error-text\",\n success:\n \"bg-status-success-bg-subtle border-border-subtle text-status-success-text\",\n };\n\n const icons = {\n info: <Info className=\"h-5 w-5\" />,\n warning: <AlertTriangle className=\"h-5 w-5\" />,\n error: <XCircle className=\"h-5 w-5\" />,\n success: <CheckCircle className=\"h-5 w-5\" />,\n };\n\n return (\n <div\n className={cn(\"rounded-lg border p-4\", variantStyles[variant], className)}\n >\n <div className=\"flex items-start gap-3\">\n {icons[variant]}\n <div className=\"flex-1\">\n {title && <h4 className=\"font-medium\">{title}</h4>}\n <div className=\"text-sm\">{children}</div>\n </div>\n {onDismiss && (\n <button\n type=\"button\"\n onClick={onDismiss}\n className=\"hover:opacity-70\"\n >\n <XCircle className=\"h-5 w-5\" />\n </button>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"DataTable.js","names":[],"sources":["../../../src/devportal/components/DataTable.tsx"],"sourcesContent":["import type { FC, ReactNode } from \"react\";\nimport {\n ChevronLeft,\n ChevronRight,\n ChevronsLeft,\n ChevronsRight,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { cn } from \"../utils/cn\";\n\nexport interface Column<T> {\n key: string;\n header: ReactNode;\n render?: (item: T) => ReactNode;\n className?: string;\n sortable?: boolean;\n}\n\nexport interface DataTableProps<T> {\n data: T[];\n columns: Column<T>[];\n keyField: keyof T;\n onRowClick?: (item: T) => void;\n className?: string;\n emptyMessage?: string;\n loading?: boolean;\n pagination?: {\n page: number;\n pageSize: number;\n totalCount: number;\n onPageChange: (page: number) => void;\n };\n}\n\n/**\n * Reusable data table component with pagination\n */\nexport function DataTable<T extends { [K in keyof T]: T[K] }>({\n data,\n columns,\n keyField,\n onRowClick,\n className,\n emptyMessage,\n loading,\n pagination,\n}: DataTableProps<T>) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const resolvedEmptyMessage =\n emptyMessage ?? tr(\"devportal.noDataAvailable\", \"No data available\");\n const totalPages = pagination\n ? Math.ceil(pagination.totalCount / pagination.pageSize)\n : 1;\n\n return (\n <div\n className={cn(\n \"rounded-lg border border-border-seam bg-bg-surface\",\n className,\n )}\n >\n <div className=\"overflow-x-auto\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/40\">\n {columns.map((column) => (\n <th\n key={column.key}\n className={cn(\n \"px-4 py-3 text-left text-sm font-medium text-text-secondary\",\n column.className,\n )}\n >\n {column.header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {loading ? (\n Array.from({ length: 5 }).map((_, i) => (\n <tr key={i} className=\"animate-pulse border-b border-border-seam\">\n {columns.map((column) => (\n <td key={column.key} className=\"px-4 py-3\">\n <div className=\"h-4 rounded bg-bg-sunken\" />\n </td>\n ))}\n </tr>\n ))\n ) : data.length === 0 ? (\n <tr>\n <td\n colSpan={columns.length}\n className=\"px-4 py-8 text-center text-text-secondary\"\n >\n {resolvedEmptyMessage}\n </td>\n </tr>\n ) : (\n data.map((item) => (\n <tr\n key={String(item[keyField])}\n role={onRowClick ? \"button\" : undefined}\n tabIndex={onRowClick ? 0 : undefined}\n className={cn(\n \"border-b border-border-seam transition-colors\",\n onRowClick &&\n \"cursor-pointer hover:bg-bg-sunken/50 focus-visible:outline-none focus-visible:bg-bg-sunken/50\",\n )}\n onClick={() => onRowClick?.(item)}\n onKeyDown={(event) => {\n if (!onRowClick) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onRowClick(item);\n }\n }}\n >\n {columns.map((column) => (\n <td\n key={String(column.key)}\n className={cn(\"px-4 py-3 text-sm\", column.className)}\n >\n {column.render\n ? column.render(item)\n : String(\n (item as Record<string, unknown>)[\n column.key as string\n ] ?? \"\",\n )}\n </td>\n ))}\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n\n {/* Pagination */}\n {pagination && totalPages > 1 && (\n <div className=\"flex items-center justify-between border-t border-border-seam px-4 py-3\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.showingResults\", \"Showing\")}{\" \"}\n {(pagination.page - 1) * pagination.pageSize + 1}{\" \"}\n {tr(\"devportal.to\", \"to\")}{\" \"}\n {Math.min(\n pagination.page * pagination.pageSize,\n pagination.totalCount,\n )}{\" \"}\n {tr(\"devportal.of\", \"of\")} {pagination.totalCount}{\" \"}\n {tr(\"devportal.results\", \"results\")}\n </p>\n <div className=\"flex items-center gap-1\">\n <button\n onClick={() => pagination.onPageChange(1)}\n disabled={pagination.page === 1}\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md hover:bg-bg-sunken disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronsLeft size={20} />\n </button>\n <button\n onClick={() => pagination.onPageChange(pagination.page - 1)}\n disabled={pagination.page === 1}\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md hover:bg-bg-sunken disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronLeft size={20} />\n </button>\n <span className=\"px-3 text-sm\">\n {tr(\"devportal.page\", \"Page\")} {pagination.page}{\" \"}\n {tr(\"devportal.of\", \"of\")} {totalPages}\n </span>\n <button\n onClick={() => pagination.onPageChange(pagination.page + 1)}\n disabled={pagination.page === totalPages}\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md hover:bg-bg-sunken disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronRight size={20} />\n </button>\n <button\n onClick={() => pagination.onPageChange(totalPages)}\n disabled={pagination.page === totalPages}\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md hover:bg-bg-sunken disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronsRight size={20} />\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n\n/**\n * Simple key-value detail list\n */\nexport const DetailList: FC<{\n items: Array<{ label: string; value: ReactNode }>;\n className?: string;\n}> = ({ items, className }) => (\n <dl\n className={cn(\n \"divide-y divide-border-seam rounded-lg border border-border-seam\",\n className,\n )}\n >\n {items.map((item, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-1 px-4 py-3 sm:flex-row sm:gap-4\"\n >\n <dt className=\"text-sm font-medium text-text-secondary sm:w-1/3\">\n {item.label}\n </dt>\n <dd className=\"text-sm sm:w-2/3\">{item.value}</dd>\n </div>\n ))}\n </dl>\n);\n"],"mappings":";;;;;AAqCA,SAAgB,EAA8C,EAC5D,SACA,YACA,aACA,eACA,cACA,iBACA,YACA,iBACoB;CACpB,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAA6B;EACpD,IAAM,IAAQ,EAAE,EAAI;AACpB,SAAO,MAAU,IAAM,IAAW;IAE9B,IACJ,KAAgB,EAAG,6BAA6B,oBAAoB,EAChE,IAAa,IACf,KAAK,KAAK,EAAW,aAAa,EAAW,SAAS,GACtD;AAEJ,QACE,kBAAC,OAAD;EACE,WAAW,EACT,sDACA,EACD;YAJH,CAME,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,SAAD;IAAO,WAAU;cAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAQ,KAAK,MACZ,kBAAC,MAAD;MAEE,WAAW,EACT,+DACA,EAAO,UACR;gBAEA,EAAO;MACL,EAPE,EAAO,IAOT,CACL;KACC,CAAA,EACC,CAAA,EACR,kBAAC,SAAD,EAAA,UACG,IACC,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,MAChC,kBAAC,MAAD;KAAY,WAAU;eACnB,EAAQ,KAAK,MACZ,kBAAC,MAAD;MAAqB,WAAU;gBAC7B,kBAAC,OAAD,EAAK,WAAU,4BAA6B,CAAA;MACzC,EAFI,EAAO,IAEX,CACL;KACC,EANI,EAMJ,CACL,GACA,EAAK,WAAW,IAClB,kBAAC,MAAD,EAAA,UACE,kBAAC,MAAD;KACE,SAAS,EAAQ;KACjB,WAAU;eAET;KACE,CAAA,EACF,CAAA,GAEL,EAAK,KAAK,MACR,kBAAC,MAAD;KAEE,MAAM,IAAa,WAAW,KAAA;KAC9B,UAAU,IAAa,IAAI,KAAA;KAC3B,WAAW,EACT,iDACA,KACE,gGACH;KACD,eAAe,IAAa,EAAK;KACjC,YAAY,MAAU;AACf,YACD,EAAM,QAAQ,WAAW,EAAM,QAAQ,SACzC,EAAM,gBAAgB,EACtB,EAAW,EAAK;;eAInB,EAAQ,KAAK,MACZ,kBAAC,MAAD;MAEE,WAAW,EAAG,qBAAqB,EAAO,UAAU;gBAEnD,EAAO,SACJ,EAAO,OAAO,EAAK,GACnB,OACG,EACC,EAAO,QACJ,GACN;MACF,EAVE,OAAO,EAAO,IAAI,CAUpB,CACL;KACC,EA/BE,OAAO,EAAK,GAAU,CA+BxB,CACL,EAEE,CAAA,CACF;;GACJ,CAAA,EAGL,KAAc,IAAa,KAC1B,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAb;KACG,EAAG,4BAA4B,UAAU;KAAE;MAC1C,EAAW,OAAO,KAAK,EAAW,WAAW;KAAG;KACjD,EAAG,gBAAgB,KAAK;KAAE;KAC1B,KAAK,IACJ,EAAW,OAAO,EAAW,UAC7B,EAAW,WACZ;KAAE;KACF,EAAG,gBAAgB,KAAK;KAAC;KAAE,EAAW;KAAY;KAClD,EAAG,qBAAqB,UAAU;KACjC;OACJ,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,UAAD;MACE,eAAe,EAAW,aAAa,EAAE;MACzC,UAAU,EAAW,SAAS;MAC9B,WAAU;gBAEV,kBAAC,GAAD,EAAc,MAAM,IAAM,CAAA;MACnB,CAAA;KACT,kBAAC,UAAD;MACE,eAAe,EAAW,aAAa,EAAW,OAAO,EAAE;MAC3D,UAAU,EAAW,SAAS;MAC9B,WAAU;gBAEV,kBAAC,GAAD,EAAa,MAAM,IAAM,CAAA;MAClB,CAAA;KACT,kBAAC,QAAD;MAAM,WAAU;gBAAhB;OACG,EAAG,kBAAkB,OAAO;OAAC;OAAE,EAAW;OAAM;OAChD,EAAG,gBAAgB,KAAK;OAAC;OAAE;OACvB;;KACP,kBAAC,UAAD;MACE,eAAe,EAAW,aAAa,EAAW,OAAO,EAAE;MAC3D,UAAU,EAAW,SAAS;MAC9B,WAAU;gBAEV,kBAAC,GAAD,EAAc,MAAM,IAAM,CAAA;MACnB,CAAA;KACT,kBAAC,UAAD;MACE,eAAe,EAAW,aAAa,EAAW;MAClD,UAAU,EAAW,SAAS;MAC9B,WAAU;gBAEV,kBAAC,GAAD,EAAe,MAAM,IAAM,CAAA;MACpB,CAAA;KACL;MACF;KAEJ;;;AAOV,IAAa,KAGP,EAAE,UAAO,mBACb,kBAAC,MAAD;CACE,WAAW,EACT,oEACA,EACD;WAEA,EAAM,KAAK,GAAM,MAChB,kBAAC,OAAD;EAEE,WAAU;YAFZ,CAIE,kBAAC,MAAD;GAAI,WAAU;aACX,EAAK;GACH,CAAA,EACL,kBAAC,MAAD;GAAI,WAAU;aAAoB,EAAK;GAAW,CAAA,CAC9C;IAPC,EAOD,CACN;CACC,CAAA"}
1
+ {"version":3,"file":"DataTable.js","names":[],"sources":["../../../src/devportal/components/DataTable.tsx"],"sourcesContent":["import type { FC, ReactNode } from \"react\";\nimport {\n ChevronLeft,\n ChevronRight,\n ChevronsLeft,\n ChevronsRight,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { cn } from \"../utils/cn\";\n\nexport interface Column<T> {\n key: string;\n header: ReactNode;\n render?: (item: T) => ReactNode;\n className?: string;\n sortable?: boolean;\n}\n\nexport interface DataTableProps<T> {\n data: T[];\n columns: Column<T>[];\n keyField: keyof T;\n onRowClick?: (item: T) => void;\n className?: string;\n emptyMessage?: string;\n loading?: boolean;\n pagination?: {\n page: number;\n pageSize: number;\n totalCount: number;\n onPageChange: (page: number) => void;\n };\n}\n\n/**\n * Reusable data table component with pagination\n */\nexport function DataTable<T extends { [K in keyof T]: T[K] }>({\n data,\n columns,\n keyField,\n onRowClick,\n className,\n emptyMessage,\n loading,\n pagination,\n}: DataTableProps<T>) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const resolvedEmptyMessage =\n emptyMessage ?? tr(\"devportal.noDataAvailable\", \"No data available\");\n const totalPages = pagination\n ? Math.ceil(pagination.totalCount / pagination.pageSize)\n : 1;\n\n return (\n <div\n className={cn(\n \"rounded-lg border border-border-seam bg-bg-surface\",\n className,\n )}\n >\n <div className=\"overflow-x-auto\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/40\">\n {columns.map((column) => (\n <th\n key={column.key}\n className={cn(\n \"px-4 py-3 text-left text-sm font-medium text-text-secondary\",\n column.className,\n )}\n >\n {column.header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {loading ? (\n Array.from({ length: 5 }).map((_, i) => (\n <tr\n key={i}\n className=\"animate-pulse border-b border-border-seam\"\n >\n {columns.map((column) => (\n <td key={column.key} className=\"px-4 py-3\">\n <div className=\"h-4 rounded bg-bg-sunken\" />\n </td>\n ))}\n </tr>\n ))\n ) : data.length === 0 ? (\n <tr>\n <td\n colSpan={columns.length}\n className=\"px-4 py-8 text-center text-text-secondary\"\n >\n {resolvedEmptyMessage}\n </td>\n </tr>\n ) : (\n data.map((item) => (\n <tr\n key={String(item[keyField])}\n role={onRowClick ? \"button\" : undefined}\n tabIndex={onRowClick ? 0 : undefined}\n className={cn(\n \"border-b border-border-seam transition-colors\",\n onRowClick &&\n \"cursor-pointer hover:bg-bg-sunken/50 focus-visible:outline-none focus-visible:bg-bg-sunken/50\",\n )}\n onClick={() => onRowClick?.(item)}\n onKeyDown={(event) => {\n if (!onRowClick) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onRowClick(item);\n }\n }}\n >\n {columns.map((column) => (\n <td\n key={String(column.key)}\n className={cn(\"px-4 py-3 text-sm\", column.className)}\n >\n {column.render\n ? column.render(item)\n : String(\n (item as Record<string, unknown>)[\n column.key as string\n ] ?? \"\",\n )}\n </td>\n ))}\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n\n {/* Pagination */}\n {pagination && totalPages > 1 && (\n <div className=\"flex items-center justify-between border-t border-border-seam px-4 py-3\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.showingResults\", \"Showing\")}{\" \"}\n {(pagination.page - 1) * pagination.pageSize + 1}{\" \"}\n {tr(\"devportal.to\", \"to\")}{\" \"}\n {Math.min(\n pagination.page * pagination.pageSize,\n pagination.totalCount,\n )}{\" \"}\n {tr(\"devportal.of\", \"of\")} {pagination.totalCount}{\" \"}\n {tr(\"devportal.results\", \"results\")}\n </p>\n <div className=\"flex items-center gap-1\">\n <button\n onClick={() => pagination.onPageChange(1)}\n disabled={pagination.page === 1}\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md hover:bg-bg-sunken disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronsLeft size={20} />\n </button>\n <button\n onClick={() => pagination.onPageChange(pagination.page - 1)}\n disabled={pagination.page === 1}\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md hover:bg-bg-sunken disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronLeft size={20} />\n </button>\n <span className=\"px-3 text-sm\">\n {tr(\"devportal.page\", \"Page\")} {pagination.page}{\" \"}\n {tr(\"devportal.of\", \"of\")} {totalPages}\n </span>\n <button\n onClick={() => pagination.onPageChange(pagination.page + 1)}\n disabled={pagination.page === totalPages}\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md hover:bg-bg-sunken disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronRight size={20} />\n </button>\n <button\n onClick={() => pagination.onPageChange(totalPages)}\n disabled={pagination.page === totalPages}\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md hover:bg-bg-sunken disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronsRight size={20} />\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n\n/**\n * Simple key-value detail list\n */\nexport const DetailList: FC<{\n items: Array<{ label: string; value: ReactNode }>;\n className?: string;\n}> = ({ items, className }) => (\n <dl\n className={cn(\n \"divide-y divide-border-seam rounded-lg border border-border-seam\",\n className,\n )}\n >\n {items.map((item, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-1 px-4 py-3 sm:flex-row sm:gap-4\"\n >\n <dt className=\"text-sm font-medium text-text-secondary sm:w-1/3\">\n {item.label}\n </dt>\n <dd className=\"text-sm sm:w-2/3\">{item.value}</dd>\n </div>\n ))}\n </dl>\n);\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"FormField.js","names":[],"sources":["../../../src/devportal/components/FormField.tsx"],"sourcesContent":["import type {\n FC,\n InputHTMLAttributes,\n TextareaHTMLAttributes,\n SelectHTMLAttributes,\n ReactNode,\n} from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { cn } from \"../utils/cn\";\n\ninterface BaseFieldProps {\n label: string;\n error?: string;\n hint?: string;\n required?: boolean;\n className?: string;\n}\n\ninterface InputFieldProps\n extends\n BaseFieldProps,\n Omit<InputHTMLAttributes<HTMLInputElement>, \"className\"> {\n type?: \"text\" | \"email\" | \"password\" | \"number\" | \"url\" | \"tel\";\n}\n\ninterface TextareaFieldProps\n extends\n BaseFieldProps,\n Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, \"className\"> {}\n\ninterface SelectFieldProps\n extends\n BaseFieldProps,\n Omit<SelectHTMLAttributes<HTMLSelectElement>, \"className\"> {\n options: Array<{ value: string; label: string }>;\n placeholder?: string;\n}\n\ninterface CheckboxFieldProps\n extends\n BaseFieldProps,\n Omit<InputHTMLAttributes<HTMLInputElement>, \"className\" | \"type\"> {\n description?: string;\n}\n\n/**\n * Text input field with label and error handling\n */\nexport const InputField: FC<InputFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n type = \"text\",\n id,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <input\n id={fieldId}\n type={type}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n \"placeholder:text-text-secondary\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n />\n {hint && !error && (\n <p className=\"text-xs text-text-secondary\">{hint}</p>\n )}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Textarea field with label and error handling\n */\nexport const TextareaField: FC<TextareaFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n id,\n rows = 4,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <textarea\n id={fieldId}\n rows={rows}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n \"placeholder:text-text-secondary resize-none\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n />\n {hint && !error && (\n <p className=\"text-xs text-text-secondary\">{hint}</p>\n )}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Select field with label and error handling\n */\nexport const SelectField: FC<SelectFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n options,\n placeholder,\n id,\n ...props\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const resolvedPlaceholder =\n placeholder ?? tr(\"devportal.selectAnOption\", \"Select an option\");\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <select\n id={fieldId}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n >\n <option value=\"\">{resolvedPlaceholder}</option>\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n {hint && !error && (\n <p className=\"text-xs text-text-secondary\">{hint}</p>\n )}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Checkbox field with label and description\n */\nexport const CheckboxField: FC<CheckboxFieldProps> = ({\n label,\n description,\n error,\n className,\n id,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"flex items-start gap-3\", className)}>\n <input\n id={fieldId}\n type=\"checkbox\"\n className={cn(\n \"mt-1 h-4 w-4 rounded border-border-default text-primary\",\n \"focus:ring-primary\",\n )}\n {...props}\n />\n <div>\n <label htmlFor={fieldId} className=\"text-sm font-medium cursor-pointer\">\n {label}\n </label>\n {description && (\n <p className=\"text-xs text-text-secondary\">{description}</p>\n )}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n </div>\n );\n};\n\n/**\n * Multi-select checkbox group\n */\nexport const CheckboxGroup: FC<{\n label: string;\n options: Array<{ value: string; label: string; description?: string }>;\n value: string[];\n onChange: (values: string[]) => void;\n error?: string;\n hint?: string;\n className?: string;\n}> = ({ label, options, value, onChange, error, hint, className }) => {\n const handleChange = (optionValue: string, checked: boolean) => {\n if (checked) {\n onChange([...value, optionValue]);\n } else {\n onChange(value.filter((v) => v !== optionValue));\n }\n };\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n <label className=\"block text-sm font-medium\">{label}</label>\n <div className=\"space-y-2\">\n {options.map((option) => (\n <CheckboxField\n key={option.value}\n label={option.label}\n description={option.description}\n checked={value.includes(option.value)}\n onChange={(e) => handleChange(option.value, e.target.checked)}\n />\n ))}\n </div>\n {hint && !error && (\n <p className=\"text-xs text-text-secondary\">{hint}</p>\n )}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Tag input for multiple values\n */\nexport const TagInput: FC<{\n label: string;\n value: string[];\n onChange: (values: string[]) => void;\n placeholder?: string;\n error?: string;\n hint?: string;\n className?: string;\n}> = ({ label, value, onChange, placeholder, error, hint, className }) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" || e.key === \",\") {\n e.preventDefault();\n const input = e.currentTarget;\n const newValue = input.value.trim();\n if (newValue && !value.includes(newValue)) {\n onChange([...value, newValue]);\n input.value = \"\";\n }\n }\n };\n\n const removeTag = (tagToRemove: string) => {\n onChange(value.filter((tag) => tag !== tagToRemove));\n };\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label className=\"block text-sm font-medium\">{label}</label>\n <div className=\"flex flex-wrap gap-2 rounded-md border bg-bg-surface p-2\">\n {value.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 rounded-full bg-action-primary-bg/10 px-2 py-1 text-xs\"\n >\n {tag}\n <button\n type=\"button\"\n onClick={() => removeTag(tag)}\n className=\"hover:text-status-error-text\"\n >\n &times;\n </button>\n </span>\n ))}\n <input\n type=\"text\"\n placeholder={\n value.length === 0\n ? placeholder\n : tr(\"devportal.addMore\", \"Add more...\")\n }\n onKeyDown={handleKeyDown}\n className=\"flex-1 min-w-[100px] bg-transparent text-sm outline-none\"\n />\n </div>\n {hint && !error && (\n <p className=\"text-xs text-text-secondary\">{hint}</p>\n )}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"FormField.js","names":[],"sources":["../../../src/devportal/components/FormField.tsx"],"sourcesContent":["import type {\n FC,\n InputHTMLAttributes,\n TextareaHTMLAttributes,\n SelectHTMLAttributes,\n ReactNode,\n} from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { cn } from \"../utils/cn\";\n\ninterface BaseFieldProps {\n label: string;\n error?: string;\n hint?: string;\n required?: boolean;\n className?: string;\n}\n\ninterface InputFieldProps\n extends\n BaseFieldProps,\n Omit<InputHTMLAttributes<HTMLInputElement>, \"className\"> {\n type?: \"text\" | \"email\" | \"password\" | \"number\" | \"url\" | \"tel\";\n}\n\ninterface TextareaFieldProps\n extends\n BaseFieldProps,\n Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, \"className\"> {}\n\ninterface SelectFieldProps\n extends\n BaseFieldProps,\n Omit<SelectHTMLAttributes<HTMLSelectElement>, \"className\"> {\n options: Array<{ value: string; label: string }>;\n placeholder?: string;\n}\n\ninterface CheckboxFieldProps\n extends\n BaseFieldProps,\n Omit<InputHTMLAttributes<HTMLInputElement>, \"className\" | \"type\"> {\n description?: string;\n}\n\n/**\n * Text input field with label and error handling\n */\nexport const InputField: FC<InputFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n type = \"text\",\n id,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <input\n id={fieldId}\n type={type}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n \"placeholder:text-text-secondary\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n />\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Textarea field with label and error handling\n */\nexport const TextareaField: FC<TextareaFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n id,\n rows = 4,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <textarea\n id={fieldId}\n rows={rows}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n \"placeholder:text-text-secondary resize-none\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n />\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Select field with label and error handling\n */\nexport const SelectField: FC<SelectFieldProps> = ({\n label,\n error,\n hint,\n required,\n className,\n options,\n placeholder,\n id,\n ...props\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const resolvedPlaceholder =\n placeholder ?? tr(\"devportal.selectAnOption\", \"Select an option\");\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium\">\n {label}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n <select\n id={fieldId}\n className={cn(\n \"w-full rounded-md border bg-bg-surface px-3 py-2 text-sm\",\n \"focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent\",\n error && \"border-status-error-bg focus:ring-status-error-bg\",\n )}\n {...props}\n >\n <option value=\"\">{resolvedPlaceholder}</option>\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Checkbox field with label and description\n */\nexport const CheckboxField: FC<CheckboxFieldProps> = ({\n label,\n description,\n error,\n className,\n id,\n ...props\n}) => {\n const fieldId = id || label.toLowerCase().replace(/\\s+/g, \"-\");\n\n return (\n <div className={cn(\"flex items-start gap-3\", className)}>\n <input\n id={fieldId}\n type=\"checkbox\"\n className={cn(\n \"mt-1 h-4 w-4 rounded border-border-default text-primary\",\n \"focus:ring-primary\",\n )}\n {...props}\n />\n <div>\n <label htmlFor={fieldId} className=\"text-sm font-medium cursor-pointer\">\n {label}\n </label>\n {description && (\n <p className=\"text-xs text-text-secondary\">{description}</p>\n )}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n </div>\n );\n};\n\n/**\n * Multi-select checkbox group\n */\nexport const CheckboxGroup: FC<{\n label: string;\n options: Array<{ value: string; label: string; description?: string }>;\n value: string[];\n onChange: (values: string[]) => void;\n error?: string;\n hint?: string;\n className?: string;\n}> = ({ label, options, value, onChange, error, hint, className }) => {\n const handleChange = (optionValue: string, checked: boolean) => {\n if (checked) {\n onChange([...value, optionValue]);\n } else {\n onChange(value.filter((v) => v !== optionValue));\n }\n };\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n <label className=\"block text-sm font-medium\">{label}</label>\n <div className=\"space-y-2\">\n {options.map((option) => (\n <CheckboxField\n key={option.value}\n label={option.label}\n description={option.description}\n checked={value.includes(option.value)}\n onChange={(e) => handleChange(option.value, e.target.checked)}\n />\n ))}\n </div>\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n/**\n * Tag input for multiple values\n */\nexport const TagInput: FC<{\n label: string;\n value: string[];\n onChange: (values: string[]) => void;\n placeholder?: string;\n error?: string;\n hint?: string;\n className?: string;\n}> = ({ label, value, onChange, placeholder, error, hint, className }) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" || e.key === \",\") {\n e.preventDefault();\n const input = e.currentTarget;\n const newValue = input.value.trim();\n if (newValue && !value.includes(newValue)) {\n onChange([...value, newValue]);\n input.value = \"\";\n }\n }\n };\n\n const removeTag = (tagToRemove: string) => {\n onChange(value.filter((tag) => tag !== tagToRemove));\n };\n\n return (\n <div className={cn(\"space-y-1\", className)}>\n <label className=\"block text-sm font-medium\">{label}</label>\n <div className=\"flex flex-wrap gap-2 rounded-md border bg-bg-surface p-2\">\n {value.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 rounded-full bg-action-primary-bg/10 px-2 py-1 text-xs\"\n >\n {tag}\n <button\n type=\"button\"\n onClick={() => removeTag(tag)}\n className=\"hover:text-status-error-text\"\n >\n &times;\n </button>\n </span>\n ))}\n <input\n type=\"text\"\n placeholder={\n value.length === 0\n ? placeholder\n : tr(\"devportal.addMore\", \"Add more...\")\n }\n onKeyDown={handleKeyDown}\n className=\"flex-1 min-w-[100px] bg-transparent text-sm outline-none\"\n />\n </div>\n {hint && !error && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n"],"mappings":"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"}
@@ -166,7 +166,8 @@ var _ = ({ open: _, onOpenChange: v, appId: y, appName: b, appScopes: x, preSele
166
166
  className: "font-medium text-text-primary",
167
167
  children: b
168
168
  }),
169
- " to act on your behalf"
169
+ " ",
170
+ "to act on your behalf"
170
171
  ]
171
172
  })]
172
173
  }),