sanity-plugin-graph-view
5.0.225.0.23
dist/GraphView-BrPWN-Cw.js.map+
dist/GraphView-BrPWN-Cw.js.mapNew file+1
Index: package/dist/GraphView-BrPWN-Cw.js.map
===================================================================
--- package/dist/GraphView-BrPWN-Cw.js.map
+++ package/dist/GraphView-BrPWN-Cw.js.map
@@ -0,0 +1,1 @@
+{"version":3,"file":"GraphView-BrPWN-Cw.js","names":[],"sources":["../src/tool/GraphViewStyle.tsx","../src/tool/utils.ts","../src/tool/GraphView.tsx"],"sourcesContent":["import {black} from '@sanity/color'\n// TODO: when upgrading to @sanity/ui@4 start using the new tokens\n// oxlint-disable typescript/no-deprecated\nimport type {Theme} from '@sanity/ui'\nimport {type PropsWithChildren} from 'react'\nimport {styled} from 'styled-components'\n\ntype Style = PropsWithChildren<{theme: SanityTheme}>\ntype SanityTheme = Theme['sanity']\n\nexport const GraphRoot: React.FC<Style> = styled.div<Style>`\n font-family: ${({theme}) => theme.fonts.text.family};\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: ${black.hex};\n`\n\nexport const GraphWrapper: React.FC<Style> = styled.div`\n position: relative;\n width: 100%;\n height: 100%;\n`\n\nexport const HoverNode: React.FC<Style> = styled.div<Style>`\n font-family: ${({theme}) => theme.fonts.text.family};\n display: none;\n position: absolute;\n bottom: ${({theme}) => theme.space[0]}px;\n left: 50%;\n transform: translate3d(-50%, 0, 0);\n background: var(--component-bg);\n border-radius: ${({theme}) => theme.radius[2]}px;\n padding: ${({theme}) => theme.space[2]}px;\n z-index: 1000;\n\n &:empty {\n display: none;\n }\n`\n\nexport const Legend: React.FC<Style> = styled.div<Style>`\n color: #ccc;\n position: absolute;\n top: ${({theme}) => theme.space[4]}px;\n left: ${({theme}) => theme.space[4]}px;\n\n & > div {\n margin: 5px 0;\n }\n`\n\nexport const LegendRow: React.FC<\n PropsWithChildren<{className?: string; style?: React.CSSProperties}>\n> = styled.div`\n display: flex;\n`\n\nexport const LegendBadge: React.FC<Style> = styled.div<Style>`\n width: 1.25em;\n height: 1.25em;\n background: currentColor;\n border-radius: 50%;\n margin-right: ${({theme}) => theme.space[2]}px;\n`\n","export function sizeOf(value: any): number {\n if (value === null) {\n return 0\n }\n\n if (typeof value === 'object') {\n return Object.entries(value).reduce((total, [k, v]) => total + sizeOf(k) + sizeOf(v), 0)\n }\n\n if (Array.isArray(value)) {\n return Object.entries(value).reduce((total, v) => total + sizeOf(v), 0)\n }\n\n if (typeof value === 'string') {\n return value.length\n }\n\n return 1\n}\n\nexport function loadImage(url: string, w: number, h: number): Promise<HTMLImageElement | null> {\n return new Promise((resolve) => {\n const img = new Image(w, h)\n // oxlint-disable-next-line prefer-add-event-listener\n img.onload = () => {\n resolve(img)\n }\n // oxlint-disable-next-line prefer-add-event-listener\n img.onerror = (event) => {\n console.error('Image error', event)\n resolve(null)\n }\n img.src = url\n })\n}\n\nexport function sortBy<T>(array: T[], f: (t: T) => number): T[] {\n return array.sort((a, b) => {\n const va = f(a)\n const vb = f(b)\n return va < vb ? -1 : va > vb ? 1 : 0\n })\n}\n\nexport function truncate(s: string, limit: number): string {\n if (s.length > limit) {\n return `${s.substring(0, limit)}…`\n }\n return s\n}\n","import {black, COLOR_HUES, gray, white, hues} from '@sanity/color'\nimport {useTheme} from '@sanity/ui'\nimport BezierEasing from 'bezier-easing'\nimport deepEqual from 'deep-equal'\nimport {rgba} from 'polished'\nimport {useEffect, useState} from 'react'\nimport ForceGraph2D from 'react-force-graph-2d'\nimport {useClient, useUserColorManager, type SanityClient, type SanityDocument} from 'sanity'\nimport {useRouter} from 'sanity/router'\nimport {v4 as uuidv4} from 'uuid'\n\nimport {GraphRoot, GraphWrapper, HoverNode, Legend, LegendBadge, LegendRow} from './GraphViewStyle'\nimport {sortBy, loadImage, sizeOf, truncate} from './utils'\n\nconst DEFAULT_QUERY = `\n *[\n !(_id in path(\"_.*\")) &&\n !(_type match \"system.*\") &&\n !(_type match \"sanity.*\")\n ]\n`\n\nconst fadeEasing = BezierEasing(0, 0.9, 1, 1)\nconst softEasing = BezierEasing(0.25, 0.1, 0.0, 1.0)\nconst idleTimeout = 10000\nconst imageSize = 40\n\nfunction getTopDocTypes(counts: Record<string, number>) {\n return sortBy(Object.keys(counts), (docType) => counts[docType] || 0)\n .reverse()\n .slice(0, 10)\n}\n\nfunction formatDocType(docType: string) {\n return (docType.substring(0, 1).toUpperCase() + docType.substring(1))\n .replace(/\\./g, ' ')\n .replace(/[A-Z]/g, ' $&')\n .trim()\n}\n\nfunction getDocTypeCounts(docs: SanityDocument[]) {\n const types: Record<string, number> = {}\n for (const doc of docs) {\n types[doc._type] = (types[doc._type] || 0) + 1\n }\n return types\n}\n\nfunction labelFor(doc: SanityDocument) {\n // oxlint-disable-next-line restrict-template-expressions,no-base-to-string\n return `${doc.title || doc.name || doc._id}`.trim()\n}\n\nfunction valueFor(doc: any, maxSize: number) {\n return 5 + 100 * (sizeOf(doc) / maxSize)\n}\n\nfunction findRefs(obj: any, dest: any[] = []) {\n if (obj !== null) {\n if (typeof obj === 'object') {\n for (const [k, v] of Object.entries(obj)) {\n if (k === '_ref' && typeof v === 'string' && v.length > 0) {\n dest.push(stripDraftId(v))\n }\n findRefs(v, dest)\n }\n } else if (Array.isArray(obj)) {\n for (const v of obj) {\n findRefs(v, dest)\n }\n }\n }\n return dest\n}\n\nfunction stripDraftId(id: string) {\n return id.replace(/^drafts\\./, '')\n}\n\nfunction deduplicateDrafts(docs: SanityDocument[]) {\n const deduped: Record<string, SanityDocument> = {}\n for (const doc of docs) {\n if (!doc._id.startsWith('drafts.')) {\n deduped[doc._id] = doc\n }\n }\n for (const doc of docs) {\n if (doc._id.startsWith('drafts.')) {\n const id = stripDraftId(doc._id)\n deduped[id] = Object.assign(doc, {_id: id})\n }\n }\n return Object.values(deduped)\n}\n\nclass Users {\n _users: any[] = []\n\n async getById(id: string, client: SanityClient) {\n let user = this._users.find((u) => u._id === id)\n if (!user) {\n user = await client.users.getById(id)\n this._users.push(user)\n user.image = await loadImage(\n user.imageUrl ||\n 'https://raw.githubusercontent.com/sanity-io/sanity-plugin-graph-view/main/assets/head-silhouette.jpg',\n imageSize,\n imageSize,\n )\n }\n return user\n }\n}\n\nclass Session {\n id: string | null = null\n user: any = null\n doc: SanityDocument | null = null\n lastActive: number = 0\n startTime: number = 0\n angle: number = 0\n}\n\nclass GraphData {\n sessions: Session[] = []\n data: any\n\n constructor(docs: SanityDocument[] = []) {\n const docsById: Record<string, SanityDocument> = {}\n for (const doc of docs) {\n docsById[doc._id] = doc\n }\n\n this.data = {\n nodes: docs.map((d) => Object.assign({id: d._id, type: 'document', doc: d})),\n links: docs\n .flatMap((doc) => findRefs(doc).map((ref) => ({source: doc._id, target: ref})))\n .filter((link) => docsById[link.source] && docsById[link.target]),\n }\n }\n\n setSession(user: any, docNode: any) {\n let session = this.sessions.find((s) => s.user.id === user.id && s.doc?._id === docNode.doc._id)\n if (!session) {\n session = new Session()\n session.id = uuidv4()\n session.user = user\n session.startTime = Date.now()\n session.doc = docNode.doc\n session.angle = Math.random() * 2 * Math.PI\n this.sessions.push(session)\n }\n session.lastActive = Date.now()\n }\n\n reapSessions() {\n for (let i = 0; i < this.sessions.length; i++) {\n const session = this.sessions[i]\n if (Date.now() - session.lastActive > idleTimeout) {\n this.sessions = [...this.sessions.slice(0, i), ...this.sessions.slice(i + 1)]\n i--\n }\n }\n }\n\n clone() {\n const copy = new GraphData()\n Object.assign(copy, this)\n copy.data = {\n nodes: [...this.data.nodes],\n links: [...this.data.links],\n }\n return copy\n }\n}\n\nconst users = new Users()\n\ninterface GraphViewConfig {\n query?: string\n /** default: '2022-09-01' */\n apiVersion?: string\n}\n\nexport default function GraphView({\n tool: {options: props},\n}: {\n tool: {options: GraphViewConfig}\n}): React.JSX.Element {\n const query = props.query || DEFAULT_QUERY\n const apiVersion = props.apiVersion ?? '2022-09-01'\n\n const userColorManager = useUserColorManager()\n const [maxSize, setMaxSize] = useState(0)\n const [hoverNode, setHoverNode] = useState<any>(null)\n const [documents, setDocuments] = useState<SanityDocument[]>([])\n const [docTypes, setDocTypes] = useState<Record<string, number>>({})\n const [graph, setGraph] = useState(() => new GraphData())\n const router = useRouter()\n const client = useClient({apiVersion})\n\n useEffect(() => {\n void client.fetch(query).then((_docs) => {\n const docs = deduplicateDrafts(_docs)\n setMaxSize(Math.max(...docs.map(sizeOf)))\n setDocuments(docs)\n setDocTypes(getDocTypeCounts(docs))\n setGraph(new GraphData(docs))\n return undefined\n })\n }, [client, query])\n\n useEffect(() => {\n const subscription = client.listen(query, {}, {}).subscribe(async (update) => {\n if (update.type !== 'mutation') return\n const doc = update.result\n if (doc) {\n doc._id = stripDraftId(doc._id)\n\n const docsById: Record<string, SanityDocument> = {}\n for (const d of documents) {\n docsById[d._id] = d\n }\n\n let oldDoc\n const docs = [...documents]\n const idx = documents.findIndex((d) => d._id === doc._id)\n if (idx >= 0) {\n oldDoc = docs[idx]\n docs[idx] = doc\n } else {\n docs.push(doc)\n }\n setDocuments(docs)\n setDocTypes(getDocTypeCounts(docs))\n setMaxSize(Math.max(...docs.map(sizeOf)))\n\n const newGraph = graph.clone()\n\n const oldRefs = findRefs(oldDoc || {}).filter(\n (id) => id === doc._id || docsById[id] !== null,\n )\n const newRefs = findRefs(doc).filter((id) => id === doc._id || docsById[id] !== null)\n\n let graphChanged = !deepEqual(oldRefs, newRefs)\n if (graphChanged) {\n newGraph.data.links = newGraph.data.links\n .filter((l: any) => l.source.id !== doc._id)\n .concat(newRefs.map((ref) => ({source: doc._id, target: ref})))\n }\n\n let docNode\n const nodeIdx = graph.data.nodes.findIndex((n: any) => n.doc && n.doc._id === doc._id)\n if (nodeIdx >= 0) {\n docNode = graph.data.nodes[nodeIdx]\n docNode.doc = doc\n } else {\n docNode = {id: doc._id, type: 'document', doc: doc}\n newGraph.data.nodes.push(docNode)\n graphChanged = true\n }\n if (graphChanged) {\n setGraph(newGraph)\n }\n\n const user = await users.getById(update.identity, client)\n graph.setSession(user, docNode)\n } else if (update.transition === 'disappear') {\n const docId = stripDraftId(update.documentId)\n\n const docs = documents.filter((d) => d._id !== docId)\n setDocuments(docs)\n setDocTypes(getDocTypeCounts(docs))\n setMaxSize(Math.max(...docs.map(sizeOf)))\n\n const newGraph = graph.clone()\n newGraph.data.links = newGraph.data.links.filter(\n (l: any) => l.source.id !== docId && l.target.id !== docId,\n )\n newGraph.data.nodes = newGraph.data.nodes.filter((n: any) => n.id !== docId)\n setGraph(newGraph)\n }\n })\n return () => {\n subscription.unsubscribe()\n }\n }, [client, query, documents, graph])\n\n useEffect(() => {\n const interval = setInterval(() => graph.reapSessions(), 1000)\n return () => clearInterval(interval)\n }, [graph])\n\n const theme = useTheme().sanity\n\n return (\n <GraphWrapper theme={theme}>\n <GraphRoot theme={theme}>\n <Legend theme={theme}>\n {getTopDocTypes(docTypes).map((docType) => (\n <LegendRow\n key={docType}\n className={'legend__row'}\n style={{color: getDocTypeColor(docType).fill}}\n >\n <LegendBadge theme={theme} />\n <div>{formatDocType(docType)}</div>\n </LegendRow>\n ))}\n </Legend>\n {hoverNode && <HoverNode theme={theme}>{labelFor(hoverNode.doc)}</HoverNode>}\n <ForceGraph2D\n graphData={graph.data}\n nodeAutoColorBy=\"group\"\n enableNodeDrag={false}\n onNodeHover={(node: any) => setHoverNode(node)}\n onNodeClick={(node: any) => {\n router.navigateIntent('edit', {id: node.doc._id, documentType: node.doc._type})\n }}\n linkColor={() => rgba(gray[500].hex, 0.25)}\n nodeLabel={() => ''}\n nodeRelSize={1}\n nodeVal={(node: any) => valueFor(node.doc, maxSize)}\n onRenderFramePost={(ctx, globalScale) => {\n for (const session of graph.sessions) {\n const node = graph.data.nodes.find(\n (n: any) => n.doc && n.doc._id === session?.doc?._id,\n )\n if (node) {\n const idleFactorRange = idleTimeout\n const angle = session.angle\n const radius = Math.sqrt(valueFor(node.doc, maxSize))\n const image = session.user.image\n const userColor = userColorManager.get(session.user.displayName).tints[400].hex\n const distance = radius * globalScale + 40\n const imgW = image ? image.width : 0\n const imgH = image ? image.height : 0\n const x = node.x + (Math.sin(angle) * distance) / globalScale\n const y = node.y + (Math.cos(angle) * distance) / globalScale\n\n ctx.save()\n // oxlint-disable-next-line react/todo\n try {\n ctx.globalAlpha = fadeEasing(\n 1 -\n Math.min(idleFactorRange, Date.now() - session.lastActive) / idleFactorRange,\n )\n ctx.font = `bold ${Math.round(12 / globalScale)}px sans-serif`\n\n ctx.beginPath()\n ctx.strokeStyle = rgba(white.hex, 1.0)\n ctx.lineWidth = 2 / globalScale\n ctx.moveTo(\n node.x + (Math.sin(angle) * (distance - imgW / 2)) / globalScale,\n node.y + (Math.cos(angle) * (distance - imgH / 2)) / globalScale,\n )\n ctx.lineTo(node.x + Math.sin(angle) * radius, node.y + Math.cos(angle) * radius)\n ctx.stroke()\n\n ctx.beginPath()\n ctx.strokeStyle = rgba(white.hex, 1.0)\n ctx.lineWidth = 2 / globalScale\n ctx.arc(node.x, node.y, radius, 0, 2 * Math.PI, false)\n ctx.stroke()\n\n if (image) {\n ctx.save()\n try {\n const dur = 700\n const f = softEasing(\n Math.max(0, (dur - (Date.now() - session.startTime)) / dur),\n )\n if (f > 0) {\n ctx.beginPath()\n ctx.fillStyle = rgba(userColor, f)\n ctx.arc(x, y, (imgW / 2 + 10) / globalScale, 0, 2 * Math.PI, false)\n ctx.fill()\n }\n\n ctx.beginPath()\n ctx.fillStyle = rgba(white.hex, 1.0)\n ctx.arc(x, y, imgW / globalScale / 2, 0, 2 * Math.PI, false)\n ctx.clip()\n\n ctx.drawImage(\n image,\n x - imgW / globalScale / 2,\n y - imgH / globalScale / 2,\n imgW / globalScale,\n imgH / globalScale,\n )\n\n ctx.strokeStyle = black.hex\n ctx.lineWidth = 6 / globalScale\n ctx.stroke()\n\n ctx.strokeStyle = userColor\n ctx.lineWidth = 4 / globalScale\n ctx.stroke()\n } finally {\n ctx.restore()\n }\n }\n\n ctx.beginPath()\n ctx.strokeStyle = rgba(black.hex, 1)\n ctx.lineWidth = 0.5 / globalScale\n ctx.arc(x, y, imgW / globalScale / 2, 0, 2 * Math.PI, false)\n ctx.stroke()\n\n const above = angle >= Math.PI / 2 && angle < Math.PI * 1.5\n const textY = above\n ? y - (imgH / 2 + 5) / globalScale\n : y + (imgH / 2 + 5) / globalScale\n ctx.fillStyle = rgba(white.hex, 1.0)\n ctx.textAlign = 'center'\n ctx.textBaseline = above ? 'bottom' : 'top'\n ctx.fillText(session.user.displayName, x, textY)\n } finally {\n ctx.restore()\n }\n }\n }\n }}\n nodeCanvasObject={(node: any, ctx, globalScale) => {\n switch (node.type) {\n case 'document': {\n const nodeColor = getDocTypeColor(node.doc._type)\n const radius = Math.sqrt(valueFor(node.doc, maxSize))\n const fontSize = Math.min(100, 10.0 / globalScale)\n\n ctx.beginPath()\n ctx.fillStyle =\n hoverNode !== null && node.doc._id === hoverNode.doc._id\n ? rgba(gray[500].hex, 0.8)\n : nodeColor.fill\n ctx.strokeStyle = nodeColor.border\n ctx.lineWidth = 0.5\n ctx.arc(node.x, node.y, radius, 0, 2 * Math.PI, false)\n ctx.stroke()\n ctx.fill()\n\n if (radius * globalScale > 10) {\n ctx.font = `${fontSize}px sans-serif`\n const w = radius * 2 + 30 / globalScale\n for (let len = 50; len >= 5; len /= 1.2) {\n const label = truncate(labelFor(node.doc), Math.round(len))\n const textMetrics = ctx.measureText(label)\n if (textMetrics.width < w) {\n // ctx.fillStyle = rgba(color.white.hex, 1.0)\n ctx.textAlign = 'center'\n ctx.textBaseline = 'top'\n\n ctx.strokeStyle = rgba(black.hex, 0.5)\n ctx.lineWidth = 2 / globalScale\n ctx.strokeText(label, node.x, node.y + radius + 5 / globalScale)\n\n ctx.fillText(label, node.x, node.y + radius + 5 / globalScale)\n break\n }\n }\n }\n }\n }\n }}\n linkCanvasObject={(link: any, ctx, globalScale) => {\n ctx.beginPath()\n ctx.strokeStyle = rgba(gray[500].hex, 0.125)\n ctx.lineWidth = 2 / globalScale\n ctx.moveTo(link.source.x, link.source.y)\n ctx.lineTo(link.target.x, link.target.y)\n ctx.stroke()\n }}\n />\n </GraphRoot>\n </GraphWrapper>\n )\n}\n\nconst colorCache: Record<string, {fill: string; border: string}> = {}\nlet typeColorNum = 0\n\nfunction getDocTypeColor(docType: any) {\n if (colorCache[docType]) {\n return colorCache[docType]\n }\n\n const hue = COLOR_HUES[typeColorNum % COLOR_HUES.length]\n\n typeColorNum += 1\n\n colorCache[docType] = {\n fill: hues[hue][400].hex,\n border: rgba(black.hex, 0.5),\n }\n\n return colorCache[docType]\n}\n"],"mappings":"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"}
\ No newline at end of file