Skip to content

Commit

Permalink
Merge branch 'main' into 66-volcano-plot-tooltips
Browse files Browse the repository at this point in the history
  • Loading branch information
jernestmyers committed Aug 9, 2023
2 parents 35be26c + e5396e5 commit 41919f4
Show file tree
Hide file tree
Showing 42 changed files with 2,305 additions and 851 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ dist
# TernJS port file
.tern-port

# VSCode config files
.vscode

.editorconfig

.pnp.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export interface AxisRangeControlProps
disabled?: boolean;
/** is this for a log scale axis? If so, we'll validate the min value to be > 0 */
logScale?: boolean;
/** specify step for increment/decrement buttons in MUI number inputs; MUI's default is 1 */
step?: number;
}

export default function AxisRangeControl({
Expand All @@ -33,6 +35,7 @@ export default function AxisRangeControl({
// add disabled prop to disable input fields: default is false
disabled = false,
logScale = false,
step = undefined,
}: AxisRangeControlProps) {
const validator = useCallback(
(
Expand Down Expand Up @@ -87,6 +90,7 @@ export default function AxisRangeControl({
validator={validator}
// add disabled prop to disable input fields
disabled={disabled}
step={step}
/>
)
) : null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React from 'react';
import { range } from 'd3';
import _ from 'lodash';

// set props for custom legend function
export interface PlotLegendBubbleProps {
legendMax: number;
valueToDiameterMapper: ((value: number) => number) | undefined;
}

// legend ellipsis function for legend title and legend items (from custom legend work)
// const legendEllipsis = (label: string, ellipsisLength: number) => {
// return (label || '').length > ellipsisLength
// ? (label || '').substring(0, ellipsisLength) + '...'
// : label;
// };

export default function PlotBubbleLegend({
legendMax,
valueToDiameterMapper,
}: PlotLegendBubbleProps) {
if (valueToDiameterMapper) {
// Declare constants
const tickFontSize = '0.8em';
// const legendTextSize = '1.0em';
const circleStrokeWidth = 3;
const padding = 5;
const numCircles = 3;

// The largest circle's value will be the first number that's larger than
// legendMax and has only one significant digit. Each smaller circle will
// be half the size of the last (rounded and >= 1)
const legendMaxLog10 = Math.floor(Math.log10(legendMax));
const largestCircleValue =
legendMax <= 10
? legendMax
: (Number(legendMax.toPrecision(1)[0]) + 1) * 10 ** legendMaxLog10;
const circleValues = _.uniq(
range(numCircles)
.map((i) => Math.round(largestCircleValue / 2 ** i))
.filter((value) => value >= 1)
);

const largestCircleDiameter = valueToDiameterMapper(largestCircleValue);
const largestCircleRadius = largestCircleDiameter / 2;

const tickLength = largestCircleRadius + 5;

return (
<svg
width={largestCircleDiameter + (tickLength - largestCircleRadius) + 50}
height={largestCircleDiameter + circleStrokeWidth * 2 + padding * 2}
>
{circleValues.map((value, i) => {
const circleDiameter = valueToDiameterMapper(value);
const circleRadius = circleDiameter / 2;
const tickY =
padding +
largestCircleDiameter +
circleStrokeWidth -
circleDiameter;

return (
<>
<circle
cx={padding + largestCircleRadius + circleStrokeWidth}
cy={
padding +
largestCircleDiameter +
circleStrokeWidth -
circleRadius
}
r={circleRadius}
stroke="black"
strokeWidth={circleStrokeWidth}
fill="white"
/>
<g
className="axisTick"
overflow="visible"
key={'gradientTick' + i}
>
<line
x1={padding + largestCircleRadius + circleStrokeWidth + 1}
x2={
padding +
largestCircleRadius +
circleStrokeWidth +
tickLength +
1
}
y1={tickY}
y2={tickY}
stroke="black"
strokeDasharray="2 2"
strokeWidth={2}
/>
<text
x={padding + largestCircleRadius + tickLength + 5}
y={tickY}
dominantBaseline="middle"
fontSize={tickFontSize}
>
{value}
</text>
</g>
</>
);
})}
</svg>
);
} else {
return null;
}

// for display, convert large value with k (e.g., 12345 -> 12k): return original value if less than a criterion
// const sumLabel = props.markerLabel ?? String(fullPieValue);
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ export default function PlotGradientLegend({

return (
<div>
<svg id="gradientLegend" height={gradientBoxHeight + 20} width={150}>
<svg
id="gradientLegend"
height={gradientBoxHeight + 20}
width={gradientBoxWidth + 60}
>
<defs>
<linearGradient id="linearGradient" x1="0" x2="0" y1="1" y2="0">
{stopPoints}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import PlotListLegend, { PlotListLegendProps } from './PlotListLegend';
import PlotGradientLegend, {
PlotLegendGradientProps,
} from './PlotGradientLegend';
import PlotBubbleLegend, { PlotLegendBubbleProps } from './PlotBubbleLegend';

interface PlotLegendBaseProps extends ContainerStylesAddon {
legendTitle?: string;
Expand All @@ -13,6 +14,7 @@ export type PlotLegendProps = PlotLegendBaseProps &
(
| ({ type: 'list' } & PlotListLegendProps)
| ({ type: 'colorscale' } & PlotLegendGradientProps)
| ({ type: 'bubble' } & PlotLegendBubbleProps)
);

export default function PlotLegend({
Expand All @@ -29,7 +31,8 @@ export default function PlotLegend({
{((type === 'list' &&
((otherProps as PlotListLegendProps).legendItems.length > 1 ||
(otherProps as PlotListLegendProps).showOverlayLegend)) ||
type === 'colorscale') && (
type === 'colorscale' ||
type === 'bubble') && (
<div
style={{
display: 'inline-block', // for general usage (e.g., story)
Expand Down Expand Up @@ -63,6 +66,9 @@ export default function PlotLegend({
{type === 'colorscale' && (
<PlotGradientLegend {...(otherProps as PlotLegendGradientProps)} />
)}
{type === 'bubble' && (
<PlotBubbleLegend {...(otherProps as PlotLegendBubbleProps)} />
)}
</div>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { NumberInput, DateInput } from './NumberAndDateInputs';
import Button from './Button';
import Notification from './Notification';
import { NumberRange, DateRange, NumberOrDateRange } from '../../types/general';
import { propTypes } from 'react-bootstrap/esm/Image';

export type BaseProps<M extends NumberOrDateRange> = {
/** Externally controlled range. */
Expand Down Expand Up @@ -44,7 +45,7 @@ export type BaseProps<M extends NumberOrDateRange> = {
disabled?: boolean;
};

export type NumberRangeInputProps = BaseProps<NumberRange>;
export type NumberRangeInputProps = BaseProps<NumberRange> & { step?: number };

export function NumberRangeInput(props: NumberRangeInputProps) {
return <BaseInput {...props} valueType="number" />;
Expand Down Expand Up @@ -85,6 +86,7 @@ function BaseInput({
clearButtonLabel = 'Clear',
// add disabled prop to disable input fields
disabled = false,
...props
}: BaseInputProps) {
if (validator && required)
console.log(
Expand Down Expand Up @@ -161,6 +163,7 @@ function BaseInput({
]);

const { min, max } = localRange ?? {};
const step = 'step' in props ? props.step : undefined;

return (
<div style={{ ...containerStyles }}>
Expand Down Expand Up @@ -188,6 +191,7 @@ function BaseInput({
}}
// add disabled prop to disable input fields
disabled={disabled}
step={step}
/>
) : (
<DateInput
Expand Down Expand Up @@ -236,6 +240,7 @@ function BaseInput({
}}
// add disabled prop to disable input fields
disabled={disabled}
step={step}
/>
) : (
<DateInput
Expand Down
11 changes: 11 additions & 0 deletions packages/libs/components/src/components/widgets/Slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ import { DARK_GRAY, LIGHT_GRAY, MEDIUM_GRAY } from '../../constants/colors';
import { debounce } from 'lodash';
import { NumberOrDate } from '../../types/general';

// a color spec shared among plot components that implements the track gradient
export const plotsSliderOpacityGradientColorSpec: SliderWidgetProps['colorSpec'] =
{
type: 'gradient',
tooltip: '#aaa',
knobColor: '#aaa',
// normal slider color: e.g., from 0 to 1
trackGradientStart: '#fff',
trackGradientEnd: '#000',
};

export type SliderWidgetProps = {
/** The minimum value of the slider. */
minimum?: number;
Expand Down
2 changes: 2 additions & 0 deletions packages/libs/components/src/map/BoundsDriftMarker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default function BoundsDriftMarker({
showPopup,
popupContent,
popupClass,
zIndexOffset,
}: BoundsDriftMarkerProps) {
const map = useMap();
const boundingBox = new LatLngBounds([
Expand Down Expand Up @@ -300,6 +301,7 @@ export default function BoundsDriftMarker({
mouseout: (e: LeafletMouseEvent) => handleMouseOut(e),
dblclick: handleDoubleClick,
}}
zIndexOffset={zIndexOffset}
{...optionalIconProp}
>
{showPopup && popup}
Expand Down
Loading

0 comments on commit 41919f4

Please sign in to comment.