@macrostrat/column-views 3.10.0 → 3.12.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.
- package/CHANGELOG.md +188 -0
- package/dist/age-model/data.cjs +57 -0
- package/dist/age-model/data.cjs.map +1 -0
- package/dist/age-model/data.d.ts +29 -0
- package/dist/age-model/data.js +57 -0
- package/dist/age-model/data.js.map +1 -0
- package/dist/age-model/details.cjs +261 -0
- package/dist/age-model/details.cjs.map +1 -0
- package/dist/age-model/details.d.ts +39 -0
- package/dist/age-model/details.js +258 -0
- package/dist/age-model/details.js.map +1 -0
- package/dist/age-model/details.module.sass.cjs +42 -0
- package/dist/age-model/details.module.sass.cjs.map +1 -0
- package/dist/age-model/details.module.sass.js +40 -0
- package/dist/age-model/details.module.sass.js.map +1 -0
- package/dist/age-model/index.d.ts +5 -0
- package/dist/age-model/legacy.cjs +28 -0
- package/dist/age-model/legacy.cjs.map +1 -0
- package/dist/age-model/legacy.d.ts +6 -0
- package/dist/age-model/legacy.js +26 -0
- package/dist/age-model/legacy.js.map +1 -0
- package/dist/age-model/surfaces.cjs +355 -0
- package/dist/age-model/surfaces.cjs.map +1 -0
- package/dist/age-model/surfaces.d.ts +68 -0
- package/dist/age-model/surfaces.js +352 -0
- package/dist/age-model/surfaces.js.map +1 -0
- package/dist/age-model/surfaces.module.sass.cjs +45 -0
- package/dist/age-model/surfaces.module.sass.cjs.map +1 -0
- package/dist/age-model/surfaces.module.sass.js +43 -0
- package/dist/age-model/surfaces.module.sass.js.map +1 -0
- package/dist/age-model/types.cjs +229 -0
- package/dist/age-model/types.cjs.map +1 -0
- package/dist/age-model/types.d.ts +112 -0
- package/dist/age-model/types.js +229 -0
- package/dist/age-model/types.js.map +1 -0
- package/dist/column-views.css +398 -56
- package/dist/column.cjs +20 -13
- package/dist/column.cjs.map +1 -1
- package/dist/column.d.ts +21 -6
- package/dist/column.js +21 -14
- package/dist/column.js.map +1 -1
- package/dist/column.module.sass.cjs +19 -15
- package/dist/column.module.sass.cjs.map +1 -1
- package/dist/column.module.sass.js +19 -15
- package/dist/column.module.sass.js.map +1 -1
- package/dist/correlation-chart/main.cjs +11 -3
- package/dist/correlation-chart/main.cjs.map +1 -1
- package/dist/correlation-chart/main.d.ts +1 -1
- package/dist/correlation-chart/main.js +11 -3
- package/dist/correlation-chart/main.js.map +1 -1
- package/dist/data-provider/store.cjs +34 -1
- package/dist/data-provider/store.cjs.map +1 -1
- package/dist/data-provider/store.d.ts +5 -0
- package/dist/data-provider/store.js +35 -2
- package/dist/data-provider/store.js.map +1 -1
- package/dist/index.cjs +57 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +57 -3
- package/dist/index.js.map +1 -1
- package/dist/notes.cjs +11 -2
- package/dist/notes.cjs.map +1 -1
- package/dist/notes.d.ts +11 -1
- package/dist/notes.js +11 -2
- package/dist/notes.js.map +1 -1
- package/dist/prepare-units/composite-scale.cjs +18 -16
- package/dist/prepare-units/composite-scale.cjs.map +1 -1
- package/dist/prepare-units/composite-scale.js +18 -16
- package/dist/prepare-units/composite-scale.js.map +1 -1
- package/dist/prepare-units/density.cjs +83 -0
- package/dist/prepare-units/density.cjs.map +1 -0
- package/dist/prepare-units/density.d.ts +92 -0
- package/dist/prepare-units/density.js +83 -0
- package/dist/prepare-units/density.js.map +1 -0
- package/dist/prepare-units/index.cjs +15 -7
- package/dist/prepare-units/index.cjs.map +1 -1
- package/dist/prepare-units/index.d.ts +1 -0
- package/dist/prepare-units/index.js +15 -7
- package/dist/prepare-units/index.js.map +1 -1
- package/dist/prepare-units/types.cjs.map +1 -1
- package/dist/prepare-units/types.d.ts +34 -13
- package/dist/prepare-units/types.js.map +1 -1
- package/dist/section.cjs +108 -24
- package/dist/section.cjs.map +1 -1
- package/dist/section.d.ts +66 -6
- package/dist/section.js +109 -25
- package/dist/section.js.map +1 -1
- package/dist/timescale-zoom.cjs +191 -0
- package/dist/timescale-zoom.cjs.map +1 -0
- package/dist/timescale-zoom.d.ts +74 -0
- package/dist/timescale-zoom.js +191 -0
- package/dist/timescale-zoom.js.map +1 -0
- package/dist/unit-details/age-range.cjs +1 -0
- package/dist/unit-details/age-range.cjs.map +1 -1
- package/dist/unit-details/age-range.d.ts +5 -1
- package/dist/unit-details/age-range.js +1 -0
- package/dist/unit-details/age-range.js.map +1 -1
- package/dist/unit-details/age-window-tag.cjs +68 -0
- package/dist/unit-details/age-window-tag.cjs.map +1 -0
- package/dist/unit-details/age-window-tag.d.ts +26 -0
- package/dist/unit-details/age-window-tag.js +66 -0
- package/dist/unit-details/age-window-tag.js.map +1 -0
- package/dist/{age-model-overlay.module.sass.cjs → unit-details/age-window-tag.module.sass.cjs} +3 -3
- package/dist/unit-details/age-window-tag.module.sass.cjs.map +1 -0
- package/dist/unit-details/age-window-tag.module.sass.js +11 -0
- package/dist/unit-details/age-window-tag.module.sass.js.map +1 -0
- package/dist/unit-details/index.d.ts +1 -0
- package/dist/units/composite.cjs +4 -1
- package/dist/units/composite.cjs.map +1 -1
- package/dist/units/composite.d.ts +2 -0
- package/dist/units/composite.js +4 -1
- package/dist/units/composite.js.map +1 -1
- package/package.json +7 -7
- package/src/age-model/data.ts +98 -0
- package/src/age-model/details.module.sass +108 -0
- package/src/age-model/details.ts +333 -0
- package/src/age-model/index.ts +5 -0
- package/src/age-model/legacy.ts +30 -0
- package/src/age-model/surfaces.module.sass +168 -0
- package/src/age-model/surfaces.ts +568 -0
- package/src/age-model/types.ts +392 -0
- package/src/column.module.sass +59 -8
- package/src/column.ts +49 -23
- package/src/correlation-chart/main.ts +14 -2
- package/src/data-provider/store.ts +50 -1
- package/src/index.ts +5 -1
- package/src/notes.ts +20 -2
- package/src/prepare-units/composite-scale.ts +34 -31
- package/src/prepare-units/density.ts +197 -0
- package/src/prepare-units/index.ts +25 -6
- package/src/prepare-units/types.ts +34 -13
- package/src/section.ts +219 -33
- package/src/timescale-zoom.ts +341 -0
- package/src/unit-details/age-range.ts +3 -3
- package/src/unit-details/age-window-tag.module.sass +10 -0
- package/src/unit-details/age-window-tag.ts +102 -0
- package/src/unit-details/index.ts +1 -0
- package/src/units/composite.ts +11 -0
- package/dist/age-model-overlay.cjs +0 -50
- package/dist/age-model-overlay.cjs.map +0 -1
- package/dist/age-model-overlay.d.ts +0 -24
- package/dist/age-model-overlay.js +0 -48
- package/dist/age-model-overlay.js.map +0 -1
- package/dist/age-model-overlay.module.sass.cjs.map +0 -1
- package/dist/age-model-overlay.module.sass.js +0 -11
- package/dist/age-model-overlay.module.sass.js.map +0 -1
- package/src/age-model-overlay.module.sass +0 -11
- package/src/age-model-overlay.ts +0 -96
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { useState, useMemo, useCallback } from "react";
|
|
2
|
+
import { useAnimatedAgeWindow } from "./animated-age-window.js";
|
|
3
|
+
const MIN_TIMESCALE_LEVEL = 1;
|
|
4
|
+
const MAX_TIMESCALE_LEVEL = 5;
|
|
5
|
+
const LEVEL_WINDOW = 3;
|
|
6
|
+
const DEFAULT_LEVEL = 3;
|
|
7
|
+
const SELECTED_INTERVAL_STYLE = { fontWeight: "bold" };
|
|
8
|
+
function useTimescaleZoom(options) {
|
|
9
|
+
const {
|
|
10
|
+
fullExtent,
|
|
11
|
+
enabled = true,
|
|
12
|
+
levelWindow = LEVEL_WINDOW,
|
|
13
|
+
defaultLevel = DEFAULT_LEVEL,
|
|
14
|
+
minLevel = MIN_TIMESCALE_LEVEL,
|
|
15
|
+
maxLevel = MAX_TIMESCALE_LEVEL,
|
|
16
|
+
duration,
|
|
17
|
+
selectedIntervalStyle = SELECTED_INTERVAL_STYLE
|
|
18
|
+
} = options;
|
|
19
|
+
const anim = useAnimatedAgeWindow({ fullExtent, duration });
|
|
20
|
+
const [intervals, setIntervals] = useState([]);
|
|
21
|
+
const [addedIntervals, setAddedIntervals] = useState([]);
|
|
22
|
+
const [selectedTimescaleID, setSelectedTimescaleID] = useState(
|
|
23
|
+
null
|
|
24
|
+
);
|
|
25
|
+
const selectedInterval = intervals[intervals.length - 1] ?? null;
|
|
26
|
+
const selectedIntervals = useMemo(() => {
|
|
27
|
+
if (selectedInterval == null) return addedIntervals;
|
|
28
|
+
return [selectedInterval, ...addedIntervals];
|
|
29
|
+
}, [selectedInterval, addedIntervals]);
|
|
30
|
+
const reset = useCallback(() => {
|
|
31
|
+
setIntervals([]);
|
|
32
|
+
setAddedIntervals([]);
|
|
33
|
+
setSelectedTimescaleID(null);
|
|
34
|
+
anim.reset();
|
|
35
|
+
}, [anim.reset]);
|
|
36
|
+
const extendToInterval = useCallback(
|
|
37
|
+
(interval) => {
|
|
38
|
+
let added = addedIntervals.filter((d) => d.oid !== interval.oid);
|
|
39
|
+
const wasSelected = added.length !== addedIntervals.length;
|
|
40
|
+
if (!wasSelected && interval.oid !== selectedInterval?.oid) {
|
|
41
|
+
added = [...addedIntervals, interval];
|
|
42
|
+
}
|
|
43
|
+
setAddedIntervals(added);
|
|
44
|
+
let selection = added;
|
|
45
|
+
if (selectedInterval != null) {
|
|
46
|
+
selection = [selectedInterval, ...added];
|
|
47
|
+
}
|
|
48
|
+
if (selection.length === 0) {
|
|
49
|
+
anim.reset();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
anim.zoomToWindow(intervalsWindow(selection));
|
|
53
|
+
},
|
|
54
|
+
[addedIntervals, selectedInterval, anim.zoomToWindow, anim.reset]
|
|
55
|
+
);
|
|
56
|
+
const zoomToInterval = useCallback(
|
|
57
|
+
(interval, timescaleID = null) => {
|
|
58
|
+
const containing = intervals.filter(
|
|
59
|
+
(d) => d.lvl < interval.lvl && d.eag >= interval.eag && d.lag <= interval.lag
|
|
60
|
+
);
|
|
61
|
+
setIntervals([...containing, interval]);
|
|
62
|
+
setAddedIntervals([]);
|
|
63
|
+
setSelectedTimescaleID(timescaleID);
|
|
64
|
+
anim.zoomToInterval(interval);
|
|
65
|
+
},
|
|
66
|
+
[intervals, anim.zoomToInterval]
|
|
67
|
+
);
|
|
68
|
+
const onClickTimescaleInterval = useCallback(
|
|
69
|
+
(event, data) => {
|
|
70
|
+
const interval = data?.interval;
|
|
71
|
+
if (interval == null || interval.lvl == null) return;
|
|
72
|
+
const timescaleID = data.timescaleID ?? null;
|
|
73
|
+
if (event?.shiftKey) {
|
|
74
|
+
extendToInterval(interval);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (interval.oid === selectedInterval?.oid && addedIntervals.length === 0) {
|
|
78
|
+
const next = intervals.slice(0, -1);
|
|
79
|
+
setIntervals(next);
|
|
80
|
+
setSelectedTimescaleID(null);
|
|
81
|
+
const parent = next[next.length - 1] ?? null;
|
|
82
|
+
if (parent == null) {
|
|
83
|
+
anim.reset();
|
|
84
|
+
} else {
|
|
85
|
+
anim.zoomToInterval(parent);
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
zoomToInterval(interval, timescaleID);
|
|
90
|
+
},
|
|
91
|
+
[
|
|
92
|
+
intervals,
|
|
93
|
+
selectedInterval,
|
|
94
|
+
selectedTimescaleID,
|
|
95
|
+
addedIntervals,
|
|
96
|
+
extendToInterval,
|
|
97
|
+
zoomToInterval,
|
|
98
|
+
anim.reset
|
|
99
|
+
]
|
|
100
|
+
);
|
|
101
|
+
const timescaleIntervalStyle = useCallback(
|
|
102
|
+
(interval) => {
|
|
103
|
+
if (selectedIntervals.some((d) => d.oid === interval.oid)) {
|
|
104
|
+
return selectedIntervalStyle;
|
|
105
|
+
}
|
|
106
|
+
return {};
|
|
107
|
+
},
|
|
108
|
+
[selectedIntervals, selectedIntervalStyle]
|
|
109
|
+
);
|
|
110
|
+
const levels = useMemo(() => {
|
|
111
|
+
let level = defaultLevel;
|
|
112
|
+
for (const interval of selectedIntervals) {
|
|
113
|
+
if (interval.lvl != null) level = Math.max(level, interval.lvl);
|
|
114
|
+
}
|
|
115
|
+
return levelsForSelected(level, { levelWindow, minLevel, maxLevel });
|
|
116
|
+
}, [selectedIntervals, defaultLevel, levelWindow, minLevel, maxLevel]);
|
|
117
|
+
if (!enabled) {
|
|
118
|
+
return {
|
|
119
|
+
...disabledZoom,
|
|
120
|
+
selectedTimescaleID: null,
|
|
121
|
+
selectedIntervals: [],
|
|
122
|
+
timescaleLevels: levels,
|
|
123
|
+
reset,
|
|
124
|
+
zoomToInterval,
|
|
125
|
+
onClickTimescaleInterval,
|
|
126
|
+
timescaleIntervalStyle
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const window = anim.window ?? fullExtent;
|
|
130
|
+
return {
|
|
131
|
+
enabled: true,
|
|
132
|
+
window,
|
|
133
|
+
intervals,
|
|
134
|
+
selectedInterval,
|
|
135
|
+
selectedTimescaleID,
|
|
136
|
+
selectedIntervals,
|
|
137
|
+
timescaleLevels: levels,
|
|
138
|
+
isFullExtent: anim.isFullExtent,
|
|
139
|
+
isAnimating: anim.isAnimating,
|
|
140
|
+
reset,
|
|
141
|
+
zoomToInterval,
|
|
142
|
+
onClickTimescaleInterval,
|
|
143
|
+
timescaleIntervalStyle,
|
|
144
|
+
columnProps: {
|
|
145
|
+
showTimescale: true,
|
|
146
|
+
timescaleLevels: levels,
|
|
147
|
+
timescaleIntervalStyle,
|
|
148
|
+
onClickTimescaleInterval,
|
|
149
|
+
t_age: window?.t_age,
|
|
150
|
+
b_age: window?.b_age,
|
|
151
|
+
isTransitioning: anim.isAnimating
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const disabledZoom = {
|
|
156
|
+
enabled: false,
|
|
157
|
+
window: null,
|
|
158
|
+
intervals: [],
|
|
159
|
+
selectedInterval: null,
|
|
160
|
+
isFullExtent: true,
|
|
161
|
+
isAnimating: false,
|
|
162
|
+
columnProps: {}
|
|
163
|
+
};
|
|
164
|
+
function levelsForSelected(selectedLevel, options) {
|
|
165
|
+
const { levelWindow, minLevel, maxLevel } = options;
|
|
166
|
+
const span = Math.max(levelWindow - 1, 0);
|
|
167
|
+
const lo = Math.min(
|
|
168
|
+
Math.max(selectedLevel - 1, minLevel),
|
|
169
|
+
Math.max(maxLevel - span, minLevel)
|
|
170
|
+
);
|
|
171
|
+
return [lo, lo + span];
|
|
172
|
+
}
|
|
173
|
+
function intervalsWindow(intervals) {
|
|
174
|
+
return {
|
|
175
|
+
t_age: Math.min(...intervals.map((d) => d.lag)),
|
|
176
|
+
b_age: Math.max(...intervals.map((d) => d.eag))
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function unitsAgeExtent(units) {
|
|
180
|
+
if (units == null || units.length === 0) return null;
|
|
181
|
+
return {
|
|
182
|
+
t_age: Math.min(...units.map((d) => d.t_age)),
|
|
183
|
+
b_age: Math.max(...units.map((d) => d.b_age))
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
export {
|
|
187
|
+
levelsForSelected,
|
|
188
|
+
unitsAgeExtent,
|
|
189
|
+
useTimescaleZoom
|
|
190
|
+
};
|
|
191
|
+
//# sourceMappingURL=timescale-zoom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timescale-zoom.js","sources":["../src/timescale-zoom.ts"],"sourcesContent":["/** Click-to-zoom navigation over geologic time.\n *\n * `useTimescaleZoom` turns clicks on a column's timescale into an animated\n * age window: clicking an interval zooms to it, clicking the interval you are\n * already in zooms back out a level, and the timescale shows a sliding window\n * of levels that follows the selection, so finer intervals come into reach as\n * you drill. The result spreads straight onto a `Column`.\n */\nimport { type CSSProperties, useCallback, useMemo, useState } from \"react\";\nimport type {\n Interval,\n IntervalStyleBuilder,\n TimescaleClickData,\n TimescaleClickHandler,\n} from \"@macrostrat/timescale\";\nimport { type AgeWindow, useAnimatedAgeWindow } from \"./animated-age-window\";\n\n/** Coarsest level worth showing; level 0 is \"all of geologic time\" */\nconst MIN_TIMESCALE_LEVEL = 1;\n/** Deepest level in the timescale (age/stage) */\nconst MAX_TIMESCALE_LEVEL = 5;\n/** How many levels are shown at once */\nconst LEVEL_WINDOW = 3;\n/** The level anchored on before an interval is picked. 3 (period) puts the\n * starting window at era–epoch, the levels a `Column` shows by default. */\nconst DEFAULT_LEVEL = 3;\n\nconst SELECTED_INTERVAL_STYLE: CSSProperties = { fontWeight: \"bold\" };\n\nexport interface UseTimescaleZoomOptions {\n /** The full data extent — the window zooming returns to. `null` until the\n * data (and hence the extent) is known. */\n fullExtent: AgeWindow | null;\n /** When false the hook reports no window and no column props, so a view can\n * offer zooming as an option without changing hook order (default `true`). */\n enabled?: boolean;\n /** How many timescale levels to show at once (default 3) */\n levelWindow?: number;\n /** The level to anchor the window on before an interval is picked\n * (default 3, period) */\n defaultLevel?: number;\n minLevel?: number;\n maxLevel?: number;\n /** Animation duration in ms */\n duration?: number;\n /** Style for the selected interval — the one whose click zooms out\n * (default bold) */\n selectedIntervalStyle?: CSSProperties;\n}\n\n/** Timescale and age-window props, ready to spread onto a `Column`. */\nexport interface TimescaleZoomColumnProps {\n showTimescale?: boolean;\n timescaleLevels?: [number, number];\n timescaleIntervalStyle?: IntervalStyleBuilder;\n onClickTimescaleInterval?: TimescaleClickHandler;\n t_age?: number;\n b_age?: number;\n isTransitioning?: boolean;\n}\n\nexport interface TimescaleZoom {\n enabled: boolean;\n /** The rendered age window — `null` when disabled or before the extent is\n * known */\n window: AgeWindow | null;\n /** The drill path: coarse to fine, the last entry being the selection */\n intervals: Interval[];\n selectedInterval: Interval | null;\n /** The timescale the selection was made in, when the click said so */\n selectedTimescaleID: number | null;\n /** Every interval in the selection: the one drilled to, plus any added by\n * shift-clicking. The window spans all of them. */\n selectedIntervals: Interval[];\n /** The levels the timescale should show, following the selection */\n timescaleLevels: [number, number];\n isFullExtent: boolean;\n isAnimating: boolean;\n /** Return to the full extent, clearing the drill path */\n reset(): void;\n zoomToInterval(interval: Interval): void;\n onClickTimescaleInterval: TimescaleClickHandler;\n timescaleIntervalStyle: (interval: Interval) => CSSProperties;\n columnProps: TimescaleZoomColumnProps;\n}\n\nexport function useTimescaleZoom(\n options: UseTimescaleZoomOptions,\n): TimescaleZoom {\n const {\n fullExtent,\n enabled = true,\n levelWindow = LEVEL_WINDOW,\n defaultLevel = DEFAULT_LEVEL,\n minLevel = MIN_TIMESCALE_LEVEL,\n maxLevel = MAX_TIMESCALE_LEVEL,\n duration,\n selectedIntervalStyle = SELECTED_INTERVAL_STYLE,\n } = options;\n\n const anim = useAnimatedAgeWindow({ fullExtent, duration });\n\n // The intervals drilled through; the last one is the current selection\n const [intervals, setIntervals] = useState<Interval[]>([]);\n // Intervals shift-clicked into the selection alongside it\n const [addedIntervals, setAddedIntervals] = useState<Interval[]>([]);\n // Which timescale the selection was made in. The same interval is drawn in\n // every timescale that contains it, and those copies are not the same\n // selection: clicking one in another column moves the selection there.\n const [selectedTimescaleID, setSelectedTimescaleID] = useState<number | null>(\n null,\n );\n const selectedInterval = intervals[intervals.length - 1] ?? null;\n\n const selectedIntervals = useMemo(() => {\n if (selectedInterval == null) return addedIntervals;\n return [selectedInterval, ...addedIntervals];\n }, [selectedInterval, addedIntervals]);\n\n const reset = useCallback(() => {\n setIntervals([]);\n setAddedIntervals([]);\n setSelectedTimescaleID(null);\n anim.reset();\n }, [anim.reset]);\n\n /** Take the interval clicked into (or out of) the selection, and span the\n * result — how you widen a window to the interval next door. */\n const extendToInterval = useCallback(\n (interval: Interval) => {\n let added = addedIntervals.filter((d) => d.oid !== interval.oid);\n const wasSelected = added.length !== addedIntervals.length;\n if (!wasSelected && interval.oid !== selectedInterval?.oid) {\n added = [...addedIntervals, interval];\n }\n setAddedIntervals(added);\n\n let selection = added;\n if (selectedInterval != null) {\n selection = [selectedInterval, ...added];\n }\n if (selection.length === 0) {\n anim.reset();\n return;\n }\n anim.zoomToWindow(intervalsWindow(selection));\n },\n [addedIntervals, selectedInterval, anim.zoomToWindow, anim.reset],\n );\n\n const zoomToInterval = useCallback(\n (interval: Interval, timescaleID: number | null = null) => {\n // Keep only the coarser intervals that actually contain this one, so\n // stepping sideways into a different parent (the last stage of the\n // Cambrian → the first of the Ordovician) doesn't strand the old one\n const containing = intervals.filter(\n (d) =>\n d.lvl < interval.lvl &&\n d.eag >= interval.eag &&\n d.lag <= interval.lag,\n );\n setIntervals([...containing, interval]);\n setAddedIntervals([]);\n setSelectedTimescaleID(timescaleID);\n anim.zoomToInterval(interval);\n },\n [intervals, anim.zoomToInterval],\n );\n\n const onClickTimescaleInterval = useCallback<TimescaleClickHandler>(\n (event: Event, data: TimescaleClickData & { timescaleID?: number }) => {\n const interval = data?.interval;\n if (interval == null || interval.lvl == null) return;\n\n const timescaleID = data.timescaleID ?? null;\n // A click in a different timescale is a different selection, even on the\n // same interval: it moves to that column rather than zooming back out\n const sameTimescale =\n timescaleID == null ||\n selectedTimescaleID == null ||\n timescaleID === selectedTimescaleID;\n\n // Shift-click widens the window instead of moving it, so a selection can\n // grow into the interval next door\n if ((event as MouseEvent)?.shiftKey) {\n extendToInterval(interval);\n return;\n }\n\n // Clicking the interval you are in is the way back out: pop a level, or\n // return to the full extent past the root\n if (interval.oid === selectedInterval?.oid && addedIntervals.length === 0) {\n const next = intervals.slice(0, -1);\n setIntervals(next);\n setSelectedTimescaleID(null);\n const parent = next[next.length - 1] ?? null;\n if (parent == null) {\n anim.reset();\n } else {\n anim.zoomToInterval(parent);\n }\n return;\n }\n\n // Every other click navigates *to* the interval clicked, whatever its\n // rank: a finer one drills in, a neighbor moves along the timescale, a\n // coarser one zooms out to it\n zoomToInterval(interval, timescaleID);\n },\n [\n intervals,\n selectedInterval,\n selectedTimescaleID,\n addedIntervals,\n extendToInterval,\n zoomToInterval,\n anim.reset,\n ],\n );\n\n const timescaleIntervalStyle = useCallback(\n (interval: Interval): CSSProperties => {\n if (selectedIntervals.some((d) => d.oid === interval.oid)) {\n return selectedIntervalStyle;\n }\n return {};\n },\n [selectedIntervals, selectedIntervalStyle],\n );\n\n const levels = useMemo(() => {\n let level = defaultLevel;\n for (const interval of selectedIntervals) {\n if (interval.lvl != null) level = Math.max(level, interval.lvl);\n }\n return levelsForSelected(level, { levelWindow, minLevel, maxLevel });\n }, [selectedIntervals, defaultLevel, levelWindow, minLevel, maxLevel]);\n\n if (!enabled) {\n return {\n ...disabledZoom,\n selectedTimescaleID: null,\n selectedIntervals: [],\n timescaleLevels: levels,\n reset,\n zoomToInterval,\n onClickTimescaleInterval,\n timescaleIntervalStyle,\n };\n }\n\n const window = anim.window ?? fullExtent;\n\n return {\n enabled: true,\n window,\n intervals,\n selectedInterval,\n selectedTimescaleID,\n selectedIntervals,\n timescaleLevels: levels,\n isFullExtent: anim.isFullExtent,\n isAnimating: anim.isAnimating,\n reset,\n zoomToInterval,\n onClickTimescaleInterval,\n timescaleIntervalStyle,\n columnProps: {\n showTimescale: true,\n timescaleLevels: levels,\n timescaleIntervalStyle,\n onClickTimescaleInterval,\n t_age: window?.t_age,\n b_age: window?.b_age,\n isTransitioning: anim.isAnimating,\n },\n };\n}\n\n/** What the hook reports when zooming is switched off: no window, and no\n * props to change how the column renders. */\nconst disabledZoom: Pick<\n TimescaleZoom,\n | \"enabled\"\n | \"window\"\n | \"intervals\"\n | \"selectedInterval\"\n | \"isFullExtent\"\n | \"isAnimating\"\n | \"columnProps\"\n> = {\n enabled: false,\n window: null,\n intervals: [],\n selectedInterval: null,\n isFullExtent: true,\n isAnimating: false,\n columnProps: {},\n};\n\ninterface LevelWindowOptions {\n levelWindow: number;\n minLevel: number;\n maxLevel: number;\n}\n\n/** A fixed window of timescale levels that slides with the selected level —\n * one coarser for context, the rest finer to drill into. Clamped so the\n * useless level 0 is never shown. */\nexport function levelsForSelected(\n selectedLevel: number,\n options: LevelWindowOptions,\n): [number, number] {\n const { levelWindow, minLevel, maxLevel } = options;\n const span = Math.max(levelWindow - 1, 0);\n const lo = Math.min(\n Math.max(selectedLevel - 1, minLevel),\n Math.max(maxLevel - span, minLevel),\n );\n return [lo, lo + span];\n}\n\n/** The window spanning a set of intervals. */\nfunction intervalsWindow(intervals: Interval[]): AgeWindow {\n return {\n t_age: Math.min(...intervals.map((d) => d.lag)),\n b_age: Math.max(...intervals.map((d) => d.eag)),\n };\n}\n\n/** The age extent of a set of units, in the shape the age-window props take.\n * `null` for an empty or absent set. */\nexport function unitsAgeExtent(\n units: { t_age: number; b_age: number }[] | null | undefined,\n): AgeWindow | null {\n if (units == null || units.length === 0) return null;\n return {\n t_age: Math.min(...units.map((d) => d.t_age)),\n b_age: Math.max(...units.map((d) => d.b_age)),\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -191,6 +191,7 @@ exports.AgeLabel = AgeLabel;
|
|
|
191
191
|
exports.AgeRange = AgeRange;
|
|
192
192
|
exports.Duration = Duration;
|
|
193
193
|
exports.IntervalProportions = IntervalProportions;
|
|
194
|
+
exports.Proportion = Proportion;
|
|
194
195
|
exports.getAge = getAge;
|
|
195
196
|
exports.getAgeRange = getAgeRange;
|
|
196
197
|
//# sourceMappingURL=age-range.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"age-range.cjs","sources":["../../src/unit-details/age-range.ts"],"sourcesContent":["import {\n DataField,\n IntervalShort,\n IntervalTag,\n type IntervalTagProps,\n ItemList,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport h from \"./age-range.module.sass\";\nimport { formatProportion, formatRange } from \"./utils\";\nimport classNames from \"classnames\";\nimport { useMemo } from \"react\";\n\nexport function AgeField({ unit, children, ...rest }) {\n const [_b_age, _t_age, _unit] = getAgeRange(unit);\n\n return h(\n DataField,\n {\n label: \"Age\",\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n ...rest,\n },\n children,\n );\n}\n\nexport function AgeRange({\n data,\n className,\n}: {\n data: {\n t_age: number;\n b_age: number;\n };\n className?: string;\n}) {\n const [_b_age, _t_age, _unit] = getAgeRange(data);\n\n return h(Value, {\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n className,\n });\n}\n\nexport function AgeLabel({\n age,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n className,\n}: {\n age: number;\n className?: string;\n maximumFractionDigits?: number;\n minimumFractionDigits?: number;\n}) {\n /** Component to display a single age value with unit conversion from\n * Ma to ka or Ga as appropriate.\n */\n const [value, unit] = getAge(age);\n\n const _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit, className });\n}\n\nexport function Duration({\n value,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n}) {\n let unit = \"Myr\";\n if (value < 0.8) {\n unit = \"kyr\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Gyr\";\n value /= 1000;\n }\n\n let _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit });\n}\n\ninterface UnitIntervalConstraints {\n b_int_id?: number;\n t_int_id?: number;\n b_prop?: number;\n t_prop?: number;\n b_int_name?: string;\n t_int_name?: string;\n b_age?: number;\n t_age?: number;\n}\n\nexport interface IntervalProportionsProps extends Omit<\n IntervalTagProps,\n \"interval\"\n> {\n unit: UnitIntervalConstraints;\n showProportions?: boolean;\n calculateProportionsFromAges?: boolean;\n onClickItem?: any;\n}\n\nexport function IntervalProportions({\n unit,\n className,\n showProportions,\n calculateProportionsFromAges = true,\n ...rest\n}: IntervalProportionsProps) {\n /** Display the proportions of the unit that belong to the base and top intervals, if they are different */\n if (unit.b_int_id == null && unit.t_int_id == null) return null;\n\n let _showProps = showProportions;\n\n const i0 = unit.b_int_id;\n const i1 = unit.t_int_id;\n\n const ints = new Set([i0, i1]);\n\n /** Get interval information */\n const intervalMap = useMacrostratDefs(\"intervals\", Array.from(ints), null);\n const [int0, int1] = useMemo(() => {\n const int0 = intervalMap?.get(i0) ?? {};\n if (i0 === i1) {\n return [int0, int0];\n }\n const int1 = intervalMap?.get(i1) ?? {};\n return [int0, int1];\n }, [intervalMap, i0, i1]);\n\n const interval0: IntervalShort = {\n id: i0,\n name: unit.b_int_name,\n ...int0,\n };\n\n let b_prop = unit.b_prop;\n let t_prop = unit.t_prop;\n\n // If we have b_age and t_age, then we can calculate proportions if they are not given\n if (b_prop == null && unit.b_age != null && calculateProportionsFromAges) {\n b_prop = getProportion(unit.b_age, int0);\n }\n if (t_prop == null && unit.t_age != null && calculateProportionsFromAges) {\n t_prop = getProportion(unit.t_age, int1);\n }\n\n // If there are no proportions given and we are not explicitly directed to show them,\n // then we set them to hidden.\n if (b_prop == null && t_prop == null) {\n _showProps ??= false;\n }\n\n /*\n Set default proportions to 0 and 1 if they are not given,\n so that we can display \"base\" and \"top\" labels\n */\n b_prop ??= 0;\n t_prop ??= 1;\n\n let p0: any = null;\n let p1: any = null;\n\n if (_showProps !== false) {\n p1 = h(Proportion, { value: t_prop });\n\n if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {\n // We have a single interval with undefined proportions\n p0 = h(Proportion, { value: b_prop });\n }\n\n if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {\n p0 = h(\"span.joint-proportion\", [p0, \" \", h(\"span.sep\", \"to\"), \" \", p1]);\n }\n }\n\n return h(\n ItemList,\n { className: classNames(\"interval-proportions\", className) },\n [\n h(IntervalTag, {\n interval: interval0,\n prefix: p0,\n ...rest,\n }),\n h.if(i0 != i1)(\"span.discourage-break\", [\n h(\"span.sep\", \" to \"),\n h(IntervalTag, {\n interval: {\n id: i1,\n name: unit.t_int_name,\n ...int1,\n },\n prefix: p1,\n ...rest,\n }),\n ]),\n ],\n );\n}\n\nfunction getProportion(age: number, interval: IntervalShort): number | null {\n /** Get proportion with the age */\n return (interval.b_age - age) / (interval.b_age - interval.t_age);\n}\n\nfunction Proportion({ value }) {\n let content = null;\n if (value == 0) {\n content = \"base\";\n } else if (value == 1) {\n content = \"top\";\n } else {\n content = formatProportion(value * 100) + \"%\";\n }\n\n return h(\"span.proportion\", content);\n}\n\nexport function getAgeRange(_unit) {\n let b_age = _unit.b_age;\n let t_age = _unit.t_age;\n let unit = \"Ma\";\n\n if (b_age < 0.8 && t_age < 1.2) {\n b_age *= 1000;\n t_age *= 1000;\n unit = \"ka\";\n } else if (b_age > 800 && t_age > 1200) {\n b_age /= 1000;\n t_age /= 1000;\n unit = \"Ga\";\n }\n\n return [b_age, t_age, unit];\n}\n\nexport function getAge(value) {\n /** Get the age value in Ma, ka, or Ga as appropriate */\n let unit = \"Ma\";\n if (value < 0.8) {\n unit = \"ka\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Ga\";\n value /= 1000;\n }\n\n return [value, unit];\n}\n"],"names":["h","DataField","formatRange","Value","useMacrostratDefs","useMemo","int0","int1","ItemList","classNames","IntervalTag","formatProportion"],"mappings":";;;;;;;;;;AAcO,SAAS,SAAS,EAAE,MAAM,UAAU,GAAG,QAAQ;AACpD,QAAM,CAAC,QAAQ,QAAQ,KAAK,IAAI,YAAY,IAAI;AAEhD,SAAOA,gBAAAA;AAAAA,IACLC,eAAAA;AAAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,OAAOC,MAAAA,YAAY,QAAQ,MAAM;AAAA,MACjC,MAAM;AAAA,MACN,GAAG;AAAA,IAAA;AAAA,IAEL;AAAA,EAAA;AAEJ;AAEO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AACF,GAMG;AACD,QAAM,CAAC,QAAQ,QAAQ,KAAK,IAAI,YAAY,IAAI;AAEhD,SAAOF,gBAAAA,QAAEG,eAAAA,OAAO;AAAA,IACd,OAAOD,MAAAA,YAAY,QAAQ,MAAM;AAAA,IACjC,MAAM;AAAA,IACN;AAAA,EAAA,CACD;AACH;AAEO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA,wBAAwB;AAAA,EACxB,wBAAwB;AAAA,EACxB;AACF,GAKG;AAID,QAAM,CAAC,OAAO,IAAI,IAAI,OAAO,GAAG;AAEhC,QAAM,SAAS,MAAM,eAAe,SAAS;AAAA,IAC3C;AAAA,IACA;AAAA,EAAA,CACD;AAED,SAAOF,gBAAAA,QAAEG,eAAAA,OAAO,EAAE,OAAO,QAAQ,MAAM,WAAW;AACpD;AAEO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA,wBAAwB;AAAA,EACxB,wBAAwB;AAC1B,GAAG;AACD,MAAI,OAAO;AACX,MAAI,QAAQ,KAAK;AACf,WAAO;AACP,aAAS;AACT,QAAI,QAAQ,GAAG;AACb,aAAO;AACP,eAAS;AAAA,IACX;AAAA,EACF,WAAW,QAAQ,KAAM;AACvB,WAAO;AACP,aAAS;AAAA,EACX;AAEA,MAAI,SAAS,MAAM,eAAe,SAAS;AAAA,IACzC;AAAA,IACA;AAAA,EAAA,CACD;AAED,SAAOH,gBAAAA,QAAEG,eAAAA,OAAO,EAAE,OAAO,QAAQ,MAAM;AACzC;AAuBO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA,+BAA+B;AAAA,EAC/B,GAAG;AACL,GAA6B;AAE3B,MAAI,KAAK,YAAY,QAAQ,KAAK,YAAY,KAAM,QAAO;AAE3D,MAAI,aAAa;AAEjB,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,KAAK;AAEhB,QAAM,OAAO,oBAAI,IAAI,CAAC,IAAI,EAAE,CAAC;AAG7B,QAAM,cAAcC,aAAAA,kBAAkB,aAAa,MAAM,KAAK,IAAI,GAAG,IAAI;AACzE,QAAM,CAAC,MAAM,IAAI,IAAIC,MAAAA,QAAQ,MAAM;AACjC,UAAMC,QAAO,aAAa,IAAI,EAAE,KAAK,CAAA;AACrC,QAAI,OAAO,IAAI;AACb,aAAO,CAACA,OAAMA,KAAI;AAAA,IACpB;AACA,UAAMC,QAAO,aAAa,IAAI,EAAE,KAAK,CAAA;AACrC,WAAO,CAACD,OAAMC,KAAI;AAAA,EACpB,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;AAExB,QAAM,YAA2B;AAAA,IAC/B,IAAI;AAAA,IACJ,MAAM,KAAK;AAAA,IACX,GAAG;AAAA,EAAA;AAGL,MAAI,SAAS,KAAK;AAClB,MAAI,SAAS,KAAK;AAGlB,MAAI,UAAU,QAAQ,KAAK,SAAS,QAAQ,8BAA8B;AACxE,aAAS,cAAc,KAAK,OAAO,IAAI;AAAA,EACzC;AACA,MAAI,UAAU,QAAQ,KAAK,SAAS,QAAQ,8BAA8B;AACxE,aAAS,cAAc,KAAK,OAAO,IAAI;AAAA,EACzC;AAIA,MAAI,UAAU,QAAQ,UAAU,MAAM;AACpC,mBAAe;AAAA,EACjB;AAMA,aAAW;AACX,aAAW;AAEX,MAAI,KAAU;AACd,MAAI,KAAU;AAEd,MAAI,eAAe,OAAO;AACxB,SAAKP,gBAAAA,QAAE,YAAY,EAAE,OAAO,QAAQ;AAEpC,QAAI,OAAO,MAAM,WAAW,KAAK,WAAW,GAAG;AAE7C,WAAKA,gBAAAA,QAAE,YAAY,EAAE,OAAO,QAAQ;AAAA,IACtC;AAEA,QAAI,OAAO,OAAO,WAAW,KAAK,WAAW,IAAI;AAC/C,WAAKA,gBAAAA,QAAE,yBAAyB,CAAC,IAAI,KAAKA,wBAAE,YAAY,IAAI,GAAG,KAAK,EAAE,CAAC;AAAA,IACzE;AAAA,EACF;AAEA,SAAOA,gBAAAA;AAAAA,IACLQ,eAAAA;AAAAA,IACA,EAAE,WAAWC,oBAAAA,QAAW,wBAAwB,SAAS,EAAA;AAAA,IACzD;AAAA,MACET,gBAAAA,QAAEU,eAAAA,aAAa;AAAA,QACb,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,GAAG;AAAA,MAAA,CACJ;AAAA,MACDV,gBAAAA,QAAE,GAAG,MAAM,EAAE,EAAE,yBAAyB;AAAA,QACtCA,gBAAAA,QAAE,YAAY,MAAM;AAAA,QACpBA,gBAAAA,QAAEU,eAAAA,aAAa;AAAA,UACb,UAAU;AAAA,YACR,IAAI;AAAA,YACJ,MAAM,KAAK;AAAA,YACX,GAAG;AAAA,UAAA;AAAA,UAEL,QAAQ;AAAA,UACR,GAAG;AAAA,QAAA,CACJ;AAAA,MAAA,CACF;AAAA,IAAA;AAAA,EACH;AAEJ;AAEA,SAAS,cAAc,KAAa,UAAwC;AAE1E,UAAQ,SAAS,QAAQ,QAAQ,SAAS,QAAQ,SAAS;AAC7D;AAEA,SAAS,WAAW,EAAE,SAAS;AAC7B,MAAI,UAAU;AACd,MAAI,SAAS,GAAG;AACd,cAAU;AAAA,EACZ,WAAW,SAAS,GAAG;AACrB,cAAU;AAAA,EACZ,OAAO;AACL,cAAUC,MAAAA,iBAAiB,QAAQ,GAAG,IAAI;AAAA,EAC5C;AAEA,SAAOX,gBAAAA,QAAE,mBAAmB,OAAO;AACrC;AAEO,SAAS,YAAY,OAAO;AACjC,MAAI,QAAQ,MAAM;AAClB,MAAI,QAAQ,MAAM;AAClB,MAAI,OAAO;AAEX,MAAI,QAAQ,OAAO,QAAQ,KAAK;AAC9B,aAAS;AACT,aAAS;AACT,WAAO;AAAA,EACT,WAAW,QAAQ,OAAO,QAAQ,MAAM;AACtC,aAAS;AACT,aAAS;AACT,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,OAAO,OAAO,IAAI;AAC5B;AAEO,SAAS,OAAO,OAAO;AAE5B,MAAI,OAAO;AACX,MAAI,QAAQ,KAAK;AACf,WAAO;AACP,aAAS;AACT,QAAI,QAAQ,GAAG;AACb,aAAO;AACP,eAAS;AAAA,IACX;AAAA,EACF,WAAW,QAAQ,KAAM;AACvB,WAAO;AACP,aAAS;AAAA,EACX;AAEA,SAAO,CAAC,OAAO,IAAI;AACrB;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"age-range.cjs","sources":["../../src/unit-details/age-range.ts"],"sourcesContent":["import {\n DataField,\n IntervalShort,\n IntervalTag,\n type IntervalTagProps,\n ItemList,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport h from \"./age-range.module.sass\";\nimport { formatProportion, formatRange } from \"./utils\";\nimport classNames from \"classnames\";\nimport { ReactNode, useMemo } from \"react\";\n\nexport function AgeField({ unit, children, ...rest }) {\n const [_b_age, _t_age, _unit] = getAgeRange(unit);\n\n return h(\n DataField,\n {\n label: \"Age\",\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n ...rest,\n },\n children,\n );\n}\n\nexport function AgeRange({\n data,\n className,\n}: {\n data: {\n t_age: number;\n b_age: number;\n };\n className?: string;\n}) {\n const [_b_age, _t_age, _unit] = getAgeRange(data);\n\n return h(Value, {\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n className,\n });\n}\n\nexport function AgeLabel({\n age,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n className,\n}: {\n age: number;\n className?: string;\n maximumFractionDigits?: number;\n minimumFractionDigits?: number;\n}) {\n /** Component to display a single age value with unit conversion from\n * Ma to ka or Ga as appropriate.\n */\n const [value, unit] = getAge(age);\n\n const _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit, className });\n}\n\nexport function Duration({\n value,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n}) {\n let unit = \"Myr\";\n if (value < 0.8) {\n unit = \"kyr\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Gyr\";\n value /= 1000;\n }\n\n let _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit });\n}\n\ninterface UnitIntervalConstraints {\n b_int_id?: number;\n t_int_id?: number;\n b_prop?: number;\n t_prop?: number;\n b_int_name?: string;\n t_int_name?: string;\n b_age?: number;\n t_age?: number;\n}\n\nexport interface IntervalProportionsProps extends Omit<\n IntervalTagProps,\n \"interval\"\n> {\n unit: UnitIntervalConstraints;\n showProportions?: boolean;\n calculateProportionsFromAges?: boolean;\n onClickItem?: any;\n}\n\nexport function IntervalProportions({\n unit,\n className,\n showProportions,\n calculateProportionsFromAges = true,\n ...rest\n}: IntervalProportionsProps) {\n /** Display the proportions of the unit that belong to the base and top intervals, if they are different */\n if (unit.b_int_id == null && unit.t_int_id == null) return null;\n\n let _showProps = showProportions;\n\n const i0 = unit.b_int_id;\n const i1 = unit.t_int_id;\n\n const ints = new Set([i0, i1]);\n\n /** Get interval information */\n const intervalMap = useMacrostratDefs(\"intervals\", Array.from(ints), null);\n const [int0, int1] = useMemo(() => {\n const int0 = intervalMap?.get(i0) ?? {};\n if (i0 === i1) {\n return [int0, int0];\n }\n const int1 = intervalMap?.get(i1) ?? {};\n return [int0, int1];\n }, [intervalMap, i0, i1]);\n\n const interval0: IntervalShort = {\n id: i0,\n name: unit.b_int_name,\n ...int0,\n };\n\n let b_prop = unit.b_prop;\n let t_prop = unit.t_prop;\n\n // If we have b_age and t_age, then we can calculate proportions if they are not given\n if (b_prop == null && unit.b_age != null && calculateProportionsFromAges) {\n b_prop = getProportion(unit.b_age, int0);\n }\n if (t_prop == null && unit.t_age != null && calculateProportionsFromAges) {\n t_prop = getProportion(unit.t_age, int1);\n }\n\n // If there are no proportions given and we are not explicitly directed to show them,\n // then we set them to hidden.\n if (b_prop == null && t_prop == null) {\n _showProps ??= false;\n }\n\n /*\n Set default proportions to 0 and 1 if they are not given,\n so that we can display \"base\" and \"top\" labels\n */\n b_prop ??= 0;\n t_prop ??= 1;\n\n let p0: any = null;\n let p1: any = null;\n\n if (_showProps !== false) {\n p1 = h(Proportion, { value: t_prop });\n\n if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {\n // We have a single interval with undefined proportions\n p0 = h(Proportion, { value: b_prop });\n }\n\n if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {\n p0 = h(\"span.joint-proportion\", [p0, \" \", h(\"span.sep\", \"to\"), \" \", p1]);\n }\n }\n\n return h(\n ItemList,\n { className: classNames(\"interval-proportions\", className) },\n [\n h(IntervalTag, {\n interval: interval0,\n prefix: p0,\n ...rest,\n }),\n h.if(i0 != i1)(\"span.discourage-break\", [\n h(\"span.sep\", \" to \"),\n h(IntervalTag, {\n interval: {\n id: i1,\n name: unit.t_int_name,\n ...int1,\n },\n prefix: p1,\n ...rest,\n }),\n ]),\n ],\n );\n}\n\nfunction getProportion(age: number, interval: IntervalShort): number | null {\n /** Get proportion with the age */\n return (interval.b_age - age) / (interval.b_age - interval.t_age);\n}\n\nexport function Proportion({ value }: { value: number }) {\n let content: ReactNode | null = null;\n if (value == 0) {\n content = \"base\";\n } else if (value == 1) {\n content = \"top\";\n } else {\n content = formatProportion(value * 100) + \"%\";\n }\n\n return h(\"span.proportion\", content);\n}\n\nexport function getAgeRange(_unit) {\n let b_age = _unit.b_age;\n let t_age = _unit.t_age;\n let unit = \"Ma\";\n\n if (b_age < 0.8 && t_age < 1.2) {\n b_age *= 1000;\n t_age *= 1000;\n unit = \"ka\";\n } else if (b_age > 800 && t_age > 1200) {\n b_age /= 1000;\n t_age /= 1000;\n unit = \"Ga\";\n }\n\n return [b_age, t_age, unit];\n}\n\nexport function getAge(value) {\n /** Get the age value in Ma, ka, or Ga as appropriate */\n let unit = \"Ma\";\n if (value < 0.8) {\n unit = \"ka\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Ga\";\n value /= 1000;\n }\n\n return [value, unit];\n}\n"],"names":["h","DataField","formatRange","Value","useMacrostratDefs","useMemo","int0","int1","ItemList","classNames","IntervalTag","formatProportion"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IntervalTagProps } from '@macrostrat/data-components';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
export declare function AgeField({ unit, children, ...rest }: {
|
|
3
4
|
[x: string]: any;
|
|
4
5
|
unit: any;
|
|
@@ -63,9 +64,12 @@ export interface IntervalProportionsProps extends Omit<IntervalTagProps, "interv
|
|
|
63
64
|
onClickItem?: any;
|
|
64
65
|
}
|
|
65
66
|
export declare function IntervalProportions({ unit, className, showProportions, calculateProportionsFromAges, ...rest }: IntervalProportionsProps): import('react').FunctionComponentElement<{
|
|
66
|
-
children?:
|
|
67
|
+
children?: ReactNode;
|
|
67
68
|
className: string;
|
|
68
69
|
}> | null;
|
|
70
|
+
export declare function Proportion({ value }: {
|
|
71
|
+
value: number;
|
|
72
|
+
}): import('react').DOMElement<import('react').DOMAttributes<Element>, Element>;
|
|
69
73
|
export declare function getAgeRange(_unit: any): any[];
|
|
70
74
|
export declare function getAge(value: any): any[];
|
|
71
75
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"age-range.js","sources":["../../src/unit-details/age-range.ts"],"sourcesContent":["import {\n DataField,\n IntervalShort,\n IntervalTag,\n type IntervalTagProps,\n ItemList,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport h from \"./age-range.module.sass\";\nimport { formatProportion, formatRange } from \"./utils\";\nimport classNames from \"classnames\";\nimport { useMemo } from \"react\";\n\nexport function AgeField({ unit, children, ...rest }) {\n const [_b_age, _t_age, _unit] = getAgeRange(unit);\n\n return h(\n DataField,\n {\n label: \"Age\",\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n ...rest,\n },\n children,\n );\n}\n\nexport function AgeRange({\n data,\n className,\n}: {\n data: {\n t_age: number;\n b_age: number;\n };\n className?: string;\n}) {\n const [_b_age, _t_age, _unit] = getAgeRange(data);\n\n return h(Value, {\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n className,\n });\n}\n\nexport function AgeLabel({\n age,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n className,\n}: {\n age: number;\n className?: string;\n maximumFractionDigits?: number;\n minimumFractionDigits?: number;\n}) {\n /** Component to display a single age value with unit conversion from\n * Ma to ka or Ga as appropriate.\n */\n const [value, unit] = getAge(age);\n\n const _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit, className });\n}\n\nexport function Duration({\n value,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n}) {\n let unit = \"Myr\";\n if (value < 0.8) {\n unit = \"kyr\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Gyr\";\n value /= 1000;\n }\n\n let _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit });\n}\n\ninterface UnitIntervalConstraints {\n b_int_id?: number;\n t_int_id?: number;\n b_prop?: number;\n t_prop?: number;\n b_int_name?: string;\n t_int_name?: string;\n b_age?: number;\n t_age?: number;\n}\n\nexport interface IntervalProportionsProps extends Omit<\n IntervalTagProps,\n \"interval\"\n> {\n unit: UnitIntervalConstraints;\n showProportions?: boolean;\n calculateProportionsFromAges?: boolean;\n onClickItem?: any;\n}\n\nexport function IntervalProportions({\n unit,\n className,\n showProportions,\n calculateProportionsFromAges = true,\n ...rest\n}: IntervalProportionsProps) {\n /** Display the proportions of the unit that belong to the base and top intervals, if they are different */\n if (unit.b_int_id == null && unit.t_int_id == null) return null;\n\n let _showProps = showProportions;\n\n const i0 = unit.b_int_id;\n const i1 = unit.t_int_id;\n\n const ints = new Set([i0, i1]);\n\n /** Get interval information */\n const intervalMap = useMacrostratDefs(\"intervals\", Array.from(ints), null);\n const [int0, int1] = useMemo(() => {\n const int0 = intervalMap?.get(i0) ?? {};\n if (i0 === i1) {\n return [int0, int0];\n }\n const int1 = intervalMap?.get(i1) ?? {};\n return [int0, int1];\n }, [intervalMap, i0, i1]);\n\n const interval0: IntervalShort = {\n id: i0,\n name: unit.b_int_name,\n ...int0,\n };\n\n let b_prop = unit.b_prop;\n let t_prop = unit.t_prop;\n\n // If we have b_age and t_age, then we can calculate proportions if they are not given\n if (b_prop == null && unit.b_age != null && calculateProportionsFromAges) {\n b_prop = getProportion(unit.b_age, int0);\n }\n if (t_prop == null && unit.t_age != null && calculateProportionsFromAges) {\n t_prop = getProportion(unit.t_age, int1);\n }\n\n // If there are no proportions given and we are not explicitly directed to show them,\n // then we set them to hidden.\n if (b_prop == null && t_prop == null) {\n _showProps ??= false;\n }\n\n /*\n Set default proportions to 0 and 1 if they are not given,\n so that we can display \"base\" and \"top\" labels\n */\n b_prop ??= 0;\n t_prop ??= 1;\n\n let p0: any = null;\n let p1: any = null;\n\n if (_showProps !== false) {\n p1 = h(Proportion, { value: t_prop });\n\n if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {\n // We have a single interval with undefined proportions\n p0 = h(Proportion, { value: b_prop });\n }\n\n if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {\n p0 = h(\"span.joint-proportion\", [p0, \" \", h(\"span.sep\", \"to\"), \" \", p1]);\n }\n }\n\n return h(\n ItemList,\n { className: classNames(\"interval-proportions\", className) },\n [\n h(IntervalTag, {\n interval: interval0,\n prefix: p0,\n ...rest,\n }),\n h.if(i0 != i1)(\"span.discourage-break\", [\n h(\"span.sep\", \" to \"),\n h(IntervalTag, {\n interval: {\n id: i1,\n name: unit.t_int_name,\n ...int1,\n },\n prefix: p1,\n ...rest,\n }),\n ]),\n ],\n );\n}\n\nfunction getProportion(age: number, interval: IntervalShort): number | null {\n /** Get proportion with the age */\n return (interval.b_age - age) / (interval.b_age - interval.t_age);\n}\n\
|
|
1
|
+
{"version":3,"file":"age-range.js","sources":["../../src/unit-details/age-range.ts"],"sourcesContent":["import {\n DataField,\n IntervalShort,\n IntervalTag,\n type IntervalTagProps,\n ItemList,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport h from \"./age-range.module.sass\";\nimport { formatProportion, formatRange } from \"./utils\";\nimport classNames from \"classnames\";\nimport { ReactNode, useMemo } from \"react\";\n\nexport function AgeField({ unit, children, ...rest }) {\n const [_b_age, _t_age, _unit] = getAgeRange(unit);\n\n return h(\n DataField,\n {\n label: \"Age\",\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n ...rest,\n },\n children,\n );\n}\n\nexport function AgeRange({\n data,\n className,\n}: {\n data: {\n t_age: number;\n b_age: number;\n };\n className?: string;\n}) {\n const [_b_age, _t_age, _unit] = getAgeRange(data);\n\n return h(Value, {\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n className,\n });\n}\n\nexport function AgeLabel({\n age,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n className,\n}: {\n age: number;\n className?: string;\n maximumFractionDigits?: number;\n minimumFractionDigits?: number;\n}) {\n /** Component to display a single age value with unit conversion from\n * Ma to ka or Ga as appropriate.\n */\n const [value, unit] = getAge(age);\n\n const _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit, className });\n}\n\nexport function Duration({\n value,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n}) {\n let unit = \"Myr\";\n if (value < 0.8) {\n unit = \"kyr\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Gyr\";\n value /= 1000;\n }\n\n let _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit });\n}\n\ninterface UnitIntervalConstraints {\n b_int_id?: number;\n t_int_id?: number;\n b_prop?: number;\n t_prop?: number;\n b_int_name?: string;\n t_int_name?: string;\n b_age?: number;\n t_age?: number;\n}\n\nexport interface IntervalProportionsProps extends Omit<\n IntervalTagProps,\n \"interval\"\n> {\n unit: UnitIntervalConstraints;\n showProportions?: boolean;\n calculateProportionsFromAges?: boolean;\n onClickItem?: any;\n}\n\nexport function IntervalProportions({\n unit,\n className,\n showProportions,\n calculateProportionsFromAges = true,\n ...rest\n}: IntervalProportionsProps) {\n /** Display the proportions of the unit that belong to the base and top intervals, if they are different */\n if (unit.b_int_id == null && unit.t_int_id == null) return null;\n\n let _showProps = showProportions;\n\n const i0 = unit.b_int_id;\n const i1 = unit.t_int_id;\n\n const ints = new Set([i0, i1]);\n\n /** Get interval information */\n const intervalMap = useMacrostratDefs(\"intervals\", Array.from(ints), null);\n const [int0, int1] = useMemo(() => {\n const int0 = intervalMap?.get(i0) ?? {};\n if (i0 === i1) {\n return [int0, int0];\n }\n const int1 = intervalMap?.get(i1) ?? {};\n return [int0, int1];\n }, [intervalMap, i0, i1]);\n\n const interval0: IntervalShort = {\n id: i0,\n name: unit.b_int_name,\n ...int0,\n };\n\n let b_prop = unit.b_prop;\n let t_prop = unit.t_prop;\n\n // If we have b_age and t_age, then we can calculate proportions if they are not given\n if (b_prop == null && unit.b_age != null && calculateProportionsFromAges) {\n b_prop = getProportion(unit.b_age, int0);\n }\n if (t_prop == null && unit.t_age != null && calculateProportionsFromAges) {\n t_prop = getProportion(unit.t_age, int1);\n }\n\n // If there are no proportions given and we are not explicitly directed to show them,\n // then we set them to hidden.\n if (b_prop == null && t_prop == null) {\n _showProps ??= false;\n }\n\n /*\n Set default proportions to 0 and 1 if they are not given,\n so that we can display \"base\" and \"top\" labels\n */\n b_prop ??= 0;\n t_prop ??= 1;\n\n let p0: any = null;\n let p1: any = null;\n\n if (_showProps !== false) {\n p1 = h(Proportion, { value: t_prop });\n\n if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {\n // We have a single interval with undefined proportions\n p0 = h(Proportion, { value: b_prop });\n }\n\n if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {\n p0 = h(\"span.joint-proportion\", [p0, \" \", h(\"span.sep\", \"to\"), \" \", p1]);\n }\n }\n\n return h(\n ItemList,\n { className: classNames(\"interval-proportions\", className) },\n [\n h(IntervalTag, {\n interval: interval0,\n prefix: p0,\n ...rest,\n }),\n h.if(i0 != i1)(\"span.discourage-break\", [\n h(\"span.sep\", \" to \"),\n h(IntervalTag, {\n interval: {\n id: i1,\n name: unit.t_int_name,\n ...int1,\n },\n prefix: p1,\n ...rest,\n }),\n ]),\n ],\n );\n}\n\nfunction getProportion(age: number, interval: IntervalShort): number | null {\n /** Get proportion with the age */\n return (interval.b_age - age) / (interval.b_age - interval.t_age);\n}\n\nexport function Proportion({ value }: { value: number }) {\n let content: ReactNode | null = null;\n if (value == 0) {\n content = \"base\";\n } else if (value == 1) {\n content = \"top\";\n } else {\n content = formatProportion(value * 100) + \"%\";\n }\n\n return h(\"span.proportion\", content);\n}\n\nexport function getAgeRange(_unit) {\n let b_age = _unit.b_age;\n let t_age = _unit.t_age;\n let unit = \"Ma\";\n\n if (b_age < 0.8 && t_age < 1.2) {\n b_age *= 1000;\n t_age *= 1000;\n unit = \"ka\";\n } else if (b_age > 800 && t_age > 1200) {\n b_age /= 1000;\n t_age /= 1000;\n unit = \"Ga\";\n }\n\n return [b_age, t_age, unit];\n}\n\nexport function getAge(value) {\n /** Get the age value in Ma, ka, or Ga as appropriate */\n let unit = \"Ma\";\n if (value < 0.8) {\n unit = \"ka\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Ga\";\n value /= 1000;\n }\n\n return [value, unit];\n}\n"],"names":["int0","int1"],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const core = require("@blueprintjs/core");
|
|
4
|
+
const dataComponents = require("@macrostrat/data-components");
|
|
5
|
+
const classNames = require("classnames");
|
|
6
|
+
const ageWindowTag_module = require("./age-window-tag.module.sass.cjs");
|
|
7
|
+
const ageRange = require("./age-range.cjs");
|
|
8
|
+
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
9
|
+
const classNames__default = /* @__PURE__ */ _interopDefault(classNames);
|
|
10
|
+
function intervalShortFromTimescale(interval) {
|
|
11
|
+
return {
|
|
12
|
+
id: interval.int_id ?? interval.oid,
|
|
13
|
+
name: interval.nam,
|
|
14
|
+
color: interval.col,
|
|
15
|
+
b_age: interval.eag,
|
|
16
|
+
t_age: interval.lag,
|
|
17
|
+
rank: interval.lvl
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function AgeWindowTag(props) {
|
|
21
|
+
const {
|
|
22
|
+
interval = null,
|
|
23
|
+
window = null,
|
|
24
|
+
onClear,
|
|
25
|
+
size = dataComponents.TagSize.Small,
|
|
26
|
+
className
|
|
27
|
+
} = props;
|
|
28
|
+
if (interval == null && window == null) return null;
|
|
29
|
+
let tag = null;
|
|
30
|
+
if (interval == null) {
|
|
31
|
+
tag = ageWindowTag_module(dataComponents.Tag, { size, name: ageWindowTag_module(ageRange.AgeRange, { data: window }) });
|
|
32
|
+
} else if (window == null || windowMatchesInterval(window, interval)) {
|
|
33
|
+
tag = ageWindowTag_module(dataComponents.IntervalTag, { interval, showAgeRange: true, size });
|
|
34
|
+
} else {
|
|
35
|
+
tag = ageWindowTag_module(RefinedIntervalTag, { interval, window, size });
|
|
36
|
+
}
|
|
37
|
+
return ageWindowTag_module("span.age-window-tag", { className: classNames__default.default(className) }, [
|
|
38
|
+
tag,
|
|
39
|
+
ageWindowTag_module.if(onClear != null)(core.Button, {
|
|
40
|
+
className: "clear-button",
|
|
41
|
+
icon: "cross",
|
|
42
|
+
minimal: true,
|
|
43
|
+
small: true,
|
|
44
|
+
title: "Clear",
|
|
45
|
+
onClick: onClear
|
|
46
|
+
})
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
49
|
+
function RefinedIntervalTag({
|
|
50
|
+
interval,
|
|
51
|
+
window,
|
|
52
|
+
size
|
|
53
|
+
}) {
|
|
54
|
+
const interaction = dataComponents.useInteractionProps({ int_id: interval.id });
|
|
55
|
+
return ageWindowTag_module(dataComponents.Tag, {
|
|
56
|
+
...interaction,
|
|
57
|
+
size,
|
|
58
|
+
name: interval.name,
|
|
59
|
+
color: interval.color,
|
|
60
|
+
details: ageWindowTag_module(ageRange.AgeRange, { data: window })
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function windowMatchesInterval(window, interval) {
|
|
64
|
+
return window.t_age === interval.t_age && window.b_age === interval.b_age;
|
|
65
|
+
}
|
|
66
|
+
exports.AgeWindowTag = AgeWindowTag;
|
|
67
|
+
exports.intervalShortFromTimescale = intervalShortFromTimescale;
|
|
68
|
+
//# sourceMappingURL=age-window-tag.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"age-window-tag.cjs","sources":["../../src/unit-details/age-window-tag.ts"],"sourcesContent":["import { Button } from \"@blueprintjs/core\";\nimport {\n IntervalShort,\n IntervalTag,\n Tag,\n TagSize,\n useInteractionProps,\n} from \"@macrostrat/data-components\";\nimport type { Interval } from \"@macrostrat/timescale\";\nimport classNames from \"classnames\";\nimport h from \"./age-window-tag.module.sass\";\nimport { AgeRange } from \"./age-range\";\nimport type { AgeWindow } from \"../animated-age-window\";\n\n/** Adapt a timescale `Interval` (as delivered by a `Timescale` click, with\n * `eag`/`lag`/`nam`/`col`) to the `IntervalShort` shape the tag components\n * take. The id prefers the Macrostrat `int_id` when the interval tree was built\n * from the API, falling back to the interval's own `oid`. */\nexport function intervalShortFromTimescale(interval: Interval): IntervalShort {\n return {\n id: interval.int_id ?? interval.oid,\n name: interval.nam,\n color: interval.col,\n b_age: interval.eag,\n t_age: interval.lag,\n rank: interval.lvl,\n };\n}\n\nexport interface AgeWindowTagProps {\n /** The interval the window was set from, if any. */\n interval?: IntervalShort | null;\n /** The rendered window. When it differs from the interval's own span (a\n * refined window) it is shown in place of the interval's range. */\n window?: AgeWindow | null;\n /** Renders a clear button when given. */\n onClear?: () => void;\n size?: TagSize;\n className?: string;\n}\n\n/** A compact, clearable indicator of the age window a column or correlation\n * chart is focused on — an interval tag (linking to the interval, with its\n * range) or a bare age range. Renders nothing without an interval or window,\n * so it can live permanently in a chart's `axisTopContent`. */\nexport function AgeWindowTag(props: AgeWindowTagProps) {\n const {\n interval = null,\n window = null,\n onClear,\n size = TagSize.Small,\n className,\n } = props;\n if (interval == null && window == null) return null;\n\n let tag = null;\n if (interval == null) {\n tag = h(Tag, { size, name: h(AgeRange, { data: window }) });\n } else if (window == null || windowMatchesInterval(window, interval)) {\n tag = h(IntervalTag, { interval, showAgeRange: true, size });\n } else {\n tag = h(RefinedIntervalTag, { interval, window, size });\n }\n\n return h(\"span.age-window-tag\", { className: classNames(className) }, [\n tag,\n h.if(onClear != null)(Button, {\n className: \"clear-button\",\n icon: \"cross\",\n minimal: true,\n small: true,\n title: \"Clear\",\n onClick: onClear,\n }),\n ]);\n}\n\nfunction RefinedIntervalTag({\n interval,\n window,\n size,\n}: {\n interval: IntervalShort;\n window: AgeWindow;\n size: TagSize;\n}) {\n const interaction = useInteractionProps({ int_id: interval.id });\n return h(Tag, {\n ...interaction,\n size,\n name: interval.name,\n color: interval.color,\n details: h(AgeRange, { data: window }),\n });\n}\n\nfunction windowMatchesInterval(\n window: AgeWindow,\n interval: IntervalShort,\n): boolean {\n return window.t_age === interval.t_age && window.b_age === interval.b_age;\n}\n"],"names":["TagSize","h","Tag","AgeRange","IntervalTag","classNames","Button","useInteractionProps"],"mappings":";;;;;;;;;AAkBO,SAAS,2BAA2B,UAAmC;AAC5E,SAAO;AAAA,IACL,IAAI,SAAS,UAAU,SAAS;AAAA,IAChC,MAAM,SAAS;AAAA,IACf,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,IAChB,MAAM,SAAS;AAAA,EAAA;AAEnB;AAkBO,SAAS,aAAa,OAA0B;AACrD,QAAM;AAAA,IACJ,WAAW;AAAA,IACX,SAAS;AAAA,IACT;AAAA,IACA,OAAOA,eAAAA,QAAQ;AAAA,IACf;AAAA,EAAA,IACE;AACJ,MAAI,YAAY,QAAQ,UAAU,KAAM,QAAO;AAE/C,MAAI,MAAM;AACV,MAAI,YAAY,MAAM;AACpB,UAAMC,oBAAEC,oBAAK,EAAE,MAAM,MAAMD,oBAAEE,SAAAA,UAAU,EAAE,MAAM,OAAA,CAAQ,EAAA,CAAG;AAAA,EAC5D,WAAW,UAAU,QAAQ,sBAAsB,QAAQ,QAAQ,GAAG;AACpE,UAAMF,oBAAEG,4BAAa,EAAE,UAAU,cAAc,MAAM,MAAM;AAAA,EAC7D,OAAO;AACL,UAAMH,oBAAE,oBAAoB,EAAE,UAAU,QAAQ,MAAM;AAAA,EACxD;AAEA,SAAOA,oBAAE,uBAAuB,EAAE,WAAWI,oBAAAA,QAAW,SAAS,KAAK;AAAA,IACpE;AAAA,IACAJ,oBAAE,GAAG,WAAW,IAAI,EAAEK,KAAAA,QAAQ;AAAA,MAC5B,WAAW;AAAA,MACX,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,IAAA,CACV;AAAA,EAAA,CACF;AACH;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAcC,eAAAA,oBAAoB,EAAE,QAAQ,SAAS,IAAI;AAC/D,SAAON,oBAAEC,eAAAA,KAAK;AAAA,IACZ,GAAG;AAAA,IACH;AAAA,IACA,MAAM,SAAS;AAAA,IACf,OAAO,SAAS;AAAA,IAChB,SAASD,oBAAEE,SAAAA,UAAU,EAAE,MAAM,QAAQ;AAAA,EAAA,CACtC;AACH;AAEA,SAAS,sBACP,QACA,UACS;AACT,SAAO,OAAO,UAAU,SAAS,SAAS,OAAO,UAAU,SAAS;AACtE;;;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { IntervalShort, TagSize } from '@macrostrat/data-components';
|
|
2
|
+
import { Interval } from '@macrostrat/timescale';
|
|
3
|
+
import { AgeWindow } from '../animated-age-window';
|
|
4
|
+
/** Adapt a timescale `Interval` (as delivered by a `Timescale` click, with
|
|
5
|
+
* `eag`/`lag`/`nam`/`col`) to the `IntervalShort` shape the tag components
|
|
6
|
+
* take. The id prefers the Macrostrat `int_id` when the interval tree was built
|
|
7
|
+
* from the API, falling back to the interval's own `oid`. */
|
|
8
|
+
export declare function intervalShortFromTimescale(interval: Interval): IntervalShort;
|
|
9
|
+
export interface AgeWindowTagProps {
|
|
10
|
+
/** The interval the window was set from, if any. */
|
|
11
|
+
interval?: IntervalShort | null;
|
|
12
|
+
/** The rendered window. When it differs from the interval's own span (a
|
|
13
|
+
* refined window) it is shown in place of the interval's range. */
|
|
14
|
+
window?: AgeWindow | null;
|
|
15
|
+
/** Renders a clear button when given. */
|
|
16
|
+
onClear?: () => void;
|
|
17
|
+
size?: TagSize;
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
/** A compact, clearable indicator of the age window a column or correlation
|
|
21
|
+
* chart is focused on — an interval tag (linking to the interval, with its
|
|
22
|
+
* range) or a bare age range. Renders nothing without an interval or window,
|
|
23
|
+
* so it can live permanently in a chart's `axisTopContent`. */
|
|
24
|
+
export declare function AgeWindowTag(props: AgeWindowTagProps): import('react').ReactElement<{
|
|
25
|
+
className: string;
|
|
26
|
+
}, string | import('react').JSXElementConstructor<any>> | null;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Button } from "@blueprintjs/core";
|
|
2
|
+
import { TagSize, Tag, IntervalTag, useInteractionProps } from "@macrostrat/data-components";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import h from "./age-window-tag.module.sass.js";
|
|
5
|
+
import { AgeRange } from "./age-range.js";
|
|
6
|
+
function intervalShortFromTimescale(interval) {
|
|
7
|
+
return {
|
|
8
|
+
id: interval.int_id ?? interval.oid,
|
|
9
|
+
name: interval.nam,
|
|
10
|
+
color: interval.col,
|
|
11
|
+
b_age: interval.eag,
|
|
12
|
+
t_age: interval.lag,
|
|
13
|
+
rank: interval.lvl
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function AgeWindowTag(props) {
|
|
17
|
+
const {
|
|
18
|
+
interval = null,
|
|
19
|
+
window = null,
|
|
20
|
+
onClear,
|
|
21
|
+
size = TagSize.Small,
|
|
22
|
+
className
|
|
23
|
+
} = props;
|
|
24
|
+
if (interval == null && window == null) return null;
|
|
25
|
+
let tag = null;
|
|
26
|
+
if (interval == null) {
|
|
27
|
+
tag = h(Tag, { size, name: h(AgeRange, { data: window }) });
|
|
28
|
+
} else if (window == null || windowMatchesInterval(window, interval)) {
|
|
29
|
+
tag = h(IntervalTag, { interval, showAgeRange: true, size });
|
|
30
|
+
} else {
|
|
31
|
+
tag = h(RefinedIntervalTag, { interval, window, size });
|
|
32
|
+
}
|
|
33
|
+
return h("span.age-window-tag", { className: classNames(className) }, [
|
|
34
|
+
tag,
|
|
35
|
+
h.if(onClear != null)(Button, {
|
|
36
|
+
className: "clear-button",
|
|
37
|
+
icon: "cross",
|
|
38
|
+
minimal: true,
|
|
39
|
+
small: true,
|
|
40
|
+
title: "Clear",
|
|
41
|
+
onClick: onClear
|
|
42
|
+
})
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
function RefinedIntervalTag({
|
|
46
|
+
interval,
|
|
47
|
+
window,
|
|
48
|
+
size
|
|
49
|
+
}) {
|
|
50
|
+
const interaction = useInteractionProps({ int_id: interval.id });
|
|
51
|
+
return h(Tag, {
|
|
52
|
+
...interaction,
|
|
53
|
+
size,
|
|
54
|
+
name: interval.name,
|
|
55
|
+
color: interval.color,
|
|
56
|
+
details: h(AgeRange, { data: window })
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function windowMatchesInterval(window, interval) {
|
|
60
|
+
return window.t_age === interval.t_age && window.b_age === interval.b_age;
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
AgeWindowTag,
|
|
64
|
+
intervalShortFromTimescale
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=age-window-tag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"age-window-tag.js","sources":["../../src/unit-details/age-window-tag.ts"],"sourcesContent":["import { Button } from \"@blueprintjs/core\";\nimport {\n IntervalShort,\n IntervalTag,\n Tag,\n TagSize,\n useInteractionProps,\n} from \"@macrostrat/data-components\";\nimport type { Interval } from \"@macrostrat/timescale\";\nimport classNames from \"classnames\";\nimport h from \"./age-window-tag.module.sass\";\nimport { AgeRange } from \"./age-range\";\nimport type { AgeWindow } from \"../animated-age-window\";\n\n/** Adapt a timescale `Interval` (as delivered by a `Timescale` click, with\n * `eag`/`lag`/`nam`/`col`) to the `IntervalShort` shape the tag components\n * take. The id prefers the Macrostrat `int_id` when the interval tree was built\n * from the API, falling back to the interval's own `oid`. */\nexport function intervalShortFromTimescale(interval: Interval): IntervalShort {\n return {\n id: interval.int_id ?? interval.oid,\n name: interval.nam,\n color: interval.col,\n b_age: interval.eag,\n t_age: interval.lag,\n rank: interval.lvl,\n };\n}\n\nexport interface AgeWindowTagProps {\n /** The interval the window was set from, if any. */\n interval?: IntervalShort | null;\n /** The rendered window. When it differs from the interval's own span (a\n * refined window) it is shown in place of the interval's range. */\n window?: AgeWindow | null;\n /** Renders a clear button when given. */\n onClear?: () => void;\n size?: TagSize;\n className?: string;\n}\n\n/** A compact, clearable indicator of the age window a column or correlation\n * chart is focused on — an interval tag (linking to the interval, with its\n * range) or a bare age range. Renders nothing without an interval or window,\n * so it can live permanently in a chart's `axisTopContent`. */\nexport function AgeWindowTag(props: AgeWindowTagProps) {\n const {\n interval = null,\n window = null,\n onClear,\n size = TagSize.Small,\n className,\n } = props;\n if (interval == null && window == null) return null;\n\n let tag = null;\n if (interval == null) {\n tag = h(Tag, { size, name: h(AgeRange, { data: window }) });\n } else if (window == null || windowMatchesInterval(window, interval)) {\n tag = h(IntervalTag, { interval, showAgeRange: true, size });\n } else {\n tag = h(RefinedIntervalTag, { interval, window, size });\n }\n\n return h(\"span.age-window-tag\", { className: classNames(className) }, [\n tag,\n h.if(onClear != null)(Button, {\n className: \"clear-button\",\n icon: \"cross\",\n minimal: true,\n small: true,\n title: \"Clear\",\n onClick: onClear,\n }),\n ]);\n}\n\nfunction RefinedIntervalTag({\n interval,\n window,\n size,\n}: {\n interval: IntervalShort;\n window: AgeWindow;\n size: TagSize;\n}) {\n const interaction = useInteractionProps({ int_id: interval.id });\n return h(Tag, {\n ...interaction,\n size,\n name: interval.name,\n color: interval.color,\n details: h(AgeRange, { data: window }),\n });\n}\n\nfunction windowMatchesInterval(\n window: AgeWindow,\n interval: IntervalShort,\n): boolean {\n return window.t_age === interval.t_age && window.b_age === interval.b_age;\n}\n"],"names":[],"mappings":";;;;;AAkBO,SAAS,2BAA2B,UAAmC;AAC5E,SAAO;AAAA,IACL,IAAI,SAAS,UAAU,SAAS;AAAA,IAChC,MAAM,SAAS;AAAA,IACf,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,IAChB,MAAM,SAAS;AAAA,EAAA;AAEnB;AAkBO,SAAS,aAAa,OAA0B;AACrD,QAAM;AAAA,IACJ,WAAW;AAAA,IACX,SAAS;AAAA,IACT;AAAA,IACA,OAAO,QAAQ;AAAA,IACf;AAAA,EAAA,IACE;AACJ,MAAI,YAAY,QAAQ,UAAU,KAAM,QAAO;AAE/C,MAAI,MAAM;AACV,MAAI,YAAY,MAAM;AACpB,UAAM,EAAE,KAAK,EAAE,MAAM,MAAM,EAAE,UAAU,EAAE,MAAM,OAAA,CAAQ,EAAA,CAAG;AAAA,EAC5D,WAAW,UAAU,QAAQ,sBAAsB,QAAQ,QAAQ,GAAG;AACpE,UAAM,EAAE,aAAa,EAAE,UAAU,cAAc,MAAM,MAAM;AAAA,EAC7D,OAAO;AACL,UAAM,EAAE,oBAAoB,EAAE,UAAU,QAAQ,MAAM;AAAA,EACxD;AAEA,SAAO,EAAE,uBAAuB,EAAE,WAAW,WAAW,SAAS,KAAK;AAAA,IACpE;AAAA,IACA,EAAE,GAAG,WAAW,IAAI,EAAE,QAAQ;AAAA,MAC5B,WAAW;AAAA,MACX,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,IAAA,CACV;AAAA,EAAA,CACF;AACH;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,cAAc,oBAAoB,EAAE,QAAQ,SAAS,IAAI;AAC/D,SAAO,EAAE,KAAK;AAAA,IACZ,GAAG;AAAA,IACH;AAAA,IACA,MAAM,SAAS;AAAA,IACf,OAAO,SAAS;AAAA,IAChB,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ;AAAA,EAAA,CACtC;AACH;AAEA,SAAS,sBACP,QACA,UACS;AACT,SAAO,OAAO,UAAU,SAAS,SAAS,OAAO,UAAU,SAAS;AACtE;"}
|
package/dist/{age-model-overlay.module.sass.cjs → unit-details/age-window-tag.module.sass.cjs}
RENAMED
|
@@ -3,10 +3,10 @@ const h$1 = require("@macrostrat/hyper");
|
|
|
3
3
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
4
4
|
const h__default = /* @__PURE__ */ _interopDefault(h$1);
|
|
5
5
|
const styles = {
|
|
6
|
-
"
|
|
7
|
-
"
|
|
6
|
+
"age-window-tag": "_age-window-tag_1tskh_1",
|
|
7
|
+
"clear-button": "_clear-button_1tskh_8"
|
|
8
8
|
};
|
|
9
9
|
let h = h__default.default.styled(styles);
|
|
10
10
|
Object.assign(h, styles);
|
|
11
11
|
module.exports = h;
|
|
12
|
-
//# sourceMappingURL=age-
|
|
12
|
+
//# sourceMappingURL=age-window-tag.module.sass.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"age-window-tag.module.sass.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import h$1 from "@macrostrat/hyper";
|
|
2
|
+
const styles = {
|
|
3
|
+
"age-window-tag": "_age-window-tag_1tskh_1",
|
|
4
|
+
"clear-button": "_clear-button_1tskh_8"
|
|
5
|
+
};
|
|
6
|
+
let h = h$1.styled(styles);
|
|
7
|
+
Object.assign(h, styles);
|
|
8
|
+
export {
|
|
9
|
+
h as default
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=age-window-tag.module.sass.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"age-window-tag.module.sass.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
|
@@ -2,5 +2,6 @@ export * from './panel';
|
|
|
2
2
|
export * from './popover';
|
|
3
3
|
export * from './modal-panel';
|
|
4
4
|
export * from './age-range';
|
|
5
|
+
export * from './age-window-tag';
|
|
5
6
|
export * from './strat-names';
|
|
6
7
|
export { ClickableText, Identifier, UnitIdentifier, } from '@macrostrat/data-components';
|
package/dist/units/composite.cjs
CHANGED
|
@@ -83,13 +83,15 @@ function AnnotatedUnitsColumn(props) {
|
|
|
83
83
|
}, []);
|
|
84
84
|
return null;
|
|
85
85
|
}
|
|
86
|
+
const DEFAULT_LABEL_SUPPRESS_HEIGHT = 2;
|
|
86
87
|
function SectionLabelsColumn(props) {
|
|
87
88
|
const {
|
|
88
89
|
width = 300,
|
|
89
90
|
noteMode = "unlabeled",
|
|
90
91
|
labelOffset = 30,
|
|
91
92
|
noteComponent,
|
|
92
|
-
shouldRenderNote
|
|
93
|
+
shouldRenderNote,
|
|
94
|
+
labelSuppressHeight = DEFAULT_LABEL_SUPPRESS_HEIGHT
|
|
93
95
|
} = props;
|
|
94
96
|
const { totalHeight, axisType } = store.useMacrostratColumnData();
|
|
95
97
|
const _compositeScale = store.useCompositeScale();
|
|
@@ -117,6 +119,7 @@ function SectionLabelsColumn(props) {
|
|
|
117
119
|
divisions: unitsToLabel,
|
|
118
120
|
paddingLeft: labelOffset,
|
|
119
121
|
width,
|
|
122
|
+
minimumHeight: labelSuppressHeight,
|
|
120
123
|
noteComponent,
|
|
121
124
|
shouldRenderNote,
|
|
122
125
|
scale: _compositeScale,
|