@anlyx/ui 0.1.1 → 0.1.3

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 (126) hide show
  1. package/dist/components/AnalysisEvidenceList.d.ts +5 -0
  2. package/dist/components/AnalysisEvidenceList.js +61 -0
  3. package/dist/components/AnlyxAppShell.d.ts +1 -1
  4. package/dist/components/AnlyxAppShell.js +159 -15
  5. package/dist/components/ApiCallList.d.ts +3 -3
  6. package/dist/components/ApiCallList.js +12 -3
  7. package/dist/components/CanvasPlaceholder.d.ts +0 -1
  8. package/dist/components/CanvasPlaceholder.js +0 -1
  9. package/dist/components/CaptureStatusEmptyState.d.ts +0 -1
  10. package/dist/components/CaptureStatusEmptyState.js +5 -4
  11. package/dist/components/EndpointList.d.ts +0 -1
  12. package/dist/components/EndpointList.js +1 -2
  13. package/dist/components/EndpointMapCanvas.d.ts +5 -2
  14. package/dist/components/EndpointMapCanvas.js +93 -13
  15. package/dist/components/FlowLegend.d.ts +4 -2
  16. package/dist/components/FlowLegend.js +4 -2
  17. package/dist/components/FlowNodeCard.d.ts +1 -2
  18. package/dist/components/FlowNodeCard.js +25 -3
  19. package/dist/components/FlowStoryView.d.ts +22 -0
  20. package/dist/components/FlowStoryView.js +117 -0
  21. package/dist/components/InspectorPanel.d.ts +8 -3
  22. package/dist/components/InspectorPanel.js +36 -3
  23. package/dist/components/PageList.d.ts +0 -1
  24. package/dist/components/PageList.js +1 -2
  25. package/dist/components/PageStoryboardCard.d.ts +0 -1
  26. package/dist/components/PageStoryboardCard.js +4 -2
  27. package/dist/components/PageStoryboardView.d.ts +4 -3
  28. package/dist/components/PageStoryboardView.js +13 -3
  29. package/dist/components/ProcessFlowView.d.ts +21 -0
  30. package/dist/components/ProcessFlowView.js +16 -0
  31. package/dist/components/ProcessTimeline.d.ts +9 -0
  32. package/dist/components/ProcessTimeline.js +46 -0
  33. package/dist/components/ReplayControls.d.ts +6 -2
  34. package/dist/components/ReplayControls.js +31 -3
  35. package/dist/components/ScreenshotSegmentCard.d.ts +0 -1
  36. package/dist/components/ScreenshotSegmentCard.js +0 -1
  37. package/dist/components/Sidebar.d.ts +5 -4
  38. package/dist/components/Sidebar.js +19 -4
  39. package/dist/components/StatusBadge.d.ts +0 -1
  40. package/dist/components/StatusBadge.js +0 -1
  41. package/dist/flow/build-react-flow-model.d.ts +6 -2
  42. package/dist/flow/build-react-flow-model.js +15 -18
  43. package/dist/flow/layout/elk-layout.d.ts +7 -0
  44. package/dist/flow/layout/elk-layout.js +74 -0
  45. package/dist/index.d.ts +0 -1
  46. package/dist/index.js +0 -1
  47. package/dist/mock-data.d.ts +0 -1
  48. package/dist/mock-data.js +50 -5
  49. package/dist/overlay/AnlyxFlowEdge.d.ts +2 -0
  50. package/dist/overlay/AnlyxFlowEdge.js +15 -0
  51. package/dist/overlay/AnlyxFlowNode.d.ts +13 -0
  52. package/dist/overlay/AnlyxFlowNode.js +28 -0
  53. package/dist/overlay/FlowDrawer.d.ts +2 -0
  54. package/dist/overlay/FlowDrawer.js +59 -0
  55. package/dist/overlay/MainFlowCanvas.d.ts +20 -0
  56. package/dist/overlay/MainFlowCanvas.js +285 -0
  57. package/dist/overlay/RecentApiEventsTable.d.ts +5 -0
  58. package/dist/overlay/RecentApiEventsTable.js +19 -0
  59. package/dist/overlay/overlay-entry.d.ts +8 -0
  60. package/dist/overlay/overlay-entry.js +14 -0
  61. package/dist/overlay/overlay-ui.css +2 -0
  62. package/dist/overlay/overlay-ui.js +14 -0
  63. package/dist/overlay/types.d.ts +38 -0
  64. package/dist/overlay/types.js +1 -0
  65. package/dist/overlay/ui.d.ts +18 -0
  66. package/dist/overlay/ui.js +13 -0
  67. package/dist/readme-demo/ReadmeDemoApp.d.ts +4 -0
  68. package/dist/readme-demo/ReadmeDemoApp.js +126 -0
  69. package/dist/readme-demo/readme-demo-entry.d.ts +1 -0
  70. package/dist/readme-demo/readme-demo-entry.js +8 -0
  71. package/dist/replay/build-replay-steps.d.ts +0 -1
  72. package/dist/replay/build-replay-steps.js +0 -1
  73. package/dist/replay/use-replay-lite.d.ts +2 -2
  74. package/dist/replay/use-replay-lite.js +1 -1
  75. package/dist/styles.css +2018 -178
  76. package/dist/viewer/ViewerApp.d.ts +0 -1
  77. package/dist/viewer/ViewerApp.js +13 -7
  78. package/dist/viewer/viewer-entry.d.ts +1 -1
  79. package/dist/viewer/viewer-entry.js +1 -1
  80. package/package.json +7 -3
  81. package/dist/components/AnlyxAppShell.d.ts.map +0 -1
  82. package/dist/components/AnlyxAppShell.js.map +0 -1
  83. package/dist/components/ApiCallList.d.ts.map +0 -1
  84. package/dist/components/ApiCallList.js.map +0 -1
  85. package/dist/components/CanvasPlaceholder.d.ts.map +0 -1
  86. package/dist/components/CanvasPlaceholder.js.map +0 -1
  87. package/dist/components/CaptureStatusEmptyState.d.ts.map +0 -1
  88. package/dist/components/CaptureStatusEmptyState.js.map +0 -1
  89. package/dist/components/EndpointList.d.ts.map +0 -1
  90. package/dist/components/EndpointList.js.map +0 -1
  91. package/dist/components/EndpointMapCanvas.d.ts.map +0 -1
  92. package/dist/components/EndpointMapCanvas.js.map +0 -1
  93. package/dist/components/FlowLegend.d.ts.map +0 -1
  94. package/dist/components/FlowLegend.js.map +0 -1
  95. package/dist/components/FlowNodeCard.d.ts.map +0 -1
  96. package/dist/components/FlowNodeCard.js.map +0 -1
  97. package/dist/components/InspectorPanel.d.ts.map +0 -1
  98. package/dist/components/InspectorPanel.js.map +0 -1
  99. package/dist/components/PageList.d.ts.map +0 -1
  100. package/dist/components/PageList.js.map +0 -1
  101. package/dist/components/PageStoryboardCard.d.ts.map +0 -1
  102. package/dist/components/PageStoryboardCard.js.map +0 -1
  103. package/dist/components/PageStoryboardView.d.ts.map +0 -1
  104. package/dist/components/PageStoryboardView.js.map +0 -1
  105. package/dist/components/ReplayControls.d.ts.map +0 -1
  106. package/dist/components/ReplayControls.js.map +0 -1
  107. package/dist/components/ScreenshotSegmentCard.d.ts.map +0 -1
  108. package/dist/components/ScreenshotSegmentCard.js.map +0 -1
  109. package/dist/components/Sidebar.d.ts.map +0 -1
  110. package/dist/components/Sidebar.js.map +0 -1
  111. package/dist/components/StatusBadge.d.ts.map +0 -1
  112. package/dist/components/StatusBadge.js.map +0 -1
  113. package/dist/flow/build-react-flow-model.d.ts.map +0 -1
  114. package/dist/flow/build-react-flow-model.js.map +0 -1
  115. package/dist/index.d.ts.map +0 -1
  116. package/dist/index.js.map +0 -1
  117. package/dist/mock-data.d.ts.map +0 -1
  118. package/dist/mock-data.js.map +0 -1
  119. package/dist/replay/build-replay-steps.d.ts.map +0 -1
  120. package/dist/replay/build-replay-steps.js.map +0 -1
  121. package/dist/replay/use-replay-lite.d.ts.map +0 -1
  122. package/dist/replay/use-replay-lite.js.map +0 -1
  123. package/dist/viewer/ViewerApp.d.ts.map +0 -1
  124. package/dist/viewer/ViewerApp.js.map +0 -1
  125. package/dist/viewer/viewer-entry.d.ts.map +0 -1
  126. package/dist/viewer/viewer-entry.js.map +0 -1
