@pie-lib/plot 4.0.4-next.3 → 4.0.4-next.31

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 (59) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +20 -0
  2. package/dist/draggable.d.ts +13 -0
  3. package/dist/draggable.js +13 -0
  4. package/dist/graph-props.d.ts +22 -0
  5. package/dist/graph-props.js +29 -0
  6. package/dist/grid-draggable.d.ts +91 -0
  7. package/dist/grid-draggable.js +168 -0
  8. package/dist/index.d.ts +16 -0
  9. package/dist/index.js +8 -0
  10. package/dist/label.d.ts +30 -0
  11. package/dist/label.js +132 -0
  12. package/dist/node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js +16 -0
  13. package/dist/node_modules/.bun/invariant@2.2.4/node_modules/invariant/browser.js +28 -0
  14. package/dist/node_modules/.bun/react-draggable@4.6.0_6dbf9a050bc9aadb/node_modules/react-draggable/build/cjs/chunk-D5BXCJ5G.js +503 -0
  15. package/dist/node_modules/.bun/react-draggable@4.6.0_6dbf9a050bc9aadb/node_modules/react-draggable/build/cjs/cjs.js +5 -0
  16. package/dist/root.d.ts +68 -0
  17. package/dist/root.js +302 -0
  18. package/dist/trig.d.ts +41 -0
  19. package/dist/trig.js +47 -0
  20. package/dist/types.d.ts +125 -0
  21. package/dist/types.js +46 -0
  22. package/dist/utils.d.ts +44 -0
  23. package/dist/utils.js +82 -0
  24. package/package.json +35 -25
  25. package/CHANGELOG.json +0 -17
  26. package/CHANGELOG.md +0 -838
  27. package/LICENSE.md +0 -5
  28. package/lib/draggable.js +0 -44
  29. package/lib/draggable.js.map +0 -1
  30. package/lib/graph-props.js +0 -46
  31. package/lib/graph-props.js.map +0 -1
  32. package/lib/grid-draggable.js +0 -361
  33. package/lib/grid-draggable.js.map +0 -1
  34. package/lib/index.js +0 -44
  35. package/lib/index.js.map +0 -1
  36. package/lib/label.js +0 -173
  37. package/lib/label.js.map +0 -1
  38. package/lib/root.js +0 -474
  39. package/lib/root.js.map +0 -1
  40. package/lib/trig.js +0 -149
  41. package/lib/trig.js.map +0 -1
  42. package/lib/types.js +0 -40
  43. package/lib/types.js.map +0 -1
  44. package/lib/utils.js +0 -165
  45. package/lib/utils.js.map +0 -1
  46. package/src/__tests__/draggable.test.jsx +0 -41
  47. package/src/__tests__/grid-draggable.test.jsx +0 -487
  48. package/src/__tests__/root.test.jsx +0 -277
  49. package/src/__tests__/trig.test.js +0 -163
  50. package/src/__tests__/utils.test.js +0 -229
  51. package/src/draggable.jsx +0 -11
  52. package/src/graph-props.js +0 -34
  53. package/src/grid-draggable.jsx +0 -332
  54. package/src/index.js +0 -9
  55. package/src/label.jsx +0 -199
  56. package/src/root.jsx +0 -485
  57. package/src/trig.js +0 -151
  58. package/src/types.js +0 -41
  59. package/src/utils.js +0 -167
