@sleep2agi/agent-network-dashboard 0.4.6-preview.28 → 0.4.6-preview.281
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/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +41 -41
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +2 -2
- package/.next/server/app/_not-found.rsc +12 -12
- package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/server/app/admin.html +2 -2
- package/.next/server/app/admin.rsc +14 -14
- package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
- package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
- package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +14 -14
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +7 -7
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +2 -2
- package/.next/server/app/login.rsc +14 -14
- package/.next/server/app/login.segments/_full.segment.rsc +14 -14
- package/.next/server/app/login.segments/_head.segment.rsc +4 -4
- package/.next/server/app/login.segments/_index.segment.rsc +7 -7
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/login.segments/login.segment.rsc +3 -3
- package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +2 -2
- package/.next/server/app/logs.rsc +14 -14
- package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
- package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
- package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +2 -2
- package/.next/server/app/messages.rsc +14 -14
- package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
- package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
- package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
- package/.next/server/app/node/page_client-reference-manifest.js +1 -1
- package/.next/server/app/node.html +2 -2
- package/.next/server/app/node.rsc +14 -14
- package/.next/server/app/node.segments/_full.segment.rsc +14 -14
- package/.next/server/app/node.segments/_head.segment.rsc +4 -4
- package/.next/server/app/node.segments/_index.segment.rsc +7 -7
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/node.segments/node.segment.rsc +3 -3
- package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/nodes.html +2 -2
- package/.next/server/app/nodes.rsc +14 -14
- package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
- package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +2 -2
- package/.next/server/app/server-logs.rsc +14 -14
- package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
- package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
- package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/networks.html +2 -2
- package/.next/server/app/settings/networks.rsc +14 -14
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +2 -2
- package/.next/server/app/settings/tokens.rsc +14 -14
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +14 -14
- package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks.html +2 -2
- package/.next/server/app/tasks.rsc +14 -14
- package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
- package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__03b.f76._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__03b.f76._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +4 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_057q.ne._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_057q.ne._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0i3759l._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0i3759l._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0xgney8._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0xgney8._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_10hjgv4._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_10hjgv4._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_1153xeb._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_1153xeb._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +2 -2
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/0-mpa_947ipeq.js +1 -0
- package/.next/static/chunks/01lmbsd37fybu.js +1 -0
- package/.next/static/chunks/03o.h6kvmw4l_.js +1 -0
- package/.next/static/chunks/03~~oirxz7~vc.js +1 -0
- package/.next/static/chunks/05uk96gc~9mni.js +1 -0
- package/.next/static/chunks/08kf-.bgs10ze.js +1 -0
- package/.next/static/chunks/0c_eg6lxw~36i.js +4 -0
- package/.next/static/chunks/0ggj5ummw2a84.js +7 -0
- package/.next/static/chunks/0glmrdj9112tc.js +7 -0
- package/.next/static/chunks/0qnfuwkukbu01.js +1 -0
- package/.next/static/chunks/0rxrez_cjn.eh.js +1 -0
- package/.next/static/chunks/0x8x.29hkju5a.js +1 -0
- package/.next/static/chunks/0y.7kwty.hl7h.css +2 -0
- package/.next/static/chunks/11ilooy_9niy-.js +1 -0
- package/.next/static/chunks/174re5ar~kxne.js +1 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/ChatPopover.tsx +38 -2
- package/app/components/CommandPalette.tsx +107 -0
- package/app/components/HelpOverlay.tsx +126 -0
- package/app/components/TopoGraph.tsx +5595 -246
- package/app/components/utils.ts +8 -7
- package/app/globals.css +110 -5
- package/app/lib/time.ts +36 -0
- package/package.json +2 -2
- package/scripts/help-overlay-topo-test.mjs +44 -0
- package/scripts/topo-active-filter-pill-test.mjs +101 -0
- package/scripts/topo-active-links-chip-hover-test.mjs +103 -0
- package/scripts/topo-active-links-chip-nav-test.mjs +117 -0
- package/scripts/topo-active-links-chip-self-hover-test.mjs +171 -0
- package/scripts/topo-active-links-chip-test.mjs +73 -0
- package/scripts/topo-active-links-empty-recede-test.mjs +125 -0
- package/scripts/topo-active-links-freshness-test.mjs +113 -0
- package/scripts/topo-active-links-tooltip-test.mjs +79 -0
- package/scripts/topo-active-pulse-ease-test.mjs +120 -0
- package/scripts/topo-arrival-ping-test.mjs +87 -0
- package/scripts/topo-auto-fit-test.mjs +73 -0
- package/scripts/topo-canvas-aria-test.mjs +108 -0
- package/scripts/topo-chat-target-breath-test.mjs +84 -0
- package/scripts/topo-chat-target-ring-ease-test.mjs +82 -0
- package/scripts/topo-chat-target-ring-fade-test.mjs +124 -0
- package/scripts/topo-chip-empty-recede-test.mjs +116 -0
- package/scripts/topo-chip-focus-test.mjs +95 -0
- package/scripts/topo-chip-pin-mirror-test.mjs +113 -0
- package/scripts/topo-chip-row-semantic-gap-test.mjs +97 -0
- package/scripts/topo-chip-row-tabular-test.mjs +111 -0
- package/scripts/topo-chrome-a11y-test.mjs +107 -0
- package/scripts/topo-chrome-pop-extension-test.mjs +98 -0
- package/scripts/topo-chrome-pop-nodesize-test.mjs +88 -0
- package/scripts/topo-chrome-press-state-test.mjs +135 -0
- package/scripts/topo-chrome-strip-semantic-gap-test.mjs +99 -0
- package/scripts/topo-chrome-strip-theme-ease-test.mjs +99 -0
- package/scripts/topo-chrome-zoom-level-pop-test.mjs +122 -0
- package/scripts/topo-chrome-zoom-pop-test.mjs +130 -0
- package/scripts/topo-click-ripple-ease-test.mjs +94 -0
- package/scripts/topo-cmdk-edge-clear-test.mjs +109 -0
- package/scripts/topo-cmdk-layout-view-test.mjs +108 -0
- package/scripts/topo-cmdk-pin-test.mjs +123 -0
- package/scripts/topo-cmdk-vendor-clear-test.mjs +133 -0
- package/scripts/topo-cmdk-vendor-pin-test.mjs +103 -0
- package/scripts/topo-corner-radius-unify-test.mjs +103 -0
- package/scripts/topo-cwd-tooltip-test.mjs +64 -0
- package/scripts/topo-dblclick-reset-test.mjs +74 -0
- package/scripts/topo-dense-alias-fill-transition-test.mjs +133 -0
- package/scripts/topo-discrete-zoom-smooth-test.mjs +125 -0
- package/scripts/topo-dispatch-pulse-test.mjs +83 -0
- package/scripts/topo-edge-badge-click-pin-test.mjs +94 -0
- package/scripts/topo-edge-badge-crossfade-test.mjs +138 -0
- package/scripts/topo-edge-badge-hot-test.mjs +115 -0
- package/scripts/topo-edge-badge-hover-test.mjs +85 -0
- package/scripts/topo-edge-badge-lift-test.mjs +150 -0
- package/scripts/topo-edge-badge-ripple-test.mjs +111 -0
- package/scripts/topo-edge-badge-stroke-transition-test.mjs +118 -0
- package/scripts/topo-edge-badge-text-pin-test.mjs +121 -0
- package/scripts/topo-edge-badge-theme-ease-test.mjs +89 -0
- package/scripts/topo-edge-count-badge-test.mjs +86 -0
- package/scripts/topo-edge-endpoint-highlight-test.mjs +111 -0
- package/scripts/topo-edge-fadein-test.mjs +106 -0
- package/scripts/topo-edge-focus-test.mjs +113 -0
- package/scripts/topo-edge-hover-test.mjs +93 -0
- package/scripts/topo-edge-pill-hot-test.mjs +129 -0
- package/scripts/topo-edge-pill-test.mjs +105 -0
- package/scripts/topo-edge-smil-sync-test.mjs +148 -0
- package/scripts/topo-edge-smil-theme-ease-test.mjs +97 -0
- package/scripts/topo-edge-stroke-ease-test.mjs +100 -0
- package/scripts/topo-edge-stroke-transition-test.mjs +132 -0
- package/scripts/topo-edge-tooltip-test.mjs +70 -0
- package/scripts/topo-empty-state-breath-test.mjs +150 -0
- package/scripts/topo-empty-state-crossfade-test.mjs +130 -0
- package/scripts/topo-empty-state-recenter-test.mjs +107 -0
- package/scripts/topo-endpoint-ring-fade-test.mjs +132 -0
- package/scripts/topo-endpoint-ring-test.mjs +93 -0
- package/scripts/topo-endpoint-ring-thicken-test.mjs +112 -0
- package/scripts/topo-esc-clears-pin-test.mjs +98 -0
- package/scripts/topo-filter-pill-aliases-test.mjs +121 -0
- package/scripts/topo-filter-pill-body-click-test.mjs +112 -0
- package/scripts/topo-filter-pill-count-test.mjs +110 -0
- package/scripts/topo-filter-pill-mobile-test.mjs +90 -0
- package/scripts/topo-fit-key-test.mjs +106 -0
- package/scripts/topo-freshness-chip-test.mjs +74 -0
- package/scripts/topo-freshness-chip-transition-test.mjs +80 -0
- package/scripts/topo-freshness-text-color-coherence-test.mjs +97 -0
- package/scripts/topo-fullscreen-active-test.mjs +115 -0
- package/scripts/topo-group-box-pinned-state-test.mjs +95 -0
- package/scripts/topo-group-count-test.mjs +6 -1
- package/scripts/topo-group-label-a11y-test.mjs +113 -0
- package/scripts/topo-group-label-count-inherit-test.mjs +99 -0
- package/scripts/topo-group-label-hover-test.mjs +119 -0
- package/scripts/topo-group-label-pin-spacing-test.mjs +136 -0
- package/scripts/topo-group-label-tint-test.mjs +99 -0
- package/scripts/topo-group-label-title-test.mjs +83 -0
- package/scripts/topo-group-pin-test.mjs +119 -0
- package/scripts/topo-group-pip-fadein-test.mjs +100 -0
- package/scripts/topo-group-pip-tabular-test.mjs +95 -0
- package/scripts/topo-group-status-pips-test.mjs +103 -0
- package/scripts/topo-groupbox-fadein-test.mjs +95 -0
- package/scripts/topo-groupbox-hover-lift-test.mjs +127 -0
- package/scripts/topo-groupbox-hubcore-ease-test.mjs +106 -0
- package/scripts/topo-groupbox-live-test.mjs +100 -0
- package/scripts/topo-groupbox-march-busyness-test.mjs +155 -0
- package/scripts/topo-groupbox-test.mjs +4 -2
- package/scripts/topo-halo-breath-ease-test.mjs +92 -0
- package/scripts/topo-halo-breath-stagger-test.mjs +89 -0
- package/scripts/topo-help-overlay-r109-test.mjs +67 -0
- package/scripts/topo-help-overlay-r118-test.mjs +69 -0
- package/scripts/topo-help-overlay-r123-test.mjs +69 -0
- package/scripts/topo-help-overlay-r134-test.mjs +74 -0
- package/scripts/topo-help-overlay-r137-test.mjs +81 -0
- package/scripts/topo-help-overlay-r141-test.mjs +86 -0
- package/scripts/topo-help-overlay-r153-test.mjs +85 -0
- package/scripts/topo-help-overlay-r59-test.mjs +67 -0
- package/scripts/topo-help-overlay-r65-test.mjs +64 -0
- package/scripts/topo-help-overlay-r70-test.mjs +63 -0
- package/scripts/topo-help-overlay-r78-test.mjs +59 -0
- package/scripts/topo-help-overlay-r81-test.mjs +58 -0
- package/scripts/topo-help-overlay-r87-test.mjs +64 -0
- package/scripts/topo-help-overlay-r91-test.mjs +65 -0
- package/scripts/topo-hot-tail-crossfade-test.mjs +117 -0
- package/scripts/topo-html-overlay-padding-unify-test.mjs +120 -0
- package/scripts/topo-hub-a11y-test.mjs +112 -0
- package/scripts/topo-hub-busyness-test.mjs +100 -0
- package/scripts/topo-hub-center-crossfade-test.mjs +124 -0
- package/scripts/topo-hub-click-fit-test.mjs +137 -0
- package/scripts/topo-hub-digit-scale-test.mjs +129 -0
- package/scripts/topo-hub-fadein-test.mjs +88 -0
- package/scripts/topo-hub-hover-lift-test.mjs +101 -0
- package/scripts/topo-hub-hover-ring-test.mjs +82 -0
- package/scripts/topo-hub-pip-theme-ease-test.mjs +116 -0
- package/scripts/topo-hub-spoke-ease-test.mjs +120 -0
- package/scripts/topo-hub-title-test.mjs +93 -0
- package/scripts/topo-hub-working-count-test.mjs +99 -0
- package/scripts/topo-ingroup-edge-test.mjs +103 -0
- package/scripts/topo-label-card-theme-ease-test.mjs +85 -0
- package/scripts/topo-label-lift-test.mjs +119 -0
- package/scripts/topo-lastseen-tooltip-test.mjs +59 -0
- package/scripts/topo-layout-hover-text-preview-test.mjs +101 -0
- package/scripts/topo-layout-key-test.mjs +91 -0
- package/scripts/topo-layout-switch-crossfade-test.mjs +126 -0
- package/scripts/topo-layout-toggle-border-unify-test.mjs +104 -0
- package/scripts/topo-layout-toggle-test.mjs +131 -0
- package/scripts/topo-legend-count-empty-test.mjs +126 -0
- package/scripts/topo-legend-count-tabular-test.mjs +87 -0
- package/scripts/topo-legend-count-test.mjs +88 -0
- package/scripts/topo-legend-count-tier-fill-test.mjs +121 -0
- package/scripts/topo-legend-header-symmetric-inset-test.mjs +112 -0
- package/scripts/topo-legend-hitbox-swatch-center-test.mjs +93 -0
- package/scripts/topo-legend-hover-test.mjs +113 -0
- package/scripts/topo-legend-offline-delimiter-test.mjs +84 -0
- package/scripts/topo-legend-panel-header-test.mjs +83 -0
- package/scripts/topo-legend-pin-ring-fade-test.mjs +112 -0
- package/scripts/topo-legend-pin-test.mjs +128 -0
- package/scripts/topo-legend-row-hover-lift-test.mjs +109 -0
- package/scripts/topo-legend-row-pin-spacing-test.mjs +124 -0
- package/scripts/topo-legend-row-tint-test.mjs +95 -0
- package/scripts/topo-legend-row-title-test.mjs +102 -0
- package/scripts/topo-legend-swatch-grow-test.mjs +116 -0
- package/scripts/topo-minimap-a11y-test.mjs +101 -0
- package/scripts/topo-minimap-dot-transition-test.mjs +113 -0
- package/scripts/topo-minimap-test.mjs +68 -0
- package/scripts/topo-minimap-viewport-smooth-test.mjs +124 -0
- package/scripts/topo-mobile-chips-test.mjs +103 -0
- package/scripts/topo-node-a11y-test.mjs +107 -0
- package/scripts/topo-node-hover-lift-test.mjs +85 -0
- package/scripts/topo-node-label-card-elevation-test.mjs +157 -0
- package/scripts/topo-node-label-card-stroke-test.mjs +135 -0
- package/scripts/topo-node-stroke-transition-test.mjs +103 -0
- package/scripts/topo-node-text-fill-transition-test.mjs +119 -0
- package/scripts/topo-node-title-peers-test.mjs +107 -0
- package/scripts/topo-node-title-test.mjs +101 -0
- package/scripts/topo-nodesize-active-hover-test.mjs +109 -0
- package/scripts/topo-nodesize-crossfade-test.mjs +141 -0
- package/scripts/topo-online-chip-nav-test.mjs +143 -0
- package/scripts/topo-orbit-busyness-test.mjs +96 -0
- package/scripts/topo-orbit-opacity-bucket-test.mjs +124 -0
- package/scripts/topo-overlap-test.mjs +32 -5
- package/scripts/topo-pan-cursor-test.mjs +62 -0
- package/scripts/topo-panel-elevation-test.mjs +76 -0
- package/scripts/topo-panel-fadein-test.mjs +102 -0
- package/scripts/topo-panel-hot-tail-fade-test.mjs +132 -0
- package/scripts/topo-panel-hover-elevation-test.mjs +118 -0
- package/scripts/topo-panel-theme-ease-test.mjs +85 -0
- package/scripts/topo-panel-title-fill-ease-test.mjs +91 -0
- package/scripts/topo-particle-stagger-test.mjs +82 -0
- package/scripts/topo-pin-intersection-color-ease-test.mjs +111 -0
- package/scripts/topo-pin-intersection-empty-test.mjs +129 -0
- package/scripts/topo-pin-intersection-tabular-test.mjs +96 -0
- package/scripts/topo-pin-intersection-test.mjs +121 -0
- package/scripts/topo-pin-intersection-warning-crossfade-test.mjs +107 -0
- package/scripts/topo-pin-mirror-transition-test.mjs +101 -0
- package/scripts/topo-pin-persistence-test.mjs +105 -0
- package/scripts/topo-ping-pulse-ease-test.mjs +96 -0
- package/scripts/topo-popover-meta-test.mjs +78 -0
- package/scripts/topo-prepublish-guard-test.mjs +95 -0
- package/scripts/topo-pressure-bar-test.mjs +69 -0
- package/scripts/topo-pressure-hover-test.mjs +123 -0
- package/scripts/topo-pressure-pin-test.mjs +119 -0
- package/scripts/topo-pressure-seg-self-hover-test.mjs +126 -0
- package/scripts/topo-pressure-seg-tooltip-test.mjs +98 -0
- package/scripts/topo-pressure-seg-transition-test.mjs +107 -0
- package/scripts/topo-pulse-dot-crossfade-test.mjs +122 -0
- package/scripts/topo-pulse-rate-test.mjs +71 -0
- package/scripts/topo-recent-panel-count-freshness-test.mjs +109 -0
- package/scripts/topo-recent-panel-count-test.mjs +72 -0
- package/scripts/topo-recent-panel-footer-breath-test.mjs +142 -0
- package/scripts/topo-recent-panel-hot-header-test.mjs +132 -0
- package/scripts/topo-recent-panel-more-crossfade-test.mjs +124 -0
- package/scripts/topo-recent-panel-more-cyan-hover-test.mjs +151 -0
- package/scripts/topo-recent-panel-more-nav-test.mjs +127 -0
- package/scripts/topo-recent-panel-more-test.mjs +106 -0
- package/scripts/topo-recent-panel-readability-bump-test.mjs +151 -0
- package/scripts/topo-recent-row-count-fill-test.mjs +129 -0
- package/scripts/topo-recent-row-fadein-test.mjs +107 -0
- package/scripts/topo-recent-row-freshness-test.mjs +102 -0
- package/scripts/topo-recent-row-hot-test.mjs +110 -0
- package/scripts/topo-recent-row-hover-lift-test.mjs +128 -0
- package/scripts/topo-recent-row-hover-test.mjs +122 -0
- package/scripts/topo-recent-row-pin-spacing-test.mjs +137 -0
- package/scripts/topo-recent-row-pin-test.mjs +126 -0
- package/scripts/topo-recent-row-tint-test.mjs +91 -0
- package/scripts/topo-recent-row-title-test.mjs +112 -0
- package/scripts/topo-recent-row-ts-alpha-test.mjs +100 -0
- package/scripts/topo-recent-row-ts-test.mjs +95 -0
- package/scripts/topo-recent-row-typography-test.mjs +119 -0
- package/scripts/topo-recent-signal-empty-hint-test.mjs +73 -0
- package/scripts/topo-recent-signal-empty-test.mjs +63 -0
- package/scripts/topo-reduced-motion-test.mjs +77 -0
- package/scripts/topo-reset-spin-test.mjs +120 -0
- package/scripts/topo-runtime-badge-grow-test.mjs +114 -0
- package/scripts/topo-spoke-busyness-test.mjs +110 -0
- package/scripts/topo-spoke-tint-test.mjs +96 -0
- package/scripts/topo-status-chip-hover-test.mjs +101 -0
- package/scripts/topo-status-chip-tooltip-test.mjs +95 -0
- package/scripts/topo-statusbar-chips-self-hover-test.mjs +177 -0
- package/scripts/topo-svg-focus-test.mjs +112 -0
- package/scripts/topo-sweep-busyness-test.mjs +94 -0
- package/scripts/topo-tabular-nums-sweep-test.mjs +93 -0
- package/scripts/topo-tier-ring-fadein-test.mjs +107 -0
- package/scripts/topo-tier-ring-occupancy-test.mjs +87 -0
- package/scripts/topo-tier-ring-test.mjs +69 -0
- package/scripts/topo-tier-ring-tint-test.mjs +110 -0
- package/scripts/topo-tier-stagger-test.mjs +89 -0
- package/scripts/topo-title-block-tight-leading-test.mjs +95 -0
- package/scripts/topo-toggle-inactive-cyan-hover-test.mjs +110 -0
- package/scripts/topo-top-rail-theme-ease-test.mjs +89 -0
- package/scripts/topo-tz-ghost-test.mjs +69 -0
- package/scripts/topo-vendor-chip-hover-test.mjs +111 -0
- package/scripts/topo-vendor-chip-self-hover-test.mjs +130 -0
- package/scripts/topo-vendor-chip-tabular-test.mjs +89 -0
- package/scripts/topo-vendor-letter-tooltip-test.mjs +92 -0
- package/scripts/topo-vendor-pill-test.mjs +125 -0
- package/scripts/topo-vendor-pin-test.mjs +125 -0
- package/scripts/topo-view-smooth-test.mjs +131 -0
- package/scripts/topo-wheel-zoom-test.mjs +79 -0
- package/scripts/topo-working-chip-pin-test.mjs +154 -0
- package/scripts/topo-working-halo-breath-test.mjs +86 -0
- package/scripts/topo-wrapper-flow-arrow-theme-test.mjs +97 -0
- package/scripts/topo-wrapper-shadow-theme-ease-test.mjs +89 -0
- package/scripts/topo-zoom-keys-test.mjs +89 -0
- package/.next/static/chunks/0-7iowzu4.798.js +0 -1
- package/.next/static/chunks/02t5jr4shh.hy.js +0 -1
- package/.next/static/chunks/09nd.t_hd.y6t.css +0 -2
- package/.next/static/chunks/0_qfg5s5uzs7..js +0 -7
- package/.next/static/chunks/0a6k5x_~ch.y7.js +0 -1
- package/.next/static/chunks/0elalb9n_.~di.js +0 -1
- package/.next/static/chunks/0ipujag5x55bt.js +0 -1
- package/.next/static/chunks/0j_q__o8p6g83.js +0 -1
- package/.next/static/chunks/0jl6_w50zh4l5.js +0 -1
- package/.next/static/chunks/0pl7l_.2im.j0.js +0 -7
- package/.next/static/chunks/0r4q73.-1bkyl.js +0 -1
- package/.next/static/chunks/0r_c8eccg3z2o.js +0 -1
- package/.next/static/chunks/0zs511wcsq~0j.js +0 -1
- package/.next/static/chunks/10oi7l-tycgl9.js +0 -1
- package/.next/static/chunks/11uk1izuv3~0t.js +0 -1
- /package/.next/static/{DCVxQ0usFqDQ5PHW3d_Zx → gjUOBeB2JqesZ_cSX14ph}/_buildManifest.js +0 -0
- /package/.next/static/{DCVxQ0usFqDQ5PHW3d_Zx → gjUOBeB2JqesZ_cSX14ph}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{DCVxQ0usFqDQ5PHW3d_Zx → gjUOBeB2JqesZ_cSX14ph}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/* Round 30 verification: minimap.
|
|
2
|
+
* - not mounted at default view (1×, centered)
|
|
3
|
+
* - mounted when zoomed in (one node dot per session, viewport rect)
|
|
4
|
+
* - click recenters the canvas (view.x / view.y change) */
|
|
5
|
+
import { chromium } from 'playwright';
|
|
6
|
+
import { readFileSync } from 'node:fs';
|
|
7
|
+
|
|
8
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
9
|
+
const browser = await chromium.launch({ headless: true });
|
|
10
|
+
const ctx = await browser.newContext({ viewport: { width: 1280, height: 1600 } });
|
|
11
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
12
|
+
await ctx.addInitScript(() => {
|
|
13
|
+
try {
|
|
14
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
15
|
+
localStorage.setItem('anet-topo-layout', 'grid');
|
|
16
|
+
localStorage.setItem('anet-topo-view', JSON.stringify({ zoom: 1, x: 0, y: 0 }));
|
|
17
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
18
|
+
} catch {}
|
|
19
|
+
});
|
|
20
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
21
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
22
|
+
const r = await route.fetch();
|
|
23
|
+
const b = await r.json();
|
|
24
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
25
|
+
const sessions = ['A站', 'B站', 'C站', 'D站', 'E站', 'F站'].flatMap(g =>
|
|
26
|
+
Array.from({ length: 3 }, (_, i) => ({
|
|
27
|
+
alias: `${g}${i + 1}`, status: 'idle', network_id: nid, project_dir: null,
|
|
28
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
29
|
+
})),
|
|
30
|
+
);
|
|
31
|
+
await route.fulfill({ response: r, json: { ...b, sessions } });
|
|
32
|
+
});
|
|
33
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
34
|
+
const page = await ctx.newPage();
|
|
35
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
36
|
+
await page.waitForSelector('svg[viewBox="0 0 1000 680"]', { timeout: 30000 });
|
|
37
|
+
await page.waitForTimeout(500);
|
|
38
|
+
|
|
39
|
+
const minimap = '[data-topo-minimap]';
|
|
40
|
+
const notMountedAtDefault = (await page.locator(minimap).count()) === 0;
|
|
41
|
+
|
|
42
|
+
// Zoom in via `+` twice → view changes → minimap mounts
|
|
43
|
+
await page.keyboard.press('=');
|
|
44
|
+
await page.keyboard.press('=');
|
|
45
|
+
await page.waitForTimeout(200);
|
|
46
|
+
const mountedAfterZoom = (await page.locator(minimap).count()) === 1;
|
|
47
|
+
const dotCount = await page.locator(`${minimap} svg circle`).count();
|
|
48
|
+
const hasViewportRect = await page.locator(`${minimap} svg rect`).count() > 0;
|
|
49
|
+
|
|
50
|
+
// Click on the minimap's far left → expect view.x to become more positive (canvas pans right)
|
|
51
|
+
const beforeView = await page.evaluate(() => JSON.parse(localStorage.getItem('anet-topo-view')));
|
|
52
|
+
const mmBox = await page.locator(minimap).boundingBox();
|
|
53
|
+
await page.mouse.click(mmBox.x + 10, mmBox.y + mmBox.height / 2);
|
|
54
|
+
await page.waitForTimeout(200);
|
|
55
|
+
const afterView = await page.evaluate(() => JSON.parse(localStorage.getItem('anet-topo-view')));
|
|
56
|
+
const clickRecenters = afterView.x !== beforeView.x || afterView.y !== beforeView.y;
|
|
57
|
+
|
|
58
|
+
await browser.close();
|
|
59
|
+
const results = {
|
|
60
|
+
notMountedAtDefault,
|
|
61
|
+
mountedAfterZoom,
|
|
62
|
+
oneDotPerSession: dotCount === 18, // 6 groups × 3 = 18 nodes
|
|
63
|
+
viewportRectPresent: hasViewportRect,
|
|
64
|
+
clickRecenters,
|
|
65
|
+
};
|
|
66
|
+
const ok = Object.values(results).every(Boolean);
|
|
67
|
+
console.log(`${ok ? '✅' : '❌'} minimap:`, JSON.stringify(results), `dots=${dotCount} view before=`, beforeView, `after=`, afterView);
|
|
68
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/* Round 199 verification: minimap viewport rect transitions x/y/w/h
|
|
2
|
+
* during R169 smoothView (discrete zoom +/− and reset). Closes the
|
|
3
|
+
* rhythm-mismatch R198 just fixed for minimap dots — now extended to
|
|
4
|
+
* the rectangle that frames them.
|
|
5
|
+
*
|
|
6
|
+
* Pre-R199 a click on zoom-in crossfaded the main canvas over R168's
|
|
7
|
+
* 280ms but the minimap viewport rect snap-cut to its new dimensions
|
|
8
|
+
* in one frame. R199 gates a `transition: x/y/w/h 280ms` on
|
|
9
|
+
* smoothView=true so discrete zooms ease the rect smoothly. Drag-pan
|
|
10
|
+
* and wheel-zoom (smoothView=false) keep snappy response — a
|
|
11
|
+
* persistent transition during drag would lag the cursor by 280ms.
|
|
12
|
+
*
|
|
13
|
+
* Test:
|
|
14
|
+
* 1. Open page with 4 sessions, zoom in once to mount minimap.
|
|
15
|
+
* 2. Idle (smoothView=false): rect has
|
|
16
|
+
* data-topo-minimap-viewport-smooth='false', style.transition='none'.
|
|
17
|
+
* 3. Click zoom-in again → smoothView arms to 'true' for ~350ms.
|
|
18
|
+
* 4. Within 100ms of click: probe rect →
|
|
19
|
+
* data-topo-minimap-viewport-smooth='true', style.transition
|
|
20
|
+
* includes 'x 280ms', 'y 280ms', 'width 280ms', 'height 280ms'.
|
|
21
|
+
* 5. Wait past 400ms → smoothView clears → back to 'false', no
|
|
22
|
+
* transition.
|
|
23
|
+
*/
|
|
24
|
+
import { chromium } from 'playwright';
|
|
25
|
+
import { readFileSync } from 'node:fs';
|
|
26
|
+
|
|
27
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
28
|
+
const browser = await chromium.launch({ headless: true });
|
|
29
|
+
|
|
30
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
31
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
32
|
+
await ctx.addInitScript(() => {
|
|
33
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
37
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
38
|
+
const r = await route.fetch();
|
|
39
|
+
const b = await r.json();
|
|
40
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
41
|
+
const mk = (alias) => ({
|
|
42
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
43
|
+
network_id: nid, project_dir: null,
|
|
44
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
45
|
+
});
|
|
46
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
47
|
+
mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
|
|
48
|
+
] } });
|
|
49
|
+
});
|
|
50
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
|
|
51
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
52
|
+
|
|
53
|
+
const page = await ctx.newPage();
|
|
54
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
55
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
|
|
56
|
+
await page.waitForSelector('[data-topo-chrome-zoom-in]', { timeout: 10000 });
|
|
57
|
+
await page.waitForTimeout(300);
|
|
58
|
+
|
|
59
|
+
// First zoom-in mounts the minimap. Wait past the 350ms smoothView
|
|
60
|
+
// timer so the minimap rect is at idle state (smooth='false') before
|
|
61
|
+
// we probe.
|
|
62
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
63
|
+
await page.waitForTimeout(450);
|
|
64
|
+
await page.waitForSelector('[data-topo-minimap-viewport]', { timeout: 5000 });
|
|
65
|
+
|
|
66
|
+
const probe = async () => page.evaluate(() => {
|
|
67
|
+
const el = document.querySelector('[data-topo-minimap-viewport]');
|
|
68
|
+
if (!el) return null;
|
|
69
|
+
return {
|
|
70
|
+
smooth: el.getAttribute('data-topo-minimap-viewport-smooth'),
|
|
71
|
+
transition: el.style.transition,
|
|
72
|
+
x: parseFloat(el.getAttribute('x') || ''),
|
|
73
|
+
y: parseFloat(el.getAttribute('y') || ''),
|
|
74
|
+
w: parseFloat(el.getAttribute('width') || ''),
|
|
75
|
+
h: parseFloat(el.getAttribute('height') || ''),
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const idle = await probe();
|
|
80
|
+
|
|
81
|
+
// Click zoom-in once more — arms smoothView for ~350ms — and probe
|
|
82
|
+
// within the arming window.
|
|
83
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
84
|
+
await page.waitForTimeout(80); // well inside the 350ms arming window
|
|
85
|
+
const armed = await probe();
|
|
86
|
+
|
|
87
|
+
await page.waitForTimeout(420); // past 350ms timer + transition
|
|
88
|
+
const settled = await probe();
|
|
89
|
+
|
|
90
|
+
await browser.close();
|
|
91
|
+
|
|
92
|
+
const hasAllAxes = (s) =>
|
|
93
|
+
/\bx\s+(?:280ms|0\.28s)/.test(s || '') &&
|
|
94
|
+
/\by\s+(?:280ms|0\.28s)/.test(s || '') &&
|
|
95
|
+
/\bwidth\s+(?:280ms|0\.28s)/.test(s || '') &&
|
|
96
|
+
/\bheight\s+(?:280ms|0\.28s)/.test(s || '');
|
|
97
|
+
|
|
98
|
+
const results = {
|
|
99
|
+
idle_smooth_false: idle?.smooth === 'false',
|
|
100
|
+
idle_transition_none: idle?.transition === 'none' || idle?.transition === '',
|
|
101
|
+
idle_has_dimensions: idle && Number.isFinite(idle.x) && Number.isFinite(idle.w) && idle.w > 0,
|
|
102
|
+
|
|
103
|
+
armed_smooth_true: armed?.smooth === 'true',
|
|
104
|
+
armed_transition_present: !!armed?.transition && armed.transition !== 'none',
|
|
105
|
+
armed_transition_has_all: hasAllAxes(armed?.transition),
|
|
106
|
+
|
|
107
|
+
settled_smooth_false: settled?.smooth === 'false',
|
|
108
|
+
settled_transition_none: settled?.transition === 'none' || settled?.transition === '',
|
|
109
|
+
|
|
110
|
+
// R199 actually changed dimensions between idle (zoom 120%) and
|
|
111
|
+
// settled (zoom 144% after second click), or x/y diverged.
|
|
112
|
+
zoom_changed_dimensions: idle && settled && (
|
|
113
|
+
Math.abs(idle.w - settled.w) > 1 ||
|
|
114
|
+
Math.abs(idle.h - settled.h) > 1 ||
|
|
115
|
+
Math.abs(idle.x - settled.x) > 1 ||
|
|
116
|
+
Math.abs(idle.y - settled.y) > 1
|
|
117
|
+
),
|
|
118
|
+
};
|
|
119
|
+
const ok = Object.values(results).every(Boolean);
|
|
120
|
+
console.log(`${ok ? '✅' : '❌'} minimap viewport smooth:`, JSON.stringify(results),
|
|
121
|
+
`\n idle:`, idle,
|
|
122
|
+
`\n armed:`, armed,
|
|
123
|
+
`\n settled:`, settled);
|
|
124
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* Round 47 verification: mobile chip collapse.
|
|
2
|
+
* - At narrow viewport (375px), pressure / vendor-dist / active-links /
|
|
3
|
+
* freshness chips are display:none; only essential chips render.
|
|
4
|
+
* - At sm+ (≥640px), the full chip row is visible.
|
|
5
|
+
* - Essential chips (Ring/Grid toggle + working + online) render at both. */
|
|
6
|
+
import { chromium } from 'playwright';
|
|
7
|
+
import { readFileSync } from 'node:fs';
|
|
8
|
+
|
|
9
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
10
|
+
const browser = await chromium.launch({ headless: true });
|
|
11
|
+
|
|
12
|
+
async function probe(width) {
|
|
13
|
+
const ctx = await browser.newContext({ viewport: { width, height: 900 } });
|
|
14
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
15
|
+
await ctx.addInitScript(() => {
|
|
16
|
+
try {
|
|
17
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
18
|
+
localStorage.setItem('anet-topo-layout', 'grid');
|
|
19
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
20
|
+
} catch {}
|
|
21
|
+
});
|
|
22
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
23
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
24
|
+
const r = await route.fetch();
|
|
25
|
+
const b = await r.json();
|
|
26
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
27
|
+
const sessions = [
|
|
28
|
+
{ alias: 'wkr', status: 'working', network_id: nid, project_dir: null,
|
|
29
|
+
model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
30
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
31
|
+
{ alias: 'idl', status: 'idle', network_id: nid, project_dir: null,
|
|
32
|
+
model: 'gpt-5', runtime: 'codex-cli',
|
|
33
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
34
|
+
];
|
|
35
|
+
await route.fulfill({ response: r, json: { ...b, sessions } });
|
|
36
|
+
});
|
|
37
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [
|
|
38
|
+
{ from_alias: 'wkr', to_alias: 'idl', content: 'm', created_at: new Date().toISOString() },
|
|
39
|
+
] } }));
|
|
40
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
41
|
+
const page = await ctx.newPage();
|
|
42
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
43
|
+
// The Overview page auto-hides the topology when window.innerWidth < 1024
|
|
44
|
+
// (the lg breakpoint). On narrow viewports the user clicks "Show
|
|
45
|
+
// Topology" to surface it; mimic that here so the chip-row tests reach
|
|
46
|
+
// the actual code path. Wait for SWR to deliver sessions first so the
|
|
47
|
+
// button renders before we look for it.
|
|
48
|
+
await page.waitForTimeout(1500);
|
|
49
|
+
const showBtn = page.locator('button', { hasText: /Show Topology/i });
|
|
50
|
+
if (await showBtn.count() > 0) await showBtn.first().click();
|
|
51
|
+
await page.waitForSelector('svg[viewBox="0 0 1000 680"]', { timeout: 30000 });
|
|
52
|
+
await page.waitForTimeout(600);
|
|
53
|
+
const visible = (sel) => page.evaluate(s => {
|
|
54
|
+
const el = document.querySelector(s);
|
|
55
|
+
if (!el) return null;
|
|
56
|
+
const r = el.getBoundingClientRect();
|
|
57
|
+
return r.width > 0 && r.height > 0;
|
|
58
|
+
}, sel);
|
|
59
|
+
const result = {
|
|
60
|
+
workingChipVisible: await page.evaluate(() => {
|
|
61
|
+
// "{N} working" chip — find the green-tinted one
|
|
62
|
+
const spans = [...document.querySelectorAll('span')];
|
|
63
|
+
const chip = spans.find(s => /^\d+ working$/.test((s.textContent || '').trim()));
|
|
64
|
+
if (!chip) return false;
|
|
65
|
+
const r = chip.getBoundingClientRect();
|
|
66
|
+
return r.width > 0 && r.height > 0;
|
|
67
|
+
}),
|
|
68
|
+
onlineChipVisible: await page.evaluate(() => {
|
|
69
|
+
const spans = [...document.querySelectorAll('span')];
|
|
70
|
+
const chip = spans.find(s => /^\d+ online$/.test((s.textContent || '').trim()));
|
|
71
|
+
if (!chip) return false;
|
|
72
|
+
const r = chip.getBoundingClientRect();
|
|
73
|
+
return r.width > 0 && r.height > 0;
|
|
74
|
+
}),
|
|
75
|
+
pressureVisible: await visible('[data-fleet-pressure]'),
|
|
76
|
+
activeLinksVisible: await page.evaluate(() => {
|
|
77
|
+
const spans = [...document.querySelectorAll('span')];
|
|
78
|
+
const chip = spans.find(s => /active link/.test(s.textContent || ''));
|
|
79
|
+
if (!chip) return false;
|
|
80
|
+
const r = chip.getBoundingClientRect();
|
|
81
|
+
return r.width > 0 && r.height > 0;
|
|
82
|
+
}),
|
|
83
|
+
freshnessVisible: await visible('[data-freshness-chip]'),
|
|
84
|
+
};
|
|
85
|
+
await ctx.close();
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const mobile = await probe(375);
|
|
90
|
+
const desktop = await probe(900);
|
|
91
|
+
await browser.close();
|
|
92
|
+
|
|
93
|
+
const results = {
|
|
94
|
+
mobileEssentialsVisible: mobile.workingChipVisible && mobile.onlineChipVisible,
|
|
95
|
+
mobilePressureHidden: mobile.pressureVisible === false,
|
|
96
|
+
mobileActiveLinksHidden: mobile.activeLinksVisible === false,
|
|
97
|
+
mobileFreshnessHidden: mobile.freshnessVisible === false,
|
|
98
|
+
desktopAllVisible: desktop.workingChipVisible && desktop.onlineChipVisible && desktop.pressureVisible && desktop.activeLinksVisible && desktop.freshnessVisible,
|
|
99
|
+
};
|
|
100
|
+
const ok = Object.values(results).every(Boolean);
|
|
101
|
+
console.log(`${ok ? '✅' : '❌'} mobile chips:`, JSON.stringify(results),
|
|
102
|
+
`\n mobile=`, mobile, `\n desktop=`, desktop);
|
|
103
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/* Round 151 verification: node <g> gains a11y compliance.
|
|
2
|
+
*
|
|
3
|
+
* Node clickable for chat since R45, but tab-unreachable +
|
|
4
|
+
* screen-reader-unannounced. R151 matches the pattern R116 /
|
|
5
|
+
* R139 / R140 / R148 / R149 applied to other interactive
|
|
6
|
+
* surfaces:
|
|
7
|
+
* role="button"
|
|
8
|
+
* tabIndex={0}
|
|
9
|
+
* aria-label="Chat with {alias} ({status})"
|
|
10
|
+
* aria-pressed={chatAlias === session.alias}
|
|
11
|
+
* onKeyDown(Enter / Space) → setChatAlias
|
|
12
|
+
*
|
|
13
|
+
* Three checks:
|
|
14
|
+
* 1. All nodes carry role=button, tabIndex=0, aria-label, aria-
|
|
15
|
+
* pressed=false by default
|
|
16
|
+
* 2. Pressing Enter on a focused node opens chat (aria-pressed
|
|
17
|
+
* flips to true, chat popover renders)
|
|
18
|
+
* 3. Pressing Space on a different node moves the open chat
|
|
19
|
+
* target — only one aria-pressed=true at a time
|
|
20
|
+
*/
|
|
21
|
+
import { chromium } from 'playwright';
|
|
22
|
+
import { readFileSync } from 'node:fs';
|
|
23
|
+
|
|
24
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
25
|
+
const browser = await chromium.launch({ headless: true });
|
|
26
|
+
|
|
27
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
28
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
29
|
+
await ctx.addInitScript(() => {
|
|
30
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
34
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
35
|
+
const r = await route.fetch();
|
|
36
|
+
const b = await r.json();
|
|
37
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
38
|
+
const mk = (alias, status) => ({
|
|
39
|
+
alias, status, model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
40
|
+
network_id: nid, project_dir: null,
|
|
41
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
42
|
+
});
|
|
43
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
44
|
+
mk('alpha', 'working'), mk('beta', 'idle'), mk('gamma', 'working'),
|
|
45
|
+
] } });
|
|
46
|
+
});
|
|
47
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
|
|
48
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
49
|
+
|
|
50
|
+
const page = await ctx.newPage();
|
|
51
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
52
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 3, { timeout: 30000 });
|
|
53
|
+
await page.waitForTimeout(400);
|
|
54
|
+
|
|
55
|
+
const inspectAll = () => page.evaluate(() => {
|
|
56
|
+
const nodes = [...document.querySelectorAll('g[data-node]')];
|
|
57
|
+
return nodes.map(n => ({
|
|
58
|
+
alias: n.getAttribute('data-node'),
|
|
59
|
+
role: n.getAttribute('role'),
|
|
60
|
+
tabIndex: n.getAttribute('tabindex'),
|
|
61
|
+
ariaLabel: n.getAttribute('aria-label'),
|
|
62
|
+
ariaPressed: n.getAttribute('aria-pressed'),
|
|
63
|
+
}));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const before = await inspectAll();
|
|
67
|
+
|
|
68
|
+
// Focus alpha node and press Enter → opens chat
|
|
69
|
+
await page.locator('g[data-node="alpha"]').focus();
|
|
70
|
+
await page.keyboard.press('Enter');
|
|
71
|
+
await page.waitForTimeout(250);
|
|
72
|
+
const afterAlpha = await inspectAll();
|
|
73
|
+
const popoverPresentA = await page.locator('.anet-chat-popover, [data-chat-popover]').count() > 0
|
|
74
|
+
|| await page.evaluate(() => !!document.querySelector('[role="dialog"]'));
|
|
75
|
+
|
|
76
|
+
// Focus gamma node and press Space → moves chat target (only one pressed)
|
|
77
|
+
await page.locator('g[data-node="gamma"]').focus();
|
|
78
|
+
await page.keyboard.press(' ');
|
|
79
|
+
await page.waitForTimeout(250);
|
|
80
|
+
const afterGamma = await inspectAll();
|
|
81
|
+
|
|
82
|
+
await browser.close();
|
|
83
|
+
|
|
84
|
+
const results = {
|
|
85
|
+
// Baseline shape
|
|
86
|
+
threeNodes: before.length === 3,
|
|
87
|
+
allRoleButton: before.every(n => n.role === 'button'),
|
|
88
|
+
allTabIndex0: before.every(n => n.tabIndex === '0'),
|
|
89
|
+
allAriaLabel: before.every(n => /^Chat with /.test(n.ariaLabel || '')),
|
|
90
|
+
allAriaPressedFalse: before.every(n => n.ariaPressed === 'false'),
|
|
91
|
+
|
|
92
|
+
// After Enter on alpha
|
|
93
|
+
enterOpensChat: afterAlpha.find(n => n.alias === 'alpha')?.ariaPressed === 'true',
|
|
94
|
+
popoverShown: popoverPresentA,
|
|
95
|
+
othersStillFalse: afterAlpha.filter(n => n.alias !== 'alpha').every(n => n.ariaPressed === 'false'),
|
|
96
|
+
|
|
97
|
+
// After Space on gamma (chat target moved)
|
|
98
|
+
spaceMovesTarget: afterGamma.find(n => n.alias === 'gamma')?.ariaPressed === 'true',
|
|
99
|
+
alphaUnpressed: afterGamma.find(n => n.alias === 'alpha')?.ariaPressed === 'false',
|
|
100
|
+
onlyOnePressed: afterGamma.filter(n => n.ariaPressed === 'true').length === 1,
|
|
101
|
+
};
|
|
102
|
+
const ok = Object.values(results).every(Boolean);
|
|
103
|
+
console.log(`${ok ? '✅' : '❌'} node a11y:`, JSON.stringify(results),
|
|
104
|
+
`\n before=`, before,
|
|
105
|
+
`\n afterAlpha=`, afterAlpha,
|
|
106
|
+
`\n afterGamma=`, afterGamma);
|
|
107
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/* Round 51 verification: hovered node <g> lifts -2px via CSS transform.
|
|
2
|
+
* - At rest, every node's CSS transform is "none" (or matrix with 0 ty).
|
|
3
|
+
* - On hover, the hovered <g> reports `translateY(-2px)` (matrix(1,0,0,1,0,-2))
|
|
4
|
+
* via getComputedStyle.transform, while siblings stay at identity.
|
|
5
|
+
* - Release: returns to identity.
|
|
6
|
+
* - With prefers-reduced-motion forced, NO lift even on hover.
|
|
7
|
+
*/
|
|
8
|
+
import { chromium } from 'playwright';
|
|
9
|
+
import { readFileSync } from 'node:fs';
|
|
10
|
+
|
|
11
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
12
|
+
const browser = await chromium.launch({ headless: true });
|
|
13
|
+
|
|
14
|
+
async function probe(reducedMotion) {
|
|
15
|
+
const ctx = await browser.newContext({
|
|
16
|
+
viewport: { width: 1280, height: 900 },
|
|
17
|
+
reducedMotion: reducedMotion ? 'reduce' : 'no-preference',
|
|
18
|
+
});
|
|
19
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
20
|
+
await ctx.addInitScript(() => {
|
|
21
|
+
try {
|
|
22
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
23
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
24
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
25
|
+
} catch {}
|
|
26
|
+
});
|
|
27
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
28
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
29
|
+
const r = await route.fetch();
|
|
30
|
+
const b = await r.json();
|
|
31
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
32
|
+
const sessions = ['alpha', 'beta', 'gamma'].map(a => ({
|
|
33
|
+
alias: a, status: 'idle', network_id: nid, project_dir: null,
|
|
34
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
35
|
+
}));
|
|
36
|
+
await route.fulfill({ response: r, json: { ...b, sessions } });
|
|
37
|
+
});
|
|
38
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
|
|
39
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
40
|
+
const page = await ctx.newPage();
|
|
41
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
42
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 3, { timeout: 30000 });
|
|
43
|
+
await page.waitForTimeout(500);
|
|
44
|
+
|
|
45
|
+
const readTy = (alias) => page.evaluate(a => {
|
|
46
|
+
const el = document.querySelector(`g[data-node="${a}"]`);
|
|
47
|
+
if (!el) return null;
|
|
48
|
+
const m = getComputedStyle(el).transform;
|
|
49
|
+
if (!m || m === 'none') return 0;
|
|
50
|
+
// matrix(a, b, c, d, tx, ty) — extract ty
|
|
51
|
+
const parts = m.match(/matrix\(([^)]+)\)/);
|
|
52
|
+
if (!parts) return null;
|
|
53
|
+
const arr = parts[1].split(',').map(s => parseFloat(s.trim()));
|
|
54
|
+
return arr[5] ?? null;
|
|
55
|
+
}, alias);
|
|
56
|
+
|
|
57
|
+
const restAlpha = await readTy('alpha');
|
|
58
|
+
const restBeta = await readTy('beta');
|
|
59
|
+
await page.locator('g[data-node="alpha"]').hover({ force: true });
|
|
60
|
+
await page.waitForTimeout(300);
|
|
61
|
+
const hoveredAlpha = await readTy('alpha');
|
|
62
|
+
const hoveredBeta = await readTy('beta');
|
|
63
|
+
await page.mouse.move(10, 10);
|
|
64
|
+
await page.waitForTimeout(300);
|
|
65
|
+
const releasedAlpha = await readTy('alpha');
|
|
66
|
+
|
|
67
|
+
await ctx.close();
|
|
68
|
+
return { restAlpha, restBeta, hoveredAlpha, hoveredBeta, releasedAlpha };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const normal = await probe(false);
|
|
72
|
+
const reduced = await probe(true);
|
|
73
|
+
await browser.close();
|
|
74
|
+
|
|
75
|
+
const results = {
|
|
76
|
+
normal_restAtZero: normal.restAlpha === 0 && normal.restBeta === 0,
|
|
77
|
+
normal_hoveredLifts: normal.hoveredAlpha === -2,
|
|
78
|
+
normal_siblingStays: normal.hoveredBeta === 0,
|
|
79
|
+
normal_released: normal.releasedAlpha === 0,
|
|
80
|
+
reduced_noLift: reduced.hoveredAlpha === 0,
|
|
81
|
+
};
|
|
82
|
+
const ok = Object.values(results).every(Boolean);
|
|
83
|
+
console.log(`${ok ? '✅' : '❌'} node hover lift:`, JSON.stringify(results),
|
|
84
|
+
`\n normal=`, normal, `\n reduced=`, reduced);
|
|
85
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/* Round 194 verification: node label card picks up drop-shadow
|
|
2
|
+
* elevation that intensifies on node hover, mirroring R135's panel
|
|
3
|
+
* hover-elevation but at per-node grain.
|
|
4
|
+
*
|
|
5
|
+
* Pre-R194 the card lifted 1.5 px on hover (R26) but had no shadow
|
|
6
|
+
* follow — the elevation gesture lacked physical weight. R194 adds
|
|
7
|
+
* rest : drop-shadow(0 1px 2px rgba(...,0.30 dark / 0.08 light))
|
|
8
|
+
* hover : drop-shadow(0 4px 12px rgba(0,0,0,0.60) dark
|
|
9
|
+
* / 0 3px 8px rgba(15,23,42,0.20) light)
|
|
10
|
+
* with transition: filter 220ms ease-out.
|
|
11
|
+
*
|
|
12
|
+
* Test (cyber/dark theme, 4 sessions = card mode):
|
|
13
|
+
* 1. data-node-label-card present + matches alias
|
|
14
|
+
* 2. Idle elevation attr = 'idle'
|
|
15
|
+
* 3. Idle filter style includes 'drop-shadow' (rest shadow on)
|
|
16
|
+
* 4. Idle blur radius is small (1-2 px range)
|
|
17
|
+
* 5. transition: filter 220ms ease-out
|
|
18
|
+
* 6. Hover the node — wait past 250ms
|
|
19
|
+
* 7. data-node-label-card-elevation flips to 'hover'
|
|
20
|
+
* 8. Hover filter has bigger blur (>= 8px) — drop-shadow strengthened
|
|
21
|
+
* 9. Other (non-hovered) cards stay 'idle'
|
|
22
|
+
* 10. Unhover — flips back to 'idle'
|
|
23
|
+
* 11. Filter transition string still present after settle
|
|
24
|
+
*/
|
|
25
|
+
import { chromium } from 'playwright';
|
|
26
|
+
import { readFileSync } from 'node:fs';
|
|
27
|
+
|
|
28
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
29
|
+
const browser = await chromium.launch({ headless: true });
|
|
30
|
+
|
|
31
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
32
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
33
|
+
await ctx.addInitScript(() => {
|
|
34
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
38
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
39
|
+
const r = await route.fetch();
|
|
40
|
+
const b = await r.json();
|
|
41
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
42
|
+
const mk = (alias) => ({
|
|
43
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
44
|
+
network_id: nid, project_dir: null,
|
|
45
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
46
|
+
});
|
|
47
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
48
|
+
mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
|
|
49
|
+
] } });
|
|
50
|
+
});
|
|
51
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
|
|
52
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
53
|
+
|
|
54
|
+
const page = await ctx.newPage();
|
|
55
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
56
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
|
|
57
|
+
await page.waitForSelector('[data-node-label-card]', { timeout: 10000 });
|
|
58
|
+
await page.waitForTimeout(400);
|
|
59
|
+
|
|
60
|
+
// Probe idle state of alpha's label card
|
|
61
|
+
const idleAlpha = await page.evaluate(() => {
|
|
62
|
+
const el = document.querySelector('[data-node-label-card="alpha"]');
|
|
63
|
+
if (!el) return null;
|
|
64
|
+
const cs = getComputedStyle(el);
|
|
65
|
+
return {
|
|
66
|
+
alias: el.getAttribute('data-node-label-card'),
|
|
67
|
+
elevation: el.getAttribute('data-node-label-card-elevation'),
|
|
68
|
+
filter: cs.filter,
|
|
69
|
+
transition: cs.transitionProperty + ' / ' + cs.transitionDuration,
|
|
70
|
+
inlineFilter: el.style.filter,
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Hover the alpha node's <g> wrapper
|
|
75
|
+
await page.hover('g[data-node="alpha"]');
|
|
76
|
+
await page.waitForTimeout(280); // past 220ms transition
|
|
77
|
+
|
|
78
|
+
const hoveredAlpha = await page.evaluate(() => {
|
|
79
|
+
const el = document.querySelector('[data-node-label-card="alpha"]');
|
|
80
|
+
const cs = getComputedStyle(el);
|
|
81
|
+
return {
|
|
82
|
+
elevation: el.getAttribute('data-node-label-card-elevation'),
|
|
83
|
+
filter: cs.filter,
|
|
84
|
+
inlineFilter: el.style.filter,
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Probe non-hovered card (beta) stays idle
|
|
89
|
+
const idleBeta = await page.evaluate(() => {
|
|
90
|
+
const el = document.querySelector('[data-node-label-card="beta"]');
|
|
91
|
+
return {
|
|
92
|
+
elevation: el.getAttribute('data-node-label-card-elevation'),
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Move away, wait for transition back
|
|
97
|
+
await page.mouse.move(0, 0);
|
|
98
|
+
await page.waitForTimeout(280);
|
|
99
|
+
|
|
100
|
+
const settledAlpha = await page.evaluate(() => {
|
|
101
|
+
const el = document.querySelector('[data-node-label-card="alpha"]');
|
|
102
|
+
const cs = getComputedStyle(el);
|
|
103
|
+
return {
|
|
104
|
+
elevation: el.getAttribute('data-node-label-card-elevation'),
|
|
105
|
+
filter: cs.filter,
|
|
106
|
+
transition: cs.transitionProperty + ' / ' + cs.transitionDuration,
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
await browser.close();
|
|
111
|
+
|
|
112
|
+
// Parse blur radius out of drop-shadow(). Chrome's getComputedStyle
|
|
113
|
+
// canonicalises into `drop-shadow(rgba(...) 0px Ypx BLURpx)` with the
|
|
114
|
+
// color first — the standard write-order `drop-shadow(0 Ypx BLURpx
|
|
115
|
+
// rgba(...))` is rearranged. So scan all numeric tokens inside the
|
|
116
|
+
// drop-shadow() parens with rgba/hsla content stripped first; blur is
|
|
117
|
+
// the 3rd numeric value.
|
|
118
|
+
function parseShadowBlur(filterStr) {
|
|
119
|
+
if (!filterStr) return null;
|
|
120
|
+
const m = filterStr.match(/drop-shadow\(([\s\S]+)\)\s*$/);
|
|
121
|
+
if (!m) return null;
|
|
122
|
+
const stripped = m[1].replace(/(rgba?|hsla?)\([^)]*\)/g, '');
|
|
123
|
+
const nums = (stripped.match(/-?\d+(?:\.\d+)?/g) || []).map(Number);
|
|
124
|
+
return nums.length >= 3 ? Math.abs(nums[2]) : null;
|
|
125
|
+
}
|
|
126
|
+
const idleBlur = parseShadowBlur(idleAlpha?.filter);
|
|
127
|
+
const hoverBlur = parseShadowBlur(hoveredAlpha?.filter);
|
|
128
|
+
const settledBlur = parseShadowBlur(settledAlpha?.filter);
|
|
129
|
+
|
|
130
|
+
const results = {
|
|
131
|
+
card_present: !!idleAlpha,
|
|
132
|
+
alias_matches: idleAlpha?.alias === 'alpha',
|
|
133
|
+
idle_elevation_attr: idleAlpha?.elevation === 'idle',
|
|
134
|
+
idle_has_dropshadow: (idleAlpha?.filter || '').includes('drop-shadow'),
|
|
135
|
+
idle_blur_small: idleBlur !== null && idleBlur > 0 && idleBlur <= 3,
|
|
136
|
+
filter_transition: idleAlpha?.transition.includes('filter') && idleAlpha?.transition.includes('0.22s'),
|
|
137
|
+
|
|
138
|
+
hover_elevation_attr: hoveredAlpha?.elevation === 'hover',
|
|
139
|
+
hover_has_dropshadow: (hoveredAlpha?.filter || '').includes('drop-shadow'),
|
|
140
|
+
hover_blur_larger: hoverBlur !== null && hoverBlur >= 8,
|
|
141
|
+
hover_blur_grew: idleBlur !== null && hoverBlur !== null && hoverBlur > idleBlur,
|
|
142
|
+
hover_filter_changed: idleAlpha?.filter !== hoveredAlpha?.filter,
|
|
143
|
+
|
|
144
|
+
beta_stays_idle: idleBeta?.elevation === 'idle',
|
|
145
|
+
|
|
146
|
+
settled_back_to_idle: settledAlpha?.elevation === 'idle',
|
|
147
|
+
settled_blur_small: settledBlur !== null && settledBlur <= 3,
|
|
148
|
+
settled_keeps_transition: settledAlpha?.transition.includes('filter'),
|
|
149
|
+
};
|
|
150
|
+
const ok = Object.values(results).every(Boolean);
|
|
151
|
+
console.log(`${ok ? '✅' : '❌'} node label card elevation:`, JSON.stringify(results),
|
|
152
|
+
`\n idleAlpha:`, idleAlpha,
|
|
153
|
+
`\n hoveredAlpha:`, hoveredAlpha,
|
|
154
|
+
`\n idleBeta:`, idleBeta,
|
|
155
|
+
`\n settledAlpha:`, settledAlpha,
|
|
156
|
+
`\n blurs:`, { idleBlur, hoverBlur, settledBlur });
|
|
157
|
+
process.exit(ok ? 0 : 1);
|