Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/column-views/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format
is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.2.1] - 2025-11-29

- Start unifying state management components
- Create a hoistable store for column state
- Begin using `jotai` for some aspects of state management

## [2.2.0] - 2025-11-28

- Update SGP and PBDB facets
Expand Down
4 changes: 3 additions & 1 deletion packages/column-views/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@macrostrat/column-views",
"version": "2.2.0",
"version": "2.2.1",
"description": "Data views for Macrostrat stratigraphic columns",
"type": "module",
"source": "src/index.ts",
Expand Down Expand Up @@ -63,6 +63,8 @@
"d3-path": "^3.1.0",
"d3-scale": "^4.0.2",
"d3-shape": "^3.2.0",
"jotai": "^2.15.1",
"jotai-scope": "^0.9.7",
"mapbox-gl": "^2.15.0||^3.0.0",
"react-spring": "^9.7.5",
"topojson-client": "^3.1.0",
Expand Down
31 changes: 17 additions & 14 deletions packages/column-views/src/column.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ import {
ComponentType,
} from "react";
import styles from "./column.module.sass";
import { UnitComponent } from "./units";
import {
UnitSelectionProvider,
UnitComponent,
UnitKeyboardNavigation,
useUnitSelectionDispatch,
} from "./units";
} from "./data-provider";

