@macrostrat/column-views 3.2.2 → 3.3.1

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/index.cjs +15 -9
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.js +11 -5
  5. package/dist/maps/column-correlation/core.cjs +10 -30
  6. package/dist/maps/column-correlation/core.cjs.map +1 -1
  7. package/dist/maps/column-correlation/core.d.ts +1 -1
  8. package/dist/maps/column-correlation/core.js +10 -30
  9. package/dist/maps/column-correlation/core.js.map +1 -1
  10. package/dist/maps/column-navigation/mapbox/index.cjs +156 -118
  11. package/dist/maps/column-navigation/mapbox/index.cjs.map +1 -1
  12. package/dist/maps/column-navigation/mapbox/index.d.ts +23 -2
  13. package/dist/maps/column-navigation/mapbox/index.js +158 -120
  14. package/dist/maps/column-navigation/mapbox/index.js.map +1 -1
  15. package/dist/maps/column-navigation/mapbox/keyboard-navigation.cjs +7 -1
  16. package/dist/maps/column-navigation/mapbox/keyboard-navigation.cjs.map +1 -1
  17. package/dist/maps/column-navigation/mapbox/keyboard-navigation.d.ts +3 -26
  18. package/dist/maps/column-navigation/mapbox/keyboard-navigation.js +9 -3
  19. package/dist/maps/column-navigation/mapbox/keyboard-navigation.js.map +1 -1
  20. package/dist/maps/index.d.ts +2 -2
  21. package/dist/maps/{_shared/inset-map.cjs → inset-map/index.cjs} +1 -1
  22. package/dist/maps/inset-map/index.cjs.map +1 -0
  23. package/dist/maps/{_shared/inset-map.js → inset-map/index.js} +1 -1
  24. package/dist/maps/inset-map/index.js.map +1 -0
  25. package/dist/maps/layers/columns.cjs +161 -0
  26. package/dist/maps/layers/columns.cjs.map +1 -0
  27. package/dist/maps/layers/columns.d.ts +28 -0
  28. package/dist/maps/layers/columns.js +161 -0
  29. package/dist/maps/layers/columns.js.map +1 -0
  30. package/dist/maps/layers/index.d.ts +2 -0
  31. package/dist/maps/{units-overlay/index.cjs → layers/units.cjs} +41 -88
  32. package/dist/maps/layers/units.cjs.map +1 -0
  33. package/dist/maps/{units-overlay/index.d.ts → layers/units.d.ts} +1 -1
  34. package/dist/maps/{units-overlay/index.js → layers/units.js} +34 -82
  35. package/dist/maps/layers/units.js.map +1 -0
  36. package/dist/unit-details/age-range.cjs +86 -44
  37. package/dist/unit-details/age-range.cjs.map +1 -1
  38. package/dist/unit-details/age-range.d.ts +32 -5
  39. package/dist/unit-details/age-range.js +84 -44
  40. package/dist/unit-details/age-range.js.map +1 -1
  41. package/package.json +4 -4
  42. package/src/maps/column-correlation/core.ts +9 -29
  43. package/src/maps/column-navigation/mapbox/index.ts +191 -138
  44. package/src/maps/column-navigation/mapbox/keyboard-navigation.ts +17 -3
  45. package/src/maps/index.ts +2 -2
  46. package/src/maps/layers/columns.ts +210 -0
  47. package/src/maps/layers/index.ts +2 -0
  48. package/src/maps/{units-overlay/index.ts → layers/units.ts} +34 -84
  49. package/src/maps/unit-map.stories.ts +27 -12
  50. package/src/unit-details/age-range.ts +124 -47
  51. package/dist/maps/_shared/index.d.ts +0 -2
  52. package/dist/maps/_shared/inset-map.cjs.map +0 -1
  53. package/dist/maps/_shared/inset-map.js.map +0 -1
  54. package/dist/maps/_shared/styles.cjs +0 -73
  55. package/dist/maps/_shared/styles.cjs.map +0 -1
  56. package/dist/maps/_shared/styles.d.ts +0 -2
  57. package/dist/maps/_shared/styles.js +0 -73
  58. package/dist/maps/_shared/styles.js.map +0 -1
  59. package/dist/maps/units-overlay/index.cjs.map +0 -1
  60. package/dist/maps/units-overlay/index.js.map +0 -1
  61. package/src/maps/_shared/index.ts +0 -2
  62. package/src/maps/_shared/styles.ts +0 -76
  63. /package/dist/maps/{_shared/inset-map.d.ts → inset-map/index.d.ts} +0 -0
  64. /package/src/maps/{_shared/inset-map.ts → inset-map/index.ts} +0 -0
  65. /package/src/maps/{_shared → inset-map}/inset-map.stories.ts +0 -0
@@ -1,16 +1,21 @@
1
1
  import { useLithologies, useMacrostratColumns } from "@macrostrat/data-provider";
2
2
  import { useAPIResult } from "@macrostrat/ui-components";
3
- import { useMapStyleOperator } from "@macrostrat/mapbox-react";
3
+ import { useOverlayStyle, useMapStyleOperator } from "@macrostrat/mapbox-react";
4
4
  import { useMemo } from "react";
