@@ -6,6 +6,61 @@ import {
66} from "../prepare-units/composite-scale" ;
77import { ColumnAxisType } from "@macrostrat/column-components" ;
88import type { ExtUnit , PackageLayoutData } from "../prepare-units" ;
9+ // An isolated jotai store for Macrostrat column usage
10+ // TODO: there might be a better way to do this using the MacrostratDataProvider or similar
11+ import { createIsolation } from "jotai-scope" ;
12+ import { atom , type WritableAtom } from "jotai" ;
13+
14+ const { Provider, useAtom, useAtomValue, useStore } = createIsolation ( ) ;
15+
16+ type ProviderProps = {
17+ children : ReactNode ;
18+ initialValues ?: Iterable < [ WritableAtom < any , any , any > , any ] > ;
19+ } ;
20+
21+ const columnUnitsAtom = atom < ExtUnit [ ] > ( ) ;
22+
23+ const columnUnitsMapAtom = atom < Map < number , ExtUnit > | null > ( ( get ) => {
24+ const units = get ( columnUnitsAtom ) ;
25+ if ( ! units ) return null ;
26+ const unitMap = new Map < number , ExtUnit > ( ) ;
27+ units . forEach ( ( unit ) => {
28+ unitMap . set ( unit . unit_id , unit ) ;
29+ } ) ;
30+ return unitMap ;
31+ } ) ;
32+
33+ function ScopedProvider ( { children, ...rest } : ProviderProps ) {
34+ // Always use the same store instance in this tree
35+ let val = null ;
36+ try {
37+ val = useStore ( ) ;
38+ } catch {
39+ // No store found, create a new one
40+ val = null ;
41+ }
42+ return h ( Provider , { store : val , ...rest } , children ) ;
43+ }
44+
45+ export function MacrostratColumnStateProvider ( {
46+ children,
47+ units,
48+ } : {
49+ children : ReactNode ;
50+ units : ExtUnit [ ] ;
51+ } ) {
52+ /** Top-level provider for Macrostrat column data.
53+ * It is either provided by the Column component itself, or
54+ * can be hoisted higher in the tree to provide a common data context
55+ */
56+ return h (
57+ ScopedProvider ,
58+ {
59+ initialValues : [ [ columnUnitsAtom , units ] ] ,
60+ } ,
61+ children ,
62+ ) ;
63+ }
964
1065export interface MacrostratColumnDataContext {
1166 units : ExtUnit [ ] ;
@@ -24,7 +79,7 @@ export function MacrostratColumnDataProvider({
2479 totalHeight,
2580 axisType,
2681} : MacrostratColumnDataContext & { children : ReactNode } ) {
27- /** Provider for Macrostrat column data.
82+ /** Internal provider for Macrostrat column data.
2883 * As a general rule, we want to provide data and column-axis
2984 * height calculations through the context, since these need to
3085 * be accessed by any component that lays out information on the
@@ -45,7 +100,11 @@ export function MacrostratColumnDataProvider({
45100 } ;
46101 } , [ units , sections , totalHeight , axisType ] ) ;
47102
48- return h ( MacrostratColumnDataContext . Provider , { value } , children ) ;
103+ return h (
104+ MacrostratColumnStateProvider ,
105+ { units } ,
106+ h ( MacrostratColumnDataContext . Provider , { value } , children ) ,
107+ ) ;
49108}
50109
51110export function useMacrostratColumnData ( ) {
@@ -59,19 +118,15 @@ export function useMacrostratColumnData() {
59118}
60119
61120export function useMacrostratUnits ( ) {
62- return useMacrostratColumnData ( ) . units ;
121+ return useAtomValue ( columnUnitsAtom ) ;
63122}
64123
65124export function useColumnUnitsMap ( ) : Map < number , ExtUnit > | null {
66- const ctx = useContext ( MacrostratColumnDataContext ) ;
67- return useMemo ( ( ) => {
68- if ( ctx == null ) return null ;
69- const unitMap = new Map < number , ExtUnit > ( ) ;
70- ctx . units . forEach ( ( unit ) => {
71- unitMap . set ( unit . unit_id , unit ) ;
72- } ) ;
73- return unitMap ;
74- } , [ ctx ?. units ] ) ;
125+ try {
126+ return useAtomValue ( columnUnitsMapAtom ) ;
127+ } catch {
128+ return null ;
129+ }
75130}
76131
77132export function useCompositeScale ( ) : CompositeColumnScale {
0 commit comments