@ashlr/hub 3.4.0 → 3.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +107 -1
- package/README.md +3 -0
- package/dist/build-identity.json +2 -2
- package/dist/cli/index.js +11 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/local-runtime.js +40 -9
- package/dist/cli/local-runtime.js.map +1 -1
- package/dist/core/fleet/external-skill-audit.js +1 -1
- package/dist/core/fleet/external-skill-audit.js.map +1 -1
- package/dist/core/local-eval/classify.d.ts +57 -0
- package/dist/core/local-eval/classify.js +121 -0
- package/dist/core/local-eval/classify.js.map +1 -0
- package/dist/core/local-eval/configuration.d.ts +37 -0
- package/dist/core/local-eval/configuration.js +171 -0
- package/dist/core/local-eval/configuration.js.map +1 -0
- package/dist/core/local-eval/index.d.ts +15 -0
- package/dist/core/local-eval/index.js +16 -0
- package/dist/core/local-eval/index.js.map +1 -0
- package/dist/core/local-eval/main.d.ts +31 -0
- package/dist/core/local-eval/main.js +174 -0
- package/dist/core/local-eval/main.js.map +1 -0
- package/dist/core/local-eval/report.d.ts +25 -0
- package/dist/core/local-eval/report.js +157 -0
- package/dist/core/local-eval/report.js.map +1 -0
- package/dist/core/local-eval/runner.d.ts +55 -0
- package/dist/core/local-eval/runner.js +290 -0
- package/dist/core/local-eval/runner.js.map +1 -0
- package/dist/core/local-eval/tasks.d.ts +22 -0
- package/dist/core/local-eval/tasks.js +303 -0
- package/dist/core/local-eval/tasks.js.map +1 -0
- package/dist/core/local-eval/trace.d.ts +67 -0
- package/dist/core/local-eval/trace.js +309 -0
- package/dist/core/local-eval/trace.js.map +1 -0
- package/dist/core/local-eval/types.d.ts +262 -0
- package/dist/core/local-eval/types.js +23 -0
- package/dist/core/local-eval/types.js.map +1 -0
- package/dist/core/local-runtime/llama/anthropic-proxy-host.d.ts +68 -0
- package/dist/core/local-runtime/llama/anthropic-proxy-host.js +120 -0
- package/dist/core/local-runtime/llama/anthropic-proxy-host.js.map +1 -0
- package/dist/core/local-runtime/llama/anthropic-proxy-process.d.ts +15 -0
- package/dist/core/local-runtime/llama/anthropic-proxy-process.js +21 -0
- package/dist/core/local-runtime/llama/anthropic-proxy-process.js.map +1 -0
- package/dist/core/local-runtime/llama/anthropic-proxy.d.ts +2 -1
- package/dist/core/local-runtime/llama/anthropic-proxy.js +14 -6
- package/dist/core/local-runtime/llama/anthropic-proxy.js.map +1 -1
- package/dist/core/local-runtime/llama/anthropic-shim.d.ts +33 -0
- package/dist/core/local-runtime/llama/anthropic-shim.js +59 -0
- package/dist/core/local-runtime/llama/anthropic-shim.js.map +1 -1
- package/dist/core/local-runtime/llama/config.d.ts +123 -6
- package/dist/core/local-runtime/llama/config.js +196 -6
- package/dist/core/local-runtime/llama/config.js.map +1 -1
- package/dist/core/local-runtime/llama/index.d.ts +15 -0
- package/dist/core/local-runtime/llama/index.js +13 -0
- package/dist/core/local-runtime/llama/index.js.map +1 -1
- package/dist/core/local-runtime/llama/paths.d.ts +17 -0
- package/dist/core/local-runtime/llama/paths.js +25 -0
- package/dist/core/local-runtime/llama/paths.js.map +1 -1
- package/dist/core/local-runtime/llama/proxy-invocation.d.ts +101 -0
- package/dist/core/local-runtime/llama/proxy-invocation.js +134 -0
- package/dist/core/local-runtime/llama/proxy-invocation.js.map +1 -0
- package/dist/core/local-runtime/llama/proxy-launchd.d.ts +83 -0
- package/dist/core/local-runtime/llama/proxy-launchd.js +216 -0
- package/dist/core/local-runtime/llama/proxy-launchd.js.map +1 -0
- package/dist/core/local-runtime/llama/shapes.d.ts +2 -1
- package/dist/core/local-runtime/llama/shapes.js +2 -1
- package/dist/core/local-runtime/llama/shapes.js.map +1 -1
- package/dist/core/verse/adapters/claude.js +16 -0
- package/dist/core/verse/adapters/claude.js.map +1 -1
- package/dist/core/verse/adapters/codex.js +60 -2
- package/dist/core/verse/adapters/codex.js.map +1 -1
- package/dist/core/verse/adapters/grok.js +13 -0
- package/dist/core/verse/adapters/grok.js.map +1 -1
- package/dist/core/verse/control-api.d.ts +8 -9
- package/dist/core/verse/control-api.js +14 -114
- package/dist/core/verse/control-api.js.map +1 -1
- package/dist/core/verse/github-api.d.ts +50 -0
- package/dist/core/verse/github-api.js +211 -0
- package/dist/core/verse/github-api.js.map +1 -0
- package/dist/core/verse/github-proposal.d.ts +64 -0
- package/dist/core/verse/github-proposal.js +186 -0
- package/dist/core/verse/github-proposal.js.map +1 -0
- package/dist/core/verse/github-repo.d.ts +104 -0
- package/dist/core/verse/github-repo.js +476 -0
- package/dist/core/verse/github-repo.js.map +1 -0
- package/dist/core/verse/github-types.d.ts +174 -0
- package/dist/core/verse/github-types.js +31 -0
- package/dist/core/verse/github-types.js.map +1 -0
- package/dist/core/verse/mcp-cli-health.d.ts +149 -0
- package/dist/core/verse/mcp-cli-health.js +227 -0
- package/dist/core/verse/mcp-cli-health.js.map +1 -0
- package/dist/core/verse/mcp-control-api.d.ts +68 -0
- package/dist/core/verse/mcp-control-api.js +322 -0
- package/dist/core/verse/mcp-control-api.js.map +1 -0
- package/dist/core/verse/mcp-mutation.d.ts +187 -0
- package/dist/core/verse/mcp-mutation.js +471 -0
- package/dist/core/verse/mcp-mutation.js.map +1 -0
- package/dist/core/verse/mcp-scope.d.ts +114 -0
- package/dist/core/verse/mcp-scope.js +149 -0
- package/dist/core/verse/mcp-scope.js.map +1 -0
- package/dist/core/verse/mcp-seat-view.d.ts +197 -0
- package/dist/core/verse/mcp-seat-view.js +322 -0
- package/dist/core/verse/mcp-seat-view.js.map +1 -0
- package/dist/core/verse/path-guard.d.ts +115 -0
- package/dist/core/verse/path-guard.js +171 -0
- package/dist/core/verse/path-guard.js.map +1 -0
- package/dist/core/verse/seats.js +30 -2
- package/dist/core/verse/seats.js.map +1 -1
- package/dist/core/verse/session-engine.js +60 -1
- package/dist/core/verse/session-engine.js.map +1 -1
- package/dist/core/verse/session-store.js +20 -0
- package/dist/core/verse/session-store.js.map +1 -1
- package/dist/core/verse/types.d.ts +225 -1
- package/dist/core/verse/types.js +26 -0
- package/dist/core/verse/types.js.map +1 -1
- package/dist/core/verse/verse-api.d.ts +16 -1
- package/dist/core/verse/verse-api.js +338 -16
- package/dist/core/verse/verse-api.js.map +1 -1
- package/dist/core/verse/workspaces.d.ts +130 -0
- package/dist/core/verse/workspaces.js +501 -0
- package/dist/core/verse/workspaces.js.map +1 -0
- package/dist/core/web/api.js +23 -0
- package/dist/core/web/api.js.map +1 -1
- package/dist/core/web/public/next/assets/App-BbVoUCIi.js +7 -0
- package/dist/core/web/public/next/assets/App-BbVoUCIi.js.map +1 -0
- package/dist/core/web/public/next/assets/App-Cgi6j1Gk.css +1 -0
- package/dist/core/web/public/next/assets/ApprovalsSection-BW9iVjUa.js +2 -0
- package/dist/core/web/public/next/assets/ApprovalsSection-BW9iVjUa.js.map +1 -0
- package/dist/core/web/public/next/assets/ApprovalsSection-Su-NUTis.css +1 -0
- package/dist/core/web/public/next/assets/AutonomySection-CRqHUhED.js +2 -0
- package/dist/core/web/public/next/assets/AutonomySection-CRqHUhED.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomySection-Cpk_oEhc.css +1 -0
- package/dist/core/web/public/next/assets/ChatSection-5irrh6Jw.js +80 -0
- package/dist/core/web/public/next/assets/ChatSection-5irrh6Jw.js.map +1 -0
- package/dist/core/web/public/next/assets/ChatSection-LQiAn6Eu.css +1 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-CXevY3Au.js +2 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-CXevY3Au.js.map +1 -0
- package/dist/core/web/public/next/assets/{ConfirmDialog-cYuivhCX.css → ConfirmDialog-Dx15x0Ho.css} +1 -1
- package/dist/core/web/public/next/assets/Dialog-Bn0CgEGz.js +2 -0
- package/dist/core/web/public/next/assets/Dialog-Bn0CgEGz.js.map +1 -0
- package/dist/core/web/public/next/assets/Dialog-tQ8kFulD.css +1 -0
- package/dist/core/web/public/next/assets/DiffViewer-C8HHTnVE.css +1 -0
- package/dist/core/web/public/next/assets/DiffViewer-QKyisN2L.js +7 -0
- package/dist/core/web/public/next/assets/DiffViewer-QKyisN2L.js.map +1 -0
- package/dist/core/web/public/next/assets/{MutationTokenDialog-jWLLCxWn.css → MutationTokenDialog-CrfJ0PdD.css} +1 -1
- package/dist/core/web/public/next/assets/MutationTokenDialog-DbSHPy3w.js +2 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-DbSHPy3w.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-C-PCgCzo.js +7 -0
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-C-PCgCzo.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-CM_8pJs6.css +1 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-Dw8ZjmkS.js +2 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-Dw8ZjmkS.js.map +1 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-ekyMXAK8.css +1 -0
- package/dist/core/web/public/next/assets/SettingsSection-BII7TTSD.css +1 -0
- package/dist/core/web/public/next/assets/SettingsSection-CWxtTNlD.js +2 -0
- package/dist/core/web/public/next/assets/SettingsSection-CWxtTNlD.js.map +1 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-Bk5HipM0.js +2 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-Bk5HipM0.js.map +1 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-Dh7A-hLD.css +1 -0
- package/dist/core/web/public/next/assets/UniverseView-Bqa8DH57.css +1 -0
- package/dist/core/web/public/next/assets/UniverseView-D8k9q0ce.js +9 -0
- package/dist/core/web/public/next/assets/UniverseView-D8k9q0ce.js.map +1 -0
- package/dist/core/web/public/next/assets/UsageSection-B2E06ZH1.js +2 -0
- package/dist/core/web/public/next/assets/UsageSection-B2E06ZH1.js.map +1 -0
- package/dist/core/web/public/next/assets/UsageSection-DwgNOYvi.css +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-CRfZUV-T.js +3 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-CRfZUV-T.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-D2E3mU9a.css +1 -0
- package/dist/core/web/public/next/assets/charts-CsrtT4rk.css +1 -0
- package/dist/core/web/public/next/assets/charts-DSUpczxG.js +2 -0
- package/dist/core/web/public/next/assets/charts-DSUpczxG.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js +2 -0
- package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js.map +1 -0
- package/dist/core/web/public/next/assets/format-BNYWGJat.js +2 -0
- package/dist/core/web/public/next/assets/format-BNYWGJat.js.map +1 -0
- package/dist/core/web/public/next/assets/global-C4jfYHrj.js +2 -0
- package/dist/core/web/public/next/assets/global-C4jfYHrj.js.map +1 -0
- package/dist/core/web/public/next/assets/global-D463gG1X.css +1 -0
- package/dist/core/web/public/next/assets/icons-BxOX8-XB.js +2 -0
- package/dist/core/web/public/next/assets/icons-BxOX8-XB.js.map +1 -0
- package/dist/core/web/public/next/assets/index-BMRIET7F.js +11 -0
- package/dist/core/web/public/next/assets/index-BMRIET7F.js.map +1 -0
- package/dist/core/web/public/next/assets/queries-AxnVa02h.js +2 -0
- package/dist/core/web/public/next/assets/queries-AxnVa02h.js.map +1 -0
- package/dist/core/web/public/next/assets/use-guarded-action-BO6c94Wp.js +2 -0
- package/dist/core/web/public/next/assets/use-guarded-action-BO6c94Wp.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-model-CvtK6vP6.js +2 -0
- package/dist/core/web/public/next/assets/verse-model-CvtK6vP6.js.map +1 -0
- package/dist/core/web/public/next/assets/workspace-model-cE4LkKpE.js +2 -0
- package/dist/core/web/public/next/assets/workspace-model-cE4LkKpE.js.map +1 -0
- package/dist/core/web/public/next/index.html +1 -1
- package/dist/release-dependency-inventory.json +1 -1
- package/docs/README.md +4 -0
- package/node_modules/marked/README.md +8 -0
- package/node_modules/marked/bin/main.js +12 -11
- package/node_modules/marked/lib/marked.d.ts +88 -25
- package/node_modules/marked/lib/marked.esm.js +50 -44
- package/node_modules/marked/lib/marked.esm.js.map +3 -3
- package/node_modules/marked/lib/marked.umd.js +50 -44
- package/node_modules/marked/lib/marked.umd.js.map +3 -3
- package/node_modules/marked/man/marked.1 +1 -1
- package/node_modules/marked/package.json +21 -21
- package/package.json +13 -8
- package/dist/cli/activation.d.ts +0 -41
- package/dist/cli/activation.js +0 -485
- package/dist/cli/activation.js.map +0 -1
- package/dist/core/fleet/generated-repair-resolution.d.ts +0 -36
- package/dist/core/fleet/generated-repair-resolution.js +0 -245
- package/dist/core/fleet/generated-repair-resolution.js.map +0 -1
- package/dist/core/local-runtime/llama/port.d.ts +0 -17
- package/dist/core/local-runtime/llama/port.js +0 -47
- package/dist/core/local-runtime/llama/port.js.map +0 -1
- package/dist/core/local-runtime/llama/proxy-host.d.ts +0 -54
- package/dist/core/local-runtime/llama/proxy-host.js +0 -159
- package/dist/core/local-runtime/llama/proxy-host.js.map +0 -1
- package/dist/core/local-runtime/llama/proxy-process.d.ts +0 -148
- package/dist/core/local-runtime/llama/proxy-process.js +0 -250
- package/dist/core/local-runtime/llama/proxy-process.js.map +0 -1
- package/dist/core/local-runtime/llama/proxy-record.d.ts +0 -40
- package/dist/core/local-runtime/llama/proxy-record.js +0 -133
- package/dist/core/local-runtime/llama/proxy-record.js.map +0 -1
- package/dist/core/local-runtime/llama/proxy-supervisor.d.ts +0 -118
- package/dist/core/local-runtime/llama/proxy-supervisor.js +0 -511
- package/dist/core/local-runtime/llama/proxy-supervisor.js.map +0 -1
- package/dist/core/web/public/next/assets/App-BCKqSppK.css +0 -1
- package/dist/core/web/public/next/assets/App-LuILXjWG.js +0 -16
- package/dist/core/web/public/next/assets/App-LuILXjWG.js.map +0 -1
- package/dist/core/web/public/next/assets/ApprovalsSection-B_Xor8JH.js +0 -2
- package/dist/core/web/public/next/assets/ApprovalsSection-B_Xor8JH.js.map +0 -1
- package/dist/core/web/public/next/assets/ApprovalsSection-CRP59wSb.css +0 -1
- package/dist/core/web/public/next/assets/AutonomySection-BB8RD-tv.css +0 -1
- package/dist/core/web/public/next/assets/AutonomySection-BEwITtPJ.js +0 -2
- package/dist/core/web/public/next/assets/AutonomySection-BEwITtPJ.js.map +0 -1
- package/dist/core/web/public/next/assets/ChatSection-DrxqhBPK.css +0 -1
- package/dist/core/web/public/next/assets/ChatSection-bRAzlMth.js +0 -77
- package/dist/core/web/public/next/assets/ChatSection-bRAzlMth.js.map +0 -1
- package/dist/core/web/public/next/assets/ConfirmDialog-BqkZdPs_.js +0 -2
- package/dist/core/web/public/next/assets/ConfirmDialog-BqkZdPs_.js.map +0 -1
- package/dist/core/web/public/next/assets/Dialog-CPmedg4S.js +0 -2
- package/dist/core/web/public/next/assets/Dialog-CPmedg4S.js.map +0 -1
- package/dist/core/web/public/next/assets/Dialog-DxN7RgB5.css +0 -1
- package/dist/core/web/public/next/assets/DiffViewer-DmPJbeM_.js +0 -7
- package/dist/core/web/public/next/assets/DiffViewer-DmPJbeM_.js.map +0 -1
- package/dist/core/web/public/next/assets/DiffViewer-hN7X6wGT.css +0 -1
- package/dist/core/web/public/next/assets/Epistemic-DiyMyeaN.css +0 -1
- package/dist/core/web/public/next/assets/Epistemic-M3SxLHjq.js +0 -2
- package/dist/core/web/public/next/assets/Epistemic-M3SxLHjq.js.map +0 -1
- package/dist/core/web/public/next/assets/Meter-CGBsbXUX.css +0 -1
- package/dist/core/web/public/next/assets/Meter-D_X7c9U3.js +0 -2
- package/dist/core/web/public/next/assets/Meter-D_X7c9U3.js.map +0 -1
- package/dist/core/web/public/next/assets/MutationTokenDialog-Ba5ZHu-8.js +0 -2
- package/dist/core/web/public/next/assets/MutationTokenDialog-Ba5ZHu-8.js.map +0 -1
- package/dist/core/web/public/next/assets/RefreshIndicator-O7jUBOmX.css +0 -1
- package/dist/core/web/public/next/assets/RefreshIndicator-vHGpmyzb.js +0 -2
- package/dist/core/web/public/next/assets/RefreshIndicator-vHGpmyzb.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-B5g6JEVk.js +0 -7
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-B5g6JEVk.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-DLl4DbGG.css +0 -1
- package/dist/core/web/public/next/assets/RouteErrorBoundary-BIpdnxp-.css +0 -1
- package/dist/core/web/public/next/assets/RouteErrorBoundary-CroxuKoi.js +0 -2
- package/dist/core/web/public/next/assets/RouteErrorBoundary-CroxuKoi.js.map +0 -1
- package/dist/core/web/public/next/assets/SettingsSection-DGJMdUh2.css +0 -1
- package/dist/core/web/public/next/assets/SettingsSection-p-7FCGfn.js +0 -2
- package/dist/core/web/public/next/assets/SettingsSection-p-7FCGfn.js.map +0 -1
- package/dist/core/web/public/next/assets/Skeleton-4qq4HuJO.js +0 -2
- package/dist/core/web/public/next/assets/Skeleton-4qq4HuJO.js.map +0 -1
- package/dist/core/web/public/next/assets/Skeleton-D2JaTXyv.css +0 -1
- package/dist/core/web/public/next/assets/StatusBadge-BbEdqEGn.js +0 -2
- package/dist/core/web/public/next/assets/StatusBadge-BbEdqEGn.js.map +0 -1
- package/dist/core/web/public/next/assets/StatusBadge-TpDqZf6K.css +0 -1
- package/dist/core/web/public/next/assets/TableView-R6Yeztp1.css +0 -1
- package/dist/core/web/public/next/assets/TableView-nyYs7Sv1.js +0 -2
- package/dist/core/web/public/next/assets/TableView-nyYs7Sv1.js.map +0 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-CiZZxRPV.css +0 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-DjTpQUrA.js +0 -2
- package/dist/core/web/public/next/assets/UniverseConsoleApp-DjTpQUrA.js.map +0 -1
- package/dist/core/web/public/next/assets/UniverseView-BtApwayT.js +0 -9
- package/dist/core/web/public/next/assets/UniverseView-BtApwayT.js.map +0 -1
- package/dist/core/web/public/next/assets/UniverseView-gBxl6yum.css +0 -1
- package/dist/core/web/public/next/assets/UsageSection-Db99N6ao.js +0 -2
- package/dist/core/web/public/next/assets/UsageSection-Db99N6ao.js.map +0 -1
- package/dist/core/web/public/next/assets/UsageSection-UUYDidOg.css +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-COa3J2dO.js +0 -3
- package/dist/core/web/public/next/assets/VerseConsoleApp-COa3J2dO.js.map +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-mOAXvWa6.css +0 -1
- package/dist/core/web/public/next/assets/fleet-model-DXCfVtNW.js +0 -2
- package/dist/core/web/public/next/assets/fleet-model-DXCfVtNW.js.map +0 -1
- package/dist/core/web/public/next/assets/format-fggwu_Rs.js +0 -2
- package/dist/core/web/public/next/assets/format-fggwu_Rs.js.map +0 -1
- package/dist/core/web/public/next/assets/global-BeRYd1Bu.css +0 -1
- package/dist/core/web/public/next/assets/global-CNVapoV1.js +0 -2
- package/dist/core/web/public/next/assets/global-CNVapoV1.js.map +0 -1
- package/dist/core/web/public/next/assets/index-BkUlX2Se.js +0 -51
- package/dist/core/web/public/next/assets/index-BkUlX2Se.js.map +0 -1
- package/dist/core/web/public/next/assets/index-YNTgDG2b.js +0 -2
- package/dist/core/web/public/next/assets/index-YNTgDG2b.js.map +0 -1
- package/dist/core/web/public/next/assets/queries-C9XS4SYq.js +0 -2
- package/dist/core/web/public/next/assets/queries-C9XS4SYq.js.map +0 -1
- package/dist/core/web/public/next/assets/use-guarded-action-Bqa2v0a-.css +0 -1
- package/dist/core/web/public/next/assets/use-guarded-action-Bql1nA-z.js +0 -2
- package/dist/core/web/public/next/assets/use-guarded-action-Bql1nA-z.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-model-IrNQKtER.js +0 -2
- package/dist/core/web/public/next/assets/verse-model-IrNQKtER.js.map +0 -1
- package/node_modules/which/CHANGELOG.md +0 -166
- /package/node_modules/marked/{LICENSE.md → LICENSE} +0 -0
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{o as t,b as x,t as _,x as u,g as y}from"./global-CNVapoV1.js";import{r as p,j as s}from"./index-BkUlX2Se.js";import{D as v}from"./Dialog-CPmedg4S.js";class j extends Error{constructor(){super("No mutation token held for this session yet."),this.name="MissingMutationTokenError"}}async function i(o,e){const a=y();if(!a)throw new j;const r=await x(o,e,a);return _(),r}async function I(){await i("/api/fleet/pause",{}),t("dashboard-snapshot"),t("control-snapshot"),t("fleet"),t("fleet-activity")}async function P(){await i("/api/fleet/resume",{}),t("dashboard-snapshot"),t("control-snapshot"),t("fleet"),t("fleet-activity")}async function $(o){await i(`/api/inbox/${encodeURIComponent(o)}/approve`,{}),t("inbox"),t("dashboard-snapshot"),t(`proposal-detail-${o}`),u("inbox-list:")}async function D(o){await i(`/api/inbox/${encodeURIComponent(o)}/reject`,{}),t("inbox"),t("dashboard-snapshot"),t(`proposal-detail-${o}`),u("inbox-list:")}const k="_body_15hsz_1",g="_error_15hsz_8",w="_actions_15hsz_17",z="_cancel_15hsz_23",C="_confirm_15hsz_33",M="_destructive_15hsz_48",n={body:k,error:g,actions:w,cancel:z,confirm:C,destructive:M};function F({open:o,onClose:e,title:a,body:r,confirmLabel:f,destructive:h,onConfirm:m,busy:c,error:l}){const b=p.useId(),d=p.useRef(null);return s.jsxs(v,{open:o,onClose:e,titleId:b,title:a,initialFocusRef:d,children:[s.jsx("div",{className:n.body,children:r}),l?s.jsx("p",{className:n.error,role:"alert",children:l}):null,s.jsxs("div",{className:n.actions,children:[s.jsx("button",{type:"button",className:n.cancel,onClick:e,disabled:c,children:"Cancel"}),s.jsx("button",{ref:d,type:"button",className:h?n.destructive:n.confirm,onClick:m,disabled:c,children:c?"Working…":f})]})]})}export{F as C,$ as a,P as b,I as p,D as r};
|
|
2
|
-
//# sourceMappingURL=ConfirmDialog-BqkZdPs_.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmDialog-BqkZdPs_.js","sources":["../../../../../../src/web-ui/data/mutations.ts","../../../../../../src/web-ui/routes/inbox/ConfirmDialog.tsx"],"sourcesContent":["/**\n * data/mutations.ts — every mutating call the foundation ships with, each\n * wrapped so it (a) pulls the held mutation token from auth-store instead\n * of asking every call site to thread it through, (b) touches the hold on\n * success so a burst of approvals doesn't idle-expire mid-session, and\n * (c) invalidates whatever cache keys the mutation obviously affects so\n * views update without waiting for the next SSE tick.\n *\n * Routes mirror the mutating surface documented at the top of\n * src/core/web/api.ts. Every one of these 404s (not 401/403) when the\n * server was started without --allow-dispatch — apiPost already maps that\n * to DispatchDisabledError.\n */\nimport { apiPost } from './client.js';\nimport { getMutationToken, touchMutationHold } from './auth-store.js';\nimport { invalidate, invalidatePrefix } from './cache.js';\n\nclass MissingMutationTokenError extends Error {\n constructor() {\n super('No mutation token held for this session yet.');\n this.name = 'MissingMutationTokenError';\n }\n}\n\nasync function post<T>(path: string, body: unknown): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new MissingMutationTokenError();\n const result = await apiPost<T>(path, body, token);\n touchMutationHold();\n return result;\n}\n\nexport async function pauseFleet(): Promise<void> {\n await post('/api/fleet/pause', {});\n invalidate('dashboard-snapshot');\n invalidate('control-snapshot');\n invalidate('fleet');\n invalidate('fleet-activity');\n}\n\nexport async function resumeFleet(): Promise<void> {\n await post('/api/fleet/resume', {});\n invalidate('dashboard-snapshot');\n invalidate('control-snapshot');\n invalidate('fleet');\n invalidate('fleet-activity');\n}\n\nexport async function approveProposal(id: string): Promise<void> {\n await post(`/api/inbox/${encodeURIComponent(id)}/approve`, {});\n invalidate('inbox');\n invalidate('dashboard-snapshot');\n invalidate(`proposal-detail-${id}`);\n invalidatePrefix('inbox-list:');\n}\n\nexport async function rejectProposal(id: string): Promise<void> {\n await post(`/api/inbox/${encodeURIComponent(id)}/reject`, {});\n invalidate('inbox');\n invalidate('dashboard-snapshot');\n invalidate(`proposal-detail-${id}`);\n invalidatePrefix('inbox-list:');\n}\n\nexport interface OpenTargetRequest {\n path: string;\n target: 'editor' | 'finder';\n}\n\nexport async function openTarget(req: OpenTargetRequest): Promise<void> {\n await post('/api/open', req);\n}\n","/**\n * routes/inbox/ConfirmDialog.tsx — explicit confirmation for approve/reject\n * (single or batch). Approve is the single most irreversible action in the\n * product (operator-console brief non-negotiable): it must require explicit\n * confirmation and clearly state what will happen, never fire on a single\n * click. Built on the shared Dialog primitive so it gets the same focus\n * trap / Escape / backdrop-close behavior as MutationTokenDialog and the\n * command palette for free.\n */\nimport { useId, useRef, type ReactNode } from 'react';\nimport { Dialog } from '../../components/primitives/Dialog.js';\nimport styles from './ConfirmDialog.module.css';\n\nexport interface ConfirmDialogProps {\n open: boolean;\n onClose: () => void;\n title: string;\n body: ReactNode;\n confirmLabel: string;\n /**\n * Weight the confirm button as the dangerous one. The rule is IRREVERSIBLE,\n * not \"negative-sounding\": whichever branch the operator cannot undo gets\n * the weight. In Verse's approvals that is Approve — a `pr` pushes a branch\n * and opens a real pull request other people see immediately, a `patch`\n * writes to disk now — while Reject only discards a proposal that stays in\n * history. This doc used to say the opposite, which is how the red button\n * came to be the safe one.\n */\n destructive?: boolean;\n onConfirm: () => void;\n busy?: boolean;\n error?: string | null;\n}\n\nexport function ConfirmDialog({ open, onClose, title, body, confirmLabel, destructive, onConfirm, busy, error }: ConfirmDialogProps) {\n const titleId = useId();\n const confirmRef = useRef<HTMLButtonElement>(null);\n\n return (\n <Dialog open={open} onClose={onClose} titleId={titleId} title={title} initialFocusRef={confirmRef}>\n <div className={styles.body}>{body}</div>\n {error ? (\n <p className={styles.error} role=\"alert\">\n {error}\n </p>\n ) : null}\n <div className={styles.actions}>\n <button type=\"button\" className={styles.cancel} onClick={onClose} disabled={busy}>\n Cancel\n </button>\n <button\n ref={confirmRef}\n type=\"button\"\n className={destructive ? styles.destructive : styles.confirm}\n onClick={onConfirm}\n disabled={busy}\n >\n {busy ? 'Working…' : confirmLabel}\n </button>\n </div>\n </Dialog>\n );\n}\n"],"names":["MissingMutationTokenError","post","path","body","token","getMutationToken","result","apiPost","touchMutationHold","pauseFleet","invalidate","resumeFleet","approveProposal","id","invalidatePrefix","rejectProposal","ConfirmDialog","open","onClose","title","confirmLabel","destructive","onConfirm","busy","error","titleId","useId","confirmRef","useRef","Dialog","jsx","styles","jsxs"],"mappings":"6JAiBA,MAAMA,UAAkC,KAAM,CAC5C,aAAc,CACZ,MAAM,8CAA8C,EACpD,KAAK,KAAO,2BACd,CACF,CAEA,eAAeC,EAAQC,EAAcC,EAA2B,CAC9D,MAAMC,EAAQC,EAAA,EACd,GAAI,CAACD,EAAO,MAAM,IAAIJ,EACtB,MAAMM,EAAS,MAAMC,EAAWL,EAAMC,EAAMC,CAAK,EACjD,OAAAI,EAAA,EACOF,CACT,CAEA,eAAsBG,GAA4B,CAChD,MAAMR,EAAK,mBAAoB,EAAE,EACjCS,EAAW,oBAAoB,EAC/BA,EAAW,kBAAkB,EAC7BA,EAAW,OAAO,EAClBA,EAAW,gBAAgB,CAC7B,CAEA,eAAsBC,GAA6B,CACjD,MAAMV,EAAK,oBAAqB,EAAE,EAClCS,EAAW,oBAAoB,EAC/BA,EAAW,kBAAkB,EAC7BA,EAAW,OAAO,EAClBA,EAAW,gBAAgB,CAC7B,CAEA,eAAsBE,EAAgBC,EAA2B,CAC/D,MAAMZ,EAAK,cAAc,mBAAmBY,CAAE,CAAC,WAAY,EAAE,EAC7DH,EAAW,OAAO,EAClBA,EAAW,oBAAoB,EAC/BA,EAAW,mBAAmBG,CAAE,EAAE,EAClCC,EAAiB,aAAa,CAChC,CAEA,eAAsBC,EAAeF,EAA2B,CAC9D,MAAMZ,EAAK,cAAc,mBAAmBY,CAAE,CAAC,UAAW,EAAE,EAC5DH,EAAW,OAAO,EAClBA,EAAW,oBAAoB,EAC/BA,EAAW,mBAAmBG,CAAE,EAAE,EAClCC,EAAiB,aAAa,CAChC,qMC5BO,SAASE,EAAc,CAAE,KAAAC,EAAM,QAAAC,EAAS,MAAAC,EAAO,KAAAhB,EAAM,aAAAiB,EAAc,YAAAC,EAAa,UAAAC,EAAW,KAAAC,EAAM,MAAAC,CAAA,EAA6B,CACnI,MAAMC,EAAUC,EAAAA,MAAA,EACVC,EAAaC,EAAAA,OAA0B,IAAI,EAEjD,cACGC,EAAA,CAAO,KAAAZ,EAAY,QAAAC,EAAkB,QAAAO,EAAkB,MAAAN,EAAc,gBAAiBQ,EACrF,SAAA,CAAAG,EAAAA,IAAC,MAAA,CAAI,UAAWC,EAAO,KAAO,SAAA5B,EAAK,EAClCqB,QACE,IAAA,CAAE,UAAWO,EAAO,MAAO,KAAK,QAC9B,SAAAP,CAAA,CACH,EACE,KACJQ,EAAAA,KAAC,MAAA,CAAI,UAAWD,EAAO,QACrB,SAAA,CAAAD,EAAAA,IAAC,SAAA,CAAO,KAAK,SAAS,UAAWC,EAAO,OAAQ,QAASb,EAAS,SAAUK,EAAM,SAAA,QAAA,CAElF,EACAO,EAAAA,IAAC,SAAA,CACC,IAAKH,EACL,KAAK,SACL,UAAWN,EAAcU,EAAO,YAAcA,EAAO,QACrD,QAAST,EACT,SAAUC,EAET,WAAO,WAAaH,CAAA,CAAA,CACvB,CAAA,CACF,CAAA,EACF,CAEJ"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as f,j as l}from"./index-BkUlX2Se.js";import{r as p}from"./index-YNTgDG2b.js";const m=["a[href]","button:not([disabled])","input:not([disabled])","select:not([disabled])","textarea:not([disabled])",'[tabindex]:not([tabindex="-1"])'].join(",");function b(e){return Array.from(e.querySelectorAll(m)).filter(r=>r.offsetParent!==null)}function g({open:e,containerRef:r,onClose:s,initialFocusRef:d}){f.useEffect(()=>{if(!e)return;const n=document.activeElement;return(d?.current??r.current)?.focus({preventScroll:!0}),()=>{n?.focus?.({preventScroll:!0})}},[e]),f.useEffect(()=>{if(!e)return;function n(t){if(t.key==="Escape"){t.stopPropagation(),s();return}if(t.key!=="Tab")return;const i=r.current;if(!i)return;const o=b(i);if(o.length===0)return;const a=o[0],c=o[o.length-1];t.shiftKey&&document.activeElement===a?(t.preventDefault(),c.focus()):!t.shiftKey&&document.activeElement===c&&(t.preventDefault(),a.focus())}return document.addEventListener("keydown",n,!0),()=>document.removeEventListener("keydown",n,!0)},[e,s])}const E="_backdrop_10r5p_1",v="_dialog_10r5p_13",x="_title_10r5p_25",y="_description_10r5p_36",u={backdrop:E,dialog:v,title:x,description:y};function k({open:e,onClose:r,titleId:s,title:d,description:n,children:t,initialFocusRef:i,widthClassName:o}){const a=f.useRef(null);return g({open:e,containerRef:a,onClose:r,initialFocusRef:i}),e?p.createPortal(l.jsx("div",{className:u.backdrop,onMouseDown:c=>c.target===c.currentTarget&&r(),children:l.jsxs("div",{ref:a,className:`${u.dialog} ${o??""}`,role:"dialog","aria-modal":"true","aria-labelledby":s,tabIndex:-1,children:[l.jsx("h2",{id:s,className:u.title,children:d}),n?l.jsx("p",{className:u.description,children:n}):null,t]})}),document.body):null}export{k as D};
|
|
2
|
-
//# sourceMappingURL=Dialog-CPmedg4S.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog-CPmedg4S.js","sources":["../../../../../../src/web-ui/components/primitives/focus-trap.ts","../../../../../../src/web-ui/components/primitives/Dialog.tsx"],"sourcesContent":["/**\n * components/primitives/focus-trap.ts — the modal focus contract, extracted\n * from Dialog.tsx so Sheet.tsx (the slide-over overlay) gets exactly the same\n * behavior instead of a second, subtly different implementation:\n *\n * - focus moves into the overlay (or `initialFocusRef`) on open\n * - focus is trapped inside while open (Tab/Shift+Tab wrap)\n * - focus returns to the element that opened it on close\n * - Escape closes\n *\n * Dialog.tsx is unchanged in behavior — it now calls this instead of\n * inlining it. Any future overlay MUST use this rather than hand-rolling a\n * trap (DESIGN.md §3, \"primitives own their accessibility\").\n */\nimport { useEffect, type RefObject } from 'react';\n\nexport const FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(',');\n\n/** Focusable descendants that are actually rendered (offsetParent is null for hidden nodes). */\nexport function focusableWithin(node: HTMLElement): HTMLElement[] {\n return Array.from(node.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter((el) => el.offsetParent !== null);\n}\n\nexport interface FocusTrapOptions {\n open: boolean;\n containerRef: RefObject<HTMLElement | null>;\n onClose: () => void;\n initialFocusRef?: RefObject<HTMLElement | null>;\n}\n\nexport function useFocusTrap({ open, containerRef, onClose, initialFocusRef }: FocusTrapOptions): void {\n useEffect(() => {\n if (!open) return;\n const previouslyFocused = document.activeElement as HTMLElement | null;\n const target = initialFocusRef?.current ?? containerRef.current;\n target?.focus({ preventScroll: true });\n\n return () => {\n previouslyFocused?.focus?.({ preventScroll: true });\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- the refs are refs (stable identity is not the point); only `open` should re-run this.\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n function onKeyDown(e: KeyboardEvent) {\n if (e.key === 'Escape') {\n e.stopPropagation();\n onClose();\n return;\n }\n if (e.key !== 'Tab') return;\n const node = containerRef.current;\n if (!node) return;\n const focusable = focusableWithin(node);\n if (focusable.length === 0) return;\n const first = focusable[0]!;\n const last = focusable[focusable.length - 1]!;\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n document.addEventListener('keydown', onKeyDown, true);\n return () => document.removeEventListener('keydown', onKeyDown, true);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- containerRef is a ref; re-binding on every render would drop in-flight key handling.\n }, [open, onClose]);\n}\n","/**\n * components/primitives/Dialog.tsx — focus-managed modal base. Used by\n * MutationTokenDialog, CommandPalette and the Verse confirm flows so all of\n * them get the same accessible behavior instead of each hand-rolling it:\n *\n * - focus moves to the dialog (or `initialFocusRef`) on open\n * - focus is trapped inside while open (Tab/Shift+Tab wrap)\n * - focus returns to the trigger element on close\n * - Escape closes\n * - a click on the backdrop closes\n *\n * The trap itself lives in ./focus-trap.ts, shared with Sheet.tsx — the\n * behavior here is unchanged, it just stopped being copy-pasteable.\n */\nimport { useRef, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useFocusTrap } from './focus-trap.js';\nimport styles from './Dialog.module.css';\n\nexport interface DialogProps {\n open: boolean;\n onClose: () => void;\n titleId: string;\n title: ReactNode;\n children: ReactNode;\n /** Optional one-line description under the title. */\n description?: ReactNode;\n initialFocusRef?: React.RefObject<HTMLElement | null>;\n widthClassName?: string;\n}\n\nexport function Dialog({\n open,\n onClose,\n titleId,\n title,\n description,\n children,\n initialFocusRef,\n widthClassName,\n}: DialogProps) {\n const dialogRef = useRef<HTMLDivElement>(null);\n\n useFocusTrap({ open, containerRef: dialogRef, onClose, initialFocusRef });\n\n if (!open) return null;\n\n return createPortal(\n <div className={styles.backdrop} onMouseDown={(e) => e.target === e.currentTarget && onClose()}>\n <div\n ref={dialogRef}\n className={`${styles.dialog} ${widthClassName ?? ''}`}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n tabIndex={-1}\n >\n <h2 id={titleId} className={styles.title}>\n {title}\n </h2>\n {description ? <p className={styles.description}>{description}</p> : null}\n {children}\n </div>\n </div>,\n document.body,\n );\n}\n"],"names":["FOCUSABLE_SELECTOR","focusableWithin","node","el","useFocusTrap","open","containerRef","onClose","initialFocusRef","useEffect","previouslyFocused","onKeyDown","e","focusable","first","last","Dialog","titleId","title","description","children","widthClassName","dialogRef","useRef","createPortal","jsx","styles","jsxs"],"mappings":"uFAgBO,MAAMA,EAAqB,CAChC,UACA,yBACA,wBACA,yBACA,2BACA,iCACF,EAAE,KAAK,GAAG,EAGH,SAASC,EAAgBC,EAAkC,CAChE,OAAO,MAAM,KAAKA,EAAK,iBAA8BF,CAAkB,CAAC,EAAE,OAAQG,GAAOA,EAAG,eAAiB,IAAI,CACnH,CASO,SAASC,EAAa,CAAE,KAAAC,EAAM,aAAAC,EAAc,QAAAC,EAAS,gBAAAC,GAA2C,CACrGC,EAAAA,UAAU,IAAM,CACd,GAAI,CAACJ,EAAM,OACX,MAAMK,EAAoB,SAAS,cAEnC,OADeF,GAAiB,SAAWF,EAAa,UAChD,MAAM,CAAE,cAAe,EAAA,CAAM,EAE9B,IAAM,CACXI,GAAmB,QAAQ,CAAE,cAAe,EAAA,CAAM,CACpD,CAEF,EAAG,CAACL,CAAI,CAAC,EAETI,EAAAA,UAAU,IAAM,CACd,GAAI,CAACJ,EAAM,OACX,SAASM,EAAUC,EAAkB,CACnC,GAAIA,EAAE,MAAQ,SAAU,CACtBA,EAAE,gBAAA,EACFL,EAAA,EACA,MACF,CACA,GAAIK,EAAE,MAAQ,MAAO,OACrB,MAAMV,EAAOI,EAAa,QAC1B,GAAI,CAACJ,EAAM,OACX,MAAMW,EAAYZ,EAAgBC,CAAI,EACtC,GAAIW,EAAU,SAAW,EAAG,OAC5B,MAAMC,EAAQD,EAAU,CAAC,EACnBE,EAAOF,EAAUA,EAAU,OAAS,CAAC,EACvCD,EAAE,UAAY,SAAS,gBAAkBE,GAC3CF,EAAE,eAAA,EACFG,EAAK,MAAA,GACI,CAACH,EAAE,UAAY,SAAS,gBAAkBG,IACnDH,EAAE,eAAA,EACFE,EAAM,MAAA,EAEV,CACA,gBAAS,iBAAiB,UAAWH,EAAW,EAAI,EAC7C,IAAM,SAAS,oBAAoB,UAAWA,EAAW,EAAI,CAEtE,EAAG,CAACN,EAAME,CAAO,CAAC,CACpB,8IC9CO,SAASS,EAAO,CACrB,KAAAX,EACA,QAAAE,EACA,QAAAU,EACA,MAAAC,EACA,YAAAC,EACA,SAAAC,EACA,gBAAAZ,EACA,eAAAa,CACF,EAAgB,CACd,MAAMC,EAAYC,EAAAA,OAAuB,IAAI,EAI7C,OAFAnB,EAAa,CAAE,KAAAC,EAAM,aAAciB,EAAW,QAAAf,EAAS,gBAAAC,EAAiB,EAEnEH,EAEEmB,EAAAA,aACLC,EAAAA,IAAC,MAAA,CAAI,UAAWC,EAAO,SAAU,YAAcd,GAAMA,EAAE,SAAWA,EAAE,eAAiBL,IACnF,SAAAoB,EAAAA,KAAC,MAAA,CACC,IAAKL,EACL,UAAW,GAAGI,EAAO,MAAM,IAAIL,GAAkB,EAAE,GACnD,KAAK,SACL,aAAW,OACX,kBAAiBJ,EACjB,SAAU,GAEV,SAAA,CAAAQ,MAAC,MAAG,GAAIR,EAAS,UAAWS,EAAO,MAChC,SAAAR,EACH,EACCC,EAAcM,EAAAA,IAAC,IAAA,CAAE,UAAWC,EAAO,YAAc,WAAY,EAAO,KACpEN,CAAA,CAAA,CAAA,EAEL,EACA,SAAS,IAAA,EAnBO,IAqBpB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._backdrop_10r5p_1{position:fixed;inset:0;background:var(--bg-overlay);display:flex;align-items:flex-start;justify-content:center;padding-top:12vh;z-index:var(--z-dialog);animation:_fade_10r5p_1 var(--duration-fast) var(--ease-standard)}._dialog_10r5p_13{width:min(480px,calc(100vw - var(--space-8)));max-height:76vh;overflow:auto;background:var(--bg-surface-raised);border:1px solid var(--border-default);border-radius:var(--radius-lg);box-shadow:var(--shadow-dialog);padding:var(--space-5);animation:_rise_10r5p_1 var(--duration-base) var(--ease-decelerate)}._title_10r5p_25{margin:0 0 var(--space-4);font-family:var(--font-display);font-size:var(--text-md-size);line-height:var(--text-md-line);font-weight:var(--font-weight-semibold);letter-spacing:var(--tracking-display)}._description_10r5p_36{margin:calc(var(--space-4) * -1 + var(--space-1)) 0 var(--space-4);color:var(--text-secondary);font-size:var(--text-sm-size);line-height:var(--text-sm-line)}@keyframes _fade_10r5p_1{0%{opacity:0}}@keyframes _rise_10r5p_1{0%{opacity:0;transform:translateY(4px)}}@media(prefers-reduced-motion:reduce){:root:not([data-motion=full]) ._backdrop_10r5p_1,:root:not([data-motion=full]) ._dialog_10r5p_13{animation:none}}:root[data-motion=reduce] ._backdrop_10r5p_1,:root[data-motion=reduce] ._dialog_10r5p_13{animation:none}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import{r as y,j as i}from"./index-BkUlX2Se.js";const T=/^diff --git a\/(.+) b\/(.+)$/,L=/^--- (?:a\/(.+)|(\/dev\/null))\s*$/,D=/^\+\+\+ (?:b\/(.+)|(\/dev\/null))\s*$/,A=/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$/;function P(l){return l.replace(/^[ab]\//,"")}function E(l){const d=l.split(`
|
|
2
|
-
`),e=d.some(t=>T.test(t)),o=[];for(let t=0;t<d.length;t++){const a=d[t];(e?T.test(a):L.test(a))&&o.push(t)}if(o.length===0)return[];const n=[];for(let t=0;t<o.length;t++){const a=o[t],c=t+1<o.length?o[t+1]:d.length;n.push(d.slice(a,c).join(`
|
|
3
|
-
`))}return n}function I(l,d){const e=l.split(`
|
|
4
|
-
`);e.length>0&&e[e.length-1]===""&&e.pop();let o=null,n=null,t=-1;for(let u=0;u<e.length;u++){const m=e[u],g=L.exec(m);if(g){o=g[2]?null:P(g[1]);continue}const k=D.exec(m);if(k){n=k[2]?null:P(k[1]),t=u+1;break}const x=T.exec(m);x&&o===null&&n===null&&(o=x[1]??null,n=x[2]??null)}let a="modified";o===null&&n!==null?a="added":o!==null&&n===null?a="deleted":o!==null&&n!==null&&o!==n&&(a="renamed");const c=n??o??`(unknown file ${d+1})`,f=[];let r=0,h=0,_=null;if(t===-1){const u=e.join(`
|
|
5
|
-
`).trim();return{id:`${d}:${c}`,oldPath:o,newPath:n,displayPath:c,status:a,hunks:[],additions:0,deletions:0,unparsedNotice:u||null}}let p=t;for(;p<e.length;){const u=A.exec(e[p]);if(!u){e[p].trim()&&(_=((_?_+`
|
|
6
|
-
`:"")+e[p]).trim()),p++;continue}const m=Number(u[1]),g=u[2]!==void 0?Number(u[2]):1,k=Number(u[3]),x=u[4]!==void 0?Number(u[4]):1,w={header:e[p],oldStart:m,oldLines:g,newStart:k,newLines:x,lines:[]};p++;let N=m,b=k;for(;p<e.length&&!A.test(e[p]);){const j=e[p];if(j.startsWith("\\")){p++;continue}const v=j[0],$=j.slice(1);v==="+"?(w.lines.push({kind:"add",text:$,oldLineNo:null,newLineNo:b}),b++,r++):v==="-"?(w.lines.push({kind:"del",text:$,oldLineNo:N,newLineNo:null}),N++,h++):(w.lines.push({kind:"context",text:v===" "?$:j,oldLineNo:N,newLineNo:b}),N++,b++),p++}f.push(w)}return{id:`${d}:${c}`,oldPath:o,newPath:n,displayPath:c,status:a,hunks:f,additions:r,deletions:h,unparsedNotice:_}}function C(l){const d=l??"";if(!d.trim())return{files:[],malformed:!1};const e=E(d);return e.length===0?{malformed:!0,files:[{id:"raw",oldPath:null,newPath:null,displayPath:"(unparsed diff)",status:"modified",hunks:[],additions:0,deletions:0,unparsedNotice:d}]}:{files:e.map((o,n)=>I(o,n)),malformed:!1}}function H(l){const d=[];let e=0;for(;e<l.length;){const o=l[e];if(o.kind==="context"){d.push({left:o,right:o}),e++;continue}const n=[];for(;e<l.length&&l[e].kind==="del";)n.push(l[e]),e++;const t=[];for(;e<l.length&&l[e].kind==="add";)t.push(l[e]),e++;const a=Math.max(n.length,t.length);for(let c=0;c<a;c++)d.push({left:n[c]??null,right:t[c]??null})}return d}const M={ts:"c-like",tsx:"c-like",js:"c-like",jsx:"c-like",mjs:"c-like",cjs:"c-like",mts:"c-like",cts:"c-like",java:"c-like",go:"c-like",rs:"c-like",c:"c-like",h:"c-like",cpp:"c-like",hpp:"c-like",cc:"c-like",swift:"c-like",kt:"c-like",kts:"c-like",py:"python",pyi:"python",sh:"shell",bash:"shell",zsh:"shell",css:"css",scss:"css",less:"css",json:"json",jsonc:"json",yml:"yaml",yaml:"yaml"};function z(l){if(!l)return"plain";const d=l.split(".").pop()?.toLowerCase()??"";return M[d]??"plain"}const F={"c-like":new Set(["const","let","var","function","return","if","else","for","while","do","switch","case","break","continue","class","extends","implements","interface","type","enum","export","import","from","default","new","this","super","try","catch","finally","throw","async","await","yield","static","public","private","protected","readonly","abstract","null","undefined","true","false","void","typeof","instanceof","in","of","as","is","never","unknown","any","package","struct","fn","impl","mod","pub","use","trait","match","func","defer","chan"]),python:new Set(["def","class","return","if","elif","else","for","while","break","continue","import","from","as","with","try","except","finally","raise","pass","lambda","yield","async","await","None","True","False","and","or","not","in","is","global","nonlocal","self"]),shell:new Set(["if","then","else","elif","fi","for","while","do","done","case","esac","function","return","export","local","echo","set","in","break","continue"]),css:new Set,json:new Set,yaml:new Set,plain:new Set},R={"c-like":/(?<comment>\/\/.*$|\/\*.*?\*\/)|(?<string>"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`)|(?<number>\b\d+(?:\.\d+)?\b)|(?<word>[A-Za-z_$][A-Za-z0-9_$]*)/g,python:/(?<comment>#.*$)|(?<string>"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(?<number>\b\d+(?:\.\d+)?\b)|(?<word>[A-Za-z_][A-Za-z0-9_]*)/g,shell:/(?<comment>#.*$)|(?<string>"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(?<word>[A-Za-z_][A-Za-z0-9_]*)/g,css:/(?<comment>\/\*.*?\*\/)|(?<string>"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(?<number>\b\d+(?:\.\d+)?\b)|(?<word>[A-Za-z_-][A-Za-z0-9_-]*)/g,json:/(?<string>"(?:[^"\\]|\\.)*")|(?<number>-?\b\d+(?:\.\d+)?\b)|(?<word>\btrue\b|\bfalse\b|\bnull\b)/g,yaml:/(?<comment>#.*$)|(?<string>"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/g};function Z(l,d){const e=R[d];if(!e)return[{kind:"plain",text:l}];const o=F[d],n=[];let t=0;e.lastIndex=0;let a;for(;a=e.exec(l);){a.index>t&&n.push({kind:"plain",text:l.slice(t,a.index)});const c=a.groups??{};if(c.comment!==void 0)n.push({kind:"comment",text:a[0]});else if(c.string!==void 0)n.push({kind:"string",text:a[0]});else if(c.number!==void 0)n.push({kind:"number",text:a[0]});else if(c.word!==void 0){const f=d==="json"||o.has(c.word);n.push({kind:f?"keyword":"plain",text:a[0]})}else n.push({kind:"plain",text:a[0]});t=a.index+a[0].length,a[0].length===0&&e.lastIndex++}return t<l.length&&n.push({kind:"plain",text:l.slice(t)}),n}const B="_viewer_gf84p_1",K="_malformedNotice_gf84p_9",U="_empty_gf84p_18",O="_tree_gf84p_27",W="_treeItem_gf84p_40",Y="_treeItemActive_gf84p_59",G="_statusDot_gf84p_64",V="_status_added_gf84p_70",X="_status_deleted_gf84p_71",q="_status_modified_gf84p_72",J="_status_renamed_gf84p_73",Q="_treePath_gf84p_75",ee="_treeStats_gf84p_83",te="_add_gf84p_89",ne="_del_gf84p_90",se="_body_gf84p_92",ie="_fileHeader_gf84p_99",le="_filePath_gf84p_109",oe="_modeToggle_gf84p_118",ae="_modeActive_gf84p_132",de="_notice_gf84p_138",ce="_emptyFile_gf84p_149",re="_hunkTable_gf84p_155",ue="_hunkCaption_gf84p_163",pe="_lineNo_gf84p_173",he="_lineMarker_gf84p_184",fe="_lineText_gf84p_192",_e="_hunkTableSplit_gf84p_199",me="_rowBlank_gf84p_203",ke="_row_add_gf84p_207",ge="_row_del_gf84p_210",xe="_row_context_gf84p_213",we="_code_gf84p_217",Ne="_tok_plain_gf84p_221",be="_tok_comment_gf84p_222",je="_tok_string_gf84p_223",ye="_tok_number_gf84p_224",ve="_tok_keyword_gf84p_225",s={viewer:B,malformedNotice:K,empty:U,tree:O,treeItem:W,treeItemActive:Y,statusDot:G,status_added:V,status_deleted:X,status_modified:q,status_renamed:J,treePath:Q,treeStats:ee,add:te,del:ne,body:se,fileHeader:ie,filePath:le,modeToggle:oe,modeActive:ae,notice:de,emptyFile:ce,hunkTable:re,hunkCaption:ue,lineNo:pe,lineMarker:he,lineText:fe,hunkTableSplit:_e,rowBlank:me,row_add:ke,row_del:ge,row_context:xe,code:we,tok_plain:Ne,tok_comment:be,tok_string:je,tok_number:ye,tok_keyword:ve};function Te({diff:l,proposalKind:d}){const e=y.useMemo(()=>C(l),[l]),[o,n]=y.useState(e.files[0]?.id??null),[t,a]=y.useState("unified");if(y.useEffect(()=>{n(e.files[0]?.id??null)},[l]),e.files.length===0)return i.jsxs("div",{className:s.empty,children:["No diff attached to this proposal (kind: ",d,")."]});const c=e.files.find(r=>r.id===o)??e.files[0];function f(r){const h=e.files.findIndex(_=>_.id===c.id);r.key==="ArrowDown"?(r.preventDefault(),n(e.files[Math.min(h+1,e.files.length-1)].id)):r.key==="ArrowUp"&&(r.preventDefault(),n(e.files[Math.max(h-1,0)].id))}return i.jsxs("div",{className:s.viewer,children:[e.malformed?i.jsx("p",{className:s.malformedNotice,children:"Could not parse this as a unified diff — showing raw content."}):null,i.jsx("div",{className:s.tree,role:"tree","aria-label":"Changed files",onKeyDown:f,children:e.files.map(r=>i.jsxs("button",{type:"button",role:"treeitem","aria-selected":r.id===c.id,tabIndex:r.id===c.id?0:-1,className:`${s.treeItem} ${r.id===c.id?s.treeItemActive:""}`,onClick:()=>n(r.id),children:[i.jsx("span",{className:`${s.statusDot} ${s[`status_${r.status}`]}`,"aria-hidden":"true"}),i.jsx("span",{className:s.treePath,title:r.displayPath,children:r.displayPath}),i.jsxs("span",{className:s.treeStats,children:[r.additions>0?i.jsxs("span",{className:s.add,children:["+",r.additions]}):null,r.deletions>0?i.jsxs("span",{className:s.del,children:["-",r.deletions]}):null]})]},r.id))}),i.jsxs("div",{className:s.body,children:[i.jsxs("div",{className:s.fileHeader,children:[i.jsx("span",{className:s.filePath,children:c.displayPath}),i.jsxs("div",{className:s.modeToggle,role:"group","aria-label":"Diff view mode",children:[i.jsx("button",{type:"button","aria-pressed":t==="unified",className:t==="unified"?s.modeActive:"",onClick:()=>a("unified"),children:"Unified"}),i.jsx("button",{type:"button","aria-pressed":t==="split",className:t==="split"?s.modeActive:"",onClick:()=>a("split"),children:"Split"})]})]}),c.unparsedNotice?i.jsx("pre",{className:s.notice,children:c.unparsedNotice}):null,c.hunks.length===0&&!c.unparsedNotice?i.jsx("p",{className:s.emptyFile,children:"No line-level changes captured for this file."}):c.hunks.map((r,h)=>i.jsx($e,{hunk:r,mode:t,path:c.displayPath},h))]})]})}function $e({hunk:l,mode:d,path:e}){const o=z(e);if(d==="split"){const n=H(l.lines);return i.jsxs("table",{className:`${s.hunkTable} ${s.hunkTableSplit}`,children:[i.jsx("caption",{className:s.hunkCaption,children:l.header}),i.jsx("tbody",{children:n.map((t,a)=>i.jsxs("tr",{children:[i.jsx("td",{className:s.lineNo,children:t.left?.oldLineNo??""}),i.jsx("td",{className:`${s.lineText} ${t.left?s[`row_${t.left.kind}`]:s.rowBlank}`,children:t.left?i.jsx(S,{text:t.left.text,lang:o}):null}),i.jsx("td",{className:s.lineNo,children:t.right?.newLineNo??""}),i.jsx("td",{className:`${s.lineText} ${t.right?s[`row_${t.right.kind}`]:s.rowBlank}`,children:t.right?i.jsx(S,{text:t.right.text,lang:o}):null})]},a))})]})}return i.jsxs("table",{className:s.hunkTable,children:[i.jsx("caption",{className:s.hunkCaption,children:l.header}),i.jsx("tbody",{children:l.lines.map((n,t)=>i.jsxs("tr",{className:s[`row_${n.kind}`],children:[i.jsx("td",{className:s.lineNo,children:n.oldLineNo??""}),i.jsx("td",{className:s.lineNo,children:n.newLineNo??""}),i.jsx("td",{className:s.lineMarker,"aria-hidden":"true",children:n.kind==="add"?"+":n.kind==="del"?"-":""}),i.jsx("td",{className:s.lineText,children:i.jsx(S,{text:n.text,lang:o})})]},t))})]})}function S({text:l,lang:d}){const e=Z(l,d);return i.jsx("code",{className:s.code,children:e.map((o,n)=>i.jsx("span",{className:s[`tok_${o.kind}`],children:o.text},n))})}export{Te as D,z as l,C as p,Z as t};
|
|
7
|
-
//# sourceMappingURL=DiffViewer-DmPJbeM_.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DiffViewer-DmPJbeM_.js","sources":["../../../../../../src/web-ui/routes/inbox/diff-parser.ts","../../../../../../src/web-ui/routes/inbox/highlight.ts","../../../../../../src/web-ui/routes/inbox/DiffViewer.tsx"],"sourcesContent":["/**\n * routes/inbox/diff-parser.ts — pure parsing of a unified diff string\n * (Proposal.diff, src/core/types.ts) into a per-file, per-hunk structure the\n * DiffViewer can render with a file tree and syntax highlighting, instead of\n * dumping the raw string into an escaped <pre> block (the old UI's\n * approach — \"not acceptable for a tool meant to be elite\" per the\n * operator-console brief). No dependency: hand-rolled parser over the\n * unified diff format, which is regular enough (`--- `/`+++ `/`@@ `/leading\n * `-`/`+`/` `) that a small line-scan state machine covers it completely.\n *\n * Pure functions only — no React, no DOM — so this is trivially unit\n * testable (see diff-parser.test.ts) independent of rendering.\n */\n\nexport type DiffLineKind = 'context' | 'add' | 'del';\n\nexport interface DiffLine {\n kind: DiffLineKind;\n text: string;\n oldLineNo: number | null;\n newLineNo: number | null;\n}\n\nexport interface DiffHunk {\n header: string;\n oldStart: number;\n oldLines: number;\n newStart: number;\n newLines: number;\n lines: DiffLine[];\n}\n\nexport type FileChangeStatus = 'added' | 'deleted' | 'renamed' | 'modified';\n\nexport interface DiffFile {\n /** Stable key for React lists / file-tree selection. */\n id: string;\n oldPath: string | null;\n newPath: string | null;\n /** The path to show — newPath, falling back to oldPath for deletes. */\n displayPath: string;\n status: FileChangeStatus;\n hunks: DiffHunk[];\n additions: number;\n deletions: number;\n /** Raw text that didn't parse as hunks (e.g. a \"Binary files differ\"\n * notice) — preserved verbatim so nothing is silently dropped. */\n unparsedNotice: string | null;\n}\n\nexport interface ParsedDiff {\n files: DiffFile[];\n /** True when the input didn't look like a unified diff at all (no\n * `--- `/`+++ ` pairs found) — the raw string is returned as one\n * unparsed \"file\" so the viewer can still show *something*. */\n malformed: boolean;\n}\n\nconst FILE_HEADER_RE = /^diff --git a\\/(.+) b\\/(.+)$/;\nconst OLD_PATH_RE = /^--- (?:a\\/(.+)|(\\/dev\\/null))\\s*$/;\nconst NEW_PATH_RE = /^\\+\\+\\+ (?:b\\/(.+)|(\\/dev\\/null))\\s*$/;\nconst HUNK_HEADER_RE = /^@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@(.*)$/;\n\nfunction stripPathPrefix(p: string): string {\n return p.replace(/^[ab]\\//, '');\n}\n\n/** Split raw text into per-file chunks: before each `diff --git` line if\n * any are present, otherwise before each `--- ` line. */\nfunction splitFileChunks(text: string): string[] {\n const lines = text.split('\\n');\n const hasGitHeaders = lines.some((l) => FILE_HEADER_RE.test(l));\n const starts: number[] = [];\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n if (hasGitHeaders ? FILE_HEADER_RE.test(line) : OLD_PATH_RE.test(line)) starts.push(i);\n }\n if (starts.length === 0) return [];\n const chunks: string[] = [];\n for (let i = 0; i < starts.length; i++) {\n const from = starts[i]!;\n const to = i + 1 < starts.length ? starts[i + 1]! : lines.length;\n chunks.push(lines.slice(from, to).join('\\n'));\n }\n return chunks;\n}\n\nfunction parseFileChunk(chunk: string, index: number): DiffFile {\n const lines = chunk.split('\\n');\n // A trailing '\\n' in the source text produces one trailing empty array\n // element that is never real diff content — every genuine line (context/\n // add/del) carries at least its 1-char marker (' '/'+'/'-'), so an empty\n // string here can only be that artifact. Drop it before parsing so it\n // isn't mistaken for a blank context line inside the last hunk.\n if (lines.length > 0 && lines[lines.length - 1] === '') lines.pop();\n let oldPath: string | null = null;\n let newPath: string | null = null;\n let bodyStart = -1;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n const oldMatch = OLD_PATH_RE.exec(line);\n if (oldMatch) {\n oldPath = oldMatch[2] ? null : stripPathPrefix(oldMatch[1]!);\n continue;\n }\n const newMatch = NEW_PATH_RE.exec(line);\n if (newMatch) {\n newPath = newMatch[2] ? null : stripPathPrefix(newMatch[1]!);\n bodyStart = i + 1;\n break;\n }\n const gitHeader = FILE_HEADER_RE.exec(line);\n if (gitHeader && oldPath === null && newPath === null) {\n // Fallback path source used only if the chunk never reaches a proper\n // `+++` line (e.g. a binary-file notice with no hunks at all).\n oldPath = gitHeader[1] ?? null;\n newPath = gitHeader[2] ?? null;\n }\n }\n\n let status: FileChangeStatus = 'modified';\n if (oldPath === null && newPath !== null) status = 'added';\n else if (oldPath !== null && newPath === null) status = 'deleted';\n else if (oldPath !== null && newPath !== null && oldPath !== newPath) status = 'renamed';\n\n const displayPath = newPath ?? oldPath ?? `(unknown file ${index + 1})`;\n\n const hunks: DiffHunk[] = [];\n let additions = 0;\n let deletions = 0;\n let unparsedNotice: string | null = null;\n\n if (bodyStart === -1) {\n // Never found a `+++` line at all — likely a binary-file notice or a\n // chunk this parser doesn't understand. Preserve it verbatim.\n const trimmed = lines.join('\\n').trim();\n return {\n id: `${index}:${displayPath}`,\n oldPath,\n newPath,\n displayPath,\n status,\n hunks: [],\n additions: 0,\n deletions: 0,\n unparsedNotice: trimmed || null,\n };\n }\n\n let i = bodyStart;\n while (i < lines.length) {\n const header = HUNK_HEADER_RE.exec(lines[i]!);\n if (!header) {\n // Stray text between the file header and the first hunk (rare) —\n // fold into the notice rather than lose it.\n if (lines[i]!.trim()) {\n unparsedNotice = ((unparsedNotice ? unparsedNotice + '\\n' : '') + lines[i]).trim();\n }\n i++;\n continue;\n }\n const oldStart = Number(header[1]);\n const oldLines = header[2] !== undefined ? Number(header[2]) : 1;\n const newStart = Number(header[3]);\n const newLines = header[4] !== undefined ? Number(header[4]) : 1;\n const hunk: DiffHunk = { header: lines[i]!, oldStart, oldLines, newStart, newLines, lines: [] };\n i++;\n let oldNo = oldStart;\n let newNo = newStart;\n while (i < lines.length && !HUNK_HEADER_RE.test(lines[i]!)) {\n const raw = lines[i]!;\n if (raw.startsWith('\\\\')) {\n i++;\n continue; // \"\\"\n }\n const marker = raw[0];\n const text = raw.slice(1);\n if (marker === '+') {\n hunk.lines.push({ kind: 'add', text, oldLineNo: null, newLineNo: newNo });\n newNo++;\n additions++;\n } else if (marker === '-') {\n hunk.lines.push({ kind: 'del', text, oldLineNo: oldNo, newLineNo: null });\n oldNo++;\n deletions++;\n } else {\n // Context line (leading space), or an empty line inside a hunk.\n hunk.lines.push({ kind: 'context', text: marker === ' ' ? text : raw, oldLineNo: oldNo, newLineNo: newNo });\n oldNo++;\n newNo++;\n }\n i++;\n }\n hunks.push(hunk);\n }\n\n return { id: `${index}:${displayPath}`, oldPath, newPath, displayPath, status, hunks, additions, deletions, unparsedNotice };\n}\n\nexport function parseUnifiedDiff(raw: string | undefined | null): ParsedDiff {\n const text = raw ?? '';\n if (!text.trim()) return { files: [], malformed: false };\n const chunks = splitFileChunks(text);\n if (chunks.length === 0) {\n return {\n malformed: true,\n files: [\n {\n id: 'raw',\n oldPath: null,\n newPath: null,\n displayPath: '(unparsed diff)',\n status: 'modified',\n hunks: [],\n additions: 0,\n deletions: 0,\n unparsedNotice: text,\n },\n ],\n };\n }\n return { files: chunks.map((c, idx) => parseFileChunk(c, idx)), malformed: false };\n}\n\nexport interface SplitRow {\n left: DiffLine | null;\n right: DiffLine | null;\n}\n\n/** Zip a hunk's lines into side-by-side rows for the split view: a run of\n * consecutive deletions is paired with the following run of consecutive\n * additions (the usual shape of a changed block), padding the shorter side\n * with a blank cell. Pure context lines occupy both sides identically. */\nexport function toSplitRows(lines: DiffLine[]): SplitRow[] {\n const rows: SplitRow[] = [];\n let i = 0;\n while (i < lines.length) {\n const line = lines[i]!;\n if (line.kind === 'context') {\n rows.push({ left: line, right: line });\n i++;\n continue;\n }\n const dels: DiffLine[] = [];\n while (i < lines.length && lines[i]!.kind === 'del') {\n dels.push(lines[i]!);\n i++;\n }\n const adds: DiffLine[] = [];\n while (i < lines.length && lines[i]!.kind === 'add') {\n adds.push(lines[i]!);\n i++;\n }\n const n = Math.max(dels.length, adds.length);\n for (let j = 0; j < n; j++) rows.push({ left: dels[j] ?? null, right: adds[j] ?? null });\n }\n return rows;\n}\n","/**\n * routes/inbox/highlight.ts — minimal, dependency-free syntax highlighting\n * for the diff viewer. Per the operator-console brief: \"do NOT pull in a\n * heavy dependency without checking what's already available — hand-rolled\n * highlighting for common languages is acceptable and preferable to a large\n * runtime dep.\" This is a single-pass tokenizer per *line* (the diff viewer\n * already renders line-by-line) — cross-line state like multi-line block\n * comments is intentionally not tracked, so an occasional line inside a\n * block comment may be mis-colored. That's a fine trade for zero\n * dependencies and O(n) rendering with no dependency on the file's context\n * outside the visible hunk.\n */\n\nexport type TokenKind = 'plain' | 'comment' | 'string' | 'number' | 'keyword';\n\nexport interface Token {\n kind: TokenKind;\n text: string;\n}\n\nexport type LangFamily = 'c-like' | 'python' | 'shell' | 'css' | 'json' | 'yaml' | 'plain';\n\nconst EXT_TO_FAMILY: Record<string, LangFamily> = {\n ts: 'c-like', tsx: 'c-like', js: 'c-like', jsx: 'c-like', mjs: 'c-like', cjs: 'c-like', mts: 'c-like', cts: 'c-like',\n java: 'c-like', go: 'c-like', rs: 'c-like', c: 'c-like', h: 'c-like', cpp: 'c-like', hpp: 'c-like', cc: 'c-like',\n swift: 'c-like', kt: 'c-like', kts: 'c-like',\n py: 'python', pyi: 'python',\n sh: 'shell', bash: 'shell', zsh: 'shell',\n css: 'css', scss: 'css', less: 'css',\n json: 'json', jsonc: 'json',\n yml: 'yaml', yaml: 'yaml',\n};\n\nexport function languageForPath(path: string | null | undefined): LangFamily {\n if (!path) return 'plain';\n const ext = path.split('.').pop()?.toLowerCase() ?? '';\n return EXT_TO_FAMILY[ext] ?? 'plain';\n}\n\nconst KEYWORDS: Record<LangFamily, Set<string>> = {\n 'c-like': new Set([\n 'const', 'let', 'var', 'function', 'return', 'if', 'else', 'for', 'while', 'do', 'switch', 'case',\n 'break', 'continue', 'class', 'extends', 'implements', 'interface', 'type', 'enum', 'export', 'import',\n 'from', 'default', 'new', 'this', 'super', 'try', 'catch', 'finally', 'throw', 'async', 'await',\n 'yield', 'static', 'public', 'private', 'protected', 'readonly', 'abstract', 'null', 'undefined',\n 'true', 'false', 'void', 'typeof', 'instanceof', 'in', 'of', 'as', 'is', 'never', 'unknown', 'any',\n 'package', 'struct', 'fn', 'impl', 'mod', 'pub', 'use', 'trait', 'match', 'func', 'defer', 'chan',\n ]),\n python: new Set([\n 'def', 'class', 'return', 'if', 'elif', 'else', 'for', 'while', 'break', 'continue', 'import', 'from',\n 'as', 'with', 'try', 'except', 'finally', 'raise', 'pass', 'lambda', 'yield', 'async', 'await', 'None',\n 'True', 'False', 'and', 'or', 'not', 'in', 'is', 'global', 'nonlocal', 'self',\n ]),\n shell: new Set([\n 'if', 'then', 'else', 'elif', 'fi', 'for', 'while', 'do', 'done', 'case', 'esac', 'function', 'return',\n 'export', 'local', 'echo', 'set', 'in', 'break', 'continue',\n ]),\n css: new Set(),\n json: new Set(),\n yaml: new Set(),\n plain: new Set(),\n};\n\n// One combined rule regex per family, using named groups so a single\n// generic scan loop works for every family regardless of which groups it\n// defines. First match wins scanning left-to-right; the gaps between\n// matches become plain-text tokens verbatim.\nconst RULES: Partial<Record<LangFamily, RegExp>> = {\n 'c-like':\n /(?<comment>\\/\\/.*$|\\/\\*.*?\\*\\/)|(?<string>\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|`(?:[^`\\\\]|\\\\.)*`)|(?<number>\\b\\d+(?:\\.\\d+)?\\b)|(?<word>[A-Za-z_$][A-Za-z0-9_$]*)/g,\n python:\n /(?<comment>#.*$)|(?<string>\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*')|(?<number>\\b\\d+(?:\\.\\d+)?\\b)|(?<word>[A-Za-z_][A-Za-z0-9_]*)/g,\n shell: /(?<comment>#.*$)|(?<string>\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*')|(?<word>[A-Za-z_][A-Za-z0-9_]*)/g,\n css: /(?<comment>\\/\\*.*?\\*\\/)|(?<string>\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*')|(?<number>\\b\\d+(?:\\.\\d+)?\\b)|(?<word>[A-Za-z_-][A-Za-z0-9_-]*)/g,\n json: /(?<string>\"(?:[^\"\\\\]|\\\\.)*\")|(?<number>-?\\b\\d+(?:\\.\\d+)?\\b)|(?<word>\\btrue\\b|\\bfalse\\b|\\bnull\\b)/g,\n yaml: /(?<comment>#.*$)|(?<string>\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*')/g,\n};\n\nexport function tokenizeLine(text: string, family: LangFamily): Token[] {\n const rule = RULES[family];\n if (!rule) return [{ kind: 'plain', text }];\n const keywords = KEYWORDS[family];\n const tokens: Token[] = [];\n let last = 0;\n rule.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = rule.exec(text))) {\n if (match.index > last) tokens.push({ kind: 'plain', text: text.slice(last, match.index) });\n const g = match.groups ?? {};\n if (g.comment !== undefined) {\n tokens.push({ kind: 'comment', text: match[0] });\n } else if (g.string !== undefined) {\n tokens.push({ kind: 'string', text: match[0] });\n } else if (g.number !== undefined) {\n tokens.push({ kind: 'number', text: match[0] });\n } else if (g.word !== undefined) {\n const isKeyword = family === 'json' || keywords.has(g.word);\n tokens.push({ kind: isKeyword ? 'keyword' : 'plain', text: match[0] });\n } else {\n tokens.push({ kind: 'plain', text: match[0] });\n }\n last = match.index + match[0].length;\n if (match[0].length === 0) rule.lastIndex++; // guard against zero-width matches\n }\n if (last < text.length) tokens.push({ kind: 'plain', text: text.slice(last) });\n return tokens;\n}\n","/**\n * routes/inbox/DiffViewer.tsx — the core review interaction (operator-\n * console brief item 2). A multi-file unified diff gets a file tree plus a\n * syntax-highlighted, split/unified-toggleable hunk view instead of one\n * escaped <pre> block (the old UI's approach). No diff/highlighting\n * dependency: diff-parser.ts and highlight.ts are both hand-rolled per the\n * foundation's \"keep new runtime deps minimal\" constraint — checked\n * package.json first; nothing suitable was already a dependency.\n */\nimport { useEffect, useMemo, useState, type ReactNode } from 'react';\nimport { parseUnifiedDiff, toSplitRows, type DiffHunk } from './diff-parser.js';\nimport { languageForPath, tokenizeLine, type LangFamily } from './highlight.js';\nimport styles from './DiffViewer.module.css';\n\ntype ViewMode = 'unified' | 'split';\n\nexport function DiffViewer({ diff, proposalKind }: { diff: string | undefined; proposalKind: string }) {\n const parsed = useMemo(() => parseUnifiedDiff(diff), [diff]);\n const [selectedId, setSelectedId] = useState<string | null>(parsed.files[0]?.id ?? null);\n const [mode, setMode] = useState<ViewMode>('unified');\n\n // Diff identity changed (a different proposal is now shown) — reset the\n // selected file rather than holding on to a stale id from the last one.\n useEffect(() => {\n setSelectedId(parsed.files[0]?.id ?? null);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- reset on diff content change only\n }, [diff]);\n\n if (parsed.files.length === 0) {\n return (\n <div className={styles.empty}>No diff attached to this proposal (kind: {proposalKind}).</div>\n );\n }\n\n const selected = parsed.files.find((f) => f.id === selectedId) ?? parsed.files[0]!;\n\n function onTreeKeyDown(e: React.KeyboardEvent) {\n const idx = parsed.files.findIndex((f) => f.id === selected.id);\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelectedId(parsed.files[Math.min(idx + 1, parsed.files.length - 1)]!.id);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelectedId(parsed.files[Math.max(idx - 1, 0)]!.id);\n }\n }\n\n return (\n <div className={styles.viewer}>\n {parsed.malformed ? (\n <p className={styles.malformedNotice}>Could not parse this as a unified diff — showing raw content.</p>\n ) : null}\n <div className={styles.tree} role=\"tree\" aria-label=\"Changed files\" onKeyDown={onTreeKeyDown}>\n {parsed.files.map((f) => (\n <button\n key={f.id}\n type=\"button\"\n role=\"treeitem\"\n aria-selected={f.id === selected.id}\n tabIndex={f.id === selected.id ? 0 : -1}\n className={`${styles.treeItem} ${f.id === selected.id ? styles.treeItemActive : ''}`}\n onClick={() => setSelectedId(f.id)}\n >\n <span className={`${styles.statusDot} ${styles[`status_${f.status}`]}`} aria-hidden=\"true\" />\n <span className={styles.treePath} title={f.displayPath}>\n {f.displayPath}\n </span>\n <span className={styles.treeStats}>\n {f.additions > 0 ? <span className={styles.add}>+{f.additions}</span> : null}\n {f.deletions > 0 ? <span className={styles.del}>-{f.deletions}</span> : null}\n </span>\n </button>\n ))}\n </div>\n\n <div className={styles.body}>\n <div className={styles.fileHeader}>\n <span className={styles.filePath}>{selected.displayPath}</span>\n <div className={styles.modeToggle} role=\"group\" aria-label=\"Diff view mode\">\n <button\n type=\"button\"\n aria-pressed={mode === 'unified'}\n className={mode === 'unified' ? styles.modeActive : ''}\n onClick={() => setMode('unified')}\n >\n Unified\n </button>\n <button\n type=\"button\"\n aria-pressed={mode === 'split'}\n className={mode === 'split' ? styles.modeActive : ''}\n onClick={() => setMode('split')}\n >\n Split\n </button>\n </div>\n </div>\n {selected.unparsedNotice ? <pre className={styles.notice}>{selected.unparsedNotice}</pre> : null}\n {selected.hunks.length === 0 && !selected.unparsedNotice ? (\n <p className={styles.emptyFile}>No line-level changes captured for this file.</p>\n ) : (\n selected.hunks.map((hunk, i) => <Hunk key={i} hunk={hunk} mode={mode} path={selected.displayPath} />)\n )}\n </div>\n </div>\n );\n}\n\nfunction Hunk({ hunk, mode, path }: { hunk: DiffHunk; mode: ViewMode; path: string }) {\n const lang = languageForPath(path);\n if (mode === 'split') {\n const rows = toSplitRows(hunk.lines);\n return (\n <table className={`${styles.hunkTable} ${styles.hunkTableSplit}`}>\n <caption className={styles.hunkCaption}>{hunk.header}</caption>\n <tbody>\n {rows.map((row, i) => (\n <tr key={i}>\n <td className={styles.lineNo}>{row.left?.oldLineNo ?? ''}</td>\n <td className={`${styles.lineText} ${row.left ? styles[`row_${row.left.kind}`] : styles.rowBlank}`}>\n {row.left ? <CodeLine text={row.left.text} lang={lang} /> : null}\n </td>\n <td className={styles.lineNo}>{row.right?.newLineNo ?? ''}</td>\n <td className={`${styles.lineText} ${row.right ? styles[`row_${row.right.kind}`] : styles.rowBlank}`}>\n {row.right ? <CodeLine text={row.right.text} lang={lang} /> : null}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n );\n }\n return (\n <table className={styles.hunkTable}>\n <caption className={styles.hunkCaption}>{hunk.header}</caption>\n <tbody>\n {hunk.lines.map((line, i) => (\n <tr key={i} className={styles[`row_${line.kind}`]}>\n <td className={styles.lineNo}>{line.oldLineNo ?? ''}</td>\n <td className={styles.lineNo}>{line.newLineNo ?? ''}</td>\n <td className={styles.lineMarker} aria-hidden=\"true\">\n {line.kind === 'add' ? '+' : line.kind === 'del' ? '-' : ''}\n </td>\n <td className={styles.lineText}>\n <CodeLine text={line.text} lang={lang} />\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n );\n}\n\nfunction CodeLine({ text, lang }: { text: string; lang: LangFamily }): ReactNode {\n const tokens = tokenizeLine(text, lang);\n return (\n <code className={styles.code}>\n {tokens.map((t, i) => (\n <span key={i} className={styles[`tok_${t.kind}`]}>\n {t.text}\n </span>\n ))}\n </code>\n );\n}\n"],"names":["FILE_HEADER_RE","OLD_PATH_RE","NEW_PATH_RE","HUNK_HEADER_RE","stripPathPrefix","p","splitFileChunks","text","lines","hasGitHeaders","l","starts","i","line","chunks","from","to","parseFileChunk","chunk","index","oldPath","newPath","bodyStart","oldMatch","newMatch","gitHeader","status","displayPath","hunks","additions","deletions","unparsedNotice","trimmed","header","oldStart","oldLines","newStart","newLines","hunk","oldNo","newNo","raw","marker","parseUnifiedDiff","c","idx","toSplitRows","rows","dels","adds","n","j","EXT_TO_FAMILY","languageForPath","path","ext","KEYWORDS","RULES","tokenizeLine","family","rule","keywords","tokens","last","match","g","isKeyword","DiffViewer","diff","proposalKind","parsed","useMemo","selectedId","setSelectedId","useState","mode","setMode","useEffect","jsxs","styles","selected","f","onTreeKeyDown","e","jsx","Hunk","lang","row","CodeLine","t"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._viewer_gf84p_1{display:grid;grid-template-columns:minmax(180px,260px) 1fr;gap:var(--space-4);align-items:start;min-height:0}._malformedNotice_gf84p_9{grid-column:1 / -1;padding:var(--space-2) var(--space-3);border-radius:var(--radius-sm);background:var(--status-warning-bg);color:var(--status-warning-fg);font-size:var(--text-xs-size)}._empty_gf84p_18{padding:var(--space-6);text-align:center;color:var(--text-tertiary);font-size:var(--text-sm-size);border:1px dashed var(--border-default);border-radius:var(--radius-md)}._tree_gf84p_27{display:flex;flex-direction:column;gap:var(--space-1);border:1px solid var(--border-subtle);border-radius:var(--radius-md);padding:var(--space-2);max-height:480px;overflow-y:auto;position:sticky;top:0}._treeItem_gf84p_40{display:flex;align-items:center;gap:var(--space-2);width:100%;padding:var(--space-1) var(--space-2);border-radius:var(--radius-sm);background:transparent;border:none;text-align:left;font-size:var(--text-xs-size);color:var(--text-secondary);cursor:pointer}._treeItem_gf84p_40:hover{background:var(--bg-hover)}._treeItemActive_gf84p_59{background:var(--bg-selected);color:var(--text-primary)}._statusDot_gf84p_64{flex:0 0 auto;width:8px;height:8px;border-radius:var(--radius-full)}._status_added_gf84p_70{background:var(--status-success-solid)}._status_deleted_gf84p_71{background:var(--status-danger-solid)}._status_modified_gf84p_72{background:var(--status-info-solid)}._status_renamed_gf84p_73{background:var(--status-warning-solid)}._treePath_gf84p_75{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--font-mono)}._treeStats_gf84p_83{flex:0 0 auto;display:flex;gap:var(--space-1);font-variant-numeric:tabular-nums}._add_gf84p_89{color:var(--status-success-fg)}._del_gf84p_90{color:var(--status-danger-fg)}._body_gf84p_92{min-width:0;border:1px solid var(--border-subtle);border-radius:var(--radius-md);overflow:hidden}._fileHeader_gf84p_99{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-2) var(--space-3);border-bottom:1px solid var(--border-subtle);background:var(--bg-canvas)}._filePath_gf84p_109{font-family:var(--font-mono);font-size:var(--text-xs-size);color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._modeToggle_gf84p_118{flex:0 0 auto;display:flex;gap:var(--space-1)}._modeToggle_gf84p_118 button{padding:var(--space-1) var(--space-2);font-size:var(--text-xs-size);border-radius:var(--radius-sm);border:1px solid var(--border-default);background:var(--bg-surface);color:var(--text-secondary);cursor:pointer}._modeActive_gf84p_132{background:var(--accent-50);border-color:var(--accent-500)!important;color:var(--accent-600)!important}._notice_gf84p_138{margin:var(--space-3);padding:var(--space-2);background:var(--bg-code);border-radius:var(--radius-sm);font-family:var(--font-mono);font-size:var(--text-xs-size);white-space:pre-wrap;word-break:break-word}._emptyFile_gf84p_149{padding:var(--space-4);color:var(--text-tertiary);font-size:var(--text-sm-size)}._hunkTable_gf84p_155{width:100%;border-collapse:collapse;font-family:var(--font-mono);font-size:var(--text-xs-size);table-layout:fixed}._hunkCaption_gf84p_163{caption-side:top;text-align:left;padding:var(--space-1) var(--space-3);color:var(--text-tertiary);background:var(--bg-canvas);border-bottom:1px solid var(--border-subtle);border-top:1px solid var(--border-subtle)}._lineNo_gf84p_173{width:44px;min-width:44px;padding:0 var(--space-2);text-align:right;color:var(--text-disabled);user-select:none;vertical-align:top;font-variant-numeric:tabular-nums}._lineMarker_gf84p_184{width:16px;min-width:16px;text-align:center;user-select:none;vertical-align:top}._lineText_gf84p_192{padding:0 var(--space-2);white-space:pre-wrap;word-break:break-word;vertical-align:top}._hunkTableSplit_gf84p_199 ._lineText_gf84p_192{width:50%}._rowBlank_gf84p_203{background:var(--bg-canvas)}._row_add_gf84p_207{background:var(--status-success-bg)}._row_del_gf84p_210{background:var(--status-danger-bg)}._row_context_gf84p_213{background:transparent}._code_gf84p_217{font-family:inherit}._tok_plain_gf84p_221{color:var(--text-primary)}._tok_comment_gf84p_222{color:var(--text-tertiary);font-style:italic}._tok_string_gf84p_223{color:var(--status-success-fg)}._tok_number_gf84p_224{color:var(--status-warning-fg)}._tok_keyword_gf84p_225{color:var(--accent-600);font-weight:var(--font-weight-medium)}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._unknown_4gf0c_1{display:inline-flex;align-items:center;gap:var(--space-1);color:var(--status-unknown-fg);font-size:var(--text-sm-size);font-style:italic;cursor:help}._dot_4gf0c_11{width:6px;height:6px;border-radius:var(--radius-full);background:var(--status-unknown-solid);flex-shrink:0}._badge_4gf0c_19{display:inline-flex;align-items:center;padding:1px var(--space-2);border-radius:var(--radius-xs);background:var(--status-unknown-bg);color:var(--status-unknown-fg);font-size:var(--text-xs-size);font-style:italic;cursor:help}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as e}from"./index-BkUlX2Se.js";const i="_unknown_4gf0c_1",u="_dot_4gf0c_11",d="_badge_4gf0c_19",a={unknown:i,dot:u,badge:d};function r(n){return n?n.sourceState==="healthy"&&n.complete!==!1:!0}function f({quality:n,children:s,renderControl:c,label:t}){if(r(n))return e.jsxs(e.Fragment,{children:[s,c?.()]});const o=n?.reason;return e.jsxs("span",{className:a.unknown,title:o?`Unavailable: ${o}`:"Source data unavailable",children:[e.jsx("span",{className:a.dot,"aria-hidden":"true"}),"unknown",t?e.jsxs("span",{className:"visually-hidden",children:[" (",t,")"]}):null]})}function m({quality:n,label:s}){return r(n)?null:e.jsxs("span",{className:a.badge,title:n?.reason??"Source data unavailable",children:[s?`${s}: `:"","unknown"]})}export{f as E,m as a,r as i};
|
|
2
|
-
//# sourceMappingURL=Epistemic-M3SxLHjq.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Epistemic-M3SxLHjq.js","sources":["../../../../../../src/web-ui/components/primitives/Epistemic.tsx"],"sourcesContent":["/**\n * components/primitives/Epistemic.tsx — the one thing the old UI got right,\n * promoted to a first-class primitive (foundation brief, item 7).\n *\n * When a piece of data's `sourceQuality.sourceState` is 'degraded' or\n * 'unknown'/'missing', this component displays \"unknown\" (never a stale or\n * guessed value dressed up as current) AND withholds any control built on\n * top of it (`renderControl` simply never runs). Every future view should\n * wrap sourceQuality-bearing fields in this rather than reinventing the\n * check — that is the whole point of making it a primitive instead of a\n * convention someone has to remember.\n *\n * Reference (old, correct behavior this replaces): app.js:311-314, :336-347.\n */\nimport type { ReactNode } from 'react';\nimport type { SourceQuality } from '../../data/api-types.js';\nimport styles from './Epistemic.module.css';\n\nexport function isKnown(quality: SourceQuality | undefined): boolean {\n if (!quality) return true; // absent quality metadata => field predates the pattern; trust it.\n return quality.sourceState === 'healthy' && quality.complete !== false;\n}\n\nexport interface EpistemicProps {\n quality: SourceQuality | undefined;\n /** Rendered when the value is known-good. */\n children: ReactNode;\n /**\n * A control (button, toggle, link) whose action depends on this data\n * being trustworthy — e.g. \"restart daemon\" next to daemon.running.\n * Omitted entirely (not disabled — omitted) when the source is degraded,\n * so an operator never sees an actionable-looking control wired to a\n * guess.\n */\n renderControl?: () => ReactNode;\n /** Optional label used in the \"unknown\" state, e.g. \"daemon status\". */\n label?: string;\n}\n\nexport function Epistemic({ quality, children, renderControl, label }: EpistemicProps): ReactNode {\n if (isKnown(quality)) {\n return (\n <>\n {children}\n {renderControl?.()}\n </>\n );\n }\n\n const reason = quality?.reason;\n return (\n <span className={styles.unknown} title={reason ? `Unavailable: ${reason}` : 'Source data unavailable'}>\n <span className={styles.dot} aria-hidden=\"true\" />\n unknown\n {label ? <span className=\"visually-hidden\"> ({label})</span> : null}\n </span>\n );\n}\n\n/** Small inline badge form, for table cells / dense rows. */\nexport function EpistemicBadge({ quality, label }: { quality: SourceQuality | undefined; label?: string }): ReactNode {\n if (isKnown(quality)) return null;\n return (\n <span className={styles.badge} title={quality?.reason ?? 'Source data unavailable'}>\n {label ? `${label}: ` : ''}unknown\n </span>\n );\n}\n"],"names":["isKnown","quality","Epistemic","children","renderControl","label","jsxs","Fragment","reason","styles","jsx","EpistemicBadge"],"mappings":"qIAkBO,SAASA,EAAQC,EAA6C,CACnE,OAAKA,EACEA,EAAQ,cAAgB,WAAaA,EAAQ,WAAa,GAD5C,EAEvB,CAkBO,SAASC,EAAU,CAAE,QAAAD,EAAS,SAAAE,EAAU,cAAAC,EAAe,MAAAC,GAAoC,CAChG,GAAIL,EAAQC,CAAO,EACjB,OACEK,EAAAA,KAAAC,WAAA,CACG,SAAA,CAAAJ,EACAC,IAAA,CAAgB,EACnB,EAIJ,MAAMI,EAASP,GAAS,OACxB,OACEK,EAAAA,KAAC,OAAA,CAAK,UAAWG,EAAO,QAAS,MAAOD,EAAS,gBAAgBA,CAAM,GAAK,0BAC1E,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,UAAWD,EAAO,IAAK,cAAY,OAAO,EAAE,UAEjDJ,EAAQC,EAAAA,KAAC,OAAA,CAAK,UAAU,kBAAkB,SAAA,CAAA,KAAGD,EAAM,GAAA,CAAA,CAAC,EAAU,IAAA,EACjE,CAEJ,CAGO,SAASM,EAAe,CAAE,QAAAV,EAAS,MAAAI,GAA4E,CACpH,OAAIL,EAAQC,CAAO,EAAU,KAE3BK,OAAC,QAAK,UAAWG,EAAO,MAAO,MAAOR,GAAS,QAAU,0BACtD,SAAA,CAAAI,EAAQ,GAAGA,CAAK,KAAO,GAAG,SAAA,EAC7B,CAEJ"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._wrap_ti026_1{display:flex;flex-direction:column;gap:var(--space-1);min-width:0}._lineWrap_ti026_8{width:100%}._head_ti026_12{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-2)}._label_ti026_19{font-size:var(--text-xs-size);line-height:var(--text-xs-line);color:var(--text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._value_ti026_28{flex:none;font-family:var(--font-display);font-variant-numeric:tabular-nums;font-size:var(--text-xs-size);letter-spacing:var(--tracking-display);color:var(--text-secondary)}._unknown_ti026_37{font-family:var(--font-ui);font-style:italic;color:var(--status-unknown-fg)}._track_ti026_43{width:100%;overflow:hidden;background:var(--bg-active)}._bar_ti026_49{height:4px;border-radius:var(--radius-full)}._line_ti026_8{height:2px;border-radius:0;background:var(--border-subtle)}._fill_ti026_61{height:100%;transition:width var(--duration-base) var(--ease-standard)}._accent_ti026_66{background:var(--accent-500)}._neutral_ti026_69{background:var(--status-neutral-solid)}._running_ti026_72{background:var(--status-running-solid)}._warning_ti026_75{background:var(--status-warning-solid)}._danger_ti026_78{background:var(--status-danger-solid)}._engine_ti026_81{background:var(--status-neutral-solid)}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as t}from"./index-BkUlX2Se.js";const p="_wrap_ti026_1",k="_lineWrap_ti026_8",m="_head_ti026_12",f="_label_ti026_19",x="_value_ti026_28",b="_unknown_ti026_37",j="_track_ti026_43",v="_bar_ti026_49",N="_line_ti026_8",M="_fill_ti026_61",F="_accent_ti026_66",W="_neutral_ti026_69",y="_running_ti026_72",E="_warning_ti026_75",P="_danger_ti026_78",R="_engine_ti026_81",e={wrap:p,lineWrap:k,head:m,label:f,value:x,unknown:b,track:j,bar:v,line:N,fill:M,accent:F,neutral:W,running:y,warning:E,danger:P,engine:R};function g(n){return n>=1e6?`${(n/1e6).toFixed(n>=1e7?0:1)}m`:n>=1e3?`${(n/1e3).toFixed(n>=1e4?0:1)}k`:String(Math.round(n))}function S(n){return n>=90?"danger":n>=70?"warning":"accent"}function z({value:n,max:r,variant:c="labelled",label:s,valueText:l,tone:h,engineColor:o,className:_,...$}){const i=n!==null&&Number.isFinite(n)&&r!==null&&Number.isFinite(r)&&r>0,a=i?Math.min(100,Math.max(0,n/r*100)):0,u=h??(i?S(a):"neutral"),d=i?l??`${g(n)} / ${g(r)}`:l??"unknown",w=t.jsx("div",{className:`${e.track} ${c==="line"?e.line:e.bar}`,role:"meter","aria-valuenow":i?Math.round(a):void 0,"aria-valuemin":0,"aria-valuemax":100,"aria-valuetext":i?`${Math.round(a)}%`:"unknown",...$,children:t.jsx("div",{className:`${e.fill} ${e[u]}`,style:{width:`${a}%`,...u==="engine"&&o?{background:o}:{}}})});return c==="line"?t.jsx("div",{className:`${e.lineWrap} ${_??""}`,children:w}):t.jsxs("div",{className:`${e.wrap} ${_??""}`,children:[s||d?t.jsxs("div",{className:e.head,children:[s?t.jsx("span",{className:e.label,children:s}):t.jsx("span",{}),t.jsx("span",{className:`${e.value} ${i?"":e.unknown}`,children:d})]}):null,w]})}export{z as M};
|
|
2
|
-
//# sourceMappingURL=Meter-D_X7c9U3.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Meter-D_X7c9U3.js","sources":["../../../../../../src/web-ui/components/primitives/Meter.tsx"],"sourcesContent":["/**\n * components/primitives/Meter.tsx — occupancy against a limit: context\n * window, daily spend against the cap, a plan's usage window.\n *\n * Two forms, one component:\n * variant=\"line\" the 2px full-width rule the design language puts\n * directly under a header strip. No text of its own —\n * wrap it in <Tooltip> and put the numbers beside it.\n * variant=\"labelled\" a 4px bar with a label and a right-aligned\n * \"18k / 66k\" in the display face.\n *\n * Tone thresholds match the V1 context meter (amber >= 70%, danger >= 90%)\n * and are ALWAYS paired with the readable value, never color alone.\n * An unknown limit renders an honest empty track and the text \"unknown\" —\n * never a full bar, never zero (DESIGN.md §7).\n */\nimport type { ReactNode } from 'react';\nimport styles from './Meter.module.css';\n\nexport type MeterTone = 'accent' | 'neutral' | 'running' | 'warning' | 'danger' | 'engine';\n\nexport interface MeterProps {\n /** Current value. null = genuinely unknown. */\n value: number | null;\n /** Limit. null/0 = unknown limit; the meter says so instead of guessing. */\n max: number | null;\n variant?: 'line' | 'labelled';\n label?: ReactNode;\n /** Right-aligned readout. Defaults to `value / max` formatted compactly. */\n valueText?: ReactNode;\n /** Force a tone; by default it is derived from the percentage. */\n tone?: MeterTone;\n /** For tone=\"engine\": the CSS color to paint the fill (an --engine-* var). */\n engineColor?: string;\n /** Accessible name when no visible label is rendered (the line variant). */\n 'aria-label'?: string;\n className?: string;\n}\n\nfunction compact(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(n >= 10_000_000 ? 0 : 1)}m`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(n >= 10_000 ? 0 : 1)}k`;\n return String(Math.round(n));\n}\n\nexport function toneForPercent(percent: number): MeterTone {\n if (percent >= 90) return 'danger';\n if (percent >= 70) return 'warning';\n return 'accent';\n}\n\nexport function Meter({\n value,\n max,\n variant = 'labelled',\n label,\n valueText,\n tone,\n engineColor,\n className,\n ...aria\n}: MeterProps) {\n const known = value !== null && Number.isFinite(value) && max !== null && Number.isFinite(max) && max > 0;\n const percent = known ? Math.min(100, Math.max(0, (value! / max!) * 100)) : 0;\n const resolvedTone = tone ?? (known ? toneForPercent(percent) : 'neutral');\n const readout = known ? (valueText ?? `${compact(value!)} / ${compact(max!)}`) : (valueText ?? 'unknown');\n\n const track = (\n <div\n className={`${styles.track} ${variant === 'line' ? styles.line : styles.bar}`}\n role=\"meter\"\n aria-valuenow={known ? Math.round(percent) : undefined}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuetext={known ? `${Math.round(percent)}%` : 'unknown'}\n {...aria}\n >\n <div\n className={`${styles.fill} ${styles[resolvedTone]}`}\n style={{\n width: `${percent}%`,\n ...(resolvedTone === 'engine' && engineColor ? { background: engineColor } : {}),\n }}\n />\n </div>\n );\n\n if (variant === 'line') return <div className={`${styles.lineWrap} ${className ?? ''}`}>{track}</div>;\n\n return (\n <div className={`${styles.wrap} ${className ?? ''}`}>\n {label || readout ? (\n <div className={styles.head}>\n {label ? <span className={styles.label}>{label}</span> : <span />}\n <span className={`${styles.value} ${known ? '' : styles.unknown}`}>{readout}</span>\n </div>\n ) : null}\n {track}\n </div>\n );\n}\n"],"names":["compact","toneForPercent","percent","Meter","value","max","variant","label","valueText","tone","engineColor","className","aria","known","resolvedTone","readout","track","jsx","styles","jsxs"],"mappings":"+fAuCA,SAASA,EAAQ,EAAmB,CAClC,OAAI,GAAK,IAAkB,IAAI,EAAI,KAAW,QAAQ,GAAK,IAAa,EAAI,CAAC,CAAC,IAC1E,GAAK,IAAc,IAAI,EAAI,KAAO,QAAQ,GAAK,IAAS,EAAI,CAAC,CAAC,IAC3D,OAAO,KAAK,MAAM,CAAC,CAAC,CAC7B,CAEO,SAASC,EAAeC,EAA4B,CACzD,OAAIA,GAAW,GAAW,SACtBA,GAAW,GAAW,UACnB,QACT,CAEO,SAASC,EAAM,CACpB,MAAAC,EACA,IAAAC,EACA,QAAAC,EAAU,WACV,MAAAC,EACA,UAAAC,EACA,KAAAC,EACA,YAAAC,EACA,UAAAC,EACA,GAAGC,CACL,EAAe,CACb,MAAMC,EAAQT,IAAU,MAAQ,OAAO,SAASA,CAAK,GAAKC,IAAQ,MAAQ,OAAO,SAASA,CAAG,GAAKA,EAAM,EAClGH,EAAUW,EAAQ,KAAK,IAAI,IAAK,KAAK,IAAI,EAAIT,EAASC,EAAQ,GAAG,CAAC,EAAI,EACtES,EAAeL,IAASI,EAAQZ,EAAeC,CAAO,EAAI,WAC1Da,EAAUF,EAASL,GAAa,GAAGR,EAAQI,CAAM,CAAC,MAAMJ,EAAQK,CAAI,CAAC,GAAOG,GAAa,UAEzFQ,EACJC,EAAAA,IAAC,MAAA,CACC,UAAW,GAAGC,EAAO,KAAK,IAAIZ,IAAY,OAASY,EAAO,KAAOA,EAAO,GAAG,GAC3E,KAAK,QACL,gBAAeL,EAAQ,KAAK,MAAMX,CAAO,EAAI,OAC7C,gBAAe,EACf,gBAAe,IACf,iBAAgBW,EAAQ,GAAG,KAAK,MAAMX,CAAO,CAAC,IAAM,UACnD,GAAGU,EAEJ,SAAAK,EAAAA,IAAC,MAAA,CACC,UAAW,GAAGC,EAAO,IAAI,IAAIA,EAAOJ,CAAY,CAAC,GACjD,MAAO,CACL,MAAO,GAAGZ,CAAO,IACjB,GAAIY,IAAiB,UAAYJ,EAAc,CAAE,WAAYA,CAAA,EAAgB,CAAA,CAAC,CAChF,CAAA,CACF,CAAA,EAIJ,OAAIJ,IAAY,OAAeW,EAAAA,IAAC,MAAA,CAAI,UAAW,GAAGC,EAAO,QAAQ,IAAIP,GAAa,EAAE,GAAK,SAAAK,EAAM,EAG7FG,OAAC,OAAI,UAAW,GAAGD,EAAO,IAAI,IAAIP,GAAa,EAAE,GAC9C,SAAA,CAAAJ,GAASQ,EACRI,EAAAA,KAAC,MAAA,CAAI,UAAWD,EAAO,KACpB,SAAA,CAAAX,EAAQU,EAAAA,IAAC,QAAK,UAAWC,EAAO,MAAQ,SAAAX,CAAA,CAAM,QAAW,OAAA,CAAA,CAAK,EAC/DU,EAAAA,IAAC,OAAA,CAAK,UAAW,GAAGC,EAAO,KAAK,IAAIL,EAAQ,GAAKK,EAAO,OAAO,GAAK,SAAAH,CAAA,CAAQ,CAAA,CAAA,CAC9E,EACE,KACHC,CAAA,EACH,CAEJ"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as s,j as t}from"./index-BkUlX2Se.js";import{D as y}from"./Dialog-CPmedg4S.js";import{u as N}from"./global-CNVapoV1.js";const R="_body_1kukj_1",w="_form_1kukj_8",E="_label_1kukj_14",g="_inputRow_1kukj_19",C="_input_1kukj_19",I="_reveal_1kukj_40",S="_error_1kukj_51",D="_actions_1kukj_56",M="_cancel_1kukj_63",T="_submit_1kukj_72",e={body:R,form:w,label:E,inputRow:g,input:C,reveal:I,error:S,actions:D,cancel:M,submit:T},F=/^[a-f0-9]{64}$/;function $({open:p,onClose:o,onUnlocked:_,reason:k,tokenLabel:h="Mutation token",tokenHelp:f="the mutation token ashlr serve printed"}){const{setToken:b}=N(),[n,i]=s.useState(""),[r,j]=s.useState(!1),[l,c]=s.useState(null),u=s.useRef(null),x=s.useId(),m=s.useId();function v(a){a.preventDefault();const d=n.trim();if(!F.test(d)){c(`Expected 64 hex characters — ${f}.`);return}b(d),i(""),c(null),o(),_?.()}return t.jsxs(y,{open:p,onClose:o,titleId:x,title:"Unlock actions",initialFocusRef:u,children:[t.jsxs("p",{className:e.body,children:[k??"This action mutates the fleet and requires the dispatch token."," It is held in memory only, for this browser tab, and is cleared automatically after 20 minutes idle."]}),t.jsxs("form",{onSubmit:v,className:e.form,noValidate:!0,children:[t.jsx("label",{htmlFor:m,className:e.label,children:h}),t.jsxs("div",{className:e.inputRow,children:[t.jsx("input",{ref:u,id:m,type:r?"text":"password",autoComplete:"off",autoCorrect:"off",spellCheck:!1,className:e.input,value:n,onChange:a=>i(a.target.value),"aria-invalid":l?!0:void 0,placeholder:"64 hex characters"}),t.jsx("button",{type:"button",className:e.reveal,onClick:()=>j(a=>!a),"aria-pressed":r,children:r?"Hide":"Show"})]}),l?t.jsx("p",{className:e.error,role:"alert",children:l}):null,t.jsxs("div",{className:e.actions,children:[t.jsx("button",{type:"button",className:e.cancel,onClick:o,children:"Cancel"}),t.jsx("button",{type:"submit",className:e.submit,disabled:n.trim().length===0,children:"Unlock"})]})]})]})}export{$ as M};
|
|
2
|
-
//# sourceMappingURL=MutationTokenDialog-Ba5ZHu-8.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MutationTokenDialog-Ba5ZHu-8.js","sources":["../../../../../../src/web-ui/components/auth/MutationTokenDialog.tsx"],"sourcesContent":["/**\n * components/auth/MutationTokenDialog.tsx — replaces window.prompt() for\n * the mutation token (foundation brief item 5, the \"biggest reason\n * operators abandon the UI for the CLI\" finding). A focus-managed dialog\n * instead of a blocking native prompt, and a session-scoped hold (see\n * auth-store.ts) so approving 12 proposals is one paste, not twelve.\n *\n * The token is NEVER written to localStorage/sessionStorage/cookies — only\n * held in an in-memory module variable in auth-store.ts, cleared on tab\n * close, idle timeout, or the explicit \"Lock\" action here.\n */\nimport { useId, useRef, useState, type FormEvent } from 'react';\nimport { Dialog } from '../primitives/Dialog.js';\nimport { useMutationHold } from '../../data/hooks.js';\nimport styles from './MutationTokenDialog.module.css';\n\nconst TOKEN_RE = /^[a-f0-9]{64}$/;\n\nexport interface MutationTokenDialogProps {\n open: boolean;\n onClose: () => void;\n onUnlocked?: () => void;\n /** Human context for why the token is being requested right now. */\n reason?: string;\n /** Scoped consoles can name their own startup token without changing the hold. */\n tokenLabel?: string;\n tokenHelp?: string;\n}\n\nexport function MutationTokenDialog({ open, onClose, onUnlocked, reason, tokenLabel = 'Mutation token',\n tokenHelp = 'the mutation token ashlr serve printed' }: MutationTokenDialogProps) {\n const { setToken } = useMutationHold();\n const [value, setValue] = useState('');\n const [reveal, setReveal] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const titleId = useId();\n const inputId = useId();\n\n function submit(e: FormEvent) {\n e.preventDefault();\n const trimmed = value.trim();\n if (!TOKEN_RE.test(trimmed)) {\n setError(`Expected 64 hex characters — ${tokenHelp}.`);\n return;\n }\n setToken(trimmed);\n setValue('');\n setError(null);\n onClose();\n onUnlocked?.();\n }\n\n return (\n <Dialog open={open} onClose={onClose} titleId={titleId} title=\"Unlock actions\" initialFocusRef={inputRef}>\n <p className={styles.body}>\n {reason ?? 'This action mutates the fleet and requires the dispatch token.'} It is held in\n memory only, for this browser tab, and is cleared automatically after 20 minutes idle.\n </p>\n <form onSubmit={submit} className={styles.form} noValidate>\n <label htmlFor={inputId} className={styles.label}>\n {tokenLabel}\n </label>\n <div className={styles.inputRow}>\n <input\n ref={inputRef}\n id={inputId}\n type={reveal ? 'text' : 'password'}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n className={styles.input}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n aria-invalid={error ? true : undefined}\n placeholder=\"64 hex characters\"\n />\n <button\n type=\"button\"\n className={styles.reveal}\n onClick={() => setReveal((r) => !r)}\n aria-pressed={reveal}\n >\n {reveal ? 'Hide' : 'Show'}\n </button>\n </div>\n {error ? (\n <p className={styles.error} role=\"alert\">\n {error}\n </p>\n ) : null}\n <div className={styles.actions}>\n <button type=\"button\" className={styles.cancel} onClick={onClose}>\n Cancel\n </button>\n <button type=\"submit\" className={styles.submit} disabled={value.trim().length === 0}>\n Unlock\n </button>\n </div>\n </form>\n </Dialog>\n );\n}\n"],"names":["TOKEN_RE","MutationTokenDialog","open","onClose","onUnlocked","reason","tokenLabel","tokenHelp","setToken","useMutationHold","value","setValue","useState","reveal","setReveal","error","setError","inputRef","useRef","titleId","useId","inputId","submit","e","trimmed","jsxs","Dialog","styles","jsx","r"],"mappings":"6aAgBMA,EAAW,iBAaV,SAASC,EAAoB,CAAE,KAAAC,EAAM,QAAAC,EAAS,WAAAC,EAAY,OAAAC,EAAQ,WAAAC,EAAa,iBACpF,UAAAC,EAAY,wCAAyC,EAA6B,CAClF,KAAM,CAAE,SAAAC,CAAA,EAAaC,EAAA,EACf,CAACC,EAAOC,CAAQ,EAAIC,EAAAA,SAAS,EAAE,EAC/B,CAACC,EAAQC,CAAS,EAAIF,EAAAA,SAAS,EAAK,EACpC,CAACG,EAAOC,CAAQ,EAAIJ,EAAAA,SAAwB,IAAI,EAChDK,EAAWC,EAAAA,OAAyB,IAAI,EACxCC,EAAUC,EAAAA,MAAA,EACVC,EAAUD,EAAAA,MAAA,EAEhB,SAASE,EAAOC,EAAc,CAC5BA,EAAE,eAAA,EACF,MAAMC,EAAUd,EAAM,KAAA,EACtB,GAAI,CAACV,EAAS,KAAKwB,CAAO,EAAG,CAC3BR,EAAS,gCAAgCT,CAAS,GAAG,EACrD,MACF,CACAC,EAASgB,CAAO,EAChBb,EAAS,EAAE,EACXK,EAAS,IAAI,EACbb,EAAA,EACAC,IAAA,CACF,CAEA,OACEqB,OAACC,GAAO,KAAAxB,EAAY,QAAAC,EAAkB,QAAAgB,EAAkB,MAAM,iBAAiB,gBAAiBF,EAC9F,SAAA,CAAAQ,EAAAA,KAAC,IAAA,CAAE,UAAWE,EAAO,KAClB,SAAA,CAAAtB,GAAU,iEAAiE,uGAAA,EAE9E,EACAoB,EAAAA,KAAC,QAAK,SAAUH,EAAQ,UAAWK,EAAO,KAAM,WAAU,GACxD,SAAA,CAAAC,MAAC,SAAM,QAASP,EAAS,UAAWM,EAAO,MACxC,SAAArB,EACH,EACAmB,EAAAA,KAAC,MAAA,CAAI,UAAWE,EAAO,SACrB,SAAA,CAAAC,EAAAA,IAAC,QAAA,CACC,IAAKX,EACL,GAAII,EACJ,KAAMR,EAAS,OAAS,WACxB,aAAa,MACb,YAAY,MACZ,WAAY,GACZ,UAAWc,EAAO,MAClB,MAAAjB,EACA,SAAWa,GAAMZ,EAASY,EAAE,OAAO,KAAK,EACxC,eAAcR,EAAQ,GAAO,OAC7B,YAAY,mBAAA,CAAA,EAEda,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,UAAWD,EAAO,OAClB,QAAS,IAAMb,EAAWe,GAAM,CAACA,CAAC,EAClC,eAAchB,EAEb,WAAS,OAAS,MAAA,CAAA,CACrB,EACF,EACCE,QACE,IAAA,CAAE,UAAWY,EAAO,MAAO,KAAK,QAC9B,SAAAZ,CAAA,CACH,EACE,KACJU,EAAAA,KAAC,MAAA,CAAI,UAAWE,EAAO,QACrB,SAAA,CAAAC,EAAAA,IAAC,SAAA,CAAO,KAAK,SAAS,UAAWD,EAAO,OAAQ,QAASxB,EAAS,SAAA,QAAA,CAElE,EACAyB,EAAAA,IAAC,SAAA,CAAO,KAAK,SAAS,UAAWD,EAAO,OAAQ,SAAUjB,EAAM,KAAA,EAAO,SAAW,EAAG,SAAA,QAAA,CAErF,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,EACF,CAEJ"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._root_1lgxn_1{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px}._spinner_1lgxn_9{width:12px;height:12px;border-radius:var(--radius-full);border:2px solid var(--border-strong);border-top-color:var(--accent-500);animation:_spin_1lgxn_9 .7s linear infinite}@keyframes _spin_1lgxn_9{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){:root:not([data-motion=full]) ._spinner_1lgxn_9{animation:none;border-top-color:var(--border-strong)}}:root[data-motion=reduce] ._spinner_1lgxn_9{animation:none;border-top-color:var(--border-strong)}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as s}from"./index-BkUlX2Se.js";const r="_root_1lgxn_1",o="_spinner_1lgxn_9",n={root:r,spinner:o};function a({label:e="Refreshing"}){return s.jsxs("span",{className:n.root,role:"status","aria-live":"polite",children:[s.jsx("span",{className:n.spinner,"aria-hidden":"true"}),s.jsx("span",{className:"visually-hidden",children:e})]})}export{a as R};
|
|
2
|
-
//# sourceMappingURL=RefreshIndicator-vHGpmyzb.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RefreshIndicator-vHGpmyzb.js","sources":["../../../../../../src/web-ui/components/primitives/RefreshIndicator.tsx"],"sourcesContent":["/**\n * components/primitives/RefreshIndicator.tsx — the \"stale data, quietly\n * refreshing\" signal (foundation brief item 4: never blank the screen on\n * refresh). Pair with a QueryEntry's `status`:\n *\n * loading -> render a Skeleton instead of the view\n * refreshing -> render the view with data, plus <RefreshIndicator />\n * success -> render the view with data, no indicator\n * error -> render the view's error state\n */\nimport styles from './RefreshIndicator.module.css';\n\nexport function RefreshIndicator({ label = 'Refreshing' }: { label?: string }) {\n return (\n <span className={styles.root} role=\"status\" aria-live=\"polite\">\n <span className={styles.spinner} aria-hidden=\"true\" />\n <span className=\"visually-hidden\">{label}</span>\n </span>\n );\n}\n"],"names":["RefreshIndicator","label","jsxs","styles","jsx"],"mappings":"0GAYO,SAASA,EAAiB,CAAE,MAAAC,EAAQ,cAAoC,CAC7E,OACEC,OAAC,QAAK,UAAWC,EAAO,KAAM,KAAK,SAAS,YAAU,SACpD,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,UAAWD,EAAO,QAAS,cAAY,OAAO,EACpDC,EAAAA,IAAC,OAAA,CAAK,UAAU,kBAAmB,SAAAH,CAAA,CAAM,CAAA,EAC3C,CAEJ"}
|