@@ -0,0 +1,22 @@
1
+ import type { Endpoint, EndpointFlow, FlowNode, PageStoryboard, ScanResult } from "@anlyx/core";
2
+ import type { ReplayStep } from "../replay/build-replay-steps.js";
3
+ import type { ReplayLiteState } from "../replay/use-replay-lite.js";
4
+ export type FlowStoryViewProps = {
5
+ data: ScanResult;
6
+ endpoint: Endpoint | undefined;
7
+ flow: EndpointFlow | undefined;
8
+ page: PageStoryboard | undefined;
9
+ replayDisabled: boolean;
10
+ replayLoop: boolean;
11
+ replaySpeed: number;
12
+ replayState: ReplayLiteState;
13
+ replaySteps: ReplayStep[];
14
+ selectedNodeId: string | undefined;
15
+ onPause: () => void;
16
+ onPlay: () => void;
17
+ onRestart: () => void;
18
+ onSelectNode: (node: FlowNode) => void;
19
+ onSpeedChange: (speed: number) => void;
20
+ onToggleLoop: () => void;
21
+ };
22
+ export declare function FlowStoryView({ data, endpoint, flow, page, replayDisabled, replayLoop, replaySpeed, replayState, replaySteps, selectedNodeId, onPause, onPlay, onRestart, onSelectNode, onSpeedChange, onToggleLoop }: FlowStoryViewProps): JSX.Element;
@@ -0,0 +1,117 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Braces, Code2, Database, FileText, GitBranch, Globe2, Layers3, Maximize2, MonitorSmartphone, MousePointerClick, Route, ShieldCheck, Wifi } from "lucide-react";
3
+ import { ReplayControls } from "./ReplayControls.js";
4
+ import { StatusBadge } from "./StatusBadge.js";
5
+ export function FlowStoryView({ data, endpoint, flow, page, replayDisabled, replayLoop, replaySpeed, replayState, replaySteps, selectedNodeId, onPause, onPlay, onRestart, onSelectNode, onSpeedChange, onToggleLoop }) {
6
+ const storyPage = page ?? findPageForEndpoint(data, endpoint);
7
+ const screenshot = storyPage?.screenshots[0];
8
+ const stats = getFlowStoryStats(flow);
9
+ const replayStepLabels = buildReplayStepLabels(flow);
10
+ const primaryApiCall = storyPage?.apiCalls.find((apiCall) => apiCall.endpointId === endpoint?.id);
11
+ return (_jsxs("main", { className: "anlyx-flow-story", children: [_jsxs("header", { className: "anlyx-flow-story__header", children: [_jsxs("div", { children: [_jsx("p", { className: "anlyx-eyebrow", children: "Flow Story" }), _jsx("h1", { children: endpoint ? titleForEndpoint(endpoint) : "Application flow story" }), _jsxs("div", { className: "anlyx-flow-story__summary", "aria-label": "Flow Story summary", children: [_jsxs("span", { children: [stats.mainSteps, " main steps"] }), _jsxs("span", { children: [stats.supportCalls, " support calls"] }), _jsxs("span", { children: [stats.evidenceCount, " evidence items"] })] })] }), _jsxs("div", { className: "anlyx-flow-story__actions", children: [_jsx(StatusBadge, { tone: "neutral", children: "Replay Lite" }), _jsxs("button", { className: "anlyx-toolbar-button", type: "button", children: [_jsx(Maximize2, { size: 14, strokeWidth: 2.4 }), "Fit view"] })] })] }), _jsx(InteractionEvidenceChain, { apiCallLabel: formatObservedApiCall(primaryApiCall, endpoint), backendStepCount: stats.mainSteps, pageRoute: storyPage?.route }), _jsxs("section", { className: "anlyx-flow-story__stage", "aria-label": "Flow Story canvas", children: [_jsx(PagePreviewCard, { page: storyPage }), _jsxs("div", { className: "anlyx-flow-story__request", "aria-hidden": "true", children: [_jsx("span", { children: "Request" }), _jsx("i", {})] }), _jsx(FlowStoryDiagram, { flow: flow, replayState: replayState, selectedNodeId: selectedNodeId, onSelectNode: onSelectNode }), _jsx("div", { className: "anlyx-flow-story__response", "aria-hidden": "true", children: _jsx("span", { children: "Response" }) })] }), _jsx(ReplayControls, { disabled: replayDisabled, loop: replayLoop, speed: replaySpeed, state: replayState, stepLabels: replayStepLabels, steps: replaySteps, unavailableReason: "Replay is unavailable because this flow has no scanned main path.", onPause: onPause, onPlay: onPlay, onRestart: onRestart, onSpeedChange: onSpeedChange, onToggleLoop: onToggleLoop }), screenshot?.path ? _jsx("span", { className: "anlyx-sr-only", children: screenshot.path }) : null] }));
12
+ }
13
+ function InteractionEvidenceChain({ apiCallLabel, backendStepCount, pageRoute }) {
14
+ return (_jsxs("section", { className: "anlyx-interaction-chain", "aria-label": "Interaction evidence chain", children: [_jsx(EvidenceChainItem, { detail: pageRoute ?? "No page linked", icon: MousePointerClick, label: "Triggered page", tone: "page" }), _jsx(EvidenceChainItem, { detail: apiCallLabel, icon: Wifi, label: "Browser API event", tone: "api" }), _jsx(EvidenceChainItem, { detail: `${backendStepCount} steps`, icon: Route, label: "Scanned backend path", tone: "backend" }), _jsx(EvidenceChainItem, { detail: "not runtime tracing", icon: ShieldCheck, label: "Static evidence", tone: "guard" })] }));
15
+ }
16
+ function EvidenceChainItem({ detail, icon: Icon, label, tone }) {
17
+ return (_jsxs("article", { className: `anlyx-interaction-chain__item anlyx-interaction-chain__item--${tone}`, children: [_jsx("span", { className: "anlyx-interaction-chain__icon", "aria-hidden": "true", children: _jsx(Icon, { size: 16, strokeWidth: 2.5 }) }), _jsxs("div", { children: [_jsx("span", { children: label }), _jsx("strong", { children: detail })] })] }));
18
+ }
19
+ function PagePreviewCard({ page }) {
20
+ const screenshot = page?.screenshots[0];
21
+ const primaryApiCall = page?.apiCalls[0];
22
+ return (_jsxs("article", { className: "anlyx-page-preview", "aria-label": "Frontend page preview", children: [_jsxs("div", { className: "anlyx-page-preview__chrome", children: [_jsx(MonitorSmartphone, { size: 16, strokeWidth: 2.4 }), _jsx("span", { children: page?.route ?? "No page linked" })] }), _jsxs("div", { className: "anlyx-page-preview__screen", children: [_jsxs("div", { className: "anlyx-page-preview__topbar", children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {}), _jsx("strong", { children: "STARBUCKS" })] }), _jsxs("div", { className: "anlyx-page-preview__hero", children: [_jsxs("div", { children: [_jsx("span", { children: screenshot?.title ?? "Captured page" }), _jsx("strong", { children: "Birthday Reward" }), _jsx("p", { children: "Enjoy a free drink or food item on your birthday." })] }), _jsxs("div", { className: "anlyx-page-preview__reward", "aria-hidden": "true", children: [_jsx("span", {}), _jsx("strong", { children: "1" })] })] }), _jsxs("div", { className: "anlyx-page-preview__facts", children: [_jsx("span", { children: "Valid Jan 1 - Dec 31" }), _jsx("span", { children: "Once per year" })] }), _jsxs("div", { className: "anlyx-page-preview__steps", children: [_jsx("span", { children: "Show this reward in store" }), _jsx("span", { children: "Choose drink or food" }), _jsx("span", { children: "Enjoy birthday treat" })] }), _jsxs("div", { className: "anlyx-page-preview__api", children: [_jsx("strong", { children: primaryApiCall?.method ?? "GET" }), _jsx("span", { children: primaryApiCall?.path ?? "/api/..." })] })] }), _jsxs("div", { className: "anlyx-page-preview__meta", children: [_jsx(StatusBadge, { tone: page?.captureStatus ?? "pending", children: page?.captureStatus ?? "pending" }), _jsxs("span", { children: [page?.apiCalls.length ?? 0, " API calls"] }), _jsxs("span", { children: [page?.screenshots.length ?? 0, " screenshots"] })] })] }));
23
+ }
24
+ function FlowStoryDiagram({ flow, replayState, selectedNodeId, onSelectNode }) {
25
+ if (!flow) {
26
+ return (_jsx("div", { className: "anlyx-flow-story__diagram anlyx-flow-story__diagram--empty", children: _jsx("p", { children: "No scanned backend flow available for this endpoint." }) }));
27
+ }
28
+ const nodesById = new Map(flow.nodes.map((node) => [node.id, node]));
29
+ const mainNodes = flow.mainPath
30
+ .map((nodeId) => nodesById.get(nodeId))
31
+ .filter((node) => Boolean(node))
32
+ .filter((node) => node.type !== "page");
33
+ const supportingNodes = flow.subFlows.flatMap((subFlow) => subFlow.nodes);
34
+ return (_jsxs("div", { className: "anlyx-flow-story__diagram", role: "region", "aria-label": "Flow Story path", children: [_jsxs("div", { className: "anlyx-flow-story__diagram-head", children: [_jsxs("div", { children: [_jsx("span", { children: "Main path" }), _jsxs("strong", { children: [mainNodes.length, " steps"] })] }), _jsxs("div", { children: [_jsx("span", { children: "Support" }), _jsxs("strong", { children: [supportingNodes.length, " calls"] })] })] }), _jsx("div", { className: "anlyx-flow-story__lane", "aria-label": "Main request path", children: mainNodes.map((node, index) => (_jsx(FlowStoryStep, { isActive: replayState.activeNodeId === node.id, isSelected: selectedNodeId === node.id, node: node, stepNumber: index + 1, showArrow: index < mainNodes.length - 1, onSelectNode: onSelectNode }, node.id))) }), supportingNodes.length > 0 ? (_jsxs("div", { className: "anlyx-flow-story__support", children: [_jsxs("div", { className: "anlyx-flow-story__support-heading", children: [_jsx(GitBranch, { size: 15, strokeWidth: 2.5 }), _jsx("span", { children: "Support calls from service" })] }), _jsx("div", { className: "anlyx-flow-story__support-grid", children: supportingNodes.map((node) => (_jsx(FlowStorySupportNode, { isActive: replayState.activeNodeId === node.id, isSelected: selectedNodeId === node.id, node: node, onSelectNode: onSelectNode }, node.id))) })] })) : null] }));
35
+ }
36
+ function FlowStoryStep({ node, isActive, isSelected, stepNumber, showArrow, onSelectNode }) {
37
+ const Icon = getFlowStoryIcon(node.type);
38
+ return (_jsxs("div", { className: "anlyx-flow-story__step-wrap", children: [_jsxs("button", { className: [
39
+ "anlyx-flow-story__step",
40
+ `anlyx-flow-story__step--${node.type}`,
41
+ isActive ? "anlyx-flow-story__step--active" : "",
42
+ isSelected ? "anlyx-flow-story__step--selected" : ""
43
+ ]
44
+ .filter(Boolean)
45
+ .join(" "), type: "button", onClick: () => onSelectNode(node), "aria-label": `Select ${node.type} step ${stepNumber}: ${node.label}`, children: [_jsx("span", { className: "anlyx-flow-story__step-number", children: String(stepNumber).padStart(2, "0") }), _jsx("span", { className: "anlyx-flow-story__step-icon", "aria-hidden": "true", children: _jsx(Icon, { size: 16, strokeWidth: 2.5 }) }), _jsx("span", { className: "anlyx-flow-story__step-type", children: node.type }), _jsx("strong", { children: node.label }), _jsx(StatusBadge, { tone: node.confidence ?? "unknown", label: "confidence", children: node.confidence ?? "unknown" })] }), showArrow ? _jsx("span", { className: "anlyx-flow-story__arrow", "aria-hidden": "true" }) : null] }));
46
+ }
47
+ function FlowStorySupportNode({ node, isActive, isSelected, onSelectNode }) {
48
+ const Icon = getFlowStoryIcon(node.type);
49
+ return (_jsxs("button", { className: [
50
+ "anlyx-flow-story__support-node",
51
+ isActive ? "anlyx-flow-story__support-node--active" : "",
52
+ isSelected ? "anlyx-flow-story__support-node--selected" : ""
53
+ ]
54
+ .filter(Boolean)
55
+ .join(" "), type: "button", onClick: () => onSelectNode(node), "aria-label": `Select support call ${node.label}`, children: [_jsx(Icon, { size: 15, strokeWidth: 2.5 }), _jsx("span", { children: node.type }), _jsx("strong", { children: node.label }), _jsx(StatusBadge, { tone: node.confidence ?? "unknown", label: "confidence", children: node.confidence ?? "unknown" })] }));
56
+ }
57
+ function findPageForEndpoint(data, endpoint) {
58
+ if (!endpoint) {
59
+ return data.pages[0];
60
+ }
61
+ return (data.pages.find((page) => page.apiCalls.some((apiCall) => apiCall.endpointId === endpoint.id)) ?? data.pages[0]);
62
+ }
63
+ function titleForEndpoint(endpoint) {
64
+ const handler = endpoint.controller && endpoint.handler
65
+ ? `${endpoint.controller}#${endpoint.handler}`
66
+ : undefined;
67
+ return handler ?? `${endpoint.method} ${endpoint.path}`;
68
+ }
69
+ function formatObservedApiCall(apiCall, endpoint) {
70
+ if (apiCall) {
71
+ return `${apiCall.method} ${apiCall.path}`;
72
+ }
73
+ if (endpoint) {
74
+ return `${endpoint.method} ${endpoint.path}`;
75
+ }
76
+ return "No API event matched";
77
+ }
78
+ function getFlowStoryStats(flow) {
79
+ if (!flow) {
80
+ return { evidenceCount: 0, mainSteps: 0, supportCalls: 0 };
81
+ }
82
+ return {
83
+ mainSteps: flow.mainPath.filter((nodeId) => !nodeId.startsWith("page:")).length,
84
+ supportCalls: flow.subFlows.reduce((count, subFlow) => count + subFlow.nodes.length, 0),
85
+ evidenceCount: flow.nodes.reduce((count, node) => count + (node.evidence?.length ?? 0), 0) +
86
+ flow.edges.reduce((count, edge) => count + (edge.evidence?.length ?? 0), 0) +
87
+ flow.subFlows.reduce((count, subFlow) => count +
88
+ subFlow.nodes.reduce((nodeCount, node) => nodeCount + (node.evidence?.length ?? 0), 0) +
89
+ subFlow.edges.reduce((edgeCount, edge) => edgeCount + (edge.evidence?.length ?? 0), 0), 0)
90
+ };
91
+ }
92
+ function buildReplayStepLabels(flow) {
93
+ if (!flow) {
94
+ return {};
95
+ }
96
+ return Object.fromEntries(flow.nodes.map((node) => [node.id, node.label]));
97
+ }
98
+ function getFlowStoryIcon(type) {
99
+ switch (type) {
100
+ case "endpoint":
101
+ return Globe2;
102
+ case "controller":
103
+ return Code2;
104
+ case "service":
105
+ return Layers3;
106
+ case "repository":
107
+ return Braces;
108
+ case "database":
109
+ return Database;
110
+ case "mapper":
111
+ case "validator":
112
+ case "utility":
113
+ return GitBranch;
114
+ default:
115
+ return FileText;
116
+ }
117
+ }
@@ -1,9 +1,14 @@
1
- import type { EndpointFlow, FlowNode, ScanResult } from "@anlyx/core";
1
+ import type { EndpointFlow, FlowNode, PageStoryboard, ScanResult } from "@anlyx/core";
2
+ import type { ReplayLiteState } from "../replay/use-replay-lite.js";
2
3
  type InspectorPanelProps = {
3
4
  data: ScanResult;
5
+ activeView: "flowStory" | "structure" | "frontend" | "process";
6
+ collapsed: boolean;
4
7
  selectedFlow: EndpointFlow | undefined;
5
8
  selectedNode: FlowNode | undefined;
9
+ selectedPage: PageStoryboard | undefined;
10
+ replayState: ReplayLiteState;
11
+ onToggleCollapsed: () => void;
6
12
  };
