@burdenoff/microfe-adaptercloud 2026.716.1 → 2026.720.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 (48) hide show
  1. package/dist/adaptercloud/AdapterCloudRoot.js.map +1 -1
  2. package/dist/adaptercloud/AdapterCloudRoutes.js.map +1 -1
  3. package/dist/adaptercloud/components/ConfirmDialog.js.map +1 -1
  4. package/dist/adaptercloud/components/DataState.js.map +1 -1
  5. package/dist/adaptercloud/components/EmptyState.js.map +1 -1
  6. package/dist/adaptercloud/components/MetricsCard.js.map +1 -1
  7. package/dist/adaptercloud/components/PageLayout.js.map +1 -1
  8. package/dist/adaptercloud/components/SeverityBadge.js.map +1 -1
  9. package/dist/adaptercloud/components/StatusBadge.js.map +1 -1
  10. package/dist/adaptercloud/components/viz/BarChart.js.map +1 -1
  11. package/dist/adaptercloud/components/viz/Sparkline.js.map +1 -1
  12. package/dist/adaptercloud/components/viz/TopologyGraph.js +5 -5
  13. package/dist/adaptercloud/components/viz/TopologyGraph.js.map +1 -1
  14. package/dist/adaptercloud/context/AdapterCloudContext.js.map +1 -1
  15. package/dist/adaptercloud/hooks/useAdapterCloudApi.d.ts.map +1 -1
  16. package/dist/adaptercloud/hooks/useAdapterCloudApi.js +8 -4
  17. package/dist/adaptercloud/hooks/useAdapterCloudApi.js.map +1 -1
  18. package/dist/adaptercloud/lib/toast.js.map +1 -1
  19. package/dist/adaptercloud/pages/OverviewPage.js.map +1 -1
  20. package/dist/adaptercloud/pages/adapters/AdapterDetailPage.js.map +1 -1
  21. package/dist/adaptercloud/pages/adapters/AdapterFormPage.js.map +1 -1
  22. package/dist/adaptercloud/pages/adapters/AdaptersListPage.js.map +1 -1
  23. package/dist/adaptercloud/pages/connections/ConnectionDetailPage.js.map +1 -1
  24. package/dist/adaptercloud/pages/connections/ConnectionFormPage.js.map +1 -1
  25. package/dist/adaptercloud/pages/connections/ConnectionsListPage.js.map +1 -1
  26. package/dist/adaptercloud/pages/costs/CostsPage.js.map +1 -1
  27. package/dist/adaptercloud/pages/drift/DriftListPage.js.map +1 -1
  28. package/dist/adaptercloud/pages/policies/PoliciesListPage.js.map +1 -1
  29. package/dist/adaptercloud/pages/policies/PolicyDetailPage.js.map +1 -1
  30. package/dist/adaptercloud/pages/policies/PolicyFormPage.js.map +1 -1
  31. package/dist/adaptercloud/pages/resources/ResourceDetailPage.js.map +1 -1
  32. package/dist/adaptercloud/pages/resources/ResourcesListPage.js.map +1 -1
  33. package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.js.map +1 -1
  34. package/dist/adaptercloud/pages/topology/TopologyPage.js.map +1 -1
  35. package/dist/adaptercloud/pages/violations/ViolationsListPage.js.map +1 -1
  36. package/dist/adaptercloud/store/adaptercloudStore.js.map +1 -1
  37. package/dist/adaptercloud/types/index.d.ts +4 -0
  38. package/dist/adaptercloud/types/index.d.ts.map +1 -1
  39. package/dist/adaptercloud/utils/cn.js.map +1 -1
  40. package/dist/adaptercloud/utils/domain.js.map +1 -1
  41. package/dist/adaptercloud/utils/formatters.js.map +1 -1
  42. package/dist/adaptercloud/utils/navigation.js.map +1 -1
  43. package/dist/node_modules/clsx/dist/clsx.js.map +1 -1
  44. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1 -1
  45. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -1
  46. package/dist/services/createSandboxAssistantTransport.js.map +1 -1
  47. package/dist/utils/pageContext.js.map +1 -1
  48. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"TopologyPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/topology/TopologyPage.tsx"],"sourcesContent":["/**\n * Estate Topology Page\n * @module adaptercloud/pages/topology\n *\n * The estate-wide dependency graph — every discovered resource laid out in one\n * live node-link map, grouped into human \"zones\" (Public Cloud, Kubernetes,\n * Edge / IoT, Data Systems, Network) and wired together by the topology edges\n * (`adaListTopologyEdges`). Selecting a node opens an inspector with its\n * dependency count and downstream blast-radius. All data is live from the\n * deployed `wspace-adaptercloud-svc` subgraph — nodes from `adaListResources`,\n * edges from `adaListTopologyEdges`. No mocks.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Waypoints,\n Search,\n X,\n RefreshCw,\n ArrowRight,\n Layers,\n Boxes,\n GitBranch,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useResources, useTopology } from '../../hooks/useAdapterCloudApi';\nimport { resourceStateLabels, humanizeEnum } from '../../utils/domain';\nimport { TopologyGraph, type TopologyNode, type TopologyEdge } from '../../components/viz';\nimport type { AdaEdgeKind, AdaResourceState } from '../../types';\n\n/** Canonical edge kinds — drives the legend so it stays in sync with the enum. */\nconst EDGE_KINDS: AdaEdgeKind[] = [\n 'DEPENDS_ON',\n 'CONNECTS_TO',\n 'ROUTES_TO',\n 'REPLICATES_TO',\n 'CONTAINS',\n];\n\n/**\n * Derive a human \"zone\" (graph column) for a resource from its type prefix,\n * falling back to the connection name. Data stores route to \"Data Systems\" even\n * when they carry a cloud prefix, matching how operators think about the estate.\n */\nfunction zoneFor(resourceType: string, connectionName?: string | null): string {\n const t = resourceType.toLowerCase();\n\n // Kubernetes clusters/workloads\n if (/^(gke|k8s|kubernetes|eks|aks)\\./.test(t)) return 'Kubernetes';\n // Edge / IoT devices and gateways\n if (/^(iot|edge)\\./.test(t)) return 'Edge / IoT';\n // Data systems — warehouses, databases, object storage\n if (\n /^snowflake\\./.test(t) ||\n /\\.(db|rds|postgres|mysql|redshift|bigquery|dynamodb|s3|bucket|storage)\\b/.test(t) ||\n t.endsWith('.db')\n ) {\n return 'Data Systems';\n }\n // Network fabric — CDNs, VPCs, routers\n if (t.endsWith('.network') || /^cloudflare\\./.test(t) || /\\.(vpc|cdn)\\b/.test(t)) {\n return 'Network';\n }\n // Public cloud compute/etc.\n if (/^(aws|azure|gcp|oci|alicloud)\\./.test(t)) return 'Public Cloud';\n\n // Fallback: infer from the connection name\n const c = (connectionName ?? '').toLowerCase();\n if (c) {\n if (/gke|k8s|kube/.test(c)) return 'Kubernetes';\n if (/iot|edge/.test(c)) return 'Edge / IoT';\n if (/snowflake|warehouse|postgres|database|\\bdb\\b/.test(c)) return 'Data Systems';\n if (/cloudflare|network|vpc|cdn/.test(c)) return 'Network';\n if (/aws|azure|gcp|cloud/.test(c)) return 'Public Cloud';\n }\n return 'Other';\n}\n\nexport function TopologyPage() {\n const { navigateTo } = useAdapterCloud();\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const resourcesQuery = useResources({ pagination: { limit: 100 } });\n const topologyQuery = useTopology();\n\n const [search, setSearch] = useState('');\n const [kindFilter, setKindFilter] = useState<AdaEdgeKind | ''>('');\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n const resources = useMemo(() => resourcesQuery.data?.items ?? [], [resourcesQuery.data]);\n const topoEdges = useMemo(() => topologyQuery.data ?? [], [topologyQuery.data]);\n\n // ---- Build the node set from resources -----------------------------------\n const allNodes: TopologyNode[] = useMemo(\n () =>\n resources.map((r) => ({\n id: r.id,\n label: r.name,\n type: r.resourceType,\n state: r.state,\n group: zoneFor(r.resourceType, r.connection?.name),\n })),\n [resources]\n );\n\n const nodeIds = useMemo(() => new Set(allNodes.map((n) => n.id)), [allNodes]);\n const stateById = useMemo(\n () => new Map(resources.map((r) => [r.id, r.state] as const)),\n [resources]\n );\n const nodeById = useMemo(() => new Map(allNodes.map((n) => [n.id, n] as const)), [allNodes]);\n\n // ---- Build edges — only where BOTH endpoints are in the node set ---------\n const allEdges: TopologyEdge[] = useMemo(\n () =>\n topoEdges\n .filter((e) => nodeIds.has(e.fromResourceId) && nodeIds.has(e.toResourceId))\n .map((e) => ({\n id: e.id,\n from: e.fromResourceId,\n to: e.toResourceId,\n kind: e.kind,\n drifted:\n stateById.get(e.fromResourceId) === 'DRIFTED' ||\n stateById.get(e.toResourceId) === 'DRIFTED',\n })),\n [topoEdges, nodeIds, stateById]\n );\n\n // Forward adjacency for inspector metrics (dependencies + blast radius).\n const outAdj = useMemo(() => {\n const adj = new Map<string, string[]>();\n for (const e of allEdges) {\n const list = adj.get(e.from) ?? [];\n list.push(e.to);\n adj.set(e.from, list);\n }\n return adj;\n }, [allEdges]);\n\n // ---- Search + edge-kind filtering (what the graph actually renders) ------\n const q = search.trim().toLowerCase();\n const displayNodes = useMemo(() => {\n if (!q) return allNodes;\n return allNodes.filter(\n (n) => n.label.toLowerCase().includes(q) || (n.type ?? '').toLowerCase().includes(q)\n );\n }, [allNodes, q]);\n\n const displayNodeIds = useMemo(() => new Set(displayNodes.map((n) => n.id)), [displayNodes]);\n\n const displayEdges = useMemo(\n () =>\n allEdges.filter(\n (e) =>\n displayNodeIds.has(e.from) &&\n displayNodeIds.has(e.to) &&\n (kindFilter === '' || e.kind === kindFilter)\n ),\n [allEdges, displayNodeIds, kindFilter]\n );\n\n // Count edges by kind for the legend badges.\n const kindCounts = useMemo(() => {\n const counts: Record<string, number> = {};\n for (const e of allEdges) counts[e.kind ?? ''] = (counts[e.kind ?? ''] ?? 0) + 1;\n return counts;\n }, [allEdges]);\n\n // ---- Inspector metrics for the selected node -----------------------------\n const inspector = useMemo(() => {\n if (!selectedId) return null;\n const node = nodeById.get(selectedId);\n if (!node) return null;\n\n const dependencies = outAdj.get(selectedId)?.length ?? 0;\n\n // Blast radius = every resource transitively reachable downstream.\n const seen = new Set<string>();\n const stack = [...(outAdj.get(selectedId) ?? [])];\n while (stack.length) {\n const cur = stack.pop();\n if (cur === undefined || cur === selectedId || seen.has(cur)) continue;\n seen.add(cur);\n for (const next of outAdj.get(cur) ?? []) stack.push(next);\n }\n\n return { node, dependencies, blastRadius: seen.size };\n }, [selectedId, nodeById, outAdj]);\n\n const zoneCount = useMemo(() => new Set(allNodes.map((n) => n.group)).size, [allNodes]);\n\n const onSelect = useCallback((id: string) => {\n setSelectedId((prev) => (prev === id ? null : id));\n }, []);\n\n const isLoading = resourcesQuery.isLoading || topologyQuery.isLoading;\n const isError = resourcesQuery.isError || topologyQuery.isError;\n\n const refetchAll = useCallback(() => {\n void resourcesQuery.refetch();\n void topologyQuery.refetch();\n }, [resourcesQuery, topologyQuery]);\n\n return (\n <PageLayout\n title={t('adaptercloud.topology.title', 'Estate Topology')}\n description={t(\n 'adaptercloud.topology.subtitle',\n 'A live dependency map of your entire infrastructure — every system in one graph.'\n )}\n actions={\n <button\n type=\"button\"\n onClick={refetchAll}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n <RefreshCw className=\"h-4 w-4\" />\n {t('adaptercloud.common.refresh', 'Refresh')}\n </button>\n }\n >\n {/* Toolbar — search + edge-kind filter + estate counts */}\n <div className=\"mb-6 flex flex-wrap items-center gap-3\">\n <div className=\"relative w-full sm:w-64\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n aria-label={t('adaptercloud.topology.searchNodes', 'Search nodes')}\n placeholder={t('adaptercloud.topology.searchPlaceholder', 'Search nodes…')}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 pl-9 pr-9 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {search && (\n <button\n type=\"button\"\n onClick={() => setSearch('')}\n aria-label={t('adaptercloud.topology.clearSearch', 'Clear search')}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-text-secondary transition-colors hover:text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n <select\n value={kindFilter}\n onChange={(e) => setKindFilter(e.target.value as AdaEdgeKind | '')}\n aria-label={t('adaptercloud.topology.filterByKind', 'Filter by edge kind')}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] sm:w-auto\"\n >\n <option value=\"\">{t('adaptercloud.topology.allKinds', 'All edge kinds')}</option>\n {EDGE_KINDS.map((k) => (\n <option key={k} value={k}>\n {humanizeEnum(k)}\n </option>\n ))}\n </select>\n\n {!isLoading && !isError && allNodes.length > 0 && (\n <div className=\"ml-auto flex flex-wrap items-center gap-4 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center gap-1.5\">\n <Boxes className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">\n {allNodes.length}\n </span>{' '}\n {t('adaptercloud.topology.nodes', 'nodes')}\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <GitBranch className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">\n {allEdges.length}\n </span>{' '}\n {t('adaptercloud.topology.edges', 'edges')}\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <Layers className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">{zoneCount}</span>{' '}\n {t('adaptercloud.topology.zones', 'zones')}\n </span>\n </div>\n )}\n </div>\n\n <DataState\n isLoading={isLoading}\n isError={isError}\n isEmpty={allNodes.length === 0}\n error={resourcesQuery.error ?? topologyQuery.error}\n onRetry={refetchAll}\n emptyTitle={t('adaptercloud.topology.emptyTitle', 'No topology yet')}\n emptyDescription={t(\n 'adaptercloud.topology.emptyDescription',\n 'No topology yet — register resources and their dependencies to see them mapped here.'\n )}\n emptyIcon={<Waypoints className=\"h-10 w-10\" />}\n emptyAction={\n <button\n type=\"button\"\n onClick={() => navigateTo('/resources')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n {t('adaptercloud.topology.goToResources', 'Go to resources')}\n </button>\n }\n >\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,1fr)_20rem]\">\n {/* Graph + legend */}\n <div className=\"min-w-0 space-y-4\">\n {allEdges.length === 0 && (\n <p className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 px-4 py-3 text-sm text-text-secondary\">\n {t(\n 'adaptercloud.topology.noEdges',\n 'No dependency edges recorded yet — nodes are shown grouped by zone. Add dependencies from a resource to connect the graph.'\n )}\n </p>\n )}\n\n {displayNodes.length > 0 ? (\n <TopologyGraph\n nodes={displayNodes}\n edges={displayEdges}\n selectedId={selectedId}\n onSelect={onSelect}\n />\n ) : (\n <div className=\"flex min-h-[200px] flex-col items-center justify-center gap-2 rounded-xl border border-border-subtle bg-bg-surface p-8 text-center\">\n <Search className=\"h-8 w-8 text-text-secondary\" />\n <p className=\"text-sm text-text-secondary\">\n {t('adaptercloud.topology.noMatches', 'No nodes match your search.')}\n </p>\n </div>\n )}\n\n {/* Edge-kinds legend */}\n <GlassCard className=\"p-4\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.topology.legend', 'Legend')}\n </h3>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n {/* Edge signals (how the graph paints edges) */}\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {t('adaptercloud.topology.edgeSignals', 'Edge signals')}\n </p>\n <ul className=\"space-y-1.5 text-xs text-text-secondary\">\n <li className=\"flex items-center gap-2\">\n <span className=\"h-0.5 w-6 shrink-0 rounded bg-border-strong\" aria-hidden />\n {t('adaptercloud.topology.dependency', 'Dependency')}\n </li>\n <li className=\"flex items-center gap-2\">\n <span className=\"h-0.5 w-6 shrink-0 rounded bg-accent-blue\" aria-hidden />\n {t('adaptercloud.topology.selectedPath', 'Selected node path')}\n </li>\n <li className=\"flex items-center gap-2\">\n <span\n className=\"h-0.5 w-6 shrink-0 rounded bg-status-warning-text\"\n aria-hidden\n />\n {t('adaptercloud.topology.drift', 'Drift (endpoint drifted)')}\n </li>\n </ul>\n </div>\n\n {/* Edge kinds (semantic relationship types) */}\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {t('adaptercloud.topology.edgeKinds', 'Edge kinds')}\n </p>\n <ul className=\"flex flex-wrap gap-1.5\">\n {EDGE_KINDS.map((k) => (\n <li key={k}>\n <span className=\"inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\">\n {humanizeEnum(k)}\n <span className=\"tabular-nums font-medium text-text-primary\">\n {kindCounts[k] ?? 0}\n </span>\n </span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n </GlassCard>\n </div>\n\n {/* Inspector */}\n <aside className=\"lg:sticky lg:top-6 lg:h-fit\">\n <GlassCard className=\"p-5\">\n {inspector ? (\n <div className=\"space-y-5\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-center gap-2.5\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-bg-sunken\">\n <Waypoints className=\"h-4.5 w-4.5 text-accent-blue\" />\n </span>\n <div className=\"min-w-0\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">\n {inspector.node.label}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t('adaptercloud.topology.inspector', 'Inspector')}\n </p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => setSelectedId(null)}\n aria-label={t('adaptercloud.topology.closeInspector', 'Close inspector')}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-accent hover:text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n <dl className=\"space-y-3 text-sm\">\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.type', 'Type')}\n </dt>\n <dd className=\"truncate font-mono text-xs text-text-primary\">\n {inspector.node.type ?? '—'}\n </dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.zone', 'Zone')}\n </dt>\n <dd className=\"text-text-primary\">{inspector.node.group}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.state', 'State')}\n </dt>\n <dd>\n <StatusBadge\n status={inspector.node.state ?? ''}\n label={\n inspector.node.state\n ? resourceStateLabels[inspector.node.state as AdaResourceState]\n : undefined\n }\n />\n </dd>\n </div>\n </dl>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 p-3\">\n <p className=\"text-2xl font-bold tabular-nums text-text-primary\">\n {inspector.dependencies}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {t('adaptercloud.topology.dependencies', 'Dependencies')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 p-3\">\n <p className=\"text-2xl font-bold tabular-nums text-text-primary\">\n {inspector.blastRadius}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {t('adaptercloud.topology.blastRadius', 'Blast radius')}\n </p>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources/${inspector.node.id}`)}\n className=\"inline-flex w-full items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n {t('adaptercloud.topology.viewResource', 'View resource')}\n <ArrowRight className=\"h-4 w-4\" />\n </button>\n </div>\n ) : (\n <div className=\"flex flex-col items-center gap-3 py-8 text-center\">\n <span className=\"flex h-11 w-11 items-center justify-center rounded-full bg-bg-sunken\">\n <Waypoints className=\"h-5 w-5 text-text-secondary\" />\n </span>\n <p className=\"text-sm font-medium text-text-primary\">\n {t('adaptercloud.topology.inspectorTitle', 'Inspector')}\n </p>\n <p className=\"max-w-[16rem] text-xs text-text-secondary\">\n {t(\n 'adaptercloud.topology.inspectorHint',\n 'Select any node in the graph to see its type, state, dependencies and downstream blast radius.'\n )}\n </p>\n </div>\n )}\n </GlassCard>\n </aside>\n </div>\n </DataState>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TopologyPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/topology/TopologyPage.tsx"],"sourcesContent":["/**\n * Estate Topology Page\n * @module adaptercloud/pages/topology\n *\n * The estate-wide dependency graph — every discovered resource laid out in one\n * live node-link map, grouped into human \"zones\" (Public Cloud, Kubernetes,\n * Edge / IoT, Data Systems, Network) and wired together by the topology edges\n * (`adaListTopologyEdges`). Selecting a node opens an inspector with its\n * dependency count and downstream blast-radius. All data is live from the\n * deployed `wspace-adaptercloud-svc` subgraph — nodes from `adaListResources`,\n * edges from `adaListTopologyEdges`. No mocks.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Waypoints,\n Search,\n X,\n RefreshCw,\n ArrowRight,\n Layers,\n Boxes,\n GitBranch,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useResources, useTopology } from '../../hooks/useAdapterCloudApi';\nimport { resourceStateLabels, humanizeEnum } from '../../utils/domain';\nimport { TopologyGraph, type TopologyNode, type TopologyEdge } from '../../components/viz';\nimport type { AdaEdgeKind, AdaResourceState } from '../../types';\n\n/** Canonical edge kinds — drives the legend so it stays in sync with the enum. */\nconst EDGE_KINDS: AdaEdgeKind[] = [\n 'DEPENDS_ON',\n 'CONNECTS_TO',\n 'ROUTES_TO',\n 'REPLICATES_TO',\n 'CONTAINS',\n];\n\n/**\n * Derive a human \"zone\" (graph column) for a resource from its type prefix,\n * falling back to the connection name. Data stores route to \"Data Systems\" even\n * when they carry a cloud prefix, matching how operators think about the estate.\n */\nfunction zoneFor(resourceType: string, connectionName?: string | null): string {\n const t = resourceType.toLowerCase();\n\n // Kubernetes clusters/workloads\n if (/^(gke|k8s|kubernetes|eks|aks)\\./.test(t)) return 'Kubernetes';\n // Edge / IoT devices and gateways\n if (/^(iot|edge)\\./.test(t)) return 'Edge / IoT';\n // Data systems — warehouses, databases, object storage\n if (\n /^snowflake\\./.test(t) ||\n /\\.(db|rds|postgres|mysql|redshift|bigquery|dynamodb|s3|bucket|storage)\\b/.test(t) ||\n t.endsWith('.db')\n ) {\n return 'Data Systems';\n }\n // Network fabric — CDNs, VPCs, routers\n if (t.endsWith('.network') || /^cloudflare\\./.test(t) || /\\.(vpc|cdn)\\b/.test(t)) {\n return 'Network';\n }\n // Public cloud compute/etc.\n if (/^(aws|azure|gcp|oci|alicloud)\\./.test(t)) return 'Public Cloud';\n\n // Fallback: infer from the connection name\n const c = (connectionName ?? '').toLowerCase();\n if (c) {\n if (/gke|k8s|kube/.test(c)) return 'Kubernetes';\n if (/iot|edge/.test(c)) return 'Edge / IoT';\n if (/snowflake|warehouse|postgres|database|\\bdb\\b/.test(c)) return 'Data Systems';\n if (/cloudflare|network|vpc|cdn/.test(c)) return 'Network';\n if (/aws|azure|gcp|cloud/.test(c)) return 'Public Cloud';\n }\n return 'Other';\n}\n\nexport function TopologyPage() {\n const { navigateTo } = useAdapterCloud();\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const resourcesQuery = useResources({ pagination: { limit: 100 } });\n const topologyQuery = useTopology();\n\n const [search, setSearch] = useState('');\n const [kindFilter, setKindFilter] = useState<AdaEdgeKind | ''>('');\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n const resources = useMemo(() => resourcesQuery.data?.items ?? [], [resourcesQuery.data]);\n const topoEdges = useMemo(() => topologyQuery.data ?? [], [topologyQuery.data]);\n\n // ---- Build the node set from resources -----------------------------------\n const allNodes: TopologyNode[] = useMemo(\n () =>\n resources.map((r) => ({\n id: r.id,\n label: r.name,\n type: r.resourceType,\n state: r.state,\n group: zoneFor(r.resourceType, r.connection?.name),\n })),\n [resources]\n );\n\n const nodeIds = useMemo(() => new Set(allNodes.map((n) => n.id)), [allNodes]);\n const stateById = useMemo(\n () => new Map(resources.map((r) => [r.id, r.state] as const)),\n [resources]\n );\n const nodeById = useMemo(() => new Map(allNodes.map((n) => [n.id, n] as const)), [allNodes]);\n\n // ---- Build edges — only where BOTH endpoints are in the node set ---------\n const allEdges: TopologyEdge[] = useMemo(\n () =>\n topoEdges\n .filter((e) => nodeIds.has(e.fromResourceId) && nodeIds.has(e.toResourceId))\n .map((e) => ({\n id: e.id,\n from: e.fromResourceId,\n to: e.toResourceId,\n kind: e.kind,\n drifted:\n stateById.get(e.fromResourceId) === 'DRIFTED' ||\n stateById.get(e.toResourceId) === 'DRIFTED',\n })),\n [topoEdges, nodeIds, stateById]\n );\n\n // Forward adjacency for inspector metrics (dependencies + blast radius).\n const outAdj = useMemo(() => {\n const adj = new Map<string, string[]>();\n for (const e of allEdges) {\n const list = adj.get(e.from) ?? [];\n list.push(e.to);\n adj.set(e.from, list);\n }\n return adj;\n }, [allEdges]);\n\n // ---- Search + edge-kind filtering (what the graph actually renders) ------\n const q = search.trim().toLowerCase();\n const displayNodes = useMemo(() => {\n if (!q) return allNodes;\n return allNodes.filter(\n (n) => n.label.toLowerCase().includes(q) || (n.type ?? '').toLowerCase().includes(q)\n );\n }, [allNodes, q]);\n\n const displayNodeIds = useMemo(() => new Set(displayNodes.map((n) => n.id)), [displayNodes]);\n\n const displayEdges = useMemo(\n () =>\n allEdges.filter(\n (e) =>\n displayNodeIds.has(e.from) &&\n displayNodeIds.has(e.to) &&\n (kindFilter === '' || e.kind === kindFilter)\n ),\n [allEdges, displayNodeIds, kindFilter]\n );\n\n // Count edges by kind for the legend badges.\n const kindCounts = useMemo(() => {\n const counts: Record<string, number> = {};\n for (const e of allEdges) counts[e.kind ?? ''] = (counts[e.kind ?? ''] ?? 0) + 1;\n return counts;\n }, [allEdges]);\n\n // ---- Inspector metrics for the selected node -----------------------------\n const inspector = useMemo(() => {\n if (!selectedId) return null;\n const node = nodeById.get(selectedId);\n if (!node) return null;\n\n const dependencies = outAdj.get(selectedId)?.length ?? 0;\n\n // Blast radius = every resource transitively reachable downstream.\n const seen = new Set<string>();\n const stack = [...(outAdj.get(selectedId) ?? [])];\n while (stack.length) {\n const cur = stack.pop();\n if (cur === undefined || cur === selectedId || seen.has(cur)) continue;\n seen.add(cur);\n for (const next of outAdj.get(cur) ?? []) stack.push(next);\n }\n\n return { node, dependencies, blastRadius: seen.size };\n }, [selectedId, nodeById, outAdj]);\n\n const zoneCount = useMemo(() => new Set(allNodes.map((n) => n.group)).size, [allNodes]);\n\n const onSelect = useCallback((id: string) => {\n setSelectedId((prev) => (prev === id ? null : id));\n }, []);\n\n const isLoading = resourcesQuery.isLoading || topologyQuery.isLoading;\n const isError = resourcesQuery.isError || topologyQuery.isError;\n\n const refetchAll = useCallback(() => {\n void resourcesQuery.refetch();\n void topologyQuery.refetch();\n }, [resourcesQuery, topologyQuery]);\n\n return (\n <PageLayout\n title={t('adaptercloud.topology.title', 'Estate Topology')}\n description={t(\n 'adaptercloud.topology.subtitle',\n 'A live dependency map of your entire infrastructure — every system in one graph.'\n )}\n actions={\n <button\n type=\"button\"\n onClick={refetchAll}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n <RefreshCw className=\"h-4 w-4\" />\n {t('adaptercloud.common.refresh', 'Refresh')}\n </button>\n }\n >\n {/* Toolbar — search + edge-kind filter + estate counts */}\n <div className=\"mb-6 flex flex-wrap items-center gap-3\">\n <div className=\"relative w-full sm:w-64\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n aria-label={t('adaptercloud.topology.searchNodes', 'Search nodes')}\n placeholder={t('adaptercloud.topology.searchPlaceholder', 'Search nodes…')}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 pl-9 pr-9 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {search && (\n <button\n type=\"button\"\n onClick={() => setSearch('')}\n aria-label={t('adaptercloud.topology.clearSearch', 'Clear search')}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-text-secondary transition-colors hover:text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n <select\n value={kindFilter}\n onChange={(e) => setKindFilter(e.target.value as AdaEdgeKind | '')}\n aria-label={t('adaptercloud.topology.filterByKind', 'Filter by edge kind')}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] sm:w-auto\"\n >\n <option value=\"\">{t('adaptercloud.topology.allKinds', 'All edge kinds')}</option>\n {EDGE_KINDS.map((k) => (\n <option key={k} value={k}>\n {humanizeEnum(k)}\n </option>\n ))}\n </select>\n\n {!isLoading && !isError && allNodes.length > 0 && (\n <div className=\"ml-auto flex flex-wrap items-center gap-4 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center gap-1.5\">\n <Boxes className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">\n {allNodes.length}\n </span>{' '}\n {t('adaptercloud.topology.nodes', 'nodes')}\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <GitBranch className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">\n {allEdges.length}\n </span>{' '}\n {t('adaptercloud.topology.edges', 'edges')}\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <Layers className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">{zoneCount}</span>{' '}\n {t('adaptercloud.topology.zones', 'zones')}\n </span>\n </div>\n )}\n </div>\n\n <DataState\n isLoading={isLoading}\n isError={isError}\n isEmpty={allNodes.length === 0}\n error={resourcesQuery.error ?? topologyQuery.error}\n onRetry={refetchAll}\n emptyTitle={t('adaptercloud.topology.emptyTitle', 'No topology yet')}\n emptyDescription={t(\n 'adaptercloud.topology.emptyDescription',\n 'No topology yet — register resources and their dependencies to see them mapped here.'\n )}\n emptyIcon={<Waypoints className=\"h-10 w-10\" />}\n emptyAction={\n <button\n type=\"button\"\n onClick={() => navigateTo('/resources')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n {t('adaptercloud.topology.goToResources', 'Go to resources')}\n </button>\n }\n >\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,1fr)_20rem]\">\n {/* Graph + legend */}\n <div className=\"min-w-0 space-y-4\">\n {allEdges.length === 0 && (\n <p className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 px-4 py-3 text-sm text-text-secondary\">\n {t(\n 'adaptercloud.topology.noEdges',\n 'No dependency edges recorded yet — nodes are shown grouped by zone. Add dependencies from a resource to connect the graph.'\n )}\n </p>\n )}\n\n {displayNodes.length > 0 ? (\n <TopologyGraph\n nodes={displayNodes}\n edges={displayEdges}\n selectedId={selectedId}\n onSelect={onSelect}\n />\n ) : (\n <div className=\"flex min-h-[200px] flex-col items-center justify-center gap-2 rounded-xl border border-border-subtle bg-bg-surface p-8 text-center\">\n <Search className=\"h-8 w-8 text-text-secondary\" />\n <p className=\"text-sm text-text-secondary\">\n {t('adaptercloud.topology.noMatches', 'No nodes match your search.')}\n </p>\n </div>\n )}\n\n {/* Edge-kinds legend */}\n <GlassCard className=\"p-4\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.topology.legend', 'Legend')}\n </h3>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n {/* Edge signals (how the graph paints edges) */}\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {t('adaptercloud.topology.edgeSignals', 'Edge signals')}\n </p>\n <ul className=\"space-y-1.5 text-xs text-text-secondary\">\n <li className=\"flex items-center gap-2\">\n <span className=\"h-0.5 w-6 shrink-0 rounded bg-border-strong\" aria-hidden />\n {t('adaptercloud.topology.dependency', 'Dependency')}\n </li>\n <li className=\"flex items-center gap-2\">\n <span className=\"h-0.5 w-6 shrink-0 rounded bg-accent-blue\" aria-hidden />\n {t('adaptercloud.topology.selectedPath', 'Selected node path')}\n </li>\n <li className=\"flex items-center gap-2\">\n <span\n className=\"h-0.5 w-6 shrink-0 rounded bg-status-warning-text\"\n aria-hidden\n />\n {t('adaptercloud.topology.drift', 'Drift (endpoint drifted)')}\n </li>\n </ul>\n </div>\n\n {/* Edge kinds (semantic relationship types) */}\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {t('adaptercloud.topology.edgeKinds', 'Edge kinds')}\n </p>\n <ul className=\"flex flex-wrap gap-1.5\">\n {EDGE_KINDS.map((k) => (\n <li key={k}>\n <span className=\"inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\">\n {humanizeEnum(k)}\n <span className=\"tabular-nums font-medium text-text-primary\">\n {kindCounts[k] ?? 0}\n </span>\n </span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n </GlassCard>\n </div>\n\n {/* Inspector */}\n <aside className=\"lg:sticky lg:top-6 lg:h-fit\">\n <GlassCard className=\"p-5\">\n {inspector ? (\n <div className=\"space-y-5\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-center gap-2.5\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-bg-sunken\">\n <Waypoints className=\"h-4.5 w-4.5 text-accent-blue\" />\n </span>\n <div className=\"min-w-0\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">\n {inspector.node.label}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t('adaptercloud.topology.inspector', 'Inspector')}\n </p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => setSelectedId(null)}\n aria-label={t('adaptercloud.topology.closeInspector', 'Close inspector')}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-accent hover:text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n <dl className=\"space-y-3 text-sm\">\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.type', 'Type')}\n </dt>\n <dd className=\"truncate font-mono text-xs text-text-primary\">\n {inspector.node.type ?? '—'}\n </dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.zone', 'Zone')}\n </dt>\n <dd className=\"text-text-primary\">{inspector.node.group}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.state', 'State')}\n </dt>\n <dd>\n <StatusBadge\n status={inspector.node.state ?? ''}\n label={\n inspector.node.state\n ? resourceStateLabels[inspector.node.state as AdaResourceState]\n : undefined\n }\n />\n </dd>\n </div>\n </dl>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 p-3\">\n <p className=\"text-2xl font-bold tabular-nums text-text-primary\">\n {inspector.dependencies}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {t('adaptercloud.topology.dependencies', 'Dependencies')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 p-3\">\n <p className=\"text-2xl font-bold tabular-nums text-text-primary\">\n {inspector.blastRadius}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {t('adaptercloud.topology.blastRadius', 'Blast radius')}\n </p>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources/${inspector.node.id}`)}\n className=\"inline-flex w-full items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n {t('adaptercloud.topology.viewResource', 'View resource')}\n <ArrowRight className=\"h-4 w-4\" />\n </button>\n </div>\n ) : (\n <div className=\"flex flex-col items-center gap-3 py-8 text-center\">\n <span className=\"flex h-11 w-11 items-center justify-center rounded-full bg-bg-sunken\">\n <Waypoints className=\"h-5 w-5 text-text-secondary\" />\n </span>\n <p className=\"text-sm font-medium text-text-primary\">\n {t('adaptercloud.topology.inspectorTitle', 'Inspector')}\n </p>\n <p className=\"max-w-[16rem] text-xs text-text-secondary\">\n {t(\n 'adaptercloud.topology.inspectorHint',\n 'Select any node in the graph to see its type, state, dependencies and downstream blast radius.'\n )}\n </p>\n </div>\n )}\n </GlassCard>\n </aside>\n </div>\n </DataState>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ViolationsListPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/violations/ViolationsListPage.tsx"],"sourcesContent":["/**\n * Violations Queue Page\n * @module adaptercloud/pages/violations\n *\n * The governance work queue (`adaListViolations`). Filters by status (and by\n * policy/resource via URL params). Each open/acknowledged violation can be\n * transitioned via `adaResolveViolation` — acknowledge, resolve, or waive (a\n * waiver requires a reason, enforced both client-side and at the service).\n */\n\nimport { useState, useCallback } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n ShieldAlert,\n ChevronLeft,\n ChevronRight,\n ChevronDown,\n Check,\n CheckCheck,\n FileText,\n Loader2,\n} from 'lucide-react';\nimport {\n GlassCard,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { SeverityBadge } from '../../components/SeverityBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useViolations, useResolveViolation } from '../../hooks/useAdapterCloudApi';\nimport { violationStatusLabels, severityRank } from '../../utils/domain';\nimport { formatDate } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { AdaPolicyViolation, AdaViolationStatus } from '../../types';\n\n/** Segmented status tabs — All plus each `AdaViolationStatus`, in queue order. */\nconst STATUS_TABS: (AdaViolationStatus | '')[] = ['', 'OPEN', 'ACKNOWLEDGED', 'RESOLVED', 'WAIVED'];\n\nconst PAGE_SIZE = 20;\n\nexport function ViolationsListPage() {\n const { navigateTo } = useAdapterCloud();\n const [searchParams] = useSearchParams();\n const policyId = searchParams.get('policyId') ?? undefined;\n const resourceId = searchParams.get('resourceId') ?? undefined;\n\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const [status, setStatus] = useState<AdaViolationStatus | ''>('OPEN');\n const [offset, setOffset] = useState(0);\n const [waiveTarget, setWaiveTarget] = useState<AdaPolicyViolation | null>(null);\n const [waiverReason, setWaiverReason] = useState('');\n const [actionError, setActionError] = useState<string | null>(null);\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n\n const query = useViolations({\n policyId,\n resourceId,\n status: status || undefined,\n pagination: { limit: PAGE_SIZE, offset },\n });\n const resolve = useResolveViolation();\n\n // Live per-status counts for the segmented tabs. Each is a cheap `limit: 1`\n // query read for its `pageInfo.totalCount` (the estate-wide total for that\n // filter); \"All\" is the same query without a status. They respect the current\n // policy/resource URL scope so the badges match the visible queue.\n const countBase = { policyId, resourceId, pagination: { limit: 1, offset: 0 } };\n const allCount = useViolations(countBase);\n const openCount = useViolations({ ...countBase, status: 'OPEN' });\n const ackCount = useViolations({ ...countBase, status: 'ACKNOWLEDGED' });\n const resolvedCount = useViolations({ ...countBase, status: 'RESOLVED' });\n const waivedCount = useViolations({ ...countBase, status: 'WAIVED' });\n\n const tabCounts: Record<AdaViolationStatus | '', number | undefined> = {\n '': allCount.data?.pageInfo.totalCount ?? undefined,\n OPEN: openCount.data?.pageInfo.totalCount ?? undefined,\n ACKNOWLEDGED: ackCount.data?.pageInfo.totalCount ?? undefined,\n RESOLVED: resolvedCount.data?.pageInfo.totalCount ?? undefined,\n WAIVED: waivedCount.data?.pageInfo.totalCount ?? undefined,\n };\n\n const toggleEvidence = useCallback((id: string) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n }, []);\n\n // Severity ordering is applied ONLY within the current server page. The queue\n // pages by offset, so this does not globally reorder across pages — a page-2\n // CRITICAL still sorts below a page-1 LOW. Kept as a within-page readability\n // aid (the service has no severity sort arg to make it global).\n const items = [...(query.data?.items ?? [])].sort(\n (a, b) => severityRank[b.severity] - severityRank[a.severity]\n );\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n\n const onError = useCallback(\n (err: unknown) =>\n setActionError(err instanceof Error ? err.message : 'Action failed. Please try again.'),\n []\n );\n\n const transition = useCallback(\n (id: string, newStatus: AdaViolationStatus) => {\n setActionError(null);\n resolve.mutate({ id, status: newStatus }, { onError });\n },\n [resolve, onError]\n );\n\n const confirmWaive = useCallback(() => {\n if (!waiveTarget) return;\n if (!waiverReason.trim()) {\n setActionError(t('adaptercloud.violations.reasonRequired', 'A waiver requires a reason.'));\n return;\n }\n setActionError(null);\n resolve.mutate(\n { id: waiveTarget.id, status: 'WAIVED', waiverReason: waiverReason.trim() },\n {\n onSuccess: () => {\n setWaiveTarget(null);\n setWaiverReason('');\n },\n onError,\n }\n );\n }, [waiveTarget, waiverReason, resolve, onError, t]);\n\n return (\n <PageLayout\n title={t('adaptercloud.violations.title', 'Violations')}\n description={t(\n 'adaptercloud.violations.subtitle',\n 'Work the governance queue — acknowledge, resolve, or waive policy breaches.'\n )}\n >\n <div\n className=\"mb-6 flex flex-wrap items-center gap-2\"\n role=\"tablist\"\n aria-label={t('adaptercloud.violations.filterByStatus', 'Filter by status')}\n >\n {STATUS_TABS.map((tab) => {\n const active = status === tab;\n const count = tabCounts[tab];\n const label =\n tab === ''\n ? t('adaptercloud.violations.allStatuses', 'All')\n : violationStatusLabels[tab];\n return (\n <button\n key={tab || 'all'}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n onClick={() => {\n setStatus(tab);\n setOffset(0);\n }}\n className={cn(\n 'inline-flex items-center gap-2 rounded-full border px-3.5 py-1.5 text-sm font-medium transition-colors',\n active\n ? 'border-transparent bg-action-primary-bg text-action-primary-text'\n : 'border-border-subtle text-text-secondary hover:bg-accent'\n )}\n >\n {label}\n {count !== undefined && (\n <span\n className={cn(\n 'inline-flex min-w-5 items-center justify-center rounded-full px-1.5 text-xs font-semibold tabular-nums',\n active\n ? 'bg-action-primary-text/20 text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary'\n )}\n >\n {count}\n </span>\n )}\n </button>\n );\n })}\n {(policyId || resourceId) && (\n <button\n type=\"button\"\n onClick={() => navigateTo('/violations')}\n className=\"inline-flex items-center gap-1.5 rounded-full bg-accent-blue-subtle px-2.5 py-1 text-xs text-accent-blue hover:underline\"\n >\n {t('adaptercloud.violations.clearScope', 'Clear scope ×')}\n </button>\n )}\n </div>\n\n {actionError && (\n <p\n role=\"alert\"\n aria-live=\"polite\"\n className=\"mb-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\"\n >\n {actionError}\n </p>\n )}\n\n <DataState\n isLoading={query.isLoading}\n isError={query.isError}\n isEmpty={items.length === 0}\n error={query.error}\n onRetry={() => void query.refetch()}\n emptyTitle={t('adaptercloud.violations.emptyTitle', 'No violations')}\n emptyDescription={t(\n 'adaptercloud.violations.emptyDescription',\n 'Nothing matches this filter — your estate is clean here.'\n )}\n emptyIcon={<ShieldAlert className=\"h-10 w-10\" />}\n >\n <div className=\"space-y-3\">\n {items.map((v) => {\n const isOpen = v.status === 'OPEN' || v.status === 'ACKNOWLEDGED';\n return (\n <GlassCard key={v.id} className=\"p-5\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"mb-1.5 flex flex-wrap items-center gap-2\">\n <SeverityBadge severity={v.severity} />\n <StatusBadge status={v.status} />\n {v.policy && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/policies/${v.policyId}`)}\n className=\"text-xs font-medium text-accent-blue hover:underline\"\n >\n {v.policy.name}\n </button>\n )}\n </div>\n <p className=\"text-sm font-medium text-text-primary\">{v.message}</p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {t('adaptercloud.violations.detected', 'Detected')} {formatDate(v.detectedAt)}\n {' · '}\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources/${v.resourceId}`)}\n className=\"hover:underline\"\n >\n {t('adaptercloud.violations.viewResource', 'View resource')}\n </button>\n </p>\n {v.waiverReason && (\n <p className=\"mt-2 rounded-lg bg-bg-sunken px-3 py-1.5 text-xs text-text-secondary\">\n {t('adaptercloud.violations.waiver', 'Waiver')}: {v.waiverReason}\n </p>\n )}\n {v.evidence != null && (\n <div className=\"mt-2\">\n <button\n type=\"button\"\n onClick={() => toggleEvidence(v.id)}\n aria-expanded={expanded.has(v.id)}\n className=\"inline-flex items-center gap-1 text-xs font-medium text-text-secondary transition-colors hover:text-text-primary\"\n >\n {expanded.has(v.id) ? (\n <ChevronDown className=\"h-3.5 w-3.5\" />\n ) : (\n <ChevronRight className=\"h-3.5 w-3.5\" />\n )}\n {t('adaptercloud.violations.evidence', 'Evidence')}\n </button>\n {expanded.has(v.id) && (\n <pre className=\"mt-2 overflow-x-auto rounded-lg border border-border-subtle bg-bg-sunken p-3 font-mono text-xs text-text-secondary\">\n {JSON.stringify(v.evidence, null, 2)}\n </pre>\n )}\n </div>\n )}\n </div>\n\n {isOpen && (\n <div className=\"flex shrink-0 flex-wrap gap-2\">\n {v.status === 'OPEN' && (\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => transition(v.id, 'ACKNOWLEDGED')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-accent disabled:opacity-50\"\n >\n <Check className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.acknowledge', 'Acknowledge')}\n </button>\n )}\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => transition(v.id, 'RESOLVED')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-success-text transition-colors hover:bg-status-success-bg-subtle disabled:opacity-50\"\n >\n <CheckCheck className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.resolve', 'Resolve')}\n </button>\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => {\n setActionError(null);\n setWaiverReason('');\n setWaiveTarget(v);\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-secondary transition-colors hover:bg-accent disabled:opacity-50\"\n >\n <FileText className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.waive', 'Waive')}\n </button>\n </div>\n )}\n </div>\n </GlassCard>\n );\n })}\n </div>\n\n {(offset > 0 || hasMore) && (\n <div className=\"mt-6 flex items-center justify-between\">\n <button\n type=\"button\"\n disabled={offset === 0}\n onClick={() => setOffset((o) => Math.max(0, o - PAGE_SIZE))}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.prev', 'Previous')}\n </button>\n <span className=\"text-sm text-text-secondary\">\n {t('adaptercloud.common.showing', 'Showing')} {offset + 1}–{offset + items.length}\n </span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setOffset((o) => o + PAGE_SIZE)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {t('adaptercloud.common.next', 'Next')}\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </DataState>\n\n {/* Waive dialog */}\n <ResponsiveDialog\n open={Boolean(waiveTarget)}\n onOpenChange={(open) => {\n if (!open) setWaiveTarget(null);\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {t('adaptercloud.violations.waiveTitle', 'Waive violation')}\n </ResponsiveDialogTitle>\n </ResponsiveDialogHeader>\n <div className=\"px-1 py-2\">\n <label htmlFor=\"ada-waiver-reason\" className=\"mb-1.5 block text-sm text-text-secondary\">\n {t(\n 'adaptercloud.violations.waivePrompt',\n 'A waiver requires a documented reason and is recorded on the violation.'\n )}\n </label>\n <textarea\n id=\"ada-waiver-reason\"\n value={waiverReason}\n onChange={(e) => setWaiverReason(e.target.value)}\n rows={4}\n autoFocus\n aria-label={t('adaptercloud.violations.waiverReason', 'Waiver reason')}\n placeholder={t(\n 'adaptercloud.violations.waiveReasonPlaceholder',\n 'Why is this acceptable?'\n )}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {actionError && (\n <p role=\"alert\" aria-live=\"polite\" className=\"mt-2 text-sm text-status-error-text\">\n {actionError}\n </p>\n )}\n </div>\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n onClick={() => setWaiveTarget(null)}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n {t('adaptercloud.common.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={confirmWaive}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90 disabled:opacity-50\"\n >\n {resolve.isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {t('adaptercloud.violations.confirmWaive', 'Waive')}\n </button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ViolationsListPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/violations/ViolationsListPage.tsx"],"sourcesContent":["/**\n * Violations Queue Page\n * @module adaptercloud/pages/violations\n *\n * The governance work queue (`adaListViolations`). Filters by status (and by\n * policy/resource via URL params). Each open/acknowledged violation can be\n * transitioned via `adaResolveViolation` — acknowledge, resolve, or waive (a\n * waiver requires a reason, enforced both client-side and at the service).\n */\n\nimport { useState, useCallback } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n ShieldAlert,\n ChevronLeft,\n ChevronRight,\n ChevronDown,\n Check,\n CheckCheck,\n FileText,\n Loader2,\n} from 'lucide-react';\nimport {\n GlassCard,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { SeverityBadge } from '../../components/SeverityBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useViolations, useResolveViolation } from '../../hooks/useAdapterCloudApi';\nimport { violationStatusLabels, severityRank } from '../../utils/domain';\nimport { formatDate } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { AdaPolicyViolation, AdaViolationStatus } from '../../types';\n\n/** Segmented status tabs — All plus each `AdaViolationStatus`, in queue order. */\nconst STATUS_TABS: (AdaViolationStatus | '')[] = ['', 'OPEN', 'ACKNOWLEDGED', 'RESOLVED', 'WAIVED'];\n\nconst PAGE_SIZE = 20;\n\nexport function ViolationsListPage() {\n const { navigateTo } = useAdapterCloud();\n const [searchParams] = useSearchParams();\n const policyId = searchParams.get('policyId') ?? undefined;\n const resourceId = searchParams.get('resourceId') ?? undefined;\n\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const [status, setStatus] = useState<AdaViolationStatus | ''>('OPEN');\n const [offset, setOffset] = useState(0);\n const [waiveTarget, setWaiveTarget] = useState<AdaPolicyViolation | null>(null);\n const [waiverReason, setWaiverReason] = useState('');\n const [actionError, setActionError] = useState<string | null>(null);\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n\n const query = useViolations({\n policyId,\n resourceId,\n status: status || undefined,\n pagination: { limit: PAGE_SIZE, offset },\n });\n const resolve = useResolveViolation();\n\n // Live per-status counts for the segmented tabs. Each is a cheap `limit: 1`\n // query read for its `pageInfo.totalCount` (the estate-wide total for that\n // filter); \"All\" is the same query without a status. They respect the current\n // policy/resource URL scope so the badges match the visible queue.\n const countBase = { policyId, resourceId, pagination: { limit: 1, offset: 0 } };\n const allCount = useViolations(countBase);\n const openCount = useViolations({ ...countBase, status: 'OPEN' });\n const ackCount = useViolations({ ...countBase, status: 'ACKNOWLEDGED' });\n const resolvedCount = useViolations({ ...countBase, status: 'RESOLVED' });\n const waivedCount = useViolations({ ...countBase, status: 'WAIVED' });\n\n const tabCounts: Record<AdaViolationStatus | '', number | undefined> = {\n '': allCount.data?.pageInfo.totalCount ?? undefined,\n OPEN: openCount.data?.pageInfo.totalCount ?? undefined,\n ACKNOWLEDGED: ackCount.data?.pageInfo.totalCount ?? undefined,\n RESOLVED: resolvedCount.data?.pageInfo.totalCount ?? undefined,\n WAIVED: waivedCount.data?.pageInfo.totalCount ?? undefined,\n };\n\n const toggleEvidence = useCallback((id: string) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n }, []);\n\n // Severity ordering is applied ONLY within the current server page. The queue\n // pages by offset, so this does not globally reorder across pages — a page-2\n // CRITICAL still sorts below a page-1 LOW. Kept as a within-page readability\n // aid (the service has no severity sort arg to make it global).\n const items = [...(query.data?.items ?? [])].sort(\n (a, b) => severityRank[b.severity] - severityRank[a.severity]\n );\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n\n const onError = useCallback(\n (err: unknown) =>\n setActionError(err instanceof Error ? err.message : 'Action failed. Please try again.'),\n []\n );\n\n const transition = useCallback(\n (id: string, newStatus: AdaViolationStatus) => {\n setActionError(null);\n resolve.mutate({ id, status: newStatus }, { onError });\n },\n [resolve, onError]\n );\n\n const confirmWaive = useCallback(() => {\n if (!waiveTarget) return;\n if (!waiverReason.trim()) {\n setActionError(t('adaptercloud.violations.reasonRequired', 'A waiver requires a reason.'));\n return;\n }\n setActionError(null);\n resolve.mutate(\n { id: waiveTarget.id, status: 'WAIVED', waiverReason: waiverReason.trim() },\n {\n onSuccess: () => {\n setWaiveTarget(null);\n setWaiverReason('');\n },\n onError,\n }\n );\n }, [waiveTarget, waiverReason, resolve, onError, t]);\n\n return (\n <PageLayout\n title={t('adaptercloud.violations.title', 'Violations')}\n description={t(\n 'adaptercloud.violations.subtitle',\n 'Work the governance queue — acknowledge, resolve, or waive policy breaches.'\n )}\n >\n <div\n className=\"mb-6 flex flex-wrap items-center gap-2\"\n role=\"tablist\"\n aria-label={t('adaptercloud.violations.filterByStatus', 'Filter by status')}\n >\n {STATUS_TABS.map((tab) => {\n const active = status === tab;\n const count = tabCounts[tab];\n const label =\n tab === ''\n ? t('adaptercloud.violations.allStatuses', 'All')\n : violationStatusLabels[tab];\n return (\n <button\n key={tab || 'all'}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n onClick={() => {\n setStatus(tab);\n setOffset(0);\n }}\n className={cn(\n 'inline-flex items-center gap-2 rounded-full border px-3.5 py-1.5 text-sm font-medium transition-colors',\n active\n ? 'border-transparent bg-action-primary-bg text-action-primary-text'\n : 'border-border-subtle text-text-secondary hover:bg-accent'\n )}\n >\n {label}\n {count !== undefined && (\n <span\n className={cn(\n 'inline-flex min-w-5 items-center justify-center rounded-full px-1.5 text-xs font-semibold tabular-nums',\n active\n ? 'bg-action-primary-text/20 text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary'\n )}\n >\n {count}\n </span>\n )}\n </button>\n );\n })}\n {(policyId || resourceId) && (\n <button\n type=\"button\"\n onClick={() => navigateTo('/violations')}\n className=\"inline-flex items-center gap-1.5 rounded-full bg-accent-blue-subtle px-2.5 py-1 text-xs text-accent-blue hover:underline\"\n >\n {t('adaptercloud.violations.clearScope', 'Clear scope ×')}\n </button>\n )}\n </div>\n\n {actionError && (\n <p\n role=\"alert\"\n aria-live=\"polite\"\n className=\"mb-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\"\n >\n {actionError}\n </p>\n )}\n\n <DataState\n isLoading={query.isLoading}\n isError={query.isError}\n isEmpty={items.length === 0}\n error={query.error}\n onRetry={() => void query.refetch()}\n emptyTitle={t('adaptercloud.violations.emptyTitle', 'No violations')}\n emptyDescription={t(\n 'adaptercloud.violations.emptyDescription',\n 'Nothing matches this filter — your estate is clean here.'\n )}\n emptyIcon={<ShieldAlert className=\"h-10 w-10\" />}\n >\n <div className=\"space-y-3\">\n {items.map((v) => {\n const isOpen = v.status === 'OPEN' || v.status === 'ACKNOWLEDGED';\n return (\n <GlassCard key={v.id} className=\"p-5\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"mb-1.5 flex flex-wrap items-center gap-2\">\n <SeverityBadge severity={v.severity} />\n <StatusBadge status={v.status} />\n {v.policy && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/policies/${v.policyId}`)}\n className=\"text-xs font-medium text-accent-blue hover:underline\"\n >\n {v.policy.name}\n </button>\n )}\n </div>\n <p className=\"text-sm font-medium text-text-primary\">{v.message}</p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {t('adaptercloud.violations.detected', 'Detected')} {formatDate(v.detectedAt)}\n {' · '}\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources/${v.resourceId}`)}\n className=\"hover:underline\"\n >\n {t('adaptercloud.violations.viewResource', 'View resource')}\n </button>\n </p>\n {v.waiverReason && (\n <p className=\"mt-2 rounded-lg bg-bg-sunken px-3 py-1.5 text-xs text-text-secondary\">\n {t('adaptercloud.violations.waiver', 'Waiver')}: {v.waiverReason}\n </p>\n )}\n {v.evidence != null && (\n <div className=\"mt-2\">\n <button\n type=\"button\"\n onClick={() => toggleEvidence(v.id)}\n aria-expanded={expanded.has(v.id)}\n className=\"inline-flex items-center gap-1 text-xs font-medium text-text-secondary transition-colors hover:text-text-primary\"\n >\n {expanded.has(v.id) ? (\n <ChevronDown className=\"h-3.5 w-3.5\" />\n ) : (\n <ChevronRight className=\"h-3.5 w-3.5\" />\n )}\n {t('adaptercloud.violations.evidence', 'Evidence')}\n </button>\n {expanded.has(v.id) && (\n <pre className=\"mt-2 overflow-x-auto rounded-lg border border-border-subtle bg-bg-sunken p-3 font-mono text-xs text-text-secondary\">\n {JSON.stringify(v.evidence, null, 2)}\n </pre>\n )}\n </div>\n )}\n </div>\n\n {isOpen && (\n <div className=\"flex shrink-0 flex-wrap gap-2\">\n {v.status === 'OPEN' && (\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => transition(v.id, 'ACKNOWLEDGED')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-accent disabled:opacity-50\"\n >\n <Check className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.acknowledge', 'Acknowledge')}\n </button>\n )}\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => transition(v.id, 'RESOLVED')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-success-text transition-colors hover:bg-status-success-bg-subtle disabled:opacity-50\"\n >\n <CheckCheck className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.resolve', 'Resolve')}\n </button>\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => {\n setActionError(null);\n setWaiverReason('');\n setWaiveTarget(v);\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-secondary transition-colors hover:bg-accent disabled:opacity-50\"\n >\n <FileText className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.waive', 'Waive')}\n </button>\n </div>\n )}\n </div>\n </GlassCard>\n );\n })}\n </div>\n\n {(offset > 0 || hasMore) && (\n <div className=\"mt-6 flex items-center justify-between\">\n <button\n type=\"button\"\n disabled={offset === 0}\n onClick={() => setOffset((o) => Math.max(0, o - PAGE_SIZE))}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.prev', 'Previous')}\n </button>\n <span className=\"text-sm text-text-secondary\">\n {t('adaptercloud.common.showing', 'Showing')} {offset + 1}–{offset + items.length}\n </span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setOffset((o) => o + PAGE_SIZE)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {t('adaptercloud.common.next', 'Next')}\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </DataState>\n\n {/* Waive dialog */}\n <ResponsiveDialog\n open={Boolean(waiveTarget)}\n onOpenChange={(open) => {\n if (!open) setWaiveTarget(null);\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {t('adaptercloud.violations.waiveTitle', 'Waive violation')}\n </ResponsiveDialogTitle>\n </ResponsiveDialogHeader>\n <div className=\"px-1 py-2\">\n <label htmlFor=\"ada-waiver-reason\" className=\"mb-1.5 block text-sm text-text-secondary\">\n {t(\n 'adaptercloud.violations.waivePrompt',\n 'A waiver requires a documented reason and is recorded on the violation.'\n )}\n </label>\n <textarea\n id=\"ada-waiver-reason\"\n value={waiverReason}\n onChange={(e) => setWaiverReason(e.target.value)}\n rows={4}\n autoFocus\n aria-label={t('adaptercloud.violations.waiverReason', 'Waiver reason')}\n placeholder={t(\n 'adaptercloud.violations.waiveReasonPlaceholder',\n 'Why is this acceptable?'\n )}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {actionError && (\n <p role=\"alert\" aria-live=\"polite\" className=\"mt-2 text-sm text-status-error-text\">\n {actionError}\n </p>\n )}\n </div>\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n onClick={() => setWaiveTarget(null)}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n {t('adaptercloud.common.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={confirmWaive}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90 disabled:opacity-50\"\n >\n {resolve.isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {t('adaptercloud.violations.confirmWaive', 'Waive')}\n </button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"adaptercloudStore.js","names":[],"sources":["../../../src/adaptercloud/store/adaptercloudStore.ts"],"sourcesContent":["/**\n * AdapterCloud Zustand Store\n * @module adaptercloud/store\n *\n * Local, persisted UI state for the AdapterCloud MFE (view mode, the active\n * domain section, sidebar collapse, and the global search term). Server state\n * lives in React Query — this store holds only view preferences.\n */\n\nimport { create } from 'zustand';\nimport { devtools, persist } from 'zustand/middleware';\nimport { createProfileScopedStorage } from '@burdenoff/fe-libs/shared/utils';\nimport type { ViewMode } from '../types';\n\n// ============================================================================\n// State Interface\n// ============================================================================\n\ninterface AdapterCloudState {\n // View state\n viewMode: ViewMode;\n activeSection: string;\n sidebarCollapsed: boolean;\n\n // Search\n searchQuery: string;\n\n // Actions\n setViewMode: (mode: ViewMode) => void;\n setActiveSection: (section: string) => void;\n setSearchQuery: (query: string) => void;\n toggleSidebar: () => void;\n reset: () => void;\n}\n\n// ============================================================================\n// Initial State\n// ============================================================================\n\nconst initialState = {\n viewMode: 'grid' as ViewMode,\n activeSection: 'dashboard',\n sidebarCollapsed: false,\n searchQuery: '',\n};\n\n// ============================================================================\n// Store\n// ============================================================================\n\nexport const useAdapterCloudStore = create<AdapterCloudState>()(\n devtools(\n persist(\n (set) => ({\n ...initialState,\n\n setViewMode: (mode) => set({ viewMode: mode }),\n setActiveSection: (section) => set({ activeSection: section }),\n toggleSidebar: () => set((state) => ({ sidebarCollapsed: !state.sidebarCollapsed })),\n setSearchQuery: (query) => set({ searchQuery: query }),\n\n reset: () => set(initialState),\n }),\n {\n name: 'burdenoff-adaptercloud-storage',\n storage: createProfileScopedStorage(),\n partialize: (state) => ({\n viewMode: state.viewMode,\n sidebarCollapsed: state.sidebarCollapsed,\n activeSection: state.activeSection,\n }),\n }\n ),\n { name: 'AdapterCloud Store', enabled: import.meta.env.DEV }\n )\n);\n"],"mappings":";;;;AAuCA,IAAM,IAAe;CACnB,UAAU;CACV,eAAe;CACf,kBAAkB;CAClB,aAAa;CACd,EAMY,IAAuB,GAA2B,CAC7D,EACE,GACG,OAAS;CACR,GAAG;CAEH,cAAc,MAAS,EAAI,EAAE,UAAU,GAAM,CAAC;CAC9C,mBAAmB,MAAY,EAAI,EAAE,eAAe,GAAS,CAAC;CAC9D,qBAAqB,GAAK,OAAW,EAAE,kBAAkB,CAAC,EAAM,kBAAkB,EAAE;CACpF,iBAAiB,MAAU,EAAI,EAAE,aAAa,GAAO,CAAC;CAEtD,aAAa,EAAI,EAAa;CAC/B,GACD;CACE,MAAM;CACN,SAAS,GAA4B;CACrC,aAAa,OAAW;EACtB,UAAU,EAAM;EAChB,kBAAkB,EAAM;EACxB,eAAe,EAAM;EACtB;CACF,CACF,EACD;CAAE,MAAM;CAAsB,SAAA;CAA8B,CAC7D,CACF"}
1
+ {"version":3,"file":"adaptercloudStore.js","names":[],"sources":["../../../src/adaptercloud/store/adaptercloudStore.ts"],"sourcesContent":["/**\n * AdapterCloud Zustand Store\n * @module adaptercloud/store\n *\n * Local, persisted UI state for the AdapterCloud MFE (view mode, the active\n * domain section, sidebar collapse, and the global search term). Server state\n * lives in React Query — this store holds only view preferences.\n */\n\nimport { create } from 'zustand';\nimport { devtools, persist } from 'zustand/middleware';\nimport { createProfileScopedStorage } from '@burdenoff/fe-libs/shared/utils';\nimport type { ViewMode } from '../types';\n\n// ============================================================================\n// State Interface\n// ============================================================================\n\ninterface AdapterCloudState {\n // View state\n viewMode: ViewMode;\n activeSection: string;\n sidebarCollapsed: boolean;\n\n // Search\n searchQuery: string;\n\n // Actions\n setViewMode: (mode: ViewMode) => void;\n setActiveSection: (section: string) => void;\n setSearchQuery: (query: string) => void;\n toggleSidebar: () => void;\n reset: () => void;\n}\n\n// ============================================================================\n// Initial State\n// ============================================================================\n\nconst initialState = {\n viewMode: 'grid' as ViewMode,\n activeSection: 'dashboard',\n sidebarCollapsed: false,\n searchQuery: '',\n};\n\n// ============================================================================\n// Store\n// ============================================================================\n\nexport const useAdapterCloudStore = create<AdapterCloudState>()(\n devtools(\n persist(\n (set) => ({\n ...initialState,\n\n setViewMode: (mode) => set({ viewMode: mode }),\n setActiveSection: (section) => set({ activeSection: section }),\n toggleSidebar: () => set((state) => ({ sidebarCollapsed: !state.sidebarCollapsed })),\n setSearchQuery: (query) => set({ searchQuery: query }),\n\n reset: () => set(initialState),\n }),\n {\n name: 'burdenoff-adaptercloud-storage',\n storage: createProfileScopedStorage(),\n partialize: (state) => ({\n viewMode: state.viewMode,\n sidebarCollapsed: state.sidebarCollapsed,\n activeSection: state.activeSection,\n }),\n }\n ),\n { name: 'AdapterCloud Store', enabled: import.meta.env.DEV }\n )\n);\n"],"mappings":";;;;AAuCA,IAAM,IAAe;CACnB,UAAU;CACV,eAAe;CACf,kBAAkB;CAClB,aAAa;AACf,GAMa,IAAuB,EAA0B,EAC5D,EACE,GACG,OAAS;CACR,GAAG;CAEH,cAAc,MAAS,EAAI,EAAE,UAAU,EAAK,CAAC;CAC7C,mBAAmB,MAAY,EAAI,EAAE,eAAe,EAAQ,CAAC;CAC7D,qBAAqB,GAAK,OAAW,EAAE,kBAAkB,CAAC,EAAM,iBAAiB,EAAE;CACnF,iBAAiB,MAAU,EAAI,EAAE,aAAa,EAAM,CAAC;CAErD,aAAa,EAAI,CAAY;AAC/B,IACA;CACE,MAAM;CACN,SAAS,EAA2B;CACpC,aAAa,OAAW;EACtB,UAAU,EAAM;EAChB,kBAAkB,EAAM;EACxB,eAAe,EAAM;CACvB;AACF,CACF,GACA;CAAE,MAAM;CAAsB,SAAA;AAA6B,CAC7D,CACF"}
@@ -245,6 +245,10 @@ export interface AdaDriftRecord {
245
245
  createdAt: string;
246
246
  updatedAt: string;
247
247
  }
248
+ export interface AdaDriftRecordPage {
249
+ items: AdaDriftRecord[];
250
+ pageInfo: AdaPageInfo;
251
+ }
248
252
  export interface AdaSyncRun {
249
253
  id: string;
250
254
  connectionId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adaptercloud/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adaptercloud/types/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"cn.js","names":[],"sources":["../../../src/adaptercloud/utils/cn.ts"],"sourcesContent":["/**\n * Class name utility\n * @module adaptercloud/utils\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n"],"mappings":";;;AAQA,SAAgB,EAAG,GAAG,GAA8B;AAClD,QAAO,EAAQ,EAAK,EAAO,CAAC"}
1
+ {"version":3,"file":"cn.js","names":[],"sources":["../../../src/adaptercloud/utils/cn.ts"],"sourcesContent":["/**\n * Class name utility\n * @module adaptercloud/utils\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n"],"mappings":";;;AAQA,SAAgB,EAAG,GAAG,GAA8B;CAClD,OAAO,EAAQ,EAAK,CAAM,CAAC;AAC7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"domain.js","names":[],"sources":["../../../src/adaptercloud/utils/domain.ts"],"sourcesContent":["/**\n * AdapterCloud domain helpers\n * @module adaptercloud/utils\n *\n * Human-readable labels and severity/status ordering for the AdapterCloud\n * domain enums, plus a USD-default money formatter (cost records carry their\n * own currency). Keeps page components free of inline enum-to-label maps.\n */\n\nimport type {\n AdaAdapterKind,\n AdaAdapterStatus,\n AdaAuthMethod,\n AdaConnectionStatus,\n AdaDriftStatus,\n AdaPolicyEnforcement,\n AdaPolicyKind,\n AdaResourceState,\n AdaSeverity,\n AdaSyncKind,\n AdaSyncStatus,\n AdaViolationStatus,\n} from '../types';\n\n/** Title-case an UPPER_SNAKE enum value into a readable label. */\nexport function humanizeEnum(value: string): string {\n return value\n .toLowerCase()\n .split('_')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ');\n}\n\nexport const adapterKindLabels: Record<AdaAdapterKind, string> = {\n CUSTOM: 'Custom',\n DATA_SYSTEM: 'Data System',\n EDGE: 'Edge',\n IOT: 'IoT',\n KUBERNETES: 'Kubernetes',\n NETWORK: 'Network',\n ON_PREM: 'On-Prem',\n PRIVATE_CLOUD: 'Private Cloud',\n PUBLIC_CLOUD: 'Public Cloud',\n SAAS: 'SaaS',\n};\n\nexport const adapterStatusLabels: Record<AdaAdapterStatus, string> = {\n ARCHIVED: 'Archived',\n DEPRECATED: 'Deprecated',\n DRAFT: 'Draft',\n PUBLISHED: 'Published',\n};\n\nexport const authMethodLabels: Record<AdaAuthMethod, string> = {\n API_KEY: 'API Key',\n CERTIFICATE: 'Certificate',\n IAM_ROLE: 'IAM Role',\n NONE: 'None',\n OAUTH2: 'OAuth2',\n SERVICE_ACCOUNT: 'Service Account',\n};\n\nexport const connectionStatusLabels: Record<AdaConnectionStatus, string> = {\n CONNECTED: 'Connected',\n DEGRADED: 'Degraded',\n DISABLED: 'Disabled',\n ERROR: 'Error',\n PENDING: 'Pending',\n};\n\nexport const resourceStateLabels: Record<AdaResourceState, string> = {\n DELETED: 'Deleted',\n DISCOVERED: 'Discovered',\n DRIFTED: 'Drifted',\n ORPHANED: 'Orphaned',\n RECONCILED: 'Reconciled',\n};\n\nexport const policyKindLabels: Record<AdaPolicyKind, string> = {\n COMPLIANCE: 'Compliance',\n COST: 'Cost',\n GUARDRAIL: 'Guardrail',\n NAMING: 'Naming',\n SECURITY: 'Security',\n TAGGING: 'Tagging',\n};\n\nexport const policyEnforcementLabels: Record<AdaPolicyEnforcement, string> = {\n ADVISORY: 'Advisory',\n BLOCK: 'Block',\n WARN: 'Warn',\n};\n\nexport const severityLabels: Record<AdaSeverity, string> = {\n CRITICAL: 'Critical',\n HIGH: 'High',\n INFO: 'Info',\n LOW: 'Low',\n MEDIUM: 'Medium',\n};\n\nexport const violationStatusLabels: Record<AdaViolationStatus, string> = {\n ACKNOWLEDGED: 'Acknowledged',\n OPEN: 'Open',\n RESOLVED: 'Resolved',\n WAIVED: 'Waived',\n};\n\nexport const driftStatusLabels: Record<AdaDriftStatus, string> = {\n ACKNOWLEDGED: 'Acknowledged',\n DETECTED: 'Detected',\n IGNORED: 'Ignored',\n REMEDIATED: 'Remediated',\n};\n\nexport const syncKindLabels: Record<AdaSyncKind, string> = {\n COST_INGEST: 'Cost Ingest',\n DISCOVERY: 'Discovery',\n FULL: 'Full',\n RECONCILE: 'Reconcile',\n};\n\nexport const syncStatusLabels: Record<AdaSyncStatus, string> = {\n CANCELLED: 'Cancelled',\n FAILED: 'Failed',\n QUEUED: 'Queued',\n RUNNING: 'Running',\n SUCCEEDED: 'Succeeded',\n};\n\n/** Highest = most urgent. Used to sort violations/drift queues. */\nexport const severityRank: Record<AdaSeverity, number> = {\n CRITICAL: 5,\n HIGH: 4,\n MEDIUM: 3,\n LOW: 2,\n INFO: 1,\n};\n\n/** Tailwind classes (semantic tokens only) for a severity pill. */\nexport const severityPillClass: Record<AdaSeverity, string> = {\n CRITICAL: 'bg-status-error-bg-subtle text-status-error-text',\n HIGH: 'bg-status-error-bg-subtle text-status-error-text',\n MEDIUM: 'bg-status-warning-bg-subtle text-status-warning-text',\n LOW: 'bg-accent-blue-subtle text-accent-blue',\n INFO: 'bg-bg-sunken text-text-secondary',\n};\n\n/**\n * Format a money amount with its currency. AdapterCloud cost is multi-cloud and\n * typically USD; cost records carry an explicit currency code.\n */\nexport function formatMoney(amount: number, currency = 'USD'): string {\n try {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency,\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n }).format(amount);\n } catch {\n return `${currency} ${amount.toFixed(2)}`;\n }\n}\n"],"mappings":";AAyBA,SAAgB,EAAa,GAAuB;AAClD,QAAO,EACJ,aAAa,CACb,MAAM,IAAI,CACV,KAAK,MAAS,EAAK,OAAO,EAAE,CAAC,aAAa,GAAG,EAAK,MAAM,EAAE,CAAC,CAC3D,KAAK,IAAI;;AAGd,IAAa,IAAoD;CAC/D,QAAQ;CACR,aAAa;CACb,MAAM;CACN,KAAK;CACL,YAAY;CACZ,SAAS;CACT,SAAS;CACT,eAAe;CACf,cAAc;CACd,MAAM;CACP,EAEY,IAAwD;CACnE,UAAU;CACV,YAAY;CACZ,OAAO;CACP,WAAW;CACZ,EAEY,IAAkD;CAC7D,SAAS;CACT,aAAa;CACb,UAAU;CACV,MAAM;CACN,QAAQ;CACR,iBAAiB;CAClB,EAEY,IAA8D;CACzE,WAAW;CACX,UAAU;CACV,UAAU;CACV,OAAO;CACP,SAAS;CACV,EAEY,IAAwD;CACnE,SAAS;CACT,YAAY;CACZ,SAAS;CACT,UAAU;CACV,YAAY;CACb,EAEY,IAAkD;CAC7D,YAAY;CACZ,MAAM;CACN,WAAW;CACX,QAAQ;CACR,UAAU;CACV,SAAS;CACV,EAEY,IAAgE;CAC3E,UAAU;CACV,OAAO;CACP,MAAM;CACP,EAEY,IAA8C;CACzD,UAAU;CACV,MAAM;CACN,MAAM;CACN,KAAK;CACL,QAAQ;CACT,EAEY,IAA4D;CACvE,cAAc;CACd,MAAM;CACN,UAAU;CACV,QAAQ;CACT,EAEY,IAAoD;CAC/D,cAAc;CACd,UAAU;CACV,SAAS;CACT,YAAY;CACb,EAEY,IAA8C;CACzD,aAAa;CACb,WAAW;CACX,MAAM;CACN,WAAW;CACZ,EAEY,IAAkD;CAC7D,WAAW;CACX,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,WAAW;CACZ,EAGY,IAA4C;CACvD,UAAU;CACV,MAAM;CACN,QAAQ;CACR,KAAK;CACL,MAAM;CACP,EAGY,IAAiD;CAC5D,UAAU;CACV,MAAM;CACN,QAAQ;CACR,KAAK;CACL,MAAM;CACP;AAMD,SAAgB,EAAY,GAAgB,IAAW,OAAe;AACpE,KAAI;AACF,SAAO,IAAI,KAAK,aAAa,SAAS;GACpC,OAAO;GACP;GACA,uBAAuB;GACvB,uBAAuB;GACxB,CAAC,CAAC,OAAO,EAAO;SACX;AACN,SAAO,GAAG,EAAS,GAAG,EAAO,QAAQ,EAAE"}
1
+ {"version":3,"file":"domain.js","names":[],"sources":["../../../src/adaptercloud/utils/domain.ts"],"sourcesContent":["/**\n * AdapterCloud domain helpers\n * @module adaptercloud/utils\n *\n * Human-readable labels and severity/status ordering for the AdapterCloud\n * domain enums, plus a USD-default money formatter (cost records carry their\n * own currency). Keeps page components free of inline enum-to-label maps.\n */\n\nimport type {\n AdaAdapterKind,\n AdaAdapterStatus,\n AdaAuthMethod,\n AdaConnectionStatus,\n AdaDriftStatus,\n AdaPolicyEnforcement,\n AdaPolicyKind,\n AdaResourceState,\n AdaSeverity,\n AdaSyncKind,\n AdaSyncStatus,\n AdaViolationStatus,\n} from '../types';\n\n/** Title-case an UPPER_SNAKE enum value into a readable label. */\nexport function humanizeEnum(value: string): string {\n return value\n .toLowerCase()\n .split('_')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ');\n}\n\nexport const adapterKindLabels: Record<AdaAdapterKind, string> = {\n CUSTOM: 'Custom',\n DATA_SYSTEM: 'Data System',\n EDGE: 'Edge',\n IOT: 'IoT',\n KUBERNETES: 'Kubernetes',\n NETWORK: 'Network',\n ON_PREM: 'On-Prem',\n PRIVATE_CLOUD: 'Private Cloud',\n PUBLIC_CLOUD: 'Public Cloud',\n SAAS: 'SaaS',\n};\n\nexport const adapterStatusLabels: Record<AdaAdapterStatus, string> = {\n ARCHIVED: 'Archived',\n DEPRECATED: 'Deprecated',\n DRAFT: 'Draft',\n PUBLISHED: 'Published',\n};\n\nexport const authMethodLabels: Record<AdaAuthMethod, string> = {\n API_KEY: 'API Key',\n CERTIFICATE: 'Certificate',\n IAM_ROLE: 'IAM Role',\n NONE: 'None',\n OAUTH2: 'OAuth2',\n SERVICE_ACCOUNT: 'Service Account',\n};\n\nexport const connectionStatusLabels: Record<AdaConnectionStatus, string> = {\n CONNECTED: 'Connected',\n DEGRADED: 'Degraded',\n DISABLED: 'Disabled',\n ERROR: 'Error',\n PENDING: 'Pending',\n};\n\nexport const resourceStateLabels: Record<AdaResourceState, string> = {\n DELETED: 'Deleted',\n DISCOVERED: 'Discovered',\n DRIFTED: 'Drifted',\n ORPHANED: 'Orphaned',\n RECONCILED: 'Reconciled',\n};\n\nexport const policyKindLabels: Record<AdaPolicyKind, string> = {\n COMPLIANCE: 'Compliance',\n COST: 'Cost',\n GUARDRAIL: 'Guardrail',\n NAMING: 'Naming',\n SECURITY: 'Security',\n TAGGING: 'Tagging',\n};\n\nexport const policyEnforcementLabels: Record<AdaPolicyEnforcement, string> = {\n ADVISORY: 'Advisory',\n BLOCK: 'Block',\n WARN: 'Warn',\n};\n\nexport const severityLabels: Record<AdaSeverity, string> = {\n CRITICAL: 'Critical',\n HIGH: 'High',\n INFO: 'Info',\n LOW: 'Low',\n MEDIUM: 'Medium',\n};\n\nexport const violationStatusLabels: Record<AdaViolationStatus, string> = {\n ACKNOWLEDGED: 'Acknowledged',\n OPEN: 'Open',\n RESOLVED: 'Resolved',\n WAIVED: 'Waived',\n};\n\nexport const driftStatusLabels: Record<AdaDriftStatus, string> = {\n ACKNOWLEDGED: 'Acknowledged',\n DETECTED: 'Detected',\n IGNORED: 'Ignored',\n REMEDIATED: 'Remediated',\n};\n\nexport const syncKindLabels: Record<AdaSyncKind, string> = {\n COST_INGEST: 'Cost Ingest',\n DISCOVERY: 'Discovery',\n FULL: 'Full',\n RECONCILE: 'Reconcile',\n};\n\nexport const syncStatusLabels: Record<AdaSyncStatus, string> = {\n CANCELLED: 'Cancelled',\n FAILED: 'Failed',\n QUEUED: 'Queued',\n RUNNING: 'Running',\n SUCCEEDED: 'Succeeded',\n};\n\n/** Highest = most urgent. Used to sort violations/drift queues. */\nexport const severityRank: Record<AdaSeverity, number> = {\n CRITICAL: 5,\n HIGH: 4,\n MEDIUM: 3,\n LOW: 2,\n INFO: 1,\n};\n\n/** Tailwind classes (semantic tokens only) for a severity pill. */\nexport const severityPillClass: Record<AdaSeverity, string> = {\n CRITICAL: 'bg-status-error-bg-subtle text-status-error-text',\n HIGH: 'bg-status-error-bg-subtle text-status-error-text',\n MEDIUM: 'bg-status-warning-bg-subtle text-status-warning-text',\n LOW: 'bg-accent-blue-subtle text-accent-blue',\n INFO: 'bg-bg-sunken text-text-secondary',\n};\n\n/**\n * Format a money amount with its currency. AdapterCloud cost is multi-cloud and\n * typically USD; cost records carry an explicit currency code.\n */\nexport function formatMoney(amount: number, currency = 'USD'): string {\n try {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency,\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n }).format(amount);\n } catch {\n return `${currency} ${amount.toFixed(2)}`;\n }\n}\n"],"mappings":";AAyBA,SAAgB,EAAa,GAAuB;CAClD,OAAO,EACJ,YAAY,EACZ,MAAM,GAAG,EACT,KAAK,MAAS,EAAK,OAAO,CAAC,EAAE,YAAY,IAAI,EAAK,MAAM,CAAC,CAAC,EAC1D,KAAK,GAAG;AACb;AAEA,IAAa,IAAoD;CAC/D,QAAQ;CACR,aAAa;CACb,MAAM;CACN,KAAK;CACL,YAAY;CACZ,SAAS;CACT,SAAS;CACT,eAAe;CACf,cAAc;CACd,MAAM;AACR,GAEa,IAAwD;CACnE,UAAU;CACV,YAAY;CACZ,OAAO;CACP,WAAW;AACb,GAEa,IAAkD;CAC7D,SAAS;CACT,aAAa;CACb,UAAU;CACV,MAAM;CACN,QAAQ;CACR,iBAAiB;AACnB,GAEa,IAA8D;CACzE,WAAW;CACX,UAAU;CACV,UAAU;CACV,OAAO;CACP,SAAS;AACX,GAEa,IAAwD;CACnE,SAAS;CACT,YAAY;CACZ,SAAS;CACT,UAAU;CACV,YAAY;AACd,GAEa,IAAkD;CAC7D,YAAY;CACZ,MAAM;CACN,WAAW;CACX,QAAQ;CACR,UAAU;CACV,SAAS;AACX,GAEa,IAAgE;CAC3E,UAAU;CACV,OAAO;CACP,MAAM;AACR,GAEa,IAA8C;CACzD,UAAU;CACV,MAAM;CACN,MAAM;CACN,KAAK;CACL,QAAQ;AACV,GAEa,IAA4D;CACvE,cAAc;CACd,MAAM;CACN,UAAU;CACV,QAAQ;AACV,GAEa,IAAoD;CAC/D,cAAc;CACd,UAAU;CACV,SAAS;CACT,YAAY;AACd,GAEa,IAA8C;CACzD,aAAa;CACb,WAAW;CACX,MAAM;CACN,WAAW;AACb,GAEa,IAAkD;CAC7D,WAAW;CACX,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,WAAW;AACb,GAGa,IAA4C;CACvD,UAAU;CACV,MAAM;CACN,QAAQ;CACR,KAAK;CACL,MAAM;AACR,GAGa,IAAiD;CAC5D,UAAU;CACV,MAAM;CACN,QAAQ;CACR,KAAK;CACL,MAAM;AACR;AAMA,SAAgB,EAAY,GAAgB,IAAW,OAAe;CACpE,IAAI;EACF,OAAO,IAAI,KAAK,aAAa,SAAS;GACpC,OAAO;GACP;GACA,uBAAuB;GACvB,uBAAuB;EACzB,CAAC,EAAE,OAAO,CAAM;CAClB,QAAQ;EACN,OAAO,GAAG,EAAS,GAAG,EAAO,QAAQ,CAAC;CACxC;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"formatters.js","names":[],"sources":["../../../src/adaptercloud/utils/formatters.ts"],"sourcesContent":["/**\n * Formatting utilities for the AdapterCloud microfrontend\n * @module adaptercloud/utils/formatters\n *\n * AdapterCloud is a global, multi-cloud infrastructure control plane: money is\n * denominated per cost record (USD by default) and rendered by the FinOps page\n * from the record's own `currency`, so there is deliberately no locale-locked\n * currency/number helper here (the previous INR/lakh/km helpers were leftover\n * template code and were removed).\n */\n\n/**\n * Format a date string or Date object into a human-readable format.\n *\n * @param date - ISO date string or Date object\n * @param options - Optional Intl.DateTimeFormat options\n * @returns Formatted date string (e.g., \"15 Jan 2026, 4:00 PM\")\n *\n * @example\n * formatDate('2026-01-15T10:30:00Z') // => \"15 Jan 2026, 4:00 PM\"\n */\nexport function formatDate(\n date: string | Date,\n options?: Partial<Intl.DateTimeFormatOptions>\n): string {\n const d = typeof date === 'string' ? new Date(date) : date;\n return new Intl.DateTimeFormat('en-GB', {\n day: 'numeric',\n month: 'short',\n year: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n ...options,\n }).format(d);\n}\n\n/**\n * Format a date into a relative time string (e.g., \"2 hours ago\")\n *\n * @param date - ISO date string or Date object\n * @returns Human-readable relative time string\n *\n * @example\n * formatRelativeTime('2024-01-15T10:30:00Z') // => \"3 days ago\"\n * formatRelativeTime(new Date()) // => \"just now\"\n */\nexport function formatRelativeTime(date: string | Date): string {\n const d = typeof date === 'string' ? new Date(date) : date;\n const now = new Date();\n const diffMs = now.getTime() - d.getTime();\n const diffSeconds = Math.floor(diffMs / 1000);\n const diffMinutes = Math.floor(diffSeconds / 60);\n const diffHours = Math.floor(diffMinutes / 60);\n const diffDays = Math.floor(diffHours / 24);\n const diffWeeks = Math.floor(diffDays / 7);\n const diffMonths = Math.floor(diffDays / 30);\n\n if (diffSeconds < 60) return 'just now';\n if (diffMinutes < 60) return `${diffMinutes} min${diffMinutes !== 1 ? 's' : ''} ago`;\n if (diffHours < 24) return `${diffHours} hour${diffHours !== 1 ? 's' : ''} ago`;\n if (diffDays < 7) return `${diffDays} day${diffDays !== 1 ? 's' : ''} ago`;\n if (diffWeeks < 4) return `${diffWeeks} week${diffWeeks !== 1 ? 's' : ''} ago`;\n if (diffMonths < 12) return `${diffMonths} month${diffMonths !== 1 ? 's' : ''} ago`;\n\n const diffYears = Math.floor(diffDays / 365);\n return `${diffYears} year${diffYears !== 1 ? 's' : ''} ago`;\n}\n"],"mappings":";AAqBA,SAAgB,EACd,GACA,GACQ;CACR,IAAM,IAAI,OAAO,KAAS,WAAW,IAAI,KAAK,EAAK,GAAG;AACtD,QAAO,IAAI,KAAK,eAAe,SAAS;EACtC,KAAK;EACL,OAAO;EACP,MAAM;EACN,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,GAAG;EACJ,CAAC,CAAC,OAAO,EAAE;;AAad,SAAgB,EAAmB,GAA6B;CAC9D,IAAM,IAAI,OAAO,KAAS,WAAW,IAAI,KAAK,EAAK,GAAG,GAEhD,qBADM,IAAI,MAAM,EACH,SAAS,GAAG,EAAE,SAAS,EACpC,IAAc,KAAK,MAAM,IAAS,IAAK,EACvC,IAAc,KAAK,MAAM,IAAc,GAAG,EAC1C,IAAY,KAAK,MAAM,IAAc,GAAG,EACxC,IAAW,KAAK,MAAM,IAAY,GAAG,EACrC,IAAY,KAAK,MAAM,IAAW,EAAE,EACpC,IAAa,KAAK,MAAM,IAAW,GAAG;AAE5C,KAAI,IAAc,GAAI,QAAO;AAC7B,KAAI,IAAc,GAAI,QAAO,GAAG,EAAY,MAAM,MAAgB,IAAU,KAAN,IAAS;AAC/E,KAAI,IAAY,GAAI,QAAO,GAAG,EAAU,OAAO,MAAc,IAAU,KAAN,IAAS;AAC1E,KAAI,IAAW,EAAG,QAAO,GAAG,EAAS,MAAM,MAAa,IAAU,KAAN,IAAS;AACrE,KAAI,IAAY,EAAG,QAAO,GAAG,EAAU,OAAO,MAAc,IAAU,KAAN,IAAS;AACzE,KAAI,IAAa,GAAI,QAAO,GAAG,EAAW,QAAQ,MAAe,IAAU,KAAN,IAAS;CAE9E,IAAM,IAAY,KAAK,MAAM,IAAW,IAAI;AAC5C,QAAO,GAAG,EAAU,OAAO,MAAc,IAAU,KAAN,IAAS"}
1
+ {"version":3,"file":"formatters.js","names":[],"sources":["../../../src/adaptercloud/utils/formatters.ts"],"sourcesContent":["/**\n * Formatting utilities for the AdapterCloud microfrontend\n * @module adaptercloud/utils/formatters\n *\n * AdapterCloud is a global, multi-cloud infrastructure control plane: money is\n * denominated per cost record (USD by default) and rendered by the FinOps page\n * from the record's own `currency`, so there is deliberately no locale-locked\n * currency/number helper here (the previous INR/lakh/km helpers were leftover\n * template code and were removed).\n */\n\n/**\n * Format a date string or Date object into a human-readable format.\n *\n * @param date - ISO date string or Date object\n * @param options - Optional Intl.DateTimeFormat options\n * @returns Formatted date string (e.g., \"15 Jan 2026, 4:00 PM\")\n *\n * @example\n * formatDate('2026-01-15T10:30:00Z') // => \"15 Jan 2026, 4:00 PM\"\n */\nexport function formatDate(\n date: string | Date,\n options?: Partial<Intl.DateTimeFormatOptions>\n): string {\n const d = typeof date === 'string' ? new Date(date) : date;\n return new Intl.DateTimeFormat('en-GB', {\n day: 'numeric',\n month: 'short',\n year: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n ...options,\n }).format(d);\n}\n\n/**\n * Format a date into a relative time string (e.g., \"2 hours ago\")\n *\n * @param date - ISO date string or Date object\n * @returns Human-readable relative time string\n *\n * @example\n * formatRelativeTime('2024-01-15T10:30:00Z') // => \"3 days ago\"\n * formatRelativeTime(new Date()) // => \"just now\"\n */\nexport function formatRelativeTime(date: string | Date): string {\n const d = typeof date === 'string' ? new Date(date) : date;\n const now = new Date();\n const diffMs = now.getTime() - d.getTime();\n const diffSeconds = Math.floor(diffMs / 1000);\n const diffMinutes = Math.floor(diffSeconds / 60);\n const diffHours = Math.floor(diffMinutes / 60);\n const diffDays = Math.floor(diffHours / 24);\n const diffWeeks = Math.floor(diffDays / 7);\n const diffMonths = Math.floor(diffDays / 30);\n\n if (diffSeconds < 60) return 'just now';\n if (diffMinutes < 60) return `${diffMinutes} min${diffMinutes !== 1 ? 's' : ''} ago`;\n if (diffHours < 24) return `${diffHours} hour${diffHours !== 1 ? 's' : ''} ago`;\n if (diffDays < 7) return `${diffDays} day${diffDays !== 1 ? 's' : ''} ago`;\n if (diffWeeks < 4) return `${diffWeeks} week${diffWeeks !== 1 ? 's' : ''} ago`;\n if (diffMonths < 12) return `${diffMonths} month${diffMonths !== 1 ? 's' : ''} ago`;\n\n const diffYears = Math.floor(diffDays / 365);\n return `${diffYears} year${diffYears !== 1 ? 's' : ''} ago`;\n}\n"],"mappings":";AAqBA,SAAgB,EACd,GACA,GACQ;CACR,IAAM,IAAI,OAAO,KAAS,WAAW,IAAI,KAAK,CAAI,IAAI;CACtD,OAAO,IAAI,KAAK,eAAe,SAAS;EACtC,KAAK;EACL,OAAO;EACP,MAAM;EACN,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,GAAG;CACL,CAAC,EAAE,OAAO,CAAC;AACb;AAYA,SAAgB,EAAmB,GAA6B;CAC9D,IAAM,IAAI,OAAO,KAAS,WAAW,IAAI,KAAK,CAAI,IAAI,GAEhD,qBAAS,IADC,KACD,GAAI,QAAQ,IAAI,EAAE,QAAQ,GACnC,IAAc,KAAK,MAAM,IAAS,GAAI,GACtC,IAAc,KAAK,MAAM,IAAc,EAAE,GACzC,IAAY,KAAK,MAAM,IAAc,EAAE,GACvC,IAAW,KAAK,MAAM,IAAY,EAAE,GACpC,IAAY,KAAK,MAAM,IAAW,CAAC,GACnC,IAAa,KAAK,MAAM,IAAW,EAAE;CAE3C,IAAI,IAAc,IAAI,OAAO;CAC7B,IAAI,IAAc,IAAI,OAAO,GAAG,EAAY,MAAM,MAAgB,IAAU,KAAN,IAAS;CAC/E,IAAI,IAAY,IAAI,OAAO,GAAG,EAAU,OAAO,MAAc,IAAU,KAAN,IAAS;CAC1E,IAAI,IAAW,GAAG,OAAO,GAAG,EAAS,MAAM,MAAa,IAAU,KAAN,IAAS;CACrE,IAAI,IAAY,GAAG,OAAO,GAAG,EAAU,OAAO,MAAc,IAAU,KAAN,IAAS;CACzE,IAAI,IAAa,IAAI,OAAO,GAAG,EAAW,QAAQ,MAAe,IAAU,KAAN,IAAS;CAE9E,IAAM,IAAY,KAAK,MAAM,IAAW,GAAG;CAC3C,OAAO,GAAG,EAAU,OAAO,MAAc,IAAU,KAAN,IAAS;AACxD"}
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.js","names":[],"sources":["../../../src/adaptercloud/utils/navigation.ts"],"sourcesContent":["/**\n * Navigation utilities for the AdapterCloud microfrontend\n * @module adaptercloud/utils\n */\n\n/**\n * Join basePath with a relative path, correctly handling slashes\n *\n * @param basePath - The base path (e.g., '/' or '/adaptercloud')\n * @param relativePath - The relative path (e.g., 'carts/new' or '/carts/new')\n * @returns The joined path (e.g., '/adaptercloud/carts/new')\n *\n * @example\n * joinPath('/', 'carts/new') // => '/carts/new'\n * joinPath('/', '/carts/new') // => '/carts/new'\n * joinPath('/adaptercloud', 'orders') // => '/adaptercloud/orders'\n * joinPath('/adaptercloud/', 'orders') // => '/adaptercloud/orders'\n * joinPath('/adaptercloud', '') // => '/adaptercloud'\n */\nexport function joinPath(basePath: string, relativePath: string): string {\n // Remove trailing slash from base\n const cleanBase = basePath.endsWith('/') ? basePath.slice(0, -1) : basePath;\n\n // Handle empty relative path (go to base)\n if (!relativePath || relativePath === '') {\n return cleanBase || '/';\n }\n\n // Ensure relative path starts with /\n const cleanPath = relativePath.startsWith('/') ? relativePath : `/${relativePath}`;\n\n // Join them\n return cleanBase + cleanPath;\n}\n"],"mappings":";AAmBA,SAAgB,EAAS,GAAkB,GAA8B;CAEvE,IAAM,IAAY,EAAS,SAAS,IAAI,GAAG,EAAS,MAAM,GAAG,GAAG,GAAG;AAWnE,QARI,CAAC,KAAgB,MAAiB,KAC7B,KAAa,MAOf,KAHW,EAAa,WAAW,IAAI,GAAG,IAAe,IAAI"}
1
+ {"version":3,"file":"navigation.js","names":[],"sources":["../../../src/adaptercloud/utils/navigation.ts"],"sourcesContent":["/**\n * Navigation utilities for the AdapterCloud microfrontend\n * @module adaptercloud/utils\n */\n\n/**\n * Join basePath with a relative path, correctly handling slashes\n *\n * @param basePath - The base path (e.g., '/' or '/adaptercloud')\n * @param relativePath - The relative path (e.g., 'carts/new' or '/carts/new')\n * @returns The joined path (e.g., '/adaptercloud/carts/new')\n *\n * @example\n * joinPath('/', 'carts/new') // => '/carts/new'\n * joinPath('/', '/carts/new') // => '/carts/new'\n * joinPath('/adaptercloud', 'orders') // => '/adaptercloud/orders'\n * joinPath('/adaptercloud/', 'orders') // => '/adaptercloud/orders'\n * joinPath('/adaptercloud', '') // => '/adaptercloud'\n */\nexport function joinPath(basePath: string, relativePath: string): string {\n // Remove trailing slash from base\n const cleanBase = basePath.endsWith('/') ? basePath.slice(0, -1) : basePath;\n\n // Handle empty relative path (go to base)\n if (!relativePath || relativePath === '') {\n return cleanBase || '/';\n }\n\n // Ensure relative path starts with /\n const cleanPath = relativePath.startsWith('/') ? relativePath : `/${relativePath}`;\n\n // Join them\n return cleanBase + cleanPath;\n}\n"],"mappings":";AAmBA,SAAgB,EAAS,GAAkB,GAA8B;CAEvE,IAAM,IAAY,EAAS,SAAS,GAAG,IAAI,EAAS,MAAM,GAAG,EAAE,IAAI;CAWnE,OARI,CAAC,KAAgB,MAAiB,KAC7B,KAAa,MAOf,KAHW,EAAa,WAAW,GAAG,IAAI,IAAe,IAAI;AAItE"}
@@ -1 +1 @@
1
- {"version":3,"file":"clsx.js","names":[],"sources":["../../../../node_modules/clsx/dist/clsx.mjs"],"sourcesContent":["function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;"],"x_google_ignoreList":[0],"mappings":";AAAA,SAAS,EAAE,GAAE;CAAC,IAAI,GAAE,GAAE,IAAE;AAAG,KAAa,OAAO,KAAjB,YAA8B,OAAO,KAAjB,SAAmB,MAAG;UAAoB,OAAO,KAAjB,SAAmB,KAAG,MAAM,QAAQ,EAAE,EAAC;EAAC,IAAI,IAAE,EAAE;AAAO,OAAI,IAAE,GAAE,IAAE,GAAE,IAAI,GAAE,OAAK,IAAE,EAAE,EAAE,GAAG,MAAI,MAAI,KAAG,MAAK,KAAG;OAAQ,MAAI,KAAK,EAAE,GAAE,OAAK,MAAI,KAAG,MAAK,KAAG;AAAG,QAAO;;AAAE,SAAgB,IAAM;AAAC,MAAI,IAAI,GAAE,GAAE,IAAE,GAAE,IAAE,IAAG,IAAE,UAAU,QAAO,IAAE,GAAE,IAAI,EAAC,IAAE,UAAU,QAAM,IAAE,EAAE,EAAE,MAAI,MAAI,KAAG,MAAK,KAAG;AAAG,QAAO"}
1
+ {"version":3,"file":"clsx.js","names":[],"sources":["../../../../node_modules/clsx/dist/clsx.mjs"],"sourcesContent":["function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;"],"x_google_ignoreList":[0],"mappings":";AAAA,SAAS,EAAE,GAAE;CAAC,IAAI,GAAE,GAAE,IAAE;CAAG,IAAa,OAAO,KAAjB,YAA8B,OAAO,KAAjB,UAAmB,KAAG;MAAO,IAAa,OAAO,KAAjB,UAAmB,IAAG,MAAM,QAAQ,CAAC,GAAE;EAAC,IAAI,IAAE,EAAE;EAAO,KAAI,IAAE,GAAE,IAAE,GAAE,KAAI,EAAE,OAAK,IAAE,EAAE,EAAE,EAAE,OAAK,MAAI,KAAG,MAAK,KAAG;CAAE,OAAM,KAAI,KAAK,GAAE,EAAE,OAAK,MAAI,KAAG,MAAK,KAAG;CAAG,OAAO;AAAC;AAAC,SAAgB,IAAM;CAAC,KAAI,IAAI,GAAE,GAAE,IAAE,GAAE,IAAE,IAAG,IAAE,UAAU,QAAO,IAAE,GAAE,KAAI,CAAC,IAAE,UAAU,QAAM,IAAE,EAAE,CAAC,OAAK,MAAI,KAAG,MAAK,KAAG;CAAG,OAAO;AAAC"}
@@ -234,7 +234,7 @@ var e = (e, t) => {
234
234
  }, Y = (e, t, n = !1) => {
235
235
  let r = j.exec(e);
236
236
  return r ? r[1] ? t(r[1]) : n : !1;
237
- }, X = (e) => e === "position" || e === "percentage", Z = (e) => e === "image" || e === "url", Q = (e) => e === "length" || e === "size" || e === "bg-size", $ = (e) => e === "length", Ce = (e) => e === "number", we = (e) => e === "family-name", Te = (e) => e === "number" || e === "weight", Ee = (e) => e === "shadow", De = /* @__PURE__ */ D(() => {
237
+ }, X = (e) => e === "position" || e === "percentage", Z = (e) => e === "image" || e === "url", Q = (e) => e === "length" || e === "size" || e === "bg-size", $ = (e) => e === "length", Ce = (e) => e === "number", we = (e) => e === "family-name", Te = (e) => e === "number" || e === "weight", Ee = (e) => e === "shadow", De = /*#__PURE__*/ D(() => {
238
238
  let e = k("color"), t = k("font"), n = k("text"), r = k("font-weight"), i = k("tracking"), a = k("leading"), o = k("breakpoint"), s = k("container"), c = k("spacing"), l = k("radius"), u = k("shadow"), d = k("inset-shadow"), ee = k("text-shadow"), f = k("drop-shadow"), p = k("blur"), m = k("perspective"), h = k("aspect"), g = k("ease"), _ = k("animate"), v = () => [
239
239
  "auto",
240
240
  "avoid",