td-plots 1.0.2 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -19
- package/dist/components/Histogram.d.ts +5 -1
- package/dist/components/RadialHistogram.d.ts +14 -0
- package/dist/components/Utils.d.ts +4 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +262 -22
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +261 -20
- package/dist/index.js.map +1 -1
- package/package.json +23 -13
- package/dist/index.css +0 -1
- package/dist/index.esm.css +0 -1
package/README.md
CHANGED
|
@@ -1,41 +1,153 @@
|
|
|
1
1
|
# td-plots
|
|
2
2
|
|
|
3
|
-
A React + TypeScript component library for interactive Plotly.js charts, with Storybook documentation and
|
|
3
|
+
A React + TypeScript component library for interactive Plotly.js charts, with Storybook documentation and comprehensive testing.
|
|
4
4
|
|
|
5
|
+
[](https://github.com/asizemore/td-plots/actions/workflows/ci.yml)
|
|
6
|
+
[](https://badge.fury.io/js/td-plots)
|
|
5
7
|
|
|
6
|
-
## Getting Started
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install td-plots
|
|
13
|
+
# or
|
|
14
|
+
yarn add td-plots
|
|
15
|
+
# or
|
|
16
|
+
pnpm add td-plots
|
|
11
17
|
```
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
## Development
|
|
20
|
+
### Prerequisites
|
|
21
|
+
|
|
22
|
+
- Node.js 18+
|
|
23
|
+
- pnpm 8+
|
|
24
|
+
|
|
25
|
+
### Setup
|
|
26
|
+
|
|
27
|
+
1. **Clone the repository**
|
|
28
|
+
```bash
|
|
29
|
+
git clone https://github.com/asizemore/td-plots.git
|
|
30
|
+
cd td-plots
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
2. **Install dependencies**
|
|
34
|
+
```bash
|
|
35
|
+
pnpm install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
3. **Set up environment variables**
|
|
39
|
+
Copy `.env.sample` to `.env` and configure:
|
|
40
|
+
```bash
|
|
41
|
+
CHROMATIC_PROJECT_TOKEN=your_chromatic_token_here
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Development Commands
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Start Storybook development server
|
|
15
48
|
pnpm storybook
|
|
16
|
-
```
|
|
17
49
|
|
|
18
|
-
|
|
19
|
-
```sh
|
|
50
|
+
# Build the library
|
|
20
51
|
pnpm run build
|
|
52
|
+
|
|
53
|
+
# Run tests
|
|
54
|
+
pnpm test
|
|
55
|
+
|
|
56
|
+
# Run tests in watch mode
|
|
57
|
+
pnpm test --watch
|
|
58
|
+
|
|
59
|
+
# Build Storybook for production
|
|
60
|
+
pnpm build-storybook
|
|
61
|
+
|
|
62
|
+
# Publish to Chromatic (visual testing)
|
|
63
|
+
pnpm chromatic
|
|
21
64
|
```
|
|
22
65
|
|
|
23
|
-
|
|
66
|
+
### Local Development Linking
|
|
67
|
+
|
|
68
|
+
To use this package in another local project during development:
|
|
69
|
+
|
|
70
|
+
1. **In this package directory:**
|
|
71
|
+
```bash
|
|
72
|
+
pnpm link --global
|
|
73
|
+
```
|
|
24
74
|
|
|
25
|
-
|
|
75
|
+
2. **In your target project:**
|
|
76
|
+
```bash
|
|
77
|
+
pnpm link td-plots
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Alternatively, you can link directly (I have best results with this):
|
|
81
|
+
```bash
|
|
82
|
+
pnpm add file:../td-plots
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Build `td-plots` and watch for new changes with
|
|
86
|
+
```bash
|
|
87
|
+
pnpm dev:full
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
If the target project doesn't see the new updates, try unlinking and relinking, or clearing cache
|
|
91
|
+
```bash
|
|
92
|
+
# Clear Parcel cache
|
|
93
|
+
rm -rf .parcel-cache
|
|
94
|
+
rm -rf dist
|
|
95
|
+
```
|
|
96
|
+
and then restarting the target project.
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
To unlink, run
|
|
100
|
+
```bash
|
|
101
|
+
pnpm unlink td-plots
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
## Components
|
|
107
|
+
|
|
108
|
+
### HistogramPlot
|
|
109
|
+
|
|
110
|
+
Interactive histogram component with click and selection event handling.
|
|
26
111
|
|
|
27
112
|
```tsx
|
|
28
|
-
import {
|
|
113
|
+
import { HistogramPlot } from 'td-plots';
|
|
29
114
|
|
|
30
|
-
|
|
31
|
-
|
|
115
|
+
function MyComponent() {
|
|
116
|
+
const data = [1, 2, 3, 4, 5, 2, 3, 4, 1, 2];
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<HistogramPlot
|
|
120
|
+
data={data}
|
|
121
|
+
title="My Histogram"
|
|
122
|
+
xAxisTitle="Values"
|
|
123
|
+
barColor="rgb(72, 72, 74)"
|
|
124
|
+
onClick={(event) => console.log('Clicked:', event)}
|
|
125
|
+
onSelected={(event) => console.log('Selected:', event)}
|
|
126
|
+
/>
|
|
127
|
+
);
|
|
32
128
|
}
|
|
33
129
|
```
|
|
34
130
|
|
|
35
|
-
## Project Structure
|
|
36
|
-
- `src/components/` – Plot components (e.g., `TestPlot.tsx`)
|
|
37
|
-
- `stories/` – Storybook stories for components
|
|
38
131
|
|
|
39
132
|
|
|
133
|
+
|
|
134
|
+
## Testing
|
|
135
|
+
|
|
136
|
+
This package uses vitest for testing.
|
|
137
|
+
|
|
138
|
+
Run tests locally:
|
|
139
|
+
```bash
|
|
140
|
+
pnpm test # Run all tests
|
|
141
|
+
pnpm test --ui # Run with Vitest UI
|
|
142
|
+
pnpm test --coverage # Run with coverage report
|
|
143
|
+
```
|
|
144
|
+
|
|
40
145
|
## License
|
|
41
|
-
|
|
146
|
+
|
|
147
|
+
MIT
|
|
148
|
+
|
|
149
|
+
## Support
|
|
150
|
+
|
|
151
|
+
- 📖 [Storybook Documentation](https://main--6871481055cbf1b95be162e1.chromatic.com)
|
|
152
|
+
- 🐛 [Issue Tracker](https://github.com/asizemore/td-plots/issues)
|
|
153
|
+
- 💬 [Discussions](https://github.com/asizemore/td-plots/discussions)
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import './plotStyles.scss';
|
|
2
3
|
export type HistogramPlotProps = {
|
|
3
|
-
data: number[];
|
|
4
|
+
data: number[] | Date[];
|
|
5
|
+
showMeanLine?: boolean;
|
|
6
|
+
meanLineColor?: string;
|
|
4
7
|
title?: string;
|
|
5
8
|
xAxisTitle?: string;
|
|
6
9
|
barColor?: string;
|
|
@@ -8,6 +11,7 @@ export type HistogramPlotProps = {
|
|
|
8
11
|
selectorsColor?: string;
|
|
9
12
|
onSelected?: (event: Plotly.PlotSelectionEvent) => void;
|
|
10
13
|
onClick?: (event: Plotly.PlotMouseEvent) => void;
|
|
14
|
+
containerStyleOverrides?: React.CSSProperties;
|
|
11
15
|
};
|
|
12
16
|
export declare const HistogramPlot: (props: HistogramPlotProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
17
|
export default HistogramPlot;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import './plotStyles.scss';
|
|
3
|
+
export type RadialHistogramPlotProps = {
|
|
4
|
+
data: number[];
|
|
5
|
+
barColor?: string;
|
|
6
|
+
unselectedBarColor?: string;
|
|
7
|
+
selectorsColor?: string;
|
|
8
|
+
onSelected?: (event: Plotly.PlotSelectionEvent) => void;
|
|
9
|
+
onClick?: (event: Plotly.PlotMouseEvent) => void;
|
|
10
|
+
containerStyleOverrides?: React.CSSProperties;
|
|
11
|
+
barWidth?: number;
|
|
12
|
+
};
|
|
13
|
+
export declare const RadialHistogramPlot: (props: RadialHistogramPlotProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
14
|
+
export default RadialHistogramPlot;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const isNumberArray: (arr: unknown[]) => arr is number[];
|
|
2
|
+
export declare const isDateArray: (arr: unknown[]) => arr is Date[];
|
|
3
|
+
export declare function calculateMean(arr: number[] | Date[]): number | undefined;
|
|
4
|
+
export declare const formatDateMDY: (timestamp: number) => string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import './components/plotStyles.scss';
|
|
1
2
|
export { HistogramPlot } from './components/Histogram';
|
|
2
3
|
export type { HistogramPlotProps } from './components/Histogram';
|
|
4
|
+
export { RadialHistogramPlot } from './components/RadialHistogram';
|
|
5
|
+
export type { RadialHistogramPlotProps } from './components/RadialHistogram';
|
|
3
6
|
export { default as TestPlot } from './components/TestPlot';
|
|
4
7
|
export type { PlotParams } from 'react-plotly.js';
|
package/dist/index.esm.js
CHANGED
|
@@ -1,23 +1,97 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { lazy, Suspense } from 'react';
|
|
2
|
+
import { lazy, useRef, Suspense } from 'react';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
function styleInject(css, ref) {
|
|
5
|
+
if ( ref === void 0 ) ref = {};
|
|
6
|
+
var insertAt = ref.insertAt;
|
|
7
|
+
|
|
8
|
+
if (typeof document === 'undefined') { return; }
|
|
9
|
+
|
|
10
|
+
var head = document.head || document.getElementsByTagName('head')[0];
|
|
11
|
+
var style = document.createElement('style');
|
|
12
|
+
style.type = 'text/css';
|
|
13
|
+
|
|
14
|
+
if (insertAt === 'top') {
|
|
15
|
+
if (head.firstChild) {
|
|
16
|
+
head.insertBefore(style, head.firstChild);
|
|
17
|
+
} else {
|
|
18
|
+
head.appendChild(style);
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
head.appendChild(style);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (style.styleSheet) {
|
|
25
|
+
style.styleSheet.cssText = css;
|
|
26
|
+
} else {
|
|
27
|
+
style.appendChild(document.createTextNode(css));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
var css_248z = ".plot-container{height:100%;max-width:100%;min-height:300px;overflow:hidden!important;position:relative;width:100%}.plot-container>div{flex:1;height:100%!important;width:100%!important}.plot-container .main-svg{max-height:100%!important;max-width:100%!important}.plot-container .main-svg,.plot-container .plotly-graph-div,.plot-container svg.main-svg[height],.plot-container svg.main-svg[width]{height:100%!important;width:100%!important}.plot-container .point{border-radius:5px!important;overflow:hidden!important}.plot-container .cursor-ns-resize{height:0;width:0}.plot-container .cursor-ew-resize{fill:var(--selection-color,blue)!important;stroke:var(--selection-color,blue)!important}.plot-container .selectionlayer>path{stroke:var(--selection-color,blue)!important;stroke-dasharray:0!important;stroke-width:1px!important;opacity:.5!important}.plot-container .zoomlayer>path{stroke-dasharray:0!important;stroke:var(--selection-color,blue)!important;fill:var(--selection-color,blue)!important}.radial-histogram-container{aspect-ratio:1}";
|
|
32
|
+
styleInject(css_248z);
|
|
33
|
+
|
|
34
|
+
/******************************************************************************
|
|
35
|
+
Copyright (c) Microsoft Corporation.
|
|
36
|
+
|
|
37
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
38
|
+
purpose with or without fee is hereby granted.
|
|
39
|
+
|
|
40
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
41
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
42
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
43
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
44
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
45
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
46
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
47
|
+
***************************************************************************** */
|
|
48
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
var __assign = function() {
|
|
52
|
+
__assign = Object.assign || function __assign(t) {
|
|
53
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
54
|
+
s = arguments[i];
|
|
55
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
56
|
+
}
|
|
57
|
+
return t;
|
|
58
|
+
};
|
|
59
|
+
return __assign.apply(this, arguments);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
63
|
+
var e = new Error(message);
|
|
64
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Utility functions for our components
|
|
68
|
+
// Type guard to check if array contains only numbers
|
|
69
|
+
var isNumberArray = function (arr) {
|
|
70
|
+
return arr.every(function (item) { return typeof item === 'number' && !isNaN(item); });
|
|
71
|
+
};
|
|
72
|
+
// Type guard to check if array contains only dates
|
|
73
|
+
var isDateArray = function (arr) {
|
|
74
|
+
return arr.every(function (item) { return item instanceof Date; });
|
|
75
|
+
};
|
|
76
|
+
// Calculate the mean of an array of numbers or dates
|
|
77
|
+
function calculateMean(arr) {
|
|
78
|
+
if (arr.length === 0)
|
|
79
|
+
return undefined;
|
|
80
|
+
if (isNumberArray(arr)) {
|
|
81
|
+
return arr.reduce(function (acc, num) { return acc + num; }, 0) / arr.length;
|
|
82
|
+
}
|
|
83
|
+
else if (isDateArray(arr)) {
|
|
84
|
+
var sum = arr.reduce(function (acc, date) { return acc + date.getTime(); }, 0);
|
|
85
|
+
return sum / arr.length;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var Plot$2 = lazy(function () { return import('react-plotly.js'); });
|
|
5
90
|
var HistogramPlot = function (props) {
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
var handleSelection = function (event) {
|
|
11
|
-
if (event.points && event.points.length === 1 && onClick) {
|
|
12
|
-
// If the user clicks on or selects a single point, we'll treat it as a click.
|
|
13
|
-
// Coule be improved by checking the range of the selection.
|
|
14
|
-
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
15
|
-
}
|
|
16
|
-
else if (event.points && event.points.length > 1) {
|
|
17
|
-
// Multiple points or area - treat as selection
|
|
18
|
-
onSelected === null || onSelected === void 0 ? void 0 : onSelected(event);
|
|
19
|
-
}
|
|
20
|
-
};
|
|
91
|
+
var _a;
|
|
92
|
+
var data = props.data, title = props.title, xAxisTitle = props.xAxisTitle, _b = props.barColor, barColor = _b === void 0 ? 'rgb(72, 72, 74)' : _b, _c = props.unselectedBarColor, unselectedBarColor = _c === void 0 ? 'rgba(203, 195, 195, 0.88)' : _c, _d = props.selectorsColor, selectorsColor = _d === void 0 ? 'black' : _d, onSelected = props.onSelected, onClick = props.onClick, _e = props.showMeanLine, showMeanLine = _e === void 0 ? true : _e, _f = props.meanLineColor, meanLineColor = _f === void 0 ? 'grey' : _f, containerStyleOverrides = props.containerStyleOverrides;
|
|
93
|
+
// Simple ref for container - no ResizeObserver needed
|
|
94
|
+
var containerRef = useRef(null);
|
|
21
95
|
var plotlyData = [
|
|
22
96
|
{
|
|
23
97
|
x: data,
|
|
@@ -40,8 +114,34 @@ var HistogramPlot = function (props) {
|
|
|
40
114
|
hovertemplate: '[%{x})<br>Count: %{y}<extra></extra>', // Custom hover text
|
|
41
115
|
}
|
|
42
116
|
];
|
|
117
|
+
// Calculate the mean
|
|
118
|
+
var meanValue = (_a = calculateMean(data)) !== null && _a !== void 0 ? _a : 0; // Default to 0 if no data
|
|
119
|
+
var meanLine = showMeanLine ? {
|
|
120
|
+
type: 'line',
|
|
121
|
+
x0: meanValue,
|
|
122
|
+
y0: 0,
|
|
123
|
+
x1: meanValue,
|
|
124
|
+
yref: 'paper',
|
|
125
|
+
y1: 1.04, // Extend slightly above so we can annotate better
|
|
126
|
+
line: {
|
|
127
|
+
color: meanLineColor,
|
|
128
|
+
width: 1.5,
|
|
129
|
+
}
|
|
130
|
+
} : {};
|
|
43
131
|
var layout = {
|
|
44
|
-
title: {
|
|
132
|
+
title: {
|
|
133
|
+
text: title,
|
|
134
|
+
},
|
|
135
|
+
autosize: true,
|
|
136
|
+
width: undefined, // Let autosize handle width
|
|
137
|
+
height: undefined, // Let autosize handle height
|
|
138
|
+
margin: {
|
|
139
|
+
l: 50,
|
|
140
|
+
r: 20,
|
|
141
|
+
t: title ? 80 : 30,
|
|
142
|
+
b: 50,
|
|
143
|
+
pad: 4
|
|
144
|
+
},
|
|
45
145
|
xaxis: {
|
|
46
146
|
title: {
|
|
47
147
|
text: xAxisTitle
|
|
@@ -80,6 +180,22 @@ var HistogramPlot = function (props) {
|
|
|
80
180
|
bargap: 0.03, // Gap between bars
|
|
81
181
|
dragmode: 'select', // Enable selection for both click and drag
|
|
82
182
|
selectdirection: 'h', // Allow selection in horizontal direction
|
|
183
|
+
shapes: meanLine ? [meanLine] : [], // Add the mean line if it exists
|
|
184
|
+
annotations: showMeanLine ? [{
|
|
185
|
+
x: meanValue,
|
|
186
|
+
y: 1.12, // Position above the top of the plot
|
|
187
|
+
yref: 'paper',
|
|
188
|
+
text: "Mean: ".concat(isDateArray(data) ? new Date(meanValue).toLocaleDateString('en-US', {
|
|
189
|
+
month: 'short',
|
|
190
|
+
day: '2-digit',
|
|
191
|
+
year: 'numeric'
|
|
192
|
+
}) : meanValue.toFixed(2)),
|
|
193
|
+
showarrow: false, // No arrow for the annotation
|
|
194
|
+
font: {
|
|
195
|
+
color: meanLineColor,
|
|
196
|
+
size: 12,
|
|
197
|
+
},
|
|
198
|
+
}] : [],
|
|
83
199
|
};
|
|
84
200
|
var config = {
|
|
85
201
|
responsive: true, // Make the plot responsive
|
|
@@ -88,9 +204,133 @@ var HistogramPlot = function (props) {
|
|
|
88
204
|
scrollZoom: false, // Disable zooming with scroll
|
|
89
205
|
staticPlot: false, // Enable interactivity
|
|
90
206
|
};
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
207
|
+
var containerStyles = __assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides);
|
|
208
|
+
return (jsx("div", { ref: containerRef, className: "plot-container", style: __assign({ '--selection-color': selectorsColor }, containerStyles), children: jsx(Suspense, { fallback: jsx("div", { style: {
|
|
209
|
+
width: "100%",
|
|
210
|
+
height: "100%",
|
|
211
|
+
minHeight: "300px",
|
|
212
|
+
display: "flex",
|
|
213
|
+
alignItems: "center",
|
|
214
|
+
justifyContent: "center",
|
|
215
|
+
color: "#666"
|
|
216
|
+
}, children: "Loading plot..." }), children: jsx(Plot$2, { data: plotlyData, layout: layout, config: config, onSelected: onSelected, onClick: onClick, useResizeHandler: true, style: {
|
|
217
|
+
width: "100%",
|
|
218
|
+
height: "100%",
|
|
219
|
+
display: "block"
|
|
220
|
+
} }) }) }));
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
var Plot$1 = lazy(function () { return import('react-plotly.js'); });
|
|
224
|
+
var RadialHistogramPlot = function (props) {
|
|
225
|
+
var data = props.data, _a = props.barColor, barColor = _a === void 0 ? 'rgb(72, 72, 74)' : _a, _b = props.unselectedBarColor, unselectedBarColor = _b === void 0 ? 'rgba(203, 195, 195, 0.88)' : _b, _c = props.selectorsColor, selectorsColor = _c === void 0 ? 'black' : _c, onSelected = props.onSelected, onClick = props.onClick, containerStyleOverrides = props.containerStyleOverrides, _d = props.barWidth, barWidth = _d === void 0 ? 20 : _d;
|
|
226
|
+
// Simple ref for container
|
|
227
|
+
var containerRef = useRef(null);
|
|
228
|
+
// TEMPORARY Calculate histogram bins manually to get proper polar coordinates
|
|
229
|
+
// This function should be extracted and used for both the regular and radial histograms.
|
|
230
|
+
if (data.length === 0) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
var min = Math.min.apply(Math, data);
|
|
234
|
+
var max = Math.max.apply(Math, data);
|
|
235
|
+
var numBins = Math.ceil(Math.sqrt(data.length)); // Default bin count
|
|
236
|
+
var binWidth = (max - min) / numBins;
|
|
237
|
+
// Create bins
|
|
238
|
+
var binCounts = new Array(numBins).fill(0);
|
|
239
|
+
var binCenters = [];
|
|
240
|
+
for (var i = 0; i < numBins; i++) {
|
|
241
|
+
binCenters.push(min + (i + 0.5) * binWidth);
|
|
242
|
+
}
|
|
243
|
+
// Count values in each bin
|
|
244
|
+
data.forEach(function (value) {
|
|
245
|
+
var binIndex = Math.min(Math.floor((value - min) / binWidth), numBins - 1);
|
|
246
|
+
binCounts[binIndex]++;
|
|
247
|
+
});
|
|
248
|
+
var plotlyData = [
|
|
249
|
+
{
|
|
250
|
+
type: 'barpolar',
|
|
251
|
+
theta: binCenters,
|
|
252
|
+
r: binCounts,
|
|
253
|
+
width: barWidth, // Width of each bar in degrees
|
|
254
|
+
marker: {
|
|
255
|
+
color: barColor,
|
|
256
|
+
line: {
|
|
257
|
+
color: "white",
|
|
258
|
+
width: 0.5,
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
// @ts-ignore - Not in the type but a valid property. See api https://plotly.com/javascript/reference/barpolar/#barpolar
|
|
262
|
+
unselected: {
|
|
263
|
+
marker: {
|
|
264
|
+
color: unselectedBarColor,
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
hovertemplate: '[%{x})<br>Count: %{y}<extra></extra>', // Custom hover text,
|
|
268
|
+
}
|
|
269
|
+
];
|
|
270
|
+
var layout = {
|
|
271
|
+
autosize: true,
|
|
272
|
+
width: undefined,
|
|
273
|
+
height: undefined,
|
|
274
|
+
margin: {
|
|
275
|
+
l: 50,
|
|
276
|
+
r: 50,
|
|
277
|
+
t: 30,
|
|
278
|
+
b: 50,
|
|
279
|
+
pad: 4
|
|
280
|
+
},
|
|
281
|
+
polar: {
|
|
282
|
+
bgcolor: 'rgba(0,0,0,0)',
|
|
283
|
+
sector: [90, -90],
|
|
284
|
+
angularaxis: {
|
|
285
|
+
tickmode: 'linear',
|
|
286
|
+
tick0: 0,
|
|
287
|
+
dtick: 45, // Show ticks every 45 degrees
|
|
288
|
+
direction: "counterclockwise",
|
|
289
|
+
rotation: 0,
|
|
290
|
+
showgrid: true,
|
|
291
|
+
gridcolor: '#efefef',
|
|
292
|
+
gridwidth: 0.5,
|
|
293
|
+
tickfont: {
|
|
294
|
+
size: 10
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
radialaxis: {
|
|
298
|
+
title: {
|
|
299
|
+
text: 'Count'
|
|
300
|
+
},
|
|
301
|
+
showgrid: true,
|
|
302
|
+
gridcolor: '#efefef',
|
|
303
|
+
gridwidth: 0.5,
|
|
304
|
+
tickfont: {
|
|
305
|
+
size: 10
|
|
306
|
+
},
|
|
307
|
+
angle: 90, // Position radial axis labels at top
|
|
308
|
+
side: 'counterclockwise',
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
dragmode: 'select',
|
|
312
|
+
selectdirection: 'any',
|
|
313
|
+
};
|
|
314
|
+
var config = {
|
|
315
|
+
responsive: true,
|
|
316
|
+
displayModeBar: false,
|
|
317
|
+
displaylogo: false,
|
|
318
|
+
scrollZoom: false,
|
|
319
|
+
staticPlot: false,
|
|
320
|
+
};
|
|
321
|
+
var containerStyles = __assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides);
|
|
322
|
+
return (jsx("div", { ref: containerRef, className: "plot-container radial-histogram-container", style: __assign({ '--selection-color': selectorsColor }, containerStyles), children: jsx(Suspense, { fallback: jsx("div", { style: {
|
|
323
|
+
width: "100%",
|
|
324
|
+
height: "100%",
|
|
325
|
+
minHeight: "300px",
|
|
326
|
+
display: "flex",
|
|
327
|
+
alignItems: "center",
|
|
328
|
+
justifyContent: "center",
|
|
329
|
+
}, children: "Loading radial plot..." }), children: jsx(Plot$1, { data: plotlyData, layout: layout, config: config, onSelected: onSelected, onClick: onClick, useResizeHandler: true, style: {
|
|
330
|
+
width: "100%",
|
|
331
|
+
height: "100%",
|
|
332
|
+
display: "block"
|
|
333
|
+
} }) }) }));
|
|
94
334
|
};
|
|
95
335
|
|
|
96
336
|
var Plot = lazy(function () { return import('react-plotly.js'); });
|
|
@@ -112,5 +352,5 @@ var TestPlot = function (props) {
|
|
|
112
352
|
return jsx(Plot, { data: data, layout: layout });
|
|
113
353
|
};
|
|
114
354
|
|
|
115
|
-
export { HistogramPlot, TestPlot };
|
|
355
|
+
export { HistogramPlot, RadialHistogramPlot, TestPlot };
|
|
116
356
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/components/Histogram.tsx","../src/components/TestPlot.tsx"],"sourcesContent":["import React, { lazy, Suspense } from 'react';\nimport { PlotParams } from 'react-plotly.js';\nimport './plotStyles.scss'; // Importing styles for the plot\n\nconst Plot = lazy(() => import('react-plotly.js'));\n\nexport type HistogramPlotProps = {\n data: number[];\n title?: string;\n xAxisTitle?: string;\n barColor?: string; // Optional prop to set the color of the bars\n unselectedBarColor?: string; // Optional prop to set the color of unselected bars\n selectorsColor?: string; // Optional prop to set the color of elements in the selection box\n onSelected?: (event: Plotly.PlotSelectionEvent) => void; // Optional handler for when a user clicks and drags to select an area of the plot\n onClick?: (event: Plotly.PlotMouseEvent) => void; // Optional handler for click events on the plot\n}\nexport const HistogramPlot = (props: HistogramPlotProps) => {\n\n const {\n data,\n title,\n xAxisTitle,\n barColor = 'rgb(72, 72, 74)',\n unselectedBarColor = 'rgba(203, 195, 195, 0.88)',\n selectorsColor = 'black',\n onSelected,\n onClick,\n } = props;\n\n // Combined handler for both click and selection events, so a user can choose either\n // Plotly prioritizes the selection handler over the click handler in general, so we use this strategy\n // to apply both.\n const handleSelection = (event: any) => {\n if (event.points && event.points.length === 1 && onClick) {\n // If the user clicks on or selects a single point, we'll treat it as a click.\n // Coule be improved by checking the range of the selection.\n onClick?.(event);\n } else if (event.points && event.points.length > 1) {\n // Multiple points or area - treat as selection\n onSelected?.(event);\n }\n };\n\n const plotlyData: PlotParams['data'] = [\n {\n x: data,\n type: 'histogram',\n marker: { \n color: barColor ?? 'blue',\n line: {\n color: \"white\",\n width: 0.5,\n },\n },\n // The following property is listed in the api. Not sure why typescript doesn't know about it.\n // Styles the unselected bars in the histogram\n //@ts-ignore\n unselected: {\n marker: { \n color: unselectedBarColor,\n }\n },\n hovertemplate: '[%{x})<br>Count: %{y}<extra></extra>', // Custom hover text\n }\n ];\n\n const layout: PlotParams['layout'] = {\n title: {text: title},\n xaxis: {\n title: {\n text: xAxisTitle\n },\n // range: [Math.min(...data, 0), Math.max(...data)], // Range needs to get padding on both sides based on bin size. Consider calculating bins here.\n showgrid: true,\n zeroline: true,\n showline: true,\n mirror: 'ticks',\n gridcolor: '#efefef',\n gridwidth: 0.2,\n zerolinecolor: '#969696',\n zerolinewidth: 1,\n linecolor: '#bababa',\n linewidth: 1,\n fixedrange: true, // Disable zooming\n ticklabelposition: 'outside',\n },\n yaxis: {\n title: {\n text: 'Count'\n },\n showgrid: true,\n zeroline: true,\n showline: true,\n mirror: 'ticks',\n gridcolor: '#efefef',\n gridwidth: 0.2,\n zerolinecolor: '#969696',\n zerolinewidth: 1,\n linecolor: '#bababa',\n linewidth: 1,\n fixedrange: true, // Disable zooming\n ticksuffix: ' ', // Add space between y axis and ticks\n },\n bargap: 0.03, // Gap between bars\n dragmode: 'select', // Enable selection for both click and drag\n selectdirection: 'h', // Allow selection in horizontal direction\n };\n\n const config: PlotParams['config'] = {\n responsive: true, // Make the plot responsive\n displayModeBar: false, // Hide the mode bar\n displaylogo: false, // Hide the Plotly logo\n scrollZoom: false, // Disable zooming with scroll\n staticPlot: false, // Enable interactivity\n };\n\n return (\n <Suspense fallback=\"Loading...\">\n <div \n className=\"plot-container\"\n style={{\n '--selection-color': selectorsColor,\n } as React.CSSProperties}\n >\n <Plot \n data={plotlyData} \n layout={layout} \n config={config}\n onSelected={handleSelection}\n />\n </div>\n </Suspense>\n );\n}\n\nexport default HistogramPlot;\n","// A test bar plotly plot\nimport React, { lazy } from 'react';\nimport { PlotParams } from 'react-plotly.js';\n\nconst Plot = lazy(() => import('react-plotly.js'));\n\nexport type TestPlotProps = {\n yaxisTitle?: string;\n xaxisTitle?: string;\n}\nexport const TestPlot = (props: TestPlotProps) => {\n const data: PlotParams['data'] = [\n {\n x: [1, 2, 3, 4],\n y: [10, 15, 13, 17],\n type: 'bar' as const,\n marker: { color: 'blue' },\n },\n ];\n\n const layout = {\n title: {text: 'Test Bar Plot'},\n xaxis: { title: {text: props.xaxisTitle ?? 'X Axis'} },\n yaxis: { title: {text: props.yaxisTitle ?? 'Y Axis'} },\n };\n\n return <Plot data={data} layout={layout} />;\n};\n\nexport default TestPlot;\n"],"names":["Plot","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js","../node_modules/.pnpm/@rollup+plugin-typescript@12.1.4_rollup@4.44.1_tslib@2.8.1_typescript@5.8.3/node_modules/tslib/tslib.es6.js","../src/components/Utils.ts","../src/components/Histogram.tsx","../src/components/RadialHistogram.tsx","../src/components/TestPlot.tsx"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n","/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\r\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\r\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\r\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\r\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\r\n var _, done = false;\r\n for (var i = decorators.length - 1; i >= 0; i--) {\r\n var context = {};\r\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\r\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\r\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\r\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\r\n if (kind === \"accessor\") {\r\n if (result === void 0) continue;\r\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\r\n if (_ = accept(result.get)) descriptor.get = _;\r\n if (_ = accept(result.set)) descriptor.set = _;\r\n if (_ = accept(result.init)) initializers.unshift(_);\r\n }\r\n else if (_ = accept(result)) {\r\n if (kind === \"field\") initializers.unshift(_);\r\n else descriptor[key] = _;\r\n }\r\n }\r\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\r\n done = true;\r\n};\r\n\r\nexport function __runInitializers(thisArg, initializers, value) {\r\n var useValue = arguments.length > 2;\r\n for (var i = 0; i < initializers.length; i++) {\r\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\r\n }\r\n return useValue ? value : void 0;\r\n};\r\n\r\nexport function __propKey(x) {\r\n return typeof x === \"symbol\" ? x : \"\".concat(x);\r\n};\r\n\r\nexport function __setFunctionName(f, name, prefix) {\r\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\r\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\r\n};\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\r\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\r\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nvar ownKeys = function(o) {\r\n ownKeys = Object.getOwnPropertyNames || function (o) {\r\n var ar = [];\r\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\r\n return ar;\r\n };\r\n return ownKeys(o);\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\nexport function __classPrivateFieldIn(state, receiver) {\r\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\r\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\r\n}\r\n\r\nexport function __addDisposableResource(env, value, async) {\r\n if (value !== null && value !== void 0) {\r\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\r\n var dispose, inner;\r\n if (async) {\r\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\r\n dispose = value[Symbol.asyncDispose];\r\n }\r\n if (dispose === void 0) {\r\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\r\n dispose = value[Symbol.dispose];\r\n if (async) inner = dispose;\r\n }\r\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\r\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\r\n env.stack.push({ value: value, dispose: dispose, async: async });\r\n }\r\n else if (async) {\r\n env.stack.push({ async: true });\r\n }\r\n return value;\r\n\r\n}\r\n\r\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\r\n\r\nexport function __disposeResources(env) {\r\n function fail(e) {\r\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\r\n env.hasError = true;\r\n }\r\n var r, s = 0;\r\n function next() {\r\n while (r = env.stack.pop()) {\r\n try {\r\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\r\n if (r.dispose) {\r\n var result = r.dispose.call(r.value);\r\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\r\n }\r\n else s |= 1;\r\n }\r\n catch (e) {\r\n fail(e);\r\n }\r\n }\r\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\r\n if (env.hasError) throw env.error;\r\n }\r\n return next();\r\n}\r\n\r\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\r\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\r\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\r\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\r\n });\r\n }\r\n return path;\r\n}\r\n\r\nexport default {\r\n __extends: __extends,\r\n __assign: __assign,\r\n __rest: __rest,\r\n __decorate: __decorate,\r\n __param: __param,\r\n __esDecorate: __esDecorate,\r\n __runInitializers: __runInitializers,\r\n __propKey: __propKey,\r\n __setFunctionName: __setFunctionName,\r\n __metadata: __metadata,\r\n __awaiter: __awaiter,\r\n __generator: __generator,\r\n __createBinding: __createBinding,\r\n __exportStar: __exportStar,\r\n __values: __values,\r\n __read: __read,\r\n __spread: __spread,\r\n __spreadArrays: __spreadArrays,\r\n __spreadArray: __spreadArray,\r\n __await: __await,\r\n __asyncGenerator: __asyncGenerator,\r\n __asyncDelegator: __asyncDelegator,\r\n __asyncValues: __asyncValues,\r\n __makeTemplateObject: __makeTemplateObject,\r\n __importStar: __importStar,\r\n __importDefault: __importDefault,\r\n __classPrivateFieldGet: __classPrivateFieldGet,\r\n __classPrivateFieldSet: __classPrivateFieldSet,\r\n __classPrivateFieldIn: __classPrivateFieldIn,\r\n __addDisposableResource: __addDisposableResource,\r\n __disposeResources: __disposeResources,\r\n __rewriteRelativeImportExtension: __rewriteRelativeImportExtension,\r\n};\r\n","// Utility functions for our components\n\n// Type guard to check if array contains only numbers\nexport const isNumberArray = (arr: unknown[]): arr is number[] => {\n return arr.every(item => typeof item === 'number' && !isNaN(item));\n};\n\n// Type guard to check if array contains only dates\nexport const isDateArray = (arr: unknown[]): arr is Date[] => {\n return arr.every(item => item instanceof Date);\n};\n\n// Calculate the mean of an array of numbers or dates\nexport function calculateMean(arr: number[] | Date[]): number | undefined {\n \n if (arr.length === 0) return undefined;\n\n if (isNumberArray(arr)) {\n return arr.reduce((acc, num) => acc + num, 0) / arr.length;\n } else if (isDateArray(arr)) {\n const sum = arr.reduce((acc, date) => acc + date.getTime(), 0);\n return sum / arr.length;\n }\n}\n\n// Utility function to format date as mm/dd/yy\nexport const formatDateMDY = (timestamp: number): string => {\n const date = new Date(timestamp);\n const month = (date.getMonth() + 1).toString().padStart(2, '0');\n const day = date.getDate().toString().padStart(2, '0');\n const year = date.getFullYear().toString().slice(-2);\n return `${month}/${day}/${year}`;\n};","import React, { lazy, Suspense, useRef } from 'react';\nimport { PlotParams } from 'react-plotly.js';\nimport './plotStyles.scss';\nimport { calculateMean, isDateArray, isNumberArray } from './Utils'; \n\n\nconst Plot = lazy(() => import('react-plotly.js'));\n\nexport type HistogramPlotProps = {\n data: number[] | Date[];\n showMeanLine?: boolean; // Optional prop to show a vertical line at the mean\n meanLineColor?: string; // Optional prop to set the color of the mean line\n title?: string;\n xAxisTitle?: string;\n barColor?: string; // Optional prop to set the color of the bars\n unselectedBarColor?: string; // Optional prop to set the color of unselected bars\n selectorsColor?: string; // Optional prop to set the color of elements in the selection box\n onSelected?: (event: Plotly.PlotSelectionEvent) => void; // Optional handler for when a user clicks and drags to select an area of the plot\n onClick?: (event: Plotly.PlotMouseEvent) => void; // Optional handler for click events on the plot\n containerStyleOverrides?: React.CSSProperties; // Optional style override for the container\n}\nexport const HistogramPlot = (props: HistogramPlotProps) => {\n\n const {\n data,\n title,\n xAxisTitle,\n barColor = 'rgb(72, 72, 74)',\n unselectedBarColor = 'rgba(203, 195, 195, 0.88)',\n selectorsColor = 'black',\n onSelected,\n onClick,\n showMeanLine = true,\n meanLineColor = 'grey',\n containerStyleOverrides,\n } = props;\n\n // Simple ref for container - no ResizeObserver needed\n const containerRef = useRef<HTMLDivElement>(null);\n\n const plotlyData: PlotParams['data'] = [\n {\n x: data,\n type: 'histogram',\n marker: { \n color: barColor ?? 'blue',\n line: {\n color: \"white\",\n width: 0.5,\n },\n },\n // The following property is listed in the api. Not sure why typescript doesn't know about it.\n // Styles the unselected bars in the histogram\n //@ts-ignore\n unselected: {\n marker: { \n color: unselectedBarColor,\n }\n },\n hovertemplate: '[%{x})<br>Count: %{y}<extra></extra>', // Custom hover text\n }\n ];\n\n\n // Calculate the mean\n const meanValue = calculateMean(data) ?? 0; // Default to 0 if no data\n\n const meanLine: Partial<Plotly.Shape> = showMeanLine ? {\n type: 'line',\n x0: meanValue,\n y0: 0,\n x1: meanValue,\n yref: 'paper',\n y1: 1.04, // Extend slightly above so we can annotate better\n line: {\n color: meanLineColor,\n width: 1.5,\n }\n } : {};\n\n const layout: PlotParams['layout'] = {\n title: {\n text: title,\n },\n autosize: true,\n width: undefined, // Let autosize handle width\n height: undefined, // Let autosize handle height\n margin: {\n l: 50,\n r: 20, \n t: title ? 80 : 30,\n b: 50,\n pad: 4\n },\n xaxis: {\n title: {\n text: xAxisTitle\n },\n // range: [Math.min(...data, 0), Math.max(...data)], // Range needs to get padding on both sides based on bin size. Consider calculating bins here.\n showgrid: true,\n zeroline: true,\n showline: true,\n mirror: 'ticks',\n gridcolor: '#efefef',\n gridwidth: 0.2,\n zerolinecolor: '#969696',\n zerolinewidth: 1,\n linecolor: '#bababa',\n linewidth: 1,\n fixedrange: true, // Disable zooming\n ticklabelposition: 'outside',\n },\n yaxis: {\n title: {\n text: 'Count'\n },\n showgrid: true,\n zeroline: true,\n showline: true,\n mirror: 'ticks',\n gridcolor: '#efefef',\n gridwidth: 0.2,\n zerolinecolor: '#969696',\n zerolinewidth: 1,\n linecolor: '#bababa',\n linewidth: 1,\n fixedrange: true, // Disable zooming\n ticksuffix: ' ', // Add space between y axis and ticks\n },\n bargap: 0.03, // Gap between bars\n dragmode: 'select', // Enable selection for both click and drag\n selectdirection: 'h', // Allow selection in horizontal direction\n shapes: meanLine ? [meanLine] : [], // Add the mean line if it exists\n annotations: showMeanLine ? [{\n x: meanValue,\n y: 1.12, // Position above the top of the plot\n yref: 'paper',\n text: `Mean: ${isDateArray(data) ? new Date(meanValue).toLocaleDateString('en-US', { \n month: 'short', \n day: '2-digit', \n year: 'numeric' \n }) : meanValue.toFixed(2)}`,\n showarrow: false, // No arrow for the annotation\n font: {\n color: meanLineColor,\n size: 12,\n },\n }] : [],\n };\n\n const config: PlotParams['config'] = {\n responsive: true, // Make the plot responsive\n displayModeBar: false, // Hide the mode bar\n displaylogo: false, // Hide the Plotly logo\n scrollZoom: false, // Disable zooming with scroll\n staticPlot: false, // Enable interactivity\n };\n\n const containerStyles: React.CSSProperties = {\n width: \"100%\",\n height: \"100%\",\n position: \"relative\",\n ...containerStyleOverrides,\n };\n\n return (\n <div \n ref={containerRef}\n className=\"plot-container\"\n style={{\n '--selection-color': selectorsColor,\n ...containerStyles\n } as React.CSSProperties}\n >\n <Suspense fallback={\n <div style={{ \n width: \"100%\", \n height: \"100%\", \n minHeight: \"300px\",\n display: \"flex\", \n alignItems: \"center\", \n justifyContent: \"center\",\n color: \"#666\"\n }}>\n Loading plot...\n </div>\n }>\n <Plot \n data={plotlyData} \n layout={layout} \n config={config}\n onSelected={onSelected}\n onClick={onClick}\n useResizeHandler={true}\n style={{ \n width: \"100%\", \n height: \"100%\",\n display: \"block\"\n }}\n />\n </Suspense>\n </div>\n );\n}\n\nexport default HistogramPlot;\n","import React, { lazy, Suspense, useRef } from 'react';\nimport { PlotParams } from 'react-plotly.js';\nimport './plotStyles.scss';\nimport { calculateMean } from './Utils';\n\nconst Plot = lazy(() => import('react-plotly.js'));\n\nexport type RadialHistogramPlotProps = {\n data: number[];\n barColor?: string; // Optional prop to set the color of the bars\n unselectedBarColor?: string; // Optional prop to set the color of unselected bars\n selectorsColor?: string; // Optional prop to set the color of elements in the selection box\n onSelected?: (event: Plotly.PlotSelectionEvent) => void; // Optional handler for when a user clicks and drags to select an area\n onClick?: (event: Plotly.PlotMouseEvent) => void; // Optional handler for click events on the plot\n containerStyleOverrides?: React.CSSProperties; // Optional style override for the container\n barWidth?: number; // Optional bar width for radial histogram\n}\n\nexport const RadialHistogramPlot = (props: RadialHistogramPlotProps) => {\n const {\n data,\n barColor = 'rgb(72, 72, 74)',\n unselectedBarColor = 'rgba(203, 195, 195, 0.88)',\n selectorsColor = 'black',\n onSelected,\n onClick,\n containerStyleOverrides,\n barWidth = 20, // Default bar width in degrees\n } = props;\n\n // Simple ref for container\n const containerRef = useRef<HTMLDivElement>(null);\n\n // TEMPORARY Calculate histogram bins manually to get proper polar coordinates\n // This function should be extracted and used for both the regular and radial histograms.\n\n if (data.length === 0) {\n return null;\n }\n\n const min = Math.min(...data);\n const max = Math.max(...data);\n const numBins = Math.ceil(Math.sqrt(data.length)); // Default bin count\n const binWidth = (max - min) / numBins;\n \n // Create bins\n const binCounts = new Array(numBins).fill(0);\n const binCenters = [];\n \n for (let i = 0; i < numBins; i++) {\n binCenters.push(min + (i + 0.5) * binWidth);\n }\n \n // Count values in each bin\n data.forEach(value => {\n const binIndex = Math.min(Math.floor((value - min) / binWidth), numBins - 1);\n binCounts[binIndex]++;\n });\n\n\n const plotlyData: PlotParams['data'] = [\n {\n type: 'barpolar',\n theta: binCenters,\n r: binCounts,\n width: barWidth, // Width of each bar in degrees\n marker: {\n color: barColor,\n line: {\n color: \"white\",\n width: 0.5,\n },\n },\n // @ts-ignore - Not in the type but a valid property. See api https://plotly.com/javascript/reference/barpolar/#barpolar\n unselected: {\n marker: {\n color: unselectedBarColor,\n }\n },\n hovertemplate: '[%{x})<br>Count: %{y}<extra></extra>', // Custom hover text,\n }\n ];\n\n\n const layout: PlotParams['layout'] = {\n autosize: true,\n width: undefined,\n height: undefined,\n margin: {\n l: 50,\n r: 50,\n t: 30,\n b: 50,\n pad: 4\n },\n polar: {\n bgcolor: 'rgba(0,0,0,0)',\n sector: [90, -90],\n angularaxis: {\n tickmode: 'linear',\n tick0: 0,\n dtick: 45, // Show ticks every 45 degrees\n direction: \"counterclockwise\",\n rotation: 0,\n showgrid: true,\n gridcolor: '#efefef',\n gridwidth: 0.5,\n tickfont: {\n size: 10\n }\n },\n radialaxis: {\n title: {\n text: 'Count'\n },\n showgrid: true,\n gridcolor: '#efefef',\n gridwidth: 0.5,\n tickfont: {\n size: 10\n },\n angle: 90, // Position radial axis labels at top\n side: 'counterclockwise',\n }\n },\n dragmode: 'select',\n selectdirection: 'any',\n };\n\n const config: PlotParams['config'] = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n scrollZoom: false,\n staticPlot: false,\n };\n\n const containerStyles: React.CSSProperties = {\n width: \"100%\",\n height: \"100%\",\n position: \"relative\",\n ...containerStyleOverrides,\n };\n\n return (\n <div \n ref={containerRef}\n className=\"plot-container radial-histogram-container\"\n style={{\n '--selection-color': selectorsColor,\n ...containerStyles\n } as React.CSSProperties}\n >\n <Suspense fallback={\n <div style={{ \n width: \"100%\", \n height: \"100%\", \n minHeight: \"300px\",\n display: \"flex\", \n alignItems: \"center\", \n justifyContent: \"center\",\n }}>\n Loading radial plot...\n </div>\n }>\n <Plot \n data={plotlyData} \n layout={layout} \n config={config}\n onSelected={onSelected}\n onClick={onClick}\n useResizeHandler={true}\n style={{ \n width: \"100%\", \n height: \"100%\",\n display: \"block\"\n }}\n />\n </Suspense>\n </div>\n );\n};\n\nexport default RadialHistogramPlot;\n","// A test bar plotly plot\nimport React, { lazy } from 'react';\nimport { PlotParams } from 'react-plotly.js';\n\nconst Plot = lazy(() => import('react-plotly.js'));\n\nexport type TestPlotProps = {\n yaxisTitle?: string;\n xaxisTitle?: string;\n}\nexport const TestPlot = (props: TestPlotProps) => {\n const data: PlotParams['data'] = [\n {\n x: [1, 2, 3, 4],\n y: [10, 15, 13, 17],\n type: 'bar' as const,\n marker: { color: 'blue' },\n },\n ];\n\n const layout = {\n title: {text: 'Test Bar Plot'},\n xaxis: { title: {text: props.xaxisTitle ?? 'X Axis'} },\n yaxis: { title: {text: props.yaxisTitle ?? 'Y Axis'} },\n };\n\n return <Plot data={data} layout={layout} />;\n};\n\nexport default TestPlot;\n"],"names":["Plot","_jsx"],"mappings":"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","x_google_ignoreList":[0,1]}
|
package/dist/index.js
CHANGED
|
@@ -3,23 +3,97 @@
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var react = require('react');
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
function styleInject(css, ref) {
|
|
7
|
+
if ( ref === void 0 ) ref = {};
|
|
8
|
+
var insertAt = ref.insertAt;
|
|
9
|
+
|
|
10
|
+
if (typeof document === 'undefined') { return; }
|
|
11
|
+
|
|
12
|
+
var head = document.head || document.getElementsByTagName('head')[0];
|
|
13
|
+
var style = document.createElement('style');
|
|
14
|
+
style.type = 'text/css';
|
|
15
|
+
|
|
16
|
+
if (insertAt === 'top') {
|
|
17
|
+
if (head.firstChild) {
|
|
18
|
+
head.insertBefore(style, head.firstChild);
|
|
19
|
+
} else {
|
|
20
|
+
head.appendChild(style);
|
|
21
|
+
}
|
|
22
|
+
} else {
|
|
23
|
+
head.appendChild(style);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (style.styleSheet) {
|
|
27
|
+
style.styleSheet.cssText = css;
|
|
28
|
+
} else {
|
|
29
|
+
style.appendChild(document.createTextNode(css));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
var css_248z = ".plot-container{height:100%;max-width:100%;min-height:300px;overflow:hidden!important;position:relative;width:100%}.plot-container>div{flex:1;height:100%!important;width:100%!important}.plot-container .main-svg{max-height:100%!important;max-width:100%!important}.plot-container .main-svg,.plot-container .plotly-graph-div,.plot-container svg.main-svg[height],.plot-container svg.main-svg[width]{height:100%!important;width:100%!important}.plot-container .point{border-radius:5px!important;overflow:hidden!important}.plot-container .cursor-ns-resize{height:0;width:0}.plot-container .cursor-ew-resize{fill:var(--selection-color,blue)!important;stroke:var(--selection-color,blue)!important}.plot-container .selectionlayer>path{stroke:var(--selection-color,blue)!important;stroke-dasharray:0!important;stroke-width:1px!important;opacity:.5!important}.plot-container .zoomlayer>path{stroke-dasharray:0!important;stroke:var(--selection-color,blue)!important;fill:var(--selection-color,blue)!important}.radial-histogram-container{aspect-ratio:1}";
|
|
34
|
+
styleInject(css_248z);
|
|
35
|
+
|
|
36
|
+
/******************************************************************************
|
|
37
|
+
Copyright (c) Microsoft Corporation.
|
|
38
|
+
|
|
39
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
40
|
+
purpose with or without fee is hereby granted.
|
|
41
|
+
|
|
42
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
43
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
44
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
45
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
46
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
47
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
48
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
49
|
+
***************************************************************************** */
|
|
50
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
var __assign = function() {
|
|
54
|
+
__assign = Object.assign || function __assign(t) {
|
|
55
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
56
|
+
s = arguments[i];
|
|
57
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
58
|
+
}
|
|
59
|
+
return t;
|
|
60
|
+
};
|
|
61
|
+
return __assign.apply(this, arguments);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
65
|
+
var e = new Error(message);
|
|
66
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Utility functions for our components
|
|
70
|
+
// Type guard to check if array contains only numbers
|
|
71
|
+
var isNumberArray = function (arr) {
|
|
72
|
+
return arr.every(function (item) { return typeof item === 'number' && !isNaN(item); });
|
|
73
|
+
};
|
|
74
|
+
// Type guard to check if array contains only dates
|
|
75
|
+
var isDateArray = function (arr) {
|
|
76
|
+
return arr.every(function (item) { return item instanceof Date; });
|
|
77
|
+
};
|
|
78
|
+
// Calculate the mean of an array of numbers or dates
|
|
79
|
+
function calculateMean(arr) {
|
|
80
|
+
if (arr.length === 0)
|
|
81
|
+
return undefined;
|
|
82
|
+
if (isNumberArray(arr)) {
|
|
83
|
+
return arr.reduce(function (acc, num) { return acc + num; }, 0) / arr.length;
|
|
84
|
+
}
|
|
85
|
+
else if (isDateArray(arr)) {
|
|
86
|
+
var sum = arr.reduce(function (acc, date) { return acc + date.getTime(); }, 0);
|
|
87
|
+
return sum / arr.length;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
var Plot$2 = react.lazy(function () { return import('react-plotly.js'); });
|
|
7
92
|
var HistogramPlot = function (props) {
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
var handleSelection = function (event) {
|
|
13
|
-
if (event.points && event.points.length === 1 && onClick) {
|
|
14
|
-
// If the user clicks on or selects a single point, we'll treat it as a click.
|
|
15
|
-
// Coule be improved by checking the range of the selection.
|
|
16
|
-
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
17
|
-
}
|
|
18
|
-
else if (event.points && event.points.length > 1) {
|
|
19
|
-
// Multiple points or area - treat as selection
|
|
20
|
-
onSelected === null || onSelected === void 0 ? void 0 : onSelected(event);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
93
|
+
var _a;
|
|
94
|
+
var data = props.data, title = props.title, xAxisTitle = props.xAxisTitle, _b = props.barColor, barColor = _b === void 0 ? 'rgb(72, 72, 74)' : _b, _c = props.unselectedBarColor, unselectedBarColor = _c === void 0 ? 'rgba(203, 195, 195, 0.88)' : _c, _d = props.selectorsColor, selectorsColor = _d === void 0 ? 'black' : _d, onSelected = props.onSelected, onClick = props.onClick, _e = props.showMeanLine, showMeanLine = _e === void 0 ? true : _e, _f = props.meanLineColor, meanLineColor = _f === void 0 ? 'grey' : _f, containerStyleOverrides = props.containerStyleOverrides;
|
|
95
|
+
// Simple ref for container - no ResizeObserver needed
|
|
96
|
+
var containerRef = react.useRef(null);
|
|
23
97
|
var plotlyData = [
|
|
24
98
|
{
|
|
25
99
|
x: data,
|
|
@@ -42,8 +116,34 @@ var HistogramPlot = function (props) {
|
|
|
42
116
|
hovertemplate: '[%{x})<br>Count: %{y}<extra></extra>', // Custom hover text
|
|
43
117
|
}
|
|
44
118
|
];
|
|
119
|
+
// Calculate the mean
|
|
120
|
+
var meanValue = (_a = calculateMean(data)) !== null && _a !== void 0 ? _a : 0; // Default to 0 if no data
|
|
121
|
+
var meanLine = showMeanLine ? {
|
|
122
|
+
type: 'line',
|
|
123
|
+
x0: meanValue,
|
|
124
|
+
y0: 0,
|
|
125
|
+
x1: meanValue,
|
|
126
|
+
yref: 'paper',
|
|
127
|
+
y1: 1.04, // Extend slightly above so we can annotate better
|
|
128
|
+
line: {
|
|
129
|
+
color: meanLineColor,
|
|
130
|
+
width: 1.5,
|
|
131
|
+
}
|
|
132
|
+
} : {};
|
|
45
133
|
var layout = {
|
|
46
|
-
title: {
|
|
134
|
+
title: {
|
|
135
|
+
text: title,
|
|
136
|
+
},
|
|
137
|
+
autosize: true,
|
|
138
|
+
width: undefined, // Let autosize handle width
|
|
139
|
+
height: undefined, // Let autosize handle height
|
|
140
|
+
margin: {
|
|
141
|
+
l: 50,
|
|
142
|
+
r: 20,
|
|
143
|
+
t: title ? 80 : 30,
|
|
144
|
+
b: 50,
|
|
145
|
+
pad: 4
|
|
146
|
+
},
|
|
47
147
|
xaxis: {
|
|
48
148
|
title: {
|
|
49
149
|
text: xAxisTitle
|
|
@@ -82,6 +182,22 @@ var HistogramPlot = function (props) {
|
|
|
82
182
|
bargap: 0.03, // Gap between bars
|
|
83
183
|
dragmode: 'select', // Enable selection for both click and drag
|
|
84
184
|
selectdirection: 'h', // Allow selection in horizontal direction
|
|
185
|
+
shapes: meanLine ? [meanLine] : [], // Add the mean line if it exists
|
|
186
|
+
annotations: showMeanLine ? [{
|
|
187
|
+
x: meanValue,
|
|
188
|
+
y: 1.12, // Position above the top of the plot
|
|
189
|
+
yref: 'paper',
|
|
190
|
+
text: "Mean: ".concat(isDateArray(data) ? new Date(meanValue).toLocaleDateString('en-US', {
|
|
191
|
+
month: 'short',
|
|
192
|
+
day: '2-digit',
|
|
193
|
+
year: 'numeric'
|
|
194
|
+
}) : meanValue.toFixed(2)),
|
|
195
|
+
showarrow: false, // No arrow for the annotation
|
|
196
|
+
font: {
|
|
197
|
+
color: meanLineColor,
|
|
198
|
+
size: 12,
|
|
199
|
+
},
|
|
200
|
+
}] : [],
|
|
85
201
|
};
|
|
86
202
|
var config = {
|
|
87
203
|
responsive: true, // Make the plot responsive
|
|
@@ -90,9 +206,133 @@ var HistogramPlot = function (props) {
|
|
|
90
206
|
scrollZoom: false, // Disable zooming with scroll
|
|
91
207
|
staticPlot: false, // Enable interactivity
|
|
92
208
|
};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
209
|
+
var containerStyles = __assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides);
|
|
210
|
+
return (jsxRuntime.jsx("div", { ref: containerRef, className: "plot-container", style: __assign({ '--selection-color': selectorsColor }, containerStyles), children: jsxRuntime.jsx(react.Suspense, { fallback: jsxRuntime.jsx("div", { style: {
|
|
211
|
+
width: "100%",
|
|
212
|
+
height: "100%",
|
|
213
|
+
minHeight: "300px",
|
|
214
|
+
display: "flex",
|
|
215
|
+
alignItems: "center",
|
|
216
|
+
justifyContent: "center",
|
|
217
|
+
color: "#666"
|
|
218
|
+
}, children: "Loading plot..." }), children: jsxRuntime.jsx(Plot$2, { data: plotlyData, layout: layout, config: config, onSelected: onSelected, onClick: onClick, useResizeHandler: true, style: {
|
|
219
|
+
width: "100%",
|
|
220
|
+
height: "100%",
|
|
221
|
+
display: "block"
|
|
222
|
+
} }) }) }));
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
var Plot$1 = react.lazy(function () { return import('react-plotly.js'); });
|
|
226
|
+
var RadialHistogramPlot = function (props) {
|
|
227
|
+
var data = props.data, _a = props.barColor, barColor = _a === void 0 ? 'rgb(72, 72, 74)' : _a, _b = props.unselectedBarColor, unselectedBarColor = _b === void 0 ? 'rgba(203, 195, 195, 0.88)' : _b, _c = props.selectorsColor, selectorsColor = _c === void 0 ? 'black' : _c, onSelected = props.onSelected, onClick = props.onClick, containerStyleOverrides = props.containerStyleOverrides, _d = props.barWidth, barWidth = _d === void 0 ? 20 : _d;
|
|
228
|
+
// Simple ref for container
|
|
229
|
+
var containerRef = react.useRef(null);
|
|
230
|
+
// TEMPORARY Calculate histogram bins manually to get proper polar coordinates
|
|
231
|
+
// This function should be extracted and used for both the regular and radial histograms.
|
|
232
|
+
if (data.length === 0) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
var min = Math.min.apply(Math, data);
|
|
236
|
+
var max = Math.max.apply(Math, data);
|
|
237
|
+
var numBins = Math.ceil(Math.sqrt(data.length)); // Default bin count
|
|
238
|
+
var binWidth = (max - min) / numBins;
|
|
239
|
+
// Create bins
|
|
240
|
+
var binCounts = new Array(numBins).fill(0);
|
|
241
|
+
var binCenters = [];
|
|
242
|
+
for (var i = 0; i < numBins; i++) {
|
|
243
|
+
binCenters.push(min + (i + 0.5) * binWidth);
|
|
244
|
+
}
|
|
245
|
+
// Count values in each bin
|
|
246
|
+
data.forEach(function (value) {
|
|
247
|
+
var binIndex = Math.min(Math.floor((value - min) / binWidth), numBins - 1);
|
|
248
|
+
binCounts[binIndex]++;
|
|
249
|
+
});
|
|
250
|
+
var plotlyData = [
|
|
251
|
+
{
|
|
252
|
+
type: 'barpolar',
|
|
253
|
+
theta: binCenters,
|
|
254
|
+
r: binCounts,
|
|
255
|
+
width: barWidth, // Width of each bar in degrees
|
|
256
|
+
marker: {
|
|
257
|
+
color: barColor,
|
|
258
|
+
line: {
|
|
259
|
+
color: "white",
|
|
260
|
+
width: 0.5,
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
// @ts-ignore - Not in the type but a valid property. See api https://plotly.com/javascript/reference/barpolar/#barpolar
|
|
264
|
+
unselected: {
|
|
265
|
+
marker: {
|
|
266
|
+
color: unselectedBarColor,
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
hovertemplate: '[%{x})<br>Count: %{y}<extra></extra>', // Custom hover text,
|
|
270
|
+
}
|
|
271
|
+
];
|
|
272
|
+
var layout = {
|
|
273
|
+
autosize: true,
|
|
274
|
+
width: undefined,
|
|
275
|
+
height: undefined,
|
|
276
|
+
margin: {
|
|
277
|
+
l: 50,
|
|
278
|
+
r: 50,
|
|
279
|
+
t: 30,
|
|
280
|
+
b: 50,
|
|
281
|
+
pad: 4
|
|
282
|
+
},
|
|
283
|
+
polar: {
|
|
284
|
+
bgcolor: 'rgba(0,0,0,0)',
|
|
285
|
+
sector: [90, -90],
|
|
286
|
+
angularaxis: {
|
|
287
|
+
tickmode: 'linear',
|
|
288
|
+
tick0: 0,
|
|
289
|
+
dtick: 45, // Show ticks every 45 degrees
|
|
290
|
+
direction: "counterclockwise",
|
|
291
|
+
rotation: 0,
|
|
292
|
+
showgrid: true,
|
|
293
|
+
gridcolor: '#efefef',
|
|
294
|
+
gridwidth: 0.5,
|
|
295
|
+
tickfont: {
|
|
296
|
+
size: 10
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
radialaxis: {
|
|
300
|
+
title: {
|
|
301
|
+
text: 'Count'
|
|
302
|
+
},
|
|
303
|
+
showgrid: true,
|
|
304
|
+
gridcolor: '#efefef',
|
|
305
|
+
gridwidth: 0.5,
|
|
306
|
+
tickfont: {
|
|
307
|
+
size: 10
|
|
308
|
+
},
|
|
309
|
+
angle: 90, // Position radial axis labels at top
|
|
310
|
+
side: 'counterclockwise',
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
dragmode: 'select',
|
|
314
|
+
selectdirection: 'any',
|
|
315
|
+
};
|
|
316
|
+
var config = {
|
|
317
|
+
responsive: true,
|
|
318
|
+
displayModeBar: false,
|
|
319
|
+
displaylogo: false,
|
|
320
|
+
scrollZoom: false,
|
|
321
|
+
staticPlot: false,
|
|
322
|
+
};
|
|
323
|
+
var containerStyles = __assign({ width: "100%", height: "100%", position: "relative" }, containerStyleOverrides);
|
|
324
|
+
return (jsxRuntime.jsx("div", { ref: containerRef, className: "plot-container radial-histogram-container", style: __assign({ '--selection-color': selectorsColor }, containerStyles), children: jsxRuntime.jsx(react.Suspense, { fallback: jsxRuntime.jsx("div", { style: {
|
|
325
|
+
width: "100%",
|
|
326
|
+
height: "100%",
|
|
327
|
+
minHeight: "300px",
|
|
328
|
+
display: "flex",
|
|
329
|
+
alignItems: "center",
|
|
330
|
+
justifyContent: "center",
|
|
331
|
+
}, children: "Loading radial plot..." }), children: jsxRuntime.jsx(Plot$1, { data: plotlyData, layout: layout, config: config, onSelected: onSelected, onClick: onClick, useResizeHandler: true, style: {
|
|
332
|
+
width: "100%",
|
|
333
|
+
height: "100%",
|
|
334
|
+
display: "block"
|
|
335
|
+
} }) }) }));
|
|
96
336
|
};
|
|
97
337
|
|
|
98
338
|
var Plot = react.lazy(function () { return import('react-plotly.js'); });
|
|
@@ -115,5 +355,6 @@ var TestPlot = function (props) {
|
|
|
115
355
|
};
|
|
116
356
|
|
|
117
357
|
exports.HistogramPlot = HistogramPlot;
|
|
358
|
+
exports.RadialHistogramPlot = RadialHistogramPlot;
|
|
118
359
|
exports.TestPlot = TestPlot;
|
|
119
360
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/components/Histogram.tsx","../src/components/TestPlot.tsx"],"sourcesContent":["import React, { lazy, Suspense } from 'react';\nimport { PlotParams } from 'react-plotly.js';\nimport './plotStyles.scss'; // Importing styles for the plot\n\nconst Plot = lazy(() => import('react-plotly.js'));\n\nexport type HistogramPlotProps = {\n data: number[];\n title?: string;\n xAxisTitle?: string;\n barColor?: string; // Optional prop to set the color of the bars\n unselectedBarColor?: string; // Optional prop to set the color of unselected bars\n selectorsColor?: string; // Optional prop to set the color of elements in the selection box\n onSelected?: (event: Plotly.PlotSelectionEvent) => void; // Optional handler for when a user clicks and drags to select an area of the plot\n onClick?: (event: Plotly.PlotMouseEvent) => void; // Optional handler for click events on the plot\n}\nexport const HistogramPlot = (props: HistogramPlotProps) => {\n\n const {\n data,\n title,\n xAxisTitle,\n barColor = 'rgb(72, 72, 74)',\n unselectedBarColor = 'rgba(203, 195, 195, 0.88)',\n selectorsColor = 'black',\n onSelected,\n onClick,\n } = props;\n\n // Combined handler for both click and selection events, so a user can choose either\n // Plotly prioritizes the selection handler over the click handler in general, so we use this strategy\n // to apply both.\n const handleSelection = (event: any) => {\n if (event.points && event.points.length === 1 && onClick) {\n // If the user clicks on or selects a single point, we'll treat it as a click.\n // Coule be improved by checking the range of the selection.\n onClick?.(event);\n } else if (event.points && event.points.length > 1) {\n // Multiple points or area - treat as selection\n onSelected?.(event);\n }\n };\n\n const plotlyData: PlotParams['data'] = [\n {\n x: data,\n type: 'histogram',\n marker: { \n color: barColor ?? 'blue',\n line: {\n color: \"white\",\n width: 0.5,\n },\n },\n // The following property is listed in the api. Not sure why typescript doesn't know about it.\n // Styles the unselected bars in the histogram\n //@ts-ignore\n unselected: {\n marker: { \n color: unselectedBarColor,\n }\n },\n hovertemplate: '[%{x})<br>Count: %{y}<extra></extra>', // Custom hover text\n }\n ];\n\n const layout: PlotParams['layout'] = {\n title: {text: title},\n xaxis: {\n title: {\n text: xAxisTitle\n },\n // range: [Math.min(...data, 0), Math.max(...data)], // Range needs to get padding on both sides based on bin size. Consider calculating bins here.\n showgrid: true,\n zeroline: true,\n showline: true,\n mirror: 'ticks',\n gridcolor: '#efefef',\n gridwidth: 0.2,\n zerolinecolor: '#969696',\n zerolinewidth: 1,\n linecolor: '#bababa',\n linewidth: 1,\n fixedrange: true, // Disable zooming\n ticklabelposition: 'outside',\n },\n yaxis: {\n title: {\n text: 'Count'\n },\n showgrid: true,\n zeroline: true,\n showline: true,\n mirror: 'ticks',\n gridcolor: '#efefef',\n gridwidth: 0.2,\n zerolinecolor: '#969696',\n zerolinewidth: 1,\n linecolor: '#bababa',\n linewidth: 1,\n fixedrange: true, // Disable zooming\n ticksuffix: ' ', // Add space between y axis and ticks\n },\n bargap: 0.03, // Gap between bars\n dragmode: 'select', // Enable selection for both click and drag\n selectdirection: 'h', // Allow selection in horizontal direction\n };\n\n const config: PlotParams['config'] = {\n responsive: true, // Make the plot responsive\n displayModeBar: false, // Hide the mode bar\n displaylogo: false, // Hide the Plotly logo\n scrollZoom: false, // Disable zooming with scroll\n staticPlot: false, // Enable interactivity\n };\n\n return (\n <Suspense fallback=\"Loading...\">\n <div \n className=\"plot-container\"\n style={{\n '--selection-color': selectorsColor,\n } as React.CSSProperties}\n >\n <Plot \n data={plotlyData} \n layout={layout} \n config={config}\n onSelected={handleSelection}\n />\n </div>\n </Suspense>\n );\n}\n\nexport default HistogramPlot;\n","// A test bar plotly plot\nimport React, { lazy } from 'react';\nimport { PlotParams } from 'react-plotly.js';\n\nconst Plot = lazy(() => import('react-plotly.js'));\n\nexport type TestPlotProps = {\n yaxisTitle?: string;\n xaxisTitle?: string;\n}\nexport const TestPlot = (props: TestPlotProps) => {\n const data: PlotParams['data'] = [\n {\n x: [1, 2, 3, 4],\n y: [10, 15, 13, 17],\n type: 'bar' as const,\n marker: { color: 'blue' },\n },\n ];\n\n const layout = {\n title: {text: 'Test Bar Plot'},\n xaxis: { title: {text: props.xaxisTitle ?? 'X Axis'} },\n yaxis: { title: {text: props.yaxisTitle ?? 'Y Axis'} },\n };\n\n return <Plot data={data} layout={layout} />;\n};\n\nexport default TestPlot;\n"],"names":["Plot","lazy","_jsx","Suspense"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js","../node_modules/.pnpm/@rollup+plugin-typescript@12.1.4_rollup@4.44.1_tslib@2.8.1_typescript@5.8.3/node_modules/tslib/tslib.es6.js","../src/components/Utils.ts","../src/components/Histogram.tsx","../src/components/RadialHistogram.tsx","../src/components/TestPlot.tsx"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n","/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\r\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\r\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\r\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\r\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\r\n var _, done = false;\r\n for (var i = decorators.length - 1; i >= 0; i--) {\r\n var context = {};\r\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\r\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\r\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\r\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\r\n if (kind === \"accessor\") {\r\n if (result === void 0) continue;\r\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\r\n if (_ = accept(result.get)) descriptor.get = _;\r\n if (_ = accept(result.set)) descriptor.set = _;\r\n if (_ = accept(result.init)) initializers.unshift(_);\r\n }\r\n else if (_ = accept(result)) {\r\n if (kind === \"field\") initializers.unshift(_);\r\n else descriptor[key] = _;\r\n }\r\n }\r\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\r\n done = true;\r\n};\r\n\r\nexport function __runInitializers(thisArg, initializers, value) {\r\n var useValue = arguments.length > 2;\r\n for (var i = 0; i < initializers.length; i++) {\r\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\r\n }\r\n return useValue ? value : void 0;\r\n};\r\n\r\nexport function __propKey(x) {\r\n return typeof x === \"symbol\" ? x : \"\".concat(x);\r\n};\r\n\r\nexport function __setFunctionName(f, name, prefix) {\r\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\r\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\r\n};\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\r\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\r\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nvar ownKeys = function(o) {\r\n ownKeys = Object.getOwnPropertyNames || function (o) {\r\n var ar = [];\r\n for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;\r\n return ar;\r\n };\r\n return ownKeys(o);\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== \"default\") __createBinding(result, mod, k[i]);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\nexport function __classPrivateFieldIn(state, receiver) {\r\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\r\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\r\n}\r\n\r\nexport function __addDisposableResource(env, value, async) {\r\n if (value !== null && value !== void 0) {\r\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\r\n var dispose, inner;\r\n if (async) {\r\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\r\n dispose = value[Symbol.asyncDispose];\r\n }\r\n if (dispose === void 0) {\r\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\r\n dispose = value[Symbol.dispose];\r\n if (async) inner = dispose;\r\n }\r\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\r\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\r\n env.stack.push({ value: value, dispose: dispose, async: async });\r\n }\r\n else if (async) {\r\n env.stack.push({ async: true });\r\n }\r\n return value;\r\n\r\n}\r\n\r\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\r\n\r\nexport function __disposeResources(env) {\r\n function fail(e) {\r\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\r\n env.hasError = true;\r\n }\r\n var r, s = 0;\r\n function next() {\r\n while (r = env.stack.pop()) {\r\n try {\r\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\r\n if (r.dispose) {\r\n var result = r.dispose.call(r.value);\r\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\r\n }\r\n else s |= 1;\r\n }\r\n catch (e) {\r\n fail(e);\r\n }\r\n }\r\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\r\n if (env.hasError) throw env.error;\r\n }\r\n return next();\r\n}\r\n\r\nexport function __rewriteRelativeImportExtension(path, preserveJsx) {\r\n if (typeof path === \"string\" && /^\\.\\.?\\//.test(path)) {\r\n return path.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+?)?)\\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {\r\n return tsx ? preserveJsx ? \".jsx\" : \".js\" : d && (!ext || !cm) ? m : (d + ext + \".\" + cm.toLowerCase() + \"js\");\r\n });\r\n }\r\n return path;\r\n}\r\n\r\nexport default {\r\n __extends: __extends,\r\n __assign: __assign,\r\n __rest: __rest,\r\n __decorate: __decorate,\r\n __param: __param,\r\n __esDecorate: __esDecorate,\r\n __runInitializers: __runInitializers,\r\n __propKey: __propKey,\r\n __setFunctionName: __setFunctionName,\r\n __metadata: __metadata,\r\n __awaiter: __awaiter,\r\n __generator: __generator,\r\n __createBinding: __createBinding,\r\n __exportStar: __exportStar,\r\n __values: __values,\r\n __read: __read,\r\n __spread: __spread,\r\n __spreadArrays: __spreadArrays,\r\n __spreadArray: __spreadArray,\r\n __await: __await,\r\n __asyncGenerator: __asyncGenerator,\r\n __asyncDelegator: __asyncDelegator,\r\n __asyncValues: __asyncValues,\r\n __makeTemplateObject: __makeTemplateObject,\r\n __importStar: __importStar,\r\n __importDefault: __importDefault,\r\n __classPrivateFieldGet: __classPrivateFieldGet,\r\n __classPrivateFieldSet: __classPrivateFieldSet,\r\n __classPrivateFieldIn: __classPrivateFieldIn,\r\n __addDisposableResource: __addDisposableResource,\r\n __disposeResources: __disposeResources,\r\n __rewriteRelativeImportExtension: __rewriteRelativeImportExtension,\r\n};\r\n","// Utility functions for our components\n\n// Type guard to check if array contains only numbers\nexport const isNumberArray = (arr: unknown[]): arr is number[] => {\n return arr.every(item => typeof item === 'number' && !isNaN(item));\n};\n\n// Type guard to check if array contains only dates\nexport const isDateArray = (arr: unknown[]): arr is Date[] => {\n return arr.every(item => item instanceof Date);\n};\n\n// Calculate the mean of an array of numbers or dates\nexport function calculateMean(arr: number[] | Date[]): number | undefined {\n \n if (arr.length === 0) return undefined;\n\n if (isNumberArray(arr)) {\n return arr.reduce((acc, num) => acc + num, 0) / arr.length;\n } else if (isDateArray(arr)) {\n const sum = arr.reduce((acc, date) => acc + date.getTime(), 0);\n return sum / arr.length;\n }\n}\n\n// Utility function to format date as mm/dd/yy\nexport const formatDateMDY = (timestamp: number): string => {\n const date = new Date(timestamp);\n const month = (date.getMonth() + 1).toString().padStart(2, '0');\n const day = date.getDate().toString().padStart(2, '0');\n const year = date.getFullYear().toString().slice(-2);\n return `${month}/${day}/${year}`;\n};","import React, { lazy, Suspense, useRef } from 'react';\nimport { PlotParams } from 'react-plotly.js';\nimport './plotStyles.scss';\nimport { calculateMean, isDateArray, isNumberArray } from './Utils'; \n\n\nconst Plot = lazy(() => import('react-plotly.js'));\n\nexport type HistogramPlotProps = {\n data: number[] | Date[];\n showMeanLine?: boolean; // Optional prop to show a vertical line at the mean\n meanLineColor?: string; // Optional prop to set the color of the mean line\n title?: string;\n xAxisTitle?: string;\n barColor?: string; // Optional prop to set the color of the bars\n unselectedBarColor?: string; // Optional prop to set the color of unselected bars\n selectorsColor?: string; // Optional prop to set the color of elements in the selection box\n onSelected?: (event: Plotly.PlotSelectionEvent) => void; // Optional handler for when a user clicks and drags to select an area of the plot\n onClick?: (event: Plotly.PlotMouseEvent) => void; // Optional handler for click events on the plot\n containerStyleOverrides?: React.CSSProperties; // Optional style override for the container\n}\nexport const HistogramPlot = (props: HistogramPlotProps) => {\n\n const {\n data,\n title,\n xAxisTitle,\n barColor = 'rgb(72, 72, 74)',\n unselectedBarColor = 'rgba(203, 195, 195, 0.88)',\n selectorsColor = 'black',\n onSelected,\n onClick,\n showMeanLine = true,\n meanLineColor = 'grey',\n containerStyleOverrides,\n } = props;\n\n // Simple ref for container - no ResizeObserver needed\n const containerRef = useRef<HTMLDivElement>(null);\n\n const plotlyData: PlotParams['data'] = [\n {\n x: data,\n type: 'histogram',\n marker: { \n color: barColor ?? 'blue',\n line: {\n color: \"white\",\n width: 0.5,\n },\n },\n // The following property is listed in the api. Not sure why typescript doesn't know about it.\n // Styles the unselected bars in the histogram\n //@ts-ignore\n unselected: {\n marker: { \n color: unselectedBarColor,\n }\n },\n hovertemplate: '[%{x})<br>Count: %{y}<extra></extra>', // Custom hover text\n }\n ];\n\n\n // Calculate the mean\n const meanValue = calculateMean(data) ?? 0; // Default to 0 if no data\n\n const meanLine: Partial<Plotly.Shape> = showMeanLine ? {\n type: 'line',\n x0: meanValue,\n y0: 0,\n x1: meanValue,\n yref: 'paper',\n y1: 1.04, // Extend slightly above so we can annotate better\n line: {\n color: meanLineColor,\n width: 1.5,\n }\n } : {};\n\n const layout: PlotParams['layout'] = {\n title: {\n text: title,\n },\n autosize: true,\n width: undefined, // Let autosize handle width\n height: undefined, // Let autosize handle height\n margin: {\n l: 50,\n r: 20, \n t: title ? 80 : 30,\n b: 50,\n pad: 4\n },\n xaxis: {\n title: {\n text: xAxisTitle\n },\n // range: [Math.min(...data, 0), Math.max(...data)], // Range needs to get padding on both sides based on bin size. Consider calculating bins here.\n showgrid: true,\n zeroline: true,\n showline: true,\n mirror: 'ticks',\n gridcolor: '#efefef',\n gridwidth: 0.2,\n zerolinecolor: '#969696',\n zerolinewidth: 1,\n linecolor: '#bababa',\n linewidth: 1,\n fixedrange: true, // Disable zooming\n ticklabelposition: 'outside',\n },\n yaxis: {\n title: {\n text: 'Count'\n },\n showgrid: true,\n zeroline: true,\n showline: true,\n mirror: 'ticks',\n gridcolor: '#efefef',\n gridwidth: 0.2,\n zerolinecolor: '#969696',\n zerolinewidth: 1,\n linecolor: '#bababa',\n linewidth: 1,\n fixedrange: true, // Disable zooming\n ticksuffix: ' ', // Add space between y axis and ticks\n },\n bargap: 0.03, // Gap between bars\n dragmode: 'select', // Enable selection for both click and drag\n selectdirection: 'h', // Allow selection in horizontal direction\n shapes: meanLine ? [meanLine] : [], // Add the mean line if it exists\n annotations: showMeanLine ? [{\n x: meanValue,\n y: 1.12, // Position above the top of the plot\n yref: 'paper',\n text: `Mean: ${isDateArray(data) ? new Date(meanValue).toLocaleDateString('en-US', { \n month: 'short', \n day: '2-digit', \n year: 'numeric' \n }) : meanValue.toFixed(2)}`,\n showarrow: false, // No arrow for the annotation\n font: {\n color: meanLineColor,\n size: 12,\n },\n }] : [],\n };\n\n const config: PlotParams['config'] = {\n responsive: true, // Make the plot responsive\n displayModeBar: false, // Hide the mode bar\n displaylogo: false, // Hide the Plotly logo\n scrollZoom: false, // Disable zooming with scroll\n staticPlot: false, // Enable interactivity\n };\n\n const containerStyles: React.CSSProperties = {\n width: \"100%\",\n height: \"100%\",\n position: \"relative\",\n ...containerStyleOverrides,\n };\n\n return (\n <div \n ref={containerRef}\n className=\"plot-container\"\n style={{\n '--selection-color': selectorsColor,\n ...containerStyles\n } as React.CSSProperties}\n >\n <Suspense fallback={\n <div style={{ \n width: \"100%\", \n height: \"100%\", \n minHeight: \"300px\",\n display: \"flex\", \n alignItems: \"center\", \n justifyContent: \"center\",\n color: \"#666\"\n }}>\n Loading plot...\n </div>\n }>\n <Plot \n data={plotlyData} \n layout={layout} \n config={config}\n onSelected={onSelected}\n onClick={onClick}\n useResizeHandler={true}\n style={{ \n width: \"100%\", \n height: \"100%\",\n display: \"block\"\n }}\n />\n </Suspense>\n </div>\n );\n}\n\nexport default HistogramPlot;\n","import React, { lazy, Suspense, useRef } from 'react';\nimport { PlotParams } from 'react-plotly.js';\nimport './plotStyles.scss';\nimport { calculateMean } from './Utils';\n\nconst Plot = lazy(() => import('react-plotly.js'));\n\nexport type RadialHistogramPlotProps = {\n data: number[];\n barColor?: string; // Optional prop to set the color of the bars\n unselectedBarColor?: string; // Optional prop to set the color of unselected bars\n selectorsColor?: string; // Optional prop to set the color of elements in the selection box\n onSelected?: (event: Plotly.PlotSelectionEvent) => void; // Optional handler for when a user clicks and drags to select an area\n onClick?: (event: Plotly.PlotMouseEvent) => void; // Optional handler for click events on the plot\n containerStyleOverrides?: React.CSSProperties; // Optional style override for the container\n barWidth?: number; // Optional bar width for radial histogram\n}\n\nexport const RadialHistogramPlot = (props: RadialHistogramPlotProps) => {\n const {\n data,\n barColor = 'rgb(72, 72, 74)',\n unselectedBarColor = 'rgba(203, 195, 195, 0.88)',\n selectorsColor = 'black',\n onSelected,\n onClick,\n containerStyleOverrides,\n barWidth = 20, // Default bar width in degrees\n } = props;\n\n // Simple ref for container\n const containerRef = useRef<HTMLDivElement>(null);\n\n // TEMPORARY Calculate histogram bins manually to get proper polar coordinates\n // This function should be extracted and used for both the regular and radial histograms.\n\n if (data.length === 0) {\n return null;\n }\n\n const min = Math.min(...data);\n const max = Math.max(...data);\n const numBins = Math.ceil(Math.sqrt(data.length)); // Default bin count\n const binWidth = (max - min) / numBins;\n \n // Create bins\n const binCounts = new Array(numBins).fill(0);\n const binCenters = [];\n \n for (let i = 0; i < numBins; i++) {\n binCenters.push(min + (i + 0.5) * binWidth);\n }\n \n // Count values in each bin\n data.forEach(value => {\n const binIndex = Math.min(Math.floor((value - min) / binWidth), numBins - 1);\n binCounts[binIndex]++;\n });\n\n\n const plotlyData: PlotParams['data'] = [\n {\n type: 'barpolar',\n theta: binCenters,\n r: binCounts,\n width: barWidth, // Width of each bar in degrees\n marker: {\n color: barColor,\n line: {\n color: \"white\",\n width: 0.5,\n },\n },\n // @ts-ignore - Not in the type but a valid property. See api https://plotly.com/javascript/reference/barpolar/#barpolar\n unselected: {\n marker: {\n color: unselectedBarColor,\n }\n },\n hovertemplate: '[%{x})<br>Count: %{y}<extra></extra>', // Custom hover text,\n }\n ];\n\n\n const layout: PlotParams['layout'] = {\n autosize: true,\n width: undefined,\n height: undefined,\n margin: {\n l: 50,\n r: 50,\n t: 30,\n b: 50,\n pad: 4\n },\n polar: {\n bgcolor: 'rgba(0,0,0,0)',\n sector: [90, -90],\n angularaxis: {\n tickmode: 'linear',\n tick0: 0,\n dtick: 45, // Show ticks every 45 degrees\n direction: \"counterclockwise\",\n rotation: 0,\n showgrid: true,\n gridcolor: '#efefef',\n gridwidth: 0.5,\n tickfont: {\n size: 10\n }\n },\n radialaxis: {\n title: {\n text: 'Count'\n },\n showgrid: true,\n gridcolor: '#efefef',\n gridwidth: 0.5,\n tickfont: {\n size: 10\n },\n angle: 90, // Position radial axis labels at top\n side: 'counterclockwise',\n }\n },\n dragmode: 'select',\n selectdirection: 'any',\n };\n\n const config: PlotParams['config'] = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n scrollZoom: false,\n staticPlot: false,\n };\n\n const containerStyles: React.CSSProperties = {\n width: \"100%\",\n height: \"100%\",\n position: \"relative\",\n ...containerStyleOverrides,\n };\n\n return (\n <div \n ref={containerRef}\n className=\"plot-container radial-histogram-container\"\n style={{\n '--selection-color': selectorsColor,\n ...containerStyles\n } as React.CSSProperties}\n >\n <Suspense fallback={\n <div style={{ \n width: \"100%\", \n height: \"100%\", \n minHeight: \"300px\",\n display: \"flex\", \n alignItems: \"center\", \n justifyContent: \"center\",\n }}>\n Loading radial plot...\n </div>\n }>\n <Plot \n data={plotlyData} \n layout={layout} \n config={config}\n onSelected={onSelected}\n onClick={onClick}\n useResizeHandler={true}\n style={{ \n width: \"100%\", \n height: \"100%\",\n display: \"block\"\n }}\n />\n </Suspense>\n </div>\n );\n};\n\nexport default RadialHistogramPlot;\n","// A test bar plotly plot\nimport React, { lazy } from 'react';\nimport { PlotParams } from 'react-plotly.js';\n\nconst Plot = lazy(() => import('react-plotly.js'));\n\nexport type TestPlotProps = {\n yaxisTitle?: string;\n xaxisTitle?: string;\n}\nexport const TestPlot = (props: TestPlotProps) => {\n const data: PlotParams['data'] = [\n {\n x: [1, 2, 3, 4],\n y: [10, 15, 13, 17],\n type: 'bar' as const,\n marker: { color: 'blue' },\n },\n ];\n\n const layout = {\n title: {text: 'Test Bar Plot'},\n xaxis: { title: {text: props.xaxisTitle ?? 'X Axis'} },\n yaxis: { title: {text: props.yaxisTitle ?? 'Y Axis'} },\n };\n\n return <Plot data={data} layout={layout} />;\n};\n\nexport default TestPlot;\n"],"names":["Plot","lazy","useRef","_jsx","Suspense"],"mappings":"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","x_google_ignoreList":[0,1]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "td-plots",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Custom React plotting components built with Plotly.js",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,9 +9,25 @@
|
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"module": "dist/index.esm.js",
|
|
11
11
|
"types": "dist/index.d.ts",
|
|
12
|
+
"style": "dist/index.css",
|
|
12
13
|
"files": [
|
|
13
14
|
"dist"
|
|
14
15
|
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "npm run clean && npm run build:rollup && npm run build:types",
|
|
18
|
+
"build:rollup": "rollup -c",
|
|
19
|
+
"build:types": "tsc --project tsconfig.build.json --emitDeclarationOnly",
|
|
20
|
+
"build:watch": "rollup -c --watch",
|
|
21
|
+
"build:types:watch": "tsc --project tsconfig.build.json --emitDeclarationOnly --watch",
|
|
22
|
+
"dev": "npm run build:watch",
|
|
23
|
+
"dev:full": "npm run build:types:watch & npm run build:watch",
|
|
24
|
+
"prepublishOnly": "npm run build",
|
|
25
|
+
"clean": "rm -rf dist",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"storybook": "storybook dev -p 6006",
|
|
28
|
+
"build-storybook": "storybook build",
|
|
29
|
+
"chromatic": "npx chromatic"
|
|
30
|
+
},
|
|
15
31
|
"keywords": [
|
|
16
32
|
"react",
|
|
17
33
|
"plotly",
|
|
@@ -47,19 +63,22 @@
|
|
|
47
63
|
"@types/react": "^19.1.8",
|
|
48
64
|
"@types/react-dom": "^19.1.6",
|
|
49
65
|
"@types/react-plotly.js": "^2.6.3",
|
|
66
|
+
"@types/seedrandom": "^3.0.8",
|
|
50
67
|
"@vitejs/plugin-react": "^4.6.0",
|
|
51
68
|
"@vitest/browser": "^3.2.4",
|
|
52
69
|
"@vitest/coverage-v8": "^3.2.4",
|
|
53
70
|
"@vitest/ui": "^3.2.4",
|
|
71
|
+
"chromatic": "^13.1.2",
|
|
54
72
|
"dotenv": "^16.5.0",
|
|
55
73
|
"jsdom": "^26.1.0",
|
|
56
74
|
"playwright": "^1.53.1",
|
|
57
|
-
"react": "^
|
|
58
|
-
"react-dom": "^
|
|
75
|
+
"react": "^18.3.1",
|
|
76
|
+
"react-dom": "^18.3.1",
|
|
59
77
|
"rollup": "^4.9.0",
|
|
60
78
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
61
79
|
"rollup-plugin-postcss": "^4.0.2",
|
|
62
80
|
"sass": "^1.69.0",
|
|
81
|
+
"seedrandom": "^3.0.5",
|
|
63
82
|
"storybook": "^9.0.13",
|
|
64
83
|
"ts-node": "^10.9.2",
|
|
65
84
|
"typescript": "^5.8.3",
|
|
@@ -67,14 +86,5 @@
|
|
|
67
86
|
"vitest": "^3.2.4",
|
|
68
87
|
"vitest-browser-react": "^1.0.0",
|
|
69
88
|
"vitest-plugin": "link:@storybook/addon-vitest/vitest-plugin"
|
|
70
|
-
},
|
|
71
|
-
"scripts": {
|
|
72
|
-
"build": "npm run clean && npm run build:rollup && npm run build:types",
|
|
73
|
-
"build:rollup": "rollup -c",
|
|
74
|
-
"build:types": "tsc --project tsconfig.build.json --emitDeclarationOnly",
|
|
75
|
-
"clean": "rm -rf dist",
|
|
76
|
-
"test": "vitest run",
|
|
77
|
-
"storybook": "storybook dev -p 6006",
|
|
78
|
-
"build-storybook": "storybook build"
|
|
79
89
|
}
|
|
80
|
-
}
|
|
90
|
+
}
|
package/dist/index.css
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.plot-container{height:100%;overflow:hidden!important;width:100%}.plot-container .point{border-radius:5px!important;overflow:hidden!important}.plot-container .cursor-ns-resize{height:0;width:0}.plot-container .cursor-ew-resize{fill:var(--selection-color,blue)!important;stroke:var(--selection-color,blue)!important}.plot-container .selectionlayer>path{stroke:var(--selection-color,blue)!important;stroke-dasharray:0!important;stroke-width:1px!important;opacity:.5!important}.plot-container .zoomlayer>path{stroke-dasharray:0!important;stroke:var(--selection-color,blue)!important;fill:var(--selection-color,blue)!important}
|
package/dist/index.esm.css
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.plot-container{height:100%;overflow:hidden!important;width:100%}.plot-container .point{border-radius:5px!important;overflow:hidden!important}.plot-container .cursor-ns-resize{height:0;width:0}.plot-container .cursor-ew-resize{fill:var(--selection-color,blue)!important;stroke:var(--selection-color,blue)!important}.plot-container .selectionlayer>path{stroke:var(--selection-color,blue)!important;stroke-dasharray:0!important;stroke-width:1px!important;opacity:.5!important}.plot-container .zoomlayer>path{stroke-dasharray:0!important;stroke:var(--selection-color,blue)!important;fill:var(--selection-color,blue)!important}
|