5
- import { setGeoJSON, buildGeoJSONSource, mergeStyles } from "@macrostrat/mapbox-utils";
5
+ import { buildGeoJSONSource, mergeStyles, setGeoJSON } from "@macrostrat/mapbox-utils";
6
6
  import { getBestFGDCPatternForLithologyList } from "../../units/resolvers.js";
7
7
  import { setupStyleImageManager, loadStyleImage } from "@macrostrat/map-styles";
8
- import { getCSSVariable, asChromaColor } from "@macrostrat/color-utils";
8
+ import { asChromaColor } from "@macrostrat/color-utils";
9
9
  import pMap from "p-map";
10
+ import { BaseColumnsLayer } from "./columns.js";
11
+ import h from "@macrostrat/hyper";
10
12
  import { flattenLithologies, getMixedColorForData } from "../../units/colors.js";
11
13
  function MacrostratUnitsOverlay(props) {
12
14
  const { time, ageSpan = 0.05, patterns = false } = props;
13
15
  const lithMap = useLithologies();
16
+ useOverlayStyle(() => {
17
+ return buildUnitsStyle({ patterns });
18
+ }, [patterns]);
14
19
  useMapStyleOperator(
15
20
  (map) => {
16
21
  if (!patterns) return;
@@ -35,19 +40,6 @@ function MacrostratUnitsOverlay(props) {
35
40
  }, [time, ageSpan, props.project]);
36
41
  const units = useAPIResult("/units", params);
37
42
  const columns = useMacrostratColumns(params.project, false);
38
- useMapStyleOperator(
39
- (map) => {
40
- if (columns == null) {
41
- return;
42
- }
43
- const data = {
44
- type: "FeatureCollection",
45
- features: columns
46
- };
47
- setGeoJSON(map, "columns", data);
48
- },
49
- [columns]
50
- );
51
43
  useMapStyleOperator(
52
44
  (map) => {
53
45
  if (units == null || columns == null || lithMap == null) {
@@ -70,7 +62,28 @@ function MacrostratUnitsOverlay(props) {
70
62
  },
71
63
  [units, lithMap, columns, patterns]
72
64
  );
73
- return null;
65
+ const isHovered = ["boolean", ["feature-state", "hover"], false];
66
+ const isShown = ["boolean", ["feature-state", "shown"], false];
67
+ const opacity = [
68
+ "case",
69
+ ["all", isHovered, isShown],
70
+ 0.9,
71
+ isShown,
72
+ 0.8,
73
+ isHovered,
74
+ 0.3,
75
+ 0
76
+ ];
77
+ return h([
78
+ h(BaseColumnsLayer, {
79
+ enabled: true,
80
+ columns,
81
+ opacity,
82
+ lineOpacity: 0.2,
83
+ lineColor: "lightgray",
84
+ color: "transparent"
85
+ })
86
+ ]);
74
87
  }
75
88
  function handleUnitsLayerUpdate(map, unitsMap, columns) {
76
89
  for (const column of columns) {
@@ -158,71 +171,10 @@ function getPatternSpec(liths, getColor) {
158
171
  return `fgdc:${patternID}:${color}:transparent`;
159
172
  }
160
173
  function buildUnitsStyle(opts = {}) {
161
- const { color = null, patterns = false } = opts;
162
- let columnBaseColor = color ?? getCSSVariable("--text-subtle-color", "black");
163
- getCSSVariable("--selection-color", "purple");
164
- let columnColor = [
165
- "coalesce",
166
- ["feature-state", "color"],
167
- ["get", "color"],
168
- columnBaseColor
169
- ];
174
+ const { patterns = false } = opts;
170
175
  const baseStyle = {
171
- sources: {
172
- columns: buildGeoJSONSource()
173
- },
174
- version: 8,
175
- layers: [
176
- {
177
- id: "columns-fill",
178
- type: "fill",
179
- source: "columns",
180
- paint: {
181
- "fill-color": columnColor,
182
- "fill-opacity": [
183
- "case",
184
- ["boolean", ["feature-state", "shown"], false],
185
- 0.8,
186
- ["boolean", ["feature-state", "hover"], false],
187
- 0.3,
188
- 0.1
189
- ]
190
- }
191
- },
192
- {
193
- id: "columns-line",
194
- type: "line",
195
- source: "columns",
196
- paint: {
197
- "line-color": columnColor,
198
- "line-width": 1,
199
- "line-opacity": 0.5
200
- }
201
- },
202
- {
203
- id: "columns-points",
204
- type: "circle",
205
- source: "columns",
206
- paint: {
207
- "circle-radius": 4,
208
- "circle-color": [
209
- "case",
210
- ["boolean", ["feature-state", "shown"], false],
211
- columnColor,
212
- columnBaseColor
213
- ],
214
- "circle-opacity": [
215
- "case",
216
- ["boolean", ["feature-state", "shown"], false],
217
- 0.8,
218
- ["boolean", ["feature-state", "hover"], false],
219
- 0.3,
220
- 0.1
221
- ]
222
- },
223
- filter: ["==", "$type", "Point"]
224
- }
225
- ]
176
+ sources: {},
177
+ version: 8
226
178
  };
227
179
  if (!patterns) {
228
180
  return baseStyle;
@@ -249,4 +201,4 @@ export {
249
201
  MacrostratUnitsOverlay,
250
202
  buildUnitsStyle
251
203
  };
252
- //# sourceMappingURL=index.js.map
204
+ //# sourceMappingURL=units.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"units.js","sources":["../../../src/maps/layers/units.ts"],"sourcesContent":["import {\n useLithologies,\n useMacrostratColumns,\n} from \"@macrostrat/data-provider\";\nimport { useAPIResult } from \"@macrostrat/ui-components\";\nimport { useMapStyleOperator, useOverlayStyle } from \"@macrostrat/mapbox-react\";\nimport { FeatureCollection } from \"geojson\";\nimport { useMemo } from \"react\";\nimport { mergeStyles, setGeoJSON } from \"@macrostrat/mapbox-utils\";\nimport { UnitLithology, UnitLong } from \"@macrostrat/api-types\";\nimport { flattenLithologies, getMixedColorForData } from \"../../units\";\nimport { getBestFGDCPatternForLithologyList } from \"../../units/resolvers\";\nimport {\n setupStyleImageManager,\n loadStyleImage,\n StyleFragment,\n} from \"@macrostrat/map-styles\";\nimport { asChromaColor } from \"@macrostrat/color-utils\";\nimport { buildGeoJSONSource } from \"@macrostrat/mapbox-utils\";\nimport pMap from \"p-map\";\nimport { BaseColumnsLayer } from \"./columns\";\nimport h from \"@macrostrat/hyper\";\n\nexport interface UnitsOverlayProps {\n time: number;\n ageSpan?: number;\n project?: number | number[];\n patterns?: boolean;\n}\n\nexport function MacrostratUnitsOverlay(props: UnitsOverlayProps) {\n const { time, ageSpan = 0.05, patterns = false } = props;\n const lithMap = useLithologies();\n\n useOverlayStyle(() => {\n return buildUnitsStyle({ patterns });\n }, [patterns]);\n\n useMapStyleOperator(\n (map) => {\n if (!patterns) return;\n setupStyleImageManager(map, { verbose: false });\n },\n [patterns],\n );\n\n const params = useMemo(() => {\n let project: number[] | undefined;\n if (Number.isFinite(props.project)) {\n project = [props.project as number];\n } else if (!Array.isArray(props.project)) {\n project = undefined;\n }\n // Project can only be a single project for now\n const projectCompat =\n project != null && project.length > 0 ? project[0] : undefined;\n\n return {\n age_bottom: time + ageSpan / 2,\n age_top: time - ageSpan / 2,\n response: \"long\",\n project: projectCompat,\n };\n }, [time, ageSpan, props.project]);\n\n const units: UnitLong[] = useAPIResult(\"/units\", params);\n const columns = useMacrostratColumns(params.project, false);\n\n useMapStyleOperator(\n (map) => {\n if (units == null || columns == null || lithMap == null) {\n return;\n }\n\n const getColorForLithology = (data: UnitLithology): string | null => {\n return lithMap?.get(data.lith_id)?.color ?? null;\n };\n\n const unitsMap = postProcessUnits(units, getColorForLithology);\n handleUnitsLayerUpdate(map, unitsMap, columns);\n if (patterns) {\n handlePatternOverlayUpdate(\n map,\n unitsMap,\n columns,\n getColorForLithology,\n ).then(() => {});\n }\n },\n [units, lithMap, columns, patterns],\n );\n\n const isHovered = [\"boolean\", [\"feature-state\", \"hover\"], false];\n const isShown = [\"boolean\", [\"feature-state\", \"shown\"], false];\n\n const opacity = [\n \"case\",\n [\"all\", isHovered, isShown],\n 0.9,\n isShown,\n 0.8,\n isHovered,\n 0.3,\n 0.0,\n ];\n\n return h([\n h(BaseColumnsLayer, {\n enabled: true,\n columns,\n opacity,\n lineOpacity: 0.2,\n lineColor: \"lightgray\",\n color: \"transparent\",\n }),\n ]);\n}\n\nfunction handleUnitsLayerUpdate(\n map,\n unitsMap: Map<number, UnitsDisplayInfo>,\n columns: any[],\n) {\n // Update feature states\n for (const column of columns) {\n const col_id = column.properties.col_id;\n const info = unitsMap.get(Number(col_id));\n const color = info?.color;\n map.setFeatureState(\n { source: \"columns\", id: col_id },\n {\n color,\n shown: color != null,\n },\n );\n }\n}\n\nasync function handlePatternOverlayUpdate(\n map,\n unitsMap: Map<number, UnitsDisplayInfo>,\n columns: any[],\n getColor: LithologyColorGetter,\n) {\n // synthesize patterns not yet in cache\n\n const colsWithPatterns = [];\n const patternIDs = new Set<string>();\n // Update feature states\n for (const column of columns) {\n const col_id = column.properties.col_id;\n const info = unitsMap.get(Number(col_id));\n if (info == null) continue;\n const pattern = getPatternSpec(info?.liths, getColor);\n if (pattern == null) continue;\n\n colsWithPatterns.push({\n type: \"Feature\",\n geometry: column.geometry,\n properties: {\n col_id,\n pattern,\n },\n });\n patternIDs.add(pattern);\n }\n\n const patternsToLoad = patternIDs.values().filter((d) => !map.hasImage(d));\n\n const mapper = async (patternID) => {\n try {\n await loadStyleImage(map, patternID, { pixelRatio: 10 });\n } catch (e) {}\n };\n // Load all pattern images\n await pMap(patternsToLoad, mapper, { concurrency: 5 });\n\n // Set data for pattern layer\n // This is inefficient but the only way to set per-feature patterns in Mapbox\n const patternData: FeatureCollection = {\n type: \"FeatureCollection\",\n features: colsWithPatterns,\n };\n setGeoJSON(map, \"column-patterns\", patternData);\n}\n\nconst cachedColors = new Map<string, string>();\n\nfunction getDarkenedColor(color: string): string {\n /** Memoized function to get a darkened version of a color for pattern use */\n if (cachedColors.has(color)) {\n return cachedColors.get(color);\n }\n const c1 = asChromaColor(color).set(\"hsl.l\", 0.4).set(\"hsl.s\", 0.8).hex();\n cachedColors.set(color, c1);\n return c1;\n}\n\ninterface UnitsDisplayInfo {\n col_id: number;\n units: UnitLong[];\n color: string;\n liths: UnitLithology[];\n}\n\ntype LithologyColorGetter = (val: UnitLithology) => string | null;\n\nfunction postProcessUnits(\n units: UnitLong[],\n getColor: LithologyColorGetter,\n): Map<number, UnitsDisplayInfo> {\n // Group by col_id\n const unitsByColumn: Map<number, UnitLong[]> = new Map();\n for (const unit of units) {\n const col_id = Number(unit.col_id);\n if (!unitsByColumn.has(col_id)) {\n unitsByColumn.set(col_id, [unit]);\n } else {\n unitsByColumn.set(col_id, [...unitsByColumn.get(col_id), unit]);\n }\n }\n\n // Summarize units for display\n const res = new Map<number, UnitsDisplayInfo>();\n for (const [col_id, unitList] of unitsByColumn.entries()) {\n const liths = flattenLithologies(unitList.map((u) => u.lith));\n res.set(col_id, {\n col_id,\n units: unitList,\n liths,\n color: getMixedColorForData(liths, getColor),\n });\n }\n\n return res;\n}\n\nfunction getPatternSpec(\n liths: UnitLithology[],\n getColor: LithologyColorGetter,\n): string | null {\n const patternData = getBestFGDCPatternForLithologyList(liths);\n if (patternData == null) return null;\n let { patternID, lith } = patternData;\n const color = getDarkenedColor(getColor(lith));\n return `fgdc:${patternID}:${color}:transparent`;\n}\n\ntype UnitsStyleOptions = {\n color?: string;\n patterns?: boolean;\n};\n\nexport function buildUnitsStyle(opts: UnitsStyleOptions = {}): StyleFragment {\n const { patterns = false } = opts;\n\n // If color is in the feature state or geojson properties, use that as second choice\n\n const baseStyle: StyleFragment = {\n sources: {},\n version: 8,\n };\n\n if (!patterns) {\n return baseStyle;\n }\n\n const patternStyle: StyleFragment = {\n sources: {\n \"column-patterns\": buildGeoJSONSource(),\n },\n layers: [\n {\n id: \"columns-fill-pattern\",\n type: \"fill\",\n source: \"column-patterns\",\n paint: {\n \"fill-pattern\": [\"get\", \"pattern\"],\n \"fill-opacity\": 1,\n },\n },\n ],\n };\n\n return mergeStyles(baseStyle, patternStyle);\n}\n"],"names":[],"mappings":"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"}
@@ -4,18 +4,34 @@ const dataComponents = require("@macrostrat/data-components");
4
4
  const dataProvider = require("@macrostrat/data-provider");
5
5
  const ageRange_module = require("./age-range.module.sass.cjs");
6
6
  const utils = require("./utils.cjs");
7
- function AgeField({ unit, children }) {
8
- const [b_age, t_age, _unit] = getAgeRange(unit);
7
+ const classNames = require("classnames");
8
+ const React = require("react");
9
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
10
+ const classNames__default = /* @__PURE__ */ _interopDefault(classNames);
11
+ function AgeField({ unit, children, ...rest }) {
12
+ const [_b_age, _t_age, _unit] = getAgeRange(unit);
9
13
  return ageRange_module.default(
10
14
  dataComponents.DataField,
11
15
  {
12
16
  label: "Age",
13
- value: utils.formatRange(b_age, t_age),
14
- unit: _unit
17
+ value: utils.formatRange(_b_age, _t_age),
18
+ unit: _unit,
19
+ ...rest
15
20
  },
16
21
  children
17
22
  );
18
23
  }
24
+ function AgeRange({
25
+ data,
26
+ className
27
+ }) {
28
+ const [_b_age, _t_age, _unit] = getAgeRange(data);
29
+ return ageRange_module.default(dataComponents.Value, {
30
+ value: utils.formatRange(_b_age, _t_age),
31
+ unit: _unit,
32
+ className
33
+ });
34
+ }
19
35
  function AgeLabel({
20
36
  age,
21
37
  maximumFractionDigits = 2,
@@ -52,56 +68,81 @@ function Duration({
52
68
  });
53
69
  return ageRange_module.default(dataComponents.Value, { value: _value, unit });
54
70
  }
55
- function IntervalProportions({ unit, onClickItem }) {
56
- if (unit.b_int_id == null && unit.t_int_id == null && unit.b_prop == null && unit.t_prop == null)
57
- return null;
71
+ function IntervalProportions({
72
+ unit,
73
+ className,
74
+ showProportions,
75
+ calculateProportionsFromAges = true,
76
+ ...rest
77
+ }) {
78
+ if (unit.b_int_id == null && unit.t_int_id == null) return null;
79
+ let _showProps = showProportions;
58
80
  const i0 = unit.b_int_id;
59
81
  const i1 = unit.t_int_id;
60
- let b_prop = unit.b_prop ?? 0;
61
- let t_prop = unit.t_prop ?? 1;
62
82
  const intervalMap = dataProvider.useMacrostratDefs("intervals");
63
- const int0 = intervalMap?.get(i0) ?? {};
83
+ const [int0, int1] = React.useMemo(() => {
84
+ const int02 = intervalMap?.get(i0) ?? {};
85
+ if (i0 === i1) {
86
+ return [int02, int02];
87
+ }
88
+ const int12 = intervalMap?.get(i1) ?? {};
89
+ return [int02, int12];
90
+ }, [intervalMap, i0, i1]);
64
91
  const interval0 = {
65
- ...int0,
66
92
  id: i0,
67
- name: unit.b_int_name
93
+ name: unit.b_int_name,
94
+ ...int0
68
95
  };
69
- let p0 = null;
70
- const int1 = intervalMap?.get(i1) ?? {};
71
- const p1 = ageRange_module.default(Proportion, { value: t_prop });
72
- if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {
73
- p0 = ageRange_module.default(Proportion, { value: b_prop });
96
+ let b_prop = unit.b_prop;
97
+ let t_prop = unit.t_prop;
98
+ if (b_prop == null && unit.b_age != null && calculateProportionsFromAges) {
99
+ b_prop = getProportion(unit.b_age, int0);
100
+ }
101
+ if (t_prop == null && unit.t_age != null && calculateProportionsFromAges) {
102
+ t_prop = getProportion(unit.t_age, int1);
74
103
  }
75
- if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {
76
- p0 = ageRange_module.default("span.joint-proportion", [p0, " ", ageRange_module.default("span.sep", "to"), " ", p1]);
104
+ if (b_prop == null && t_prop == null) {
105
+ _showProps ??= false;
77
106
  }
78
- const clickable = onClickItem != null;
79
- const handleClick = (event) => {
80
- if (onClickItem) {
81
- onClickItem(event, interval0);
107
+ b_prop ??= 0;
108
+ t_prop ??= 1;
109
+ let p0 = null;
110
+ let p1 = null;
111
+ if (_showProps !== false) {
112
+ p1 = ageRange_module.default(Proportion, { value: t_prop });
113
+ if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {
114
+ p0 = ageRange_module.default(Proportion, { value: b_prop });
82
115
  }
83
- };
84
- return ageRange_module.default(dataComponents.ItemList, { className: "interval-proportions" }, [
85
- ageRange_module.default(dataComponents.IntervalTag, {
86
- className: clickable ? "clickable" : "",
87
- onClick: clickable ? handleClick : void 0,
88
- interval: interval0,
89
- prefix: p0
90
- }),
91
- ageRange_module.default.if(i0 != i1)("span.discourage-break", [
92
- ageRange_module.default("span.sep", " to "),
116
+ if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {
117
+ p0 = ageRange_module.default("span.joint-proportion", [p0, " ", ageRange_module.default("span.sep", "to"), " ", p1]);
118
+ }
119
+ }
120
+ return ageRange_module.default(
121
+ dataComponents.ItemList,
122
+ { className: classNames__default.default("interval-proportions", className) },
123
+ [
93
124
  ageRange_module.default(dataComponents.IntervalTag, {
94
- className: clickable ? "clickable" : "",
95
- onClick: clickable ? handleClick : void 0,
96
- interval: {
97
- ...int1,
98
- id: i1,
99
- name: unit.t_int_name
100
- },
101
- prefix: p1
102
- })
103
- ])
104
- ]);
125
+ interval: interval0,
126
+ prefix: p0,
127
+ ...rest
128
+ }),
129
+ ageRange_module.default.if(i0 != i1)("span.discourage-break", [
130
+ ageRange_module.default("span.sep", " to "),
131
+ ageRange_module.default(dataComponents.IntervalTag, {
132
+ interval: {
133
+ id: i1,
134
+ name: unit.t_int_name,
135
+ ...int1
136
+ },
137
+ prefix: p1,
138
+ ...rest
139
+ })
140
+ ])
141
+ ]
142
+ );
143
+ }
144
+ function getProportion(age, interval) {
145
+ return (interval.b_age - age) / (interval.b_age - interval.t_age);
105
146
  }
106
147
  function Proportion({ value }) {
107
148
  let content = null;
@@ -146,6 +187,7 @@ function getAge(value) {
146
187
  }
147
188
  exports.AgeField = AgeField;
148
189
  exports.AgeLabel = AgeLabel;
190
+ exports.AgeRange = AgeRange;
149
191
  exports.Duration = Duration;
150
192
  exports.IntervalProportions = IntervalProportions;
151
193
  exports.getAge = getAge;
@@ -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 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\";\n\nexport function AgeField({ unit, children }) {\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 },\n children,\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\nexport function IntervalProportions({ unit, onClickItem }) {\n /** Display the proportions of the unit that belong to the base and top intervals, if they are different */\n if (\n unit.b_int_id == null &&\n unit.t_int_id == null &&\n unit.b_prop == null &&\n unit.t_prop == null\n )\n return null;\n\n const i0 = unit.b_int_id;\n const i1 = unit.t_int_id;\n let b_prop = unit.b_prop ?? 0;\n let t_prop = unit.t_prop ?? 1;\n\n const intervalMap = useMacrostratDefs(\"intervals\");\n const int0 = intervalMap?.get(i0) ?? {};\n\n const interval0: IntervalShort = {\n ...int0,\n id: i0,\n name: unit.b_int_name,\n };\n\n let p0: any = null;\n const int1 = intervalMap?.get(i1) ?? {};\n const p1: any = 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 const clickable = onClickItem != null;\n\n const handleClick = (event: MouseEvent) => {\n if (onClickItem) {\n onClickItem(event, interval0);\n }\n };\n\n return h(ItemList, { className: \"interval-proportions\" }, [\n h(IntervalTag, {\n className: clickable ? \"clickable\" : \"\",\n onClick: clickable ? handleClick : undefined,\n interval: interval0,\n prefix: p0,\n }),\n h.if(i0 != i1)(\"span.discourage-break\", [\n h(\"span.sep\", \" to \"),\n h(IntervalTag, {\n className: clickable ? \"clickable\" : \"\",\n onClick: clickable ? handleClick : undefined,\n interval: {\n ...int1,\n id: i1,\n name: unit.t_int_name,\n },\n prefix: p1,\n }),\n ]),\n ]);\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","ItemList","IntervalTag","formatProportion"],"mappings":";;;;;;AAWO,SAAS,SAAS,EAAE,MAAM,YAAY;AAC3C,QAAM,CAAC,OAAO,OAAO,KAAK,IAAI,YAAY,IAAI;AAE9C,SAAOA,gBAAAA;AAAAA,IACLC,eAAAA;AAAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,OAAOC,MAAAA,YAAY,OAAO,KAAK;AAAA,MAC/B,MAAM;AAAA,IAAA;AAAA,IAER;AAAA,EAAA;AAEJ;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;AAEO,SAAS,oBAAoB,EAAE,MAAM,eAAe;AAEzD,MACE,KAAK,YAAY,QACjB,KAAK,YAAY,QACjB,KAAK,UAAU,QACf,KAAK,UAAU;AAEf,WAAO;AAET,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,KAAK;AAChB,MAAI,SAAS,KAAK,UAAU;AAC5B,MAAI,SAAS,KAAK,UAAU;AAE5B,QAAM,cAAcC,aAAAA,kBAAkB,WAAW;AACjD,QAAM,OAAO,aAAa,IAAI,EAAE,KAAK,CAAA;AAErC,QAAM,YAA2B;AAAA,IAC/B,GAAG;AAAA,IACH,IAAI;AAAA,IACJ,MAAM,KAAK;AAAA,EAAA;AAGb,MAAI,KAAU;AACd,QAAM,OAAO,aAAa,IAAI,EAAE,KAAK,CAAA;AACrC,QAAM,KAAUJ,gBAAAA,QAAE,YAAY,EAAE,OAAO,QAAQ;AAE/C,MAAI,OAAO,MAAM,WAAW,KAAK,WAAW,GAAG;AAE7C,SAAKA,gBAAAA,QAAE,YAAY,EAAE,OAAO,QAAQ;AAAA,EACtC;AAEA,MAAI,OAAO,OAAO,WAAW,KAAK,WAAW,IAAI;AAC/C,SAAKA,gBAAAA,QAAE,yBAAyB,CAAC,IAAI,KAAKA,wBAAE,YAAY,IAAI,GAAG,KAAK,EAAE,CAAC;AAAA,EACzE;AAEA,QAAM,YAAY,eAAe;AAEjC,QAAM,cAAc,CAAC,UAAsB;AACzC,QAAI,aAAa;AACf,kBAAY,OAAO,SAAS;AAAA,IAC9B;AAAA,EACF;AAEA,SAAOA,gBAAAA,QAAEK,eAAAA,UAAU,EAAE,WAAW,0BAA0B;AAAA,IACxDL,gBAAAA,QAAEM,eAAAA,aAAa;AAAA,MACb,WAAW,YAAY,cAAc;AAAA,MACrC,SAAS,YAAY,cAAc;AAAA,MACnC,UAAU;AAAA,MACV,QAAQ;AAAA,IAAA,CACT;AAAA,IACDN,gBAAAA,QAAE,GAAG,MAAM,EAAE,EAAE,yBAAyB;AAAA,MACtCA,gBAAAA,QAAE,YAAY,MAAM;AAAA,MACpBA,gBAAAA,QAAEM,eAAAA,aAAa;AAAA,QACb,WAAW,YAAY,cAAc;AAAA,QACrC,SAAS,YAAY,cAAc;AAAA,QACnC,UAAU;AAAA,UACR,GAAG;AAAA,UACH,IAAI;AAAA,UACJ,MAAM,KAAK;AAAA,QAAA;AAAA,QAEb,QAAQ;AAAA,MAAA,CACT;AAAA,IAAA,CACF;AAAA,EAAA,CACF;AACH;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,SAAOP,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 { 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}\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 /** Get interval information */\n const intervalMap = useMacrostratDefs(\"intervals\");\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":"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"}
@@ -1,4 +1,6 @@
1
- export declare function AgeField({ unit, children }: {
1
+ import { IntervalTagProps } from '@macrostrat/data-components';
2
+ export declare function AgeField({ unit, children, ...rest }: {
3
+ [x: string]: any;
2
4
  unit: any;
3
5
  children: any;
4
6
  }): import('react').FunctionComponentElement<{
@@ -11,6 +13,18 @@ export declare function AgeField({ unit, children }: {
11
13
  unit?: string;
12
14
  row?: boolean;
13
15
  }>;
16
+ export declare function AgeRange({ data, className, }: {
17
+ data: {
18
+ t_age: number;
19
+ b_age: number;
20
+ };
21
+ className?: string;
22
+ }): import('react').FunctionComponentElement<{
23
+ value?: any;
24
+ unit?: string;
25
+ children?: any;
26
+ className?: string;
27
+ }>;
14
28
  export declare function AgeLabel({ age, maximumFractionDigits, minimumFractionDigits, className, }: {
15
29
  age: number;
16
30
  className?: string;
@@ -32,12 +46,25 @@ export declare function Duration({ value, maximumFractionDigits, minimumFraction
32
46
  children?: any;
33
47
  className?: string;
34
48
  }>;
35
- export declare function IntervalProportions({ unit, onClickItem }: {
36
- unit: any;
37
- onClickItem: any;
38
- }): import('react').FunctionComponentElement<{
49
+ interface UnitIntervalConstraints {
50
+ b_int_id?: number;
51
+ t_int_id?: number;
52
+ b_prop?: number;
53
+ t_prop?: number;
54
+ b_int_name?: string;
55
+ t_int_name?: string;
56
+ b_age?: number;
57
+ t_age?: number;
58
+ }
59
+ export interface IntervalProportionsProps extends Omit<IntervalTagProps, "interval"> {
60
+ unit: UnitIntervalConstraints;
61
+ showProportions?: boolean;
62
+ calculateProportionsFromAges?: boolean;
63
+ }
64
+ export declare function IntervalProportions({ unit, className, showProportions, calculateProportionsFromAges, ...rest }: IntervalProportionsProps): import('react').FunctionComponentElement<{
39
65
  children?: import('react').ReactNode;
40
66
  className: string;
41
67
  }>;
42
68
  export declare function getAgeRange(_unit: any): any[];
43
69
  export declare function getAge(value: any): any[];
70
+ export {};
@@ -2,18 +2,32 @@ import { DataField, Value, ItemList, IntervalTag } from "@macrostrat/data-compon
2
2
  import { useMacrostratDefs } from "@macrostrat/data-provider";
3
3
  import h from "./age-range.module.sass.js";
4
4
  import { formatRange, formatProportion } from "./utils.js";
5
- function AgeField({ unit, children }) {
6
- const [b_age, t_age, _unit] = getAgeRange(unit);
5
+ import classNames from "classnames";
6
+ import { useMemo } from "react";
7
+ function AgeField({ unit, children, ...rest }) {
8
+ const [_b_age, _t_age, _unit] = getAgeRange(unit);
7
9
  return h(
8
10
  DataField,
9
11
  {
10
12
  label: "Age",
11
- value: formatRange(b_age, t_age),
12
- unit: _unit
13
+ value: formatRange(_b_age, _t_age),
14
+ unit: _unit,
15
+ ...rest
13
16
  },
14
17
  children
15
18
  );
16
19
  }
20
+ function AgeRange({
21
+ data,
22
+ className
23
+ }) {
24
+ const [_b_age, _t_age, _unit] = getAgeRange(data);
25
+ return h(Value, {
26
+ value: formatRange(_b_age, _t_age),
27
+ unit: _unit,
28
+ className
29
+ });
30
+ }
17
31
  function AgeLabel({
18
32
  age,
19
33
  maximumFractionDigits = 2,
@@ -50,56 +64,81 @@ function Duration({
50
64
  });
51
65
  return h(Value, { value: _value, unit });
52
66
  }
53
- function IntervalProportions({ unit, onClickItem }) {
54
- if (unit.b_int_id == null && unit.t_int_id == null && unit.b_prop == null && unit.t_prop == null)
55
- return null;
67
+ function IntervalProportions({
68
+ unit,
69
+ className,
70
+ showProportions,
71
+ calculateProportionsFromAges = true,
72
+ ...rest
73
+ }) {
74
+ if (unit.b_int_id == null && unit.t_int_id == null) return null;
75
+ let _showProps = showProportions;
56
76
  const i0 = unit.b_int_id;
57
77
  const i1 = unit.t_int_id;
58
- let b_prop = unit.b_prop ?? 0;
59
- let t_prop = unit.t_prop ?? 1;
60
78
  const intervalMap = useMacrostratDefs("intervals");
61
- const int0 = intervalMap?.get(i0) ?? {};
79
+ const [int0, int1] = useMemo(() => {
80
+ const int02 = intervalMap?.get(i0) ?? {};
81
+ if (i0 === i1) {
82
+ return [int02, int02];
83
+ }
84
+ const int12 = intervalMap?.get(i1) ?? {};
85
+ return [int02, int12];
86
+ }, [intervalMap, i0, i1]);
62
87
  const interval0 = {
63
- ...int0,
64
88
  id: i0,
65
- name: unit.b_int_name
89
+ name: unit.b_int_name,
90
+ ...int0
66
91
  };
67
- let p0 = null;
68
- const int1 = intervalMap?.get(i1) ?? {};
69
- const p1 = h(Proportion, { value: t_prop });
70
- if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {
71
- p0 = h(Proportion, { value: b_prop });
92
+ let b_prop = unit.b_prop;
93
+ let t_prop = unit.t_prop;
94
+ if (b_prop == null && unit.b_age != null && calculateProportionsFromAges) {
95
+ b_prop = getProportion(unit.b_age, int0);
96
+ }
97
+ if (t_prop == null && unit.t_age != null && calculateProportionsFromAges) {
98
+ t_prop = getProportion(unit.t_age, int1);
72
99
  }
73
- if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {
74
- p0 = h("span.joint-proportion", [p0, " ", h("span.sep", "to"), " ", p1]);
100
+ if (b_prop == null && t_prop == null) {
101
+ _showProps ??= false;
75
102
  }
76
- const clickable = onClickItem != null;
77
- const handleClick = (event) => {
78
- if (onClickItem) {
79
- onClickItem(event, interval0);
103
+ b_prop ??= 0;
104
+ t_prop ??= 1;
105
+ let p0 = null;
106
+ let p1 = null;
107
+ if (_showProps !== false) {
108
+ p1 = h(Proportion, { value: t_prop });
109
+ if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {
110
+ p0 = h(Proportion, { value: b_prop });
80
111
  }
81
- };
82
- return h(ItemList, { className: "interval-proportions" }, [
83
- h(IntervalTag, {
84
- className: clickable ? "clickable" : "",
85
- onClick: clickable ? handleClick : void 0,
86
- interval: interval0,
87
- prefix: p0
88
- }),
89
- h.if(i0 != i1)("span.discourage-break", [
90
- h("span.sep", " to "),
112
+ if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {
113
+ p0 = h("span.joint-proportion", [p0, " ", h("span.sep", "to"), " ", p1]);
114
+ }
115
+ }
116
+ return h(
117
+ ItemList,
118
+ { className: classNames("interval-proportions", className) },
119
+ [
91
120
  h(IntervalTag, {
92
- className: clickable ? "clickable" : "",
93
- onClick: clickable ? handleClick : void 0,
94
- interval: {
95
- ...int1,
96
- id: i1,
97
- name: unit.t_int_name
98
- },
99
- prefix: p1
100
- })
101
- ])
102
- ]);
121
+ interval: interval0,
122
+ prefix: p0,
123
+ ...rest
124
+ }),
125
+ h.if(i0 != i1)("span.discourage-break", [
126
+ h("span.sep", " to "),
127
+ h(IntervalTag, {
128
+ interval: {
129
+ id: i1,
130
+ name: unit.t_int_name,
131
+ ...int1
132
+ },
133
+ prefix: p1,
134
+ ...rest
135
+ })
136
+ ])
137
+ ]
138
+ );
139
+ }
140
+ function getProportion(age, interval) {
141
+ return (interval.b_age - age) / (interval.b_age - interval.t_age);
103
142
  }
104
143
  function Proportion({ value }) {
105
144
  let content = null;
@@ -145,6 +184,7 @@ function getAge(value) {
145
184
  export {
146
185
  AgeField,
147
186
  AgeLabel,
187
+ AgeRange,
148
188
  Duration,
149
189
  IntervalProportions,
150
190
  getAge,