UNPKG

@macrostrat/column-components

Version:

React rendering primitives for stratigraphic columns

139 lines (121 loc) 3.31 kB
import { Component, useContext } from "react"; import h from "@macrostrat/hyper"; import classNames from "classnames"; import { ColumnContext, AssetPathContext, ColumnCtx, ColumnDivision, AssetPathCtx, } from "./context"; import { UUIDComponent } from "./frame"; const symbolIndex = { "Hummocky cross-stratified": "hcs.svg", "Trough cross-stratified": "tcs.svg", "Dessication cracks": "dessication-cracks.svg", Ooids: "ooids.svg", "Domal stromatolites": "domal-stromatolites.svg", "Digitate stromatolites": "digitate-stromatolites.svg", }; const Symbol = function (props) { const { symbol, width, height, UUID } = props; const { resolveSymbol } = useContext(AssetPathContext); const id = `${UUID}-${symbol}`; const symbolSize = { width }; const href = resolveSymbol(symbolIndex[symbol]); return h( "symbol", { id, key: id, ...symbolSize, }, [ h("image", { href, x: 0, y: 0, ...symbolSize, }), ], ); }; const SymbolDefs = function (props) { const { patterns, ...rest } = props; const ids = []; return h( "defs", patterns.map(function (sym) { const { symbol } = sym; if (ids.includes(symbol)) { return null; } ids.push(symbol); return h(Symbol, { symbol, ...rest }); }), ); }; interface SymbolColumnProps { width: number; left: number; symbols: any[]; } export class SymbolColumn extends UUIDComponent<SymbolColumnProps> { constructor(props) { super(props); this.renderSymbol = this.renderSymbol.bind(this); } static contextType = ColumnContext; context: ColumnCtx<ColumnDivision>; static defaultProps = { width: 30, left: 0, }; render() { const { scale, pixelHeight, zoom } = this.context; const { left, width } = this.props; let { symbols } = this.props; const patterns = symbols.filter((x, i, arr) => arr.indexOf(x) === i); let transform = null; if (left != null) { transform = `translate(${left})`; } symbols = symbols .filter((d) => d.symbol_min_zoom < zoom) .map(this.renderSymbol); const x = 0; const y = 0; return h("g.symbol-column", { transform }, [ h(SymbolDefs, { width, patterns, UUID: this.UUID }), h("rect.symbol-column-area", { width, height: pixelHeight }), h("g.symbols", symbols), ]); } renderSymbol(d) { const { scale, pixelHeight } = this.context; const { symbol, id, height } = d; const className = classNames({ symbol }, "symbol"); const { width } = this.props; const y = scale(height) - width / 2; if (y < 0 || y > pixelHeight) return null; const href = `#${this.UUID}-${symbol}`; return h("use", { className, y, x: 0, width, xlinkHref: href, key: id }); } } export class SymbolLegend extends Component { static contextType = AssetPathContext; context: AssetPathCtx; render() { const { resolveSymbol } = this.context; const arr = []; for (let name in symbolIndex) { const symbol = symbolIndex[name]; const sym = h("div", { key: name }, [ h("img", { src: resolveSymbol(symbol) }), h("span.label", name), ]); arr.push(sym); } return h("div.symbol-legend", arr); } }