note-graph
Advanced tools
Comparing version 0.0.2 to 0.0.3
@@ -5,2 +5,9 @@ # Changelog | ||
### [0.0.3](https://github.com/hikerpig/note-graph/compare/v0.0.2...v0.0.3) (2020-12-02) | ||
### Features | ||
* change default color theme and add a style editor in storybook ([7777d83](https://github.com/hikerpig/note-graph/commit/7777d83330078ed7aae303c046fc3e44c43832d3)) | ||
### [0.0.2](https://gitlab.com/hikerpig/note-graph/compare/v0.0.1...v0.0.2) (2020-12-02) | ||
@@ -7,0 +14,0 @@ |
@@ -5,1 +5,2 @@ export { NoteGraphModel } from './note-graph-model'; | ||
export * from './view'; | ||
export * from './theme'; |
@@ -1,2 +0,2 @@ | ||
import { forceX, forceY, forceCollide, rgb, scaleLinear, hsl } from 'd3'; | ||
import { rgb, forceX, forceY, forceCollide, hsl, scaleLinear } from 'd3'; | ||
import ForceGraph from 'force-graph'; | ||
@@ -147,2 +147,55 @@ | ||
function getColorOnContainer(container, name, fallback) { | ||
return getComputedStyle(container).getPropertyValue(name) || fallback; | ||
} | ||
function getDefaultColorOf(opts) { | ||
if (opts === void 0) { | ||
opts = {}; | ||
} | ||
var container = opts.container || document.body; | ||
var highlightedForeground = getColorOnContainer(container, '--notegraph-highlighted-foreground-color', '#f9c74f'); | ||
return { | ||
background: getColorOnContainer(container, "--notegraph-background", '#f7f7f7'), | ||
fontSize: parseInt(getColorOnContainer(container, "--notegraph-font-size", 12)), | ||
highlightedForeground: highlightedForeground, | ||
node: { | ||
note: { | ||
regular: getColorOnContainer(container, '--notegraph-note-color-regular', '#5f76e7') | ||
}, | ||
unknown: getColorOnContainer(container, '--notegraph-unkown-node-color', '#f94144') | ||
}, | ||
link: { | ||
regular: getColorOnContainer(container, '--notegraph-link-color-regular', '#ccc'), | ||
highlighted: getColorOnContainer(container, '--notegraph-link-color-highlighted', highlightedForeground) | ||
}, | ||
hoverNodeLink: { | ||
highlightedDirection: { | ||
inbound: '#3078cd', | ||
outbound: highlightedForeground | ||
} | ||
} | ||
}; | ||
} | ||
var makeDrawWrapper = function makeDrawWrapper(ctx) { | ||
return { | ||
circle: function circle(x, y, radius, color) { | ||
ctx.beginPath(); | ||
ctx.arc(x, y, radius, 0, 2 * Math.PI, false); | ||
ctx.fillStyle = color; | ||
ctx.fill(); | ||
ctx.closePath(); | ||
return this; | ||
}, | ||
text: function text(_text, x, y, size, color) { | ||
ctx.font = size + "px Sans-Serif"; | ||
ctx.textAlign = 'center'; | ||
ctx.textBaseline = 'top'; | ||
ctx.fillStyle = color; | ||
ctx.fillText(_text, x, y); | ||
return this; | ||
} | ||
}; | ||
}; | ||
/** | ||
@@ -153,2 +206,3 @@ * The view of the graph. | ||
var NoteGraphView = /*#__PURE__*/function () { | ||
@@ -173,2 +227,3 @@ function NoteGraphView(opts) { | ||
}; | ||
this.shouldDebugColor = false; | ||
this.options = opts; | ||
@@ -202,23 +257,5 @@ this.container = opts.container; | ||
if (!this.style) { | ||
var highlightedForeground = this.getColorOnContainer('--notegraph-highlighted-foreground-color', '#f9c74f'); | ||
this.style = { | ||
background: this.getColorOnContainer("--notegraph-background", '#f7f7f7'), | ||
fontSize: parseInt(this.getColorOnContainer("--notegraph-font-size", 12)), | ||
highlightedForeground: highlightedForeground, | ||
node: { | ||
note: { | ||
regular: this.getColorOnContainer('--notegraph-note-color-regular', '#277da1') | ||
}, | ||
unknown: this.getColorOnContainer('--notegraph-unkown-node-color', '#f94144') | ||
}, | ||
link: { | ||
regular: this.getColorOnContainer('--notegraph-link-color-regular', '#ccc'), | ||
highlighted: this.getColorOnContainer('--notegraph-link-color-highlighted', highlightedForeground) | ||
}, | ||
hoverNodeLink: { | ||
highlightedWithDirection: { | ||
inbound: '#3078cd' | ||
} | ||
} | ||
}; | ||
this.style = getDefaultColorOf({ | ||
container: this.container | ||
}); | ||
} | ||
@@ -232,88 +269,20 @@ | ||
this.initStyle(); | ||
if (this.forceGraph) { | ||
this.forceGraph.backgroundColor(this.style.background); | ||
} | ||
this.refreshByStyle(); | ||
}; | ||
_proto.linkWithGraphModel = function linkWithGraphModel(graphModel) { | ||
_proto.refreshByStyle = function refreshByStyle() { | ||
var _this = this; | ||
if (this.currentDataModelEntry) { | ||
this.currentDataModelEntry.unsub(); | ||
} | ||
this.updateViewData(graphModel.toGraphViewData()); | ||
var unsub = graphModel.subscribe(function () { | ||
_this.updateViewData(graphModel.toGraphViewData()); | ||
}); | ||
this.currentDataModelEntry = { | ||
graphModel: graphModel, | ||
unsub: unsub | ||
}; | ||
}; | ||
_proto.getColorOnContainer = function getColorOnContainer(name, fallback) { | ||
return getComputedStyle(this.container).getPropertyValue(name) || fallback; | ||
}; | ||
_proto.updateViewData = function updateViewData(dataInput) { | ||
Object.assign(this.model, dataInput); | ||
if (dataInput.focusedNode) { | ||
this.model.hoverNode = dataInput.focusedNode; | ||
} | ||
}; | ||
_proto.updateCanvasSize = function updateCanvasSize(size) { | ||
if (!this.forceGraph) return; | ||
if ('width' in size) { | ||
this.forceGraph.width(size.width); | ||
} | ||
var getNodeColor = function getNodeColor(nodeId, model) { | ||
var info = model.nodeInfos[nodeId]; | ||
var noteStyle = _this.style.node.note; | ||
var typeFill = _this.style.node.note[info.type || 'regular'] || _this.style.node.unknown; | ||
if ('height' in size) { | ||
this.forceGraph.height(size.height); | ||
} | ||
}; | ||
if (_this.shouldDebugColor) { | ||
console.log('node fill', typeFill); | ||
} | ||
_proto.initView = function initView() { | ||
var _this2 = this; | ||
var options = this.options, | ||
model = this.model, | ||
style = this.style, | ||
actions = this.actions; // this runtime dependency may not be ready when this umd file excutes, | ||
// so we will retrieve it from the global scope | ||
var forceGraphFactory = ForceGraph || globalThis.ForceGraph; | ||
var forceGraph = this.forceGraph || forceGraphFactory(); | ||
var makeDrawWrapper = function makeDrawWrapper(ctx) { | ||
return { | ||
circle: function circle(x, y, radius, color) { | ||
ctx.beginPath(); | ||
ctx.arc(x, y, radius, 0, 2 * Math.PI, false); | ||
ctx.fillStyle = color; | ||
ctx.fill(); | ||
ctx.closePath(); | ||
return this; | ||
}, | ||
text: function text(_text, x, y, size, color) { | ||
ctx.font = size + "px Sans-Serif"; | ||
ctx.textAlign = 'center'; | ||
ctx.textBaseline = 'top'; | ||
ctx.fillStyle = color; | ||
ctx.fillText(_text, x, y); | ||
return this; | ||
} | ||
}; | ||
}; | ||
function getNodeColor(nodeId, model) { | ||
var info = model.nodeInfos[nodeId]; | ||
var noteStyle = style.node.note; | ||
var typeFill = style.node[info.type || 'unknown']; | ||
switch (getNodeState(nodeId, model)) { | ||
switch (_this.getNodeState(nodeId, model)) { | ||
case 'regular': | ||
@@ -342,3 +311,3 @@ return { | ||
fill: typeFill, | ||
border: style.highlightedForeground | ||
border: _this.style.highlightedForeground | ||
}; | ||
@@ -349,57 +318,80 @@ | ||
} | ||
} | ||
}; | ||
function getLinkNodeId(v) { | ||
var t = typeof v; | ||
return t === 'string' || t === 'number' ? v : v.id; | ||
} | ||
this.forceGraph.backgroundColor(this.style.background).nodeCanvasObject(function (node, ctx, globalScale) { | ||
if (!node.id) return; | ||
var info = _this.model.nodeInfos[node.id]; | ||
function getLinkColor(link, model) { | ||
var linkStyle = style.link; | ||
var size = _this.sizeScaler(info.neighbors ? info.neighbors.length : 1); | ||
switch (getLinkState(link, model)) { | ||
case 'regular': | ||
return linkStyle.regular; | ||
var _getNodeColor = getNodeColor(node.id, _this.model), | ||
fill = _getNodeColor.fill, | ||
border = _getNodeColor.border; | ||
case 'highlighted': | ||
// inbound/outbound link is a little bit different with hoverNode | ||
var linkColorByDirection; | ||
var hoverNodeLinkStyle = style.hoverNodeLink; | ||
var fontSize = _this.style.fontSize / globalScale; | ||
var textColor = rgb(fill); | ||
if (model.hoverNode === getLinkNodeId(link.source)) { | ||
var _hoverNodeLinkStyle$h; | ||
var nodeState = _this.getNodeState(node.id, _this.model); | ||
linkColorByDirection = (_hoverNodeLinkStyle$h = hoverNodeLinkStyle.highlightedWithDirection) == null ? void 0 : _hoverNodeLinkStyle$h.outbound; | ||
} else if (model.hoverNode === getLinkNodeId(link.target)) { | ||
var _hoverNodeLinkStyle$h2; | ||
var alphaByDistance = _this.labelAlphaScaler(globalScale); | ||
linkColorByDirection = (_hoverNodeLinkStyle$h2 = hoverNodeLinkStyle.highlightedWithDirection) == null ? void 0 : _hoverNodeLinkStyle$h2.inbound; | ||
} | ||
textColor.opacity = nodeState === 'highlighted' ? 1 : nodeState === 'lessened' ? Math.min(0.2, alphaByDistance) : alphaByDistance; | ||
var label = info.title; | ||
makeDrawWrapper(ctx).circle(node.x, node.y, size + 0.5, border).circle(node.x, node.y, size, fill).text(label, node.x, node.y + size + 1, fontSize, textColor); | ||
}).linkColor(function (link) { | ||
return _this.getLinkColor(link, _this.model); | ||
}); | ||
}; | ||
return linkColorByDirection || linkStyle.highlighted || style.highlightedForeground; | ||
_proto.linkWithGraphModel = function linkWithGraphModel(graphModel) { | ||
var _this2 = this; | ||
case 'lessened': | ||
var color = linkStyle.lessened; | ||
if (this.currentDataModelEntry) { | ||
this.currentDataModelEntry.unsub(); | ||
} | ||
if (!color) { | ||
var c = hsl(style.node.note.lessened); | ||
c.opacity = 0.2; | ||
color = c; | ||
} | ||
this.updateViewData(graphModel.toGraphViewData()); | ||
var unsub = graphModel.subscribe(function () { | ||
_this2.updateViewData(graphModel.toGraphViewData()); | ||
}); | ||
this.currentDataModelEntry = { | ||
graphModel: graphModel, | ||
unsub: unsub | ||
}; | ||
}; | ||
return color; | ||
_proto.getColorOnContainer = function getColorOnContainer(name, fallback) { | ||
return getComputedStyle(this.container).getPropertyValue(name) || fallback; | ||
}; | ||
default: | ||
throw new Error("Unknown type for link " + link); | ||
} | ||
_proto.updateViewData = function updateViewData(dataInput) { | ||
Object.assign(this.model, dataInput); | ||
if (dataInput.focusedNode) { | ||
this.model.hoverNode = dataInput.focusedNode; | ||
} | ||
}; | ||
function getNodeState(nodeId, model) { | ||
return model.selectedNodes.has(nodeId) || model.hoverNode === nodeId ? 'highlighted' : model.focusNodes.size === 0 ? 'regular' : model.focusNodes.has(nodeId) ? 'regular' : 'lessened'; | ||
_proto.updateCanvasSize = function updateCanvasSize(size) { | ||
if (!this.forceGraph) return; | ||
if ('width' in size) { | ||
this.forceGraph.width(size.width); | ||
} | ||
function getLinkState(link, model) { | ||
return model.focusNodes.size === 0 ? 'regular' : model.focusLinks.has(link.id) ? 'highlighted' : 'lessened'; | ||
if ('height' in size) { | ||
this.forceGraph.height(size.height); | ||
} | ||
}; | ||
_proto.initView = function initView() { | ||
var _this3 = this; | ||
var options = this.options, | ||
model = this.model, | ||
actions = this.actions; // this runtime dependency may not be ready when this umd file excutes, | ||
// so we will retrieve it from the global scope | ||
var forceGraphFactory = ForceGraph || globalThis.ForceGraph; | ||
var forceGraph = this.forceGraph || forceGraphFactory(); | ||
var width = options.width || window.innerWidth - this.container.offsetLeft - 20; | ||
@@ -410,25 +402,4 @@ var height = options.height || window.innerHeight - this.container.offsetTop - 20; | ||
forceGraph(this.container).height(height).width(width).graphData(model.graphData).backgroundColor(style.background).linkHoverPrecision(8).enableNodeDrag(!!options.enableNodeDrag).cooldownTime(200).d3Force('x', forceX()).d3Force('y', forceY()).d3Force('collide', forceCollide(forceGraph.nodeRelSize())).linkWidth(1).linkDirectionalParticles(1).linkDirectionalParticleWidth(function (link) { | ||
return getLinkState(link, model) === 'highlighted' ? 2 : 0; | ||
}).nodeCanvasObject(function (node, ctx, globalScale) { | ||
if (!node.id) return; | ||
var info = _this2.model.nodeInfos[node.id]; | ||
var size = _this2.sizeScaler(info.neighbors ? info.neighbors.length : 1); | ||
var _getNodeColor = getNodeColor(node.id, model), | ||
fill = _getNodeColor.fill, | ||
border = _getNodeColor.border; | ||
var fontSize = style.fontSize / globalScale; | ||
var textColor = rgb(fill); | ||
var nodeState = getNodeState(node.id, model); | ||
var alphaByDistance = _this2.labelAlphaScaler(globalScale); | ||
textColor.opacity = nodeState === 'highlighted' ? 1 : nodeState === 'lessened' ? Math.min(0.2, alphaByDistance) : alphaByDistance; | ||
var label = info.title; | ||
makeDrawWrapper(ctx).circle(node.x, node.y, size + 0.5, border).circle(node.x, node.y, size, fill).text(label, node.x, node.y + size + 1, fontSize, textColor); | ||
}).linkColor(function (link) { | ||
return getLinkColor(link, _this2.model); | ||
forceGraph(this.container).height(height).width(width).graphData(model.graphData).linkHoverPrecision(8).enableNodeDrag(!!options.enableNodeDrag).cooldownTime(200).d3Force('x', forceX()).d3Force('y', forceY()).d3Force('collide', forceCollide(forceGraph.nodeRelSize())).linkWidth(1).linkDirectionalParticles(1).linkDirectionalParticleWidth(function (link) { | ||
return _this3.getLinkState(link, model) === 'highlighted' ? 2 : 0; | ||
}).onEngineStop(function () { | ||
@@ -440,11 +411,11 @@ if (!hasInitialZoomToFit) { | ||
}).onNodeHover(function (node) { | ||
actions.highlightNode(_this2.model, node == null ? void 0 : node.id); | ||
actions.highlightNode(_this3.model, node == null ? void 0 : node.id); | ||
_this2.updateViewModeInteractiveState(); | ||
_this3.updateViewModeInteractiveState(); | ||
}).onNodeClick(function (node, event) { | ||
actions.selectNode(_this2.model, node.id, event.getModifierState('Shift')); | ||
actions.selectNode(_this3.model, node.id, event.getModifierState('Shift')); | ||
_this2.updateViewModeInteractiveState(); | ||
_this3.updateViewModeInteractiveState(); | ||
_this2.fireInteraction('nodeClick', { | ||
_this3.fireInteraction('nodeClick', { | ||
node: node, | ||
@@ -454,3 +425,3 @@ event: event | ||
}).onLinkClick(function (link, event) { | ||
_this2.fireInteraction('linkClick', { | ||
_this3.fireInteraction('linkClick', { | ||
link: link, | ||
@@ -460,7 +431,7 @@ event: event | ||
}).onBackgroundClick(function (event) { | ||
actions.selectNode(_this2.model, null, event.getModifierState('Shift')); | ||
actions.selectNode(_this3.model, null, event.getModifierState('Shift')); | ||
_this2.updateViewModeInteractiveState(); | ||
_this3.updateViewModeInteractiveState(); | ||
_this2.fireInteraction('backgroundClick', { | ||
_this3.fireInteraction('backgroundClick', { | ||
event: event | ||
@@ -471,3 +442,3 @@ }); | ||
_this2.fireInteraction('backgroundRightClick', { | ||
_this3.fireInteraction('backgroundRightClick', { | ||
event: event | ||
@@ -477,4 +448,67 @@ }); | ||
this.forceGraph = forceGraph; | ||
this.refreshByStyle(); | ||
}; | ||
_proto.getLinkNodeId = function getLinkNodeId(v) { | ||
var t = typeof v; | ||
return t === 'string' || t === 'number' ? v : v.id; | ||
}; | ||
_proto.getNodeState = function getNodeState(nodeId, model) { | ||
if (model === void 0) { | ||
model = this.model; | ||
} | ||
return model.selectedNodes.has(nodeId) || model.hoverNode === nodeId ? 'highlighted' : model.focusNodes.size === 0 ? 'regular' : model.focusNodes.has(nodeId) ? 'regular' : 'lessened'; | ||
}; | ||
_proto.getLinkState = function getLinkState(link, model) { | ||
if (model === void 0) { | ||
model = this.model; | ||
} | ||
return model.focusNodes.size === 0 ? 'regular' : model.focusLinks.has(link.id) ? 'highlighted' : 'lessened'; | ||
}; | ||
_proto.getLinkColor = function getLinkColor(link, model) { | ||
var style = this.style; | ||
var linkStyle = style.link; | ||
switch (this.getLinkState(link, model)) { | ||
case 'regular': | ||
return linkStyle.regular; | ||
case 'highlighted': | ||
// inbound/outbound link is a little bit different with hoverNode | ||
var linkColorByDirection; | ||
var hoverNodeLinkStyle = style.hoverNodeLink; | ||
if (model.hoverNode === this.getLinkNodeId(link.source)) { | ||
var _hoverNodeLinkStyle$h; | ||
linkColorByDirection = (_hoverNodeLinkStyle$h = hoverNodeLinkStyle.highlightedDirection) == null ? void 0 : _hoverNodeLinkStyle$h.outbound; | ||
} else if (model.hoverNode === this.getLinkNodeId(link.target)) { | ||
var _hoverNodeLinkStyle$h2; | ||
linkColorByDirection = (_hoverNodeLinkStyle$h2 = hoverNodeLinkStyle.highlightedDirection) == null ? void 0 : _hoverNodeLinkStyle$h2.inbound; | ||
} | ||
return linkColorByDirection || linkStyle.highlighted || style.highlightedForeground; | ||
case 'lessened': | ||
var color = linkStyle.lessened; | ||
if (!color) { | ||
var c = hsl(style.node.note.lessened); | ||
c.opacity = 0.2; | ||
color = c; | ||
} | ||
return color; | ||
default: | ||
throw new Error("Unknown type for link " + link); | ||
} | ||
}; | ||
_proto.updateViewModeInteractiveState = function updateViewModeInteractiveState() { | ||
@@ -550,3 +584,3 @@ var model = this.model; // compute highlighted elements | ||
export { NoteGraphModel, NoteGraphView }; | ||
export { NoteGraphModel, NoteGraphView, getColorOnContainer, getDefaultColorOf }; | ||
//# sourceMappingURL=note-graph.esm.js.map |
@@ -149,2 +149,55 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | ||
function getColorOnContainer(container, name, fallback) { | ||
return getComputedStyle(container).getPropertyValue(name) || fallback; | ||
} | ||
function getDefaultColorOf(opts) { | ||
if (opts === void 0) { | ||
opts = {}; | ||
} | ||
var container = opts.container || document.body; | ||
var highlightedForeground = getColorOnContainer(container, '--notegraph-highlighted-foreground-color', '#f9c74f'); | ||
return { | ||
background: getColorOnContainer(container, "--notegraph-background", '#f7f7f7'), | ||
fontSize: parseInt(getColorOnContainer(container, "--notegraph-font-size", 12)), | ||
highlightedForeground: highlightedForeground, | ||
node: { | ||
note: { | ||
regular: getColorOnContainer(container, '--notegraph-note-color-regular', '#5f76e7') | ||
}, | ||
unknown: getColorOnContainer(container, '--notegraph-unkown-node-color', '#f94144') | ||
}, | ||
link: { | ||
regular: getColorOnContainer(container, '--notegraph-link-color-regular', '#ccc'), | ||
highlighted: getColorOnContainer(container, '--notegraph-link-color-highlighted', highlightedForeground) | ||
}, | ||
hoverNodeLink: { | ||
highlightedDirection: { | ||
inbound: '#3078cd', | ||
outbound: highlightedForeground | ||
} | ||
} | ||
}; | ||
} | ||
var makeDrawWrapper = function makeDrawWrapper(ctx) { | ||
return { | ||
circle: function circle(x, y, radius, color) { | ||
ctx.beginPath(); | ||
ctx.arc(x, y, radius, 0, 2 * Math.PI, false); | ||
ctx.fillStyle = color; | ||
ctx.fill(); | ||
ctx.closePath(); | ||
return this; | ||
}, | ||
text: function text(_text, x, y, size, color) { | ||
ctx.font = size + "px Sans-Serif"; | ||
ctx.textAlign = 'center'; | ||
ctx.textBaseline = 'top'; | ||
ctx.fillStyle = color; | ||
ctx.fillText(_text, x, y); | ||
return this; | ||
} | ||
}; | ||
}; | ||
/** | ||
@@ -155,2 +208,3 @@ * The view of the graph. | ||
var NoteGraphView = /*#__PURE__*/function () { | ||
@@ -175,2 +229,3 @@ function NoteGraphView(opts) { | ||
}; | ||
this.shouldDebugColor = false; | ||
this.options = opts; | ||
@@ -204,23 +259,5 @@ this.container = opts.container; | ||
if (!this.style) { | ||
var highlightedForeground = this.getColorOnContainer('--notegraph-highlighted-foreground-color', '#f9c74f'); | ||
this.style = { | ||
background: this.getColorOnContainer("--notegraph-background", '#f7f7f7'), | ||
fontSize: parseInt(this.getColorOnContainer("--notegraph-font-size", 12)), | ||
highlightedForeground: highlightedForeground, | ||
node: { | ||
note: { | ||
regular: this.getColorOnContainer('--notegraph-note-color-regular', '#277da1') | ||
}, | ||
unknown: this.getColorOnContainer('--notegraph-unkown-node-color', '#f94144') | ||
}, | ||
link: { | ||
regular: this.getColorOnContainer('--notegraph-link-color-regular', '#ccc'), | ||
highlighted: this.getColorOnContainer('--notegraph-link-color-highlighted', highlightedForeground) | ||
}, | ||
hoverNodeLink: { | ||
highlightedWithDirection: { | ||
inbound: '#3078cd' | ||
} | ||
} | ||
}; | ||
this.style = getDefaultColorOf({ | ||
container: this.container | ||
}); | ||
} | ||
@@ -234,88 +271,20 @@ | ||
this.initStyle(); | ||
if (this.forceGraph) { | ||
this.forceGraph.backgroundColor(this.style.background); | ||
} | ||
this.refreshByStyle(); | ||
}; | ||
_proto.linkWithGraphModel = function linkWithGraphModel(graphModel) { | ||
_proto.refreshByStyle = function refreshByStyle() { | ||
var _this = this; | ||
if (this.currentDataModelEntry) { | ||
this.currentDataModelEntry.unsub(); | ||
} | ||
this.updateViewData(graphModel.toGraphViewData()); | ||
var unsub = graphModel.subscribe(function () { | ||
_this.updateViewData(graphModel.toGraphViewData()); | ||
}); | ||
this.currentDataModelEntry = { | ||
graphModel: graphModel, | ||
unsub: unsub | ||
}; | ||
}; | ||
_proto.getColorOnContainer = function getColorOnContainer(name, fallback) { | ||
return getComputedStyle(this.container).getPropertyValue(name) || fallback; | ||
}; | ||
_proto.updateViewData = function updateViewData(dataInput) { | ||
Object.assign(this.model, dataInput); | ||
if (dataInput.focusedNode) { | ||
this.model.hoverNode = dataInput.focusedNode; | ||
} | ||
}; | ||
_proto.updateCanvasSize = function updateCanvasSize(size) { | ||
if (!this.forceGraph) return; | ||
if ('width' in size) { | ||
this.forceGraph.width(size.width); | ||
} | ||
var getNodeColor = function getNodeColor(nodeId, model) { | ||
var info = model.nodeInfos[nodeId]; | ||
var noteStyle = _this.style.node.note; | ||
var typeFill = _this.style.node.note[info.type || 'regular'] || _this.style.node.unknown; | ||
if ('height' in size) { | ||
this.forceGraph.height(size.height); | ||
} | ||
}; | ||
if (_this.shouldDebugColor) { | ||
console.log('node fill', typeFill); | ||
} | ||
_proto.initView = function initView() { | ||
var _this2 = this; | ||
var options = this.options, | ||
model = this.model, | ||
style = this.style, | ||
actions = this.actions; // this runtime dependency may not be ready when this umd file excutes, | ||
// so we will retrieve it from the global scope | ||
var forceGraphFactory = ForceGraph || globalThis.ForceGraph; | ||
var forceGraph = this.forceGraph || forceGraphFactory(); | ||
var makeDrawWrapper = function makeDrawWrapper(ctx) { | ||
return { | ||
circle: function circle(x, y, radius, color) { | ||
ctx.beginPath(); | ||
ctx.arc(x, y, radius, 0, 2 * Math.PI, false); | ||
ctx.fillStyle = color; | ||
ctx.fill(); | ||
ctx.closePath(); | ||
return this; | ||
}, | ||
text: function text(_text, x, y, size, color) { | ||
ctx.font = size + "px Sans-Serif"; | ||
ctx.textAlign = 'center'; | ||
ctx.textBaseline = 'top'; | ||
ctx.fillStyle = color; | ||
ctx.fillText(_text, x, y); | ||
return this; | ||
} | ||
}; | ||
}; | ||
function getNodeColor(nodeId, model) { | ||
var info = model.nodeInfos[nodeId]; | ||
var noteStyle = style.node.note; | ||
var typeFill = style.node[info.type || 'unknown']; | ||
switch (getNodeState(nodeId, model)) { | ||
switch (_this.getNodeState(nodeId, model)) { | ||
case 'regular': | ||
@@ -344,3 +313,3 @@ return { | ||
fill: typeFill, | ||
border: style.highlightedForeground | ||
border: _this.style.highlightedForeground | ||
}; | ||
@@ -351,57 +320,80 @@ | ||
} | ||
} | ||
}; | ||
function getLinkNodeId(v) { | ||
var t = typeof v; | ||
return t === 'string' || t === 'number' ? v : v.id; | ||
} | ||
this.forceGraph.backgroundColor(this.style.background).nodeCanvasObject(function (node, ctx, globalScale) { | ||
if (!node.id) return; | ||
var info = _this.model.nodeInfos[node.id]; | ||
function getLinkColor(link, model) { | ||
var linkStyle = style.link; | ||
var size = _this.sizeScaler(info.neighbors ? info.neighbors.length : 1); | ||
switch (getLinkState(link, model)) { | ||
case 'regular': | ||
return linkStyle.regular; | ||
var _getNodeColor = getNodeColor(node.id, _this.model), | ||
fill = _getNodeColor.fill, | ||
border = _getNodeColor.border; | ||
case 'highlighted': | ||
// inbound/outbound link is a little bit different with hoverNode | ||
var linkColorByDirection; | ||
var hoverNodeLinkStyle = style.hoverNodeLink; | ||
var fontSize = _this.style.fontSize / globalScale; | ||
var textColor = d3.rgb(fill); | ||
if (model.hoverNode === getLinkNodeId(link.source)) { | ||
var _hoverNodeLinkStyle$h; | ||
var nodeState = _this.getNodeState(node.id, _this.model); | ||
linkColorByDirection = (_hoverNodeLinkStyle$h = hoverNodeLinkStyle.highlightedWithDirection) == null ? void 0 : _hoverNodeLinkStyle$h.outbound; | ||
} else if (model.hoverNode === getLinkNodeId(link.target)) { | ||
var _hoverNodeLinkStyle$h2; | ||
var alphaByDistance = _this.labelAlphaScaler(globalScale); | ||
linkColorByDirection = (_hoverNodeLinkStyle$h2 = hoverNodeLinkStyle.highlightedWithDirection) == null ? void 0 : _hoverNodeLinkStyle$h2.inbound; | ||
} | ||
textColor.opacity = nodeState === 'highlighted' ? 1 : nodeState === 'lessened' ? Math.min(0.2, alphaByDistance) : alphaByDistance; | ||
var label = info.title; | ||
makeDrawWrapper(ctx).circle(node.x, node.y, size + 0.5, border).circle(node.x, node.y, size, fill).text(label, node.x, node.y + size + 1, fontSize, textColor); | ||
}).linkColor(function (link) { | ||
return _this.getLinkColor(link, _this.model); | ||
}); | ||
}; | ||
return linkColorByDirection || linkStyle.highlighted || style.highlightedForeground; | ||
_proto.linkWithGraphModel = function linkWithGraphModel(graphModel) { | ||
var _this2 = this; | ||
case 'lessened': | ||
var color = linkStyle.lessened; | ||
if (this.currentDataModelEntry) { | ||
this.currentDataModelEntry.unsub(); | ||
} | ||
if (!color) { | ||
var c = d3.hsl(style.node.note.lessened); | ||
c.opacity = 0.2; | ||
color = c; | ||
} | ||
this.updateViewData(graphModel.toGraphViewData()); | ||
var unsub = graphModel.subscribe(function () { | ||
_this2.updateViewData(graphModel.toGraphViewData()); | ||
}); | ||
this.currentDataModelEntry = { | ||
graphModel: graphModel, | ||
unsub: unsub | ||
}; | ||
}; | ||
return color; | ||
_proto.getColorOnContainer = function getColorOnContainer(name, fallback) { | ||
return getComputedStyle(this.container).getPropertyValue(name) || fallback; | ||
}; | ||
default: | ||
throw new Error("Unknown type for link " + link); | ||
} | ||
_proto.updateViewData = function updateViewData(dataInput) { | ||
Object.assign(this.model, dataInput); | ||
if (dataInput.focusedNode) { | ||
this.model.hoverNode = dataInput.focusedNode; | ||
} | ||
}; | ||
function getNodeState(nodeId, model) { | ||
return model.selectedNodes.has(nodeId) || model.hoverNode === nodeId ? 'highlighted' : model.focusNodes.size === 0 ? 'regular' : model.focusNodes.has(nodeId) ? 'regular' : 'lessened'; | ||
_proto.updateCanvasSize = function updateCanvasSize(size) { | ||
if (!this.forceGraph) return; | ||
if ('width' in size) { | ||
this.forceGraph.width(size.width); | ||
} | ||
function getLinkState(link, model) { | ||
return model.focusNodes.size === 0 ? 'regular' : model.focusLinks.has(link.id) ? 'highlighted' : 'lessened'; | ||
if ('height' in size) { | ||
this.forceGraph.height(size.height); | ||
} | ||
}; | ||
_proto.initView = function initView() { | ||
var _this3 = this; | ||
var options = this.options, | ||
model = this.model, | ||
actions = this.actions; // this runtime dependency may not be ready when this umd file excutes, | ||
// so we will retrieve it from the global scope | ||
var forceGraphFactory = ForceGraph || globalThis.ForceGraph; | ||
var forceGraph = this.forceGraph || forceGraphFactory(); | ||
var width = options.width || window.innerWidth - this.container.offsetLeft - 20; | ||
@@ -412,25 +404,4 @@ var height = options.height || window.innerHeight - this.container.offsetTop - 20; | ||
forceGraph(this.container).height(height).width(width).graphData(model.graphData).backgroundColor(style.background).linkHoverPrecision(8).enableNodeDrag(!!options.enableNodeDrag).cooldownTime(200).d3Force('x', d3.forceX()).d3Force('y', d3.forceY()).d3Force('collide', d3.forceCollide(forceGraph.nodeRelSize())).linkWidth(1).linkDirectionalParticles(1).linkDirectionalParticleWidth(function (link) { | ||
return getLinkState(link, model) === 'highlighted' ? 2 : 0; | ||
}).nodeCanvasObject(function (node, ctx, globalScale) { | ||
if (!node.id) return; | ||
var info = _this2.model.nodeInfos[node.id]; | ||
var size = _this2.sizeScaler(info.neighbors ? info.neighbors.length : 1); | ||
var _getNodeColor = getNodeColor(node.id, model), | ||
fill = _getNodeColor.fill, | ||
border = _getNodeColor.border; | ||
var fontSize = style.fontSize / globalScale; | ||
var textColor = d3.rgb(fill); | ||
var nodeState = getNodeState(node.id, model); | ||
var alphaByDistance = _this2.labelAlphaScaler(globalScale); | ||
textColor.opacity = nodeState === 'highlighted' ? 1 : nodeState === 'lessened' ? Math.min(0.2, alphaByDistance) : alphaByDistance; | ||
var label = info.title; | ||
makeDrawWrapper(ctx).circle(node.x, node.y, size + 0.5, border).circle(node.x, node.y, size, fill).text(label, node.x, node.y + size + 1, fontSize, textColor); | ||
}).linkColor(function (link) { | ||
return getLinkColor(link, _this2.model); | ||
forceGraph(this.container).height(height).width(width).graphData(model.graphData).linkHoverPrecision(8).enableNodeDrag(!!options.enableNodeDrag).cooldownTime(200).d3Force('x', d3.forceX()).d3Force('y', d3.forceY()).d3Force('collide', d3.forceCollide(forceGraph.nodeRelSize())).linkWidth(1).linkDirectionalParticles(1).linkDirectionalParticleWidth(function (link) { | ||
return _this3.getLinkState(link, model) === 'highlighted' ? 2 : 0; | ||
}).onEngineStop(function () { | ||
@@ -442,11 +413,11 @@ if (!hasInitialZoomToFit) { | ||
}).onNodeHover(function (node) { | ||
actions.highlightNode(_this2.model, node == null ? void 0 : node.id); | ||
actions.highlightNode(_this3.model, node == null ? void 0 : node.id); | ||
_this2.updateViewModeInteractiveState(); | ||
_this3.updateViewModeInteractiveState(); | ||
}).onNodeClick(function (node, event) { | ||
actions.selectNode(_this2.model, node.id, event.getModifierState('Shift')); | ||
actions.selectNode(_this3.model, node.id, event.getModifierState('Shift')); | ||
_this2.updateViewModeInteractiveState(); | ||
_this3.updateViewModeInteractiveState(); | ||
_this2.fireInteraction('nodeClick', { | ||
_this3.fireInteraction('nodeClick', { | ||
node: node, | ||
@@ -456,3 +427,3 @@ event: event | ||
}).onLinkClick(function (link, event) { | ||
_this2.fireInteraction('linkClick', { | ||
_this3.fireInteraction('linkClick', { | ||
link: link, | ||
@@ -462,7 +433,7 @@ event: event | ||
}).onBackgroundClick(function (event) { | ||
actions.selectNode(_this2.model, null, event.getModifierState('Shift')); | ||
actions.selectNode(_this3.model, null, event.getModifierState('Shift')); | ||
_this2.updateViewModeInteractiveState(); | ||
_this3.updateViewModeInteractiveState(); | ||
_this2.fireInteraction('backgroundClick', { | ||
_this3.fireInteraction('backgroundClick', { | ||
event: event | ||
@@ -473,3 +444,3 @@ }); | ||
_this2.fireInteraction('backgroundRightClick', { | ||
_this3.fireInteraction('backgroundRightClick', { | ||
event: event | ||
@@ -479,4 +450,67 @@ }); | ||
this.forceGraph = forceGraph; | ||
this.refreshByStyle(); | ||
}; | ||
_proto.getLinkNodeId = function getLinkNodeId(v) { | ||
var t = typeof v; | ||
return t === 'string' || t === 'number' ? v : v.id; | ||
}; | ||
_proto.getNodeState = function getNodeState(nodeId, model) { | ||
if (model === void 0) { | ||
model = this.model; | ||
} | ||
return model.selectedNodes.has(nodeId) || model.hoverNode === nodeId ? 'highlighted' : model.focusNodes.size === 0 ? 'regular' : model.focusNodes.has(nodeId) ? 'regular' : 'lessened'; | ||
}; | ||
_proto.getLinkState = function getLinkState(link, model) { | ||
if (model === void 0) { | ||
model = this.model; | ||
} | ||
return model.focusNodes.size === 0 ? 'regular' : model.focusLinks.has(link.id) ? 'highlighted' : 'lessened'; | ||
}; | ||
_proto.getLinkColor = function getLinkColor(link, model) { | ||
var style = this.style; | ||
var linkStyle = style.link; | ||
switch (this.getLinkState(link, model)) { | ||
case 'regular': | ||
return linkStyle.regular; | ||
case 'highlighted': | ||
// inbound/outbound link is a little bit different with hoverNode | ||
var linkColorByDirection; | ||
var hoverNodeLinkStyle = style.hoverNodeLink; | ||
if (model.hoverNode === this.getLinkNodeId(link.source)) { | ||
var _hoverNodeLinkStyle$h; | ||
linkColorByDirection = (_hoverNodeLinkStyle$h = hoverNodeLinkStyle.highlightedDirection) == null ? void 0 : _hoverNodeLinkStyle$h.outbound; | ||
} else if (model.hoverNode === this.getLinkNodeId(link.target)) { | ||
var _hoverNodeLinkStyle$h2; | ||
linkColorByDirection = (_hoverNodeLinkStyle$h2 = hoverNodeLinkStyle.highlightedDirection) == null ? void 0 : _hoverNodeLinkStyle$h2.inbound; | ||
} | ||
return linkColorByDirection || linkStyle.highlighted || style.highlightedForeground; | ||
case 'lessened': | ||
var color = linkStyle.lessened; | ||
if (!color) { | ||
var c = d3.hsl(style.node.note.lessened); | ||
c.opacity = 0.2; | ||
color = c; | ||
} | ||
return color; | ||
default: | ||
throw new Error("Unknown type for link " + link); | ||
} | ||
}; | ||
_proto.updateViewModeInteractiveState = function updateViewModeInteractiveState() { | ||
@@ -554,2 +588,4 @@ var model = this.model; // compute highlighted elements | ||
exports.NoteGraphView = NoteGraphView; | ||
exports.getColorOnContainer = getColorOnContainer; | ||
exports.getDefaultColorOf = getDefaultColorOf; | ||
//# sourceMappingURL=note-graph.js.map |
@@ -1,2 +0,2 @@ | ||
import { scaleLinear, forceX, forceY, forceCollide, rgb, hsl } from 'd3'; | ||
import { scaleLinear, rgb, forceX, forceY, forceCollide, hsl } from 'd3'; | ||
import ForceGraph from 'force-graph'; | ||
@@ -137,2 +137,49 @@ | ||
function getColorOnContainer(container, name, fallback) { | ||
return getComputedStyle(container).getPropertyValue(name) || fallback; | ||
} | ||
function getDefaultColorOf(opts = {}) { | ||
const container = opts.container || document.body; | ||
const highlightedForeground = getColorOnContainer(container, '--notegraph-highlighted-foreground-color', '#f9c74f'); | ||
return { | ||
background: getColorOnContainer(container, `--notegraph-background`, '#f7f7f7'), | ||
fontSize: parseInt(getColorOnContainer(container, `--notegraph-font-size`, 12)), | ||
highlightedForeground, | ||
node: { | ||
note: { | ||
regular: getColorOnContainer(container, '--notegraph-note-color-regular', '#5f76e7') | ||
}, | ||
unknown: getColorOnContainer(container, '--notegraph-unkown-node-color', '#f94144') | ||
}, | ||
link: { | ||
regular: getColorOnContainer(container, '--notegraph-link-color-regular', '#ccc'), | ||
highlighted: getColorOnContainer(container, '--notegraph-link-color-highlighted', highlightedForeground) | ||
}, | ||
hoverNodeLink: { | ||
highlightedDirection: { | ||
inbound: '#3078cd', | ||
outbound: highlightedForeground | ||
} | ||
} | ||
}; | ||
} | ||
const makeDrawWrapper = ctx => ({ | ||
circle: function (x, y, radius, color) { | ||
ctx.beginPath(); | ||
ctx.arc(x, y, radius, 0, 2 * Math.PI, false); | ||
ctx.fillStyle = color; | ||
ctx.fill(); | ||
ctx.closePath(); | ||
return this; | ||
}, | ||
text: function (text, x, y, size, color) { | ||
ctx.font = `${size}px Sans-Serif`; | ||
ctx.textAlign = 'center'; | ||
ctx.textBaseline = 'top'; | ||
ctx.fillStyle = color; | ||
ctx.fillText(text, x, y); | ||
return this; | ||
} | ||
}); | ||
/** | ||
@@ -143,2 +190,3 @@ * The view of the graph. | ||
class NoteGraphView { | ||
@@ -165,2 +213,3 @@ constructor(opts) { | ||
}; | ||
this.shouldDebugColor = false; | ||
this.options = opts; | ||
@@ -192,23 +241,5 @@ this.container = opts.container; | ||
if (!this.style) { | ||
const highlightedForeground = this.getColorOnContainer('--notegraph-highlighted-foreground-color', '#f9c74f'); | ||
this.style = { | ||
background: this.getColorOnContainer(`--notegraph-background`, '#f7f7f7'), | ||
fontSize: parseInt(this.getColorOnContainer(`--notegraph-font-size`, 12)), | ||
highlightedForeground, | ||
node: { | ||
note: { | ||
regular: this.getColorOnContainer('--notegraph-note-color-regular', '#277da1') | ||
}, | ||
unknown: this.getColorOnContainer('--notegraph-unkown-node-color', '#f94144') | ||
}, | ||
link: { | ||
regular: this.getColorOnContainer('--notegraph-link-color-regular', '#ccc'), | ||
highlighted: this.getColorOnContainer('--notegraph-link-color-highlighted', highlightedForeground) | ||
}, | ||
hoverNodeLink: { | ||
highlightedWithDirection: { | ||
inbound: '#3078cd' | ||
} | ||
} | ||
}; | ||
this.style = getDefaultColorOf({ | ||
container: this.container | ||
}); | ||
} | ||
@@ -222,6 +253,67 @@ | ||
this.initStyle(); | ||
this.refreshByStyle(); | ||
} | ||
if (this.forceGraph) { | ||
this.forceGraph.backgroundColor(this.style.background); | ||
} | ||
refreshByStyle() { | ||
if (!this.forceGraph) return; | ||
const getNodeColor = (nodeId, model) => { | ||
const info = model.nodeInfos[nodeId]; | ||
const noteStyle = this.style.node.note; | ||
const typeFill = this.style.node.note[info.type || 'regular'] || this.style.node.unknown; | ||
if (this.shouldDebugColor) { | ||
console.log('node fill', typeFill); | ||
} | ||
switch (this.getNodeState(nodeId, model)) { | ||
case 'regular': | ||
return { | ||
fill: typeFill, | ||
border: typeFill | ||
}; | ||
case 'lessened': | ||
let color = noteStyle.lessened; | ||
if (!color) { | ||
const c = hsl(typeFill); | ||
c.opacity = 0.2; | ||
color = c; | ||
} | ||
return { | ||
fill: color, | ||
border: color | ||
}; | ||
case 'highlighted': | ||
return { | ||
fill: typeFill, | ||
border: this.style.highlightedForeground | ||
}; | ||
default: | ||
throw new Error(`Unknown type for node ${nodeId}`); | ||
} | ||
}; | ||
this.forceGraph.backgroundColor(this.style.background).nodeCanvasObject((node, ctx, globalScale) => { | ||
if (!node.id) return; | ||
const info = this.model.nodeInfos[node.id]; | ||
const size = this.sizeScaler(info.neighbors ? info.neighbors.length : 1); | ||
const { | ||
fill, | ||
border | ||
} = getNodeColor(node.id, this.model); | ||
const fontSize = this.style.fontSize / globalScale; | ||
let textColor = rgb(fill); | ||
const nodeState = this.getNodeState(node.id, this.model); | ||
const alphaByDistance = this.labelAlphaScaler(globalScale); | ||
textColor.opacity = nodeState === 'highlighted' ? 1 : nodeState === 'lessened' ? Math.min(0.2, alphaByDistance) : alphaByDistance; | ||
const label = info.title; | ||
makeDrawWrapper(ctx).circle(node.x, node.y, size + 0.5, border).circle(node.x, node.y, size, fill).text(label, node.x, node.y + size + 1, fontSize, textColor); | ||
}).linkColor(link => { | ||
return this.getLinkColor(link, this.model); | ||
}); | ||
} | ||
@@ -279,112 +371,2 @@ | ||
const forceGraph = this.forceGraph || forceGraphFactory(); | ||
const makeDrawWrapper = ctx => ({ | ||
circle: function (x, y, radius, color) { | ||
ctx.beginPath(); | ||
ctx.arc(x, y, radius, 0, 2 * Math.PI, false); | ||
ctx.fillStyle = color; | ||
ctx.fill(); | ||
ctx.closePath(); | ||
return this; | ||
}, | ||
text: function (text, x, y, size, color) { | ||
ctx.font = `${size}px Sans-Serif`; | ||
ctx.textAlign = 'center'; | ||
ctx.textBaseline = 'top'; | ||
ctx.fillStyle = color; | ||
ctx.fillText(text, x, y); | ||
return this; | ||
} | ||
}); | ||
function getNodeColor(nodeId, model) { | ||
const info = model.nodeInfos[nodeId]; | ||
const noteStyle = style.node.note; | ||
const typeFill = style.node[info.type || 'unknown']; | ||
switch (getNodeState(nodeId, model)) { | ||
case 'regular': | ||
return { | ||
fill: typeFill, | ||
border: typeFill | ||
}; | ||
case 'lessened': | ||
let color = noteStyle.lessened; | ||
if (!color) { | ||
const c = hsl(typeFill); | ||
c.opacity = 0.2; | ||
color = c; | ||
} | ||
return { | ||
fill: color, | ||
border: color | ||
}; | ||
case 'highlighted': | ||
return { | ||
fill: typeFill, | ||
border: style.highlightedForeground | ||
}; | ||
default: | ||
throw new Error(`Unknown type for node ${nodeId}`); | ||
} | ||
} | ||
function getLinkNodeId(v) { | ||
const t = typeof v; | ||
return t === 'string' || t === 'number' ? v : v.id; | ||
} | ||
function getLinkColor(link, model) { | ||
const linkStyle = style.link; | ||
switch (getLinkState(link, model)) { | ||
case 'regular': | ||
return linkStyle.regular; | ||
case 'highlighted': | ||
// inbound/outbound link is a little bit different with hoverNode | ||
let linkColorByDirection; | ||
const hoverNodeLinkStyle = style.hoverNodeLink; | ||
if (model.hoverNode === getLinkNodeId(link.source)) { | ||
var _hoverNodeLinkStyle$h; | ||
linkColorByDirection = (_hoverNodeLinkStyle$h = hoverNodeLinkStyle.highlightedWithDirection) == null ? void 0 : _hoverNodeLinkStyle$h.outbound; | ||
} else if (model.hoverNode === getLinkNodeId(link.target)) { | ||
var _hoverNodeLinkStyle$h2; | ||
linkColorByDirection = (_hoverNodeLinkStyle$h2 = hoverNodeLinkStyle.highlightedWithDirection) == null ? void 0 : _hoverNodeLinkStyle$h2.inbound; | ||
} | ||
return linkColorByDirection || linkStyle.highlighted || style.highlightedForeground; | ||
case 'lessened': | ||
let color = linkStyle.lessened; | ||
if (!color) { | ||
const c = hsl(style.node.note.lessened); | ||
c.opacity = 0.2; | ||
color = c; | ||
} | ||
return color; | ||
default: | ||
throw new Error(`Unknown type for link ${link}`); | ||
} | ||
} | ||
function getNodeState(nodeId, model) { | ||
return model.selectedNodes.has(nodeId) || model.hoverNode === nodeId ? 'highlighted' : model.focusNodes.size === 0 ? 'regular' : model.focusNodes.has(nodeId) ? 'regular' : 'lessened'; | ||
} | ||
function getLinkState(link, model) { | ||
return model.focusNodes.size === 0 ? 'regular' : model.focusLinks.has(link.id) ? 'highlighted' : 'lessened'; | ||
} | ||
const width = options.width || window.innerWidth - this.container.offsetLeft - 20; | ||
@@ -395,20 +377,3 @@ const height = options.height || window.innerHeight - this.container.offsetTop - 20; | ||
forceGraph(this.container).height(height).width(width).graphData(model.graphData).backgroundColor(style.background).linkHoverPrecision(8).enableNodeDrag(!!options.enableNodeDrag).cooldownTime(200).d3Force('x', forceX()).d3Force('y', forceY()).d3Force('collide', forceCollide(forceGraph.nodeRelSize())).linkWidth(1).linkDirectionalParticles(1).linkDirectionalParticleWidth(link => getLinkState(link, model) === 'highlighted' ? 2 : 0).nodeCanvasObject((node, ctx, globalScale) => { | ||
if (!node.id) return; | ||
const info = this.model.nodeInfos[node.id]; | ||
const size = this.sizeScaler(info.neighbors ? info.neighbors.length : 1); | ||
const { | ||
fill, | ||
border | ||
} = getNodeColor(node.id, model); | ||
const fontSize = style.fontSize / globalScale; | ||
let textColor = rgb(fill); | ||
const nodeState = getNodeState(node.id, model); | ||
const alphaByDistance = this.labelAlphaScaler(globalScale); | ||
textColor.opacity = nodeState === 'highlighted' ? 1 : nodeState === 'lessened' ? Math.min(0.2, alphaByDistance) : alphaByDistance; | ||
const label = info.title; | ||
makeDrawWrapper(ctx).circle(node.x, node.y, size + 0.5, border).circle(node.x, node.y, size, fill).text(label, node.x, node.y + size + 1, fontSize, textColor); | ||
}).linkColor(link => { | ||
return getLinkColor(link, this.model); | ||
}).onEngineStop(() => { | ||
forceGraph(this.container).height(height).width(width).graphData(model.graphData).linkHoverPrecision(8).enableNodeDrag(!!options.enableNodeDrag).cooldownTime(200).d3Force('x', forceX()).d3Force('y', forceY()).d3Force('collide', forceCollide(forceGraph.nodeRelSize())).linkWidth(1).linkDirectionalParticles(1).linkDirectionalParticleWidth(link => this.getLinkState(link, model) === 'highlighted' ? 2 : 0).onEngineStop(() => { | ||
if (!hasInitialZoomToFit) { | ||
@@ -446,4 +411,59 @@ hasInitialZoomToFit = true; | ||
this.forceGraph = forceGraph; | ||
this.refreshByStyle(); | ||
} | ||
getLinkNodeId(v) { | ||
const t = typeof v; | ||
return t === 'string' || t === 'number' ? v : v.id; | ||
} | ||
getNodeState(nodeId, model = this.model) { | ||
return model.selectedNodes.has(nodeId) || model.hoverNode === nodeId ? 'highlighted' : model.focusNodes.size === 0 ? 'regular' : model.focusNodes.has(nodeId) ? 'regular' : 'lessened'; | ||
} | ||
getLinkState(link, model = this.model) { | ||
return model.focusNodes.size === 0 ? 'regular' : model.focusLinks.has(link.id) ? 'highlighted' : 'lessened'; | ||
} | ||
getLinkColor(link, model) { | ||
const style = this.style; | ||
const linkStyle = style.link; | ||
switch (this.getLinkState(link, model)) { | ||
case 'regular': | ||
return linkStyle.regular; | ||
case 'highlighted': | ||
// inbound/outbound link is a little bit different with hoverNode | ||
let linkColorByDirection; | ||
const hoverNodeLinkStyle = style.hoverNodeLink; | ||
if (model.hoverNode === this.getLinkNodeId(link.source)) { | ||
var _hoverNodeLinkStyle$h; | ||
linkColorByDirection = (_hoverNodeLinkStyle$h = hoverNodeLinkStyle.highlightedDirection) == null ? void 0 : _hoverNodeLinkStyle$h.outbound; | ||
} else if (model.hoverNode === this.getLinkNodeId(link.target)) { | ||
var _hoverNodeLinkStyle$h2; | ||
linkColorByDirection = (_hoverNodeLinkStyle$h2 = hoverNodeLinkStyle.highlightedDirection) == null ? void 0 : _hoverNodeLinkStyle$h2.inbound; | ||
} | ||
return linkColorByDirection || linkStyle.highlighted || style.highlightedForeground; | ||
case 'lessened': | ||
let color = linkStyle.lessened; | ||
if (!color) { | ||
const c = hsl(style.node.note.lessened); | ||
c.opacity = 0.2; | ||
color = c; | ||
} | ||
return color; | ||
default: | ||
throw new Error(`Unknown type for link ${link}`); | ||
} | ||
} | ||
updateViewModeInteractiveState() { | ||
@@ -510,3 +530,3 @@ const { | ||
export { NoteGraphModel, NoteGraphView }; | ||
export { NoteGraphModel, NoteGraphView, getColorOnContainer, getDefaultColorOf }; | ||
//# sourceMappingURL=note-graph.modern.js.map |
@@ -151,2 +151,55 @@ (function (global, factory) { | ||
function getColorOnContainer(container, name, fallback) { | ||
return getComputedStyle(container).getPropertyValue(name) || fallback; | ||
} | ||
function getDefaultColorOf(opts) { | ||
if (opts === void 0) { | ||
opts = {}; | ||
} | ||
var container = opts.container || document.body; | ||
var highlightedForeground = getColorOnContainer(container, '--notegraph-highlighted-foreground-color', '#f9c74f'); | ||
return { | ||
background: getColorOnContainer(container, "--notegraph-background", '#f7f7f7'), | ||
fontSize: parseInt(getColorOnContainer(container, "--notegraph-font-size", 12)), | ||
highlightedForeground: highlightedForeground, | ||
node: { | ||
note: { | ||
regular: getColorOnContainer(container, '--notegraph-note-color-regular', '#5f76e7') | ||
}, | ||
unknown: getColorOnContainer(container, '--notegraph-unkown-node-color', '#f94144') | ||
}, | ||
link: { | ||
regular: getColorOnContainer(container, '--notegraph-link-color-regular', '#ccc'), | ||
highlighted: getColorOnContainer(container, '--notegraph-link-color-highlighted', highlightedForeground) | ||
}, | ||
hoverNodeLink: { | ||
highlightedDirection: { | ||
inbound: '#3078cd', | ||
outbound: highlightedForeground | ||
} | ||
} | ||
}; | ||
} | ||
var makeDrawWrapper = function makeDrawWrapper(ctx) { | ||
return { | ||
circle: function circle(x, y, radius, color) { | ||
ctx.beginPath(); | ||
ctx.arc(x, y, radius, 0, 2 * Math.PI, false); | ||
ctx.fillStyle = color; | ||
ctx.fill(); | ||
ctx.closePath(); | ||
return this; | ||
}, | ||
text: function text(_text, x, y, size, color) { | ||
ctx.font = size + "px Sans-Serif"; | ||
ctx.textAlign = 'center'; | ||
ctx.textBaseline = 'top'; | ||
ctx.fillStyle = color; | ||
ctx.fillText(_text, x, y); | ||
return this; | ||
} | ||
}; | ||
}; | ||
/** | ||
@@ -157,2 +210,3 @@ * The view of the graph. | ||
var NoteGraphView = /*#__PURE__*/function () { | ||
@@ -177,2 +231,3 @@ function NoteGraphView(opts) { | ||
}; | ||
this.shouldDebugColor = false; | ||
this.options = opts; | ||
@@ -206,23 +261,5 @@ this.container = opts.container; | ||
if (!this.style) { | ||
var highlightedForeground = this.getColorOnContainer('--notegraph-highlighted-foreground-color', '#f9c74f'); | ||
this.style = { | ||
background: this.getColorOnContainer("--notegraph-background", '#f7f7f7'), | ||
fontSize: parseInt(this.getColorOnContainer("--notegraph-font-size", 12)), | ||
highlightedForeground: highlightedForeground, | ||
node: { | ||
note: { | ||
regular: this.getColorOnContainer('--notegraph-note-color-regular', '#277da1') | ||
}, | ||
unknown: this.getColorOnContainer('--notegraph-unkown-node-color', '#f94144') | ||
}, | ||
link: { | ||
regular: this.getColorOnContainer('--notegraph-link-color-regular', '#ccc'), | ||
highlighted: this.getColorOnContainer('--notegraph-link-color-highlighted', highlightedForeground) | ||
}, | ||
hoverNodeLink: { | ||
highlightedWithDirection: { | ||
inbound: '#3078cd' | ||
} | ||
} | ||
}; | ||
this.style = getDefaultColorOf({ | ||
container: this.container | ||
}); | ||
} | ||
@@ -236,88 +273,20 @@ | ||
this.initStyle(); | ||
if (this.forceGraph) { | ||
this.forceGraph.backgroundColor(this.style.background); | ||
} | ||
this.refreshByStyle(); | ||
}; | ||
_proto.linkWithGraphModel = function linkWithGraphModel(graphModel) { | ||
_proto.refreshByStyle = function refreshByStyle() { | ||
var _this = this; | ||
if (this.currentDataModelEntry) { | ||
this.currentDataModelEntry.unsub(); | ||
} | ||
this.updateViewData(graphModel.toGraphViewData()); | ||
var unsub = graphModel.subscribe(function () { | ||
_this.updateViewData(graphModel.toGraphViewData()); | ||
}); | ||
this.currentDataModelEntry = { | ||
graphModel: graphModel, | ||
unsub: unsub | ||
}; | ||
}; | ||
_proto.getColorOnContainer = function getColorOnContainer(name, fallback) { | ||
return getComputedStyle(this.container).getPropertyValue(name) || fallback; | ||
}; | ||
_proto.updateViewData = function updateViewData(dataInput) { | ||
Object.assign(this.model, dataInput); | ||
if (dataInput.focusedNode) { | ||
this.model.hoverNode = dataInput.focusedNode; | ||
} | ||
}; | ||
_proto.updateCanvasSize = function updateCanvasSize(size) { | ||
if (!this.forceGraph) return; | ||
if ('width' in size) { | ||
this.forceGraph.width(size.width); | ||
} | ||
var getNodeColor = function getNodeColor(nodeId, model) { | ||
var info = model.nodeInfos[nodeId]; | ||
var noteStyle = _this.style.node.note; | ||
var typeFill = _this.style.node.note[info.type || 'regular'] || _this.style.node.unknown; | ||
if ('height' in size) { | ||
this.forceGraph.height(size.height); | ||
} | ||
}; | ||
if (_this.shouldDebugColor) { | ||
console.log('node fill', typeFill); | ||
} | ||
_proto.initView = function initView() { | ||
var _this2 = this; | ||
var options = this.options, | ||
model = this.model, | ||
style = this.style, | ||
actions = this.actions; // this runtime dependency may not be ready when this umd file excutes, | ||
// so we will retrieve it from the global scope | ||
var forceGraphFactory = ForceGraph || globalThis.ForceGraph; | ||
var forceGraph = this.forceGraph || forceGraphFactory(); | ||
var makeDrawWrapper = function makeDrawWrapper(ctx) { | ||
return { | ||
circle: function circle(x, y, radius, color) { | ||
ctx.beginPath(); | ||
ctx.arc(x, y, radius, 0, 2 * Math.PI, false); | ||
ctx.fillStyle = color; | ||
ctx.fill(); | ||
ctx.closePath(); | ||
return this; | ||
}, | ||
text: function text(_text, x, y, size, color) { | ||
ctx.font = size + "px Sans-Serif"; | ||
ctx.textAlign = 'center'; | ||
ctx.textBaseline = 'top'; | ||
ctx.fillStyle = color; | ||
ctx.fillText(_text, x, y); | ||
return this; | ||
} | ||
}; | ||
}; | ||
function getNodeColor(nodeId, model) { | ||
var info = model.nodeInfos[nodeId]; | ||
var noteStyle = style.node.note; | ||
var typeFill = style.node[info.type || 'unknown']; | ||
switch (getNodeState(nodeId, model)) { | ||
switch (_this.getNodeState(nodeId, model)) { | ||
case 'regular': | ||
@@ -346,3 +315,3 @@ return { | ||
fill: typeFill, | ||
border: style.highlightedForeground | ||
border: _this.style.highlightedForeground | ||
}; | ||
@@ -353,57 +322,80 @@ | ||
} | ||
} | ||
}; | ||
function getLinkNodeId(v) { | ||
var t = typeof v; | ||
return t === 'string' || t === 'number' ? v : v.id; | ||
} | ||
this.forceGraph.backgroundColor(this.style.background).nodeCanvasObject(function (node, ctx, globalScale) { | ||
if (!node.id) return; | ||
var info = _this.model.nodeInfos[node.id]; | ||
function getLinkColor(link, model) { | ||
var linkStyle = style.link; | ||
var size = _this.sizeScaler(info.neighbors ? info.neighbors.length : 1); | ||
switch (getLinkState(link, model)) { | ||
case 'regular': | ||
return linkStyle.regular; | ||
var _getNodeColor = getNodeColor(node.id, _this.model), | ||
fill = _getNodeColor.fill, | ||
border = _getNodeColor.border; | ||
case 'highlighted': | ||
// inbound/outbound link is a little bit different with hoverNode | ||
var linkColorByDirection; | ||
var hoverNodeLinkStyle = style.hoverNodeLink; | ||
var fontSize = _this.style.fontSize / globalScale; | ||
var textColor = d3.rgb(fill); | ||
if (model.hoverNode === getLinkNodeId(link.source)) { | ||
var _hoverNodeLinkStyle$h; | ||
var nodeState = _this.getNodeState(node.id, _this.model); | ||
linkColorByDirection = (_hoverNodeLinkStyle$h = hoverNodeLinkStyle.highlightedWithDirection) == null ? void 0 : _hoverNodeLinkStyle$h.outbound; | ||
} else if (model.hoverNode === getLinkNodeId(link.target)) { | ||
var _hoverNodeLinkStyle$h2; | ||
var alphaByDistance = _this.labelAlphaScaler(globalScale); | ||
linkColorByDirection = (_hoverNodeLinkStyle$h2 = hoverNodeLinkStyle.highlightedWithDirection) == null ? void 0 : _hoverNodeLinkStyle$h2.inbound; | ||
} | ||
textColor.opacity = nodeState === 'highlighted' ? 1 : nodeState === 'lessened' ? Math.min(0.2, alphaByDistance) : alphaByDistance; | ||
var label = info.title; | ||
makeDrawWrapper(ctx).circle(node.x, node.y, size + 0.5, border).circle(node.x, node.y, size, fill).text(label, node.x, node.y + size + 1, fontSize, textColor); | ||
}).linkColor(function (link) { | ||
return _this.getLinkColor(link, _this.model); | ||
}); | ||
}; | ||
return linkColorByDirection || linkStyle.highlighted || style.highlightedForeground; | ||
_proto.linkWithGraphModel = function linkWithGraphModel(graphModel) { | ||
var _this2 = this; | ||
case 'lessened': | ||
var color = linkStyle.lessened; | ||
if (this.currentDataModelEntry) { | ||
this.currentDataModelEntry.unsub(); | ||
} | ||
if (!color) { | ||
var c = d3.hsl(style.node.note.lessened); | ||
c.opacity = 0.2; | ||
color = c; | ||
} | ||
this.updateViewData(graphModel.toGraphViewData()); | ||
var unsub = graphModel.subscribe(function () { | ||
_this2.updateViewData(graphModel.toGraphViewData()); | ||
}); | ||
this.currentDataModelEntry = { | ||
graphModel: graphModel, | ||
unsub: unsub | ||
}; | ||
}; | ||
return color; | ||
_proto.getColorOnContainer = function getColorOnContainer(name, fallback) { | ||
return getComputedStyle(this.container).getPropertyValue(name) || fallback; | ||
}; | ||
default: | ||
throw new Error("Unknown type for link " + link); | ||
} | ||
_proto.updateViewData = function updateViewData(dataInput) { | ||
Object.assign(this.model, dataInput); | ||
if (dataInput.focusedNode) { | ||
this.model.hoverNode = dataInput.focusedNode; | ||
} | ||
}; | ||
function getNodeState(nodeId, model) { | ||
return model.selectedNodes.has(nodeId) || model.hoverNode === nodeId ? 'highlighted' : model.focusNodes.size === 0 ? 'regular' : model.focusNodes.has(nodeId) ? 'regular' : 'lessened'; | ||
_proto.updateCanvasSize = function updateCanvasSize(size) { | ||
if (!this.forceGraph) return; | ||
if ('width' in size) { | ||
this.forceGraph.width(size.width); | ||
} | ||
function getLinkState(link, model) { | ||
return model.focusNodes.size === 0 ? 'regular' : model.focusLinks.has(link.id) ? 'highlighted' : 'lessened'; | ||
if ('height' in size) { | ||
this.forceGraph.height(size.height); | ||
} | ||
}; | ||
_proto.initView = function initView() { | ||
var _this3 = this; | ||
var options = this.options, | ||
model = this.model, | ||
actions = this.actions; // this runtime dependency may not be ready when this umd file excutes, | ||
// so we will retrieve it from the global scope | ||
var forceGraphFactory = ForceGraph || globalThis.ForceGraph; | ||
var forceGraph = this.forceGraph || forceGraphFactory(); | ||
var width = options.width || window.innerWidth - this.container.offsetLeft - 20; | ||
@@ -414,25 +406,4 @@ var height = options.height || window.innerHeight - this.container.offsetTop - 20; | ||
forceGraph(this.container).height(height).width(width).graphData(model.graphData).backgroundColor(style.background).linkHoverPrecision(8).enableNodeDrag(!!options.enableNodeDrag).cooldownTime(200).d3Force('x', d3.forceX()).d3Force('y', d3.forceY()).d3Force('collide', d3.forceCollide(forceGraph.nodeRelSize())).linkWidth(1).linkDirectionalParticles(1).linkDirectionalParticleWidth(function (link) { | ||
return getLinkState(link, model) === 'highlighted' ? 2 : 0; | ||
}).nodeCanvasObject(function (node, ctx, globalScale) { | ||
if (!node.id) return; | ||
var info = _this2.model.nodeInfos[node.id]; | ||
var size = _this2.sizeScaler(info.neighbors ? info.neighbors.length : 1); | ||
var _getNodeColor = getNodeColor(node.id, model), | ||
fill = _getNodeColor.fill, | ||
border = _getNodeColor.border; | ||
var fontSize = style.fontSize / globalScale; | ||
var textColor = d3.rgb(fill); | ||
var nodeState = getNodeState(node.id, model); | ||
var alphaByDistance = _this2.labelAlphaScaler(globalScale); | ||
textColor.opacity = nodeState === 'highlighted' ? 1 : nodeState === 'lessened' ? Math.min(0.2, alphaByDistance) : alphaByDistance; | ||
var label = info.title; | ||
makeDrawWrapper(ctx).circle(node.x, node.y, size + 0.5, border).circle(node.x, node.y, size, fill).text(label, node.x, node.y + size + 1, fontSize, textColor); | ||
}).linkColor(function (link) { | ||
return getLinkColor(link, _this2.model); | ||
forceGraph(this.container).height(height).width(width).graphData(model.graphData).linkHoverPrecision(8).enableNodeDrag(!!options.enableNodeDrag).cooldownTime(200).d3Force('x', d3.forceX()).d3Force('y', d3.forceY()).d3Force('collide', d3.forceCollide(forceGraph.nodeRelSize())).linkWidth(1).linkDirectionalParticles(1).linkDirectionalParticleWidth(function (link) { | ||
return _this3.getLinkState(link, model) === 'highlighted' ? 2 : 0; | ||
}).onEngineStop(function () { | ||
@@ -444,11 +415,11 @@ if (!hasInitialZoomToFit) { | ||
}).onNodeHover(function (node) { | ||
actions.highlightNode(_this2.model, node == null ? void 0 : node.id); | ||
actions.highlightNode(_this3.model, node == null ? void 0 : node.id); | ||
_this2.updateViewModeInteractiveState(); | ||
_this3.updateViewModeInteractiveState(); | ||
}).onNodeClick(function (node, event) { | ||
actions.selectNode(_this2.model, node.id, event.getModifierState('Shift')); | ||
actions.selectNode(_this3.model, node.id, event.getModifierState('Shift')); | ||
_this2.updateViewModeInteractiveState(); | ||
_this3.updateViewModeInteractiveState(); | ||
_this2.fireInteraction('nodeClick', { | ||
_this3.fireInteraction('nodeClick', { | ||
node: node, | ||
@@ -458,3 +429,3 @@ event: event | ||
}).onLinkClick(function (link, event) { | ||
_this2.fireInteraction('linkClick', { | ||
_this3.fireInteraction('linkClick', { | ||
link: link, | ||
@@ -464,7 +435,7 @@ event: event | ||
}).onBackgroundClick(function (event) { | ||
actions.selectNode(_this2.model, null, event.getModifierState('Shift')); | ||
actions.selectNode(_this3.model, null, event.getModifierState('Shift')); | ||
_this2.updateViewModeInteractiveState(); | ||
_this3.updateViewModeInteractiveState(); | ||
_this2.fireInteraction('backgroundClick', { | ||
_this3.fireInteraction('backgroundClick', { | ||
event: event | ||
@@ -475,3 +446,3 @@ }); | ||
_this2.fireInteraction('backgroundRightClick', { | ||
_this3.fireInteraction('backgroundRightClick', { | ||
event: event | ||
@@ -481,4 +452,67 @@ }); | ||
this.forceGraph = forceGraph; | ||
this.refreshByStyle(); | ||
}; | ||
_proto.getLinkNodeId = function getLinkNodeId(v) { | ||
var t = typeof v; | ||
return t === 'string' || t === 'number' ? v : v.id; | ||
}; | ||
_proto.getNodeState = function getNodeState(nodeId, model) { | ||
if (model === void 0) { | ||
model = this.model; | ||
} | ||
return model.selectedNodes.has(nodeId) || model.hoverNode === nodeId ? 'highlighted' : model.focusNodes.size === 0 ? 'regular' : model.focusNodes.has(nodeId) ? 'regular' : 'lessened'; | ||
}; | ||
_proto.getLinkState = function getLinkState(link, model) { | ||
if (model === void 0) { | ||
model = this.model; | ||
} | ||
return model.focusNodes.size === 0 ? 'regular' : model.focusLinks.has(link.id) ? 'highlighted' : 'lessened'; | ||
}; | ||
_proto.getLinkColor = function getLinkColor(link, model) { | ||
var style = this.style; | ||
var linkStyle = style.link; | ||
switch (this.getLinkState(link, model)) { | ||
case 'regular': | ||
return linkStyle.regular; | ||
case 'highlighted': | ||
// inbound/outbound link is a little bit different with hoverNode | ||
var linkColorByDirection; | ||
var hoverNodeLinkStyle = style.hoverNodeLink; | ||
if (model.hoverNode === this.getLinkNodeId(link.source)) { | ||
var _hoverNodeLinkStyle$h; | ||
linkColorByDirection = (_hoverNodeLinkStyle$h = hoverNodeLinkStyle.highlightedDirection) == null ? void 0 : _hoverNodeLinkStyle$h.outbound; | ||
} else if (model.hoverNode === this.getLinkNodeId(link.target)) { | ||
var _hoverNodeLinkStyle$h2; | ||
linkColorByDirection = (_hoverNodeLinkStyle$h2 = hoverNodeLinkStyle.highlightedDirection) == null ? void 0 : _hoverNodeLinkStyle$h2.inbound; | ||
} | ||
return linkColorByDirection || linkStyle.highlighted || style.highlightedForeground; | ||
case 'lessened': | ||
var color = linkStyle.lessened; | ||
if (!color) { | ||
var c = d3.hsl(style.node.note.lessened); | ||
c.opacity = 0.2; | ||
color = c; | ||
} | ||
return color; | ||
default: | ||
throw new Error("Unknown type for link " + link); | ||
} | ||
}; | ||
_proto.updateViewModeInteractiveState = function updateViewModeInteractiveState() { | ||
@@ -556,4 +590,6 @@ var model = this.model; // compute highlighted elements | ||
exports.NoteGraphView = NoteGraphView; | ||
exports.getColorOnContainer = getColorOnContainer; | ||
exports.getDefaultColorOf = getDefaultColorOf; | ||
}))); | ||
//# sourceMappingURL=note-graph.umd.js.map |
@@ -1,5 +0,6 @@ | ||
import { ForceGraphInstance } from 'force-graph'; | ||
import { ForceGraphInstance, LinkObject, NodeObject } from 'force-graph'; | ||
import { NodeId, GraphViewModel, GraphViewData } from './type'; | ||
import { NoteGraphModel } from './note-graph-model'; | ||
import { RecursivePartial } from './util'; | ||
import { GraphViewStyle } from './theme'; | ||
export declare type LinkState = 'regular' | 'lessened' | 'highlighted'; | ||
@@ -21,28 +22,2 @@ export declare type NodeState = 'regular' | 'lessened' | 'highlighted'; | ||
}; | ||
export declare type GraphViewStyle = { | ||
/** canvas background */ | ||
background: string; | ||
fontSize: number; | ||
/** node highlighted border corlor */ | ||
highlightedForeground: string; | ||
node: { | ||
note: { | ||
regular: string; | ||
highlighted?: string; | ||
lessened?: string; | ||
}; | ||
unknown: string; | ||
}; | ||
link: { | ||
regular?: string; | ||
highlighted?: string; | ||
lessened?: string; | ||
}; | ||
hoverNodeLink: { | ||
highlightedWithDirection?: { | ||
inbound?: string; | ||
outbound?: string; | ||
}; | ||
}; | ||
}; | ||
/** | ||
@@ -69,2 +44,3 @@ * The view of the graph. | ||
updateStyle(style: RecursivePartial<GraphViewStyle>): void; | ||
refreshByStyle(): void; | ||
linkWithGraphModel(graphModel: NoteGraphModel): void; | ||
@@ -77,3 +53,8 @@ protected getColorOnContainer(name: any, fallback: any): string; | ||
}>): void; | ||
protected shouldDebugColor: boolean; | ||
initView(): void; | ||
protected getLinkNodeId(v: LinkObject['source']): string | number | NodeObject; | ||
protected getNodeState(nodeId: any, model?: GraphViewModel): NodeState; | ||
protected getLinkState(link: any, model?: GraphViewModel): LinkState; | ||
protected getLinkColor(link: LinkObject, model: GraphViewModel): string; | ||
protected updateViewModeInteractiveState(): void; | ||
@@ -80,0 +61,0 @@ onInteraction(name: InteractionCallbackName, cb: any): () => void; |
{ | ||
"name": "note-graph", | ||
"description": "a generic visualization tool designed to show the structure of the document space and the relations between each doc", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"scripts": { | ||
@@ -27,2 +27,6 @@ "bootstrap": "lerna bootstrap", | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/hikerpig/note-graph.git" | ||
}, | ||
"dependencies": { | ||
@@ -29,0 +33,0 @@ "d3": "^6.2.0", |
# Welcome to note-graph 👋 | ||
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](#) | ||
![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg) | ||
[![CDN version](https://badgen.net/jsdelivr/v/npm/note-graph)](https://www.jsdelivr.com/package/npm/note-graph) | ||
Note Graph is a generic visualization tool designed to show the structure of the document space and the relations between each doc. | ||
It aims to be a handy tool for anyone who's interested in building a graph view for document spaces. | ||
A handy tool for anyone who is interested in building a graph view for document spaces. | ||
@@ -17,2 +18,10 @@ It depends on D3.js and [force-graph](https://github.com/vasturiano/force-graph), written in Typescript and can be used in the browser. | ||
## Features ✨ | ||
- Display bidirectional links with an elegant yet informative way. | ||
- Rich interaction | ||
- Hover on the node to see it's link flow. | ||
- Right click on the background to make the graph auto-fits the canvas size, easier to find contents when panning and scrolling makes you lost in the view. | ||
- 🎨 Highly customizable, pick your favorite colors for <del>all</del> (not yet but closing to it) the visual elements. | ||
## Usage | ||
@@ -24,5 +33,8 @@ | ||
Open [this fiddle](https://jsfiddle.net/hikerpig/3ed215um) to see how it look like. | ||
```html | ||
<html> | ||
<head> | ||
<title>Note Graph simple example</title> | ||
<script src="https://cdn.jsdelivr.net/npm/d3@6.2.0/dist/d3.min.js"></script> | ||
@@ -32,15 +44,12 @@ <script src="https://cdn.jsdelivr.net/npm/force-graph@1.35.1/dist/force-graph.js"></script> | ||
</head> | ||
<body> | ||
<div id="note-graph-container"></div> | ||
<script> | ||
function initGraphView() { | ||
const notes = [ | ||
{ | ||
id: '1', | ||
title: 'Note Graph', | ||
linkTo: [], | ||
referencedBy: [], | ||
}, | ||
] | ||
async function initGraphView() { | ||
const notes = await ( | ||
await fetch( | ||
'https://raw.githubusercontent.com/hikerpig/note-graph/master/demo/src/data/concept-data.json' | ||
) | ||
).json() | ||
const graphModel = new NOTE_GRAPH.NoteGraphModel(notes) | ||
@@ -47,0 +56,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
226552
17
2044
110
0
0