@@ -1,34 +0,0 @@
1
- import invariant from 'invariant';
2
- import { snapTo } from './utils';
3
- import { scaleLinear } from 'd3-scale';
4
-
5
- const createSnapMinAndMax = ({ min, max, step }) => {
6
- // for graphing, if step is a value with decimals, we have to calculate the min & max for the grid taking in consideration that 0 has to be exactly in the middle
7
- // for example, if min: -5 & max: 5 & step: 0.75, in order to keep 0 in the middle we have to set min: -4.5 & max: 4.5
8
-
9
- return {
10
- step,
11
- min: parseInt(min / step) * step,
12
- max: parseInt(max / step) * step,
13
- };
14
- };
15
-
16
- export const create = (domain, range, size, getRootNode) => {
17
- invariant(domain.min < domain.max, 'domain: min must be less than max');
18
- invariant(range.min < range.max, 'range: min must be less than max');
19
-
20
- const domainMinMax = createSnapMinAndMax(domain);
21
- const rangeMinMax = createSnapMinAndMax(range);
22
-
23
- const scale = {
24
- x: scaleLinear().domain([domain.min, domain.max]).range([0, size.width]),
25
- y: scaleLinear().domain([range.max, range.min]).range([0, size.height]),
26
- };
27
-
28
- const snap = {
29
- x: snapTo.bind(null, domainMinMax.min, domainMinMax.max, domainMinMax.step),
30
- y: snapTo.bind(null, rangeMinMax.min, rangeMinMax.max, rangeMinMax.step),
31
- };
32
-
33
- return { scale, snap, domain, range, size, getRootNode };
34
- };
@@ -1,332 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { GraphPropsType } from './types';
4
- import { DraggableCore } from './draggable';
5
- import debug from 'debug';
6
- import * as utils from './utils';
7
- import { isFunction } from 'lodash-es';
8
- import invariant from 'invariant';
9
- import { pointer } from 'd3-selection';
10
-
11
- const log = debug('pie-lib:plot:grid-draggable');
12
-
13
- export const deltaFn = (scale, snap, val) => (delta) => {
14
- const normalized = delta + scale(0);
15
- const inverted = scale.invert(normalized);
16
-
17
- const fixDecimalsArithmetic = (snap(val + inverted).toFixed(4) * 1000) / 1000;
18
-
19
- return fixDecimalsArithmetic;
20
- };
21
-
22
- /**
23
- * Creates a Component that is draggable, within a bounded grid.
24
- * @param {*} opts
25
- */
26
- export const gridDraggable = (opts) => (Comp) => {
27
- invariant(
28
- !!opts && isFunction(opts.fromDelta) && isFunction(opts.bounds) && isFunction(opts.anchorPoint),
29
- 'You must supply an object with: { anchorPoint: Function, fromDelta: Function, bounds: Function }',
30
- );
31
- return class GridDraggable extends React.Component {
32
- static propTypes = {
33
- disabled: PropTypes.bool,
34
- onDragStart: PropTypes.func,
35
- onDrag: PropTypes.func,
36
- onDragStop: PropTypes.func,
37
- onClick: PropTypes.func,
38
- onMove: PropTypes.func,
39
- graphProps: GraphPropsType.isRequired,
40
- };
41
-
42
- constructor(props) {
43
- super(props);
44
- this.state = {
45
- startX: null,
46
- startY: null,
47
- };
48
- }
49
-
50
- grid = () => {
51
- const { graphProps } = this.props;
52
- const { scale, domain, range } = graphProps;
53
- return {
54
- x: scale.x(domain.step) - scale.x(0),
55
- y: scale.y(range.step) - scale.y(0),
56
- };
57
- };
58
- onStart = (e) => {
59
- const { onDragStart } = this.props;
60
- if (document.activeElement) {
61
- document.activeElement.blur();
62
- }
63
- this._didDrag = false;
64
- this.setState({ startX: e.clientX, startY: e.clientY });
65
-
66
- // Intercept the native 'click' event that the browser fires after mouseup.
67
- // We use a one-time capture-phase listener so we can suppress it when a
68
- // real drag occurred, preventing Bg's d3 click listener from creating a new mark.
69
- const target = e.target;
70
- const onNativeClick = (clickEvent) => {
71
- target.removeEventListener('click', onNativeClick, true);
72
- if (this._didDrag) {
73
- clickEvent.stopPropagation();
74
- clickEvent.preventDefault();
75
- }
76
- };
77
- target.addEventListener('click', onNativeClick, true);
78
-
79
- if (onDragStart) {
80
- onDragStart();
81
- }
82
- };
83
- position = () => {
84
- const { x, y } = opts.anchorPoint(this.props);
85
- const { graphProps } = this.props;
86
- const { scale, snap } = graphProps;
87
-
88
- return {
89
- anchorPoint: {
90
- x,
91
- y,
92
- },
93
- x: deltaFn(scale.x, snap.x, x),
94
- y: deltaFn(scale.y, snap.y, y),
95
- };
96
- };
97
-
98
- tiny = (key, event) => {
99
- const K = key.toUpperCase();
100
- const end = event[`client${K}`];
101
- const start = this.state[`start${K}`];
102
- const delta = Math.abs(end - start);
103
- const out = delta < Math.abs(this.grid()[key]) / 10;
104
- log('[tiny] key: ', key, 'delta: ', delta, 'out: ', out);
105
- return out;
106
- };
107
-
108
- getScaledBounds = () => {
109
- const bounds = opts.bounds(this.props, this.props.graphProps);
110
- log('bounds: ', bounds);
111
- const grid = this.grid();
112
-
113
- let scaled = {
114
- left: bounds.left * grid.x,
115
- right: bounds.right * grid.x,
116
- top: bounds.top * grid.y,
117
- bottom: bounds.bottom * grid.y,
118
- };
119
-
120
- // Normalize Y bounds so that:
121
- // - top is <= 0 (negative or zero, allowing upward movement)
122
- // - bottom is >= 0 (positive or zero, allowing downward movement)
123
- // This compensates for the inverted Y scale (range.max -> 0, range.min -> size.height)
124
- // Add a small buffer (1 grid unit) to ensure we can reach exact boundaries
125
- const buffer = Math.abs(grid.y);
126
- scaled = {
127
- ...scaled,
128
- top: Math.min(0, scaled.top) - buffer, // More negative to allow reaching max
129
- bottom: Math.abs(scaled.bottom) + buffer, // More positive to allow reaching min
130
- };
131
-
132
- log('[getScaledBounds]: ', scaled);
133
- return scaled;
134
- };
135
-
136
- /**
137
- * Retrieves the coordinates of a mouse or touch event relative to an SVG element.
138
- * This method has been overwritten from the d3-selection library's clientPoint to handle touch events and improve clarity.
139
- * @param {Element} node - The SVG element.
140
- * @param {Event} event - The mouse or touch event.
141
- * @returns {Array} - An array containing the coordinates [x, y] relative to the SVG element.
142
- */
143
- getClientPoint = (node, event) => {
144
- if (!node || !event) {
145
- return null;
146
- }
147
- const svg = node.ownerSVGElement || node;
148
-
149
- if (svg && svg.createSVGPoint) {
150
- let point = svg.createSVGPoint();
151
- // Check if it's a touch event and use the first touch point
152
- if (event.touches && event.touches.length > 0) {
153
- const touch = event.touches[0];
154
- point.x = touch.clientX;
155
- point.y = touch.clientY;
156
- } else {
157
- // Fall back to mouse event properties
158
- point.x = event.clientX;
159
- point.y = event.clientY;
160
- }
161
- if (node.getScreenCTM) {
162
- point = point.matrixTransform(node.getScreenCTM().inverse());
163
- return [point.x, point.y];
164
- } else {
165
- return null;
166
- }
167
- }
168
-
169
- const rect = node.getBoundingClientRect();
170
- if (rect) {
171
- return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
172
- } else {
173
- return null;
174
- }
175
- };
176
-
177
- skipDragOutsideOfBounds = (dd, e, graphProps) => {
178
- // Ignore drag movement outside of the domain and range.
179
- const rootNode = graphProps.getRootNode();
180
- const clientPoint = this.getClientPoint(rootNode, e);
181
-
182
- if (clientPoint === null) {
183
- return true; // Indicate that the drag is outside of bounds
184
- }
185
-
186
- const [rawX, rawY] = clientPoint;
187
- const { scale, domain, range } = graphProps;
188
- let x = scale.x.invert(rawX);
189
- let y = scale.y.invert(rawY);
190
-
191
- const xOutside = (dd.deltaX > 0 && x < domain.min) || (dd.deltaX < 0 && x > domain.max);
192
- const yOutside = (dd.deltaY > 0 && y > range.max) || (dd.deltaY < 0 && y < range.min);
193
- return xOutside || yOutside;
194
- };
195
-
196
- onDrag = (e, dd) => {
197
- const { onDrag, graphProps, disabled } = this.props;
198
-
199
- // Track drag movement BEFORE any early returns so that onStop always
200
- // knows a real drag occurred, even when onDrag prop is absent or disabled.
201
- if (Math.abs(dd.deltaX) > 1 || Math.abs(dd.deltaY) > 1) {
202
- this._didDrag = true;
203
- }
204
-
205
- if (!onDrag || disabled) {
206
- return;
207
- }
208
-
209
- const bounds = this.getScaledBounds();
210
-
211
- if (dd.deltaX < 0 && dd.deltaX < bounds.left) {
212
- return;
213
- }
214
-
215
- if (dd.deltaX > 0 && dd.deltaX > bounds.right) {
216
- return;
217
- }
218
-
219
- if (dd.deltaY < 0 && dd.deltaY < bounds.top) {
220
- return;
221
- }
222
-
223
- if (dd.deltaY > 0 && dd.deltaY > bounds.bottom) {
224
- return;
225
- }
226
-
227
- if (this.skipDragOutsideOfBounds(dd, e, graphProps)) {
228
- return;
229
- }
230
-
231
- const dragArg = this.applyDelta({ x: dd.deltaX, y: dd.deltaY });
232
-
233
- if (dragArg !== undefined || dragArg !== null) {
234
- onDrag(dragArg);
235
- }
236
- };
237
-
238
- getDelta = (point) => {
239
- const pos = this.position();
240
-
241
- const p = {
242
- x: pos.x(point.x),
243
- y: pos.y(point.y),
244
- };
245
-
246
- return utils.getDelta(pos.anchorPoint, p);
247
- };
248
-
249
- applyDelta = (point) => {
250
- const delta = this.getDelta(point);
251
- log('[applyDelta] delta:', delta);
252
- return opts.fromDelta(this.props, delta);
253
- };
254
-
255
- onStop = (e, dd) => {
256
- log('[onStop] dd:', dd);
257
- const { onDragStop, onClick, disabled } = this.props;
258
-
259
- if (onDragStop && !disabled) {
260
- onDragStop();
261
- }
262
-
263
- log('[onStop] lastX/Y: ', dd.lastX, dd.lastY);
264
- const isClick = !this._didDrag;
265
-
266
- if (isClick) {
267
- // For non-disabled marks, stop propagation so the Bg d3 listener
268
- // doesn't also create a new mark on top of this one.
269
- // Disabled/background marks allow propagation so Bg can handle the click.
270
- if (!disabled && typeof e?.stopPropagation === 'function') {
271
- e.stopPropagation();
272
- }
273
-
274
- if (onClick) {
275
- log('call onClick');
276
- this.setState({ startX: null, startY: null });
277
- const { graphProps } = this.props;
278
- const { scale, snap } = graphProps;
279
- try {
280
- const [rawX, rawY] = pointer(e, e.target);
281
- let x = scale.x.invert(rawX);
282
- let y = scale.y.invert(rawY);
283
- x = snap.x(x);
284
- y = snap.y(y);
285
- onClick({ x, y });
286
- } catch (_) {
287
- // pointer() can fail on SVG elements (e.g. <circle>) that lack a valid
288
- // coordinate transform. Label-mode callbacks use props data, not coords.
289
- onClick({});
290
- }
291
- }
292
-
293
- return false;
294
- }
295
-
296
- this.setState({ startX: null, startY: null });
297
- // return false to prevent state updates in the underlying draggable - a move will have triggered an update already.
298
- return false;
299
- };
300
-
301
- render() {
302
- // we extract onClick here to prevent it from being passed to the DraggableCore
303
- // and to prevent it from being included in the ...rest that gets passed to the Comp
304
- // because otherwise it is called on every drag event
305
- // eslint-disable-next-line no-unused-vars
306
- const { disabled, onClick, ...rest } = this.props;
307
- const grid = this.grid();
308
-
309
- // prevent the text select icon from rendering.
310
- const onMouseDown = (e) => e.nativeEvent.preventDefault();
311
-
312
- /**
313
- * TODO: This shouldnt be necessary, we should be able to use the r-d classnames.
314
- * But they aren't being unset. If we continue with this lib, we'll have to fix this.
315
- */
316
- const isDragging = this.state ? !!this.state.startX : false;
317
-
318
- return (
319
- <DraggableCore
320
- onMouseDown={onMouseDown}
321
- onStart={this.onStart}
322
- onDrag={this.onDrag}
323
- onStop={this.onStop}
324
- axis={opts.axis || 'both'}
325
- grid={[grid.x, grid.y]}
326
- >
327
- <Comp {...rest} disabled={disabled} isDragging={isDragging} onClick={isDragging ? undefined : onClick} />
328
- </DraggableCore>
329
- );
330
- }
331
- };
332
- };
package/src/index.js DELETED
@@ -1,9 +0,0 @@
1
- import Root from './root';
2
- import Draggable from './draggable';
3
- import { gridDraggable } from './grid-draggable';
4
- import * as utils from './utils';
5
- import * as trig from './trig';
6
- import * as types from './types';
7
- import { create as createGraphProps } from './graph-props';
8
-
9
- export { Root, Draggable, gridDraggable, utils, trig, types, createGraphProps };
package/src/label.jsx DELETED
@@ -1,199 +0,0 @@
1
- import React, { useState } from 'react';
2
- import { styled } from '@mui/material/styles';
3
- import { Readable } from '@pie-lib/render-ui';
4
- import EditableHtml from '@pie-lib/editable-html-tip-tap';
5
- import PropTypes from 'prop-types';
6
- import { extractTextFromHTML, isEmptyString } from './utils';
7
-
8
- const styles = {
9
- axisLabel: {
10
- fontSize: 12,
11
- textAlign: 'center',
12
- margin: 4,
13
- padding: '4px 0',
14
- },
15
- chartLabel: {
16
- fontSize: 16,
17
- textAlign: 'center',
18
- margin: 4,
19
- padding: '4px 0',
20
- },
21
- disabledLabel: {
22
- pointerEvents: 'none',
23
- width: '100%',
24
- },
25
- editLabel: {
26
- position: 'absolute',
27
- backgroundColor: 'white',
28
- borderRadius: 4,
29
- boxShadow: '0px 5px 8px rgba(0,0,0,0.15)',
30
- zIndex: 10,
31
- },
32
- rotateLeftLabel: {
33
- transform: 'rotate(-90deg)',
34
- transformOrigin: '0 0',
35
- position: 'absolute',
36
- },
37
- rotateRightLabel: {
38
- transform: 'rotate(90deg)',
39
- transformOrigin: '0 0',
40
- position: 'absolute',
41
- },
42
- customBottom: {
43
- position: 'absolute',
44
- },
45
- displayNone: {
46
- display: 'none',
47
- },
48
- centerPlaceholder: {
49
- '& .ProseMirror p.is-editor-empty::before, & .ProseMirror div.is-editor-empty::before': {
50
- left: 0,
51
- right: 0,
52
- width: '100%',
53
- textAlign: 'center',
54
- },
55
- },
56
- };
57
-
58
-
59
- const LabelWrapper = styled('div')({
60
- ...styles.centerPlaceholder,
61
- });
62
-
63
- const LabelContent = styled('div')({
64
- ...styles.disabledLabel,
65
- '& p': {
66
- margin: 0,
67
- },
68
- });
69
-
70
- const LabelComponent = (props) => {
71
- const {
72
- disabledLabel,
73
- graphHeight,
74
- graphWidth,
75
- isChartBottomLabel,
76
- isDefineChartBottomLabel,
77
- isChartLeftLabel,
78
- isDefineChartLeftLabel,
79
- placeholder,
80
- text,
81
- side,
82
- onChange,
83
- mathMlOptions = {},
84
- charactersLimit,
85
- titleHeight,
86
- preventNewLines,
87
- } = props;
88
-
89
- const [rotatedToHorizontal, setRotatedToHorizontal] = useState(false);
90
-
91
- const activePlugins = ['bold', 'italic', 'underline', 'strikethrough', 'math'];
92
-
93
- const isChart = isChartBottomLabel || isChartLeftLabel || isDefineChartBottomLabel || isDefineChartLeftLabel;
94
-
95
- const chartValue = side === 'left' && isDefineChartLeftLabel && graphHeight - 220;
96
-
97
- const defaultStyle = {
98
- width: chartValue || (side === 'left' || side === 'right' ? graphHeight - 8 : graphWidth - 8),
99
- top:
100
- chartValue ||
101
- (isChartLeftLabel && `${graphHeight - 70}px`) ||
102
- (side === 'left' && `${graphHeight - 8}px`) ||
103
- (isChartBottomLabel && `${graphHeight - 60 + titleHeight}px`) ||
104
- (side === 'bottom' && `${graphHeight - 120 + titleHeight}px`) ||
105
- 0,
106
- left:
107
- (side === 'right' && `${graphWidth - 8}px`) ||
108
- ((isDefineChartLeftLabel || isDefineChartBottomLabel) && '40px') ||
109
- (isChartBottomLabel && '-10px') ||
110
- 0,
111
- };
112
-
113
- const rotatedStyle = {
114
- width: graphWidth - 8,
115
- top: side === 'right' ? `${graphHeight - 22}px` : 0,
116
- left: 0,
117
- };
118
-
119
- const rotateLabel = () => {
120
- if (!disabledLabel && (side === 'left' || side === 'right')) {
121
- setRotatedToHorizontal(true);
122
- }
123
- };
124
-
125
- const exitEditMode = () => {
126
- setRotatedToHorizontal(false);
127
-
128
- // blur active element because rotation is causing editing issues on exit
129
- requestAnimationFrame(() => {
130
- document.activeElement?.blur?.();
131
- });
132
- };
133
-
134
- const onKeyDown = (event) => {
135
- if (preventNewLines && event.key === 'Enter') {
136
- // prevent adding new lines - cancelling event
137
- return true;
138
- }
139
-
140
- return false;
141
- };
142
-
143
- return (
144
- <Readable false>
145
- <LabelWrapper
146
- onClick={rotateLabel}
147
- style={{
148
- ...(rotatedToHorizontal ? rotatedStyle : defaultStyle),
149
- ...(isChart ? styles.chartLabel : styles.axisLabel),
150
- ...(side === 'left' && !rotatedToHorizontal ? styles.rotateLeftLabel : {}),
151
- ...(side === 'right' && !rotatedToHorizontal ? styles.rotateRightLabel : {}),
152
- ...(rotatedToHorizontal ? styles.editLabel : {}),
153
- ...(isChartBottomLabel || isDefineChartBottomLabel ? styles.customBottom : {}),
154
- ...(disabledLabel && !isChart && isEmptyString(extractTextFromHTML(text)) && styles.displayNone),
155
- }}
156
- >
157
- {disabledLabel ? (
158
- <LabelContent dangerouslySetInnerHTML={{ __html: text || '' }} />
159
- ) : (
160
- <EditableHtml
161
- markup={text || ''}
162
- onChange={onChange}
163
- placeholder={!disabledLabel && placeholder}
164
- toolbarOpts={{
165
- position: side === 'bottom' ? 'top' : 'bottom',
166
- noPadding: true,
167
- noBorder: true,
168
- }}
169
- disableScrollbar
170
- activePlugins={activePlugins}
171
- onDone={exitEditMode}
172
- onKeyDown={onKeyDown}
173
- mathMlOptions={mathMlOptions}
174
- charactersLimit={charactersLimit}
175
- />
176
- )}
177
- </LabelWrapper>
178
- </Readable>
179
- );
180
- };
181
-
182
- LabelComponent.propTypes = {
183
- disabledLabel: PropTypes.bool,
184
- graphHeight: PropTypes.number,
185
- graphWidth: PropTypes.number,
186
- isChartBottomLabel: PropTypes.bool,
187
- isDefineChartBottomLabel: PropTypes.bool,
188
- isChartLeftLabel: PropTypes.bool,
189
- isDefineChartLeftLabel: PropTypes.bool,
190
- placeholder: PropTypes.string,
191
- text: PropTypes.string,
192
- side: PropTypes.string,
193
- onChange: PropTypes.func,
194
- mathMlOptions: PropTypes.object,
195
- charactersLimit: PropTypes.number,
196
- titleHeight: PropTypes.number,
197
- };
198
-
199
- export default LabelComponent;