@jrkasprzyk/parcoord-es 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +160 -0
  3. package/dist/parcoords.css +61 -0
  4. package/dist/parcoords.esm.js +4132 -0
  5. package/dist/parcoords.esm.js.map +1 -0
  6. package/dist/parcoords.js +4130 -0
  7. package/dist/parcoords.js.map +1 -0
  8. package/dist/parcoords.standalone.js +11233 -0
  9. package/dist/parcoords.standalone.js.map +1 -0
  10. package/package.json +89 -0
  11. package/src/api/adjacentPairs.js +10 -0
  12. package/src/api/applyAxisConfig.js +35 -0
  13. package/src/api/applyDimensionDefaults.js +25 -0
  14. package/src/api/autoscale.js +133 -0
  15. package/src/api/axisDots.js +27 -0
  16. package/src/api/brushMode.js +50 -0
  17. package/src/api/brushReset.js +34 -0
  18. package/src/api/brushable.js +81 -0
  19. package/src/api/clear.js +21 -0
  20. package/src/api/commonScale.js +45 -0
  21. package/src/api/computeRealCentroids.js +8 -0
  22. package/src/api/createAxes.js +101 -0
  23. package/src/api/detectDimensionTypes.js +12 -0
  24. package/src/api/detectDimensions.js +7 -0
  25. package/src/api/flip.js +11 -0
  26. package/src/api/getOrderedDimensionKeys.js +8 -0
  27. package/src/api/highlight.js +26 -0
  28. package/src/api/init.js +53 -0
  29. package/src/api/interactive.js +7 -0
  30. package/src/api/intersection.js +16 -0
  31. package/src/api/mark.js +20 -0
  32. package/src/api/mergeParcoords.js +86 -0
  33. package/src/api/removeAxes.js +9 -0
  34. package/src/api/render.js +26 -0
  35. package/src/api/renderBrushed.js +39 -0
  36. package/src/api/renderDefault.js +27 -0
  37. package/src/api/renderMarked.js +34 -0
  38. package/src/api/reorder.js +37 -0
  39. package/src/api/reorderable.js +41 -0
  40. package/src/api/resize.js +36 -0
  41. package/src/api/scale.js +10 -0
  42. package/src/api/selected.js +209 -0
  43. package/src/api/shadows.js +9 -0
  44. package/src/api/sortDimensions.js +13 -0
  45. package/src/api/sortDimensionsByRowData.js +20 -0
  46. package/src/api/toString.js +11 -0
  47. package/src/api/toType.js +9 -0
  48. package/src/api/toTypeCoerceNumbers.js +7 -0
  49. package/src/api/unhighlight.js +12 -0
  50. package/src/api/unmark.js +12 -0
  51. package/src/api/updateAxes.js +103 -0
  52. package/src/bindEvents.js +60 -0
  53. package/src/brush/1d/brushExtents.js +73 -0
  54. package/src/brush/1d/brushFor.js +92 -0
  55. package/src/brush/1d/brushReset.js +36 -0
  56. package/src/brush/1d/index.js +20 -0
  57. package/src/brush/1d/install.js +41 -0
  58. package/src/brush/1d/selected.js +79 -0
  59. package/src/brush/1d/uninstall.js +12 -0
  60. package/src/brush/1d-multi/brushExtents.js +101 -0
  61. package/src/brush/1d-multi/brushFor.js +13 -0
  62. package/src/brush/1d-multi/brushReset.js +53 -0
  63. package/src/brush/1d-multi/drawBrushes.js +36 -0
  64. package/src/brush/1d-multi/index.js +20 -0
  65. package/src/brush/1d-multi/install.js +29 -0
  66. package/src/brush/1d-multi/newBrush.js +102 -0
  67. package/src/brush/1d-multi/selected.js +160 -0
  68. package/src/brush/1d-multi/uninstall.js +12 -0
  69. package/src/brush/angular/brushReset.js +14 -0
  70. package/src/brush/angular/index.js +19 -0
  71. package/src/brush/angular/install.js +141 -0
  72. package/src/brush/angular/onDrag.js +109 -0
  73. package/src/brush/angular/onDragEnd.js +30 -0
  74. package/src/brush/angular/onDragStart.js +38 -0
  75. package/src/brush/angular/removeStrum.js +12 -0
  76. package/src/brush/angular/selected.js +63 -0
  77. package/src/brush/angular/uninstall.js +17 -0
  78. package/src/brush/angular/util/hypothenuse.js +3 -0
  79. package/src/brush/consecutive.js +11 -0
  80. package/src/brush/dimensionsForPoint.js +32 -0
  81. package/src/brush/invertByScale.js +24 -0
  82. package/src/brush/strums/brushReset.js +14 -0
  83. package/src/brush/strums/index.js +19 -0
  84. package/src/brush/strums/install.js +81 -0
  85. package/src/brush/strums/onDrag.js +83 -0
  86. package/src/brush/strums/onDragEnd.js +20 -0
  87. package/src/brush/strums/onDragStart.js +33 -0
  88. package/src/brush/strums/removeStrum.js +10 -0
  89. package/src/brush/strums/selected.js +52 -0
  90. package/src/brush/strums/uninstall.js +16 -0
  91. package/src/index.js +226 -0
  92. package/src/parallel-coordinates.css +61 -0
  93. package/src/state/defaultConfig.js +36 -0
  94. package/src/state/index.js +86 -0
  95. package/src/state/sideEffects.js +89 -0
  96. package/src/util/colorPath.js +71 -0
  97. package/src/util/computeCentroids.js +44 -0
  98. package/src/util/computeClusterCentroids.js +33 -0
  99. package/src/util/computeControlPoints.js +38 -0
  100. package/src/util/dimensionLabels.js +11 -0
  101. package/src/util/flipAxisAndUpdatePCP.js +19 -0
  102. package/src/util/functor.js +3 -0
  103. package/src/util/getRange.js +24 -0
  104. package/src/util/getset.js +23 -0
  105. package/src/util/height.js +3 -0
  106. package/src/util/isBrushed.js +15 -0
  107. package/src/util/renderQueue.js +67 -0
  108. package/src/util/rotateLabels.js +18 -0
  109. package/src/util/width.js +3 -0
