sanity-plugin-graph-view 3.2.2 → 3.2.4
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/README.md +5 -7
- package/dist/_chunks-cjs/GraphView.cjs +27 -53
- package/dist/_chunks-cjs/GraphView.cjs.map +1 -1
- package/dist/_chunks-es/GraphView.js +27 -53
- package/dist/_chunks-es/GraphView.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
<p><img src="assets/screengrab.gif" width="540" alt="Screengrab of the Graph tool" /></p>
|
|
5
5
|
</div>
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
Wonder how a visualization of your dataset will look? How many authors do you have? How many items have they worked on? And are currently working on! Edits and changes are shown in real-time!
|
|
9
8
|
|
|
10
9
|
**Explore your data with this plugin, seek out strange corners and data types, boldly go where you could not before!**
|
|
@@ -15,7 +14,6 @@ Wonder how a visualization of your dataset will look? How many authors do you ha
|
|
|
15
14
|
npm install --save sanity-plugin-graph-view
|
|
16
15
|
```
|
|
17
16
|
|
|
18
|
-
|
|
19
17
|
## Usage
|
|
20
18
|
|
|
21
19
|
Add it as a plugin in sanity.config.ts (or .js):
|
|
@@ -27,18 +25,19 @@ export default defineConfig({
|
|
|
27
25
|
// ...
|
|
28
26
|
plugins: [
|
|
29
27
|
contentGraphView({}),
|
|
30
|
-
]
|
|
28
|
+
]
|
|
31
29
|
})
|
|
32
30
|
```
|
|
33
31
|
|
|
34
32
|
This will add a /graph-your-content tools to the Sanity Studio, configured with this default query:
|
|
33
|
+
|
|
35
34
|
```
|
|
36
35
|
*[
|
|
37
36
|
!(_id in path("_.*")) &&
|
|
38
37
|
!(_type match "system.*") &&
|
|
39
38
|
!(_type match "sanity.*")
|
|
40
39
|
]
|
|
41
|
-
|
|
40
|
+
```
|
|
42
41
|
|
|
43
42
|
## Configuration
|
|
44
43
|
|
|
@@ -54,11 +53,11 @@ export default defineConfig({
|
|
|
54
53
|
"query": "*[_type in ['a', 'b']]",
|
|
55
54
|
apiVersion: "2022-09-01" // optional, default shown
|
|
56
55
|
}),
|
|
57
|
-
]
|
|
56
|
+
]
|
|
58
57
|
})
|
|
59
58
|
```
|
|
60
59
|
|
|
61
|
-
For references to turn into graph edges, the entire document must be fetched,
|
|
60
|
+
For references to turn into graph edges, the entire document must be fetched,
|
|
62
61
|
but you can also selectively filter what references will be included. For example:
|
|
63
62
|
|
|
64
63
|
```js
|
|
@@ -71,7 +70,6 @@ By default, the plugin uses `doc.title || doc.name || doc._id` as the node label
|
|
|
71
70
|
|
|
72
71
|
If you want to use another property, compute a `title` property in your query, e.g.:
|
|
73
72
|
|
|
74
|
-
|
|
75
73
|
```js
|
|
76
74
|
contentGraphView({
|
|
77
75
|
"query": "*[_type in ['a', 'b']] { ..., \"title\": select(_type == 'a' => 'Title A', _type == 'b' => 'Title B') }"
|
|
@@ -4,67 +4,41 @@ function _interopDefaultCompat(e) {
|
|
|
4
4
|
return e && typeof e == "object" && "default" in e ? e : { default: e };
|
|
5
5
|
}
|
|
6
6
|
var BezierEasing__default = /* @__PURE__ */ _interopDefaultCompat(BezierEasing), deepEqual__default = /* @__PURE__ */ _interopDefaultCompat(deepEqual);
|
|
7
|
-
const GraphRoot = styledComponents.styled.div
|
|
8
|
-
|
|
7
|
+
const GraphRoot = styledComponents.styled.div.withConfig({
|
|
8
|
+
displayName: "GraphRoot",
|
|
9
|
+
componentId: "sc-vxc9wk-0"
|
|
10
|
+
})`font-family:${({
|
|
9
11
|
theme
|
|
10
|
-
}) => theme.fonts.text.family};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
`, GraphWrapper = styledComponents.styled.div`
|
|
18
|
-
position: relative;
|
|
19
|
-
width: 100%;
|
|
20
|
-
height: 100%;
|
|
21
|
-
`, HoverNode = styledComponents.styled.div`
|
|
22
|
-
font-family: ${({
|
|
12
|
+
}) => theme.fonts.text.family};position:absolute;top:0;left:0;width:100%;height:100%;background:${color.black.hex};`, GraphWrapper = styledComponents.styled.div.withConfig({
|
|
13
|
+
displayName: "GraphWrapper",
|
|
14
|
+
componentId: "sc-vxc9wk-1"
|
|
15
|
+
})`position:relative;width:100%;height:100%;`, HoverNode = styledComponents.styled.div.withConfig({
|
|
16
|
+
displayName: "HoverNode",
|
|
17
|
+
componentId: "sc-vxc9wk-2"
|
|
18
|
+
})`font-family:${({
|
|
23
19
|
theme
|
|
24
|
-
}) => theme.fonts.text.family};
|
|
25
|
-
display: none;
|
|
26
|
-
position: absolute;
|
|
27
|
-
bottom: ${({
|
|
20
|
+
}) => theme.fonts.text.family};display:none;position:absolute;bottom:${({
|
|
28
21
|
theme
|
|
29
|
-
}) => theme.space[0]}px;
|
|
30
|
-
left: 50%;
|
|
31
|
-
transform: translate3d(-50%, 0, 0);
|
|
32
|
-
background: var(--component-bg);
|
|
33
|
-
border-radius: ${({
|
|
22
|
+
}) => theme.space[0]}px;left:50%;transform:translate3d(-50%,0,0);background:var(--component-bg);border-radius:${({
|
|
34
23
|
theme
|
|
35
|
-
}) => theme.radius[2]}px;
|
|
36
|
-
padding: ${({
|
|
24
|
+
}) => theme.radius[2]}px;padding:${({
|
|
37
25
|
theme
|
|
38
|
-
}) => theme.space[2]}px;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
display: none;
|
|
43
|
-
}
|
|
44
|
-
`, Legend = styledComponents.styled.div`
|
|
45
|
-
color: #ccc;
|
|
46
|
-
position: absolute;
|
|
47
|
-
top: ${({
|
|
26
|
+
}) => theme.space[2]}px;z-index:1000;&:empty{display:none;}`, Legend = styledComponents.styled.div.withConfig({
|
|
27
|
+
displayName: "Legend",
|
|
28
|
+
componentId: "sc-vxc9wk-3"
|
|
29
|
+
})`color:#ccc;position:absolute;top:${({
|
|
48
30
|
theme
|
|
49
|
-
}) => theme.space[4]}px;
|
|
50
|
-
left: ${({
|
|
31
|
+
}) => theme.space[4]}px;left:${({
|
|
51
32
|
theme
|
|
52
|
-
}) => theme.space[4]}px;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
`, LegendBadge = styledComponents.styled.div`
|
|
60
|
-
width: 1.25em;
|
|
61
|
-
height: 1.25em;
|
|
62
|
-
background: currentColor;
|
|
63
|
-
border-radius: 50%;
|
|
64
|
-
margin-right: ${({
|
|
33
|
+
}) => theme.space[4]}px;& > div{margin:5px 0;}`, LegendRow = styledComponents.styled.div.withConfig({
|
|
34
|
+
displayName: "LegendRow",
|
|
35
|
+
componentId: "sc-vxc9wk-4"
|
|
36
|
+
})`display:flex;`, LegendBadge = styledComponents.styled.div.withConfig({
|
|
37
|
+
displayName: "LegendBadge",
|
|
38
|
+
componentId: "sc-vxc9wk-5"
|
|
39
|
+
})`width:1.25em;height:1.25em;background:currentColor;border-radius:50%;margin-right:${({
|
|
65
40
|
theme
|
|
66
|
-
}) => theme.space[2]}px
|
|
67
|
-
`;
|
|
41
|
+
}) => theme.space[2]}px;`;
|
|
68
42
|
function sizeOf(value) {
|
|
69
43
|
return value === null ? 0 : typeof value == "object" ? Object.entries(value).reduce((total, [k, v]) => total + sizeOf(k) + sizeOf(v), 0) : Array.isArray(value) ? Object.entries(value).reduce((total, v) => total + sizeOf(v), 0) : typeof value == "string" ? value.length : 1;
|
|
70
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphView.cjs","sources":["../../src/tool/GraphViewStyle.tsx","../../src/tool/utils.ts","../../src/tool/GraphView.tsx"],"sourcesContent":["import type {Theme} from '@sanity/ui'\n\nimport {black} from '@sanity/color'\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`\n font-family: ${({theme}: Style) => 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` as React.FC<Style>\n\nexport const HoverNode: React.FC<Style> = styled.div`\n font-family: ${({theme}: Style) => theme.fonts.text.family};\n display: none;\n position: absolute;\n bottom: ${({theme}: Style) => theme.space[0]}px;\n left: 50%;\n transform: translate3d(-50%, 0, 0);\n background: var(--component-bg);\n border-radius: ${({theme}: Style) => theme.radius[2]}px;\n padding: ${({theme}: Style) => 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`\n color: #ccc;\n position: absolute;\n top: ${({theme}: Style) => theme.space[4]}px;\n left: ${({theme}: Style) => 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`\n width: 1.25em;\n height: 1.25em;\n background: currentColor;\n border-radius: 50%;\n margin-right: ${({theme}: Style) => 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 img.onload = () => {\n resolve(img)\n }\n img.onerror = (event) => {\n console.log('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'\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 })\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 className={'legend__row'}\n key={docType}\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 // eslint-disable-next-line react-hooks/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"],"names":["GraphRoot","styled","div","theme","fonts","text","family","black","hex","GraphWrapper","HoverNode","space","radius","Legend","LegendRow","LegendBadge","sizeOf","value","Object","entries","reduce","total","k","v","Array","isArray","length","loadImage","url","w","h","Promise","resolve","img","Image","onload","onerror","event","console","log","src","sortBy","array","f","sort","a","b","va","vb","truncate","s","limit","substring","DEFAULT_QUERY","fadeEasing","BezierEasing","softEasing","idleTimeout","imageSize","getTopDocTypes","counts","keys","docType","reverse","slice","formatDocType","toUpperCase","replace","trim","getDocTypeCounts","docs","types","doc","_type","labelFor","title","name","_id","valueFor","maxSize","findRefs","obj","dest","push","stripDraftId","id","deduplicateDrafts","deduped","startsWith","assign","values","Users","_users","getById","client","user","find","u","users","image","imageUrl","Session","lastActive","startTime","angle","GraphData","sessions","constructor","docsById","data","nodes","map","d","type","links","flatMap","ref","source","target","filter","link","setSession","docNode","session","uuidv4","Date","now","Math","random","PI","reapSessions","i","clone","copy","GraphView","tool","options","props","query","apiVersion","userColorManager","useUserColorManager","setMaxSize","useState","hoverNode","setHoverNode","documents","setDocuments","docTypes","setDocTypes","graph","setGraph","router","useRouter","useClient","useEffect","fetch","then","_docs","max","subscription","listen","subscribe","update","result","oldDoc","idx","findIndex","newGraph","oldRefs","newRefs","graphChanged","deepEqual","l","concat","nodeIdx","n","identity","transition","docId","documentId","unsubscribe","interval","setInterval","clearInterval","useTheme","sanity","jsx","jsxs","color","getDocTypeColor","fill","ForceGraph2D","node","navigateIntent","documentType","rgba","gray","ctx","globalScale","idleFactorRange","sqrt","userColor","get","displayName","tints","distance","imgW","width","imgH","height","x","sin","y","cos","save","globalAlpha","min","font","round","beginPath","strokeStyle","white","lineWidth","moveTo","lineTo","stroke","arc","dur","fillStyle","clip","drawImage","restore","above","textY","textAlign","textBaseline","fillText","nodeColor","fontSize","border","len","label","measureText","strokeText","colorCache","typeColorNum","hue","COLOR_HUES","hues"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GraphView.cjs","sources":["../../src/tool/GraphViewStyle.tsx","../../src/tool/utils.ts","../../src/tool/GraphView.tsx"],"sourcesContent":["import type {Theme} from '@sanity/ui'\n\nimport {black} from '@sanity/color'\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`\n font-family: ${({theme}: Style) => 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` as React.FC<Style>\n\nexport const HoverNode: React.FC<Style> = styled.div`\n font-family: ${({theme}: Style) => theme.fonts.text.family};\n display: none;\n position: absolute;\n bottom: ${({theme}: Style) => theme.space[0]}px;\n left: 50%;\n transform: translate3d(-50%, 0, 0);\n background: var(--component-bg);\n border-radius: ${({theme}: Style) => theme.radius[2]}px;\n padding: ${({theme}: Style) => 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`\n color: #ccc;\n position: absolute;\n top: ${({theme}: Style) => theme.space[4]}px;\n left: ${({theme}: Style) => 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`\n width: 1.25em;\n height: 1.25em;\n background: currentColor;\n border-radius: 50%;\n margin-right: ${({theme}: Style) => 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 img.onload = () => {\n resolve(img)\n }\n img.onerror = (event) => {\n console.log('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'\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 })\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 className={'legend__row'}\n key={docType}\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 // eslint-disable-next-line react-hooks/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"],"names":["GraphRoot","styled","div","withConfig","displayName","componentId","theme","fonts","text","family","black","hex","GraphWrapper","HoverNode","space","radius","Legend","LegendRow","LegendBadge","sizeOf","value","Object","entries","reduce","total","k","v","Array","isArray","length","loadImage","url","w","h","Promise","resolve","img","Image","onload","onerror","event","console","log","src","sortBy","array","f","sort","a","b","va","vb","truncate","s","limit","substring","DEFAULT_QUERY","fadeEasing","BezierEasing","softEasing","idleTimeout","imageSize","getTopDocTypes","counts","keys","docType","reverse","slice","formatDocType","toUpperCase","replace","trim","getDocTypeCounts","docs","types","doc","_type","labelFor","title","name","_id","valueFor","maxSize","findRefs","obj","dest","push","stripDraftId","id","deduplicateDrafts","deduped","startsWith","assign","values","Users","_users","getById","client","user","find","u","users","image","imageUrl","Session","lastActive","startTime","angle","GraphData","sessions","constructor","docsById","data","nodes","map","d","type","links","flatMap","ref","source","target","filter","link","setSession","docNode","session","uuidv4","Date","now","Math","random","PI","reapSessions","i","clone","copy","GraphView","tool","options","props","query","apiVersion","userColorManager","useUserColorManager","setMaxSize","useState","hoverNode","setHoverNode","documents","setDocuments","docTypes","setDocTypes","graph","setGraph","router","useRouter","useClient","useEffect","fetch","then","_docs","max","subscription","listen","subscribe","update","result","oldDoc","idx","findIndex","newGraph","oldRefs","newRefs","graphChanged","deepEqual","l","concat","nodeIdx","n","identity","transition","docId","documentId","unsubscribe","interval","setInterval","clearInterval","useTheme","sanity","jsx","jsxs","color","getDocTypeColor","fill","ForceGraph2D","node","navigateIntent","documentType","rgba","gray","ctx","globalScale","idleFactorRange","sqrt","userColor","get","tints","distance","imgW","width","imgH","height","x","sin","y","cos","save","globalAlpha","min","font","round","beginPath","strokeStyle","white","lineWidth","moveTo","lineTo","stroke","arc","dur","fillStyle","clip","drawImage","restore","above","textY","textAlign","textBaseline","fillText","nodeColor","fontSize","border","len","label","measureText","strokeText","colorCache","typeColorNum","hue","COLOR_HUES","hues"],"mappings":"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"}
|
|
@@ -10,67 +10,41 @@ import { useUserColorManager, useClient } from "sanity";
|
|
|
10
10
|
import { useRouter } from "sanity/router";
|
|
11
11
|
import { v4 } from "uuid";
|
|
12
12
|
import { styled } from "styled-components";
|
|
13
|
-
const GraphRoot = styled.div
|
|
14
|
-
|
|
13
|
+
const GraphRoot = styled.div.withConfig({
|
|
14
|
+
displayName: "GraphRoot",
|
|
15
|
+
componentId: "sc-vxc9wk-0"
|
|
16
|
+
})`font-family:${({
|
|
15
17
|
theme
|
|
16
|
-
}) => theme.fonts.text.family};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
`, GraphWrapper = styled.div`
|
|
24
|
-
position: relative;
|
|
25
|
-
width: 100%;
|
|
26
|
-
height: 100%;
|
|
27
|
-
`, HoverNode = styled.div`
|
|
28
|
-
font-family: ${({
|
|
18
|
+
}) => theme.fonts.text.family};position:absolute;top:0;left:0;width:100%;height:100%;background:${black.hex};`, GraphWrapper = styled.div.withConfig({
|
|
19
|
+
displayName: "GraphWrapper",
|
|
20
|
+
componentId: "sc-vxc9wk-1"
|
|
21
|
+
})`position:relative;width:100%;height:100%;`, HoverNode = styled.div.withConfig({
|
|
22
|
+
displayName: "HoverNode",
|
|
23
|
+
componentId: "sc-vxc9wk-2"
|
|
24
|
+
})`font-family:${({
|
|
29
25
|
theme
|
|
30
|
-
}) => theme.fonts.text.family};
|
|
31
|
-
display: none;
|
|
32
|
-
position: absolute;
|
|
33
|
-
bottom: ${({
|
|
26
|
+
}) => theme.fonts.text.family};display:none;position:absolute;bottom:${({
|
|
34
27
|
theme
|
|
35
|
-
}) => theme.space[0]}px;
|
|
36
|
-
left: 50%;
|
|
37
|
-
transform: translate3d(-50%, 0, 0);
|
|
38
|
-
background: var(--component-bg);
|
|
39
|
-
border-radius: ${({
|
|
28
|
+
}) => theme.space[0]}px;left:50%;transform:translate3d(-50%,0,0);background:var(--component-bg);border-radius:${({
|
|
40
29
|
theme
|
|
41
|
-
}) => theme.radius[2]}px;
|
|
42
|
-
padding: ${({
|
|
30
|
+
}) => theme.radius[2]}px;padding:${({
|
|
43
31
|
theme
|
|
44
|
-
}) => theme.space[2]}px;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
display: none;
|
|
49
|
-
}
|
|
50
|
-
`, Legend = styled.div`
|
|
51
|
-
color: #ccc;
|
|
52
|
-
position: absolute;
|
|
53
|
-
top: ${({
|
|
32
|
+
}) => theme.space[2]}px;z-index:1000;&:empty{display:none;}`, Legend = styled.div.withConfig({
|
|
33
|
+
displayName: "Legend",
|
|
34
|
+
componentId: "sc-vxc9wk-3"
|
|
35
|
+
})`color:#ccc;position:absolute;top:${({
|
|
54
36
|
theme
|
|
55
|
-
}) => theme.space[4]}px;
|
|
56
|
-
left: ${({
|
|
37
|
+
}) => theme.space[4]}px;left:${({
|
|
57
38
|
theme
|
|
58
|
-
}) => theme.space[4]}px;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
`, LegendBadge = styled.div`
|
|
66
|
-
width: 1.25em;
|
|
67
|
-
height: 1.25em;
|
|
68
|
-
background: currentColor;
|
|
69
|
-
border-radius: 50%;
|
|
70
|
-
margin-right: ${({
|
|
39
|
+
}) => theme.space[4]}px;& > div{margin:5px 0;}`, LegendRow = styled.div.withConfig({
|
|
40
|
+
displayName: "LegendRow",
|
|
41
|
+
componentId: "sc-vxc9wk-4"
|
|
42
|
+
})`display:flex;`, LegendBadge = styled.div.withConfig({
|
|
43
|
+
displayName: "LegendBadge",
|
|
44
|
+
componentId: "sc-vxc9wk-5"
|
|
45
|
+
})`width:1.25em;height:1.25em;background:currentColor;border-radius:50%;margin-right:${({
|
|
71
46
|
theme
|
|
72
|
-
}) => theme.space[2]}px
|
|
73
|
-
`;
|
|
47
|
+
}) => theme.space[2]}px;`;
|
|
74
48
|
function sizeOf(value) {
|
|
75
49
|
return value === null ? 0 : typeof value == "object" ? Object.entries(value).reduce((total, [k, v]) => total + sizeOf(k) + sizeOf(v), 0) : Array.isArray(value) ? Object.entries(value).reduce((total, v) => total + sizeOf(v), 0) : typeof value == "string" ? value.length : 1;
|
|
76
50
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphView.js","sources":["../../src/tool/GraphViewStyle.tsx","../../src/tool/utils.ts","../../src/tool/GraphView.tsx"],"sourcesContent":["import type {Theme} from '@sanity/ui'\n\nimport {black} from '@sanity/color'\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`\n font-family: ${({theme}: Style) => 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` as React.FC<Style>\n\nexport const HoverNode: React.FC<Style> = styled.div`\n font-family: ${({theme}: Style) => theme.fonts.text.family};\n display: none;\n position: absolute;\n bottom: ${({theme}: Style) => theme.space[0]}px;\n left: 50%;\n transform: translate3d(-50%, 0, 0);\n background: var(--component-bg);\n border-radius: ${({theme}: Style) => theme.radius[2]}px;\n padding: ${({theme}: Style) => 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`\n color: #ccc;\n position: absolute;\n top: ${({theme}: Style) => theme.space[4]}px;\n left: ${({theme}: Style) => 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`\n width: 1.25em;\n height: 1.25em;\n background: currentColor;\n border-radius: 50%;\n margin-right: ${({theme}: Style) => 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 img.onload = () => {\n resolve(img)\n }\n img.onerror = (event) => {\n console.log('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'\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 })\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 className={'legend__row'}\n key={docType}\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 // eslint-disable-next-line react-hooks/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"],"names":["GraphRoot","styled","div","theme","fonts","text","family","black","hex","GraphWrapper","HoverNode","space","radius","Legend","LegendRow","LegendBadge","sizeOf","value","Object","entries","reduce","total","k","v","Array","isArray","length","loadImage","url","w","h","Promise","resolve","img","Image","onload","onerror","event","console","log","src","sortBy","array","f","sort","a","b","va","vb","truncate","s","limit","substring","DEFAULT_QUERY","fadeEasing","BezierEasing","softEasing","idleTimeout","imageSize","getTopDocTypes","counts","keys","docType","reverse","slice","formatDocType","toUpperCase","replace","trim","getDocTypeCounts","docs","types","doc","_type","labelFor","title","name","_id","valueFor","maxSize","findRefs","obj","dest","push","stripDraftId","id","deduplicateDrafts","deduped","startsWith","assign","values","Users","_users","getById","client","user","find","u","users","image","imageUrl","Session","lastActive","startTime","angle","GraphData","sessions","constructor","docsById","data","nodes","map","d","type","links","flatMap","ref","source","target","filter","link","setSession","docNode","session","uuidv4","Date","now","Math","random","PI","reapSessions","i","clone","copy","GraphView","tool","options","props","query","apiVersion","userColorManager","useUserColorManager","setMaxSize","useState","hoverNode","setHoverNode","documents","setDocuments","docTypes","setDocTypes","graph","setGraph","router","useRouter","useClient","useEffect","fetch","then","_docs","max","subscription","listen","subscribe","update","result","oldDoc","idx","findIndex","newGraph","oldRefs","newRefs","graphChanged","deepEqual","l","concat","nodeIdx","n","identity","transition","docId","documentId","unsubscribe","interval","setInterval","clearInterval","useTheme","sanity","color","getDocTypeColor","fill","node","navigateIntent","documentType","rgba","gray","ctx","globalScale","idleFactorRange","sqrt","userColor","get","displayName","tints","distance","imgW","width","imgH","height","x","sin","y","cos","save","globalAlpha","min","font","round","beginPath","strokeStyle","white","lineWidth","moveTo","lineTo","stroke","arc","dur","fillStyle","clip","drawImage","restore","above","textY","textAlign","textBaseline","fillText","nodeColor","fontSize","border","len","label","measureText","strokeText","colorCache","typeColorNum","hue","COLOR_HUES","hues"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GraphView.js","sources":["../../src/tool/GraphViewStyle.tsx","../../src/tool/utils.ts","../../src/tool/GraphView.tsx"],"sourcesContent":["import type {Theme} from '@sanity/ui'\n\nimport {black} from '@sanity/color'\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`\n font-family: ${({theme}: Style) => 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` as React.FC<Style>\n\nexport const HoverNode: React.FC<Style> = styled.div`\n font-family: ${({theme}: Style) => theme.fonts.text.family};\n display: none;\n position: absolute;\n bottom: ${({theme}: Style) => theme.space[0]}px;\n left: 50%;\n transform: translate3d(-50%, 0, 0);\n background: var(--component-bg);\n border-radius: ${({theme}: Style) => theme.radius[2]}px;\n padding: ${({theme}: Style) => 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`\n color: #ccc;\n position: absolute;\n top: ${({theme}: Style) => theme.space[4]}px;\n left: ${({theme}: Style) => 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`\n width: 1.25em;\n height: 1.25em;\n background: currentColor;\n border-radius: 50%;\n margin-right: ${({theme}: Style) => 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 img.onload = () => {\n resolve(img)\n }\n img.onerror = (event) => {\n console.log('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'\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 })\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 className={'legend__row'}\n key={docType}\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 // eslint-disable-next-line react-hooks/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"],"names":["GraphRoot","styled","div","withConfig","displayName","componentId","theme","fonts","text","family","black","hex","GraphWrapper","HoverNode","space","radius","Legend","LegendRow","LegendBadge","sizeOf","value","Object","entries","reduce","total","k","v","Array","isArray","length","loadImage","url","w","h","Promise","resolve","img","Image","onload","onerror","event","console","log","src","sortBy","array","f","sort","a","b","va","vb","truncate","s","limit","substring","DEFAULT_QUERY","fadeEasing","BezierEasing","softEasing","idleTimeout","imageSize","getTopDocTypes","counts","keys","docType","reverse","slice","formatDocType","toUpperCase","replace","trim","getDocTypeCounts","docs","types","doc","_type","labelFor","title","name","_id","valueFor","maxSize","findRefs","obj","dest","push","stripDraftId","id","deduplicateDrafts","deduped","startsWith","assign","values","Users","_users","getById","client","user","find","u","users","image","imageUrl","Session","lastActive","startTime","angle","GraphData","sessions","constructor","docsById","data","nodes","map","d","type","links","flatMap","ref","source","target","filter","link","setSession","docNode","session","uuidv4","Date","now","Math","random","PI","reapSessions","i","clone","copy","GraphView","tool","options","props","query","apiVersion","userColorManager","useUserColorManager","setMaxSize","useState","hoverNode","setHoverNode","documents","setDocuments","docTypes","setDocTypes","graph","setGraph","router","useRouter","useClient","useEffect","fetch","then","_docs","max","subscription","listen","subscribe","update","result","oldDoc","idx","findIndex","newGraph","oldRefs","newRefs","graphChanged","deepEqual","l","concat","nodeIdx","n","identity","transition","docId","documentId","unsubscribe","interval","setInterval","clearInterval","useTheme","sanity","color","getDocTypeColor","fill","node","navigateIntent","documentType","rgba","gray","ctx","globalScale","idleFactorRange","sqrt","userColor","get","tints","distance","imgW","width","imgH","height","x","sin","y","cos","save","globalAlpha","min","font","round","beginPath","strokeStyle","white","lineWidth","moveTo","lineTo","stroke","arc","dur","fillStyle","clip","drawImage","restore","above","textY","textAlign","textBaseline","fillText","nodeColor","fontSize","border","len","label","measureText","strokeText","colorCache","typeColorNum","hue","COLOR_HUES","hues"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,7 @@ var react = require("react"), sanity = require("sanity"), router = require("sani
|
|
|
4
4
|
function GraphViewIcon() {
|
|
5
5
|
const $ = reactCompilerRuntime.c(1);
|
|
6
6
|
let t0;
|
|
7
|
-
return $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 46.063 46.063", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fill: "currentColor", d: "M18.022 38.676v2.813h-1.21q-4.864 0-6.525-1.447-1.64-1.445-1.64-5.762v-4.666q0-2.95-1.055-4.083-1.055-1.13-3.828-1.13h-1.19v-2.794h1.19q2.793 0 3.828-1.114 1.055-1.132 1.055-4.043V11.76q0-4.316 1.64-5.742 1.66-1.446 6.524-1.446h1.212v2.793h-1.328q-2.754 0-3.594.86-.84.86-.84 3.613v4.844q0 3.066-.898 4.453-.88 1.387-3.028 1.875 2.168.527 3.047 1.914.88 1.387.88 4.434v4.843q0 2.754.84 3.614.84.86 3.594.86h1.328zM28.04 38.676h1.368q2.735 0 3.555-.84.84-.84.84-3.633V29.36q0-3.047.88-4.434.878-1.387 3.046-1.914-2.17-.488-3.048-1.875-.88-1.387-.88-4.453V11.84q0-2.773-.84-3.613-.82-.86-3.554-.86H28.04V4.574h1.232q4.863 0 6.484 1.446 1.64 1.426 1.64 5.742v4.687q0 2.91 1.055 4.042 1.056 1.114 3.83 1.114h1.21V24.4h-1.21q-2.774 0-3.83 1.13-1.053 1.134-1.053 4.084v4.667q0 4.318-1.64 5.763-1.622 1.446-6.485 1.446h-1.23v-2.814z" }) }), $[0] = t0) : t0 = $[0], t0;
|
|
7
|
+
return $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 46.063 46.063", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fill: "currentColor", d: "M18.022 38.676v2.813h-1.21q-4.864 0-6.525-1.447-1.64-1.445-1.64-5.762v-4.666q0-2.95-1.055-4.083-1.055-1.13-3.828-1.13h-1.19v-2.794h1.19q2.793 0 3.828-1.114 1.055-1.132 1.055-4.043V11.76q0-4.316 1.64-5.742 1.66-1.446 6.524-1.446h1.212v2.793h-1.328q-2.754 0-3.594.86-.84.86-.84 3.613v4.844q0 3.066-.898 4.453-.88 1.387-3.028 1.875 2.168.527 3.047 1.914.88 1.387.88 4.434v4.843q0 2.754.84 3.614.84.86 3.594.86h1.328zM28.04 38.676h1.368q2.735 0 3.555-.84.84-.84.84-3.633V29.36q0-3.047.88-4.434.878-1.387 3.046-1.914-2.17-.488-3.048-1.875-.88-1.387-.88-4.453V11.84q0-2.773-.84-3.613-.82-.86-3.554-.86H28.04V4.574h1.232q4.863 0 6.484 1.446 1.64 1.426 1.64 5.742v4.687q0 2.91 1.055 4.042 1.056 1.114 3.83 1.114h1.21V24.4h-1.21q-2.774 0-3.83 1.13-1.053 1.134-1.053 4.084v4.667q0 4.318-1.64 5.763-1.622 1.446-6.485 1.446h-1.23v-2.814z" }) }), $[0] = t0) : t0 = $[0], t0;
|
|
8
8
|
}
|
|
9
9
|
const GraphView = react.lazy(() => Promise.resolve().then(function() {
|
|
10
10
|
return require("./_chunks-cjs/GraphView.cjs");
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/tool/GraphViewIcon.tsx","../src/plugin.tsx"],"sourcesContent":["/**\n * Couple of things to note:\n * - width and height is set to 1em\n * - fill is `currentColor` - this will ensure that the icon looks uniform and\n * that the hover/active state works. You can of course render anything you\n * would like here, but for plugins that are to be used in more than one\n * studio, we suggest these rules are followed\n **/\nexport function GraphViewIcon(): React.JSX.Element {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 46.063 46.063\">\n <path\n fill=\"currentColor\"\n d=\"M18.022 38.676v2.813h-1.21q-4.864 0-6.525-1.447-1.64-1.445-1.64-5.762v-4.666q0-2.95-1.055-4.083-1.055-1.13-3.828-1.13h-1.19v-2.794h1.19q2.793 0 3.828-1.114 1.055-1.132 1.055-4.043V11.76q0-4.316 1.64-5.742 1.66-1.446 6.524-1.446h1.212v2.793h-1.328q-2.754 0-3.594.86-.84.86-.84 3.613v4.844q0 3.066-.898 4.453-.88 1.387-3.028 1.875 2.168.527 3.047 1.914.88 1.387.88 4.434v4.843q0 2.754.84 3.614.84.86 3.594.86h1.328zM28.04 38.676h1.368q2.735 0 3.555-.84.84-.84.84-3.633V29.36q0-3.047.88-4.434.878-1.387 3.046-1.914-2.17-.488-3.048-1.875-.88-1.387-.88-4.453V11.84q0-2.773-.84-3.613-.82-.86-3.554-.86H28.04V4.574h1.232q4.863 0 6.484 1.446 1.64 1.426 1.64 5.742v4.687q0 2.91 1.055 4.042 1.056 1.114 3.83 1.114h1.21V24.4h-1.21q-2.774 0-3.83 1.13-1.053 1.134-1.053 4.084v4.667q0 4.318-1.64 5.763-1.622 1.446-6.485 1.446h-1.23v-2.814z\"\n />\n </svg>\n )\n}\n","import {lazy} from 'react'\nimport {definePlugin} from 'sanity'\nimport {route} from 'sanity/router'\n\nimport {GraphViewIcon} from './tool/GraphViewIcon'\n\nexport interface GraphViewConfig {\n query?: string\n}\n\nconst GraphView = lazy(() => import('./tool/GraphView'))\n\nexport const contentGraphView = definePlugin<void | GraphViewConfig>(\n (config: GraphViewConfig = {}) => {\n return {\n name: '@sanity/content-graph-view',\n\n tools: [\n {\n name: 'graph-your-content',\n title: 'Graph',\n icon: GraphViewIcon,\n component: GraphView,\n options: config,\n router: route.create('/:selectedDocumentId'),\n },\n ],\n }\n },\n)\n"],"names":["GraphViewIcon","$","_c","t0","Symbol","for","jsx","GraphView","lazy","contentGraphView","definePlugin","config","name","tools","title","icon","component","options","router","route","create"],"mappings":";;;AAQO,SAAAA,gBAAA;AAAA,QAAAC,IAAAC,qBAAAA,EAAA,CAAA;AAAA,MAAAC;AAAA,SAAAF,EAAA,CAAA,MAAAG,
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/tool/GraphViewIcon.tsx","../src/plugin.tsx"],"sourcesContent":["/**\n * Couple of things to note:\n * - width and height is set to 1em\n * - fill is `currentColor` - this will ensure that the icon looks uniform and\n * that the hover/active state works. You can of course render anything you\n * would like here, but for plugins that are to be used in more than one\n * studio, we suggest these rules are followed\n **/\nexport function GraphViewIcon(): React.JSX.Element {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 46.063 46.063\">\n <path\n fill=\"currentColor\"\n d=\"M18.022 38.676v2.813h-1.21q-4.864 0-6.525-1.447-1.64-1.445-1.64-5.762v-4.666q0-2.95-1.055-4.083-1.055-1.13-3.828-1.13h-1.19v-2.794h1.19q2.793 0 3.828-1.114 1.055-1.132 1.055-4.043V11.76q0-4.316 1.64-5.742 1.66-1.446 6.524-1.446h1.212v2.793h-1.328q-2.754 0-3.594.86-.84.86-.84 3.613v4.844q0 3.066-.898 4.453-.88 1.387-3.028 1.875 2.168.527 3.047 1.914.88 1.387.88 4.434v4.843q0 2.754.84 3.614.84.86 3.594.86h1.328zM28.04 38.676h1.368q2.735 0 3.555-.84.84-.84.84-3.633V29.36q0-3.047.88-4.434.878-1.387 3.046-1.914-2.17-.488-3.048-1.875-.88-1.387-.88-4.453V11.84q0-2.773-.84-3.613-.82-.86-3.554-.86H28.04V4.574h1.232q4.863 0 6.484 1.446 1.64 1.426 1.64 5.742v4.687q0 2.91 1.055 4.042 1.056 1.114 3.83 1.114h1.21V24.4h-1.21q-2.774 0-3.83 1.13-1.053 1.134-1.053 4.084v4.667q0 4.318-1.64 5.763-1.622 1.446-6.485 1.446h-1.23v-2.814z\"\n />\n </svg>\n )\n}\n","import {lazy} from 'react'\nimport {definePlugin} from 'sanity'\nimport {route} from 'sanity/router'\n\nimport {GraphViewIcon} from './tool/GraphViewIcon'\n\nexport interface GraphViewConfig {\n query?: string\n}\n\nconst GraphView = lazy(() => import('./tool/GraphView'))\n\nexport const contentGraphView = definePlugin<void | GraphViewConfig>(\n (config: GraphViewConfig = {}) => {\n return {\n name: '@sanity/content-graph-view',\n\n tools: [\n {\n name: 'graph-your-content',\n title: 'Graph',\n icon: GraphViewIcon,\n component: GraphView,\n options: config,\n router: route.create('/:selectedDocumentId'),\n },\n ],\n }\n },\n)\n"],"names":["GraphViewIcon","$","_c","t0","Symbol","for","jsx","GraphView","lazy","contentGraphView","definePlugin","config","name","tools","title","icon","component","options","router","route","create"],"mappings":";;;AAQO,SAAAA,gBAAA;AAAA,QAAAC,IAAAC,qBAAAA,EAAA,CAAA;AAAA,MAAAC;AAAA,SAAAF,EAAA,CAAA,MAAAG,uBAAAC,IAAA,2BAAA,KAEHF,KAAAG,2BAAAA,IAAA,OAAA,EAAW,OAAA,8BAAmC,OAAA,OAAa,QAAA,OAAc,SAAA,qBACvE,UAAAA,2BAAAA,IAAA,QAAA,EACO,MAAA,gBACH,GAAA,4zBAAA,CAA2zB,EAAA,CAEj0B,GAAML,OAAAE,MAAAA,KAAAF,EAAA,CAAA,GALNE;AAKM;ACLV,MAAMI,YAAYC,MAAAA,KAAK,MAAM,QAAA,QAAA,EAAA,KAAA,WAAA;AAAA,SAAA,QAAO,6BAAkB;EAAC,GAE1CC,mBAAmBC,OAAAA,aAC9B,CAACC,SAA0B,QAClB;AAAA,EACLC,MAAM;AAAA,EAENC,OAAO,CACL;AAAA,IACED,MAAM;AAAA,IACNE,OAAO;AAAA,IACPC,MAAMf;AAAAA,IACNgB,WAAWT;AAAAA,IACXU,SAASN;AAAAA,IACTO,QAAQC,OAAAA,MAAMC,OAAO,sBAAsB;AAAA,EAAA,CAC5C;AAEL,EAEJ;;"}
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { c } from "react-compiler-runtime";
|
|
|
6
6
|
function GraphViewIcon() {
|
|
7
7
|
const $ = c(1);
|
|
8
8
|
let t0;
|
|
9
|
-
return $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 46.063 46.063", children: /* @__PURE__ */ jsx("path", { fill: "currentColor", d: "M18.022 38.676v2.813h-1.21q-4.864 0-6.525-1.447-1.64-1.445-1.64-5.762v-4.666q0-2.95-1.055-4.083-1.055-1.13-3.828-1.13h-1.19v-2.794h1.19q2.793 0 3.828-1.114 1.055-1.132 1.055-4.043V11.76q0-4.316 1.64-5.742 1.66-1.446 6.524-1.446h1.212v2.793h-1.328q-2.754 0-3.594.86-.84.86-.84 3.613v4.844q0 3.066-.898 4.453-.88 1.387-3.028 1.875 2.168.527 3.047 1.914.88 1.387.88 4.434v4.843q0 2.754.84 3.614.84.86 3.594.86h1.328zM28.04 38.676h1.368q2.735 0 3.555-.84.84-.84.84-3.633V29.36q0-3.047.88-4.434.878-1.387 3.046-1.914-2.17-.488-3.048-1.875-.88-1.387-.88-4.453V11.84q0-2.773-.84-3.613-.82-.86-3.554-.86H28.04V4.574h1.232q4.863 0 6.484 1.446 1.64 1.426 1.64 5.742v4.687q0 2.91 1.055 4.042 1.056 1.114 3.83 1.114h1.21V24.4h-1.21q-2.774 0-3.83 1.13-1.053 1.134-1.053 4.084v4.667q0 4.318-1.64 5.763-1.622 1.446-6.485 1.446h-1.23v-2.814z" }) }), $[0] = t0) : t0 = $[0], t0;
|
|
9
|
+
return $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 46.063 46.063", children: /* @__PURE__ */ jsx("path", { fill: "currentColor", d: "M18.022 38.676v2.813h-1.21q-4.864 0-6.525-1.447-1.64-1.445-1.64-5.762v-4.666q0-2.95-1.055-4.083-1.055-1.13-3.828-1.13h-1.19v-2.794h1.19q2.793 0 3.828-1.114 1.055-1.132 1.055-4.043V11.76q0-4.316 1.64-5.742 1.66-1.446 6.524-1.446h1.212v2.793h-1.328q-2.754 0-3.594.86-.84.86-.84 3.613v4.844q0 3.066-.898 4.453-.88 1.387-3.028 1.875 2.168.527 3.047 1.914.88 1.387.88 4.434v4.843q0 2.754.84 3.614.84.86 3.594.86h1.328zM28.04 38.676h1.368q2.735 0 3.555-.84.84-.84.84-3.633V29.36q0-3.047.88-4.434.878-1.387 3.046-1.914-2.17-.488-3.048-1.875-.88-1.387-.88-4.453V11.84q0-2.773-.84-3.613-.82-.86-3.554-.86H28.04V4.574h1.232q4.863 0 6.484 1.446 1.64 1.426 1.64 5.742v4.687q0 2.91 1.055 4.042 1.056 1.114 3.83 1.114h1.21V24.4h-1.21q-2.774 0-3.83 1.13-1.053 1.134-1.053 4.084v4.667q0 4.318-1.64 5.763-1.622 1.446-6.485 1.446h-1.23v-2.814z" }) }), $[0] = t0) : t0 = $[0], t0;
|
|
10
10
|
}
|
|
11
11
|
const GraphView = lazy(() => import("./_chunks-es/GraphView.js")), contentGraphView = definePlugin((config = {}) => ({
|
|
12
12
|
name: "@sanity/content-graph-view",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/tool/GraphViewIcon.tsx","../src/plugin.tsx"],"sourcesContent":["/**\n * Couple of things to note:\n * - width and height is set to 1em\n * - fill is `currentColor` - this will ensure that the icon looks uniform and\n * that the hover/active state works. You can of course render anything you\n * would like here, but for plugins that are to be used in more than one\n * studio, we suggest these rules are followed\n **/\nexport function GraphViewIcon(): React.JSX.Element {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 46.063 46.063\">\n <path\n fill=\"currentColor\"\n d=\"M18.022 38.676v2.813h-1.21q-4.864 0-6.525-1.447-1.64-1.445-1.64-5.762v-4.666q0-2.95-1.055-4.083-1.055-1.13-3.828-1.13h-1.19v-2.794h1.19q2.793 0 3.828-1.114 1.055-1.132 1.055-4.043V11.76q0-4.316 1.64-5.742 1.66-1.446 6.524-1.446h1.212v2.793h-1.328q-2.754 0-3.594.86-.84.86-.84 3.613v4.844q0 3.066-.898 4.453-.88 1.387-3.028 1.875 2.168.527 3.047 1.914.88 1.387.88 4.434v4.843q0 2.754.84 3.614.84.86 3.594.86h1.328zM28.04 38.676h1.368q2.735 0 3.555-.84.84-.84.84-3.633V29.36q0-3.047.88-4.434.878-1.387 3.046-1.914-2.17-.488-3.048-1.875-.88-1.387-.88-4.453V11.84q0-2.773-.84-3.613-.82-.86-3.554-.86H28.04V4.574h1.232q4.863 0 6.484 1.446 1.64 1.426 1.64 5.742v4.687q0 2.91 1.055 4.042 1.056 1.114 3.83 1.114h1.21V24.4h-1.21q-2.774 0-3.83 1.13-1.053 1.134-1.053 4.084v4.667q0 4.318-1.64 5.763-1.622 1.446-6.485 1.446h-1.23v-2.814z\"\n />\n </svg>\n )\n}\n","import {lazy} from 'react'\nimport {definePlugin} from 'sanity'\nimport {route} from 'sanity/router'\n\nimport {GraphViewIcon} from './tool/GraphViewIcon'\n\nexport interface GraphViewConfig {\n query?: string\n}\n\nconst GraphView = lazy(() => import('./tool/GraphView'))\n\nexport const contentGraphView = definePlugin<void | GraphViewConfig>(\n (config: GraphViewConfig = {}) => {\n return {\n name: '@sanity/content-graph-view',\n\n tools: [\n {\n name: 'graph-your-content',\n title: 'Graph',\n icon: GraphViewIcon,\n component: GraphView,\n options: config,\n router: route.create('/:selectedDocumentId'),\n },\n ],\n }\n },\n)\n"],"names":["GraphViewIcon","$","_c","t0","Symbol","for","GraphView","lazy","contentGraphView","definePlugin","config","name","tools","title","icon","component","options","router","route","create"],"mappings":";;;;;AAQO,SAAAA,gBAAA;AAAA,QAAAC,IAAAC,EAAA,CAAA;AAAA,MAAAC;AAAA,SAAAF,EAAA,CAAA,MAAAG,
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/tool/GraphViewIcon.tsx","../src/plugin.tsx"],"sourcesContent":["/**\n * Couple of things to note:\n * - width and height is set to 1em\n * - fill is `currentColor` - this will ensure that the icon looks uniform and\n * that the hover/active state works. You can of course render anything you\n * would like here, but for plugins that are to be used in more than one\n * studio, we suggest these rules are followed\n **/\nexport function GraphViewIcon(): React.JSX.Element {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 46.063 46.063\">\n <path\n fill=\"currentColor\"\n d=\"M18.022 38.676v2.813h-1.21q-4.864 0-6.525-1.447-1.64-1.445-1.64-5.762v-4.666q0-2.95-1.055-4.083-1.055-1.13-3.828-1.13h-1.19v-2.794h1.19q2.793 0 3.828-1.114 1.055-1.132 1.055-4.043V11.76q0-4.316 1.64-5.742 1.66-1.446 6.524-1.446h1.212v2.793h-1.328q-2.754 0-3.594.86-.84.86-.84 3.613v4.844q0 3.066-.898 4.453-.88 1.387-3.028 1.875 2.168.527 3.047 1.914.88 1.387.88 4.434v4.843q0 2.754.84 3.614.84.86 3.594.86h1.328zM28.04 38.676h1.368q2.735 0 3.555-.84.84-.84.84-3.633V29.36q0-3.047.88-4.434.878-1.387 3.046-1.914-2.17-.488-3.048-1.875-.88-1.387-.88-4.453V11.84q0-2.773-.84-3.613-.82-.86-3.554-.86H28.04V4.574h1.232q4.863 0 6.484 1.446 1.64 1.426 1.64 5.742v4.687q0 2.91 1.055 4.042 1.056 1.114 3.83 1.114h1.21V24.4h-1.21q-2.774 0-3.83 1.13-1.053 1.134-1.053 4.084v4.667q0 4.318-1.64 5.763-1.622 1.446-6.485 1.446h-1.23v-2.814z\"\n />\n </svg>\n )\n}\n","import {lazy} from 'react'\nimport {definePlugin} from 'sanity'\nimport {route} from 'sanity/router'\n\nimport {GraphViewIcon} from './tool/GraphViewIcon'\n\nexport interface GraphViewConfig {\n query?: string\n}\n\nconst GraphView = lazy(() => import('./tool/GraphView'))\n\nexport const contentGraphView = definePlugin<void | GraphViewConfig>(\n (config: GraphViewConfig = {}) => {\n return {\n name: '@sanity/content-graph-view',\n\n tools: [\n {\n name: 'graph-your-content',\n title: 'Graph',\n icon: GraphViewIcon,\n component: GraphView,\n options: config,\n router: route.create('/:selectedDocumentId'),\n },\n ],\n }\n },\n)\n"],"names":["GraphViewIcon","$","_c","t0","Symbol","for","GraphView","lazy","contentGraphView","definePlugin","config","name","tools","title","icon","component","options","router","route","create"],"mappings":";;;;;AAQO,SAAAA,gBAAA;AAAA,QAAAC,IAAAC,EAAA,CAAA;AAAA,MAAAC;AAAA,SAAAF,EAAA,CAAA,MAAAG,uBAAAC,IAAA,2BAAA,KAEHF,KAAA,oBAAA,OAAA,EAAW,OAAA,8BAAmC,OAAA,OAAa,QAAA,OAAc,SAAA,qBACvE,UAAA,oBAAA,QAAA,EACO,MAAA,gBACH,GAAA,4zBAAA,CAA2zB,EAAA,CAEj0B,GAAMF,OAAAE,MAAAA,KAAAF,EAAA,CAAA,GALNE;AAKM;ACLV,MAAMG,YAAYC,KAAK,MAAM,OAAO,2BAAkB,CAAC,GAE1CC,mBAAmBC,aAC9B,CAACC,SAA0B,QAClB;AAAA,EACLC,MAAM;AAAA,EAENC,OAAO,CACL;AAAA,IACED,MAAM;AAAA,IACNE,OAAO;AAAA,IACPC,MAAMd;AAAAA,IACNe,WAAWT;AAAAA,IACXU,SAASN;AAAAA,IACTO,QAAQC,MAAMC,OAAO,sBAAsB;AAAA,EAAA,CAC5C;AAEL,EAEJ;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sanity-plugin-graph-view",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"homepage": "https://github.com/sanity-io/plugins/tree/main/plugins/sanity-plugin-graph-view#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -37,23 +37,24 @@
|
|
|
37
37
|
"uuid": "^13.0.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@sanity/pkg-utils": "^10.
|
|
40
|
+
"@sanity/pkg-utils": "^10.1.2",
|
|
41
41
|
"@types/deep-equal": "^1.0.4",
|
|
42
42
|
"@types/react": "^19.2.7",
|
|
43
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
43
|
+
"@typescript/native-preview": "7.0.0-dev.20251205.1",
|
|
44
44
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
45
|
+
"babel-plugin-styled-components": "^2.1.4",
|
|
45
46
|
"eslint": "^9.39.1",
|
|
46
|
-
"react": "^19.2.
|
|
47
|
-
"sanity": "^4.20.
|
|
47
|
+
"react": "^19.2.1",
|
|
48
|
+
"sanity": "^4.20.3",
|
|
48
49
|
"styled-components": "^6.1.19",
|
|
49
50
|
"typescript": "5.9.3",
|
|
50
|
-
"@repo/eslint-config": "0.0.
|
|
51
|
+
"@repo/eslint-config": "0.0.5",
|
|
51
52
|
"@repo/package.config": "0.0.0",
|
|
52
53
|
"@repo/tsconfig": "1.0.0"
|
|
53
54
|
},
|
|
54
55
|
"peerDependencies": {
|
|
55
56
|
"react": "^18.3 || ^19",
|
|
56
|
-
"sanity": "^4",
|
|
57
|
+
"sanity": "^4.0.0-0 || ^5.0.0-0",
|
|
57
58
|
"styled-components": "^6.1"
|
|
58
59
|
},
|
|
59
60
|
"engines": {
|