7
- export declare function InspectorPanel({ data, selectedFlow, selectedNode }: InspectorPanelProps): JSX.Element;
13
+ export declare function InspectorPanel({ data, activeView, collapsed, selectedFlow, selectedNode, selectedPage, replayState, onToggleCollapsed }: InspectorPanelProps): JSX.Element;
8
14
  export {};
9
- //# sourceMappingURL=InspectorPanel.d.ts.map
@@ -1,8 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { AnalysisEvidenceList } from "./AnalysisEvidenceList.js";
2
3
  import { StatusBadge } from "./StatusBadge.js";
3
- export function InspectorPanel({ data, selectedFlow, selectedNode }) {
4
+ export function InspectorPanel({ data, activeView, collapsed, selectedFlow, selectedNode, selectedPage, replayState, onToggleCollapsed }) {
5
+ if (collapsed) {
6
+ return (_jsxs("aside", { className: "anlyx-inspector anlyx-inspector--collapsed", role: "complementary", "aria-label": "Inspector", children: [_jsx("button", { className: "anlyx-panel-toggle", type: "button", "aria-label": "Expand inspector panel", onClick: onToggleCollapsed, children: "Open" }), _jsx("span", { className: "anlyx-collapsed-label", children: "Inspector" })] }));
7
+ }
8
+ if (activeView === "frontend") {
9
+ return (_jsxs("aside", { className: "anlyx-inspector", role: "complementary", "aria-label": "Inspector", children: [_jsxs("div", { className: "anlyx-panel-heading", children: [_jsxs("div", { children: [_jsx("p", { className: "anlyx-eyebrow", children: "Inspector" }), _jsx("h2", { children: "Frontend Page" })] }), _jsx("button", { className: "anlyx-panel-toggle", type: "button", "aria-label": "Collapse inspector panel", onClick: onToggleCollapsed, children: "Collapse" })] }), selectedPage ? (_jsxs("div", { className: "anlyx-inspector-stack", children: [_jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Details", children: [_jsx("h3", { children: "Details" }), _jsx(Field, { label: "Route", value: selectedPage.route }), _jsx(Field, { label: "File path", value: selectedPage.filePath ?? "Manual or unknown" }), _jsxs("div", { className: "anlyx-field", children: [_jsx("span", { className: "anlyx-field__label", children: "Capture status" }), _jsx(StatusBadge, { tone: selectedPage.captureStatus, children: selectedPage.captureStatus })] }), _jsx(Field, { label: "Screenshots", value: String(selectedPage.screenshots.length) }), _jsx(Field, { label: "API calls", value: String(selectedPage.apiCalls.length) })] }), selectedPage.errorMessage ? (_jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Capture error", children: [_jsx("h3", { children: "Capture error" }), _jsx("p", { children: selectedPage.errorMessage })] })) : null] })) : (_jsx("p", { className: "anlyx-empty", children: "No page selected" }))] }));
10
+ }
4
11
  const linkedPages = selectedNode ? findLinkedPages(data, selectedNode.id) : [];