@@ -0,0 +1,83 @@
1
+ import { select } from 'd3-selection';
2
+ import { drag } from 'd3-drag';
3
+ import onDragEnd from './onDragEnd';
4
+
5
+ const drawStrum = (
6
+ brushGroup,
7
+ state,
8
+ config,
9
+ pc,
10
+ events,
11
+ strum,
12
+ activePoint
13
+ ) => {
14
+ let _svg = pc.selection.select('svg').select('g#strums'),
15
+ id = strum.dims.i,
16
+ points = [strum.p1, strum.p2],
17
+ _line = _svg.selectAll('line#strum-' + id).data([strum]),
18
+ circles = _svg.selectAll('circle#strum-' + id).data(points),
19
+ _drag = drag();
20
+
21
+ _line
22
+ .enter()
23
+ .append('line')
24
+ .attr('id', 'strum-' + id)
25
+ .attr('class', 'strum');
26
+
27
+ _line
28
+ .attr('x1', d => d.p1[0])
29
+ .attr('y1', d => d.p1[1])
30
+ .attr('x2', d => d.p2[0])
31
+ .attr('y2', d => d.p2[1])
32
+ .attr('stroke', 'black')
33
+ .attr('stroke-width', 2);
34
+
35
+ _drag
36
+ .on('drag', function(event, d) {
37
+ const i = points.indexOf(d) + 1;
38
+ strum['p' + i][0] = Math.min(Math.max(strum.minX + 1, event.x), strum.maxX);
39
+ strum['p' + i][1] = Math.min(Math.max(strum.minY, event.y), strum.maxY);
40
+ drawStrum(brushGroup, state, config, pc, events, strum, i - 1);
41
+ })
42
+ .on('end', onDragEnd(brushGroup, state, config, pc, events));
43
+
44
+ circles
45
+ .enter()
46
+ .append('circle')
47
+ .attr('id', 'strum-' + id)
48
+ .attr('class', 'strum');
49
+
50
+ circles
51
+ .attr('cx', d => d[0])
52
+ .attr('cy', d => d[1])
53
+ .attr('r', 5)
54
+ .style(
55
+ 'opacity',
56
+ (d, i) => (activePoint !== undefined && i === activePoint ? 0.8 : 0)
57
+ )
58
+ .on('mouseover', function() {
59
+ select(this).style('opacity', 0.8);
60
+ })
61
+ .on('mouseout', function() {
62
+ select(this).style('opacity', 0);
63
+ })
64
+ .call(_drag);
65
+ };
66
+
67
+ const onDrag = (brushGroup, state, config, pc, events) => (event) => {
68
+ const strum = state.strums[state.strums.active];
69
+
70
+ // Make sure that the point is within the bounds
71
+ strum.p2[0] = Math.min(
72
+ Math.max(strum.minX + 1, event.x - config.margin.left),
73
+ strum.maxX
74
+ );
75
+ strum.p2[1] = Math.min(
76
+ Math.max(strum.minY, event.y - config.margin.top),
77
+ strum.maxY
78
+ );
79
+
80
+ drawStrum(brushGroup, state, config, pc, events, strum, 1);
81
+ };
82
+
83
+ export default onDrag;
@@ -0,0 +1,20 @@
1
+ import selected from './selected';
2
+ import removeStrum from './removeStrum';
3
+
4
+ const onDragEnd = (brushGroup, state, config, pc, events) => () => {
5
+ const strum = state.strums[state.strums.active];
6
+
7
+ // Okay, somewhat unexpected, but not totally unsurprising, a mousclick is
8
+ // considered a drag without move. So we have to deal with that case
9
+ if (strum && strum.p1[0] === strum.p2[0] && strum.p1[1] === strum.p2[1]) {
10
+ removeStrum(state, pc);
11
+ }
12
+
13
+ const brushed = selected(brushGroup, state, config);
14
+ state.strums.active = undefined;
15
+ config.brushed = brushed;
16
+ pc.renderBrushed();
17
+ events.call('brushend', pc, config.brushed);
18
+ };
19
+
20
+ export default onDragEnd;
@@ -0,0 +1,33 @@
1
+ import { pointer } from 'd3-selection';
2
+ import h from '../../util/height';
3
+ import dimensionsForPoint from '../dimensionsForPoint';
4
+
5
+ // First we need to determine between which two axes the sturm was started.
6
+ // This will determine the freedom of movement, because a strum can
7
+ // logically only happen between two axes, so no movement outside these axes
8
+ // should be allowed.
9
+ const onDragStart = (state, config, pc, xscale) => (event) => {
10
+ let p = pointer(event, state.strumRect.node());
11
+
12
+ p[0] = p[0] - config.margin.left;
13
+ p[1] = p[1] - config.margin.top;
14
+
15
+ const dims = dimensionsForPoint(config, pc, xscale, p);
16
+ const strum = {
17
+ p1: p,
18
+ dims: dims,
19
+ minX: xscale(dims.left),
20
+ maxX: xscale(dims.right),
21
+ minY: 0,
22
+ maxY: h(config),
23
+ };
24
+
25
+ // Make sure that the point is within the bounds
26
+ strum.p1[0] = Math.min(Math.max(strum.minX, p[0]), strum.maxX);
27
+ strum.p2 = strum.p1.slice();
28
+
29
+ state.strums[dims.i] = strum;
30
+ state.strums.active = dims.i;
31
+ };
32
+
33
+ export default onDragStart;
@@ -0,0 +1,10 @@
1
+ const removeStrum = (state, pc) => {
2
+ const strum = state.strums[state.strums.active],
3
+ svg = pc.selection.select('svg').select('g#strums');
4
+
5
+ delete state.strums[state.strums.active];
6
+ svg.selectAll('line#strum-' + strum.dims.i).remove();
7
+ svg.selectAll('circle#strum-' + strum.dims.i).remove();
8
+ };
9
+
10
+ export default removeStrum;
@@ -0,0 +1,52 @@
1
+ // test if point falls between lines
2
+ const containmentTest = (strum, width) => p => {
3
+ const p1 = [strum.p1[0] - strum.minX, strum.p1[1] - strum.minX],
4
+ p2 = [strum.p2[0] - strum.minX, strum.p2[1] - strum.minX],
5
+ m1 = 1 - width / p1[0],
6
+ b1 = p1[1] * (1 - m1),
7
+ m2 = 1 - width / p2[0],
8
+ b2 = p2[1] * (1 - m2);
9
+
10
+ const x = p[0],
11
+ y = p[1],
12
+ y1 = m1 * x + b1,
13
+ y2 = m2 * x + b2;
14
+
15
+ return y > Math.min(y1, y2) && y < Math.max(y1, y2);
16
+ };
17
+
18
+ const crossesStrum = (state, config) => (d, id) => {
19
+ let strum = state.strums[id],
20
+ test = containmentTest(strum, state.strums.width(id)),
21
+ d1 = strum.dims.left,
22
+ d2 = strum.dims.right,
23
+ y1 = config.dimensions[d1].yscale,
24
+ y2 = config.dimensions[d2].yscale,
25
+ point = [y1(d[d1]) - strum.minX, y2(d[d2]) - strum.minX];
26
+ return test(point);
27
+ };
28
+
29
+ const selected = (brushGroup, state, config) => {
30
+ // Get the ids of the currently active strums.
31
+ const ids = Object.getOwnPropertyNames(state.strums).filter(d => !isNaN(d)),
32
+ brushed = config.data;
33
+
34
+ if (ids.length === 0) {
35
+ return brushed;
36
+ }
37
+
38
+ const crossTest = crossesStrum(state, config);
39
+
40
+ return brushed.filter(d => {
41
+ switch (brushGroup.predicate) {
42
+ case 'AND':
43
+ return ids.every(id => crossTest(d, id));
44
+ case 'OR':
45
+ return ids.some(id => crossTest(d, id));
46
+ default:
47
+ throw new Error('Unknown brush predicate ' + config.brushPredicate);
48
+ }
49
+ });
50
+ };
51
+
52
+ export default selected;
@@ -0,0 +1,16 @@
1
+ const uninstall = (state, pc) => () => {
2
+ pc.selection
3
+ .select('svg')
4
+ .select('g#strums')
5
+ .remove();
6
+ pc.selection
7
+ .select('svg')
8
+ .select('rect#strum-events')
9
+ .remove();
10
+ pc.on('axesreorder.strums', undefined);
11
+ delete pc.brushReset;
12
+
13
+ state.strumRect = undefined;
14
+ };
15
+
16
+ export default uninstall;
package/src/index.js ADDED
@@ -0,0 +1,226 @@
1
+ // misc
2
+ import renderQueue from './util/renderQueue';
3
+ import w from './util/width';
4
+
5
+ // brush
6
+ import install1DAxes from './brush/1d';
7
+ import install1DAxesMulti from './brush/1d-multi';
8
+ import install2DStrums from './brush/strums';
9
+ import installAngularBrush from './brush/angular';
10
+
11
+ // api
12
+ import intersection from './api/intersection';
13
+ import mergeParcoords from './api/mergeParcoords';
14
+ import selected from './api/selected';
15
+ import brushMode from './api/brushMode';
16
+ import updateAxes from './api/updateAxes';
17
+ import autoscale from './api/autoscale';
18
+ import brushable from './api/brushable';
19
+ import commonScale from './api/commonScale';
20
+ import computeRealCentroids from './api/computeRealCentroids';
21
+ import applyDimensionDefaults from './api/applyDimensionDefaults';
22
+ import createAxes from './api/createAxes';
23
+ import axisDots from './api/axisDots';
24
+ import applyAxisConfig from './api/applyAxisConfig';
25
+ import reorderable from './api/reorderable';
26
+ import resize from './api/resize';
27
+ import reorder from './api/reorder';
28
+ import sortDimensions from './api/sortDimensions';
29
+ import sortDimensionsByRowData from './api/sortDimensionsByRowData';
30
+ import clear from './api/clear';
31
+ import {
32
+ pathMark,
33
+ renderMarked,
34
+ renderMarkedDefault,
35
+ renderMarkedQueue,
36
+ } from './api/renderMarked';
37
+ import {
38
+ pathBrushed,
39
+ renderBrushed,
40
+ renderBrushedDefault,
41
+ renderBrushedQueue,
42
+ } from './api/renderBrushed';
43
+ import brushReset from './api/brushReset';
44
+ import toType from './api/toType';
45
+ import toString from './api/toString';
46
+ import adjacentPairs from './api/adjacentPairs';
47
+ import highlight from './api/highlight';
48
+ import unhighlight from './api/unhighlight';
49
+ import mark from './api/mark';
50
+ import unmark from './api/unmark';
51
+ import removeAxes from './api/removeAxes';
52
+ import render from './api/render';
53
+ import renderDefault, {
54
+ pathForeground,
55
+ renderDefaultQueue,
56
+ } from './api/renderDefault';
57
+ import toTypeCoerceNumbers from './api/toTypeCoerceNumbers';
58
+ import detectDimensionTypes from './api/detectDimensionTypes';
59
+ import getOrderedDimensionKeys from './api/getOrderedDimensionKeys';
60
+ import interactive from './api/interactive';
61
+ import shadows from './api/shadows';
62
+ import init from './api/init';
63
+ import flip from './api/flip';
64
+ import detectDimensions from './api/detectDimensions';
65
+ import scale from './api/scale';
66
+
67
+ import { version } from '../package.json';
68
+ import initState from './state';
69
+ import bindEvents from './bindEvents';
70
+
71
+ //css
72
+ import './parallel-coordinates.css';
73
+
74
+ const ParCoords = userConfig => {
75
+ const state = initState(userConfig);
76
+ const {
77
+ config,
78
+ events,
79
+ flags,
80
+ xscale,
81
+ dragging,
82
+ axis,
83
+ ctx,
84
+ canvas,
85
+ brush,
86
+ } = state;
87
+
88
+ const pc = init(config, canvas, ctx);
89
+
90
+ const position = d => {
91
+ if (xscale.range().length === 0) {
92
+ xscale.range([0, w(config)], 1);
93
+ }
94
+ return dragging[d] == null ? xscale(d) : dragging[d];
95
+ };
96
+
97
+ const brushedQueue = renderQueue(pathBrushed(config, ctx, position))
98
+ .rate(50)
99
+ .clear(() => pc.clear('brushed'));
100
+
101
+ const markedQueue = renderQueue(pathMark(config, ctx, position))
102
+ .rate(50)
103
+ .clear(() => pc.clear('marked'));
104
+
105
+ const foregroundQueue = renderQueue(pathForeground(config, ctx, position))
106
+ .rate(50)
107
+ .clear(function() {
108
+ pc.clear('foreground');
109
+ pc.clear('highlight');
110
+ });
111
+
112
+ bindEvents(
113
+ config,
114
+ ctx,
115
+ pc,
116
+ xscale,
117
+ flags,
118
+ brushedQueue,
119
+ markedQueue,
120
+ foregroundQueue,
121
+ events,
122
+ axis
123
+ );
124
+
125
+ // expose the state of the chart
126
+ pc.state = config;
127
+ pc.flags = flags;
128
+
129
+ pc.autoscale = autoscale(config, pc, xscale, ctx);
130
+ pc.scale = scale(config, pc);
131
+ pc.flip = flip(config);
132
+ pc.commonScale = commonScale(config, pc);
133
+ pc.detectDimensions = detectDimensions(pc);
134
+ // attempt to determine types of each dimension based on first row of data
135
+ pc.detectDimensionTypes = detectDimensionTypes;
136
+ pc.applyDimensionDefaults = applyDimensionDefaults(config, pc);
137
+ pc.getOrderedDimensionKeys = getOrderedDimensionKeys(config);
138
+
139
+ //Renders the polylines.
140
+ pc.render = render(config, pc, events);
141
+ pc.renderBrushed = renderBrushed(config, pc, events);
142
+ pc.renderMarked = renderMarked(config, pc, events);
143
+ pc.render.default = renderDefault(config, pc, ctx, position);
144
+ pc.render.queue = renderDefaultQueue(config, pc, foregroundQueue);
145
+ pc.renderBrushed.default = renderBrushedDefault(
146
+ config,
147
+ ctx,
148
+ position,
149
+ pc,
150
+ brush
151
+ );
152
+ pc.renderBrushed.queue = renderBrushedQueue(config, brush, brushedQueue);
153
+ pc.renderMarked.default = renderMarkedDefault(config, pc, ctx, position);
154
+ pc.renderMarked.queue = renderMarkedQueue(config, markedQueue);
155
+
156
+ pc.compute_real_centroids = computeRealCentroids(config, position);
157
+ pc.shadows = shadows(flags, pc);
158
+ pc.axisDots = axisDots(config, pc, position);
159
+ pc.clear = clear(config, pc, ctx, brush);
160
+ pc.createAxes = createAxes(config, pc, xscale, flags, axis);
161
+ pc.removeAxes = removeAxes(pc);
162
+ pc.updateAxes = updateAxes(config, pc, position, axis, flags);
163
+ pc.applyAxisConfig = applyAxisConfig;
164
+ pc.brushable = brushable(config, pc, flags);
165
+ pc.brushReset = brushReset(config, pc);
166
+ pc.selected = selected(config, pc);
167
+ pc.reorderable = reorderable(config, pc, xscale, position, dragging, flags);
168
+
169
+ // Reorder dimensions, such that the highest value (visually) is on the left and
170
+ // the lowest on the right. Visual values are determined by the data values in
171
+ // the given row.
172
+ pc.reorder = reorder(config, pc, xscale);
173
+ pc.sortDimensionsByRowData = sortDimensionsByRowData(config);
174
+ pc.sortDimensions = sortDimensions(config, position);
175
+
176
+ // pairs of adjacent dimensions
177
+ pc.adjacent_pairs = adjacentPairs;
178
+ pc.interactive = interactive(flags);
179
+
180
+ // expose internal state
181
+ pc.xscale = xscale;
182
+ pc.ctx = ctx;
183
+ pc.canvas = canvas;
184
+ pc.g = () => pc._g;
185
+
186
+ // rescale for height, width and margins
187
+ // TODO currently assumes chart is brushable, and destroys old brushes
188
+ pc.resize = resize(config, pc, flags, events);
189
+
190
+ // highlight an array of data
191
+ pc.highlight = highlight(config, pc, canvas, events, ctx, position);
192
+ // clear highlighting
193
+ pc.unhighlight = unhighlight(config, pc, canvas);
194
+
195
+ // mark an array of data
196
+ pc.mark = mark(config, pc, canvas, events, ctx, position);
197
+ // clear marked data
198
+ pc.unmark = unmark(config, pc, canvas);
199
+
200
+ // calculate 2d intersection of line a->b with line c->d
201
+ // points are objects with x and y properties
202
+ pc.intersection = intersection;
203
+
204
+ // Merges the canvases and SVG elements into one canvas element which is then passed into the callback
205
+ // (so you can choose to save it to disk, etc.)
206
+ pc.mergeParcoords = mergeParcoords(pc);
207
+ pc.brushModes = () => Object.getOwnPropertyNames(brush.modes);
208
+ pc.brushMode = brushMode(brush, config, pc);
209
+
210
+ // install brushes
211
+ install1DAxes(brush, config, pc, events);
212
+ install2DStrums(brush, config, pc, events, xscale);
213
+ installAngularBrush(brush, config, pc, events, xscale);
214
+ install1DAxesMulti(brush, config, pc, events);
215
+
216
+ pc.version = version;
217
+ // this descriptive text should live with other introspective methods
218
+ pc.toString = toString(config);
219
+ pc.toType = toType;
220
+ // try to coerce to number before returning type
221
+ pc.toTypeCoerceNumbers = toTypeCoerceNumbers;
222
+
223
+ return pc;
224
+ };
225
+
226
+ export default ParCoords;
@@ -0,0 +1,61 @@
1
+ .parcoords > svg, .parcoords > canvas {
2
+ font: 14px sans-serif;
3
+ position: absolute;
4
+ }
5
+
6
+ .parcoords > canvas {
7
+ pointer-events: none;
8
+ }
9
+
10
+ .parcoords text.label {
11
+ cursor: default;
12
+ fill: black;
13
+ }
14
+
15
+ .parcoords rect.background {
16
+ fill: transparent;
17
+ }
18
+
19
+ .parcoords rect.background:hover {
20
+ fill: rgba(120, 120, 120, 0.2);
21
+ }
22
+
23
+ .parcoords .resize rect {
24
+ fill: rgba(0, 0, 0, 0.1);
25
+ }
26
+
27
+ .parcoords rect.extent {
28
+ fill: rgba(255, 255, 255, 0.25);
29
+ stroke: rgba(0, 0, 0, 0.6);
30
+ }
31
+
32
+ .parcoords .axis line, .parcoords .axis path {
33
+ fill: none;
34
+ stroke: #222;
35
+ shape-rendering: crispEdges;
36
+ }
37
+
38
+ .parcoords canvas {
39
+ opacity: 1;
40
+ -moz-transition: opacity 0.3s;
41
+ -webkit-transition: opacity 0.3s;
42
+ -o-transition: opacity 0.3s;
43
+ }
44
+
45
+ .parcoords canvas.faded {
46
+ opacity: 0.25;
47
+ }
48
+
49
+ .parcoords canvas.dimmed {
50
+ opacity: 0.85;
51
+ }
52
+
53
+ .parcoords {
54
+ -webkit-touch-callout: none;
55
+ -webkit-user-select: none;
56
+ -khtml-user-select: none;
57
+ -moz-user-select: none;
58
+ -ms-user-select: none;
59
+ user-select: none;
60
+ background-color: white;
61
+ }
@@ -0,0 +1,36 @@
1
+ const DefaultConfig = {
2
+ data: [],
3
+ highlighted: [],
4
+ marked: [],
5
+ dimensions: {},
6
+ dimensionTitleRotation: 0,
7
+ brushes: [],
8
+ brushed: false,
9
+ brushedColor: null,
10
+ alphaOnBrushed: 0.0,
11
+ lineWidth: 1.4,
12
+ highlightedLineWidth: 3,
13
+ mode: 'default',
14
+ markedLineWidth: 3,
15
+ markedShadowColor: '#ffffff',
16
+ markedShadowBlur: 10,
17
+ rate: 20,
18
+ width: 600,
19
+ height: 300,
20
+ margin: { top: 24, right: 20, bottom: 12, left: 20 },
21
+ nullValueSeparator: 'undefined', // set to "top" or "bottom"
22
+ nullValueSeparatorPadding: { top: 8, right: 0, bottom: 8, left: 0 },
23
+ color: '#069',
24
+ composite: 'source-over',
25
+ alpha: 0.7,
26
+ bundlingStrength: 0.5,
27
+ bundleDimension: null,
28
+ smoothness: 0.0,
29
+ showControlPoints: false,
30
+ hideAxis: [],
31
+ flipAxes: [],
32
+ animationTime: 1100, // How long it takes to flip the axis when you double click
33
+ rotateLabels: false,
34
+ };
35
+
36
+ export default DefaultConfig;
@@ -0,0 +1,86 @@
1
+ import { axisLeft } from 'd3-axis';
2
+ import { dispatch } from 'd3-dispatch';
3
+ import { scalePoint } from 'd3-scale';
4
+
5
+ import DefaultConfig from './defaultConfig';
6
+
7
+ const initState = userConfig => {
8
+ const config = Object.assign({}, DefaultConfig, userConfig);
9
+
10
+ if (userConfig && userConfig.dimensionTitles) {
11
+ console.warn(
12
+ 'dimensionTitles passed in userConfig is deprecated. Add title to dimension object.'
13
+ );
14
+ Object.entries(userConfig.dimensionTitles).forEach(([key, value]) => {
15
+ if (config.dimensions[key]) {
16
+ config.dimensions[key].title = config.dimensions[key].title
17
+ ? config.dimensions[key].title
18
+ : value;
19
+ } else {
20
+ config.dimensions[key] = {
21
+ title: value,
22
+ };
23
+ }
24
+ });
25
+ }
26
+
27
+ const eventTypes = [
28
+ 'render',
29
+ 'resize',
30
+ 'highlight',
31
+ 'mark',
32
+ 'brush',
33
+ 'brushend',
34
+ 'brushstart',
35
+ 'axesreorder',
36
+ ].concat(Object.keys(config));
37
+
38
+ const events = dispatch.apply(this, eventTypes),
39
+ flags = {
40
+ brushable: false,
41
+ reorderable: false,
42
+ axes: false,
43
+ interactive: false,
44
+ debug: false,
45
+ },
46
+ xscale = scalePoint(),
47
+ dragging = {},
48
+ axis = axisLeft().ticks(5),
49
+ ctx = {},
50
+ canvas = {};
51
+
52
+ const brush = {
53
+ modes: {
54
+ None: {
55
+ install: function(pc) {}, // Nothing to be done.
56
+ uninstall: function(pc) {}, // Nothing to be done.
57
+ selected: function() {
58
+ return [];
59
+ }, // Nothing to return
60
+ brushState: function() {
61
+ return {};
62
+ },
63
+ },
64
+ },
65
+ mode: 'None',
66
+ predicate: 'AND',
67
+ currentMode: function() {
68
+ return this.modes[this.mode];
69
+ },
70
+ };
71
+
72
+ return {
73
+ config,
74
+ events,
75
+ eventTypes,
76
+ flags,
77
+ xscale,
78
+ dragging,
79
+ axis,
80
+ ctx,
81
+ canvas,
82
+ brush,
83
+ };
84
+ };
85
+
86
+ export default initState;