@macrostrat/column-views 3.3.5 → 3.4.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 (72) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/column.cjs +2 -1
  3. package/dist/column.cjs.map +1 -1
  4. package/dist/column.js +2 -1
  5. package/dist/column.js.map +1 -1
  6. package/dist/data-provider/unit-selection.cjs +7 -3
  7. package/dist/data-provider/unit-selection.cjs.map +1 -1
  8. package/dist/data-provider/unit-selection.d.ts +1 -0
  9. package/dist/data-provider/unit-selection.js +7 -3
  10. package/dist/data-provider/unit-selection.js.map +1 -1
  11. package/dist/facets/carbon-isotopes/data-area.cjs +0 -3
  12. package/dist/facets/carbon-isotopes/data-area.cjs.map +1 -1
  13. package/dist/facets/carbon-isotopes/data-area.js +0 -3
  14. package/dist/facets/carbon-isotopes/data-area.js.map +1 -1
  15. package/dist/index.cjs +13 -8
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.js +7 -2
  18. package/dist/index.js.map +1 -1
  19. package/dist/prepare-units/composite-scale.cjs +0 -1
  20. package/dist/prepare-units/composite-scale.cjs.map +1 -1
  21. package/dist/prepare-units/composite-scale.js +0 -1
  22. package/dist/prepare-units/composite-scale.js.map +1 -1
  23. package/dist/prepare-units/helpers.cjs +83 -49
  24. package/dist/prepare-units/helpers.cjs.map +1 -1
  25. package/dist/prepare-units/helpers.d.ts +19 -2
  26. package/dist/prepare-units/helpers.js +84 -50
  27. package/dist/prepare-units/helpers.js.map +1 -1
  28. package/dist/prepare-units/index.cjs.map +1 -1
  29. package/dist/prepare-units/index.js.map +1 -1
  30. package/dist/section.cjs +1 -2
  31. package/dist/section.cjs.map +1 -1
  32. package/dist/section.js +1 -2
  33. package/dist/section.js.map +1 -1
  34. package/dist/unit-details/identifiers.cjs +56 -0
  35. package/dist/unit-details/identifiers.cjs.map +1 -0
  36. package/dist/unit-details/identifiers.d.ts +31 -0
  37. package/dist/unit-details/identifiers.js +54 -0
  38. package/dist/unit-details/identifiers.js.map +1 -0
  39. package/dist/unit-details/index.d.ts +2 -0
  40. package/dist/unit-details/panel.cjs +11 -88
  41. package/dist/unit-details/panel.cjs.map +1 -1
  42. package/dist/unit-details/panel.d.ts +3 -19
  43. package/dist/unit-details/panel.js +10 -87
  44. package/dist/unit-details/panel.js.map +1 -1
  45. package/dist/unit-details/popover.cjs +1 -2
  46. package/dist/unit-details/popover.cjs.map +1 -1
  47. package/dist/unit-details/popover.js +2 -3
  48. package/dist/unit-details/popover.js.map +1 -1
  49. package/dist/unit-details/strat-names.cjs +44 -0
  50. package/dist/unit-details/strat-names.cjs.map +1 -0
  51. package/dist/unit-details/strat-names.d.ts +14 -0
  52. package/dist/unit-details/strat-names.js +42 -0
  53. package/dist/unit-details/strat-names.js.map +1 -0
  54. package/dist/units/index.cjs +19 -6
  55. package/dist/units/index.cjs.map +1 -1
  56. package/dist/units/index.d.ts +11 -20
  57. package/dist/units/index.js +19 -6
  58. package/dist/units/index.js.map +1 -1
  59. package/package.json +14 -14
  60. package/src/column.ts +1 -1
  61. package/src/data-provider/unit-selection.ts +8 -4
  62. package/src/facets/carbon-isotopes/data-area.ts +0 -3
  63. package/src/prepare-units/composite-scale.ts +1 -1
  64. package/src/prepare-units/helpers.ts +121 -72
  65. package/src/prepare-units/index.ts +1 -1
  66. package/src/section.ts +0 -1
  67. package/src/unit-details/identifiers.ts +67 -0
  68. package/src/unit-details/index.ts +2 -0
  69. package/src/unit-details/panel.ts +13 -126
  70. package/src/unit-details/popover.ts +2 -7
  71. package/src/unit-details/strat-names.ts +57 -0
  72. package/src/units/index.ts +28 -8