import {
Identifier,
Expand Down Expand Up @@ -95,7 +95,6 @@ export function Column(props: ColumnProps) {
selectedUnit,
children,
units: rawUnits,
axisType = ColumnAxisType.AGE,
t_age,
b_age,
t_pos,
Expand All @@ -109,6 +108,7 @@ export function Column(props: ColumnProps) {
allowUnitSelection,
hybridScale,
scale,
axisType,
...rest
} = props;
const ref = useRef<HTMLElement>();
Expand All @@ -125,8 +125,20 @@ export function Column(props: ColumnProps) {
_minPixelScale = pixelScale;
}

// Handle special cases for hybrid scales (WIP, we need to regularize this)
let _axisType = axisType ?? ColumnAxisType.AGE;
let ageAxisComponent = CompositeAgeAxis;
if (
hybridScale?.type === HybridScaleType.ApproximateHeight &&
_axisType != ColumnAxisType.AGE
) {
// Use approximate height axis for non-age columns if a non-age axis type is requested
ageAxisComponent = ApproximateHeightAxis;
_axisType = ColumnAxisType.AGE;
}

const { sections, units, totalHeight } = usePreparedColumnUnits(rawUnits, {
axisType,
axisType: _axisType,
t_age,
b_age,
t_pos,
Expand Down Expand Up @@ -154,15 +166,6 @@ export function Column(props: ColumnProps) {
);
}

let ageAxisComponent = CompositeAgeAxis;
if (
hybridScale?.type === HybridScaleType.ApproximateHeight &&
axisType != ColumnAxisType.AGE
) {
// Use approximate height axis for non-age columns if a non-age axis type is requested
ageAxisComponent = ApproximateHeightAxis;
}

let main: any = h(
ColumnInner,
{ columnRef: ref, ageAxisComponent, ...rest },
Expand Down Expand Up @@ -196,7 +199,7 @@ export function Column(props: ColumnProps) {

return h(
MacrostratColumnDataProvider,
{ units, sections, totalHeight, axisType },
{ units, sections, totalHeight, axisType: _axisType },
main,
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/column-views/src/correlation-chart/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
UnitSelectionProvider,
UnitKeyboardNavigation,
useUnitSelectionStore,
} from "../units";
} from "../data-provider";
import { UnitSelectionPopover } from "../unit-details";
import hyper from "@macrostrat/hyper";
import styles from "./main.module.sass";
Expand Down
1 change: 1 addition & 0 deletions packages/column-views/src/data-provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./fetch";
export * from "./base";
export * from "./column-nav";
export * from "./store";
export * from "./unit-selection";
79 changes: 67 additions & 12 deletions packages/column-views/src/data-provider/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,61 @@ import {
} from "../prepare-units/composite-scale";
import { ColumnAxisType } from "@macrostrat/column-components";
import type { ExtUnit, PackageLayoutData } from "../prepare-units";
// An isolated jotai store for Macrostrat column usage
// TODO: there might be a better way to do this using the MacrostratDataProvider or similar
import { createIsolation } from "jotai-scope";
import { atom, type WritableAtom } from "jotai";

const { Provider, useAtom, useAtomValue, useStore } = createIsolation();

type ProviderProps = {
children: ReactNode;
initialValues?: Iterable<[WritableAtom<any, any, any>, any]>;
};

const columnUnitsAtom = atom<ExtUnit[]>();

const columnUnitsMapAtom = atom<Map<number, ExtUnit> | null>((get) => {
const units = get(columnUnitsAtom);
if (!units) return null;
const unitMap = new Map<number, ExtUnit>();
units.forEach((unit) => {
unitMap.set(unit.unit_id, unit);
});
return unitMap;
});

function ScopedProvider({ children, ...rest }: ProviderProps) {
// Always use the same store instance in this tree
let val = null;
try {
val = useStore();
} catch {
// No store found, create a new one
val = null;
}
return h(Provider, { store: val, ...rest }, children);
}

export function MacrostratColumnStateProvider({
children,
units,
}: {
children: ReactNode;
units: ExtUnit[];
}) {
/** Top-level provider for Macrostrat column data.
* It is either provided by the Column component itself, or
* can be hoisted higher in the tree to provide a common data context
*/
return h(
ScopedProvider,
{
initialValues: [[columnUnitsAtom, units]],
},
children,
);
}

export interface MacrostratColumnDataContext {
units: ExtUnit[];
Expand All @@ -24,7 +79,7 @@ export function MacrostratColumnDataProvider({
totalHeight,
axisType,
}: MacrostratColumnDataContext & { children: ReactNode }) {
/** Provider for Macrostrat column data.
/** Internal provider for Macrostrat column data.
* As a general rule, we want to provide data and column-axis
* height calculations through the context, since these need to
* be accessed by any component that lays out information on the
Expand All @@ -45,7 +100,11 @@ export function MacrostratColumnDataProvider({
};
}, [units, sections, totalHeight, axisType]);

return h(MacrostratColumnDataContext.Provider, { value }, children);
return h(
MacrostratColumnStateProvider,
{ units },
h(MacrostratColumnDataContext.Provider, { value }, children),
);
}

export function useMacrostratColumnData() {
Expand All @@ -59,19 +118,15 @@ export function useMacrostratColumnData() {
}

export function useMacrostratUnits() {
return useMacrostratColumnData().units;
return useAtomValue(columnUnitsAtom);
}

export function useColumnUnitsMap(): Map<number, ExtUnit> | null {
const ctx = useContext(MacrostratColumnDataContext);
return useMemo(() => {
if (ctx == null) return null;
const unitMap = new Map<number, ExtUnit>();
ctx.units.forEach((unit) => {
unitMap.set(unit.unit_id, unit);
});
return unitMap;
}, [ctx?.units]);
try {
return useAtomValue(columnUnitsMapAtom);
} catch {
return null;
}
}

export function useCompositeScale(): CompositeColumnScale {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
useCallback,
} from "react";
import { createStore, StoreApi, useStore } from "zustand";
import type { RectBounds, IUnit } from "./types";
import type { RectBounds, IUnit } from "../units/types";

type UnitSelectDispatch = (
unit: number | BaseUnit | null,
Expand Down
1 change: 0 additions & 1 deletion packages/column-views/src/maps/column-correlation/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { lineIntersect } from "@turf/line-intersect";
import distance from "@turf/distance";
import { nearestPointOnLine } from "@turf/nearest-point-on-line";
import { centroid } from "@turf/centroid";
import mapboxgl from "mapbox-gl";
import {
createContext,
useState,
Expand Down
2 changes: 1 addition & 1 deletion packages/column-views/src/unit-details/panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ function UnitIDList({ units, onSelectUnit, showNames = false }) {
const u1 = units.filter((d) => d != 0);
if (showNames) {
return u1.map((unitID) => {
const unitData = unitsMap.get(unitID);
const unitData = unitsMap?.get(unitID);
let name: string = undefined;
if (unitData != null) {
name = defaultNameFunction(unitData);
Expand Down
2 changes: 1 addition & 1 deletion packages/column-views/src/unit-details/popover.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import hyper from "@macrostrat/hyper";
import { Popover } from "@blueprintjs/core";
import styles from "./popover.module.sass";
import { useSelectedUnit, useUnitSelectionStore } from "../units";
import { useSelectedUnit, useUnitSelectionStore } from "../data-provider";
import { UnitDetailsPanel } from "./panel";

const h = hyper.styled(styles);
Expand Down
3 changes: 1 addition & 2 deletions packages/column-views/src/units/boxes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ import { SizeAwareLabel, Clickable } from "@macrostrat/ui-components";
import hyper from "@macrostrat/hyper";
import { forwardRef, ReactNode, useContext, useMemo } from "react";
import { resolveID, scalePattern } from "./resolvers";
import { useUnitSelectionTarget } from "./selection";
import { useUnitSelectionTarget, useLithologies } from "../data-provider";
import { IUnit } from "./types";
import styles from "./boxes.module.sass";
import classNames from "classnames";
import { getUnitHeightRange } from "../prepare-units/utils";
import { useLithologies } from "../data-provider";
import { getMixedUnitColor } from "./colors";
import type { RectBounds } from "./types";

Expand Down
7 changes: 5 additions & 2 deletions packages/column-views/src/units/composite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ import {
import { BaseUnit } from "@macrostrat/api-types";
import { LabeledUnit, UnitBoxes } from "./boxes";
import styles from "./composite.module.sass";
import { useCompositeScale, useMacrostratColumnData } from "../data-provider";
import { useUnitSelectionDispatch } from "../units";
import {
useCompositeScale,
useMacrostratColumnData,
useUnitSelectionDispatch,
} from "../data-provider";

const h = hyperStyled(styles);

Expand Down
1 change: 0 additions & 1 deletion packages/column-views/src/units/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { Lithology } from "@macrostrat/api-types";

export * from "./composite";
export * from "./types";
export * from "./selection";
export * from "./colors";

export function UnitsColumn({ width = 100 }) {
Expand Down
6 changes: 1 addition & 5 deletions packages/column-views/stories/nonlinear-scale.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export const WithApproximateHeightScaleOnly: Story = {
id: 448,
// Ordered time bins
pixelScale: 0.5,
axisType: ColumnAxisType.AGE,
axisType: ColumnAxisType.HEIGHT,
hybridScale: {
type: HybridScaleType.ApproximateHeight,
},
Expand All @@ -177,9 +177,5 @@ export const WithApproximateHeightScaleOnly: Story = {
showTimescale: false,
unconformityHeight: 20,
unconformityLabels: false,
children: h(ApproximateHeightAxis, {
// Move to the left side
style: { order: -1, marginRight: "8px" },
}),
},
};
Loading