mirror of
https://github.com/dolthub/dolt.git
synced 2026-05-05 19:31:36 -05:00
splore now uses js2
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"optional": ["asyncToGenerator"],
|
||||
"blacklist": [
|
||||
"es6.blockScoping",
|
||||
"es6.constants",
|
||||
"es6.forOf",
|
||||
"es6.properties.computed",
|
||||
"es6.properties.shorthand",
|
||||
"es6.templateLiterals"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"parser": "babel-eslint",
|
||||
"rules": {
|
||||
"array-bracket-spacing": [2, "never"],
|
||||
"camelcase": 2,
|
||||
"eqeqeq": 2,
|
||||
"indent": [2, 2, {"SwitchCase": 1}],
|
||||
"linebreak-style": [2, "unix"],
|
||||
"no-multi-spaces": 2,
|
||||
"no-new-wrappers": 2,
|
||||
"no-throw-literal": 2,
|
||||
"no-var": 2,
|
||||
"object-curly-spacing": [2, "never"],
|
||||
"quotes": [2, "single"],
|
||||
"radix": 2,
|
||||
"semi": 2,
|
||||
"space-after-keywords": 2,
|
||||
"space-before-function-paren": [2, "never"],
|
||||
"space-infix-ops": 2,
|
||||
"space-in-parens": [2, "never"]
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"browser": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
"experimentalObjectRestSpread": true
|
||||
},
|
||||
"plugins": [
|
||||
"react"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
[ignore]
|
||||
.*/node_modules/react/.*
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
|
||||
[options]
|
||||
unsafe.enable_getters_and_setters=true
|
||||
munge_underscores=true
|
||||
+89
-58
@@ -1,3 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
'use strict';
|
||||
|
||||
// JavaScript implementation of Christoph Buchheim, Michael Jünger, Sebastian Leipert's tree layout algorithm. See: http://dl.acm.org/citation.cfm?id=729576.
|
||||
@@ -5,16 +7,51 @@
|
||||
// Thanks also to Bill Mill for the explanation and Python sample code: http://billmill.org/pymag-trees/.
|
||||
|
||||
// TreeNode represents one node of the tree visualization.
|
||||
class TreeNode {
|
||||
constructor(data, id, parent, depth, number, seen) {
|
||||
|
||||
function assertNotNull<T>(v: ?T): T {
|
||||
if (v !== null && v !== undefined) {
|
||||
return v;
|
||||
}
|
||||
|
||||
throw new Error('Non-null assertion failed');
|
||||
}
|
||||
|
||||
export type NodeData = {
|
||||
name: string,
|
||||
fullName: string,
|
||||
isOpen: boolean,
|
||||
canOpen: boolean
|
||||
};
|
||||
|
||||
export type NodeGraph = {
|
||||
nodes: {[key: string]: NodeData},
|
||||
links: {[key: string]: Array<string>}
|
||||
};
|
||||
|
||||
export class TreeNode {
|
||||
x: number;
|
||||
y: number;
|
||||
data: NodeData;
|
||||
id: string;
|
||||
children: Array<TreeNode>;
|
||||
parent: ?TreeNode;
|
||||
thread: ?TreeNode;
|
||||
offset: number;
|
||||
ancestor: TreeNode;
|
||||
change: number;
|
||||
shift: number;
|
||||
number: number;
|
||||
mod: number;
|
||||
|
||||
constructor(graph: NodeGraph, id: string, parent: ?TreeNode, depth: number, number: number, seen: {[key: string]: boolean}) {
|
||||
seen[id] = true;
|
||||
this.x = -1;
|
||||
this.y = depth;
|
||||
this.data = data.nodes[id];
|
||||
this.data = graph.nodes[id];
|
||||
this.id = id;
|
||||
this.children = ((this.data.isOpen && data.links[id]) || [])
|
||||
this.children = ((this.data.isOpen && graph.links[id]) || [])
|
||||
.filter(cid => !(cid in seen))
|
||||
.map((cid, i) => new TreeNode(data, cid, this, depth+1, i+1, seen));
|
||||
.map((cid, i) => new TreeNode(graph, cid, this, depth + 1, i + 1, seen));
|
||||
this.parent = parent;
|
||||
this.thread = null;
|
||||
this.offset = 0;
|
||||
@@ -25,24 +62,24 @@ class TreeNode {
|
||||
this.mod = 0;
|
||||
}
|
||||
|
||||
left() {
|
||||
left(): ?TreeNode {
|
||||
if (this.children.length > 0) {
|
||||
return this.children[0];
|
||||
}
|
||||
return this.thread;
|
||||
}
|
||||
|
||||
right() {
|
||||
right(): ?TreeNode {
|
||||
if (this.children.length > 0) {
|
||||
return this.children[this.children.length - 1];
|
||||
}
|
||||
return this.thread;
|
||||
}
|
||||
|
||||
leftBrother() {
|
||||
var n = null;
|
||||
leftBrother(): ?TreeNode {
|
||||
let n = null;
|
||||
if (this.parent) {
|
||||
for (var node of this.parent.children) {
|
||||
for (let node of this.parent.children) {
|
||||
if (node === this) {
|
||||
return n;
|
||||
} else {
|
||||
@@ -53,8 +90,8 @@ class TreeNode {
|
||||
return n;
|
||||
}
|
||||
|
||||
getLeftMostSibling() {
|
||||
if (this.parent && this != this.parent.children[0]) {
|
||||
getLeftMostSibling(): ?TreeNode {
|
||||
if (this.parent && this !== this.parent.children[0]) {
|
||||
return this.parent.children[0];
|
||||
} else {
|
||||
return null;
|
||||
@@ -62,31 +99,29 @@ class TreeNode {
|
||||
}
|
||||
}
|
||||
|
||||
function layout(tree) {
|
||||
export function layout(tree: TreeNode): void{
|
||||
firstWalk(tree, 1);
|
||||
secondWalk(tree, 0, 0);
|
||||
}
|
||||
|
||||
function firstWalk(v, distance) {
|
||||
function firstWalk(v: TreeNode, distance: number): void {
|
||||
if (v.children.length === 0) {
|
||||
if (v.getLeftMostSibling()) {
|
||||
v.x = v.leftBrother().x + distance;
|
||||
v.x = assertNotNull(v.leftBrother()).x + distance;
|
||||
} else {
|
||||
v.x = 0;
|
||||
}
|
||||
} else {
|
||||
var defaultAncestor = v.children[0];
|
||||
for (var w of v.children) {
|
||||
let defaultAncestor = v.children[0];
|
||||
for (let w of v.children) {
|
||||
firstWalk(w, distance);
|
||||
defaultAncestor = apportion(w, defaultAncestor, distance);
|
||||
}
|
||||
executeShifts(v);
|
||||
|
||||
var midpoint = (v.children[0].x + v.children[v.children.length - 1].x) / 2;
|
||||
let midpoint = (v.children[0].x + v.children[v.children.length - 1].x) / 2;
|
||||
|
||||
var ell = v.children[0];
|
||||
var arr = v.children[v.children.length - 1];
|
||||
var w = v.leftBrother();
|
||||
let w = v.leftBrother();
|
||||
if (w) {
|
||||
v.x = w.x + distance;
|
||||
v.mod = v.x - midpoint;
|
||||
@@ -94,30 +129,28 @@ function firstWalk(v, distance) {
|
||||
v.x = midpoint;
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
function apportion(v, defaultAncestor, distance) {
|
||||
var w = v.leftBrother();
|
||||
if (w != null) {
|
||||
var vir = v;
|
||||
var vor = v;
|
||||
var vil = w;
|
||||
var vol = v.getLeftMostSibling();
|
||||
var sir = v.mod;
|
||||
var sor = v.mod;
|
||||
var sil = vil.mod;
|
||||
var sol = vol.mod;
|
||||
function apportion(v: TreeNode, defaultAncestor: TreeNode, distance: number): TreeNode {
|
||||
let w = v.leftBrother();
|
||||
if (w !== null) {
|
||||
let vir = v;
|
||||
let vor = v;
|
||||
let vil = assertNotNull(w);
|
||||
let vol = assertNotNull(v.getLeftMostSibling());
|
||||
let sir = v.mod;
|
||||
let sor = v.mod;
|
||||
let sil = vil.mod;
|
||||
let sol = vol.mod;
|
||||
while (vil.right() && vir.left()) {
|
||||
vil = vil.right();
|
||||
vir = vir.left();
|
||||
vol = vol.left();
|
||||
vor = vor.right();
|
||||
vor.ancestor = v
|
||||
var shift = (vil.x + sil) - (vir.x + sir) + distance;
|
||||
vil = assertNotNull(vil.right());
|
||||
vir = assertNotNull(vir.left());
|
||||
vol = assertNotNull(vol.left());
|
||||
vor = assertNotNull(vor.right());
|
||||
vor.ancestor = v;
|
||||
let shift = (vil.x + sil) - (vir.x + sir) + distance;
|
||||
if (shift > 0) {
|
||||
var a = ancestor(vil, v, defaultAncestor);
|
||||
let a = ancestor(vil, v, defaultAncestor);
|
||||
moveSubtree(a, v, shift);
|
||||
sir = sir + shift;
|
||||
sor = sor + shift;
|
||||
@@ -138,11 +171,11 @@ function apportion(v, defaultAncestor, distance) {
|
||||
defaultAncestor = v;
|
||||
}
|
||||
}
|
||||
return defaultAncestor
|
||||
return defaultAncestor;
|
||||
}
|
||||
|
||||
function moveSubtree(wl, wr, shift) {
|
||||
var subtrees = wr.number - wl.number;
|
||||
function moveSubtree(wl: TreeNode, wr: TreeNode, shift: number): void {
|
||||
let subtrees = wr.number - wl.number;
|
||||
wr.change -= shift / subtrees;
|
||||
wr.shift += shift;
|
||||
wl.change += shift / subtrees;
|
||||
@@ -150,11 +183,11 @@ function moveSubtree(wl, wr, shift) {
|
||||
wr.mod += shift;
|
||||
}
|
||||
|
||||
function executeShifts(v) {
|
||||
var shift = 0;
|
||||
var change = 0;
|
||||
for (var i = v.children.length - 1; i >= 0; i--) {
|
||||
var w = v.children[i];
|
||||
function executeShifts(v: TreeNode): void {
|
||||
let shift = 0;
|
||||
let change = 0;
|
||||
for (let i = v.children.length - 1; i >= 0; i--) {
|
||||
let w = v.children[i];
|
||||
w.x += shift;
|
||||
w.mod += shift;
|
||||
change += w.change;
|
||||
@@ -162,21 +195,19 @@ function executeShifts(v) {
|
||||
}
|
||||
}
|
||||
|
||||
function ancestor(vil, v, defaultAncestor) {
|
||||
if (v.parent.children.indexOf(vil.ancestor) > -1) {
|
||||
function ancestor(vil: TreeNode, v: TreeNode, defaultAncestor: TreeNode): TreeNode {
|
||||
if (v.parent && v.parent.children.indexOf(vil.ancestor) > -1) {
|
||||
return vil.ancestor;
|
||||
} else {
|
||||
return defaultAncestor;
|
||||
}
|
||||
}
|
||||
|
||||
function secondWalk(v, m, depth) {
|
||||
v.x += m
|
||||
v.y = depth
|
||||
function secondWalk(v: TreeNode, m: number, depth: number): void {
|
||||
v.x += m;
|
||||
v.y = depth;
|
||||
|
||||
for (var w of v.children) {
|
||||
secondWalk(w, m + v.mod, depth+1)
|
||||
for (let w of v.children) {
|
||||
secondWalk(w, m + v.mod, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {TreeNode, layout};
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
<script src="out.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
</head>
|
||||
<body/>
|
||||
<body><div id="splore"></div></body>
|
||||
|
||||
+42
-33
@@ -1,44 +1,55 @@
|
||||
/* @flow */
|
||||
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node.js');
|
||||
var React = require('react');
|
||||
import Node from './node.js';
|
||||
import React from 'react';
|
||||
import type {NodeGraph} from './buchheim.js';
|
||||
import {TreeNode} from './buchheim.js';
|
||||
|
||||
var Layout = React.createClass({
|
||||
propTypes: {
|
||||
data: React.PropTypes.object.isRequired,
|
||||
onNodeClick: React.PropTypes.func.isRequired,
|
||||
tree: React.PropTypes.object.isRequired,
|
||||
},
|
||||
type Props = {
|
||||
data: NodeGraph,
|
||||
onNodeClick: (e: Event, s: string) => void,
|
||||
tree: TreeNode
|
||||
}
|
||||
|
||||
render() {
|
||||
var children = [];
|
||||
var edges = [];
|
||||
var lookup = {};
|
||||
export default class Layout extends React.Component {
|
||||
static defaultProps: {};
|
||||
props: Props;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render(): React.Element {
|
||||
let children = [];
|
||||
let edges = [];
|
||||
let lookup = {};
|
||||
|
||||
const spaceX = 75;
|
||||
const spaceY = 20;
|
||||
var getX = d => d.y * spaceX;
|
||||
var getY = d => d.x * spaceY;
|
||||
var maxX = 0;
|
||||
var minY = 0;
|
||||
var maxY = 0;
|
||||
let getX = d => d.y * spaceX;
|
||||
let getY = d => d.x * spaceY;
|
||||
let maxX = 0;
|
||||
let minY = 0;
|
||||
let maxY = 0;
|
||||
|
||||
var process = (treeNode, fromX, fromY) => {
|
||||
var links = this.props.data.links[treeNode.id] || [];
|
||||
var hasChildren = treeNode.data.canOpen || links.length > 0;
|
||||
var x = getX(treeNode);
|
||||
var y = getY(treeNode);
|
||||
var title = '';
|
||||
let process = (treeNode, fromX, fromY) => {
|
||||
let links = this.props.data.links[treeNode.id] || [];
|
||||
let hasChildren = treeNode.data.canOpen || links.length > 0;
|
||||
let x = getX(treeNode);
|
||||
let y = getY(treeNode);
|
||||
let title = '';
|
||||
|
||||
if (treeNode.data.fullName) {
|
||||
title = 'Alt-click for full ref'
|
||||
title = 'Alt-click for full ref';
|
||||
}
|
||||
|
||||
maxX = Math.max(x + spaceX, maxX);
|
||||
minY = Math.min(y, minY);
|
||||
maxY = Math.max(y + spaceY, maxY);
|
||||
|
||||
var n = (
|
||||
let n = (
|
||||
<Node
|
||||
key={'n' + treeNode.id}
|
||||
shape='circle'
|
||||
@@ -67,16 +78,16 @@ var Layout = React.createClass({
|
||||
process(this.props.tree, 0, 0);
|
||||
|
||||
edges.forEach(e => {
|
||||
var from = lookup[e[0]];
|
||||
var to = lookup[e[1]];
|
||||
let from = lookup[e[0]];
|
||||
let to = lookup[e[1]];
|
||||
children.push(
|
||||
<path key={'p' + e[0] + '-' + e[1]} className='link' d={`M${getX(from)},${getY(from)}L${getX(to)},${getY(to)}`}/>);
|
||||
});
|
||||
|
||||
var sortOrder = (elm => elm.type == 'path' ? 0 : 1);
|
||||
let sortOrder = (elm => elm.type === 'path' ? 0 : 1);
|
||||
children.sort((a, b) => sortOrder(a) - sortOrder(b));
|
||||
|
||||
var translateY = spaceY;
|
||||
let translateY = spaceY;
|
||||
if (minY < 0) {
|
||||
translateY -= minY;
|
||||
maxY -= minY;
|
||||
@@ -89,7 +100,5 @@ var Layout = React.createClass({
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = React.createFactory(Layout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
pushd ../../js
|
||||
pushd ../../js2
|
||||
npm run build
|
||||
./link.sh
|
||||
popd
|
||||
|
||||
+69
-49
@@ -1,41 +1,43 @@
|
||||
/* @flow */
|
||||
|
||||
'use strict';
|
||||
|
||||
var buchheim = require('./buchheim.js');
|
||||
var Layout = require('./layout.js');
|
||||
var Immutable = require('immutable');
|
||||
var noms = require('noms');
|
||||
var queryString = require('query-string');
|
||||
var React = require('react');
|
||||
var {Ref} = require('noms');
|
||||
import {layout, NodeGraph, TreeNode} from './buchheim.js';
|
||||
import Layout from './layout.js';
|
||||
import React from 'react'; //eslint-disable-line no-unused-vars
|
||||
import ReactDOM from 'react-dom';
|
||||
import {readValue, HttpStore, Ref} from 'noms';
|
||||
|
||||
var data = {nodes: {}, links: {}};
|
||||
var rootRef = null;
|
||||
let data: NodeGraph = {nodes: {}, links: {}};
|
||||
let rootRef: Ref;
|
||||
let httpStore: HttpStore;
|
||||
let renderNode: ?HTMLElement;
|
||||
|
||||
window.onload = function() {
|
||||
var target = document.getElementById('root');
|
||||
var w = window.innerWidth;
|
||||
var h = window.innerHeight;
|
||||
window.addEventListener('load', () => {
|
||||
renderNode = document.getElementById('splore');
|
||||
httpStore = new HttpStore('http://localhost:8000');
|
||||
|
||||
noms.getRoot().then(ref => {
|
||||
httpStore.getRoot().then(ref => {
|
||||
rootRef = ref;
|
||||
handleChunkLoad(ref, new Ref(ref));
|
||||
handleChunkLoad(ref, ref);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
window.onresize = render;
|
||||
|
||||
function handleChunkLoad(ref, val, fromRef) {
|
||||
var counter = 0
|
||||
var process = (ref, val, fromId) => {
|
||||
if (typeof val == 'undefined') {
|
||||
function handleChunkLoad(ref: Ref, val: any, fromRef: ?string) {
|
||||
let counter = 0;
|
||||
|
||||
function process(ref, val, fromId): ?string {
|
||||
if (typeof val === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Assign a unique ID to this node.
|
||||
// We don't use the noms ref because we only want to represent values as shared in the graph if they are actually in the same chunk.
|
||||
var id;
|
||||
let id;
|
||||
if (val instanceof Ref) {
|
||||
id = val.ref;
|
||||
id = val.toString();
|
||||
} else {
|
||||
id = ref + '/' + counter++;
|
||||
}
|
||||
@@ -55,48 +57,65 @@ function handleChunkLoad(ref, val, fromRef) {
|
||||
|
||||
if (val instanceof Blob) {
|
||||
data.nodes[id] = {name: `Blob (${val.size})`};
|
||||
} else if (Immutable.List.isList(val)) {
|
||||
data.nodes[id] = {name: `List (${val.size})`};
|
||||
} else if (Array.isArray(val)) {
|
||||
data.nodes[id] = {name: `List (${val.length})`};
|
||||
val.forEach(c => process(ref, c, id));
|
||||
} else if (Immutable.Set.isSet(val)) {
|
||||
} else if (val instanceof Set) {
|
||||
data.nodes[id] = {name: `Set (${val.size})`};
|
||||
val.forEach(c => process(ref, c, id));
|
||||
} else if (Immutable.Map.isMap(val)) {
|
||||
var structName = val.get('$name');
|
||||
if (structName) {
|
||||
data.nodes[id] = {name: structName};
|
||||
} else {
|
||||
data.nodes[id] = {name: `Map (${val.size})`};
|
||||
}
|
||||
val.keySeq().filter(k => k != '$name')
|
||||
.forEach(k => {
|
||||
// TODO: handle non-string keys
|
||||
var kid = process(ref, k, id);
|
||||
|
||||
} else if (val instanceof Map) {
|
||||
data.nodes[id] = {name: `Map (${val.size})`};
|
||||
val.forEach((v, k) => {
|
||||
// TODO: handle non-string keys
|
||||
let kid = process(ref, k, id);
|
||||
if (kid) {
|
||||
// Start map keys open, just makes it easier to use.
|
||||
data.nodes[kid].isOpen = true;
|
||||
|
||||
process(ref, val.get(k), kid);
|
||||
});
|
||||
process(ref, v, kid);
|
||||
} else {
|
||||
throw new Error('No kid id.');
|
||||
}
|
||||
});
|
||||
} else if (val instanceof Ref) {
|
||||
let refStr = val.toString();
|
||||
data.nodes[id] = {
|
||||
canOpen: true,
|
||||
name: val.ref.substr(5, 6),
|
||||
fullName: val.ref,
|
||||
name: refStr.substr(5, 6),
|
||||
fullName: refStr
|
||||
};
|
||||
} else if (val._typeRef) {
|
||||
// Struct
|
||||
let structName = val._typeRef.name;
|
||||
data.nodes[id] = {name: structName};
|
||||
Object.keys(val).forEach(k => {
|
||||
if (k === '_typeRef') {
|
||||
return;
|
||||
}
|
||||
// TODO: handle non-string keys
|
||||
let kid = process(ref, k, id);
|
||||
if (kid) {
|
||||
// Start map keys open, just makes it easier to use.
|
||||
data.nodes[kid].isOpen = true;
|
||||
|
||||
process(ref, val[k], kid);
|
||||
} else {
|
||||
throw new Error('No kid id.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return id;
|
||||
};
|
||||
}
|
||||
|
||||
process(ref, val, fromRef);
|
||||
render();
|
||||
}
|
||||
|
||||
function handleNodeClick(e, id) {
|
||||
function handleNodeClick(e: Event, id: string) {
|
||||
if (e.altKey) {
|
||||
if (data.nodes[id].fullName) {
|
||||
window.prompt("Full ref", data.nodes[id].fullName);
|
||||
window.prompt('Full ref', data.nodes[id].fullName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -111,14 +130,15 @@ function handleNodeClick(e, id) {
|
||||
if (data.links[id] || !data.nodes[id].isOpen) {
|
||||
render();
|
||||
} else {
|
||||
noms.readValue(id, noms.getChunk)
|
||||
.then(chunk => handleChunkLoad(id, chunk, id));
|
||||
readValue(Ref.parse(id), httpStore).then(value => {
|
||||
handleChunkLoad(id, value, id);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
var dt = new buchheim.TreeNode(data, rootRef, null, 0, 0, {});
|
||||
buchheim.layout(dt);
|
||||
React.render(<Layout tree={dt} data={data} onNodeClick={handleNodeClick}/>, document.body);
|
||||
let dt = new TreeNode(data, rootRef.toString(), null, 0, 0, {});
|
||||
layout(dt);
|
||||
ReactDOM.render(<Layout tree={dt} data={data} onNodeClick={handleNodeClick}/>, renderNode);
|
||||
}
|
||||
|
||||
+48
-33
@@ -1,41 +1,58 @@
|
||||
/* @flow */
|
||||
|
||||
'use strict';
|
||||
|
||||
var classNames = require('classnames');
|
||||
var React = require('react');
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
|
||||
var Node = React.createClass({
|
||||
propTypes: {
|
||||
canOpen: React.PropTypes.bool.isRequired,
|
||||
isOpen: React.PropTypes.bool.isRequired,
|
||||
shape: React.PropTypes.string.isRequired,
|
||||
text: React.PropTypes.string.isRequired,
|
||||
title: React.PropTypes.string,
|
||||
fromX: React.PropTypes.number.isRequired,
|
||||
fromY: React.PropTypes.number.isRequired,
|
||||
x: React.PropTypes.number.isRequired,
|
||||
y: React.PropTypes.number.isRequired,
|
||||
onClick: React.PropTypes.func.isRequired,
|
||||
},
|
||||
type Props = {
|
||||
canOpen: boolean,
|
||||
isOpen: boolean,
|
||||
shape: string,
|
||||
text: string,
|
||||
title: string,
|
||||
fromX: number,
|
||||
fromY: number,
|
||||
x: number,
|
||||
y: number,
|
||||
onClick: (e: Event, s: String) => void;
|
||||
}
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
type State = {
|
||||
x: number,
|
||||
y: number
|
||||
}
|
||||
|
||||
export default class Node extends React.Component {
|
||||
static defaultProps: {};
|
||||
props: Props;
|
||||
state: State;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
x: this.props.fromX,
|
||||
y: this.props.fromY,
|
||||
y: this.props.fromY
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.x != this.props.x ||
|
||||
this.state.y != this.props.y) {
|
||||
setState(state: State) {
|
||||
super.setState(state);
|
||||
}
|
||||
|
||||
render(): React.Element {
|
||||
if (this.state.x !== this.props.x ||
|
||||
this.state.y !== this.props.y) {
|
||||
window.requestAnimationFrame(() => this.setState({
|
||||
x: this.props.x,
|
||||
y: this.props.y,
|
||||
y: this.props.y
|
||||
}));
|
||||
}
|
||||
|
||||
var textAnchor = 'start';
|
||||
var textX = 10;
|
||||
var translate = `translate3d(${this.state.x}px, ${this.state.y}px, 0)`;
|
||||
let textAnchor = 'start';
|
||||
let textX = 10;
|
||||
let translate = `translate3d(${this.state.x}px, ${this.state.y}px, 0)`;
|
||||
|
||||
if (this.props.canOpen) {
|
||||
textAnchor = 'end';
|
||||
@@ -51,10 +68,10 @@ var Node = React.createClass({
|
||||
<title>{this.props.title}</title>
|
||||
</g>
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
getShape() {
|
||||
var className = classNames('icon', {open:this.props.isOpen});
|
||||
let className = classNames('icon', {open:this.props.isOpen});
|
||||
switch (this.props.shape) {
|
||||
case 'circle':
|
||||
return <circle className={className} r='4.5'/>;
|
||||
@@ -62,9 +79,7 @@ var Node = React.createClass({
|
||||
// rx:1.35 and ry:1.35 for rounded corners, but not doing until I learn how to make the triangle match below.
|
||||
return <rect className={className} x='-4.5' y='-4.5' width='9' height='9'/>;
|
||||
case 'triangle':
|
||||
return <polygon className={className} points='0,-4.5 4.5,4.5 -4.5,4.5' rx='1.35' ry='1.35'/>
|
||||
return <polygon className={className} points='0,-4.5 4.5,4.5 -4.5,4.5' rx='1.35' ry='1.35'/>;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = React.createFactory(Node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,21 @@
|
||||
"name": "noms-splore",
|
||||
"dependencies": {
|
||||
"classnames": "^2.1.3",
|
||||
"immutable": "^3.7.4",
|
||||
"query-string": "^2.4.0",
|
||||
"react": "^0.12.0"
|
||||
"react": "^0.14.1",
|
||||
"react-dom": "^0.14.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "^5.6.23",
|
||||
"babel-eslint": "^4.1.3",
|
||||
"babelify": "^6.1.3",
|
||||
"browserify": "^6.2.0",
|
||||
"uglify-js": "~2.4.15",
|
||||
"eslint": "^1.7.3",
|
||||
"eslint-plugin-react": "^3.6.3",
|
||||
"watchify": "^2.1.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "watchify -o out.js -t babelify -v -d main.js",
|
||||
"build": "NODE_ENV=production browserify main.js -t babelify | uglifyjs -cm > out.js"
|
||||
"build": "NODE_ENV=production browserify main.js -t babelify > out.js",
|
||||
"test": "rm -f out.js && eslint *.js && flow"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user