@macrostrat/column-views 3.4.1 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,10 @@
1
- import { createContext, ReactNode, useContext, useMemo } from "react";
1
+ import {
2
+ createContext,
3
+ ReactNode,
4
+ RefObject,
5
+ useContext,
6
+ useMemo,
7
+ } from "react";
2
8
  import h from "@macrostrat/hyper";
3
9
  import {
4
10
  CompositeColumnScale,
@@ -11,13 +17,18 @@ import {
11
17
  selectedUnitIDAtom,
12
18
  UnitSelectionCallbacks,
13
19
  UnitSelectionCallbackManager,
20
+ selectedUnitElementAtom,
14
21
  } from "./unit-selection";
15
22
  import type { BaseUnit } from "@macrostrat/api-types";
16
- import { type AtomMap, createScopedStore } from "@macrostrat/data-components";
23
+ import {
24
+ type AtomMap,
25
+ createScopedStore,
26
+ StateIsolation,
27
+ } from "@macrostrat/data-components";
17
28
  import { atom } from "jotai";
18
29
  import { useEffect } from "react";
19
30
 
20
- export const scope = createScopedStore();
31
+ export const scope: StateIsolation = createScopedStore();
21
32
 
22
33
  export const columnUnitsAtom = atom<BaseUnit[]>();
23
34
 
@@ -84,6 +95,13 @@ export function MacrostratColumnStateProvider<T extends BaseUnit>({
84
95
  );
85
96
  }
86
97
 
98
+ /** Interface for imperative handlers that can
99
+ * be invoked outside of the column's react context
100
+ */
101
+ export interface ColumnRef {
102
+ scrollSelectedUnitIntoView(): void;
103
+ }
104
+
87
105
  export interface MacrostratColumnDataContext<T extends BaseUnit> {
88
106
  units: T[];
89
107
  sections: PackageLayoutData[];
@@ -95,6 +113,7 @@ export interface MacrostratColumnDataContext<T extends BaseUnit> {
95
113
  export interface ColumnDataProviderProps<T extends BaseUnit>
96
114
  extends MacrostratColumnDataContext<T>, ColumnStateProviderProps<T> {
97
115
  children: ReactNode;
116
+ ref: RefObject<ColumnRef>;
98
117
  }
99
118
 
100
119
  const MacrostratColumnDataContext =
@@ -109,6 +128,7 @@ export function MacrostratColumnDataProvider<T extends BaseUnit>({
109
128
  allowUnitSelection,
110
129
  onUnitSelected,
111
130
  selectedUnit,
131
+ ref,
112
132
  }: ColumnDataProviderProps<T>) {
113
133
  /** Internal provider for Macrostrat column data.
114
134
  * As a general rule, we want to provide data and column-axis
@@ -138,11 +158,35 @@ export function MacrostratColumnDataProvider<T extends BaseUnit>({
138
158
  allowUnitSelection,
139
159
  onUnitSelected,
140
160
  selectedUnit,
161
+ ref,
141
162
  },
142
- h(MacrostratColumnDataContext.Provider, { value }, children),
163
+ [
164
+ h(ColumnRefManager, { ref }),
165
+ h(MacrostratColumnDataContext.Provider, { value }, children),
166
+ ],
143
167
  );
144
168
  }
145
169
 
170
+ function ColumnRefManager({ ref }: { ref?: RefObject<ColumnRef> }) {
171
+ const selectedUnitElement = scope.useAtomValue(selectedUnitElementAtom);
172
+ useEffect(() => {
173
+ if (ref == null) return;
174
+ ref.current = {
175
+ scrollSelectedUnitIntoView(opts?: ScrollIntoViewOptions) {
176
+ selectedUnitElement?.scrollIntoView(
177
+ opts ?? {
178
+ behavior: "smooth",
179
+ block: "center",
180
+ inline: "nearest",
181
+ },
182
+ );
183
+ },
184
+ };
185
+ }, [ref, selectedUnitElement]);
186
+
187
+ return null;
188
+ }
189
+
146
190
  export function UnitSelectionProvider(props: ColumnStateProviderProps<any>) {
147
191
  /* A basic unit selection provider without column data context.
148
192
  Mostly for use with the CorrelationChart component.
@@ -48,6 +48,7 @@ export interface UnitSelectionCallbacks {
48
48
  export const allowUnitSelectionAtom = atom<boolean>(true);
49
49
 
50
50
  export const selectedUnitIDAtom = atom<number | null>();
51
+ export const selectedUnitElementAtom = atom<HTMLElement | null>();
51
52
 
52
53
  const overlayPositionAtom = atom<RectBounds | null>();
53
54
 
@@ -113,6 +114,7 @@ const selectedUnitAtom = atom(
113
114
  };
114
115
  }
115
116
 
117
+ set(selectedUnitElementAtom, target);
116
118
  set(selectedUnitIDAtom, unitID);
117
119
  set(overlayPositionAtom, overlayPosition);
118
120
 
@@ -158,6 +160,7 @@ export function useUnitSelectionTarget(
158
160
  const ref = useRef<HTMLElement>(null);
159
161
  const [selectedUnit, selectUnit] = useUnitSelection();
160
162
  const selected = selectedUnit?.unit_id == unit.unit_id;
163
+ const selectedUnitElement = scope.useAtomValue(selectedUnitElementAtom);
161
164
 
162
165
  const onClick = useCallback(
163
166
  (evt: Event) => {
@@ -168,17 +171,19 @@ export function useUnitSelectionTarget(
168
171
  );
169
172
 
170
173
  useEffect(() => {
171
- if (!selected || selectUnit == null) return;
172
- // In case we haven't set the position of the unit (if we don't have a target), set the selected unit
173
- selectUnit(unit, ref.current);
174
+ // Sync selection with unit element...
175
+ if (!selected) return;
176
+ selectUnit?.(unit, ref.current);
177
+ }, [ref.current, selected, selectUnit]);
174
178
 
179
+ useEffect(() => {
175
180
  // Scroll the unit into view
176
- ref.current?.scrollIntoView({
181
+ selectedUnitElement?.scrollIntoView({
177
182
  behavior: "smooth",
178
183
  block: "center",
179
184
  inline: "nearest",
180
185
  });
181
- }, [selected, selectUnit]);
186
+ }, [selectedUnitElement]);
182
187
 
183
188
  return [ref, selected, onClick];
184
189
  }
package/src/section.ts CHANGED
@@ -17,7 +17,10 @@ import {
17
17
  useMacrostratUnits,
18
18
  MacrostratColumnProvider,
19
19
  } from "./data-provider";
20
- import { useMacrostratBaseURL } from "@macrostrat/data-provider";
20
+ import {
21
+ useMacrostratBaseURL,
22
+ useMacrostratData,
23
+ } from "@macrostrat/data-provider";
21
24
  import { Duration } from "./unit-details";
22
25
  import { Value } from "@macrostrat/data-components";
23
26
  import type { ExtUnit, PackageScaleLayoutData } from "./prepare-units/types";
@@ -222,7 +225,7 @@ export function CompositeTimescaleCore(props: CompositeTimescaleCoreProps) {
222
225
 
223
226
  // Use intervals from Macrostrat API
224
227
  const baseURL = useMacrostratBaseURL();
225
- const intervals = useMacrostratIntervals(baseURL);
228
+ const intervals = useMacrostratIntervals({ baseURL });
226
229
 
227
230
  let _levels: [number, number];
228
231
  if (typeof levels === "number") {