@macrostrat/column-components
Version:
React rendering primitives for stratigraphic columns
129 lines (128 loc) • 3.22 kB
JavaScript
import { scaleLinear, scaleOrdinal } from "d3-scale";
import { createContext, useContext, Component, useMemo, useCallback } from "react";
import h from "@macrostrat/hyper";
import { ColumnContext, useColumnDivisions } from "./column.js";
const ColumnLayoutContext = createContext({
scale: scaleLinear(),
scaleClamped: scaleLinear().clamp(true),
width: 0,
divisions: [],
grainSizes: [],
grainsizeScale: (d) => 40,
xScale: null,
widthForDivision: (d) => 0,
pixelsPerMeter: 1,
zoom: 1
});
function ColumnLayoutProvider({
children,
width,
grainSizes = [],
grainsizeScale = (d) => 40,
xScale
}) {
const ctx = useContext(ColumnContext);
return h(
ColumnLayoutContext.Provider,
{
value: {
...ctx,
width,
grainSizes,
grainsizeScale,
xScale,
widthForDivision: (d) => width
}
},
children
);
}
class CrossAxisLayoutProvider extends Component {
static contextType = ColumnContext;
render() {
let { domain, range, width, children } = this.props;
if (range == null) {
range = [0, width];
}
const xScale = scaleLinear().domain(domain).range(range);
return h(ColumnLayoutProvider, {
...this.context,
xScale,
width,
children
});
}
}
function GrainsizeLayoutProvider({
width,
grainSizes = ["ms", "s", "vf", "f", "m", "c", "vc", "p"],
grainsizeScaleStart = 50,
grainsizeScaleRange,
tickPositions,
children
}) {
if (grainsizeScaleRange == null) {
console.warn(
"GrainsizeLayoutProvider: grainsizeScaleStart and width are deprecated in favor of grainsizeScaleRange"
);
}
grainsizeScaleRange ??= [grainsizeScaleStart, width];
const divisions = useColumnDivisions();
const grainsizeScale = useMemo(() => {
const scale = scaleLinear().domain([0, grainSizes.length - 1]).range(grainsizeScaleRange);
tickPositions ??= grainSizes.map((d, i) => scale(i));
return scaleOrdinal().domain(grainSizes).range(tickPositions);
}, [grainSizes, grainsizeScaleRange, tickPositions]);
const grainsizeForDivision = useCallback(
(division) => {
let ix = divisions.indexOf(division);
while (ix > 0) {
const { grainsize } = divisions[ix];
if (grainsize != null) {
return grainsize;
}
ix -= 1;
}
},
[divisions]
);
const widthForDivision = useCallback(
(division) => {
if (division == null) {
return width;
}
return grainsizeScale(grainsizeForDivision(division));
},
[grainsizeForDivision, grainsizeScale, width]
);
return h(
ColumnLayoutProvider,
{
width,
grainSizes,
grainsizeScale,
grainsizeScaleStart,
grainsizeScaleRange,
grainsizeForDivision,
widthForDivision
},
children
);
}
function useColumnLayout() {
const ctx = useContext(ColumnLayoutContext);
if (ctx == null) {
throw new Error(
"useColumnLayout must be used within a ColumnLayoutProvider"
);
}
return ctx;
}
export {
ColumnLayoutContext,
ColumnLayoutProvider,
CrossAxisLayoutProvider,
GrainsizeLayoutProvider,
useColumnLayout
};
//# sourceMappingURL=layout.js.map