5
- return (_jsxs("aside", { className: "anlyx-inspector", role: "complementary", "aria-label": "Inspector", children: [_jsxs("div", { className: "anlyx-panel-heading", children: [_jsx("p", { className: "anlyx-eyebrow", children: "Inspector" }), _jsx("h2", { children: "Selected Node" })] }), selectedNode ? (_jsxs("div", { className: "anlyx-inspector-stack", children: [_jsx(Field, { label: "Type", value: selectedNode.type }), _jsx(Field, { label: "Label", value: selectedNode.label }), _jsx(Field, { label: "File path", value: selectedNode.filePath ?? "Unknown" }), _jsx(Field, { label: "Line number", value: formatLineNumber(selectedNode.lineNumber) }), selectedNode.metadata ? (_jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Metadata", children: [_jsx("h3", { children: "Metadata" }), _jsx("pre", { className: "anlyx-metadata", children: JSON.stringify(selectedNode.metadata, null, 2) })] })) : null, _jsxs("div", { className: "anlyx-field", children: [_jsx("span", { className: "anlyx-field__label", children: "Confidence" }), _jsx(StatusBadge, { tone: selectedNode.confidence ?? "unknown", label: "confidence", children: selectedNode.confidence ?? "unknown" })] }), _jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Linked pages", children: [_jsx("h3", { children: "Linked pages" }), linkedPages.length > 0 ? (_jsx("ul", { children: linkedPages.map((page) => (_jsx("li", { children: page.route }, page.id))) })) : (_jsx("p", { children: "None" }))] }), _jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Sub flows", children: [_jsx("h3", { children: "Sub flows" }), _jsxs("p", { children: [selectedFlow?.subFlows.length ?? 0, " collapsed"] })] }), _jsxs("section", { className: "anlyx-inspector-group", "aria-label": "DB tables", children: [_jsx("h3", { children: "DB tables" }), _jsx("p", { children: findDatabaseLabel(selectedFlow) ?? "None" })] })] })) : (_jsx("p", { className: "anlyx-empty", children: "No node selected" }))] }));
12
+ const calls = selectedNode ? findCalls(selectedFlow, selectedNode.id) : [];
13
+ return (_jsxs("aside", { className: "anlyx-inspector", role: "complementary", "aria-label": "Inspector", children: [_jsxs("div", { className: "anlyx-panel-heading", children: [_jsxs("div", { children: [_jsx("p", { className: "anlyx-eyebrow", children: "Inspector" }), _jsx("h2", { children: activeView === "process" ? "Process Step" : "Flow Evidence" })] }), _jsx("button", { className: "anlyx-panel-toggle", type: "button", "aria-label": "Collapse inspector panel", onClick: onToggleCollapsed, children: "Collapse" })] }), selectedNode ? (_jsxs("div", { className: "anlyx-inspector-stack", children: [activeView === "process" ? (_jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Replay state", children: [_jsx("h3", { children: "Process replay" }), _jsx(Field, { label: "Active Step", value: replayState.phase }), _jsx(Field, { label: "Step", value: String(replayState.currentStepIndex + 1) }), _jsx(Field, { label: "Active Node", value: replayState.activeNodeId ?? "none" }), _jsx(Field, { label: "Active Edge", value: formatActiveEdge(replayState) }), _jsx("p", { className: "anlyx-inspector-note", children: "Source: scanned static flow graph" })] })) : null, _jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Details", children: [_jsx("h3", { children: "Details" }), _jsx(Field, { label: "Type", value: selectedNode.type }), _jsx(Field, { label: "Label", value: selectedNode.label }), _jsx(Field, { label: "File path", value: selectedNode.filePath ?? "Unknown" }), _jsx(Field, { label: "Line number", value: formatLineNumber(selectedNode.lineNumber) })] }), _jsx(AnalysisEvidenceList, { node: selectedNode }), _jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Calls", children: [_jsx("h3", { children: "Calls" }), calls.length > 0 ? (_jsx("ul", { className: "anlyx-call-list", children: calls.map((call) => (_jsxs("li", { children: [_jsx("span", { children: call.label }), _jsx(StatusBadge, { tone: call.confidence, children: call.confidence })] }, call.id))) })) : (_jsx("p", { children: "No outgoing calls detected for this node." }))] }), selectedNode.metadata ? (_jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Metadata", children: [_jsxs("div", { className: "anlyx-inspector-group__heading", children: [_jsx("h3", { children: "Metadata" }), _jsx("button", { className: "anlyx-copy-button", type: "button", onClick: () => copyToClipboard(JSON.stringify(selectedNode.metadata, null, 2)), children: "Copy" })] }), _jsx("pre", { className: "anlyx-metadata", children: JSON.stringify(selectedNode.metadata, null, 2) })] })) : null, _jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Confidence", children: [_jsx("h3", { children: "Confidence" }), _jsx(StatusBadge, { tone: selectedNode.confidence ?? "unknown", label: "confidence", children: selectedNode.confidence ?? "unknown" })] }), _jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Linked pages", children: [_jsx("h3", { children: "Linked pages" }), linkedPages.length > 0 ? (_jsx("ul", { children: linkedPages.map((page) => (_jsx("li", { children: page.route }, page.id))) })) : (_jsx("p", { children: "None" }))] }), _jsxs("section", { className: "anlyx-inspector-group", "aria-label": "Sub flows", children: [_jsx("h3", { children: "Sub flows" }), _jsxs("p", { children: [selectedFlow?.subFlows.length ?? 0, " collapsed"] })] }), _jsxs("section", { className: "anlyx-inspector-group", "aria-label": "DB tables", children: [_jsx("h3", { children: "DB tables" }), _jsx("p", { children: findDatabaseLabel(selectedFlow) ?? "None" })] })] })) : (_jsx("p", { className: "anlyx-empty", children: "No node selected" }))] }));
6
14
  }
