@mastra/playground-ui 68.0.0-alpha.2 → 68.0.0
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/dist/{FilterBar-CQl04O6t.cjs → FilterBar-BSP2UTjc.cjs} +2 -2
- package/dist/{FilterBar-CQl04O6t.cjs.map → FilterBar-BSP2UTjc.cjs.map} +1 -1
- package/dist/{FilterBar-BgW2dqRQ.js → FilterBar-PSQ1OwqH.js} +2 -2
- package/dist/{FilterBar-BgW2dqRQ.js.map → FilterBar-PSQ1OwqH.js.map} +1 -1
- package/dist/KnowledgePageGraph.css +55 -0
- package/dist/{MarkdownRenderer-2GOXQJEv.js → MarkdownRenderer-CI30RqdB.js} +19 -6
- package/dist/MarkdownRenderer-CI30RqdB.js.map +1 -0
- package/dist/{MarkdownRenderer-CB8Z_CHc.cjs → MarkdownRenderer-y65WGBhC.cjs} +19 -6
- package/dist/MarkdownRenderer-y65WGBhC.cjs.map +1 -0
- package/dist/{MetricsCard-CEB-f2sv.cjs → MetricsCard-BEwiS7Pe.cjs} +8 -8
- package/dist/MetricsCard-BEwiS7Pe.cjs.map +1 -0
- package/dist/{MetricsCard-M8awJ2B_.js → MetricsCard-ua6C6b8a.js} +10 -10
- package/dist/MetricsCard-ua6C6b8a.js.map +1 -0
- package/dist/{MetricsLineChart-BhHoduO0.js → MetricsLineChart-4SwxBbQx.js} +14 -3
- package/dist/MetricsLineChart-4SwxBbQx.js.map +1 -0
- package/dist/{MetricsLineChart-CjBm4IXu.cjs → MetricsLineChart-tZxsauau.cjs} +13 -2
- package/dist/MetricsLineChart-tZxsauau.cjs.map +1 -0
- package/dist/{MetricsStackedBarChart-BdMlKv6G.cjs → MetricsStackedBarChart-CDLE76IB.cjs} +2 -2
- package/dist/{MetricsStackedBarChart-BdMlKv6G.cjs.map → MetricsStackedBarChart-CDLE76IB.cjs.map} +1 -1
- package/dist/{MetricsStackedBarChart-BRuA6MTE.js → MetricsStackedBarChart-D2QyS4-z.js} +2 -2
- package/dist/{MetricsStackedBarChart-BRuA6MTE.js.map → MetricsStackedBarChart-D2QyS4-z.js.map} +1 -1
- package/dist/{activity-rJ1NQl_2.js → activity-C8Ql81WM.js} +2 -2
- package/dist/{activity-rJ1NQl_2.js.map → activity-C8Ql81WM.js.map} +1 -1
- package/dist/{activity-DyB5H3gF.cjs → activity-CcQZeDYi.cjs} +2 -2
- package/dist/{activity-DyB5H3gF.cjs.map → activity-CcQZeDYi.cjs.map} +1 -1
- package/dist/components/DateTimeRangePicker.cjs.js +1 -1
- package/dist/components/DateTimeRangePicker.es.js +1 -1
- package/dist/components/FilterBar.cjs.js +2 -2
- package/dist/components/FilterBar.es.js +2 -2
- package/dist/components/MarkdownRenderer.cjs.js +1 -1
- package/dist/components/MarkdownRenderer.es.js +1 -1
- package/dist/components/MetricsCard.cjs.js +1 -1
- package/dist/components/MetricsCard.es.js +1 -1
- package/dist/components/MetricsLineChart.cjs.js +1 -1
- package/dist/components/MetricsLineChart.es.js +1 -1
- package/dist/components/MetricsStackedBarChart.cjs.js +1 -1
- package/dist/components/MetricsStackedBarChart.es.js +1 -1
- package/dist/components/SavedViews.cjs.js +1 -1
- package/dist/components/SavedViews.es.js +1 -1
- package/dist/components/ai/activity.cjs.js +1 -1
- package/dist/components/ai/activity.es.js +1 -1
- package/dist/components/ai/plan.cjs.js +1 -1
- package/dist/components/ai/plan.es.js +1 -1
- package/dist/components/ai/tool-approval.cjs.js +1 -1
- package/dist/components/ai/tool-approval.es.js +1 -1
- package/dist/components/ai/tool-call.cjs.js +2 -2
- package/dist/components/ai/tool-call.es.js +2 -2
- package/dist/{date-time-range-picker-CTt7Od0P.cjs → date-time-range-picker-CWGjoR3j.cjs} +40 -13
- package/dist/date-time-range-picker-CWGjoR3j.cjs.map +1 -0
- package/dist/{date-time-range-picker-DKh1K9Iy.js → date-time-range-picker-CdSiXwB4.js} +40 -13
- package/dist/date-time-range-picker-CdSiXwB4.js.map +1 -0
- package/dist/domains/chat/activity/activity-stretch-line.cjs.js +1 -1
- package/dist/domains/chat/activity/activity-stretch-line.es.js +1 -1
- package/dist/domains/chat/activity/components/activity-fold.cjs.js +1 -1
- package/dist/domains/chat/activity/components/activity-fold.es.js +1 -1
- package/dist/domains/chat/activity/components/activity-timed-trigger.cjs.js +1 -1
- package/dist/domains/chat/activity/components/activity-timed-trigger.es.js +1 -1
- package/dist/domains/chat/activity/components/calls-panel.cjs.js +1 -1
- package/dist/domains/chat/activity/components/calls-panel.es.js +1 -1
- package/dist/domains/chat/activity/components/stretch-content.cjs.js +1 -1
- package/dist/domains/chat/activity/components/stretch-content.es.js +1 -1
- package/dist/domains/chat/activity/components/stretch-thought.cjs.js +1 -1
- package/dist/domains/chat/activity/components/stretch-thought.es.js +1 -1
- package/dist/domains/chat/activity/model/activity-segments.cjs.js +1 -1
- package/dist/domains/chat/activity/model/activity-segments.es.js +1 -1
- package/dist/domains/chat/activity/model/activity-words.cjs.js +2 -2
- package/dist/domains/chat/activity/model/activity-words.es.js +2 -2
- package/dist/domains/chat/components/badge-wrapper.cjs.js +1 -1
- package/dist/domains/chat/components/badge-wrapper.es.js +1 -1
- package/dist/domains/chat/knowledge/knowledge-links.cjs.js +52 -6
- package/dist/domains/chat/knowledge/knowledge-links.cjs.js.map +1 -1
- package/dist/domains/chat/knowledge/knowledge-links.es.js +53 -9
- package/dist/domains/chat/knowledge/knowledge-links.es.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js +10 -3
- package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js +10 -3
- package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js +8 -3
- package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js.map +1 -1
- package/dist/domains/chat/knowledge/pinned-knowledge.es.js +8 -3
- package/dist/domains/chat/knowledge/pinned-knowledge.es.js.map +1 -1
- package/dist/domains/chat/knowledge.cjs.js +2 -0
- package/dist/domains/chat/knowledge.es.js +2 -2
- package/dist/domains/chat/messages/message-row.cjs.js +3 -3
- package/dist/domains/chat/messages/message-row.es.js +3 -3
- package/dist/domains/chat/messages/notification-signal-notice.cjs.js +1 -1
- package/dist/domains/chat/messages/notification-signal-notice.es.js +1 -1
- package/dist/domains/chat/messages/reasoning-content.cjs.js +1 -1
- package/dist/domains/chat/messages/reasoning-content.es.js +1 -1
- package/dist/domains/chat/messages/renderers/message-text.cjs.js +35 -1
- package/dist/domains/chat/messages/renderers/message-text.cjs.js.map +1 -1
- package/dist/domains/chat/messages/renderers/message-text.es.js +36 -2
- package/dist/domains/chat/messages/renderers/message-text.es.js.map +1 -1
- package/dist/domains/chat/messages/renderers/reasoning-part-renderer.cjs.js +1 -1
- package/dist/domains/chat/messages/renderers/reasoning-part-renderer.es.js +1 -1
- package/dist/domains/chat/messages/signal-badge.cjs.js +1 -1
- package/dist/domains/chat/messages/signal-badge.es.js +1 -1
- package/dist/domains/chat/messages/skill-message.cjs.js +2 -2
- package/dist/domains/chat/messages/skill-message.es.js +2 -2
- package/dist/domains/chat/messages/system-reminder-badge.cjs.js +1 -1
- package/dist/domains/chat/messages/system-reminder-badge.es.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge-wrapper.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge-wrapper.es.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/agent-badge.es.js +1 -1
- package/dist/domains/chat/tools/badges/file-tree-badge.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/file-tree-badge.es.js +2 -2
- package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js +80 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js.map +1 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.d.ts +1 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.es.js +78 -0
- package/dist/domains/chat/tools/badges/knowledge-body-range.es.js.map +1 -0
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js +163 -13
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js +165 -15
- package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js +51 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js.map +1 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.d.ts +1 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js +49 -0
- package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js.map +1 -0
- package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js +7 -2
- package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/mcp-task-chip.es.js +7 -2
- package/dist/domains/chat/tools/badges/mcp-task-chip.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/observation-marker-badge.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/observation-marker-badge.es.js +2 -2
- package/dist/domains/chat/tools/badges/observation-marker-details.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/observation-marker-details.es.js +2 -2
- package/dist/domains/chat/tools/badges/observation-renderer.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/observation-renderer.es.js +1 -1
- package/dist/domains/chat/tools/badges/sandbox-execution-badge.cjs.js +2 -2
- package/dist/domains/chat/tools/badges/sandbox-execution-badge.es.js +2 -2
- package/dist/domains/chat/tools/badges/tool-approval-badge.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/tool-approval-badge.es.js +1 -1
- package/dist/domains/chat/tools/badges/tool-badge.cjs.js +9 -4
- package/dist/domains/chat/tools/badges/tool-badge.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/tool-badge.es.js +9 -4
- package/dist/domains/chat/tools/badges/tool-badge.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js +81 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js.map +1 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.d.ts +1 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js +77 -0
- package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js.map +1 -0
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js +11 -2
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js.map +1 -1
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js +11 -2
- package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js.map +1 -1
- package/dist/domains/chat/tools/badges/workflow-badge.cjs.js +1 -1
- package/dist/domains/chat/tools/badges/workflow-badge.es.js +1 -1
- package/dist/domains/chat/tools/connect-prompt-tool.cjs.js +79 -4
- package/dist/domains/chat/tools/connect-prompt-tool.cjs.js.map +1 -1
- package/dist/domains/chat/tools/connect-prompt-tool.es.js +79 -4
- package/dist/domains/chat/tools/connect-prompt-tool.es.js.map +1 -1
- package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js +238 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js.map +1 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.d.ts +1 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.es.js +237 -0
- package/dist/domains/chat/tools/mcp-input-request-tool.es.js.map +1 -0
- package/dist/domains/chat/tools/mcp-input-request.cjs.js +40 -0
- package/dist/domains/chat/tools/mcp-input-request.cjs.js.map +1 -0
- package/dist/domains/chat/tools/mcp-input-request.d.ts +1 -0
- package/dist/domains/chat/tools/mcp-input-request.es.js +33 -0
- package/dist/domains/chat/tools/mcp-input-request.es.js.map +1 -0
- package/dist/domains/chat/tools/tool-card-kind.cjs.js +9 -4
- package/dist/domains/chat/tools/tool-card-kind.cjs.js.map +1 -1
- package/dist/domains/chat/tools/tool-card-kind.es.js +9 -5
- package/dist/domains/chat/tools/tool-card-kind.es.js.map +1 -1
- package/dist/domains/chat/tools/tool-card.cjs.js +1 -1
- package/dist/domains/chat/tools/tool-card.es.js +1 -1
- package/dist/domains/chat/tools/tool-groups.cjs.js +1 -1
- package/dist/domains/chat/tools/tool-groups.es.js +1 -1
- package/dist/domains/chat.cjs.js +5 -3
- package/dist/domains/chat.es.js +4 -4
- package/dist/domains/connect/types.cjs.js.map +1 -1
- package/dist/domains/connect/types.es.js.map +1 -1
- package/dist/domains/connect/use-user-connect.cjs.js +19 -2
- package/dist/domains/connect/use-user-connect.cjs.js.map +1 -1
- package/dist/domains/connect/use-user-connect.es.js +19 -2
- package/dist/domains/connect/use-user-connect.es.js.map +1 -1
- package/dist/domains/dashboards/components/dashboard-renderer.cjs.js +4 -3
- package/dist/domains/dashboards/components/dashboard-renderer.cjs.js.map +1 -1
- package/dist/domains/dashboards/components/dashboard-renderer.es.js +4 -3
- package/dist/domains/dashboards/components/dashboard-renderer.es.js.map +1 -1
- package/dist/domains/dashboards/components/widget-chrome.cjs.js +1 -1
- package/dist/domains/dashboards/components/widget-chrome.es.js +1 -1
- package/dist/domains/dashboards/components/widget-error.cjs.js +1 -1
- package/dist/domains/dashboards/components/widget-error.es.js +1 -1
- package/dist/domains/dashboards/hooks/use-widget-views.cjs.js +4 -3
- package/dist/domains/dashboards/hooks/use-widget-views.cjs.js.map +1 -1
- package/dist/domains/dashboards/hooks/use-widget-views.es.js +4 -3
- package/dist/domains/dashboards/hooks/use-widget-views.es.js.map +1 -1
- package/dist/domains/dashboards/kinds/scores/scores-widget.cjs.js +9 -6
- package/dist/domains/dashboards/kinds/scores/scores-widget.cjs.js.map +1 -1
- package/dist/domains/dashboards/kinds/scores/scores-widget.es.js +9 -6
- package/dist/domains/dashboards/kinds/scores/scores-widget.es.js.map +1 -1
- package/dist/domains/dashboards/kinds/table/table-tabs.cjs.js +2 -2
- package/dist/domains/dashboards/kinds/table/table-tabs.es.js +2 -2
- package/dist/domains/dashboards/kinds/table/table-widget.cjs.js +1 -1
- package/dist/domains/dashboards/kinds/table/table-widget.es.js +1 -1
- package/dist/domains/dashboards/kinds/timeseries/timeseries-widget.cjs.js +6 -5
- package/dist/domains/dashboards/kinds/timeseries/timeseries-widget.cjs.js.map +1 -1
- package/dist/domains/dashboards/kinds/timeseries/timeseries-widget.es.js +6 -5
- package/dist/domains/dashboards/kinds/timeseries/timeseries-widget.es.js.map +1 -1
- package/dist/domains/dashboards/lib/chrome.cjs.js +9 -2
- package/dist/domains/dashboards/lib/chrome.cjs.js.map +1 -1
- package/dist/domains/dashboards/lib/chrome.es.js +9 -2
- package/dist/domains/dashboards/lib/chrome.es.js.map +1 -1
- package/dist/domains/dashboards/widget-kind.cjs.js.map +1 -1
- package/dist/domains/dashboards/widget-kind.es.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js +48 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js.map +1 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.d.ts +1 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.es.js +47 -0
- package/dist/domains/knowledge/components/KnowledgePageCard.es.js.map +1 -0
- package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js +63 -5
- package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageDetail.es.js +64 -6
- package/dist/domains/knowledge/components/KnowledgePageDetail.es.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js +485 -47
- package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js +487 -50
- package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js +1051 -123
- package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageGraph.es.js +1054 -126
- package/dist/domains/knowledge/components/KnowledgePageGraph.es.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js +75 -3
- package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js.map +1 -1
- package/dist/domains/knowledge/components/KnowledgePageTree.es.js +76 -4
- package/dist/domains/knowledge/components/KnowledgePageTree.es.js.map +1 -1
- package/dist/domains/knowledge/lib/circleText.cjs.js +9 -0
- package/dist/domains/knowledge/lib/circleText.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/circleText.d.ts +1 -0
- package/dist/domains/knowledge/lib/circleText.es.js +8 -0
- package/dist/domains/knowledge/lib/circleText.es.js.map +1 -0
- package/dist/domains/knowledge/lib/fitViewport.cjs.js +82 -0
- package/dist/domains/knowledge/lib/fitViewport.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/fitViewport.d.ts +1 -0
- package/dist/domains/knowledge/lib/fitViewport.es.js +73 -0
- package/dist/domains/knowledge/lib/fitViewport.es.js.map +1 -0
- package/dist/domains/knowledge/lib/graphShape.cjs.js +524 -0
- package/dist/domains/knowledge/lib/graphShape.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/graphShape.d.ts +1 -0
- package/dist/domains/knowledge/lib/graphShape.es.js +499 -0
- package/dist/domains/knowledge/lib/graphShape.es.js.map +1 -0
- package/dist/domains/knowledge/lib/linkCountsText.cjs.js +11 -0
- package/dist/domains/knowledge/lib/linkCountsText.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/linkCountsText.d.ts +1 -0
- package/dist/domains/knowledge/lib/linkCountsText.es.js +10 -0
- package/dist/domains/knowledge/lib/linkCountsText.es.js.map +1 -0
- package/dist/domains/knowledge/lib/pageAddress.cjs.js +29 -0
- package/dist/domains/knowledge/lib/pageAddress.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/pageAddress.d.ts +1 -0
- package/dist/domains/knowledge/lib/pageAddress.es.js +27 -0
- package/dist/domains/knowledge/lib/pageAddress.es.js.map +1 -0
- package/dist/domains/knowledge/lib/pageGraph.cjs.js +11 -11
- package/dist/domains/knowledge/lib/pageGraph.cjs.js.map +1 -1
- package/dist/domains/knowledge/lib/pageGraph.es.js +11 -11
- package/dist/domains/knowledge/lib/pageGraph.es.js.map +1 -1
- package/dist/domains/knowledge/lib/pageRefs.cjs.js +69 -0
- package/dist/domains/knowledge/lib/pageRefs.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/pageRefs.d.ts +1 -0
- package/dist/domains/knowledge/lib/pageRefs.es.js +66 -0
- package/dist/domains/knowledge/lib/pageRefs.es.js.map +1 -0
- package/dist/domains/knowledge/lib/pageTree.cjs.js +5 -0
- package/dist/domains/knowledge/lib/pageTree.cjs.js.map +1 -1
- package/dist/domains/knowledge/lib/pageTree.es.js +5 -1
- package/dist/domains/knowledge/lib/pageTree.es.js.map +1 -1
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js +82 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +1 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js +78 -0
- package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js.map +1 -0
- package/dist/domains/knowledge/lib/tooltipSide.cjs.js +77 -0
- package/dist/domains/knowledge/lib/tooltipSide.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/tooltipSide.d.ts +1 -0
- package/dist/domains/knowledge/lib/tooltipSide.es.js +75 -0
- package/dist/domains/knowledge/lib/tooltipSide.es.js.map +1 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js +65 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.d.ts +1 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.es.js +62 -0
- package/dist/domains/knowledge/lib/useLeavingNodes.es.js.map +1 -0
- package/dist/domains/knowledge/lib/useStableWhile.cjs.js +15 -0
- package/dist/domains/knowledge/lib/useStableWhile.cjs.js.map +1 -0
- package/dist/domains/knowledge/lib/useStableWhile.d.ts +1 -0
- package/dist/domains/knowledge/lib/useStableWhile.es.js +14 -0
- package/dist/domains/knowledge/lib/useStableWhile.es.js.map +1 -0
- package/dist/domains/metrics/components/agent-runs-card.cjs.js +3 -3
- package/dist/domains/metrics/components/agent-runs-card.es.js +3 -3
- package/dist/domains/metrics/components/breakdown/breakdown-tab-body.cjs.js +1 -1
- package/dist/domains/metrics/components/breakdown/breakdown-tab-body.es.js +1 -1
- package/dist/domains/metrics/components/breakdown-card.cjs.js +1 -1
- package/dist/domains/metrics/components/breakdown-card.es.js +1 -1
- package/dist/domains/metrics/components/chart-area.cjs.js +1 -1
- package/dist/domains/metrics/components/chart-area.es.js +1 -1
- package/dist/domains/metrics/components/chart-card-error.cjs.js +1 -1
- package/dist/domains/metrics/components/chart-card-error.es.js +1 -1
- package/dist/domains/metrics/components/chart-card.cjs.js +1 -1
- package/dist/domains/metrics/components/chart-card.es.js +1 -1
- package/dist/domains/metrics/components/date-range-selector.cjs.js +1 -1
- package/dist/domains/metrics/components/date-range-selector.es.js +1 -1
- package/dist/domains/metrics/components/distinct-ids/distinct-ids-chart.cjs.js +3 -2
- package/dist/domains/metrics/components/distinct-ids/distinct-ids-chart.cjs.js.map +1 -1
- package/dist/domains/metrics/components/distinct-ids/distinct-ids-chart.es.js +3 -2
- package/dist/domains/metrics/components/distinct-ids/distinct-ids-chart.es.js.map +1 -1
- package/dist/domains/metrics/components/failure-rate-card.cjs.js +3 -2
- package/dist/domains/metrics/components/failure-rate-card.cjs.js.map +1 -1
- package/dist/domains/metrics/components/failure-rate-card.es.js +3 -2
- package/dist/domains/metrics/components/failure-rate-card.es.js.map +1 -1
- package/dist/domains/metrics/components/latency-card.cjs.js +3 -2
- package/dist/domains/metrics/components/latency-card.cjs.js.map +1 -1
- package/dist/domains/metrics/components/latency-card.es.js +3 -2
- package/dist/domains/metrics/components/latency-card.es.js.map +1 -1
- package/dist/domains/metrics/components/metrics-time-range-chip.cjs.js +1 -1
- package/dist/domains/metrics/components/metrics-time-range-chip.es.js +1 -1
- package/dist/domains/metrics/components/scores-card.cjs.js +2 -1
- package/dist/domains/metrics/components/scores-card.cjs.js.map +1 -1
- package/dist/domains/metrics/components/scores-card.es.js +2 -1
- package/dist/domains/metrics/components/scores-card.es.js.map +1 -1
- package/dist/domains/metrics/components/token-usage-card.cjs.js +3 -3
- package/dist/domains/metrics/components/token-usage-card.es.js +3 -3
- package/dist/domains/metrics/components/trace-aggregate-card.cjs.js +1 -1
- package/dist/domains/metrics/components/trace-aggregate-card.es.js +1 -1
- package/dist/domains/observability/components/observability-histogram.cjs.js +1 -1
- package/dist/domains/observability/components/observability-histogram.es.js +1 -1
- package/dist/domains/scores/components/trace-scores-list.cjs.js +2 -2
- package/dist/domains/scores/components/trace-scores-list.es.js +2 -2
- package/dist/domains/skills/skill-simple-form.cjs.js +1 -1
- package/dist/domains/skills/skill-simple-form.es.js +1 -1
- package/dist/domains/spans/components/spans-filter-bar.cjs.js +2 -2
- package/dist/domains/spans/components/spans-filter-bar.es.js +2 -2
- package/dist/domains/spans/hooks/use-spans-filter-bar.cjs.js +1 -1
- package/dist/domains/spans/hooks/use-spans-filter-bar.es.js +1 -1
- package/dist/domains/threads/components/threads-filter-bar.cjs.js +2 -2
- package/dist/domains/threads/components/threads-filter-bar.es.js +2 -2
- package/dist/domains/threads/hooks/use-threads-filter-bar.cjs.js +1 -1
- package/dist/domains/threads/hooks/use-threads-filter-bar.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-error-renderer.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-error-renderer.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-input-renderers.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-input-renderers.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-output-renderers.cjs.js +2 -2
- package/dist/domains/traces/components/span-payload/span-output-renderers.es.js +2 -2
- package/dist/domains/traces/components/span-payload/span-payload-messages.cjs.js +2 -2
- package/dist/domains/traces/components/span-payload/span-payload-messages.es.js +2 -2
- package/dist/domains/traces/components/span-payload/span-payload-primitives.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-primitives.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-processor.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-processor.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-tool.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-payload-tool.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-processor-mutations.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-processor-mutations.es.js +1 -1
- package/dist/domains/traces/components/span-payload/span-tools-section.cjs.js +1 -1
- package/dist/domains/traces/components/span-payload/span-tools-section.es.js +1 -1
- package/dist/domains/traces/components/span-timeline-row.cjs.js +1 -1
- package/dist/domains/traces/components/span-timeline-row.es.js +1 -1
- package/dist/domains/traces/components/span-timing-hover-card.cjs.js +1 -1
- package/dist/domains/traces/components/span-timing-hover-card.es.js +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.cjs.js +8 -2
- package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.es.js +8 -2
- package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
- package/dist/domains/traces/components/trace-error-cell.cjs.js +1 -1
- package/dist/domains/traces/components/trace-error-cell.es.js +1 -1
- package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js +2 -2
- package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js +2 -2
- package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.cjs.js +1 -1
- package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.es.js +1 -1
- package/dist/domains/workflows/runs/workflow-run-list.cjs.js +1 -1
- package/dist/domains/workflows/runs/workflow-run-list.es.js +1 -1
- package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js +2 -2
- package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js +2 -2
- package/dist/domains/workflows/workflow/use-workflow-trigger.cjs.js +3 -3
- package/dist/domains/workflows/workflow/use-workflow-trigger.es.js +3 -3
- package/dist/domains/workflows/workflow/workflow-input-data.cjs.js +1 -1
- package/dist/domains/workflows/workflow/workflow-input-data.es.js +1 -1
- package/dist/domains/workflows/workflow/workflow-suspended-steps.cjs.js +2 -2
- package/dist/domains/workflows/workflow/workflow-suspended-steps.es.js +2 -2
- package/dist/domains/workflows/workflow/workflow-time-travel-form.cjs.js +2 -2
- package/dist/domains/workflows/workflow/workflow-time-travel-form.es.js +2 -2
- package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js +1 -1
- package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js +1 -1
- package/dist/domains/workspace/components/workspace-markdown-preview.cjs.js +1 -1
- package/dist/domains/workspace/components/workspace-markdown-preview.es.js +1 -1
- package/dist/{filter-bar-time-range-mg9JeYue.js → filter-bar-time-range-qlV8p7hp.js} +2 -2
- package/dist/{filter-bar-time-range-mg9JeYue.js.map → filter-bar-time-range-qlV8p7hp.js.map} +1 -1
- package/dist/{filter-bar-time-range-BA-pXMlo.cjs → filter-bar-time-range-zdM024JD.cjs} +2 -2
- package/dist/{filter-bar-time-range-BA-pXMlo.cjs.map → filter-bar-time-range-zdM024JD.cjs.map} +1 -1
- package/dist/lib/form/dynamic-form.cjs.js +2 -2
- package/dist/lib/form/dynamic-form.es.js +2 -2
- package/dist/lib/form/json-draft.cjs.js +1 -1
- package/dist/lib/form/json-draft.es.js +1 -1
- package/dist/lib/form/zod-provider.cjs.js +1 -1
- package/dist/lib/form/zod-provider.es.js +1 -1
- package/dist/{span-payload-primitives-B3RdahsC.js → span-payload-primitives-CKKIAVPJ.js} +4 -4
- package/dist/{span-payload-primitives-B3RdahsC.js.map → span-payload-primitives-CKKIAVPJ.js.map} +1 -1
- package/dist/{span-payload-primitives-_2d-pAOD.cjs → span-payload-primitives-D4tHWN2W.cjs} +4 -4
- package/dist/{span-payload-primitives-_2d-pAOD.cjs.map → span-payload-primitives-D4tHWN2W.cjs.map} +1 -1
- package/dist/src/domains/chat/knowledge/knowledge-links.d.ts +32 -4
- package/dist/src/domains/chat/knowledge/pinned-knowledge-data.d.ts +2 -0
- package/dist/src/domains/chat/tools/badges/knowledge-body-range.d.ts +12 -0
- package/dist/src/domains/chat/tools/badges/knowledge-tool-badge.d.ts +5 -2
- package/dist/src/domains/chat/tools/badges/mcp-input-request-badge.d.ts +18 -0
- package/dist/src/domains/chat/tools/badges/tool-badge.d.ts +4 -1
- package/dist/src/domains/chat/tools/badges/use-deferred-input-request.d.ts +44 -0
- package/dist/src/domains/chat/tools/badges/use-mcp-task-progress.d.ts +6 -1
- package/dist/src/domains/chat/tools/connect-prompt-tool.d.ts +10 -1
- package/dist/src/domains/chat/tools/mcp-input-request-tool.d.ts +18 -0
- package/dist/src/domains/chat/tools/mcp-input-request.d.ts +40 -0
- package/dist/src/domains/chat/tools/tool-card-kind.d.ts +4 -2
- package/dist/src/domains/chat/tools/tool-card.d.ts +1 -1
- package/dist/src/domains/connect/types.d.ts +16 -0
- package/dist/src/domains/dashboards/components/dashboard-renderer.d.ts +4 -2
- package/dist/src/domains/dashboards/hooks/use-widget-views.d.ts +4 -3
- package/dist/src/domains/dashboards/index.d.ts +1 -1
- package/dist/src/domains/dashboards/kinds/scores/scores-widget.d.ts +1 -1
- package/dist/src/domains/dashboards/lib/chrome.d.ts +6 -4
- package/dist/src/domains/dashboards/widget-kind.d.ts +12 -0
- package/dist/src/domains/knowledge/components/KnowledgePageCard.d.ts +23 -0
- package/dist/src/domains/knowledge/components/KnowledgePageExplorer.d.ts +29 -0
- package/dist/src/domains/knowledge/components/KnowledgePageGraph.d.ts +27 -1
- package/dist/src/domains/knowledge/components/KnowledgePageTree.d.ts +2 -1
- package/dist/src/domains/knowledge/lib/circleText.d.ts +2 -0
- package/dist/src/domains/knowledge/lib/fitViewport.d.ts +67 -0
- package/dist/src/domains/knowledge/lib/graphShape.d.ts +131 -0
- package/dist/src/domains/knowledge/lib/linkCountsText.d.ts +5 -0
- package/dist/src/domains/knowledge/lib/pageAddress.d.ts +5 -0
- package/dist/src/domains/knowledge/lib/pageGraph.d.ts +4 -4
- package/dist/src/domains/knowledge/lib/pageRefs.d.ts +15 -0
- package/dist/src/domains/knowledge/lib/pageTree.d.ts +2 -0
- package/dist/src/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +13 -0
- package/dist/src/domains/knowledge/lib/tooltipSide.d.ts +40 -0
- package/dist/src/domains/knowledge/lib/useLeavingNodes.d.ts +14 -0
- package/dist/src/domains/knowledge/lib/useStableWhile.d.ts +5 -0
- package/dist/src/domains/knowledge/pageTypes.d.ts +6 -1
- package/dist/src/ds/components/DateTimeRangePicker/date-time-range-picker.d.ts +12 -1
- package/dist/src/ds/components/MarkdownRenderer/markdown-renderer.d.ts +8 -1
- package/dist/src/ds/components/MetricsCard/metrics-card-headline.d.ts +1 -1
- package/dist/src/ds/components/MetricsLineChart/metrics-line-chart.d.ts +8 -0
- package/dist/src/ds/components/ai/tool-call/tool-phrases.d.ts +6 -0
- package/dist/style.css +73 -2
- package/dist/{tool-approval-1qiB4hhG.cjs → tool-approval-CJvPDL7D.cjs} +4 -4
- package/dist/{tool-approval-1qiB4hhG.cjs.map → tool-approval-CJvPDL7D.cjs.map} +1 -1
- package/dist/{tool-approval-B6MFcaKV.js → tool-approval-DyN11vFA.js} +4 -4
- package/dist/{tool-approval-B6MFcaKV.js.map → tool-approval-DyN11vFA.js.map} +1 -1
- package/dist/{tool-call-Bu66PkD-.cjs → tool-call-DBn14X-3.cjs} +9 -3
- package/dist/{tool-call-Bu66PkD-.cjs.map → tool-call-DBn14X-3.cjs.map} +1 -1
- package/dist/{tool-call-Ch9-jjXU.js → tool-call-Dsj43lvJ.js} +9 -3
- package/dist/{tool-call-Ch9-jjXU.js.map → tool-call-Dsj43lvJ.js.map} +1 -1
- package/dist/{tool-card-DrqPZfPQ.cjs → tool-card-BOLXeKIp.cjs} +167 -126
- package/dist/tool-card-BOLXeKIp.cjs.map +1 -0
- package/dist/{tool-card-sO6P2Qj4.js → tool-card-HZ5bm7ue.js} +168 -127
- package/dist/tool-card-HZ5bm7ue.js.map +1 -0
- package/dist/{tool-presentation-DvCsb_kz.js → tool-presentation-CvibOP1J.js} +6 -1
- package/dist/tool-presentation-CvibOP1J.js.map +1 -0
- package/dist/{tool-presentation-CQlDEwgS.cjs → tool-presentation-D6nzVruN.cjs} +6 -1
- package/dist/tool-presentation-D6nzVruN.cjs.map +1 -0
- package/package.json +11 -11
- package/dist/MarkdownRenderer-2GOXQJEv.js.map +0 -1
- package/dist/MarkdownRenderer-CB8Z_CHc.cjs.map +0 -1
- package/dist/MetricsCard-CEB-f2sv.cjs.map +0 -1
- package/dist/MetricsCard-M8awJ2B_.js.map +0 -1
- package/dist/MetricsLineChart-BhHoduO0.js.map +0 -1
- package/dist/MetricsLineChart-CjBm4IXu.cjs.map +0 -1
- package/dist/date-time-range-picker-CTt7Od0P.cjs.map +0 -1
- package/dist/date-time-range-picker-DKh1K9Iy.js.map +0 -1
- package/dist/domains/knowledge/lib/pageLayout.cjs.js +0 -49
- package/dist/domains/knowledge/lib/pageLayout.cjs.js.map +0 -1
- package/dist/domains/knowledge/lib/pageLayout.d.ts +0 -1
- package/dist/domains/knowledge/lib/pageLayout.es.js +0 -48
- package/dist/domains/knowledge/lib/pageLayout.es.js.map +0 -1
- package/dist/src/domains/knowledge/lib/pageLayout.d.ts +0 -24
- package/dist/tool-card-DrqPZfPQ.cjs.map +0 -1
- package/dist/tool-card-sO6P2Qj4.js.map +0 -1
- package/dist/tool-presentation-CQlDEwgS.cjs.map +0 -1
- package/dist/tool-presentation-DvCsb_kz.js.map +0 -1
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { t as Txt } from "../../../Txt-BM6TVV_c.js";
|
|
2
|
+
import { linkCountsText } from "../lib/linkCountsText.es.js";
|
|
3
|
+
import { KnowledgePageCard } from "./KnowledgePageCard.es.js";
|
|
4
|
+
import { childCountLabel } from "../lib/pageTree.es.js";
|
|
5
|
+
import { branchColors, crowdScale, graphShape, isChildPlaceholder, isRestCircle, isScopeGroup, radialLayout } from "../lib/graphShape.es.js";
|
|
6
|
+
import { fitWords } from "../lib/circleText.es.js";
|
|
7
|
+
import { prefersMotion, useLeavingNodes } from "../lib/useLeavingNodes.es.js";
|
|
8
|
+
import { INITIAL_SETTLE_MS, fitAllViewport, fitDuration, fitViewport, nudgeAxis } from "../lib/fitViewport.es.js";
|
|
9
|
+
import { runLayout } from "../lib/layout.es.js";
|
|
10
|
+
import { pagePath, pageRef } from "../lib/pageAddress.es.js";
|
|
2
11
|
import { grantGraph, pageGraphEdges, pageNeighbourIds, toPageFlow } from "../lib/pageGraph.es.js";
|
|
3
|
-
import {
|
|
4
|
-
import { Fragment, memo, useCallback, useEffect, useMemo, useRef } from "react";
|
|
12
|
+
import { chooseTooltipSide } from "../lib/tooltipSide.es.js";
|
|
13
|
+
import { Fragment, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
14
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import { Maximize, Pin } from "lucide-react";
|
|
7
|
-
import { Background, BackgroundVariant, BaseEdge, ControlButton, Controls, Handle, MarkerType, Position, ReactFlow, ReactFlowProvider,
|
|
15
|
+
import { ArrowUpToLine, Layers, Maximize, Pin } from "lucide-react";
|
|
16
|
+
import { Background, BackgroundVariant, BaseEdge, ControlButton, Controls, Handle, MarkerType, Position, ReactFlow, ReactFlowProvider, useReactFlow, useStore } from "@xyflow/react";
|
|
8
17
|
import "@xyflow/react/dist/style.css";
|
|
9
18
|
import '../../../KnowledgePageGraph.css';// src/domains/knowledge/components/KnowledgePageGraph.tsx
|
|
10
19
|
var SCOPE_STYLE = {
|
|
@@ -12,12 +21,29 @@ var SCOPE_STYLE = {
|
|
|
12
21
|
background: "color-mix(in oklab, var(--chart-blue) 16%, var(--card))"
|
|
13
22
|
};
|
|
14
23
|
var PAGE_STYLE = { "--knowledge-color": "var(--border-strong)" };
|
|
24
|
+
/** A farther page drawn as a named circle: the legend's "Page in another branch" dot grown, same solid grey fill, name in the page background colour to read on it. */
|
|
25
|
+
var FAR_FILL = "var(--muted-foreground)";
|
|
26
|
+
var FAR_STYLE = {
|
|
27
|
+
"--knowledge-color": FAR_FILL,
|
|
28
|
+
background: FAR_FILL
|
|
29
|
+
};
|
|
15
30
|
var PARENT_EDGE_STYLE = {
|
|
16
31
|
stroke: "var(--foreground)",
|
|
17
32
|
strokeOpacity: .45,
|
|
18
33
|
strokeDasharray: "4 4",
|
|
19
34
|
strokeWidth: 1.25
|
|
20
35
|
};
|
|
36
|
+
var UP_EDGE_COLOR = "var(--chart-cyan)";
|
|
37
|
+
var UP_EDGE_STYLE = {
|
|
38
|
+
stroke: UP_EDGE_COLOR,
|
|
39
|
+
strokeWidth: 2.25
|
|
40
|
+
};
|
|
41
|
+
var UP_ARROW = {
|
|
42
|
+
type: MarkerType.ArrowClosed,
|
|
43
|
+
color: UP_EDGE_COLOR,
|
|
44
|
+
width: 14,
|
|
45
|
+
height: 14
|
|
46
|
+
};
|
|
21
47
|
var MENTION_EDGE_COLOR = "var(--chart-blue)";
|
|
22
48
|
var PARENT_ARROW_COLOR = "var(--muted-foreground)";
|
|
23
49
|
var PARENT_ARROW = {
|
|
@@ -39,6 +65,38 @@ var GRANT_ARROW = {
|
|
|
39
65
|
width: 13,
|
|
40
66
|
height: 13
|
|
41
67
|
};
|
|
68
|
+
var LINK_EDGE_COLOR = "var(--chart-green)";
|
|
69
|
+
var LINK_EDGE_STYLE = {
|
|
70
|
+
stroke: LINK_EDGE_COLOR,
|
|
71
|
+
strokeWidth: 1.25
|
|
72
|
+
};
|
|
73
|
+
var LINK_ARROW = {
|
|
74
|
+
type: MarkerType.ArrowClosed,
|
|
75
|
+
color: LINK_EDGE_COLOR,
|
|
76
|
+
width: 12,
|
|
77
|
+
height: 12
|
|
78
|
+
};
|
|
79
|
+
var DIRECTION_EDGE_STYLE = {
|
|
80
|
+
out: { stroke: LINK_EDGE_COLOR },
|
|
81
|
+
in: {
|
|
82
|
+
stroke: "var(--chart-orange)",
|
|
83
|
+
strokeDasharray: "6 3"
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var DIRECTION_ARROW = {
|
|
87
|
+
out: LINK_ARROW,
|
|
88
|
+
in: {
|
|
89
|
+
type: MarkerType.ArrowClosed,
|
|
90
|
+
color: "var(--chart-orange)",
|
|
91
|
+
width: 12,
|
|
92
|
+
height: 12
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
var DOT_PARENT_EDGE_STYLE = {
|
|
96
|
+
stroke: "var(--foreground)",
|
|
97
|
+
strokeOpacity: .2,
|
|
98
|
+
strokeWidth: 1
|
|
99
|
+
};
|
|
42
100
|
var PLACEHOLDER_STYLE = {
|
|
43
101
|
background: "var(--card)",
|
|
44
102
|
borderColor: "var(--chart-purple)",
|
|
@@ -61,44 +119,291 @@ function pinBadgeStyle(size) {
|
|
|
61
119
|
}
|
|
62
120
|
};
|
|
63
121
|
}
|
|
64
|
-
/**
|
|
122
|
+
/** How long a focus change loads before the graph says so. */
|
|
123
|
+
var LOADING_HINT_DELAY_MS = 150;
|
|
124
|
+
/** How long it holds the old layout for pages that never arrive before drawing what it has. */
|
|
125
|
+
var LOADING_RELEASE_MS = 4e3;
|
|
126
|
+
/** Most a tooltip is enlarged to offset a zoomed-out graph. */
|
|
127
|
+
var TOOLTIP_MAX_SCALE = 3;
|
|
128
|
+
/** Screen-space box of an element. */
|
|
129
|
+
function boxOf(el) {
|
|
130
|
+
const { left, top, right, bottom } = el.getBoundingClientRect();
|
|
131
|
+
return {
|
|
132
|
+
left,
|
|
133
|
+
top,
|
|
134
|
+
right,
|
|
135
|
+
bottom
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/** The highlighted lines of the graph as screen-space segments, where the browser can measure them. */
|
|
139
|
+
function drawnLines(root) {
|
|
140
|
+
const lines = [];
|
|
141
|
+
for (const path of root.querySelectorAll(".react-flow__edge-path")) {
|
|
142
|
+
if (typeof path.getTotalLength !== "function" || typeof path.getScreenCTM !== "function") continue;
|
|
143
|
+
const matrix = path.getScreenCTM();
|
|
144
|
+
if (!matrix) continue;
|
|
145
|
+
const length = path.getTotalLength();
|
|
146
|
+
const start = path.getPointAtLength(0);
|
|
147
|
+
const end = path.getPointAtLength(length);
|
|
148
|
+
lines.push({
|
|
149
|
+
from: {
|
|
150
|
+
x: matrix.a * start.x + matrix.c * start.y + matrix.e,
|
|
151
|
+
y: matrix.b * start.x + matrix.d * start.y + matrix.f
|
|
152
|
+
},
|
|
153
|
+
to: {
|
|
154
|
+
x: matrix.a * end.x + matrix.c * end.y + matrix.e,
|
|
155
|
+
y: matrix.b * end.x + matrix.d * end.y + matrix.f
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return lines;
|
|
160
|
+
}
|
|
161
|
+
/** Where a tooltip sits against its dot, and which way it grows from it. */
|
|
162
|
+
var TOOLTIP_PLACEMENT = {
|
|
163
|
+
top: {
|
|
164
|
+
tip: "bottom-full left-1/2 mb-2",
|
|
165
|
+
transform: "translateX(-50%)",
|
|
166
|
+
origin: "bottom center",
|
|
167
|
+
tail: "top-full left-1/2 -translate-x-1/2 -translate-y-1/2 border-r border-b"
|
|
168
|
+
},
|
|
169
|
+
bottom: {
|
|
170
|
+
tip: "top-full left-1/2 mt-2",
|
|
171
|
+
transform: "translateX(-50%)",
|
|
172
|
+
origin: "top center",
|
|
173
|
+
tail: "bottom-full left-1/2 -translate-x-1/2 translate-y-1/2 border-l border-t"
|
|
174
|
+
},
|
|
175
|
+
right: {
|
|
176
|
+
tip: "left-full top-1/2 ml-2",
|
|
177
|
+
transform: "translateY(-50%)",
|
|
178
|
+
origin: "center left",
|
|
179
|
+
tail: "right-full top-1/2 translate-x-1/2 -translate-y-1/2 border-l border-b"
|
|
180
|
+
},
|
|
181
|
+
left: {
|
|
182
|
+
tip: "right-full top-1/2 mr-2",
|
|
183
|
+
transform: "translateY(-50%)",
|
|
184
|
+
origin: "center right",
|
|
185
|
+
tail: "left-full top-1/2 -translate-x-1/2 -translate-y-1/2 border-r border-t"
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
/** The mark on a circle for a page that sits above others: layers for a scope, an up arrow for an ancestor page. */
|
|
189
|
+
function LevelIcon({ level }) {
|
|
190
|
+
return /* @__PURE__ */ jsx(level === "scope" ? Layers : ArrowUpToLine, {
|
|
191
|
+
"aria-hidden": true,
|
|
192
|
+
"data-testid": `knowledge-level-icon-${level}`,
|
|
193
|
+
className: "mr-1 inline-block size-3 align-text-bottom"
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
/** A page far from the focus: a small coloured dot that names itself on hover. */
|
|
197
|
+
function DotNode({ data }) {
|
|
198
|
+
const { page, size, color, path, ref, links, notShown } = data;
|
|
199
|
+
const [hover, setHover] = useState(false);
|
|
200
|
+
const dotRef = useRef(null);
|
|
201
|
+
const tipRef = useRef(null);
|
|
202
|
+
const [side, setSide] = useState("top");
|
|
203
|
+
const zoom = useStore((state) => state.transform[2]);
|
|
204
|
+
const tipScale = Math.min(Math.max(1 / zoom, 1), TOOLTIP_MAX_SCALE);
|
|
205
|
+
const standIn = isChildPlaceholder(page);
|
|
206
|
+
const group = isScopeGroup(page);
|
|
207
|
+
const hint = standIn ? "Hover or click to load them" : group ? "Click to show them" : null;
|
|
208
|
+
const children = !hint && page.childCount ? `${childCountLabel(page)} ${page.childCount === 1 ? "child" : "children"}` : null;
|
|
209
|
+
const kind = page.isScope ? page.displayLabel ?? "Scope" : "Page";
|
|
210
|
+
const linkText = links && (links.in > 0 || links.out > 0) ? linkCountsText(links, notShown) : null;
|
|
211
|
+
const label = [
|
|
212
|
+
page.name,
|
|
213
|
+
hint ?? path,
|
|
214
|
+
children,
|
|
215
|
+
linkText
|
|
216
|
+
].filter(Boolean).join(" · ");
|
|
217
|
+
useLayoutEffect(() => {
|
|
218
|
+
const dot = dotRef.current;
|
|
219
|
+
const tip = tipRef.current;
|
|
220
|
+
const graph = dot?.closest(".knowledge-graph");
|
|
221
|
+
if (!hover || !dot || !tip || !graph) return;
|
|
222
|
+
const dotBox = boxOf(dot);
|
|
223
|
+
const tipBox = boxOf(tip);
|
|
224
|
+
const scaledWidth = tip.offsetWidth * tipScale;
|
|
225
|
+
const scaledHeight = tip.offsetHeight * tipScale;
|
|
226
|
+
if (!scaledWidth || !scaledHeight) return;
|
|
227
|
+
const obstacles = [...graph.querySelectorAll("[data-testid=\"knowledge-page-node\"], [data-testid=\"knowledge-page-dot\"]"), ...(graph.parentElement ?? graph).querySelectorAll("[aria-label=\"Legend\"], [data-testid=\"knowledge-graph-back\"], .react-flow__controls")].map(boxOf).filter((box) => box.right > box.left && !(box.left === tipBox.left && box.top === tipBox.top) && !(box.left === dotBox.left && box.top === dotBox.top));
|
|
228
|
+
setSide(chooseTooltipSide({
|
|
229
|
+
dot: dotBox,
|
|
230
|
+
tip: {
|
|
231
|
+
width: scaledWidth,
|
|
232
|
+
height: scaledHeight
|
|
233
|
+
},
|
|
234
|
+
gap: 8,
|
|
235
|
+
bounds: boxOf(graph),
|
|
236
|
+
obstacles,
|
|
237
|
+
lines: drawnLines(graph)
|
|
238
|
+
}));
|
|
239
|
+
}, [hover, tipScale]);
|
|
240
|
+
const placement = TOOLTIP_PLACEMENT[side];
|
|
241
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
242
|
+
ref: dotRef,
|
|
243
|
+
"data-testid": "knowledge-page-dot",
|
|
244
|
+
"data-page-id": page.id,
|
|
245
|
+
"data-page-type": standIn ? "stand-in" : group ? "group" : page.isScope ? "scope" : "page",
|
|
246
|
+
"aria-label": label,
|
|
247
|
+
className: "relative cursor-pointer transition-opacity",
|
|
248
|
+
style: {
|
|
249
|
+
width: size,
|
|
250
|
+
height: size,
|
|
251
|
+
opacity: standIn ? .5 : void 0
|
|
252
|
+
},
|
|
253
|
+
onPointerEnter: () => setHover(true),
|
|
254
|
+
onPointerLeave: () => setHover(false),
|
|
255
|
+
children: [
|
|
256
|
+
/* @__PURE__ */ jsx("span", {
|
|
257
|
+
"aria-hidden": true,
|
|
258
|
+
"data-testid": "knowledge-dot-hit-area",
|
|
259
|
+
className: "absolute rounded-full",
|
|
260
|
+
style: { inset: -8 }
|
|
261
|
+
}),
|
|
262
|
+
/* @__PURE__ */ jsx("div", {
|
|
263
|
+
className: "size-full rounded-full border",
|
|
264
|
+
style: {
|
|
265
|
+
background: standIn ? "transparent" : color ?? "var(--muted-foreground)",
|
|
266
|
+
borderColor: color ?? "var(--muted-foreground)",
|
|
267
|
+
borderStyle: standIn ? "dashed" : "solid"
|
|
268
|
+
},
|
|
269
|
+
children: data.showCount && !standIn && !group && links && links.in + links.out > 0 ? /* @__PURE__ */ jsx(Txt, {
|
|
270
|
+
as: "span",
|
|
271
|
+
variant: "meta",
|
|
272
|
+
"data-testid": "knowledge-dot-count",
|
|
273
|
+
className: "flex size-full items-center justify-center",
|
|
274
|
+
style: { color: "var(--background)" },
|
|
275
|
+
children: links.in + links.out
|
|
276
|
+
}) : null
|
|
277
|
+
}),
|
|
278
|
+
hover ? /* @__PURE__ */ jsxs("div", {
|
|
279
|
+
role: "tooltip",
|
|
280
|
+
ref: tipRef,
|
|
281
|
+
"data-side": side,
|
|
282
|
+
className: `pointer-events-none absolute ${placement.tip} flex w-max max-w-72 flex-col rounded-md border border-border bg-card px-2 py-1 shadow-overlay`,
|
|
283
|
+
style: {
|
|
284
|
+
transform: `${placement.transform} scale(${tipScale})`,
|
|
285
|
+
transformOrigin: placement.origin
|
|
286
|
+
},
|
|
287
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
288
|
+
"data-testid": "knowledge-tooltip-tail",
|
|
289
|
+
"aria-hidden": true,
|
|
290
|
+
className: `absolute size-2 rotate-45 border-border bg-card ${placement.tail}`
|
|
291
|
+
}), hint ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Txt, {
|
|
292
|
+
as: "span",
|
|
293
|
+
variant: "label",
|
|
294
|
+
tone: "ink",
|
|
295
|
+
children: page.name
|
|
296
|
+
}), /* @__PURE__ */ jsx(Txt, {
|
|
297
|
+
as: "span",
|
|
298
|
+
variant: "meta",
|
|
299
|
+
tone: "muted",
|
|
300
|
+
children: group ? `${path} · ${hint}` : hint
|
|
301
|
+
})] }) : /* @__PURE__ */ jsx(KnowledgePageCard, {
|
|
302
|
+
name: page.name,
|
|
303
|
+
kind,
|
|
304
|
+
pageRef: ref,
|
|
305
|
+
path,
|
|
306
|
+
childCount: page.childCount ? childCountLabel(page) : void 0,
|
|
307
|
+
links,
|
|
308
|
+
notShown
|
|
309
|
+
})]
|
|
310
|
+
}) : null,
|
|
311
|
+
/* @__PURE__ */ jsx(Handle, {
|
|
312
|
+
type: "target",
|
|
313
|
+
position: Position.Top,
|
|
314
|
+
className: "!invisible"
|
|
315
|
+
}),
|
|
316
|
+
/* @__PURE__ */ jsx(Handle, {
|
|
317
|
+
type: "source",
|
|
318
|
+
position: Position.Bottom,
|
|
319
|
+
className: "!invisible"
|
|
320
|
+
})
|
|
321
|
+
]
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
/** Below this a circle uses the small type and two lines of name. */
|
|
325
|
+
var COMPACT_CIRCLE_SIZE = 96;
|
|
326
|
+
/** The share of a circle's width its text may use; a circle is narrower toward the top and bottom. */
|
|
327
|
+
var CIRCLE_TEXT_SHARE = .74;
|
|
328
|
+
/** A scope or page: its kind on top, its name below, both inside the circle; far pages draw as dots. */
|
|
65
329
|
function PageNodeComponent({ data }) {
|
|
66
|
-
|
|
330
|
+
if (data.form === "dot") return /* @__PURE__ */ jsx(DotNode, { data });
|
|
331
|
+
const { page, size, selected, pinned, badge } = data;
|
|
332
|
+
const group = isScopeGroup(page);
|
|
67
333
|
const kind = page.isScope ? page.displayLabel ?? "Scope" : "Page";
|
|
68
334
|
const placeholder = isPlaceholder(page);
|
|
335
|
+
const rest = isRestCircle(page);
|
|
336
|
+
const compact = size < COMPACT_CIRCLE_SIZE;
|
|
337
|
+
const fit = Math.max(4, Math.floor(size * CIRCLE_TEXT_SHARE / (compact ? 6.5 : 7.5)));
|
|
69
338
|
return /* @__PURE__ */ jsxs("div", {
|
|
70
339
|
"data-testid": "knowledge-page-node",
|
|
71
340
|
"data-page-id": page.id,
|
|
72
|
-
"data-page-type": placeholder ? "placeholder" : page.isScope ? "scope" : "page",
|
|
341
|
+
"data-page-type": placeholder ? "placeholder" : rest ? "rest" : group ? "group" : page.isScope ? "scope" : "page",
|
|
73
342
|
className: `relative transition-opacity ${placeholder ? "cursor-default" : "cursor-pointer"}`,
|
|
74
343
|
style: {
|
|
75
344
|
width: size,
|
|
76
|
-
height: size
|
|
77
|
-
opacity: dimmed ? .35 : 1
|
|
345
|
+
height: size
|
|
78
346
|
},
|
|
79
|
-
title: placeholder ? `${kind} · ${page.address} · nothing written to it yet` : page.isScope && page.address ? `${kind} · ${page.address}` : page.name,
|
|
347
|
+
title: placeholder ? `${kind} · ${page.address} · nothing written to it yet` : rest ? `Show ${Math.min(12, page.childCount ?? 12)} more of ${page.childCount ?? "the rest"}` : group ? `${page.name}: click to show them` : page.isScope && page.address ? `${kind} · ${page.address}` : data.links && data.links.in + data.links.out > 0 ? `${page.name} · ${linkCountsText(data.links, data.notShown)}` : page.name,
|
|
80
348
|
children: [
|
|
81
349
|
/* @__PURE__ */ jsxs("div", {
|
|
82
|
-
className:
|
|
350
|
+
className: `knowledge-circle flex size-full flex-col items-center justify-center gap-0.5 overflow-hidden rounded-full border-2 text-center shadow-raised ${rest ? "hover:border-foreground" : ""}`,
|
|
83
351
|
"data-selected": selected || void 0,
|
|
84
|
-
|
|
85
|
-
|
|
352
|
+
"data-far": data.far || void 0,
|
|
353
|
+
style: {
|
|
354
|
+
...placeholder || rest ? PLACEHOLDER_STYLE : data.far ? FAR_STYLE : page.isScope ? SCOPE_STYLE : PAGE_STYLE,
|
|
355
|
+
paddingInline: size * (.26 / 2)
|
|
356
|
+
},
|
|
357
|
+
children: [data.far ? null : /* @__PURE__ */ jsxs(Txt, {
|
|
86
358
|
as: "span",
|
|
87
359
|
variant: "meta",
|
|
88
360
|
tone: page.isScope ? void 0 : "muted",
|
|
89
|
-
className: "pointer-events-none
|
|
361
|
+
className: "pointer-events-none inline-flex max-w-full items-center justify-center gap-1 whitespace-nowrap uppercase",
|
|
90
362
|
style: page.isScope ? { color: "var(--chart-blue)" } : void 0,
|
|
91
363
|
"data-testid": page.isScope ? "knowledge-scope-caption" : "knowledge-page-caption",
|
|
92
|
-
children:
|
|
364
|
+
children: [data.level ? /* @__PURE__ */ jsx(LevelIcon, { level: data.level }) : null, /* @__PURE__ */ jsx("span", {
|
|
365
|
+
className: "truncate",
|
|
366
|
+
children: rest ? "More" : data.isParent ? "Parent" : kind
|
|
367
|
+
})]
|
|
93
368
|
}), /* @__PURE__ */ jsx(Txt, {
|
|
94
369
|
as: "span",
|
|
95
|
-
variant: "label",
|
|
370
|
+
variant: compact ? "meta" : "label",
|
|
96
371
|
tone: "ink",
|
|
97
|
-
className:
|
|
98
|
-
|
|
372
|
+
className: `pointer-events-none max-w-full overflow-hidden [overflow-wrap:normal] ${compact ? "line-clamp-2" : "line-clamp-3"}`,
|
|
373
|
+
style: data.far ? { color: "var(--background)" } : void 0,
|
|
374
|
+
"data-testid": "knowledge-circle-name",
|
|
375
|
+
children: page.isScope && page.address && !group ? /* @__PURE__ */ jsx(BreakAtColons, { text: fitWords(page.address, fit) }) : fitWords(page.name, fit)
|
|
99
376
|
})]
|
|
100
377
|
}),
|
|
101
378
|
pinned ? /* @__PURE__ */ jsx(PinBadge, { size }) : null,
|
|
379
|
+
data.hiddenLinks && (data.hiddenLinks.in > 0 || data.hiddenLinks.out > 0) ? /* @__PURE__ */ jsxs("span", {
|
|
380
|
+
"data-testid": "knowledge-hidden-links",
|
|
381
|
+
title: linkCountsText(data.hiddenLinks),
|
|
382
|
+
"aria-label": linkCountsText(data.hiddenLinks),
|
|
383
|
+
className: "absolute bottom-full left-1/2 -mb-1 flex -translate-x-1/2 gap-1 rounded-full border border-border bg-card px-1.5 shadow-raised",
|
|
384
|
+
children: [data.hiddenLinks.in > 0 ? /* @__PURE__ */ jsxs(Txt, {
|
|
385
|
+
as: "span",
|
|
386
|
+
variant: "meta",
|
|
387
|
+
style: { color: "var(--chart-orange)" },
|
|
388
|
+
children: ["→", data.hiddenLinks.in]
|
|
389
|
+
}) : null, data.hiddenLinks.out > 0 ? /* @__PURE__ */ jsxs(Txt, {
|
|
390
|
+
as: "span",
|
|
391
|
+
variant: "meta",
|
|
392
|
+
style: { color: LINK_EDGE_COLOR },
|
|
393
|
+
children: [data.hiddenLinks.out, "→"]
|
|
394
|
+
}) : null]
|
|
395
|
+
}) : null,
|
|
396
|
+
badge ? /* @__PURE__ */ jsx("span", {
|
|
397
|
+
"data-testid": "knowledge-child-count-badge",
|
|
398
|
+
"aria-label": `${badge} children, not all drawn`,
|
|
399
|
+
className: "absolute top-full left-1/2 -mt-1 -translate-x-1/2 rounded-full border border-border bg-card px-1.5 shadow-raised",
|
|
400
|
+
children: /* @__PURE__ */ jsx(Txt, {
|
|
401
|
+
as: "span",
|
|
402
|
+
variant: "meta",
|
|
403
|
+
tone: "ink",
|
|
404
|
+
children: badge
|
|
405
|
+
})
|
|
406
|
+
}) : null,
|
|
102
407
|
/* @__PURE__ */ jsx(Handle, {
|
|
103
408
|
type: "target",
|
|
104
409
|
position: Position.Top,
|
|
@@ -155,10 +460,7 @@ function RimEdgeComponent({ id, data, style, markerEnd }) {
|
|
|
155
460
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(BaseEdge, {
|
|
156
461
|
id,
|
|
157
462
|
path,
|
|
158
|
-
style
|
|
159
|
-
...style,
|
|
160
|
-
opacity: data.dimmed ? .2 : 1
|
|
161
|
-
},
|
|
463
|
+
style,
|
|
162
464
|
markerEnd,
|
|
163
465
|
interactionWidth: mention ? 20 : 0
|
|
164
466
|
}), data.kind === "grant" && data.role ? /* @__PURE__ */ jsx("path", {
|
|
@@ -172,7 +474,7 @@ function RimEdgeComponent({ id, data, style, markerEnd }) {
|
|
|
172
474
|
children: /* @__PURE__ */ jsx("title", { children: `Grants ${data.role}` })
|
|
173
475
|
}) : null] });
|
|
174
476
|
}
|
|
175
|
-
var edgeTypes = { rim: RimEdgeComponent };
|
|
477
|
+
var edgeTypes = { rim: memo(RimEdgeComponent) };
|
|
176
478
|
var nodeTypes = { page: memo(PageNodeComponent) };
|
|
177
479
|
/** The box around laid-out circles, in graph coordinates; `null` when there are none. */
|
|
178
480
|
function graphBounds(nodes) {
|
|
@@ -196,7 +498,7 @@ function graphBounds(nodes) {
|
|
|
196
498
|
}
|
|
197
499
|
var LEGEND_SWATCH = "knowledge-circle inline-block size-3 shrink-0 rounded-full border-2";
|
|
198
500
|
/** What the circles, lines and badge mean. */
|
|
199
|
-
function GraphLegend({
|
|
501
|
+
function GraphLegend({ drawn, counts, dots, linkEnds, focused, levels, branches }) {
|
|
200
502
|
return /* @__PURE__ */ jsxs("ul", {
|
|
201
503
|
"aria-label": "Legend",
|
|
202
504
|
className: "pointer-events-none absolute top-2 left-2 z-10 flex flex-col gap-1 rounded-md border border-border bg-card/90 px-2 py-1.5 shadow-raised",
|
|
@@ -214,6 +516,32 @@ function GraphLegend({ grants }) {
|
|
|
214
516
|
children: "Scope"
|
|
215
517
|
})]
|
|
216
518
|
}),
|
|
519
|
+
levels.includes("scope") ? /* @__PURE__ */ jsxs("li", {
|
|
520
|
+
className: "flex items-center gap-2",
|
|
521
|
+
"data-testid": "knowledge-legend-level-scope",
|
|
522
|
+
children: [/* @__PURE__ */ jsx(Layers, {
|
|
523
|
+
"aria-hidden": true,
|
|
524
|
+
className: "size-3 shrink-0 text-muted-foreground"
|
|
525
|
+
}), /* @__PURE__ */ jsx(Txt, {
|
|
526
|
+
as: "span",
|
|
527
|
+
variant: "meta",
|
|
528
|
+
tone: "muted",
|
|
529
|
+
children: "Scope, above its pages"
|
|
530
|
+
})]
|
|
531
|
+
}) : null,
|
|
532
|
+
levels.includes("ancestor") ? /* @__PURE__ */ jsxs("li", {
|
|
533
|
+
className: "flex items-center gap-2",
|
|
534
|
+
"data-testid": "knowledge-legend-level-ancestor",
|
|
535
|
+
children: [/* @__PURE__ */ jsx(ArrowUpToLine, {
|
|
536
|
+
"aria-hidden": true,
|
|
537
|
+
className: "size-3 shrink-0 text-muted-foreground"
|
|
538
|
+
}), /* @__PURE__ */ jsx(Txt, {
|
|
539
|
+
as: "span",
|
|
540
|
+
variant: "meta",
|
|
541
|
+
tone: "muted",
|
|
542
|
+
children: "Page above the focus"
|
|
543
|
+
})]
|
|
544
|
+
}) : null,
|
|
217
545
|
/* @__PURE__ */ jsxs("li", {
|
|
218
546
|
className: "flex items-center gap-2",
|
|
219
547
|
children: [/* @__PURE__ */ jsx("span", {
|
|
@@ -227,8 +555,122 @@ function GraphLegend({ grants }) {
|
|
|
227
555
|
children: "Page"
|
|
228
556
|
})]
|
|
229
557
|
}),
|
|
230
|
-
/* @__PURE__ */ jsxs("li", {
|
|
558
|
+
focused ? /* @__PURE__ */ jsxs("li", {
|
|
559
|
+
className: "flex items-center gap-2",
|
|
560
|
+
"data-testid": "knowledge-legend-focused",
|
|
561
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
562
|
+
className: LEGEND_SWATCH,
|
|
563
|
+
style: {
|
|
564
|
+
...PAGE_STYLE,
|
|
565
|
+
outline: "2px solid var(--knowledge-color)",
|
|
566
|
+
outlineOffset: 2,
|
|
567
|
+
borderWidth: 3
|
|
568
|
+
},
|
|
569
|
+
"aria-hidden": true
|
|
570
|
+
}), /* @__PURE__ */ jsx(Txt, {
|
|
571
|
+
as: "span",
|
|
572
|
+
variant: "meta",
|
|
573
|
+
tone: "muted",
|
|
574
|
+
children: "Focused page"
|
|
575
|
+
})]
|
|
576
|
+
}) : null,
|
|
577
|
+
dots || linkEnds ? /* @__PURE__ */ jsxs("li", {
|
|
578
|
+
className: "flex items-center gap-2",
|
|
579
|
+
"data-testid": "knowledge-legend-dot",
|
|
580
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
581
|
+
className: "inline-block size-2 shrink-0 rounded-full bg-muted-foreground",
|
|
582
|
+
"aria-hidden": true
|
|
583
|
+
}), /* @__PURE__ */ jsx(Txt, {
|
|
584
|
+
as: "span",
|
|
585
|
+
variant: "meta",
|
|
586
|
+
tone: "muted",
|
|
587
|
+
children: "Page in another branch"
|
|
588
|
+
})]
|
|
589
|
+
}) : null,
|
|
590
|
+
branches.slice(0, LEGEND_BRANCH_CAP).map((branch) => /* @__PURE__ */ jsxs("li", {
|
|
591
|
+
className: "flex items-center gap-2 pl-0.5",
|
|
592
|
+
"data-testid": "knowledge-legend-branch",
|
|
593
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
594
|
+
className: "inline-block size-2 shrink-0 rounded-full",
|
|
595
|
+
style: { background: branch.color },
|
|
596
|
+
"aria-hidden": true
|
|
597
|
+
}), /* @__PURE__ */ jsx(Txt, {
|
|
598
|
+
as: "span",
|
|
599
|
+
variant: "meta",
|
|
600
|
+
tone: "muted",
|
|
601
|
+
className: "max-w-40 truncate",
|
|
602
|
+
title: branch.name,
|
|
603
|
+
children: branches.length > 1 ? `Under ${branch.name}` : branch.scope ? "Under parent scope" : "Under parent page"
|
|
604
|
+
})]
|
|
605
|
+
}, branch.id)),
|
|
606
|
+
branches.length > LEGEND_BRANCH_CAP ? /* @__PURE__ */ jsx("li", {
|
|
607
|
+
className: "pl-0.5",
|
|
608
|
+
children: /* @__PURE__ */ jsxs(Txt, {
|
|
609
|
+
as: "span",
|
|
610
|
+
variant: "meta",
|
|
611
|
+
tone: "muted",
|
|
612
|
+
children: [
|
|
613
|
+
"+",
|
|
614
|
+
branches.length - LEGEND_BRANCH_CAP,
|
|
615
|
+
" more branches"
|
|
616
|
+
]
|
|
617
|
+
})
|
|
618
|
+
}) : null,
|
|
619
|
+
drawn.has("out") || drawn.has("in") ? /* @__PURE__ */ jsxs(Fragment$1, { children: [drawn.has("out") ? /* @__PURE__ */ jsxs("li", {
|
|
231
620
|
className: "flex items-center gap-2",
|
|
621
|
+
"data-testid": "knowledge-legend-out",
|
|
622
|
+
children: [/* @__PURE__ */ jsxs("svg", {
|
|
623
|
+
width: "16",
|
|
624
|
+
height: "8",
|
|
625
|
+
"aria-hidden": true,
|
|
626
|
+
className: "shrink-0",
|
|
627
|
+
children: [/* @__PURE__ */ jsx("line", {
|
|
628
|
+
x1: "0",
|
|
629
|
+
y1: "4",
|
|
630
|
+
x2: "12",
|
|
631
|
+
y2: "4",
|
|
632
|
+
stroke: LINK_EDGE_COLOR,
|
|
633
|
+
strokeWidth: "1.5"
|
|
634
|
+
}), /* @__PURE__ */ jsx("polygon", {
|
|
635
|
+
points: "11,1 16,4 11,7",
|
|
636
|
+
fill: LINK_EDGE_COLOR
|
|
637
|
+
})]
|
|
638
|
+
}), /* @__PURE__ */ jsx(Txt, {
|
|
639
|
+
as: "span",
|
|
640
|
+
variant: "meta",
|
|
641
|
+
tone: "muted",
|
|
642
|
+
children: "Links out of the selected page"
|
|
643
|
+
})]
|
|
644
|
+
}) : null, drawn.has("in") ? /* @__PURE__ */ jsxs("li", {
|
|
645
|
+
className: "flex items-center gap-2",
|
|
646
|
+
"data-testid": "knowledge-legend-in",
|
|
647
|
+
children: [/* @__PURE__ */ jsxs("svg", {
|
|
648
|
+
width: "16",
|
|
649
|
+
height: "8",
|
|
650
|
+
"aria-hidden": true,
|
|
651
|
+
className: "shrink-0",
|
|
652
|
+
children: [/* @__PURE__ */ jsx("line", {
|
|
653
|
+
x1: "0",
|
|
654
|
+
y1: "4",
|
|
655
|
+
x2: "12",
|
|
656
|
+
y2: "4",
|
|
657
|
+
stroke: "var(--chart-orange)",
|
|
658
|
+
strokeWidth: "1.5",
|
|
659
|
+
strokeDasharray: "3 2"
|
|
660
|
+
}), /* @__PURE__ */ jsx("polygon", {
|
|
661
|
+
points: "11,1 16,4 11,7",
|
|
662
|
+
fill: "var(--chart-orange)"
|
|
663
|
+
})]
|
|
664
|
+
}), /* @__PURE__ */ jsx(Txt, {
|
|
665
|
+
as: "span",
|
|
666
|
+
variant: "meta",
|
|
667
|
+
tone: "muted",
|
|
668
|
+
children: "Links into it"
|
|
669
|
+
})]
|
|
670
|
+
}) : null] }) : null,
|
|
671
|
+
drawn.has("mention") ? /* @__PURE__ */ jsxs("li", {
|
|
672
|
+
className: "flex items-center gap-2",
|
|
673
|
+
"data-testid": "knowledge-legend-mention",
|
|
232
674
|
children: [/* @__PURE__ */ jsx("svg", {
|
|
233
675
|
width: "12",
|
|
234
676
|
height: "4",
|
|
@@ -248,8 +690,81 @@ function GraphLegend({ grants }) {
|
|
|
248
690
|
tone: "muted",
|
|
249
691
|
children: "Mentioned in notes"
|
|
250
692
|
})]
|
|
251
|
-
}),
|
|
252
|
-
/* @__PURE__ */ jsxs("li", {
|
|
693
|
+
}) : null,
|
|
694
|
+
drawn.has("link") ? /* @__PURE__ */ jsxs("li", {
|
|
695
|
+
className: "flex items-center gap-2",
|
|
696
|
+
children: [/* @__PURE__ */ jsxs("svg", {
|
|
697
|
+
width: "16",
|
|
698
|
+
height: "8",
|
|
699
|
+
"aria-hidden": true,
|
|
700
|
+
className: "shrink-0",
|
|
701
|
+
"data-testid": "knowledge-legend-link",
|
|
702
|
+
children: [/* @__PURE__ */ jsx("line", {
|
|
703
|
+
x1: "0",
|
|
704
|
+
y1: "4",
|
|
705
|
+
x2: "12",
|
|
706
|
+
y2: "4",
|
|
707
|
+
...LINK_EDGE_STYLE
|
|
708
|
+
}), /* @__PURE__ */ jsx("polygon", {
|
|
709
|
+
points: "11,1 16,4 11,7",
|
|
710
|
+
fill: LINK_EDGE_COLOR
|
|
711
|
+
})]
|
|
712
|
+
}), /* @__PURE__ */ jsx(Txt, {
|
|
713
|
+
as: "span",
|
|
714
|
+
variant: "meta",
|
|
715
|
+
tone: "muted",
|
|
716
|
+
children: "Linked in page body"
|
|
717
|
+
})]
|
|
718
|
+
}) : null,
|
|
719
|
+
drawn.has("dot-parent") ? /* @__PURE__ */ jsxs("li", {
|
|
720
|
+
className: "flex items-center gap-2",
|
|
721
|
+
"data-testid": "knowledge-legend-dot-parent",
|
|
722
|
+
children: [/* @__PURE__ */ jsx("svg", {
|
|
723
|
+
width: "16",
|
|
724
|
+
height: "4",
|
|
725
|
+
"aria-hidden": true,
|
|
726
|
+
className: "shrink-0",
|
|
727
|
+
children: /* @__PURE__ */ jsx("line", {
|
|
728
|
+
x1: "0",
|
|
729
|
+
y1: "2",
|
|
730
|
+
x2: "16",
|
|
731
|
+
y2: "2",
|
|
732
|
+
...DOT_PARENT_EDGE_STYLE,
|
|
733
|
+
strokeOpacity: .5
|
|
734
|
+
})
|
|
735
|
+
}), /* @__PURE__ */ jsx(Txt, {
|
|
736
|
+
as: "span",
|
|
737
|
+
variant: "meta",
|
|
738
|
+
tone: "muted",
|
|
739
|
+
children: "Child page (dot)"
|
|
740
|
+
})]
|
|
741
|
+
}) : null,
|
|
742
|
+
drawn.has("up") ? /* @__PURE__ */ jsxs("li", {
|
|
743
|
+
className: "flex items-center gap-2",
|
|
744
|
+
"data-testid": "knowledge-legend-up",
|
|
745
|
+
children: [/* @__PURE__ */ jsxs("svg", {
|
|
746
|
+
width: "16",
|
|
747
|
+
height: "8",
|
|
748
|
+
"aria-hidden": true,
|
|
749
|
+
className: "shrink-0",
|
|
750
|
+
children: [/* @__PURE__ */ jsx("line", {
|
|
751
|
+
x1: "0",
|
|
752
|
+
y1: "4",
|
|
753
|
+
x2: "12",
|
|
754
|
+
y2: "4",
|
|
755
|
+
...UP_EDGE_STYLE
|
|
756
|
+
}), /* @__PURE__ */ jsx("polygon", {
|
|
757
|
+
points: "9,1 15,4 9,7",
|
|
758
|
+
fill: UP_EDGE_COLOR
|
|
759
|
+
})]
|
|
760
|
+
}), /* @__PURE__ */ jsx(Txt, {
|
|
761
|
+
as: "span",
|
|
762
|
+
variant: "meta",
|
|
763
|
+
tone: "muted",
|
|
764
|
+
children: "Parent of the focused page"
|
|
765
|
+
})]
|
|
766
|
+
}) : null,
|
|
767
|
+
drawn.has("parent") ? /* @__PURE__ */ jsxs("li", {
|
|
253
768
|
className: "flex items-center gap-2",
|
|
254
769
|
children: [/* @__PURE__ */ jsxs("svg", {
|
|
255
770
|
width: "16",
|
|
@@ -278,8 +793,32 @@ function GraphLegend({ grants }) {
|
|
|
278
793
|
tone: "muted",
|
|
279
794
|
children: "Parent → child"
|
|
280
795
|
})]
|
|
281
|
-
}),
|
|
282
|
-
|
|
796
|
+
}) : null,
|
|
797
|
+
counts ? /* @__PURE__ */ jsxs("li", {
|
|
798
|
+
className: "flex items-center gap-2",
|
|
799
|
+
"data-testid": "knowledge-legend-link-counts",
|
|
800
|
+
children: [
|
|
801
|
+
/* @__PURE__ */ jsx(Txt, {
|
|
802
|
+
as: "span",
|
|
803
|
+
variant: "meta",
|
|
804
|
+
style: { color: "var(--chart-orange)" },
|
|
805
|
+
children: "→4"
|
|
806
|
+
}),
|
|
807
|
+
/* @__PURE__ */ jsx(Txt, {
|
|
808
|
+
as: "span",
|
|
809
|
+
variant: "meta",
|
|
810
|
+
style: { color: LINK_EDGE_COLOR },
|
|
811
|
+
children: "14→"
|
|
812
|
+
}),
|
|
813
|
+
/* @__PURE__ */ jsx(Txt, {
|
|
814
|
+
as: "span",
|
|
815
|
+
variant: "meta",
|
|
816
|
+
tone: "muted",
|
|
817
|
+
children: "Links in, links out (not drawn)"
|
|
818
|
+
})
|
|
819
|
+
]
|
|
820
|
+
}) : null,
|
|
821
|
+
drawn.has("grant") ? /* @__PURE__ */ jsxs("li", {
|
|
283
822
|
className: "flex items-center gap-2",
|
|
284
823
|
children: [/* @__PURE__ */ jsxs("svg", {
|
|
285
824
|
width: "16",
|
|
@@ -324,14 +863,82 @@ function GraphLegend({ grants }) {
|
|
|
324
863
|
}
|
|
325
864
|
/** How far the pointer may move between press and release and still count as a click, not a pan. */
|
|
326
865
|
var CLICK_SLOP_PX = 4;
|
|
866
|
+
/** Marks the nodes and lines that stay lit while the rest of the graph fades (see knowledge.css). */
|
|
867
|
+
var NEIGHBOUR_CLASS = "knowledge-neighbour";
|
|
868
|
+
/**
|
|
869
|
+
* The same edge objects while their content is unchanged. Pointing at a page changes the style of the
|
|
870
|
+
* few lines touching it; handing React Flow fresh objects for every line would redraw them all.
|
|
871
|
+
*/
|
|
872
|
+
function useStableEdges(edges) {
|
|
873
|
+
const seen = useRef(/* @__PURE__ */ new Map());
|
|
874
|
+
return useMemo(() => {
|
|
875
|
+
const next = /* @__PURE__ */ new Map();
|
|
876
|
+
const result = edges.map((edge) => {
|
|
877
|
+
const sig = JSON.stringify(edge);
|
|
878
|
+
const before = seen.current.get(edge.id);
|
|
879
|
+
const entry = before && before.sig === sig ? before : {
|
|
880
|
+
sig,
|
|
881
|
+
edge
|
|
882
|
+
};
|
|
883
|
+
next.set(edge.id, entry);
|
|
884
|
+
return entry.edge;
|
|
885
|
+
});
|
|
886
|
+
seen.current = next;
|
|
887
|
+
return result;
|
|
888
|
+
}, [edges]);
|
|
889
|
+
}
|
|
890
|
+
/** The focused page's circle is this much larger than its neighbours'. */
|
|
891
|
+
var FOCUSED_SCALE = 1.2;
|
|
892
|
+
/** Pages in other branches that the focus links to draw a little smaller than its own neighbours. */
|
|
893
|
+
var LINK_END_SCALE = .8;
|
|
894
|
+
/** Most branch colours the legend names; the rest are counted. */
|
|
895
|
+
var LEGEND_BRANCH_CAP = 4;
|
|
896
|
+
/** Most links a hovered page draws that aren't drawn already. */
|
|
897
|
+
var HOVER_LINK_CAP = 40;
|
|
327
898
|
/**
|
|
328
899
|
* The schema-4 Knowledge page graph: scopes and pages as circles sized by how often they are mentioned,
|
|
329
900
|
* parent links as faint edges and mentions as solid ones. The first layout is deterministic for the same pages; later updates start from where pages already sit.
|
|
330
901
|
*/
|
|
331
902
|
function KnowledgePageGraph(props) {
|
|
332
|
-
|
|
903
|
+
const { settled = true } = props;
|
|
904
|
+
const held = useRef(props);
|
|
905
|
+
const [released, setReleased] = useState(false);
|
|
906
|
+
const holding = !settled && !released;
|
|
907
|
+
if (!holding) held.current = props;
|
|
908
|
+
const shown = !holding ? props : {
|
|
909
|
+
...props,
|
|
910
|
+
pages: held.current.pages,
|
|
911
|
+
edges: held.current.edges,
|
|
912
|
+
pinnedIds: held.current.pinnedIds,
|
|
913
|
+
grants: held.current.grants,
|
|
914
|
+
selectedPageId: held.current.selectedPageId,
|
|
915
|
+
centerId: held.current.centerId,
|
|
916
|
+
hiddenLinks: held.current.hiddenLinks,
|
|
917
|
+
knownLinks: held.current.knownLinks,
|
|
918
|
+
nearIds: held.current.nearIds
|
|
919
|
+
};
|
|
920
|
+
const [slow, setSlow] = useState(false);
|
|
921
|
+
useEffect(() => {
|
|
922
|
+
if (settled) {
|
|
923
|
+
setSlow(false);
|
|
924
|
+
setReleased(false);
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
const hint = setTimeout(() => setSlow(true), LOADING_HINT_DELAY_MS);
|
|
928
|
+
const deadline = setTimeout(() => setReleased(true), LOADING_RELEASE_MS);
|
|
929
|
+
return () => {
|
|
930
|
+
clearTimeout(hint);
|
|
931
|
+
clearTimeout(deadline);
|
|
932
|
+
};
|
|
933
|
+
}, [settled, props.selectedPageId]);
|
|
934
|
+
return /* @__PURE__ */ jsxs(ReactFlowProvider, { children: [/* @__PURE__ */ jsx(KnowledgePageGraphInner, { ...shown }), slow && holding ? /* @__PURE__ */ jsx("p", {
|
|
935
|
+
role: "status",
|
|
936
|
+
"data-testid": "knowledge-graph-loading",
|
|
937
|
+
className: "text-ui-sm pointer-events-none absolute bottom-3 left-1/2 z-10 -translate-x-1/2 rounded border border-border bg-card px-3 py-1 text-muted-foreground shadow-overlay",
|
|
938
|
+
children: "Loading pages…"
|
|
939
|
+
}) : null] });
|
|
333
940
|
}
|
|
334
|
-
function KnowledgePageGraphInner({ pages, edges, pinnedIds = [], grants, selectedPageId, onSelect, onOpen, onClearSelection, onMentionSelect }) {
|
|
941
|
+
function KnowledgePageGraphInner({ pages, edges, pinnedIds = [], grants, selectedPageId, centerId, hiddenLinks, knownLinks, nearIds, exactLinkCounts, fetchedLinks, onHover, showCounts, onPreview, onSelect, onOpen, onClearSelection, onMentionSelect }) {
|
|
335
942
|
const { graphPages, allEdges } = useMemo(() => {
|
|
336
943
|
const granted = grantGraph(pages, grants);
|
|
337
944
|
return {
|
|
@@ -343,28 +950,167 @@ function KnowledgePageGraphInner({ pages, edges, pinnedIds = [], grants, selecte
|
|
|
343
950
|
edges,
|
|
344
951
|
grants
|
|
345
952
|
]);
|
|
346
|
-
const
|
|
953
|
+
const linkSource = knownLinks ?? edges;
|
|
954
|
+
const linkCounts = useMemo(() => {
|
|
955
|
+
const counts = /* @__PURE__ */ new Map();
|
|
956
|
+
const pairs = /* @__PURE__ */ new Set();
|
|
957
|
+
for (const edge of linkSource) {
|
|
958
|
+
if (edge.kind !== "mention" && edge.kind !== "link") continue;
|
|
959
|
+
if (edge.source === edge.target || pairs.has(`${edge.source}\u0000${edge.target}`)) continue;
|
|
960
|
+
pairs.add(`${edge.source}\u0000${edge.target}`);
|
|
961
|
+
const out = counts.get(edge.source) ?? {
|
|
962
|
+
in: 0,
|
|
963
|
+
out: 0
|
|
964
|
+
};
|
|
965
|
+
out.out++;
|
|
966
|
+
counts.set(edge.source, out);
|
|
967
|
+
const into = counts.get(edge.target) ?? {
|
|
968
|
+
in: 0,
|
|
969
|
+
out: 0
|
|
970
|
+
};
|
|
971
|
+
into.in++;
|
|
972
|
+
counts.set(edge.target, into);
|
|
973
|
+
}
|
|
974
|
+
for (const [id, exact] of exactLinkCounts ?? []) counts.set(id, exact);
|
|
975
|
+
return counts;
|
|
976
|
+
}, [linkSource, exactLinkCounts]);
|
|
977
|
+
const hoverLinks = useMemo(() => {
|
|
978
|
+
const touching = /* @__PURE__ */ new Map();
|
|
979
|
+
const add = (id, edge) => {
|
|
980
|
+
const list = touching.get(id);
|
|
981
|
+
if (list) list.push(edge);
|
|
982
|
+
else touching.set(id, [edge]);
|
|
983
|
+
};
|
|
984
|
+
for (const edge of [...linkSource, ...fetchedLinks ?? []]) {
|
|
985
|
+
if (edge.kind !== "mention" && edge.kind !== "link") continue;
|
|
986
|
+
add(edge.source, edge);
|
|
987
|
+
if (edge.target !== edge.source) add(edge.target, edge);
|
|
988
|
+
}
|
|
989
|
+
return touching;
|
|
990
|
+
}, [linkSource, fetchedLinks]);
|
|
347
991
|
const laidOut = useMemo(() => {
|
|
992
|
+
const shape = graphShape(graphPages, selectedPageId ?? centerId ?? null, nearIds);
|
|
993
|
+
const colors = branchColors(graphPages, shape);
|
|
348
994
|
const flow = toPageFlow(graphPages, allEdges);
|
|
349
|
-
const
|
|
995
|
+
for (const node of flow.nodes) if (shape.form.get(node.id) === "dot") {
|
|
996
|
+
const links = linkCounts.get(node.id);
|
|
997
|
+
const counted = showCounts && !isChildPlaceholder(node.data.page) && !!links && links.in + links.out > 0;
|
|
998
|
+
node.data.size = counted ? 28 : 20;
|
|
999
|
+
} else if (node.id === shape.center) node.data.size = Math.round(node.data.size * FOCUSED_SCALE);
|
|
1000
|
+
else node.data.size = Math.round(108 * (shape.linked.has(node.id) ? LINK_END_SCALE : 1));
|
|
1001
|
+
const ring = flow.nodes.filter((node) => shape.depth.get(node.id) === 1 && shape.form.get(node.id) === "full");
|
|
1002
|
+
const crowd = crowdScale(ring.length);
|
|
1003
|
+
if (crowd < 1) for (const node of ring) node.data.size = Math.round(node.data.size * crowd);
|
|
1004
|
+
const sizes = new Map(flow.nodes.map((node) => [node.id, node.data.size]));
|
|
1005
|
+
const radial = radialLayout(graphPages, shape, (page) => sizes.get(page.id) ?? 20, nearIds);
|
|
1006
|
+
const positions = runLayout(flow.nodes.map((node) => ({
|
|
350
1007
|
id: node.id,
|
|
351
|
-
size: node.data.size
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
})));
|
|
356
|
-
lastLayout.current = layout;
|
|
1008
|
+
size: node.data.size,
|
|
1009
|
+
padding: shape.form.get(node.id) === "dot" ? 4 : 24,
|
|
1010
|
+
initial: radial.get(node.id)
|
|
1011
|
+
})), [], { ticks: 0 });
|
|
357
1012
|
return {
|
|
358
1013
|
nodes: flow.nodes,
|
|
359
1014
|
edges: flow.edges,
|
|
360
|
-
positions
|
|
1015
|
+
positions,
|
|
1016
|
+
shape,
|
|
1017
|
+
colors
|
|
361
1018
|
};
|
|
362
|
-
}, [
|
|
363
|
-
|
|
364
|
-
|
|
1019
|
+
}, [
|
|
1020
|
+
graphPages,
|
|
1021
|
+
allEdges,
|
|
365
1022
|
selectedPageId,
|
|
1023
|
+
centerId,
|
|
1024
|
+
linkCounts,
|
|
1025
|
+
showCounts,
|
|
1026
|
+
nearIds
|
|
1027
|
+
]);
|
|
1028
|
+
const pageById = useMemo(() => new Map(graphPages.map((page) => [page.id, page])), [graphPages]);
|
|
1029
|
+
const focusParentId = useMemo(() => {
|
|
1030
|
+
const parentId = laidOut.shape.center ? pageById.get(laidOut.shape.center)?.parentId : void 0;
|
|
1031
|
+
return parentId && laidOut.positions.has(parentId) ? parentId : null;
|
|
1032
|
+
}, [laidOut, pageById]);
|
|
1033
|
+
const drawnLevels = useMemo(() => {
|
|
1034
|
+
const kinds = /* @__PURE__ */ new Set();
|
|
1035
|
+
for (const [id, level] of laidOut.shape.level) if (laidOut.shape.form.get(id) === "full") kinds.add(level);
|
|
1036
|
+
return [...kinds];
|
|
1037
|
+
}, [laidOut]);
|
|
1038
|
+
const dotBranches = useMemo(() => {
|
|
1039
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1040
|
+
for (const node of laidOut.nodes) {
|
|
1041
|
+
if (laidOut.shape.form.get(node.id) !== "dot" || isChildPlaceholder(node.data.page)) continue;
|
|
1042
|
+
const branch = laidOut.shape.branch.get(node.id);
|
|
1043
|
+
const color = branch ? laidOut.colors.get(branch) : void 0;
|
|
1044
|
+
const owner = branch ? pageById.get(branch) : void 0;
|
|
1045
|
+
if (branch && color && owner && !seen.has(branch)) seen.set(branch, {
|
|
1046
|
+
id: branch,
|
|
1047
|
+
name: owner.displayLabel ?? owner.name,
|
|
1048
|
+
color,
|
|
1049
|
+
scope: !!owner.isScope
|
|
1050
|
+
});
|
|
1051
|
+
}
|
|
1052
|
+
return [...seen.values()];
|
|
1053
|
+
}, [laidOut, pageById]);
|
|
1054
|
+
const pinned = useMemo(() => new Set(pinnedIds), [pinnedIds]);
|
|
1055
|
+
const childrenUndrawn = useMemo(() => {
|
|
1056
|
+
const drawn = /* @__PURE__ */ new Map();
|
|
1057
|
+
for (const page of graphPages) if (page.parentId && !isChildPlaceholder(page) && !isRestCircle(page)) drawn.set(page.parentId, (drawn.get(page.parentId) ?? 0) + 1);
|
|
1058
|
+
return new Set(graphPages.filter((page) => !isScopeGroup(page) && !isRestCircle(page) && (page.childCountCapped || (page.childCount ?? 0) > (drawn.get(page.id) ?? 0))).map((page) => page.id));
|
|
1059
|
+
}, [graphPages]);
|
|
1060
|
+
const [hoveredId, setHoveredId] = useState(null);
|
|
1061
|
+
useEffect(() => onHover?.(hoveredId), [hoveredId, onHover]);
|
|
1062
|
+
const hoverExtra = useMemo(() => {
|
|
1063
|
+
if (!hoveredId) return [];
|
|
1064
|
+
const drawnIds = new Set(laidOut.nodes.map((node) => node.id));
|
|
1065
|
+
const have = new Set(laidOut.edges.map((edge) => edge.id));
|
|
1066
|
+
const extra = [];
|
|
1067
|
+
for (const edge of hoverLinks.get(hoveredId) ?? []) {
|
|
1068
|
+
const id = `${edge.kind}:${edge.source}->${edge.target}`;
|
|
1069
|
+
if (have.has(id) || !drawnIds.has(edge.source) || !drawnIds.has(edge.target)) continue;
|
|
1070
|
+
have.add(id);
|
|
1071
|
+
extra.push({
|
|
1072
|
+
id,
|
|
1073
|
+
source: edge.source,
|
|
1074
|
+
target: edge.target,
|
|
1075
|
+
data: {
|
|
1076
|
+
kind: edge.kind,
|
|
1077
|
+
count: edge.count ?? 1
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
if (extra.length >= HOVER_LINK_CAP) break;
|
|
1081
|
+
}
|
|
1082
|
+
return extra;
|
|
1083
|
+
}, [
|
|
1084
|
+
hoveredId,
|
|
1085
|
+
hoverLinks,
|
|
1086
|
+
laidOut
|
|
1087
|
+
]);
|
|
1088
|
+
const hoveredNotShown = useMemo(() => {
|
|
1089
|
+
const total = hoveredId ? linkCounts.get(hoveredId) : void 0;
|
|
1090
|
+
if (!hoveredId || !total) return 0;
|
|
1091
|
+
const pairs = /* @__PURE__ */ new Set();
|
|
1092
|
+
for (const edge of [...laidOut.edges, ...hoverExtra]) {
|
|
1093
|
+
const kind = edge.data?.kind;
|
|
1094
|
+
if (kind !== "mention" && kind !== "link" || edge.source !== hoveredId && edge.target !== hoveredId) continue;
|
|
1095
|
+
pairs.add(`${edge.source}\u0000${edge.target}`);
|
|
1096
|
+
}
|
|
1097
|
+
return Math.max(0, total.in + total.out - pairs.size);
|
|
1098
|
+
}, [
|
|
1099
|
+
hoveredId,
|
|
1100
|
+
linkCounts,
|
|
366
1101
|
laidOut,
|
|
367
|
-
|
|
1102
|
+
hoverExtra
|
|
1103
|
+
]);
|
|
1104
|
+
const emphasisId = hoveredId && laidOut.positions.has(hoveredId) ? hoveredId : selectedPageId ?? null;
|
|
1105
|
+
const neighbours = useMemo(() => emphasisId && laidOut.positions.has(emphasisId) ? pageNeighbourIds(emphasisId, [...allEdges, ...hoverExtra.map((edge) => ({
|
|
1106
|
+
kind: edge.data?.kind ?? "link",
|
|
1107
|
+
source: edge.source,
|
|
1108
|
+
target: edge.target
|
|
1109
|
+
}))]) : null, [
|
|
1110
|
+
emphasisId,
|
|
1111
|
+
laidOut,
|
|
1112
|
+
allEdges,
|
|
1113
|
+
hoverExtra
|
|
368
1114
|
]);
|
|
369
1115
|
const nodes = useMemo(() => laidOut.nodes.map((node) => {
|
|
370
1116
|
const center = laidOut.positions.get(node.id) ?? {
|
|
@@ -398,16 +1144,32 @@ function KnowledgePageGraphInner({ pages, edges, pinnedIds = [], grants, selecte
|
|
|
398
1144
|
...node.data,
|
|
399
1145
|
selected: node.id === selectedPageId,
|
|
400
1146
|
pinned: pinned.has(node.id),
|
|
401
|
-
|
|
1147
|
+
form: laidOut.shape.form.get(node.id) ?? "full",
|
|
1148
|
+
color: laidOut.colors.get(laidOut.shape.branch.get(node.id) ?? ""),
|
|
1149
|
+
badge: childrenUndrawn.has(node.id) ? childCountLabel(node.data.page) : void 0,
|
|
1150
|
+
path: pagePath(node.data.page, pageById),
|
|
1151
|
+
hiddenLinks: laidOut.shape.form.get(node.id) === "full" ? hiddenLinks?.get(node.id) : void 0,
|
|
1152
|
+
ref: pageRef(node.data.page, pageById),
|
|
1153
|
+
links: linkCounts.get(node.id),
|
|
1154
|
+
showCount: showCounts,
|
|
1155
|
+
level: laidOut.shape.form.get(node.id) === "full" ? laidOut.shape.level.get(node.id) : void 0,
|
|
1156
|
+
isParent: node.id === focusParentId,
|
|
1157
|
+
far: laidOut.shape.linked.has(node.id) || void 0
|
|
402
1158
|
}
|
|
403
1159
|
};
|
|
404
1160
|
}), [
|
|
405
1161
|
laidOut,
|
|
406
1162
|
selectedPageId,
|
|
407
1163
|
pinned,
|
|
408
|
-
|
|
1164
|
+
childrenUndrawn,
|
|
1165
|
+
pageById,
|
|
1166
|
+
hiddenLinks,
|
|
1167
|
+
linkCounts,
|
|
1168
|
+
showCounts,
|
|
1169
|
+
focusParentId
|
|
409
1170
|
]);
|
|
410
|
-
const flowEdges = useMemo(() => {
|
|
1171
|
+
const { flowEdges: builtEdges, drawnEdgeStyles } = useMemo(() => {
|
|
1172
|
+
const drawn = /* @__PURE__ */ new Set();
|
|
411
1173
|
const sizes = new Map(laidOut.nodes.map((node) => [node.id, node.data.size]));
|
|
412
1174
|
const circle = (id) => {
|
|
413
1175
|
return {
|
|
@@ -418,71 +1180,168 @@ function KnowledgePageGraphInner({ pages, edges, pinnedIds = [], grants, selecte
|
|
|
418
1180
|
r: (sizes.get(id) ?? 0) / 2
|
|
419
1181
|
};
|
|
420
1182
|
};
|
|
421
|
-
return
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
...edge
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
1183
|
+
return {
|
|
1184
|
+
flowEdges: [...laidOut.edges, ...hoverExtra].map((edge) => {
|
|
1185
|
+
const mention = edge.data?.kind === "mention";
|
|
1186
|
+
const grant = edge.data?.kind === "grant";
|
|
1187
|
+
const link = edge.data?.kind === "link";
|
|
1188
|
+
const toDot = laidOut.shape.form.get(edge.target) === "dot";
|
|
1189
|
+
const direction = (mention || link) && emphasisId ? edge.source === emphasisId ? "out" : edge.target === emphasisId ? "in" : void 0 : void 0;
|
|
1190
|
+
const up = !mention && !grant && !link && edge.source === focusParentId && edge.target === laidOut.shape.center;
|
|
1191
|
+
drawn.add(direction ?? (up ? "up" : mention ? "mention" : grant ? "grant" : link ? "link" : toDot ? "dot-parent" : "parent"));
|
|
1192
|
+
return {
|
|
1193
|
+
...edge,
|
|
1194
|
+
type: "rim",
|
|
1195
|
+
data: {
|
|
1196
|
+
kind: edge.data?.kind ?? "parent",
|
|
1197
|
+
count: edge.data?.count ?? 1,
|
|
1198
|
+
...edge.data?.role ? { role: edge.data.role } : {},
|
|
1199
|
+
from: circle(edge.source),
|
|
1200
|
+
to: circle(edge.target)
|
|
1201
|
+
},
|
|
1202
|
+
...direction === "in" ? { zIndex: 1 } : {},
|
|
1203
|
+
...mention && onMentionSelect ? { className: "cursor-pointer" } : {},
|
|
1204
|
+
style: direction ? {
|
|
1205
|
+
...DIRECTION_EDGE_STYLE[direction],
|
|
1206
|
+
strokeWidth: mention ? 2 : 1.5
|
|
1207
|
+
} : mention ? {
|
|
1208
|
+
stroke: MENTION_EDGE_COLOR,
|
|
1209
|
+
strokeWidth: Math.min(1.5 + (edge.data?.count ?? 1) * .5, 4)
|
|
1210
|
+
} : up ? UP_EDGE_STYLE : grant ? GRANT_EDGE_STYLE : link ? LINK_EDGE_STYLE : toDot ? DOT_PARENT_EDGE_STYLE : PARENT_EDGE_STYLE,
|
|
1211
|
+
markerEnd: direction ? DIRECTION_ARROW[direction] : up ? UP_ARROW : mention ? {
|
|
1212
|
+
type: MarkerType.ArrowClosed,
|
|
1213
|
+
color: MENTION_EDGE_COLOR,
|
|
1214
|
+
width: 14,
|
|
1215
|
+
height: 14
|
|
1216
|
+
} : grant ? GRANT_ARROW : link ? LINK_ARROW : toDot ? void 0 : PARENT_ARROW
|
|
1217
|
+
};
|
|
1218
|
+
}),
|
|
1219
|
+
drawnEdgeStyles: drawn
|
|
1220
|
+
};
|
|
449
1221
|
}, [
|
|
450
1222
|
laidOut,
|
|
1223
|
+
hoverExtra,
|
|
451
1224
|
onMentionSelect,
|
|
452
|
-
|
|
1225
|
+
emphasisId,
|
|
1226
|
+
focusParentId
|
|
1227
|
+
]);
|
|
1228
|
+
const flowEdges = useStableEdges(builtEdges);
|
|
1229
|
+
const emphasisedNodes = useMemo(() => nodes.map((node) => {
|
|
1230
|
+
const near = neighbours?.has(node.id);
|
|
1231
|
+
const hovered = node.id === hoveredId && hoveredNotShown > 0;
|
|
1232
|
+
if (!near && !hovered) return node;
|
|
1233
|
+
return {
|
|
1234
|
+
...node,
|
|
1235
|
+
...near ? { className: NEIGHBOUR_CLASS } : {},
|
|
1236
|
+
...hovered ? { data: {
|
|
1237
|
+
...node.data,
|
|
1238
|
+
notShown: hoveredNotShown
|
|
1239
|
+
} } : {}
|
|
1240
|
+
};
|
|
1241
|
+
}), [
|
|
1242
|
+
nodes,
|
|
1243
|
+
neighbours,
|
|
1244
|
+
hoveredId,
|
|
1245
|
+
hoveredNotShown
|
|
453
1246
|
]);
|
|
1247
|
+
const emphasisedEdges = useMemo(() => neighbours ? flowEdges.map((edge) => neighbours.has(edge.source) && neighbours.has(edge.target) ? {
|
|
1248
|
+
...edge,
|
|
1249
|
+
className: [edge.className, NEIGHBOUR_CLASS].filter(Boolean).join(" ")
|
|
1250
|
+
} : edge) : flowEdges, [flowEdges, neighbours]);
|
|
454
1251
|
const pagesById = useMemo(() => new Map(pages.map((page) => [page.id, page])), [pages]);
|
|
455
1252
|
const reactFlow = useReactFlow();
|
|
456
1253
|
const containerRef = useRef(null);
|
|
457
1254
|
const hasNodes = nodes.length > 0;
|
|
1255
|
+
const drawnNodes = useLeavingNodes(emphasisedNodes, prefersMotion());
|
|
1256
|
+
const linkedIds = laidOut.shape.linked;
|
|
458
1257
|
const fitState = useRef({
|
|
459
1258
|
nodes,
|
|
460
|
-
allEdges,
|
|
461
1259
|
selectedPageId,
|
|
462
|
-
|
|
1260
|
+
centerId,
|
|
1261
|
+
reactFlow,
|
|
1262
|
+
linkedIds
|
|
463
1263
|
});
|
|
464
1264
|
fitState.current = {
|
|
465
1265
|
nodes,
|
|
466
|
-
allEdges,
|
|
467
1266
|
selectedPageId,
|
|
468
|
-
|
|
1267
|
+
centerId,
|
|
1268
|
+
reactFlow,
|
|
1269
|
+
linkedIds
|
|
469
1270
|
};
|
|
470
1271
|
const fitPending = useRef(false);
|
|
471
|
-
const
|
|
1272
|
+
const paneAndNodes = () => {
|
|
472
1273
|
const container = containerRef.current;
|
|
473
1274
|
const width = container?.clientWidth ?? 0;
|
|
474
1275
|
const height = container?.clientHeight ?? 0;
|
|
475
1276
|
if (width === 0 || height === 0) {
|
|
476
1277
|
fitPending.current = true;
|
|
477
|
-
return;
|
|
1278
|
+
return null;
|
|
478
1279
|
}
|
|
479
1280
|
fitPending.current = false;
|
|
480
|
-
const { nodes: current,
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
1281
|
+
const { nodes: current, reactFlow: flow } = fitState.current;
|
|
1282
|
+
const bounds = graphBounds(current);
|
|
1283
|
+
return bounds ? {
|
|
1284
|
+
container,
|
|
1285
|
+
width,
|
|
1286
|
+
height,
|
|
1287
|
+
current,
|
|
1288
|
+
flow,
|
|
1289
|
+
bounds
|
|
1290
|
+
} : null;
|
|
1291
|
+
};
|
|
1292
|
+
const fit = useCallback((duration) => {
|
|
1293
|
+
const view = paneAndNodes();
|
|
1294
|
+
if (!view) return;
|
|
1295
|
+
const { selectedPageId: selected, centerId: centre, linkedIds: linked } = fitState.current;
|
|
1296
|
+
const anchor = view.current.find((node) => node.id === (selected ?? centre));
|
|
1297
|
+
const ring = !!selected && view.current.some((node) => linked.has(node.id));
|
|
1298
|
+
const viewport = fitViewport({
|
|
1299
|
+
bounds: view.bounds,
|
|
1300
|
+
width: view.width,
|
|
1301
|
+
height: view.height,
|
|
1302
|
+
ring,
|
|
1303
|
+
anchor
|
|
1304
|
+
});
|
|
1305
|
+
view.flow.setViewport(viewport, duration ? { duration } : void 0);
|
|
1306
|
+
}, []);
|
|
1307
|
+
const fitInitial = useCallback(() => {
|
|
1308
|
+
const view = paneAndNodes();
|
|
1309
|
+
if (!view) return;
|
|
1310
|
+
const box = view.container?.getBoundingClientRect();
|
|
1311
|
+
const legend = view.container?.querySelector("[aria-label=\"Legend\"]")?.getBoundingClientRect();
|
|
1312
|
+
const viewport = fitAllViewport({
|
|
1313
|
+
bounds: view.bounds,
|
|
1314
|
+
nodes: view.current.map((node) => ({
|
|
1315
|
+
x: node.position.x,
|
|
1316
|
+
y: node.position.y,
|
|
1317
|
+
width: node.width ?? 0,
|
|
1318
|
+
height: node.height ?? 0
|
|
1319
|
+
})),
|
|
1320
|
+
width: view.width,
|
|
1321
|
+
height: view.height,
|
|
1322
|
+
legend: box && legend ? {
|
|
1323
|
+
right: legend.right - box.left + 8,
|
|
1324
|
+
bottom: legend.bottom - box.top + 8
|
|
1325
|
+
} : void 0
|
|
1326
|
+
});
|
|
1327
|
+
view.flow.setViewport(viewport);
|
|
1328
|
+
}, []);
|
|
1329
|
+
const nudgeToSelection = useCallback((duration) => {
|
|
1330
|
+
const container = containerRef.current;
|
|
1331
|
+
const width = container?.clientWidth ?? 0;
|
|
1332
|
+
const height = container?.clientHeight ?? 0;
|
|
1333
|
+
const { nodes: current, selectedPageId: selected, centerId: centre, reactFlow: flow } = fitState.current;
|
|
1334
|
+
const anchor = current.find((node) => node.id === (selected ?? centre));
|
|
1335
|
+
if (!anchor || width === 0 || height === 0) return;
|
|
1336
|
+
const view = flow.getViewport();
|
|
1337
|
+
const dx = nudgeAxis(anchor.position.x * view.zoom + view.x, (anchor.width ?? 0) * view.zoom, width);
|
|
1338
|
+
const dy = nudgeAxis(anchor.position.y * view.zoom + view.y, (anchor.height ?? 0) * view.zoom, height);
|
|
1339
|
+
if (dx === 0 && dy === 0) return;
|
|
1340
|
+
flow.setViewport({
|
|
1341
|
+
zoom: view.zoom,
|
|
1342
|
+
x: view.x + dx,
|
|
1343
|
+
y: view.y + dy
|
|
1344
|
+
}, duration ? { duration } : void 0);
|
|
486
1345
|
}, []);
|
|
487
1346
|
useEffect(() => {
|
|
488
1347
|
const container = containerRef.current;
|
|
@@ -492,10 +1351,12 @@ function KnowledgePageGraphInner({ pages, edges, pinnedIds = [], grants, selecte
|
|
|
492
1351
|
height: container.clientHeight
|
|
493
1352
|
};
|
|
494
1353
|
let frame;
|
|
1354
|
+
let needsFit = false;
|
|
495
1355
|
const observer = new ResizeObserver(([entry]) => {
|
|
496
1356
|
if (!entry) return;
|
|
497
1357
|
const { width, height } = entry.contentRect;
|
|
498
1358
|
const changed = width !== last.width || height !== last.height;
|
|
1359
|
+
if (last.width === 0 || last.height === 0) needsFit = true;
|
|
499
1360
|
last = {
|
|
500
1361
|
width,
|
|
501
1362
|
height
|
|
@@ -504,7 +1365,10 @@ function KnowledgePageGraphInner({ pages, edges, pinnedIds = [], grants, selecte
|
|
|
504
1365
|
if (frame !== void 0) cancelAnimationFrame(frame);
|
|
505
1366
|
frame = requestAnimationFrame(() => {
|
|
506
1367
|
frame = void 0;
|
|
507
|
-
|
|
1368
|
+
if (needsFit || fitPending.current) {
|
|
1369
|
+
needsFit = false;
|
|
1370
|
+
fitInitial();
|
|
1371
|
+
} else nudgeToSelection();
|
|
508
1372
|
});
|
|
509
1373
|
});
|
|
510
1374
|
observer.observe(container);
|
|
@@ -512,33 +1376,51 @@ function KnowledgePageGraphInner({ pages, edges, pinnedIds = [], grants, selecte
|
|
|
512
1376
|
observer.disconnect();
|
|
513
1377
|
if (frame !== void 0) cancelAnimationFrame(frame);
|
|
514
1378
|
};
|
|
515
|
-
}, [
|
|
1379
|
+
}, [
|
|
1380
|
+
hasNodes,
|
|
1381
|
+
fitInitial,
|
|
1382
|
+
nudgeToSelection
|
|
1383
|
+
]);
|
|
516
1384
|
const selectedHere = useRef(null);
|
|
517
1385
|
const selectedIsLoaded = !!selectedPageId && pagesById.has(selectedPageId);
|
|
518
1386
|
const initialized = useRef(false);
|
|
1387
|
+
const settleUntil = useRef(0);
|
|
1388
|
+
const settledOn = useRef(null);
|
|
1389
|
+
const fittedLayout = useRef("");
|
|
1390
|
+
const stopSettling = useCallback(() => {
|
|
1391
|
+
settleUntil.current = 0;
|
|
1392
|
+
}, []);
|
|
1393
|
+
useEffect(() => {
|
|
1394
|
+
if (!initialized.current) return;
|
|
1395
|
+
if ((selectedPageId ?? null) !== settledOn.current) settleUntil.current = 0;
|
|
1396
|
+
if (Date.now() >= settleUntil.current) return;
|
|
1397
|
+
const layout = nodes.map((node) => `${node.id}@${node.position.x},${node.position.y}`).join("|");
|
|
1398
|
+
if (layout === fittedLayout.current) return;
|
|
1399
|
+
fittedLayout.current = layout;
|
|
1400
|
+
fitInitial();
|
|
1401
|
+
}, [
|
|
1402
|
+
nodes,
|
|
1403
|
+
selectedPageId,
|
|
1404
|
+
fitInitial
|
|
1405
|
+
]);
|
|
519
1406
|
useEffect(() => {
|
|
520
1407
|
if (!initialized.current || !selectedIsLoaded || !selectedPageId) return;
|
|
521
1408
|
const fromGraph = selectedHere.current === selectedPageId;
|
|
522
1409
|
selectedHere.current = null;
|
|
523
1410
|
if (fromGraph) return;
|
|
524
|
-
|
|
1411
|
+
nudgeToSelection(fitDuration(prefersMotion()));
|
|
525
1412
|
}, [
|
|
526
1413
|
selectedPageId,
|
|
527
1414
|
selectedIsLoaded,
|
|
528
|
-
|
|
1415
|
+
nudgeToSelection
|
|
529
1416
|
]);
|
|
530
1417
|
const activate = (page) => {
|
|
1418
|
+
if (isChildPlaceholder(page) || isScopeGroup(page) || isRestCircle(page)) return onSelect(page);
|
|
531
1419
|
if (page.id === selectedPageId && onOpen) return onOpen(page);
|
|
532
1420
|
selectedHere.current = page.id;
|
|
533
1421
|
onSelect(page);
|
|
534
1422
|
};
|
|
535
1423
|
const pressedAt = useRef(null);
|
|
536
|
-
const onPaneClick = (event) => {
|
|
537
|
-
const start = pressedAt.current;
|
|
538
|
-
pressedAt.current = null;
|
|
539
|
-
if (start && Math.hypot(event.clientX - start.x, event.clientY - start.y) > CLICK_SLOP_PX) return;
|
|
540
|
-
onClearSelection?.();
|
|
541
|
-
};
|
|
542
1424
|
const onKeyDown = (event) => {
|
|
543
1425
|
if (event.key !== "Enter" && event.key !== " ") return;
|
|
544
1426
|
const id = event.target.closest(".react-flow__node")?.dataset.id;
|
|
@@ -547,6 +1429,56 @@ function KnowledgePageGraphInner({ pages, edges, pinnedIds = [], grants, selecte
|
|
|
547
1429
|
event.preventDefault();
|
|
548
1430
|
activate(page);
|
|
549
1431
|
};
|
|
1432
|
+
const latest = useRef({
|
|
1433
|
+
activate,
|
|
1434
|
+
onPreview,
|
|
1435
|
+
onMentionSelect,
|
|
1436
|
+
onClearSelection,
|
|
1437
|
+
laidOut,
|
|
1438
|
+
pagesById
|
|
1439
|
+
});
|
|
1440
|
+
latest.current = {
|
|
1441
|
+
activate,
|
|
1442
|
+
onPreview,
|
|
1443
|
+
onMentionSelect,
|
|
1444
|
+
onClearSelection,
|
|
1445
|
+
laidOut,
|
|
1446
|
+
pagesById
|
|
1447
|
+
};
|
|
1448
|
+
const onNodeMouseEnter = useCallback((_, node) => {
|
|
1449
|
+
setHoveredId(node.id);
|
|
1450
|
+
if (latest.current.laidOut.shape.form.get(node.id) === "dot") latest.current.onPreview?.(node.data.page);
|
|
1451
|
+
}, []);
|
|
1452
|
+
const onNodeMouseLeave = useCallback(() => setHoveredId(null), []);
|
|
1453
|
+
const onNodeClick = useCallback((_, node) => {
|
|
1454
|
+
if (!isPlaceholder(node.data.page)) latest.current.activate(node.data.page);
|
|
1455
|
+
}, []);
|
|
1456
|
+
const onEdgeClick = useCallback((event, edge) => {
|
|
1457
|
+
const { onMentionSelect, pagesById } = latest.current;
|
|
1458
|
+
if (edge.data?.kind !== "mention" || !onMentionSelect) return;
|
|
1459
|
+
const source = pagesById.get(edge.source);
|
|
1460
|
+
const target = pagesById.get(edge.target);
|
|
1461
|
+
if (!source || !target) return;
|
|
1462
|
+
const box = containerRef.current?.getBoundingClientRect();
|
|
1463
|
+
onMentionSelect({
|
|
1464
|
+
source,
|
|
1465
|
+
target,
|
|
1466
|
+
point: {
|
|
1467
|
+
x: event.clientX - (box?.left ?? 0),
|
|
1468
|
+
y: event.clientY - (box?.top ?? 0)
|
|
1469
|
+
},
|
|
1470
|
+
pane: {
|
|
1471
|
+
width: box?.width ?? 0,
|
|
1472
|
+
height: box?.height ?? 0
|
|
1473
|
+
}
|
|
1474
|
+
});
|
|
1475
|
+
}, []);
|
|
1476
|
+
const onPaneClick = useCallback((event) => {
|
|
1477
|
+
const start = pressedAt.current;
|
|
1478
|
+
pressedAt.current = null;
|
|
1479
|
+
if (start && Math.hypot(event.clientX - start.x, event.clientY - start.y) > CLICK_SLOP_PX) return;
|
|
1480
|
+
latest.current.onClearSelection?.();
|
|
1481
|
+
}, []);
|
|
550
1482
|
if (!hasNodes) return /* @__PURE__ */ jsx("div", {
|
|
551
1483
|
className: "flex h-full items-center justify-center p-6",
|
|
552
1484
|
children: /* @__PURE__ */ jsx(Txt, {
|
|
@@ -557,51 +1489,47 @@ function KnowledgePageGraphInner({ pages, edges, pinnedIds = [], grants, selecte
|
|
|
557
1489
|
});
|
|
558
1490
|
return /* @__PURE__ */ jsxs("div", {
|
|
559
1491
|
ref: containerRef,
|
|
560
|
-
className: "relative size-full",
|
|
1492
|
+
className: "knowledge-graph relative size-full",
|
|
1493
|
+
"data-emphasis": neighbours ? "on" : void 0,
|
|
561
1494
|
"data-testid": "knowledge-page-graph",
|
|
562
1495
|
onKeyDown,
|
|
1496
|
+
onWheelCapture: stopSettling,
|
|
563
1497
|
onPointerDownCapture: (event) => {
|
|
1498
|
+
stopSettling();
|
|
564
1499
|
pressedAt.current = {
|
|
565
1500
|
x: event.clientX,
|
|
566
1501
|
y: event.clientY
|
|
567
1502
|
};
|
|
568
1503
|
},
|
|
569
|
-
children: [/* @__PURE__ */ jsx(GraphLegend, {
|
|
570
|
-
|
|
571
|
-
|
|
1504
|
+
children: [/* @__PURE__ */ jsx(GraphLegend, {
|
|
1505
|
+
branches: dotBranches,
|
|
1506
|
+
levels: drawnLevels,
|
|
1507
|
+
focused: !!selectedPageId && laidOut.positions.has(selectedPageId),
|
|
1508
|
+
dots: [...laidOut.shape.form.values()].includes("dot"),
|
|
1509
|
+
linkEnds: laidOut.shape.linked.size > 0,
|
|
1510
|
+
drawn: drawnEdgeStyles,
|
|
1511
|
+
counts: [...hiddenLinks ?? []].some(([id, hidden]) => laidOut.shape.form.get(id) === "full" && (hidden.in > 0 || hidden.out > 0))
|
|
1512
|
+
}), /* @__PURE__ */ jsxs(ReactFlow, {
|
|
1513
|
+
nodes: drawnNodes,
|
|
1514
|
+
edges: emphasisedEdges,
|
|
572
1515
|
nodeTypes,
|
|
573
1516
|
edgeTypes,
|
|
574
1517
|
onInit: () => {
|
|
575
1518
|
initialized.current = true;
|
|
576
|
-
|
|
1519
|
+
settleUntil.current = Date.now() + INITIAL_SETTLE_MS;
|
|
1520
|
+
settledOn.current = fitState.current.selectedPageId ?? null;
|
|
1521
|
+
fittedLayout.current = fitState.current.nodes.map((node) => `${node.id}@${node.position.x},${node.position.y}`).join("|");
|
|
1522
|
+
fitInitial();
|
|
577
1523
|
},
|
|
578
1524
|
minZoom: .1,
|
|
579
1525
|
proOptions: { hideAttribution: true },
|
|
580
1526
|
nodesConnectable: false,
|
|
581
1527
|
nodesDraggable: false,
|
|
582
1528
|
onPaneClick,
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
onEdgeClick
|
|
587
|
-
if (edge.data?.kind !== "mention" || !onMentionSelect) return;
|
|
588
|
-
const source = pagesById.get(edge.source);
|
|
589
|
-
const target = pagesById.get(edge.target);
|
|
590
|
-
if (!source || !target) return;
|
|
591
|
-
const box = containerRef.current?.getBoundingClientRect();
|
|
592
|
-
onMentionSelect({
|
|
593
|
-
source,
|
|
594
|
-
target,
|
|
595
|
-
point: {
|
|
596
|
-
x: event.clientX - (box?.left ?? 0),
|
|
597
|
-
y: event.clientY - (box?.top ?? 0)
|
|
598
|
-
},
|
|
599
|
-
pane: {
|
|
600
|
-
width: box?.width ?? 0,
|
|
601
|
-
height: box?.height ?? 0
|
|
602
|
-
}
|
|
603
|
-
});
|
|
604
|
-
},
|
|
1529
|
+
onNodeMouseEnter,
|
|
1530
|
+
onNodeMouseLeave,
|
|
1531
|
+
onNodeClick,
|
|
1532
|
+
onEdgeClick,
|
|
605
1533
|
children: [/* @__PURE__ */ jsx(Background, {
|
|
606
1534
|
variant: BackgroundVariant.Dots,
|
|
607
1535
|
gap: 26,
|
|
@@ -611,7 +1539,7 @@ function KnowledgePageGraphInner({ pages, edges, pinnedIds = [], grants, selecte
|
|
|
611
1539
|
showInteractive: false,
|
|
612
1540
|
showFitView: false,
|
|
613
1541
|
children: /* @__PURE__ */ jsx(ControlButton, {
|
|
614
|
-
onClick: () => fit(
|
|
1542
|
+
onClick: () => fit(fitDuration(prefersMotion())),
|
|
615
1543
|
title: "Fit view",
|
|
616
1544
|
"aria-label": "Fit view",
|
|
617
1545
|
children: /* @__PURE__ */ jsx(Maximize, { "aria-hidden": true })
|