@@ -37,9 +37,6 @@ const IsotopesDataArea = function (props: DataAreaProps) {
37
37
  let { corrected, system, children, getHeight, clipY = false } = props;
38
38
  if (getHeight == null) {
39
39
  getHeight = function (d) {
40
- if (d.height == null) {
41
- console.log(d);
42
- }
43
40
  return d.height;
44
41
  };
45
42
  }
@@ -346,7 +346,7 @@ export function createCompositeScale(
346
346
  pixelHeight > Math.min(...range) &&
347
347
  pixelHeight <= Math.max(...range)
348
348
  ) {
349
- console.log("Inverting scale at pixel height", pixelHeight);
349
+ //console.log("Inverting scale at pixel height", pixelHeight);
350
350
  return scale.invert(pixelHeight);
351
351
  }
352
352
  }
@@ -16,95 +16,143 @@ import type { ExtUnit, SectionInfo, StratigraphicPackage } from "./types";
16
16
 
17
17
  const dt = 0.001;
18
18
 
19
- export function preprocessUnits<T extends UnitLong = UnitLong>(
20
- section: SectionInfo<T>,
21
- axisType: ColumnAxisType = ColumnAxisType.AGE,
22
- ): ExtUnit[] {
23
- /** Preprocess units to add overlapping units and columns. */
24
- let units = section.units;
19
+ export type UnitWithDefinedOverlap<T extends BaseUnit> = T & {
20
+ overlap: UnitOverlapInfo<T>;
21
+ };
25
22
 
26
- let divisions = units.map((...args) => extendDivision(...args, axisType));
27
- for (let d of divisions) {
28
- const overlappingUnits = divisions.filter((u) =>
29
- d.overlappingUnits.includes(u.unit_id),
30
- );
23
+ type UnitOverlapInfo<T extends BaseUnit> = {
24
+ column: number;
25
+ nColumns: number;
26
+ unitGroup: UnitGroup<T>;
27
+ };
31
28
 
32
- // Overlapping columns
33
- const columns = overlappingUnits.map((d) => d.column);
29
+ class UnitGroup<T extends BaseUnit> implements StratigraphicPackage {
30
+ units: T[];
34
31
 
35
- if (columns.includes(d.column)) {
36
- let col = 0;
37
- // Go through columns to find a better index
38
- while (columns.includes(col)) {
39
- col++;
40
- }
41
- d.column ??= col;
42
- }
32
+ constructor(units: T[]) {
33
+ this.units = units;
34
+ }
43
35
 
44
- // If unit overlaps the edges of a section, set the clip positions
45
- const [b_pos, t_pos] = getUnitHeightRange(d, axisType);
46
- if (axisType == ColumnAxisType.AGE) {
47
- if (b_pos > section.b_age) {
48
- d.b_clip_pos = section.b_age;
49
- }
50
- if (t_pos < section.t_age) {
51
- d.t_clip_pos = section.t_age;
36
+ get t_age(): number {
37
+ return Math.min(...this.units.map((d) => d.t_age));
38
+ }
39
+
40
+ get b_age(): number {
41
+ return Math.max(...this.units.map((d) => d.b_age));
42
+ }
43
+
44
+ getUnits(): UnitWithDefinedOverlap<T>[] {
45
+ return assignColumnsToUnitsWithinOverlappingGroup(this);
46
+ }
47
+ }
48
+
49
+ function groupUnitsByMutualOverlap<T extends BaseUnit>(
50
+ units: T[],
51
+ tolerance: number = dt,
52
+ ): UnitGroup<T>[] {
53
+ /** Group units within a section that have mutual overlap. */
54
+ const sections = groupUnitsIntoSectionsByOverlap(
55
+ units,
56
+ ColumnAxisType.AGE,
57
+ tolerance,
58
+ );
59
+ return sections.map((d) => {
60
+ return new UnitGroup(d.units);
61
+ });
62
+ }
63
+
64
+ const sortByAge = createUnitSorter(ColumnAxisType.AGE);
65
+
66
+ function assignColumnsToUnitsWithinOverlappingGroup<T extends BaseUnit>(
67
+ group: UnitGroup<T>,
68
+ ): UnitWithDefinedOverlap<T>[] {
69
+ /** A relatively naïve function to assign columns to units within a mutually overlapping group.
70
+ * This gets the number of columns that would be needed to accommodate the units in the group.
71
+ * It then assigns columns to units in the group based on the number of columns needed, with
72
+ * lower units further to the left.
73
+ */
74
+
75
+ const sortedUnits = [...group.units].sort((a, b) => b.b_age - a.b_age);
76
+
77
+ const columns: T[][] = [];
78
+
79
+ for (const unit of sortedUnits) {
80
+ // Find a column that is not already occupied by an overlapping unit
81
+ let didAddToExistingColumn = false;
82
+ for (const column of columns) {
83
+ const lastUnit = column[column.length - 1];
84
+ if (!unitsOverlap(unit, lastUnit, ColumnAxisType.AGE, dt)) {
85
+ column.push(unit);
86
+ didAddToExistingColumn = true;
87
+ break;
52
88
  }
53
89
  }
54
- if (axisType == ColumnAxisType.DEPTH) {
55
- if (b_pos > section.b_pos) {
56
- d.b_clip_pos = section.b_pos;
57
- }
58
- if (t_pos < section.t_pos) {
59
- d.t_clip_pos = section.t_pos;
60
- }
90
+ if (!didAddToExistingColumn) {
91
+ columns.push([unit]);
61
92
  }
62
- // if (axisType == ColumnAxisType.HEIGHT) {
63
- // if (b_pos < section.b_pos) {
64
- // d.b_clip_pos = section.b_pos;
65
- // }
66
- // if (t_pos > section.t_pos) {
67
- // d.t_clip_pos = section.t_pos;
68
- // }
69
- // }
70
93
  }
71
94
 
72
- return divisions;
95
+ const units: UnitWithDefinedOverlap<T>[] = columns.flatMap(
96
+ (column, columnIndex) =>
97
+ column.map((unit) => {
98
+ return {
99
+ ...unit,
100
+ overlap: {
101
+ column: columnIndex,
102
+ nColumns: columns.length,
103
+ unitGroup: group,
104
+ },
105
+ };
106
+ }),
107
+ );
108
+
109
+ return units.toSorted(sortByAge);
73
110
  }
74
111
 
75
- function extendDivision(
76
- unit: UnitLong,
77
- i: number,
78
- divisions: UnitLong[],
112
+ export function preprocessUnits<T extends UnitLong = UnitLong>(
113
+ section: SectionInfo<T>,
79
114
  axisType: ColumnAxisType = ColumnAxisType.AGE,
80
- ): ExtUnit {
81
- // TODO: make this configurable
115
+ ): ExtUnit[] {
116
+ /** Preprocess units to add overlapping units and columns. */
117
+ let units = section.units;
118
+
82
119
  let tolerance = 0.001; // 1 kyr tolerance for age columns
83
120
  if (axisType != ColumnAxisType.AGE) {
84
121
  tolerance = 0.01; // 1cm tolerance for height/depth columns
85
122
  }
86
123
 
87
- const overlappingUnits = divisions.filter(
88
- (d) =>
89
- d.unit_id != unit.unit_id && unitsOverlap(unit, d, axisType, tolerance),
90
- );
91
- const u_pos = getUnitHeightRange(unit, axisType);
92
- const bottomOverlap = overlappingUnits.some((d) => {
93
- const d_pos = getUnitHeightRange(d, axisType);
94
- // Check if the unit is below the current unit
95
- return d_pos[0] < u_pos[0] + dt;
96
- });
97
- let column = 0;
98
- if (overlappingUnits.length == 1) {
99
- column = 1;
124
+ const unitGroups = groupUnitsByMutualOverlap(units, tolerance);
125
+
126
+ const divisions: any[] = [];
127
+ // Serialize all groups' units to a single array
128
+ for (const group of unitGroups) {
129
+ divisions.push(...group.getUnits());
100
130
  }
101
131
 
102
- return {
103
- ...unit,
104
- bottomOverlap,
105
- column: unit.column ?? column,
106
- overlappingUnits: overlappingUnits.map((d) => d.unit_id),
107
- };
132
+ return divisions.map((d) =>
133
+ enhanceUnitWithClippingPosition(section, d, axisType),
134
+ );
135
+ }
136
+
137
+ export function enhanceUnitWithClippingPosition(section, d, axisType) {
138
+ const [b_pos, t_pos] = getUnitHeightRange(d, axisType);
139
+ if (axisType == ColumnAxisType.AGE) {
140
+ if (b_pos > section.b_age) {
141
+ d.b_clip_pos = section.b_age;
142
+ }
143
+ if (t_pos < section.t_age) {
144
+ d.t_clip_pos = section.t_age;
145
+ }
146
+ }
147
+ if (axisType == ColumnAxisType.DEPTH) {
148
+ if (b_pos > section.b_pos) {
149
+ d.b_clip_pos = section.b_pos;
150
+ }
151
+ if (t_pos < section.t_pos) {
152
+ d.t_clip_pos = section.t_pos;
153
+ }
154
+ }
155
+ return d;
108
156
  }
109
157
 
110
158
  export function groupUnitsIntoSectionsBySectionID<T extends UnitLong>(
@@ -141,9 +189,10 @@ interface WorkingSection {
141
189
  heightRange?: [number, number];
142
190
  }
143
191
 
144
- export function groupUnitsIntoSectionsByOverlap<T extends UnitLong>(
192
+ export function groupUnitsIntoSectionsByOverlap<T extends BaseUnit>(
145
193
  units: T[],
146
194
  axisType: ColumnAxisType = ColumnAxisType.AGE,
195
+ tolerance: number = dt,
147
196
  ): SectionInfo<T>[] {
148
197
  /** Group units into sections by overlap.
149
198
  * This creates "synthetic" sections that correspond to packages bound by scale gaps.
@@ -157,7 +206,7 @@ export function groupUnitsIntoSectionsByOverlap<T extends UnitLong>(
157
206
  const heightRange = getUnitHeightRange(unit, axisType);
158
207
  let section: WorkingSection | undefined = sectionList.find(
159
208
  (s) =>
160
- compareAgeRanges(heightRange, s.heightRange) !==
209
+ compareAgeRanges(heightRange, s.heightRange, tolerance) !==
161
210
  AgeRangeRelationship.Disjoint,
162
211
  );
163
212
  if (section == null) {
@@ -59,7 +59,7 @@ export function prepareColumnUnits(
59
59
  scale,
60
60
  } = options;
61
61
 
62
- let _totalHeight = null;
62
+ let _totalHeight: number | null = null;
63
63
 
64
64
  if (scale != null) {
65
65
  // Set t_age and b_age based on scale domain if not already set
package/src/section.ts CHANGED
@@ -164,7 +164,6 @@ function SectionUnits(props: SectionProps) {
164
164
  nColumns: Math.min(
165
165
  maxInternalColumns ?? Math.floor(width / 10),
166
166
  unitComponentProps?.nColumns ?? Infinity,
167
- Math.max(...units.map((d) => d.column)) + 1,
168
167
  ),
169
168
  //axisType,
170
169
  };
@@ -0,0 +1,67 @@
1
+ import { isClickable, ItemInteractionProps } from "@macrostrat/data-components";
2
+ import h from "./panel.module.sass";
3
+ import { ReactNode } from "react";
4
+ import classNames from "classnames";
5
+
6
+ export function ClickableText({
7
+ className,
8
+ ...rest
9
+ }: {
10
+ className?: string;
11
+ children: ReactNode;
12
+ } & ItemInteractionProps) {
13
+ /** An optionally clickable text element */
14
+ const clickable = isClickable(rest);
15
+ const tag = clickable ? "a" : "span";
16
+ return h(tag, { className: classNames(className, { clickable }), ...rest });
17
+ }
18
+
19
+ export function Identifier({
20
+ id,
21
+ className,
22
+ ...rest
23
+ }: {
24
+ id: number | string;
25
+ className?: string;
26
+ } & ItemInteractionProps) {
27
+ /** An item that displays a numeric identifier, optionally clickable */
28
+ return h(
29
+ ClickableText,
30
+ {
31
+ className: classNames("identifier", className),
32
+ ...rest,
33
+ },
34
+ id,
35
+ );
36
+ }
37
+
38
+ export type UnitInfo = {
39
+ unitID: number;
40
+ colID?: number;
41
+ name?: string;
42
+ };
43
+
44
+ export function UnitIdentifier({
45
+ unitID,
46
+ colID,
47
+ name,
48
+ ...interactionProps
49
+ }: UnitInfo & ItemInteractionProps) {
50
+ if (name != null) {
51
+ return h(
52
+ ClickableText,
53
+ {
54
+ className: "unit-name",
55
+ ...interactionProps,
56
+ },
57
+ name,
58
+ );
59
+ }
60
+
61
+ return h(Identifier, {
62
+ className: "unit-id",
63
+ key: unitID,
64
+ id: unitID,
65
+ ...interactionProps,
66
+ });
67
+ }
@@ -2,3 +2,5 @@ export * from "./panel";
2
2
  export * from "./popover";
3
3
  export * from "./modal-panel";
4
4
  export * from "./age-range";
5
+ export * from "./strat-names";
6
+ export * from "./identifiers";
@@ -4,8 +4,6 @@ import { ReactNode, useMemo, useState } from "react";
4
4
  import {
5
5
  DataField,
6
6
  EnvironmentsList,
7
- isClickable,
8
- ItemInteractionProps,
9
7
  ItemList,
10
8
  LithologyList,
11
9
  LithologyTagFeature,
@@ -14,7 +12,6 @@ import {
14
12
  MacrostratItemIdentifier,
15
13
  Parenthetical,
16
14
  useInteractionManager,
17
- useInteractionProps,
18
15
  Value,
19
16
  } from "@macrostrat/data-components";
20
17
  import { useColumnUnitsMap } from "../data-provider";
@@ -22,13 +19,12 @@ import {
22
19
  useMacrostratColumnInfo,
23
20
  useMacrostratData,
24
21
  useMacrostratDefs,
25
- useStratNames,
26
22
  } from "@macrostrat/data-provider";
27
23
  import type {
28
24
  Environment,
25
+ EnvironmentIdentifier,
29
26
  Interval,
30
27
  Lithology,
31
- UnitLithology,
32
28
  UnitLong,
33
29
  UnitLongFull,
34
30
  } from "@macrostrat/api-types";
@@ -37,6 +33,9 @@ import classNames from "classnames";
37
33
  import { AgeField, Duration, IntervalProportions } from "./age-range";
38
34
  import { formatRange, formatSignificance } from "./utils.ts";
39
35
  import h from "./panel.module.sass";
36
+ import { StratNameField } from "./strat-names.ts";
37
+ import { Identifier, UnitIdentifier, UnitInfo } from "./identifiers.ts";
38
+ import { LithologyIdentifier } from "@macrostrat/api-types/src/lithologies";
40
39
 
41
40
  export interface UnitDetailsPanelProps {
42
41
  unit: any;
@@ -49,6 +48,7 @@ export interface UnitDetailsPanelProps {
49
48
  onSelectUnit?: (unitID: number) => void;
50
49
  onClickItem?: MacrostratItemClickHandler;
51
50
  interactionManager?: MacrostratInteractionManager;
51
+ showJSON?: boolean;
52
52
  }
53
53
 
54
54
  export function UnitDetailsPanel({
@@ -66,11 +66,12 @@ export function UnitDetailsPanel({
66
66
  hiddenActions = null,
67
67
  onSelectUnit,
68
68
  onClickItem,
69
+ showJSON,
69
70
  }: UnitDetailsPanelProps) {
70
- const [showJSON, setShowJSON] = useState(false);
71
+ const [_showJSON, setShowJSON] = useState(false);
71
72
 
72
73
  let content: ReactNode = null;
73
- if (showJSON) {
74
+ if (showJSON ?? _showJSON) {
74
75
  content = h(JSONView, { data: unit, showRoot: false });
75
76
  } else {
76
77
  content = h(UnitDetailsContent, {
@@ -113,7 +114,7 @@ export function UnitDetailsPanel({
113
114
 
114
115
  /** Handle unit selection clicks */
115
116
  const clickHandlerForItem = useMemo(() => {
116
- if (onSelectUnit == null || onClickItem == null) return null;
117
+ if (onSelectUnit == null && onClickItem == null) return null;
117
118
  return (item: MacrostratItemIdentifier) => {
118
119
  if ("unit_id" in item && !("col_id" in item)) {
119
120
  // We are selecting a unit within the column
@@ -367,53 +368,7 @@ export function ReferencesField({ refs, className = null, ...rest }) {
367
368
  );
368
369
  }
369
370
 
370
- function useStratNameData(strat_name_id: number) {
371
- const stratNames = useStratNames([strat_name_id]);
372
- return stratNames?.[0];
373
- }
374
-
375
- function StratNameField(
376
- props: {
377
- strat_name_id: number;
378
- className?: string;
379
- } & ItemInteractionProps,
380
- ) {
381
- /** Handling for stratigraphic name field */
382
- const { strat_name_id, className, ...rest } = props;
383
- const data = useStratNameData(strat_name_id);
384
-
385
- const baseInteractionProps = useInteractionProps({ strat_name_id });
386
-
387
- const coreProps = {
388
- ...baseInteractionProps,
389
- ...rest,
390
- };
391
-
392
- let inner: any = h(Identifier, { id: strat_name_id });
393
- const name = data?.strat_name_long;
394
- if (name != null) {
395
- inner = h("span.strat-name", name);
396
- }
397
-
398
- const clickable = isClickable(coreProps);
399
-
400
- return h(
401
- DataField,
402
- {
403
- label: "Stratigraphic name",
404
- },
405
- h(
406
- clickable ? "a" : "span",
407
- {
408
- className: classNames({ clickable }, className),
409
- ...coreProps,
410
- },
411
- inner,
412
- ),
413
- );
414
- }
415
-
416
- function getThickness(unit): [string, string] {
371
+ function getThickness(unit): [string, string | null] {
417
372
  let minThickness = unit.min_thick ?? 0;
418
373
  let maxThickness = unit.max_thick ?? unit.min_thick ?? 0;
419
374
  let _unit = "m";
@@ -484,7 +439,7 @@ function Citation({ data, tag = "p" }) {
484
439
  }
485
440
 
486
441
  function enhanceEnvironments(
487
- environments?: Partial<Environment>[] | null,
442
+ environments?: EnvironmentIdentifier[] | null,
488
443
  envMap?: Map<number, Environment> | null,
489
444
  ) {
490
445
  return environments?.map((env) => {
@@ -495,13 +450,8 @@ function enhanceEnvironments(
495
450
  });
496
451
  }
497
452
 
498
- type LithID =
499
- | (Partial<Lithology> & Pick<Lithology, "lith_id">)
500
- | UnitLithology
501
- | Lithology;
502
-
503
453
  function enhanceLithologies(
504
- lithologies?: LithID[] | null,
454
+ lithologies?: LithologyIdentifier[] | null,
505
455
  lithMap?: Map<number, any> | null,
506
456
  ) {
507
457
  return lithologies?.map((lith) => {
@@ -512,44 +462,6 @@ function enhanceLithologies(
512
462
  });
513
463
  }
514
464
 
515
- export function ClickableText({
516
- className,
517
- ...rest
518
- }: {
519
- className?: string;
520
- children: ReactNode;
521
- } & ItemInteractionProps) {
522
- /** An optionally clickable text element */
523
- const clickable = isClickable(rest);
524
- const tag = clickable ? "a" : "span";
525
- return h(tag, { className: classNames(className, { clickable }), ...rest });
526
- }
527
-
528
- export function Identifier({
529
- id,
530
- className,
531
- ...rest
532
- }: {
533
- id: number | string;
534
- className?: string;
535
- } & ItemInteractionProps) {
536
- /** An item that displays a numeric identifier, optionally clickable */
537
- return h(
538
- ClickableText,
539
- {
540
- className: classNames("identifier", className),
541
- ...rest,
542
- },
543
- id,
544
- );
545
- }
546
-
547
- type UnitInfo = {
548
- unitID: number;
549
- colID?: number;
550
- name?: string;
551
- };
552
-
553
465
  function UnitIDList({ units, showNames = false }) {
554
466
  const unitsMap = useColumnUnitsMap();
555
467
 
@@ -560,7 +472,7 @@ function UnitIDList({ units, showNames = false }) {
560
472
  if (showNames) {
561
473
  return u1.map((unitID) => {
562
474
  const unitData = unitsMap?.get(unitID);
563
- let name: string = undefined;
475
+ let name: string | null = null;
564
476
  if (unitData != null) {
565
477
  name = defaultNameFunction(unitData);
566
478
  }
@@ -595,28 +507,3 @@ function UnitIDList({ units, showNames = false }) {
595
507
  }),
596
508
  );
597
509
  }
598
-
599
- function UnitIdentifier({
600
- unitID,
601
- colID,
602
- name,
603
- ...interactionProps
604
- }: UnitInfo & ItemInteractionProps) {
605
- if (name != null) {
606
- return h(
607
- ClickableText,
608
- {
609
- className: "unit-name",
610
- ...interactionProps,
611
- },
612
- name,
613
- );
614
- }
615
-
616
- return h(Identifier, {
617
- className: "unit-id",
618
- key: unitID,
619
- id: unitID,
620
- ...interactionProps,
621
- });
622
- }
@@ -1,11 +1,7 @@
1
1
  import hyper from "@macrostrat/hyper";
2
2
  import { Popover } from "@blueprintjs/core";
3
3
  import styles from "./popover.module.sass";
4
- import {
5
- useAtomOverlayPosition,
6
- useSelectedUnit,
7
- useUnitSelectionDispatch,
8
- } from "../data-provider";
4
+ import { useAtomOverlayPosition, useUnitSelection } from "../data-provider";
9
5
  import {
10
6
  UnitDetailsFeature,
11
7
  UnitDetailsPanel,
@@ -66,8 +62,7 @@ function InteractionBarrier({ children }) {
66
62
  export function UnitSelectionPopover(
67
63
  props: Omit<UnitDetailsPanelProps, "onSelectUnit" | "unit">,
68
64
  ) {
69
- const unit = useSelectedUnit();
70
- const selectUnit = useUnitSelectionDispatch();
65
+ const [unit, selectUnit] = useUnitSelection();
71
66
  const position = useAtomOverlayPosition();
72
67
  if (unit == null) {
73
68
  return null;
@@ -0,0 +1,57 @@
1
+ import {
2
+ DataField,
3
+ isClickable,
4
+ ItemInteractionProps,
5
+ useInteractionProps,
6
+ } from "@macrostrat/data-components";
7
+ import h from "./panel.module.sass";
8
+ import classNames from "classnames";
9
+ import { useStratNames } from "@macrostrat/data-provider";
10
+ import { Identifier } from "./identifiers.ts";
11
+
12
+ function useStratNameData(strat_name_id: number) {
13
+ const stratNames = useStratNames([strat_name_id]);
14
+ return stratNames?.[0];
15
+ }
16
+
17
+ export function StratNameField(
18
+ props: {
19
+ strat_name_id: number;
20
+ className?: string;
21
+ } & ItemInteractionProps,
22
+ ) {
23
+ /** Handling for stratigraphic name field */
24
+ const { strat_name_id, className, ...rest } = props;
25
+
26
+ const data = useStratNameData(strat_name_id);
27
+
28
+ const baseInteractionProps = useInteractionProps({ strat_name_id });
29
+
30
+ const coreProps = {
31
+ ...baseInteractionProps,
32
+ ...rest,
33
+ };
34
+
35
+ let inner: any = h(Identifier, { id: strat_name_id });
36
+ const name = data?.strat_name_long;
37
+ if (name != null) {
38
+ inner = h("span.strat-name", name);
39
+ }
40
+
41
+ const clickable = isClickable(coreProps);
42
+
43
+ return h(
44
+ DataField,
45
+ {
46
+ label: "Stratigraphic name",
47
+ },
48
+ h(
49
+ clickable ? "a" : "span",
50
+ {
51
+ className: classNames({ clickable }, className),
52
+ ...coreProps,
53
+ },
54
+ inner,
55
+ ),
56
+ );
57
+ }