@burdenoff/microfe-devportal 2026.921.2 → 2026.1013.1

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.
@@ -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, useLocation } from \"react-router\";\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);\nconst InvitationDecisionPage = lazy(() =>\n import(\"./pages/InvitationDecisionPage\").then((m) => ({\n default: m.InvitationDecisionPage,\n })),\n);\nconst SellerDashboardPage = lazy(() =>\n import(\"./pages/SellerDashboardPage\").then((m) => ({\n default: m.SellerDashboardPage,\n })),\n);\nconst SellerItemsPage = lazy(() =>\n import(\"./pages/SellerItemsPage\").then((m) => ({\n default: m.SellerItemsPage,\n })),\n);\nconst CreatePhysicalItemPage = lazy(() =>\n import(\"./pages/CreatePhysicalItemPage\").then((m) => ({\n default: m.CreatePhysicalItemPage,\n })),\n);\nconst SellerOrdersPage = lazy(() =>\n import(\"./pages/SellerOrdersPage\").then((m) => ({\n default: m.SellerOrdersPage,\n })),\n);\nconst EditPhysicalItemPage = lazy(() =>\n import(\"./pages/EditPhysicalItemPage\").then((m) => ({\n default: m.EditPhysicalItemPage,\n })),\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/**\n * The org switcher only matters on pages that actually read the active-org\n * state it controls (dashboard, apps, webhooks, analytics, revenue, create\n * flows, etc). Pages that are already scoped by their own route param (an\n * org/item detail page) or that list every org regardless of which one is\n * \"active\" (the org list) don't use that state at all, so showing a\n * switcher there is just confusing. Matched by path suffix so it doesn't\n * care which basePath a given product shell mounts devportal under, and\n * works for both the digital (`organizations`) and seller\n * (`seller/organizations`) route families since they share the same pages.\n */\nfunction hideOrgSwitcher(pathname: string): boolean {\n const segments = pathname.split(\"/\").filter(Boolean);\n const last = segments[segments.length - 1];\n const secondLast = segments[segments.length - 2];\n const thirdLast = segments[segments.length - 3];\n\n // organizations | seller/organizations (list)\n if (last === \"organizations\") return true;\n // organizations/:id | seller/organizations/:id (detail) — not /new\n if (secondLast === \"organizations\" && last !== \"new\") return true;\n // seller/items/:id (item edit) — not /new\n if (thirdLast === \"seller\" && secondLast === \"items\" && last !== \"new\")\n return true;\n\n return false;\n}\n\n/** Layout wrapping org-context devportal routes — adds the org context bar,\n * except on routes that don't depend on the active-org it controls. */\nfunction GlobalLayout() {\n const { pathname } = useLocation();\n return (\n <>\n {!hideOrgSwitcher(pathname) && <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 <Route\n path=\"invitations/:token\"\n element={\n <TelemetryErrorBoundary scope=\"invitations.accept\">\n <InvitationDecisionPage />\n </TelemetryErrorBoundary>\n }\n />\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 {/* Seller routes */}\n <Route\n path=\"seller\"\n element={gated(\"seller.dashboard\", <SellerDashboardPage />)}\n />\n <Route\n path=\"seller/items\"\n element={gated(\"seller.items\", <SellerItemsPage />)}\n />\n <Route\n path=\"seller/items/new\"\n element={gated(\"seller.items.create\", <CreatePhysicalItemPage />)}\n />\n <Route\n path=\"seller/items/:itemId\"\n element={gated(\"seller.items.edit\", <EditPhysicalItemPage />)}\n />\n <Route\n path=\"seller/orders\"\n element={gated(\"seller.orders\", <SellerOrdersPage />)}\n />\n\n {/* Seller organizations — same pages as the regular \"Organizations\"\n routes above, reused as-is. They tell PHYSICAL from DIGITAL by\n route (useIsSellerSection), not by a separate component. See\n DeveloperOrgKind (BOFF-7285). */}\n <Route\n path=\"seller/organizations\"\n element={gated(\"seller.organizations\", <OrganizationsPage />)}\n />\n <Route\n path=\"seller/organizations/new\"\n element={gated(\n \"seller.organizations.create\",\n <CreateOrganizationPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId\"\n element={gated(\n \"seller.organizations.detail\",\n <OrganizationDetailPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId/members\"\n element={gated(\n \"seller.organizations.members\",\n <OrganizationMembersPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId/revenue\"\n element={gated(\n \"seller.organizations.revenue\",\n <RevenueDashboardPage />,\n )}\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
+ {"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, useLocation } from \"react-router\";\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/commercial/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);\nconst InvitationDecisionPage = lazy(() =>\n import(\"./pages/InvitationDecisionPage\").then((m) => ({\n default: m.InvitationDecisionPage,\n })),\n);\nconst SellerDashboardPage = lazy(() =>\n import(\"./pages/SellerDashboardPage\").then((m) => ({\n default: m.SellerDashboardPage,\n })),\n);\nconst SellerItemsPage = lazy(() =>\n import(\"./pages/SellerItemsPage\").then((m) => ({\n default: m.SellerItemsPage,\n })),\n);\nconst CreatePhysicalItemPage = lazy(() =>\n import(\"./pages/CreatePhysicalItemPage\").then((m) => ({\n default: m.CreatePhysicalItemPage,\n })),\n);\nconst SellerOrdersPage = lazy(() =>\n import(\"./pages/SellerOrdersPage\").then((m) => ({\n default: m.SellerOrdersPage,\n })),\n);\nconst EditPhysicalItemPage = lazy(() =>\n import(\"./pages/EditPhysicalItemPage\").then((m) => ({\n default: m.EditPhysicalItemPage,\n })),\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/**\n * The org switcher only matters on pages that actually read the active-org\n * state it controls (dashboard, apps, webhooks, analytics, revenue, create\n * flows, etc). Pages that are already scoped by their own route param (an\n * org/item detail page) or that list every org regardless of which one is\n * \"active\" (the org list) don't use that state at all, so showing a\n * switcher there is just confusing. Matched by path suffix so it doesn't\n * care which basePath a given product shell mounts devportal under, and\n * works for both the digital (`organizations`) and seller\n * (`seller/organizations`) route families since they share the same pages.\n */\nfunction hideOrgSwitcher(pathname: string): boolean {\n const segments = pathname.split(\"/\").filter(Boolean);\n const last = segments[segments.length - 1];\n const secondLast = segments[segments.length - 2];\n const thirdLast = segments[segments.length - 3];\n\n // organizations | seller/organizations (list)\n if (last === \"organizations\") return true;\n // organizations/:id | seller/organizations/:id (detail) — not /new\n if (secondLast === \"organizations\" && last !== \"new\") return true;\n // seller/items/:id (item edit) — not /new\n if (thirdLast === \"seller\" && secondLast === \"items\" && last !== \"new\")\n return true;\n\n return false;\n}\n\n/** Layout wrapping org-context devportal routes — adds the org context bar,\n * except on routes that don't depend on the active-org it controls. */\nfunction GlobalLayout() {\n const { pathname } = useLocation();\n return (\n <>\n {!hideOrgSwitcher(pathname) && <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 <Route\n path=\"invitations/:token\"\n element={\n <TelemetryErrorBoundary scope=\"invitations.accept\">\n <InvitationDecisionPage />\n </TelemetryErrorBoundary>\n }\n />\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 {/* Seller routes */}\n <Route\n path=\"seller\"\n element={gated(\"seller.dashboard\", <SellerDashboardPage />)}\n />\n <Route\n path=\"seller/items\"\n element={gated(\"seller.items\", <SellerItemsPage />)}\n />\n <Route\n path=\"seller/items/new\"\n element={gated(\"seller.items.create\", <CreatePhysicalItemPage />)}\n />\n <Route\n path=\"seller/items/:itemId\"\n element={gated(\"seller.items.edit\", <EditPhysicalItemPage />)}\n />\n <Route\n path=\"seller/orders\"\n element={gated(\"seller.orders\", <SellerOrdersPage />)}\n />\n\n {/* Seller organizations — same pages as the regular \"Organizations\"\n routes above, reused as-is. They tell PHYSICAL from DIGITAL by\n route (useIsSellerSection), not by a separate component. See\n DeveloperOrgKind (BOFF-7285). */}\n <Route\n path=\"seller/organizations\"\n element={gated(\"seller.organizations\", <OrganizationsPage />)}\n />\n <Route\n path=\"seller/organizations/new\"\n element={gated(\n \"seller.organizations.create\",\n <CreateOrganizationPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId\"\n element={gated(\n \"seller.organizations.detail\",\n <OrganizationDetailPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId/members\"\n element={gated(\n \"seller.organizations.members\",\n <OrganizationMembersPage />,\n )}\n />\n <Route\n path=\"seller/organizations/:orgId/revenue\"\n element={gated(\n \"seller.organizations.revenue\",\n <RevenueDashboardPage />,\n )}\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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"}
@@ -47,7 +47,7 @@ var d = ({ open: d, onOpenChange: f, onConfirm: p, title: m, description: h, con
47
47
  }
48
48
  }[v === "destructive" ? "danger" : v], k = () => f(!1);