7
15
  function Field({ label, value }) {
8
16
  return (_jsxs("div", { className: "anlyx-field", children: [_jsx("span", { className: "anlyx-field__label", children: label }), _jsx("span", { className: "anlyx-field__value", children: value })] }));
@@ -10,10 +18,35 @@ function Field({ label, value }) {
10
18
  function formatLineNumber(lineNumber) {
11
19
  return lineNumber === undefined ? "Unknown" : String(lineNumber);
12
20
  }
21
+ function formatActiveEdge(replayState) {
22
+ if (!replayState.activeEdge) {
23
+ return "none";
24
+ }
25
+ return `${replayState.activeEdge.from} -> ${replayState.activeEdge.to}`;
26
+ }
27
+ function copyToClipboard(value) {
28
+ void navigator.clipboard?.writeText(value);
29
+ }
13
30
  function findLinkedPages(data, nodeId) {
14
31
  return data.pages.filter((page) => page.apiCalls.some((apiCall) => apiCall.endpointId === nodeId));
15
32
  }
16
33
  function findDatabaseLabel(flow) {
17
34
  return flow?.nodes.find((node) => node.type === "database")?.label;
18
35
  }
19
- //# sourceMappingURL=InspectorPanel.js.map
36
+ function findCalls(flow, nodeId) {
37
+ if (!flow) {
38
+ return [];
39
+ }
40
+ const allNodes = [...flow.nodes, ...flow.subFlows.flatMap((subFlow) => subFlow.nodes)];
41
+ const allEdges = [...flow.edges, ...flow.subFlows.flatMap((subFlow) => subFlow.edges)];
42
+ return allEdges
43
+ .filter((edge) => edge.from === nodeId)
44
+ .map((edge) => {
45
+ const target = allNodes.find((node) => node.id === edge.to);
46
+ return {
47
+ id: edge.id,
48
+ label: target?.label ?? edge.to,
49
+ confidence: edge.confidence ?? "unknown"
50
+ };
51
+ });
52
+ }
@@ -6,4 +6,3 @@ type PageListProps = {
6
6
  };
7
7
  export declare function PageList({ pages, selectedPageId, onSelectPage }: PageListProps): JSX.Element;
8
8
  export {};
9
- //# sourceMappingURL=PageList.d.ts.map
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { StatusBadge } from "./StatusBadge.js";
3
3
  export function PageList({ pages, selectedPageId, onSelectPage }) {
4
- return (_jsxs("section", { className: "anlyx-sidebar-section", "aria-labelledby": "anlyx-pages-heading", children: [_jsx("div", { className: "anlyx-section-heading", id: "anlyx-pages-heading", children: "Pages" }), _jsx("ul", { className: "anlyx-list", "aria-label": "Page list", children: pages.map((page) => (_jsx("li", { className: "anlyx-list-item", children: _jsxs("button", { className: "anlyx-page-button", type: "button", "aria-current": page.id === selectedPageId ? "true" : undefined, "aria-label": `${page.route} ${page.captureStatus} ${page.apiCalls.length} API calls ${page.screenshots.length} screenshots`, onClick: () => onSelectPage(page), children: [_jsx("span", { className: "anlyx-list-item__line", children: _jsx("span", { className: "anlyx-list-item__primary", children: page.route }) }), _jsxs("span", { className: "anlyx-list-item__meta", children: [_jsx(StatusBadge, { tone: page.captureStatus, children: page.captureStatus }), _jsxs("span", { children: [page.apiCalls.length, " API calls"] }), _jsxs("span", { children: [page.screenshots.length, " screenshots"] })] }), page.errorMessage ? (_jsx("span", { className: "anlyx-list-item__meta", children: page.errorMessage })) : null] }) }, page.id))) })] }));
4
+ return (_jsxs("section", { className: "anlyx-sidebar-section", "aria-labelledby": "anlyx-pages-heading", children: [_jsx("div", { className: "anlyx-section-heading", id: "anlyx-pages-heading", children: "Frontend Pages" }), _jsx("ul", { className: "anlyx-list", "aria-label": "Page list", children: pages.map((page) => (_jsx("li", { className: "anlyx-list-item", children: _jsxs("button", { className: "anlyx-page-button", type: "button", "aria-current": page.id === selectedPageId ? "true" : undefined, "aria-label": `${page.route} ${page.captureStatus} ${page.apiCalls.length} API calls ${page.screenshots.length} screenshots`, onClick: () => onSelectPage(page), children: [_jsx("span", { className: "anlyx-list-item__line", children: _jsx("span", { className: "anlyx-list-item__primary", children: page.route }) }), _jsxs("span", { className: "anlyx-list-item__meta", children: [_jsx(StatusBadge, { tone: page.captureStatus, children: page.captureStatus }), _jsxs("span", { children: [page.apiCalls.length, " API calls"] }), _jsxs("span", { children: [page.screenshots.length, " screenshots"] })] }), page.errorMessage ? (_jsx("span", { className: "anlyx-list-item__meta", children: page.errorMessage })) : null] }) }, page.id))) })] }));
5
5
  }
6
- //# sourceMappingURL=PageList.js.map
@@ -3,4 +3,3 @@ export type PageStoryboardCardProps = {
3
3
  page: PageStoryboard;
4
4
  };
5
5
  export declare function PageStoryboardCard({ page }: PageStoryboardCardProps): JSX.Element;
6
- //# sourceMappingURL=PageStoryboardCard.d.ts.map
@@ -1,6 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ScreenshotSegmentCard } from "./ScreenshotSegmentCard.js";
3
3
  export function PageStoryboardCard({ page }) {
4
- return (_jsxs("section", { className: "anlyx-storyboard-panel", "aria-label": "Screenshot segments", children: [_jsxs("div", { className: "anlyx-storyboard-section-heading", children: [_jsx("h2", { children: "Segments" }), _jsx("span", { children: page.screenshots.length })] }), page.screenshots.length > 0 ? (_jsx("div", { className: "anlyx-segment-grid", children: page.screenshots.map((segment) => (_jsx(ScreenshotSegmentCard, { segment: segment }, `${page.id}:segment:${segment.segmentIndex}`))) })) : (_jsx("p", { className: "anlyx-empty-inline", children: "No screenshots captured yet." }))] }));
4
+ return (_jsxs("section", { className: "anlyx-storyboard-panel", "aria-label": "Screenshot segments", children: [_jsxs("div", { className: "anlyx-storyboard-section-heading", children: [_jsx("h2", { children: "Segments" }), _jsx("span", { children: page.screenshots.length })] }), page.screenshots.length > 0 ? (_jsx("div", { className: "anlyx-segment-grid", children: page.screenshots.map((segment) => (_jsx(ScreenshotSegmentCard, { segment: segment }, `${page.id}:segment:${segment.segmentIndex}`))) })) : (_jsxs("div", { className: "anlyx-segment-grid anlyx-segment-grid--empty", children: [_jsx(PlaceholderSegment, { index: 1, title: "Overview" }), _jsx(PlaceholderSegment, { index: 2, title: "Primary content" }), _jsx(PlaceholderSegment, { index: 3, title: "Related sections" })] }))] }));
5
+ }
6
+ function PlaceholderSegment({ index, title }) {
7
+ return (_jsxs("article", { className: "anlyx-segment-card anlyx-segment-card--placeholder", children: [_jsx("div", { className: "anlyx-segment-card__image", "aria-hidden": "true", children: _jsx("span", { children: index }) }), _jsxs("div", { className: "anlyx-segment-card__body", children: [_jsx("h3", { children: title }), _jsx("p", { children: "Waiting for capture data" }), _jsxs("div", { className: "anlyx-segment-card__meta", children: [_jsx("span", { children: "Viewport pending" }), _jsx("span", { children: "Capture pending" })] })] })] }));
5
8
  }
6
- //# sourceMappingURL=PageStoryboardCard.js.map
@@ -1,6 +1,7 @@
1
- import type { PageStoryboard } from "@anlyx/core";
1
+ import type { PageStoryboard, ScanResult } from "@anlyx/core";
2
2
  export type PageStoryboardViewProps = {
3
+ data: ScanResult;
3
4
  page: PageStoryboard | undefined;
5
+ onViewProcessFlow: (view: "process") => void;
4
6
  };
5
- export declare function PageStoryboardView({ page }: PageStoryboardViewProps): JSX.Element;
6
- //# sourceMappingURL=PageStoryboardView.d.ts.map
7
+ export declare function PageStoryboardView({ data, page, onViewProcessFlow }: PageStoryboardViewProps): JSX.Element;
@@ -3,7 +3,17 @@ import { ApiCallList } from "./ApiCallList.js";
3
3
  import { CaptureStatusEmptyState } from "./CaptureStatusEmptyState.js";
4
4
  import { PageStoryboardCard } from "./PageStoryboardCard.js";
5
5
  import { StatusBadge } from "./StatusBadge.js";
6
- export function PageStoryboardView({ page }) {
7
- return (_jsxs("main", { className: "anlyx-workspace", children: [_jsxs("header", { className: "anlyx-workspace-header", children: [_jsxs("div", { children: [_jsx("p", { className: "anlyx-eyebrow", children: "Page Storyboard" }), _jsx("h1", { children: "Page Storyboard" })] }), page ? _jsx(StatusBadge, { tone: page.captureStatus, children: page.captureStatus }) : null] }), _jsx("section", { className: "anlyx-page-storyboard", role: "region", "aria-label": "Page Storyboard", children: page ? (_jsxs(_Fragment, { children: [_jsxs("section", { className: "anlyx-page-summary", "aria-label": "Selected page summary", children: [_jsxs("div", { children: [_jsx("span", { className: "anlyx-field__label", children: "Route" }), _jsx("h2", { children: page.route })] }), _jsxs("div", { children: [_jsx("span", { className: "anlyx-field__label", children: "File" }), _jsx("p", { children: page.filePath ?? "Unknown" })] }), _jsxs("div", { children: [_jsx("span", { className: "anlyx-field__label", children: "Status" }), _jsx(StatusBadge, { tone: page.captureStatus, children: page.captureStatus })] })] }), _jsx(CaptureStatusEmptyState, { status: page.captureStatus, ...(page.errorMessage ? { reason: page.errorMessage } : {}) }), _jsxs("div", { className: "anlyx-storyboard-grid", children: [_jsx(PageStoryboardCard, { page: page }), _jsx(ApiCallList, { apiCalls: page.apiCalls })] })] })) : (_jsx("div", { className: "anlyx-storyboard-empty", children: _jsx("p", { children: "No pages available yet." }) })) })] }));
6
+ export function PageStoryboardView({ data, page, onViewProcessFlow }) {
7
+ const linkedEndpoints = page
8
+ ? data.endpoints.filter((endpoint) => page.apiCalls.some((apiCall) => apiCall.endpointId === endpoint.id))
9
+ : [];
10
+ const linkedApiCallCount = page?.apiCalls.filter((apiCall) => apiCall.endpointId).length ?? 0;
11
+ const unmatchedApiCallCount = page ? page.apiCalls.length - linkedApiCallCount : 0;
12
+ return (_jsxs("main", { className: "anlyx-workspace", children: [_jsxs("header", { className: "anlyx-workspace-header", children: [_jsxs("div", { children: [_jsx("p", { className: "anlyx-eyebrow", children: "Connected Frontend" }), _jsx("h1", { children: page ? page.route : "Page Storyboard" })] }), _jsxs("div", { className: "anlyx-workspace-actions", children: [_jsx("button", { className: "anlyx-toolbar-button", type: "button", disabled: linkedEndpoints.length === 0, onClick: () => onViewProcessFlow("process"), children: "View Process Flow" }), page ? _jsx(StatusBadge, { tone: page.captureStatus, children: page.captureStatus }) : null] })] }), _jsx("section", { className: "anlyx-page-storyboard", role: "region", "aria-label": "Page Storyboard", children: page ? (_jsxs(_Fragment, { children: [_jsxs("section", { className: "anlyx-page-summary", "aria-label": "Selected page summary", children: [_jsxs("div", { children: [_jsx("span", { className: "anlyx-field__label", children: "Route" }), _jsx("h2", { children: page.route })] }), _jsxs("div", { children: [_jsx("span", { className: "anlyx-field__label", children: "File" }), _jsx("p", { children: page.filePath ?? "Unknown" })] }), _jsxs("div", { children: [_jsx("span", { className: "anlyx-field__label", children: "Status" }), _jsx(StatusBadge, { tone: page.captureStatus, children: page.captureStatus })] }), _jsxs("div", { children: [_jsx("span", { className: "anlyx-field__label", children: "Linked endpoints" }), _jsx("p", { children: linkedEndpoints.length })] })] }), _jsx(CaptureStatusEmptyState, { status: page.captureStatus, ...(page.errorMessage ? { reason: page.errorMessage } : {}) }), _jsx(PageEvidenceBoard, { linkedApiCallCount: linkedApiCallCount, linkedEndpointCount: linkedEndpoints.length, page: page, unmatchedApiCallCount: unmatchedApiCallCount }), _jsxs("div", { className: "anlyx-storyboard-grid", children: [_jsx(PageStoryboardCard, { page: page }), _jsxs("div", { className: "anlyx-storyboard-side", children: [_jsx(ApiCallList, { apiCalls: page.apiCalls, endpoints: data.endpoints }), _jsxs("section", { className: "anlyx-storyboard-panel", "aria-label": "Page to endpoint relationship", children: [_jsxs("div", { className: "anlyx-storyboard-section-heading", children: [_jsx("h2", { children: "Page to Endpoint" }), _jsx("span", { children: linkedEndpoints.length })] }), linkedEndpoints.length > 0 ? (_jsxs("div", { className: "anlyx-relationship-diagram", children: [_jsxs("div", { className: "anlyx-relationship-source", children: [_jsx("strong", { children: page.route }), _jsx("span", { children: "Frontend Page" })] }), _jsx("ul", { className: "anlyx-relationship-list", children: linkedEndpoints.map((endpoint) => (_jsxs("li", { children: [_jsx("span", { className: "anlyx-relationship-line", "aria-hidden": "true" }), _jsx(StatusBadge, { tone: endpoint.method, children: endpoint.method }), _jsx("span", { children: endpoint.path })] }, endpoint.id))) })] })) : (_jsx("p", { className: "anlyx-empty-inline", children: "No backend endpoint was linked during capture." }))] })] })] })] })) : (_jsx("div", { className: "anlyx-storyboard-empty", children: _jsx("p", { children: "No pages available yet." }) })) })] }));
13
+ }
14
+ function PageEvidenceBoard({ linkedApiCallCount, linkedEndpointCount, page, unmatchedApiCallCount }) {
15
+ return (_jsxs("section", { className: "anlyx-page-evidence-board", role: "region", "aria-label": "Page execution evidence", children: [_jsxs("div", { className: "anlyx-page-evidence-board__intro", children: [_jsx("span", { children: "Capture proof" }), _jsx("strong", { children: page.captureStatus === "success" ? "Observed page run" : "Incomplete page run" })] }), _jsx(EvidenceMetric, { label: "Screenshots", value: String(page.screenshots.length), detail: page.screenshots.length > 0 ? "visual segments captured" : "waiting for capture" }), _jsx(EvidenceMetric, { label: "API evidence", value: String(page.apiCalls.length), detail: `${linkedApiCallCount} linked` }), _jsx(EvidenceMetric, { label: "Backend linkage", value: String(linkedEndpointCount), detail: `${unmatchedApiCallCount} unmatched` })] }));
16
+ }
17
+ function EvidenceMetric({ detail, label, value }) {
18
+ return (_jsxs("div", { className: "anlyx-page-evidence-metric", children: [_jsx("span", { children: label }), _jsx("strong", { children: value }), _jsx("em", { children: detail })] }));
8
19
  }
9
- //# sourceMappingURL=PageStoryboardView.js.map
@@ -0,0 +1,21 @@
1
+ import type { Endpoint, EndpointFlow, FlowNode } from "@anlyx/core";
2
+ import type { ReplayLiteState } from "../replay/use-replay-lite.js";
3
+ import type { ReplayStep } from "../replay/build-replay-steps.js";
4
+ export type ProcessFlowViewProps = {
5
+ endpoint: Endpoint | undefined;
6
+ flow: EndpointFlow | undefined;
7
+ replayState: ReplayLiteState;
8
+ replaySteps: ReplayStep[];
9
+ replayLoop: boolean;
10
+ replayDisabled: boolean;
11
+ replaySpeed: number;
12
+ selectedNodeId: string | undefined;
13
+ onSelectNode: (node: FlowNode) => void;
14
+ onPause: () => void;
15
+ onPlay: () => void;
16
+ onRestart: () => void;
17
+ onToggleLoop: () => void;
18
+ onSpeedChange: (speed: number) => void;
19
+ onViewStructure: () => void;
20
+ };
21
+ export declare function ProcessFlowView({ endpoint, flow, replayState, replaySteps, replayLoop, replayDisabled, replaySpeed, selectedNodeId, onSelectNode, onPause, onPlay, onRestart, onToggleLoop, onSpeedChange, onViewStructure }: ProcessFlowViewProps): JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { EndpointMapCanvas } from "./EndpointMapCanvas.js";
3
+ import { ProcessTimeline } from "./ProcessTimeline.js";
4
+ import { ReplayControls } from "./ReplayControls.js";
5
+ export function ProcessFlowView({ endpoint, flow, replayState, replaySteps, replayLoop, replayDisabled, replaySpeed, selectedNodeId, onSelectNode, onPause, onPlay, onRestart, onToggleLoop, onSpeedChange, onViewStructure }) {
6
+ const replayStepLabels = buildReplayStepLabels(flow);
7
+ return (_jsxs("div", { className: "anlyx-process-view", children: [_jsx(ReplayControls, { disabled: replayDisabled, loop: replayLoop, speed: replaySpeed, state: replayState, stepLabels: replayStepLabels, steps: replaySteps, unavailableReason: "Process Flow is unavailable because this endpoint has no scanned main path.", onPause: onPause, onPlay: onPlay, onRestart: onRestart, onSpeedChange: onSpeedChange, onToggleLoop: onToggleLoop }), _jsx(EndpointMapCanvas, { eyebrow: "Request Process Flow", endpoint: endpoint, flow: flow, replayState: replayState, selectedNodeId: selectedNodeId, title: endpoint
8
+ ? `${endpoint.method} ${endpoint.path}`
9
+ : "Request process flow from scanned graph", toolbar: _jsx("button", { className: "anlyx-toolbar-button", type: "button", onClick: onViewStructure, children: "View on Structure" }), variant: "process", onSelectNode: onSelectNode }), _jsx(ProcessTimeline, { flow: flow, state: replayState, steps: replaySteps })] }));
10
+ }
11
+ function buildReplayStepLabels(flow) {
12
+ if (!flow) {
13
+ return {};
14
+ }
15
+ return Object.fromEntries(flow.nodes.map((node) => [node.id, node.label]));
16
+ }
@@ -0,0 +1,9 @@
1
+ import type { EndpointFlow } from "@anlyx/core";
2
+ import type { ReplayStep } from "../replay/build-replay-steps.js";
3
+ import type { ReplayLiteState } from "../replay/use-replay-lite.js";
4
+ export type ProcessTimelineProps = {
5
+ flow: EndpointFlow | undefined;
6
+ steps: ReplayStep[];
7
+ state: ReplayLiteState;
8
+ };
9
+ export declare function ProcessTimeline({ flow, steps, state }: ProcessTimelineProps): JSX.Element;
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Check } from "lucide-react";
3
+ import { motion } from "motion/react";
4
+ export function ProcessTimeline({ flow, steps, state }) {
5
+ const nodeById = new Map(flow?.nodes.map((node) => [node.id, node]) ?? []);
6
+ const isComplete = state.phase === "complete";
7
+ return (_jsxs("section", { className: "anlyx-process-timeline", "aria-label": "Process Flow timeline", children: [_jsxs("div", { className: "anlyx-process-timeline__header", children: [_jsx("span", { children: "Inferred request path" }), _jsxs("span", { children: [steps.length, " replay steps"] })] }), _jsxs("ol", { className: "anlyx-process-timeline__rail", children: [steps.map((step, index) => {
8
+ const node = nodeById.get(step.nodeId);
9
+ const isActive = state.phase !== "idle" &&
10
+ state.phase !== "complete" &&
11
+ state.currentStepIndex === index;
12
+ const isCompleted = state.phase === "complete" ||
13
+ (state.phase !== "idle" && state.currentStepIndex > index);
14
+ return (_jsxs("li", { className: [
15
+ "anlyx-process-step",
16
+ `anlyx-process-step--${step.phase}`,
17
+ isActive ? "anlyx-process-step--active" : "",
18
+ isCompleted ? "anlyx-process-step--complete" : ""
19
+ ]
20
+ .filter(Boolean)
21
+ .join(" "), children: [_jsx(motion.span, { animate: isActive ? { scale: [1, 1.18, 1] } : { scale: 1 }, className: "anlyx-process-step__dot", "aria-hidden": "true", transition: { duration: 1.1, repeat: isActive ? Infinity : 0 }, children: isCompleted ? _jsx(Check, { size: 11, strokeWidth: 3 }) : null }), _jsx("span", { className: "anlyx-process-step__phase", children: step.phase === "request" ? "Request" : "Response" }), _jsx("span", { className: "anlyx-process-step__label", children: formatStepLabel(node?.type, step.phase) }), _jsx("span", { className: "anlyx-process-step__node", children: node?.label ?? step.nodeId })] }, `${step.phase}:${step.nodeId}:${index}`));
22
+ }), _jsxs("li", { className: [
23
+ "anlyx-process-step",
24
+ "anlyx-process-step--complete-stop",
25
+ isComplete ? "anlyx-process-step--active" : ""
26
+ ]
27
+ .filter(Boolean)
28
+ .join(" "), children: [_jsx(motion.span, { animate: isComplete ? { scale: [1, 1.18, 1] } : { scale: 1 }, className: "anlyx-process-step__dot", "aria-hidden": "true", transition: { duration: 1.1, repeat: isComplete ? Infinity : 0 }, children: isComplete ? _jsx(Check, { size: 11, strokeWidth: 3 }) : null }), _jsx("span", { className: "anlyx-process-step__phase", children: "Complete" }), _jsx("span", { className: "anlyx-process-step__label", children: "Client" }), _jsx("span", { className: "anlyx-process-step__node", children: "Response delivered" })] })] })] }));
29
+ }
30
+ function formatStepLabel(type, phase) {
31
+ const suffix = phase === "response" ? " Return" : "";
32
+ switch (type) {
33
+ case "endpoint":
34
+ return phase === "response" ? "Endpoint Return" : "Endpoint";
35
+ case "controller":
36
+ return `Controller${suffix}`;
37
+ case "service":
38
+ return `Service${suffix}`;
39
+ case "repository":
40
+ return `Repository${suffix}`;
41
+ case "database":
42
+ return phase === "response" ? "Database Result" : "Database";
43
+ default:
44
+ return "Flow Node";
45
+ }
46
+ }
@@ -1,13 +1,17 @@
1
1
  import type { ReplayLiteState } from "../replay/use-replay-lite.js";
2
+ import type { ReplayStep } from "../replay/build-replay-steps.js";
2
3
  export type ReplayControlsProps = {
3
4
  state: ReplayLiteState;
5
+ steps: ReplayStep[];
6
+ stepLabels?: Record<string, string>;
4
7
  loop: boolean;
5
8
  disabled?: boolean;
9
+ speed: number;
6
10
  unavailableReason?: string;
7
11
  onPlay: () => void;
8
12
  onPause: () => void;
9
13
  onRestart: () => void;
10
14
  onToggleLoop: () => void;
15
+ onSpeedChange: (speed: number) => void;
11
16
  };
12
- export declare function ReplayControls({ state, loop, disabled, unavailableReason, onPlay, onPause, onRestart, onToggleLoop }: ReplayControlsProps): JSX.Element;
13
- //# sourceMappingURL=ReplayControls.d.ts.map
17
+ export declare function ReplayControls({ state, steps, stepLabels, loop, speed, disabled, unavailableReason, onPlay, onPause, onRestart, onToggleLoop, onSpeedChange }: ReplayControlsProps): JSX.Element;
@@ -1,5 +1,33 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- export function ReplayControls({ state, loop, disabled = false, unavailableReason, onPlay, onPause, onRestart, onToggleLoop }) {
3
- return (_jsxs("section", { className: "anlyx-replay", "aria-label": "Replay Lite controls", children: [_jsxs("div", { className: "anlyx-replay__buttons", "aria-label": "Replay actions", children: [_jsx("button", { type: "button", disabled: disabled || state.isPlaying, onClick: onPlay, children: "Play" }), _jsx("button", { type: "button", disabled: disabled || !state.isPlaying, onClick: onPause, children: "Pause" }), _jsx("button", { type: "button", disabled: disabled, onClick: onRestart, children: "Restart" }), _jsxs("button", { type: "button", "aria-pressed": loop, disabled: disabled, onClick: onToggleLoop, children: ["Loop ", loop ? "on" : "off"] })] }), _jsxs("div", { className: "anlyx-replay__state", children: [_jsxs("span", { children: ["Phase: ", state.phase] }), _jsxs("span", { children: ["Active: ", state.activeNodeId ?? "none"] }), _jsx("span", { children: "Main Flow only" })] }), disabled && unavailableReason ? (_jsx("p", { className: "anlyx-replay__empty", children: unavailableReason })) : null] }));
2
+ import { Pause, Play, RefreshCw, Repeat2 } from "lucide-react";
3
+ export function ReplayControls({ state, steps, stepLabels = {}, loop, speed, disabled = false, unavailableReason, onPlay, onPause, onRestart, onToggleLoop, onSpeedChange }) {
4
+ const currentStepNumber = state.phase === "idle" ? 0 : Math.min(state.currentStepIndex + 1, steps.length);
5
+ const currentStep = state.phase === "idle" || state.phase === "complete"
6
+ ? undefined
7
+ : steps[state.currentStepIndex];
8
+ const focusLabel = currentStep ? formatStepNode(currentStep.nodeId, stepLabels) : "Ready";
9
+ const edgeLabel = formatStepEdge(currentStep, stepLabels);
10
+ const phaseLabel = formatReplayPhase(state.phase);
11
+ return (_jsxs("section", { className: "anlyx-replay", "aria-label": "Process Flow controls", children: [_jsxs("div", { className: "anlyx-replay__top", children: [_jsxs("div", { children: [_jsx("p", { className: "anlyx-eyebrow", children: "Replay from scanned flow graph" }), _jsxs("div", { className: "anlyx-replay__buttons", "aria-label": "Process Flow actions", children: [_jsxs("button", { className: "anlyx-replay__button--primary", type: "button", disabled: disabled || state.isPlaying, onClick: onPlay, children: [_jsx(Play, { size: 14, strokeWidth: 2.5 }), _jsx("span", { children: "Play" })] }), _jsxs("button", { type: "button", disabled: disabled || !state.isPlaying, onClick: onPause, children: [_jsx(Pause, { size: 14, strokeWidth: 2.5 }), _jsx("span", { children: "Pause" })] }), _jsxs("button", { type: "button", disabled: disabled, onClick: onRestart, children: [_jsx(RefreshCw, { size: 14, strokeWidth: 2.5 }), _jsx("span", { children: "Restart" })] }), _jsxs("button", { type: "button", "aria-pressed": loop, disabled: disabled, onClick: onToggleLoop, children: [_jsx(Repeat2, { size: 14, strokeWidth: 2.5 }), _jsxs("span", { children: ["Loop ", loop ? "on" : "off"] })] })] })] }), _jsxs("div", { className: "anlyx-replay__state", children: [_jsxs("span", { children: ["Step ", currentStepNumber, "/", steps.length] }), _jsxs("span", { children: ["Phase: ", state.phase] }), _jsxs("label", { children: ["Speed", _jsxs("select", { "aria-label": "Replay speed", disabled: disabled, value: speed, onChange: (event) => onSpeedChange(Number(event.currentTarget.value)), children: [_jsx("option", { value: 1100, children: "0.75x" }), _jsx("option", { value: 800, children: "1x" }), _jsx("option", { value: 520, children: "1.5x" })] })] }), _jsx("span", { children: "Main Flow only" })] })] }), _jsxs("div", { className: "anlyx-replay__focus", role: "group", "aria-label": "Replay focus", children: [_jsxs("div", { children: [_jsx("span", { className: "anlyx-replay__phase", children: phaseLabel }), _jsx("strong", { children: focusLabel }), _jsx("p", { children: edgeLabel })] }), _jsx("ol", { className: "anlyx-replay__rail", "aria-label": "Replay step rail", children: steps.map((step, index) => (_jsx("li", { className: index === state.currentStepIndex ? "anlyx-replay__rail-step--active" : "", "aria-current": index === state.currentStepIndex ? "step" : undefined, title: `${formatReplayPhase(step.phase)}: ${formatStepNode(step.nodeId, stepLabels)}`, children: _jsx("span", { children: String(index + 1).padStart(2, "0") }) }, `${step.phase}:${step.nodeId}:${step.index}`))) })] }), disabled && unavailableReason ? (_jsx("p", { className: "anlyx-replay__empty", children: unavailableReason })) : null] }));
12
+ }
13
+ function formatReplayPhase(phase) {
14
+ switch (phase) {
15
+ case "request":
16
+ return "Request travel";
17
+ case "response":
18
+ return "Response return";
19
+ case "complete":
20
+ return "Response delivered";
21
+ case "idle":
22
+ return "Ready to replay";
23
+ }
24
+ }
25
+ function formatStepNode(nodeId, labels) {
26
+ return labels[nodeId] ?? nodeId;
27
+ }
28
+ function formatStepEdge(step, labels) {
29
+ if (!step?.fromNodeId || !step.toNodeId) {
30
+ return "Waiting at the first visible node in the scanned main path.";
31
+ }
32
+ return `${formatStepNode(step.fromNodeId, labels)} -> ${formatStepNode(step.toNodeId, labels)}`;
4
33
  }
5
- //# sourceMappingURL=ReplayControls.js.map
@@ -3,4 +3,3 @@ export type ScreenshotSegmentCardProps = {
3
3
  segment: ScreenshotSegment;
4
4
  };
5
5
  export declare function ScreenshotSegmentCard({ segment }: ScreenshotSegmentCardProps): JSX.Element;
6
- //# sourceMappingURL=ScreenshotSegmentCard.d.ts.map
@@ -3,4 +3,3 @@ export function ScreenshotSegmentCard({ segment }) {
3
3
  const title = segment.title ?? `Segment ${segment.segmentIndex + 1}`;
4
4
  return (_jsxs("article", { className: "anlyx-segment-card", children: [_jsx("div", { className: "anlyx-segment-card__image", children: segment.path ? _jsx("img", { alt: title, src: segment.path }) : _jsx("span", { children: "No image path" }) }), _jsxs("div", { className: "anlyx-segment-card__body", children: [_jsxs("h3", { children: ["Segment ", segment.segmentIndex + 1] }), segment.title ? _jsx("p", { children: segment.title }) : null, segment.path ? _jsx("code", { children: segment.path }) : _jsx("code", { children: "No path" }), _jsxs("div", { className: "anlyx-segment-card__meta", children: [_jsxs("span", { children: ["scrollY ", segment.scrollY] }), _jsxs("span", { children: [segment.viewport.width, " x ", segment.viewport.height] })] })] })] }));
5
5
  }
6
- //# sourceMappingURL=ScreenshotSegmentCard.js.map
@@ -1,13 +1,14 @@
1
1
  import type { Endpoint, PageStoryboard, ScanResult } from "@anlyx/core";
2
2
  type SidebarProps = {
3
3
  data: ScanResult;
4
- activeView: "endpoint" | "pages" | "replay";
4
+ activeView: "flowStory" | "structure" | "frontend" | "process";
5
+ collapsed: boolean;
5
6
  selectedEndpointId: string | undefined;
6
7
  selectedPageId: string | undefined;
7
- onSelectView: (view: "endpoint" | "pages" | "replay") => void;
8
+ onSelectView: (view: "flowStory" | "structure" | "frontend" | "process") => void;
9
+ onToggleCollapsed: () => void;
8
10
  onSelectEndpoint: (endpoint: Endpoint) => void;
9
11
  onSelectPage: (page: PageStoryboard) => void;
10
12
  };
11
- export declare function Sidebar({ data, activeView, selectedEndpointId, selectedPageId, onSelectView, onSelectEndpoint, onSelectPage }: SidebarProps): JSX.Element;
13
+ export declare function Sidebar({ data, activeView, collapsed, selectedEndpointId, selectedPageId, onSelectView, onToggleCollapsed, onSelectEndpoint, onSelectPage }: SidebarProps): JSX.Element;
12
14
  export {};
13
- //# sourceMappingURL=Sidebar.d.ts.map
@@ -1,7 +1,22 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Box, PanelLeftClose, PanelLeftOpen, Search } from "lucide-react";
2
3
  import { EndpointList } from "./EndpointList.js";
3
4
  import { PageList } from "./PageList.js";
4
- export function Sidebar({ data, activeView, selectedEndpointId, selectedPageId, onSelectView, onSelectEndpoint, onSelectPage }) {
5
- return (_jsxs("aside", { className: "anlyx-sidebar", "aria-label": "Primary navigation", children: [_jsxs("div", { className: "anlyx-brand", children: [_jsx("div", { className: "anlyx-brand__mark", "aria-hidden": "true", children: "A" }), _jsxs("div", { children: [_jsx("div", { className: "anlyx-brand__name", children: "Anlyx" }), _jsx("div", { className: "anlyx-brand__project", children: data.projectName })] })] }), _jsxs("nav", { className: "anlyx-tabs", "aria-label": "Views", children: [_jsx("button", { className: activeView === "endpoint" ? "anlyx-tab anlyx-tab--active" : "anlyx-tab", type: "button", onClick: () => onSelectView("endpoint"), children: "Endpoint" }), _jsx("button", { className: activeView === "pages" ? "anlyx-tab anlyx-tab--active" : "anlyx-tab", type: "button", onClick: () => onSelectView("pages"), children: "Pages" }), _jsx("button", { className: activeView === "replay" ? "anlyx-tab anlyx-tab--active" : "anlyx-tab", type: "button", onClick: () => onSelectView("replay"), children: "Replay" })] }), _jsxs("label", { className: "anlyx-search", children: [_jsx("span", { className: "anlyx-search__label", children: "Search" }), _jsx("input", { placeholder: "Search endpoints or pages", type: "search" })] }), _jsx(EndpointList, { endpoints: data.endpoints, selectedEndpointId: selectedEndpointId, onSelectEndpoint: onSelectEndpoint }), _jsx(PageList, { pages: data.pages, selectedPageId: selectedPageId, onSelectPage: onSelectPage })] }));
5
+ export function Sidebar({ data, activeView, collapsed, selectedEndpointId, selectedPageId, onSelectView, onToggleCollapsed, onSelectEndpoint, onSelectPage }) {
6
+ if (collapsed) {
7
+ return (_jsxs("aside", { className: "anlyx-sidebar anlyx-sidebar--collapsed", "aria-label": "Primary navigation", children: [_jsx("button", { className: "anlyx-panel-toggle", type: "button", "aria-label": "Expand navigation panel", onClick: onToggleCollapsed, children: _jsx(PanelLeftOpen, { size: 15, strokeWidth: 2.4 }) }), _jsx("span", { className: "anlyx-collapsed-label", children: "Nav" })] }));
8
+ }
9
+ return (_jsxs("aside", { className: "anlyx-sidebar", "aria-label": "Primary navigation", children: [_jsxs("div", { className: "anlyx-brand", children: [_jsx("div", { className: "anlyx-brand__mark", "aria-hidden": "true", children: "A" }), _jsxs("div", { children: [_jsx("div", { className: "anlyx-brand__name", children: "Anlyx" }), _jsx("div", { className: "anlyx-brand__project", children: "Interaction flow map" })] }), _jsx("button", { className: "anlyx-panel-toggle", type: "button", "aria-label": "Collapse navigation panel", onClick: onToggleCollapsed, children: _jsx(PanelLeftClose, { size: 15, strokeWidth: 2.4 }) })] }), _jsxs("button", { className: "anlyx-project-select", type: "button", "aria-label": `Project ${data.projectName}`, children: [_jsx(Box, { size: 15, strokeWidth: 2.4 }), _jsx("span", { children: data.projectName })] }), _jsxs("nav", { className: "anlyx-tabs", "aria-label": "Views", children: [_jsx("button", { className: activeView === "flowStory" ? "anlyx-tab anlyx-tab--active" : "anlyx-tab", type: "button", onClick: () => onSelectView("flowStory"), children: "Flow Story" }), _jsx("button", { className: activeView === "structure" ? "anlyx-tab anlyx-tab--active" : "anlyx-tab", type: "button", onClick: () => onSelectView("structure"), children: "Structure" }), _jsx("button", { className: activeView === "frontend" ? "anlyx-tab anlyx-tab--active" : "anlyx-tab", type: "button", onClick: () => onSelectView("frontend"), children: "Captures" }), _jsx("button", { className: activeView === "process" ? "anlyx-tab anlyx-tab--active" : "anlyx-tab", type: "button", onClick: () => onSelectView("process"), children: "Process" })] }), _jsxs("label", { className: "anlyx-search", children: [_jsx("span", { className: "anlyx-search__label", children: "Search" }), _jsxs("span", { className: "anlyx-search__control", children: [_jsx(Search, { size: 14, strokeWidth: 2.4 }), _jsx("input", { placeholder: "Search pages, endpoints, or services", type: "search" })] })] }), _jsxs("div", { className: "anlyx-sidebar__list-region", children: [_jsx(PageList, { pages: data.pages, selectedPageId: selectedPageId, onSelectPage: onSelectPage }), _jsx(EndpointList, { endpoints: data.endpoints, selectedEndpointId: selectedEndpointId, onSelectEndpoint: onSelectEndpoint }), _jsx(BackendServiceList, { data: data })] })] }));
10
+ }
11
+ function BackendServiceList({ data }) {
12
+ const services = [
13
+ ...new Map(data.flows
14
+ .flatMap((flow) => [...flow.nodes, ...flow.subFlows.flatMap((subFlow) => subFlow.nodes)])
15
+ .filter((node) => ["service", "repository", "mapper", "validator", "utility"].includes(node.type))
16
+ .map((node) => [node.id, node])).values()
17
+ ];
18
+ if (services.length === 0) {
19
+ return _jsx(_Fragment, {});
20
+ }
21
+ return (_jsxs("section", { className: "anlyx-sidebar-section", "aria-labelledby": "anlyx-services-heading", children: [_jsx("div", { className: "anlyx-section-heading", id: "anlyx-services-heading", children: "Backend Services" }), _jsx("ul", { className: "anlyx-list anlyx-list--compact", "aria-label": "Backend service list", children: services.map((node) => (_jsxs("li", { className: "anlyx-service-row", children: [_jsx(Box, { size: 14, strokeWidth: 2.3 }), _jsx("span", { children: node.label })] }, node.id))) })] }));
6
22
  }
7
- //# sourceMappingURL=Sidebar.js.map
@@ -6,4 +6,3 @@ type StatusBadgeProps = {
6
6
  };
7
7
  export declare function StatusBadge({ children, tone, label }: StatusBadgeProps): JSX.Element;
8
8
  export {};
9
- //# sourceMappingURL=StatusBadge.d.ts.map
@@ -2,4 +2,3 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  export function StatusBadge({ children, tone = "neutral", label }) {
3
3
  return (_jsxs("span", { className: `anlyx-status-badge anlyx-status-badge--${tone.toLowerCase()}`, children: [label ? _jsx("span", { className: "anlyx-status-badge__label", children: label }) : null, children] }));
4
4
  }
5
- //# sourceMappingURL=StatusBadge.js.map