UNPKG

@macrostrat/column-components

Version:

React rendering primitives for stratigraphic columns

129 lines (128 loc) 3.22 kB
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