49
49
  return /* @__PURE__ */ u("div", {
50
- className: "fixed inset-0 z-50 flex items-center justify-center",
50
+ className: "fixed inset-0 z-50 flex items-center justify-center pt-[3.5rem]",
51
51
  children: [/* @__PURE__ */ l("button", {
52
52
  type: "button",
53
53
  "aria-label": "Close dialog backdrop",
@@ -60,7 +60,7 @@ var d = ({ open: d, onOpenChange: f, onConfirm: p, title: m, description: h, con
60
60
  "aria-labelledby": x,
61
61
  "aria-describedby": h || b ? S : void 0,
62
62
  tabIndex: -1,
63
- className: "relative z-10 w-full max-w-md rounded-lg bg-bg-surface p-6 shadow-xl",
63
+ className: "relative z-10 flex max-h-[calc(100dvh-3.5rem-2rem)] w-full max-w-md flex-col overflow-y-auto rounded-lg bg-bg-surface p-6 shadow-xl",
64
64
  children: [/* @__PURE__ */ u("div", {
65
65
  className: "flex items-start gap-4",
66
66
  children: [/* @__PURE__ */ l("div", {
@@ -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 { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\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 tr = useTr();\n\n // Keep a stable ref to the latest onOpenChange. Parents commonly pass an\n // inline arrow (new reference every render), so depending on it directly\n // would re-run the focus effect on every keystroke and yank focus away from\n // form inputs. Storing it in a ref lets the effect depend only on open/loading.\n const onOpenChangeRef = useRef(onOpenChange);\n useEffect(() => {\n onOpenChangeRef.current = onOpenChange;\n }, [onOpenChange]);\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 // For form dialogs (with children), focus the container so Tab naturally\n // walks through the form fields first. Only auto-focus the confirm button\n // for simple confirmation dialogs that have no form fields.\n const focusTarget = children\n ? dialogRef.current\n : (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 onOpenChangeRef.current(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 // children is intentionally omitted: it re-creates every render and would\n // re-trigger focus-stealing on each keystroke. Only open/loading gate this.\n }, [loading, 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
+ {"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 { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\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 tr = useTr();\n\n // Keep a stable ref to the latest onOpenChange. Parents commonly pass an\n // inline arrow (new reference every render), so depending on it directly\n // would re-run the focus effect on every keystroke and yank focus away from\n // form inputs. Storing it in a ref lets the effect depend only on open/loading.\n const onOpenChangeRef = useRef(onOpenChange);\n useEffect(() => {\n onOpenChangeRef.current = onOpenChange;\n }, [onOpenChange]);\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 // For form dialogs (with children), focus the container so Tab naturally\n // walks through the form fields first. Only auto-focus the confirm button\n // for simple confirmation dialogs that have no form fields.\n const focusTarget = children\n ? dialogRef.current\n : (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 onOpenChangeRef.current(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 // children is intentionally omitted: it re-creates every render and would\n // re-trigger focus-stealing on each keystroke. Only open/loading gate this.\n }, [loading, 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 pt-[3.5rem]\">\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 flex max-h-[calc(100dvh-3.5rem-2rem)] w-full max-w-md flex-col overflow-y-auto 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":"FeatureFlaggedRoute.js","names":[],"sources":["../../../src/devportal/components/FeatureFlaggedRoute.tsx"],"sourcesContent":["/**\n * FeatureFlaggedRoute\n *\n * Wraps a route's lazy-loaded element with a feature flag gate.\n * When the flag is disabled the user sees a friendly \"feature unavailable\"\n * message; otherwise the wrapped page renders.\n *\n * Default-allow: if the flag service is unreachable or returns nothing,\n * the FeatureFlagProvider's `defaultEnabled` setting controls behaviour\n * (currently `true` — see `DevportalRoot.tsx`).\n *\n * Per `dev/platform/context/feature-flags`.\n */\nimport type { FC, ReactNode } from \"react\";\nimport { useFeatureFlag } from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { EmptyState } from \"./EmptyState\";\n\nexport interface FeatureFlaggedRouteProps {\n flag: string;\n children: ReactNode;\n /** Optional override message; defaults to translated \"coming soon\" copy. */\n fallback?: ReactNode;\n}\n\n/**\n * Safely evaluate a feature flag — `useFeatureFlag` itself throws if no\n * `FeatureFlagProvider` is mounted (standalone dev mode). We always call\n * the hook (rules-of-hooks) and rely on the underlying provider's\n * `defaultEnabled` to default-allow.\n */\nconst useFeatureFlagSafe = (flag: string): boolean => {\n try {\n return useFeatureFlag(flag);\n } catch {\n return true;\n }\n};\n\nconst useI18nSafe = (): {\n t: (key: string, fallback?: string) => string;\n} => {\n try {\n const ctx = useI18n();\n return { t: (key, fallback) => ctx.t(key, fallback) };\n } catch {\n return { t: (key, fallback) => fallback ?? key };\n }\n};\n\nexport const FeatureFlaggedRoute: FC<FeatureFlaggedRouteProps> = ({\n flag,\n children,\n fallback,\n}) => {\n const enabled = useFeatureFlagSafe(flag);\n const { t } = useI18nSafe();\n\n if (enabled) return <>{children}</>;\n if (fallback) return <>{fallback}</>;\n\n return (\n <EmptyState\n title={t(\n \"devportal.featureDisabled.title\",\n \"This feature is currently unavailable\",\n )}\n description={t(\n \"devportal.featureDisabled.description\",\n \"Your administrator has disabled this section. Please check back later.\",\n )}\n />\n );\n};\n"],"mappings":";;;;;AA+BA,IAAM,KAAsB,MAA0B;AACpD,KAAI;AACF,SAAO,EAAe,EAAK;SACrB;AACN,SAAO;;GAIL,UAED;AACH,KAAI;EACF,IAAM,IAAM,GAAS;AACrB,SAAO,EAAE,IAAI,GAAK,MAAa,EAAI,EAAE,GAAK,EAAS,EAAE;SAC/C;AACN,SAAO,EAAE,IAAI,GAAK,MAAa,KAAY,GAAK;;GAIvC,KAAqD,EAChE,SACA,aACA,kBACI;CACJ,IAAM,IAAU,EAAmB,EAAK,EAClC,EAAE,SAAM,GAAa;AAK3B,QAHI,IAAgB,kBAAA,GAAA,EAAG,aAAY,CAAA,GAC/B,IAAiB,kBAAA,GAAA,EAAA,UAAG,GAAY,CAAA,GAGlC,kBAAC,GAAD;EACE,OAAO,EACL,mCACA,wCACD;EACD,aAAa,EACX,yCACA,yEACD;EACD,CAAA"}
1
+ {"version":3,"file":"FeatureFlaggedRoute.js","names":[],"sources":["../../../src/devportal/components/FeatureFlaggedRoute.tsx"],"sourcesContent":["/**\n * FeatureFlaggedRoute\n *\n * Wraps a route's lazy-loaded element with a feature flag gate.\n * When the flag is disabled the user sees a friendly \"feature unavailable\"\n * message; otherwise the wrapped page renders.\n *\n * Default-allow: if the flag service is unreachable or returns nothing,\n * the FeatureFlagProvider's `defaultEnabled` setting controls behaviour\n * (currently `true` — see `DevportalRoot.tsx`).\n *\n * Per `dev/platform/context/commercial/feature-flags`.\n */\nimport type { FC, ReactNode } from \"react\";\nimport { useFeatureFlag } from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { EmptyState } from \"./EmptyState\";\n\nexport interface FeatureFlaggedRouteProps {\n flag: string;\n children: ReactNode;\n /** Optional override message; defaults to translated \"coming soon\" copy. */\n fallback?: ReactNode;\n}\n\n/**\n * Safely evaluate a feature flag — `useFeatureFlag` itself throws if no\n * `FeatureFlagProvider` is mounted (standalone dev mode). We always call\n * the hook (rules-of-hooks) and rely on the underlying provider's\n * `defaultEnabled` to default-allow.\n */\nconst useFeatureFlagSafe = (flag: string): boolean => {\n try {\n return useFeatureFlag(flag);\n } catch {\n return true;\n }\n};\n\nconst useI18nSafe = (): {\n t: (key: string, fallback?: string) => string;\n} => {\n try {\n const ctx = useI18n();\n return { t: (key, fallback) => ctx.t(key, fallback) };\n } catch {\n return { t: (key, fallback) => fallback ?? key };\n }\n};\n\nexport const FeatureFlaggedRoute: FC<FeatureFlaggedRouteProps> = ({\n flag,\n children,\n fallback,\n}) => {\n const enabled = useFeatureFlagSafe(flag);\n const { t } = useI18nSafe();\n\n if (enabled) return <>{children}</>;\n if (fallback) return <>{fallback}</>;\n\n return (\n <EmptyState\n title={t(\n \"devportal.featureDisabled.title\",\n \"This feature is currently unavailable\",\n )}\n description={t(\n \"devportal.featureDisabled.description\",\n \"Your administrator has disabled this section. Please check back later.\",\n )}\n />\n );\n};\n"],"mappings":";;;;;AA+BA,IAAM,KAAsB,MAA0B;AACpD,KAAI;AACF,SAAO,EAAe,EAAK;SACrB;AACN,SAAO;;GAIL,UAED;AACH,KAAI;EACF,IAAM,IAAM,GAAS;AACrB,SAAO,EAAE,IAAI,GAAK,MAAa,EAAI,EAAE,GAAK,EAAS,EAAE;SAC/C;AACN,SAAO,EAAE,IAAI,GAAK,MAAa,KAAY,GAAK;;GAIvC,KAAqD,EAChE,SACA,aACA,kBACI;CACJ,IAAM,IAAU,EAAmB,EAAK,EAClC,EAAE,SAAM,GAAa;AAK3B,QAHI,IAAgB,kBAAA,GAAA,EAAG,aAAY,CAAA,GAC/B,IAAiB,kBAAA,GAAA,EAAA,UAAG,GAAY,CAAA,GAGlC,kBAAC,GAAD;EACE,OAAO,EACL,mCACA,wCACD;EACD,aAAa,EACX,yCACA,yEACD;EACD,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-devportal",
3
- "version": "2026.921.2",
3
+ "version": "2026.1013.1",
4
4
  "description": "Burdenoff Developer Portal Microfrontend - Complete developer operations interface",
5
5
  "type": "module",
6
6
  "files": [