@macrostrat/column-views 1.0.2 → 2.0.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.
Files changed (242) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/esm/_shared.f7eec55a.js +9 -0
  3. package/dist/esm/_shared.f7eec55a.js.map +1 -0
  4. package/dist/esm/age-axis.4a8cf5e6.js +98 -0
  5. package/dist/esm/age-axis.4a8cf5e6.js.map +1 -0
  6. package/dist/esm/age-axis.module.03773a80.css +33 -0
  7. package/dist/esm/age-axis.module.03773a80.css.map +1 -0
  8. package/dist/esm/age-axis.module.3cc91335.js +22 -0
  9. package/dist/esm/age-axis.module.3cc91335.js.map +1 -0
  10. package/dist/esm/age-model-overlay.c7226855.js +57 -0
  11. package/dist/esm/age-model-overlay.c7226855.js.map +1 -0
  12. package/dist/esm/age-model-overlay.module.5d9e78fb.css +14 -0
  13. package/dist/esm/age-model-overlay.module.5d9e78fb.css.map +1 -0
  14. package/dist/esm/age-model-overlay.module.cd985dcb.js +16 -0
  15. package/dist/esm/age-model-overlay.module.cd985dcb.js.map +1 -0
  16. package/dist/esm/base.910b80b4.js +288 -0
  17. package/dist/esm/base.910b80b4.js.map +1 -0
  18. package/dist/esm/boxes.8292cff2.js +258 -0
  19. package/dist/esm/boxes.8292cff2.js.map +1 -0
  20. package/dist/esm/boxes.module.2b5fb18e.css +26 -0
  21. package/dist/esm/boxes.module.2b5fb18e.css.map +1 -0
  22. package/dist/esm/boxes.module.4ebc7796.js +19 -0
  23. package/dist/esm/boxes.module.4ebc7796.js.map +1 -0
  24. package/dist/esm/{carbon-isotopes.3b502a9e.js → carbon-isotopes.10db8285.js} +2 -2
  25. package/dist/esm/{carbon-isotopes.3b502a9e.js.map → carbon-isotopes.10db8285.js.map} +1 -1
  26. package/dist/esm/colors.395c6db5.js +40 -0
  27. package/dist/esm/colors.395c6db5.js.map +1 -0
  28. package/dist/esm/column-correlation.c8dcfe98.js +9 -0
  29. package/dist/esm/column-correlation.c8dcfe98.js.map +1 -0
  30. package/dist/esm/column-nav.5414677c.js +55 -0
  31. package/dist/esm/column-nav.5414677c.js.map +1 -0
  32. package/dist/esm/column-navigation.37cd3245.js +9 -0
  33. package/dist/esm/column-navigation.37cd3245.js.map +1 -0
  34. package/dist/esm/column.01d68dd8.js +127 -0
  35. package/dist/esm/column.01d68dd8.js.map +1 -0
  36. package/dist/esm/{column.db058031.js → column.a25f8ebd.js} +4 -4
  37. package/dist/esm/column.a25f8ebd.js.map +1 -0
  38. package/dist/esm/column.module.1b776e15.js +46 -0
  39. package/dist/esm/column.module.1b776e15.js.map +1 -0
  40. package/dist/esm/column.module.a67a6b4c.css +159 -0
  41. package/dist/esm/column.module.a67a6b4c.css.map +1 -0
  42. package/dist/esm/composite-scale.577bf64a.js +222 -0
  43. package/dist/esm/composite-scale.577bf64a.js.map +1 -0
  44. package/dist/esm/composite.039e4798.js +163 -0
  45. package/dist/esm/composite.039e4798.js.map +1 -0
  46. package/dist/esm/{core.4db8e452.js → core.843310d3.js} +11 -12
  47. package/dist/esm/core.843310d3.js.map +1 -0
  48. package/dist/esm/core.91ede078.js +206 -0
  49. package/dist/esm/core.91ede078.js.map +1 -0
  50. package/dist/esm/correlation-chart.abd8b346.js +9 -0
  51. package/dist/esm/correlation-chart.abd8b346.js.map +1 -0
  52. package/dist/esm/data-provider.1506eb64.js.map +1 -1
  53. package/dist/esm/data-provider.f10c6d0b.js +13 -0
  54. package/dist/esm/data-provider.f10c6d0b.js.map +1 -0
  55. package/dist/esm/fetch.99aec438.js +152 -0
  56. package/dist/esm/fetch.99aec438.js.map +1 -0
  57. package/dist/esm/hash-string.285b37fb.js +39 -0
  58. package/dist/esm/hash-string.285b37fb.js.map +1 -0
  59. package/dist/esm/helpers.2f0a0cb7.js +141 -0
  60. package/dist/esm/helpers.2f0a0cb7.js.map +1 -0
  61. package/dist/esm/index.d.ts +797 -120
  62. package/dist/esm/index.d.ts.map +1 -1
  63. package/dist/esm/index.js +14 -8
  64. package/dist/esm/index.js.map +1 -1
  65. package/dist/esm/inset-map.3c18106d.js +66 -0
  66. package/dist/esm/inset-map.3c18106d.js.map +1 -0
  67. package/dist/esm/keyboard-navigation.6713401b.js +48 -0
  68. package/dist/esm/keyboard-navigation.6713401b.js.map +1 -0
  69. package/dist/esm/keyboard-navigation.a9fc80dd.js +112 -0
  70. package/dist/esm/keyboard-navigation.a9fc80dd.js.map +1 -0
  71. package/dist/esm/layers.033d3fb0.js +170 -0
  72. package/dist/esm/layers.033d3fb0.js.map +1 -0
  73. package/dist/esm/main.2e0375a5.js +221 -0
  74. package/dist/esm/main.2e0375a5.js.map +1 -0
  75. package/dist/esm/main.module.3dd9500b.css +134 -0
  76. package/dist/esm/main.module.3dd9500b.css.map +1 -0
  77. package/dist/esm/main.module.c09154b1.js +70 -0
  78. package/dist/esm/main.module.c09154b1.js.map +1 -0
  79. package/dist/esm/mapbox.cac42eed.js +167 -0
  80. package/dist/esm/mapbox.cac42eed.js.map +1 -0
  81. package/dist/esm/maps.bcdea9c1.js +11 -0
  82. package/dist/esm/maps.bcdea9c1.js.map +1 -0
  83. package/dist/esm/{names.f6a4e9a4.js → names.a8f2b452.js} +5 -5
  84. package/dist/esm/names.a8f2b452.js.map +1 -0
  85. package/dist/esm/panel.598f76a5.js +420 -0
  86. package/dist/esm/panel.598f76a5.js.map +1 -0
  87. package/dist/esm/panel.module.386166cc.js +58 -0
  88. package/dist/esm/panel.module.386166cc.js.map +1 -0
  89. package/dist/esm/panel.module.3d2ea3c6.css +111 -0
  90. package/dist/esm/panel.module.3d2ea3c6.css.map +1 -0
  91. package/dist/esm/popover.a810b7bc.js +66 -0
  92. package/dist/esm/popover.a810b7bc.js.map +1 -0
  93. package/dist/esm/popover.module.c4ba4189.js +22 -0
  94. package/dist/esm/popover.module.c4ba4189.js.map +1 -0
  95. package/dist/esm/{selection-popover.module.0a701258.css → popover.module.c4d6bfb0.css} +11 -8
  96. package/dist/esm/popover.module.c4d6bfb0.css.map +1 -0
  97. package/dist/esm/prepare-data.d4284b4a.js +125 -0
  98. package/dist/esm/prepare-data.d4284b4a.js.map +1 -0
  99. package/dist/esm/prepare-units.6c890a96.js +104 -0
  100. package/dist/esm/prepare-units.6c890a96.js.map +1 -0
  101. package/dist/esm/{resolvers.b5c82b78.js → resolvers.36013b49.js} +13 -2
  102. package/dist/esm/resolvers.36013b49.js.map +1 -0
  103. package/dist/esm/section.a34d379a.js +215 -0
  104. package/dist/esm/section.a34d379a.js.map +1 -0
  105. package/dist/esm/selection.f5b0297e.js +143 -0
  106. package/dist/esm/selection.f5b0297e.js.map +1 -0
  107. package/dist/esm/state.178ef364.js +75 -0
  108. package/dist/esm/state.178ef364.js.map +1 -0
  109. package/dist/esm/state.2952cbca.js +118 -0
  110. package/dist/esm/state.2952cbca.js.map +1 -0
  111. package/dist/esm/store.c4d7a8a4.js +52 -0
  112. package/dist/esm/store.c4d7a8a4.js.map +1 -0
  113. package/dist/esm/styles.7bc776d1.js +95 -0
  114. package/dist/esm/styles.7bc776d1.js.map +1 -0
  115. package/dist/esm/svg.4b9a96c1.js +89 -0
  116. package/dist/esm/svg.4b9a96c1.js.map +1 -0
  117. package/dist/esm/types.0f0b57c9.js +3 -0
  118. package/dist/esm/types.0f0b57c9.js.map +1 -0
  119. package/dist/esm/unit-details.071cefed.js +9 -0
  120. package/dist/esm/unit-details.071cefed.js.map +1 -0
  121. package/dist/esm/units.5a4fc058.js +98 -0
  122. package/dist/esm/units.5a4fc058.js.map +1 -0
  123. package/dist/esm/utils.d7a43a2a.js +55 -0
  124. package/dist/esm/utils.d7a43a2a.js.map +1 -0
  125. package/dist/node/index.js.map +1 -1
  126. package/package.json +24 -7
  127. package/src/age-axis.module.sass +27 -0
  128. package/src/age-axis.ts +82 -19
  129. package/src/age-model-overlay.module.sass +11 -0
  130. package/src/age-model-overlay.ts +73 -0
  131. package/src/carbon-isotopes/column.ts +4 -2
  132. package/src/carbon-isotopes/core.ts +9 -6
  133. package/src/carbon-isotopes/data-provider.ts +3 -3
  134. package/src/column.module.sass +58 -49
  135. package/src/column.ts +149 -135
  136. package/src/correlation-chart/hash-string.ts +57 -0
  137. package/src/correlation-chart/index.ts +2 -0
  138. package/src/correlation-chart/main.module.sass +122 -0
  139. package/src/correlation-chart/main.ts +305 -0
  140. package/src/correlation-chart/prepare-data.ts +217 -0
  141. package/src/correlation-chart/stories/correlation-chart.stories.ts +192 -0
  142. package/src/correlation-chart/stories/stories.module.sass +18 -0
  143. package/src/correlation-chart/unconformity-line.module.sass +8 -0
  144. package/src/correlation-chart/unconformity-line.ts +25 -0
  145. package/src/data-provider/base.ts +388 -0
  146. package/src/data-provider/column-nav.ts +53 -0
  147. package/src/data-provider/fetch.ts +231 -0
  148. package/src/data-provider/index.ts +4 -0
  149. package/src/data-provider/store.ts +72 -0
  150. package/src/index.ts +6 -3
  151. package/src/maps/_shared/index.ts +2 -0
  152. package/src/maps/_shared/inset-map.stories.ts +20 -0
  153. package/src/maps/_shared/inset-map.ts +87 -0
  154. package/src/maps/_shared/styles.ts +57 -0
  155. package/src/maps/column-correlation/column-correlation-map.stories.ts +96 -0
  156. package/src/maps/column-correlation/core.ts +225 -0
  157. package/src/maps/column-correlation/index.ts +2 -0
  158. package/src/maps/column-correlation/state.ts +192 -0
  159. package/src/maps/column-navigation/index.ts +2 -0
  160. package/src/maps/column-navigation/mapbox/column-navigation-map.stories.ts +102 -0
  161. package/src/maps/column-navigation/mapbox/index.ts +219 -0
  162. package/src/maps/column-navigation/mapbox/keyboard-navigation.ts +119 -0
  163. package/src/maps/column-navigation/mapbox/state.ts +109 -0
  164. package/src/maps/column-navigation/svg/column-navigation-svg-map.stories.ts +46 -0
  165. package/src/{map → maps/column-navigation/svg}/index.ts +18 -6
  166. package/src/{map → maps/column-navigation/svg}/layers.ts +28 -109
  167. package/src/maps/column-navigation/utils/keyboard-navigation.ts +58 -0
  168. package/src/maps/index.ts +3 -0
  169. package/src/prepare-units/composite-scale.ts +353 -0
  170. package/src/prepare-units/helpers.ts +226 -0
  171. package/src/prepare-units/index.ts +177 -0
  172. package/src/prepare-units/utils.ts +98 -0
  173. package/src/section.ts +264 -84
  174. package/src/unit-details/index.ts +2 -215
  175. package/src/unit-details/{index.module.sass → panel.module.sass} +39 -8
  176. package/src/unit-details/panel.ts +523 -0
  177. package/src/{selection-popover.module.sass → unit-details/popover.module.sass} +4 -2
  178. package/src/unit-details/popover.ts +82 -0
  179. package/src/units/boxes.module.sass +16 -0
  180. package/src/units/boxes.ts +243 -90
  181. package/src/units/colors.ts +64 -0
  182. package/src/units/composite.ts +157 -152
  183. package/src/units/index.ts +76 -9
  184. package/src/units/names.ts +8 -4
  185. package/src/units/resolvers.ts +11 -0
  186. package/src/units/selection.ts +115 -101
  187. package/src/units/types.ts +5 -16
  188. package/dist/esm/age-axis.64c509ee.js +0 -41
  189. package/dist/esm/age-axis.64c509ee.js.map +0 -1
  190. package/dist/esm/boxes.13968b76.js +0 -164
  191. package/dist/esm/boxes.13968b76.js.map +0 -1
  192. package/dist/esm/boxes.module.28873d08.css +0 -4
  193. package/dist/esm/boxes.module.28873d08.css.map +0 -1
  194. package/dist/esm/boxes.module.605bdcd6.js +0 -13
  195. package/dist/esm/boxes.module.605bdcd6.js.map +0 -1
  196. package/dist/esm/column.8dd26e1a.js +0 -149
  197. package/dist/esm/column.8dd26e1a.js.map +0 -1
  198. package/dist/esm/column.db058031.js.map +0 -1
  199. package/dist/esm/column.module.039d872c.css +0 -151
  200. package/dist/esm/column.module.039d872c.css.map +0 -1
  201. package/dist/esm/column.module.e632868a.js +0 -19
  202. package/dist/esm/column.module.e632868a.js.map +0 -1
  203. package/dist/esm/composite.608a4ca2.js +0 -153
  204. package/dist/esm/composite.608a4ca2.js.map +0 -1
  205. package/dist/esm/core.4db8e452.js.map +0 -1
  206. package/dist/esm/helpers.8a03cfc7.js +0 -94
  207. package/dist/esm/helpers.8a03cfc7.js.map +0 -1
  208. package/dist/esm/index.module.0844afd8.css +0 -65
  209. package/dist/esm/index.module.0844afd8.css.map +0 -1
  210. package/dist/esm/index.module.24fe3a2e.js +0 -37
  211. package/dist/esm/index.module.24fe3a2e.js.map +0 -1
  212. package/dist/esm/layers.ad5fd25d.js +0 -231
  213. package/dist/esm/layers.ad5fd25d.js.map +0 -1
  214. package/dist/esm/map.7aa26f17.js +0 -82
  215. package/dist/esm/map.7aa26f17.js.map +0 -1
  216. package/dist/esm/names.f6a4e9a4.js.map +0 -1
  217. package/dist/esm/providers.cd1e652f.js +0 -25
  218. package/dist/esm/providers.cd1e652f.js.map +0 -1
  219. package/dist/esm/resolvers.b5c82b78.js.map +0 -1
  220. package/dist/esm/section.cc1b1100.js +0 -118
  221. package/dist/esm/section.cc1b1100.js.map +0 -1
  222. package/dist/esm/selection-popover.17d1bd55.js +0 -60
  223. package/dist/esm/selection-popover.17d1bd55.js.map +0 -1
  224. package/dist/esm/selection-popover.module.0a701258.css.map +0 -1
  225. package/dist/esm/selection-popover.module.e22f5183.js +0 -22
  226. package/dist/esm/selection-popover.module.e22f5183.js.map +0 -1
  227. package/dist/esm/selection.bbf26d0e.js +0 -117
  228. package/dist/esm/selection.bbf26d0e.js.map +0 -1
  229. package/dist/esm/store.25eaa168.js +0 -18
  230. package/dist/esm/store.25eaa168.js.map +0 -1
  231. package/dist/esm/types.f016e032.js +0 -18
  232. package/dist/esm/types.f016e032.js.map +0 -1
  233. package/dist/esm/unit-details.56ff8b70.js +0 -209
  234. package/dist/esm/unit-details.56ff8b70.js.map +0 -1
  235. package/dist/esm/units.361088d4.js +0 -42
  236. package/dist/esm/units.361088d4.js.map +0 -1
  237. package/src/helpers.ts +0 -133
  238. package/src/providers.ts +0 -34
  239. package/src/selection-popover.ts +0 -71
  240. package/src/store.ts +0 -12
  241. package/src/units/units.scss +0 -16
  242. /package/src/{map → maps/column-navigation/svg}/animated.ts +0 -0
@@ -9,31 +9,25 @@ import {
9
9
  } from "@macrostrat/column-components";
10
10
  import { SizeAwareLabel, Clickable } from "@macrostrat/ui-components";
11
11
  import hyper from "@macrostrat/hyper";
12
- import {
13
- ReactNode,
14
- useCallback,
15
- useContext,
16
- useEffect,
17
- useMemo,
18
- useRef,
19
- } from "react";
12
+ import { forwardRef, ReactNode, useContext, useMemo } from "react";
20
13
  import { resolveID, scalePattern } from "./resolvers";
21
- import { useSelectedUnit, useUnitSelectionDispatch } from "./selection";
22
- import { IUnit, transformAxisType } from "./types";
14
+ import { useUnitSelectionTarget } from "./selection";
15
+ import { IUnit } from "./types";
23
16
  import styles from "./boxes.module.sass";
17
+ import classNames from "classnames";
18
+ import { getUnitHeightRange } from "../prepare-units/utils";
19
+ import { useLithologies } from "../data-provider";
20
+ import { getMixedUnitColor } from "./colors";
21
+ import { path } from "d3-path";
22
+ import type { RectBounds } from "./types";
24
23
 
25
24
  const h = hyper.styled(styles);
26
25
 
27
- export interface RectBounds {
28
- x: number;
29
- y: number;
30
- width: number;
31
- height: number;
32
- }
33
-
34
26
  interface UnitRectOptions {
35
27
  widthFraction?: number;
36
28
  axisType?: ColumnAxisType;
29
+ // Padding to create overflow for zig-zags or other ornamented edges
30
+ padding?: number;
37
31
  }
38
32
 
39
33
  interface UnitProps extends Clickable, Partial<RectBounds>, UnitRectOptions {
@@ -44,6 +38,9 @@ interface UnitProps extends Clickable, Partial<RectBounds>, UnitRectOptions {
44
38
  widthFraction?: number;
45
39
  children?: ReactNode;
46
40
  className?: string;
41
+ fill?: string;
42
+ backgroundColor?: string;
43
+ patternColor?: string;
47
44
  }
48
45
 
49
46
  export interface LabeledUnitProps
@@ -54,109 +51,262 @@ export interface LabeledUnitProps
54
51
  label: string;
55
52
  onLabelUpdated?(label: string, shown: boolean);
56
53
  halfWidth?: boolean;
54
+ showLabel?: boolean;
55
+ backgroundColor?: string;
57
56
  }
58
57
 
59
58
  function useUnitRect(
60
59
  division: IUnit,
61
60
  options: UnitRectOptions = {}
62
61
  ): RectBounds {
63
- const { widthFraction = 1, axisType = ColumnAxisType.AGE } = options;
62
+ const {
63
+ widthFraction = 1,
64
+ axisType = ColumnAxisType.AGE,
65
+ padding = 0,
66
+ } = options;
64
67
  const { scale } = useContext(ColumnContext);
65
68
  const { width } = useContext(ColumnLayoutContext);
66
- const macrostratAxisKey = transformAxisType(axisType);
67
- const t_key = "t_" + macrostratAxisKey;
68
- const b_key = "b_" + macrostratAxisKey;
69
-
70
- const topHeight = division[t_key];
71
- const bottomHeight = division[b_key];
72
- if (topHeight == null && bottomHeight == null) {
73
- console.warn(
74
- `Missing keys ${t_key} and ${b_key} for ${division.unit_id} (${division.unit_name})`
75
- );
76
- }
69
+
70
+ const [bottomHeight, topHeight] = getUnitHeightRange(division, axisType);
77
71
 
78
72
  const y = scale(topHeight);
79
73
  const height = Math.abs(scale(bottomHeight) - y);
80
74
 
81
75
  return {
82
- x: width * (1 - widthFraction),
83
- y,
84
- height,
85
- width: widthFraction * width,
76
+ x: width * (1 - widthFraction) - padding,
77
+ y: y - padding,
78
+ height: height + padding * 2,
79
+ width: widthFraction * width + padding * 2,
86
80
  };
87
81
  }
88
82
 
83
+ export function MinimalUnit(props) {
84
+ const {
85
+ division: d,
86
+ children,
87
+ className,
88
+ widthFraction = 1,
89
+ axisType: _, // not sure why this is brought in...
90
+ nColumns: __,
91
+ ...baseBounds
92
+ } = props;
93
+
94
+ const { axisType } = useColumn();
95
+ const lithMap = useLithologies();
96
+ const bounds = {
97
+ ...useUnitRect(d, { widthFraction, axisType }),
98
+ ...baseBounds,
99
+ };
100
+
101
+ const backgroundColor = getMixedUnitColor(d, lithMap, null, false);
102
+
103
+ const [ref, selected, onClick] = useUnitSelectionTarget(d);
104
+
105
+ return h(
106
+ "g.unit",
107
+ {
108
+ className,
109
+ style: {
110
+ "--column-unit-background-color": backgroundColor,
111
+ "--column-stroke-color": backgroundColor,
112
+ },
113
+ },
114
+ [
115
+ h("rect.unit.background", {
116
+ ref,
117
+ ...bounds,
118
+ fill: backgroundColor,
119
+ fillOpacity: 0.8,
120
+ stroke: backgroundColor,
121
+ onClick,
122
+ }),
123
+ h.if(selected)("rect.selection-overlay", bounds),
124
+ ]
125
+ );
126
+ }
127
+
89
128
  function Unit(props: UnitProps) {
90
129
  const {
91
130
  division: d,
92
131
  children,
132
+ fill,
93
133
  defaultFill = "transparent",
94
134
  className,
95
135
  widthFraction = 1,
136
+ backgroundColor,
137
+ patternColor,
138
+ axisType: _, // not sure why this is brought in...
96
139
  ...baseBounds
97
140
  } = props;
98
141
 
99
142
  const { axisType } = useColumn();
143
+
144
+ const hasOverflowTop = d.t_clip_pos != null;
145
+ const hasOverflowBottom = d.b_clip_pos != null;
146
+
100
147
  const bounds = {
101
148
  ...useUnitRect(d, { widthFraction, axisType }),
102
149
  ...baseBounds,
150
+ overflowTop: hasOverflowTop,
151
+ overflowBottom: hasOverflowBottom,
103
152
  };
104
153
  const patternID = resolveID(d);
105
- const fill = useGeologicPattern(patternID, defaultFill);
106
- // Allow us to select this unit if in the proper context
154
+ let _fill = fill ?? useGeologicPattern(patternID, defaultFill);
107
155
 
108
- const ref = useRef<HTMLElement>();
156
+ const hasBackgroundColor = backgroundColor != null;
109
157
 
110
- const [selected, onClick] = useUnitSelectionManager(ref, d);
158
+ const _className = classNames(className, { colored: hasBackgroundColor });
111
159
 
112
- return h("g.unit", { className }, [
113
- h("rect.unit", {
114
- ref,
115
- ...bounds,
116
- fill,
117
- onClick,
118
- }),
119
- h.if(selected)("rect.selection-overlay", bounds),
120
- children,
121
- ]);
122
- }
123
-
124
- function useUnitSelectionManager(
125
- ref: React.RefObject<HTMLElement>,
126
- unit: IUnit
127
- ): [boolean, (evt: Event) => void] {
128
- const selectedUnit = useSelectedUnit();
129
- const selected = selectedUnit?.unit_id == unit.unit_id;
160
+ const [ref, selected, onClick] = useUnitSelectionTarget(d);
130
161
 
131
- const dispatch = useUnitSelectionDispatch();
162
+ //const key = `unit-${d.unit_id}`;
132
163
 
133
- const onClick = useCallback(
134
- (evt: Event) => {
135
- dispatch(unit, ref.current, evt);
136
- evt.stopPropagation();
164
+ return h(
165
+ "g.unit",
166
+ {
167
+ className: _className,
168
+ style: {
169
+ "--column-unit-background-color": backgroundColor,
170
+ },
137
171
  },
138
- [unit, ref, dispatch]
172
+ [
173
+ h(UnitRect, {
174
+ ...bounds,
175
+ fill: backgroundColor,
176
+ onClick,
177
+ className: "background",
178
+ }),
179
+ h(UnitRect, {
180
+ ref,
181
+ ...bounds,
182
+ fill: _fill,
183
+ //mask,
184
+ onClick,
185
+ className: "unit",
186
+ }),
187
+ h.if(selected)(UnitRect, { ...bounds, className: "selection-overlay" }),
188
+ //defs,
189
+ children,
190
+ ]
139
191
  );
192
+ }
193
+
194
+ interface UnitRectProps {
195
+ x: number;
196
+ y: number;
197
+ width: number;
198
+ height: number;
199
+ className: string;
200
+ // Used to determine if the rect should have a zig-zag edge on the top or bottom
201
+ overflowTop?: boolean;
202
+ overflowBottom?: boolean;
203
+ [key: string]: any;
204
+ }
140
205
 
141
- useEffect(() => {
142
- if (!selected) return;
143
- // In case we haven't set the position of the unit (if we don't have a target), set the selected unit
144
- dispatch(unit, ref.current, null);
206
+ const UnitRect = forwardRef((props: UnitRectProps, ref) => {
207
+ const {
208
+ x,
209
+ y,
210
+ width,
211
+ height,
212
+ overflowTop = false,
213
+ overflowBottom = false,
214
+ ...rest
215
+ } = props;
145
216
 
146
- // Scroll the unit into view
147
- ref.current?.scrollIntoView({
148
- behavior: "smooth",
149
- block: "center",
150
- inline: "nearest",
217
+ if (!overflowTop && !overflowBottom) {
218
+ return h("rect", {
219
+ x,
220
+ y,
221
+ width,
222
+ height,
223
+ ref,
224
+ ...rest,
225
+ });
226
+ } else {
227
+ const d = zigZagBoxPath(x, y, width, height, overflowTop, overflowBottom);
228
+ return h("path", {
229
+ d,
230
+ ref,
231
+ ...rest,
151
232
  });
152
- }, [selected]);
233
+ }
234
+ });
235
+
236
+ function zigZagBoxPath(x, y, width, height, top: boolean, bottom: boolean) {
237
+ const zigZagWidth = 10;
238
+ const zigZagHeight = 4;
239
+
240
+ const d = path();
241
+
242
+ const nZigZags = Math.floor(width / zigZagWidth - 0.5);
243
+ const _zigZagWidth = width / (nZigZags + 0.5);
244
+
245
+ d.moveTo(x, y);
246
+ let dy = zigZagHeight / 2;
247
+ // Each zig-zag consists of a short outward motion
248
+ let dx = _zigZagWidth / 4;
249
+
250
+ let cx = x;
251
+ let cy = y;
252
+
253
+ const doZigZag = (last = false) => {
254
+ cx += dx;
255
+ cy -= dy;
256
+ d.lineTo(cx, cy);
257
+ let scalar = last ? 1 : 2;
258
+ cx += dx * scalar;
259
+ cy += dy * scalar;
260
+ d.lineTo(cx, cy);
261
+ cx += dx;
262
+ cy -= dy;
263
+ };
264
+
265
+ if (top) {
266
+ // Move to the offset
267
+ //d.lineTo(cx, y);
268
+ // Draw the zig-zags
269
+ for (let i = 0; i < nZigZags; i++) {
270
+ doZigZag();
271
+ }
272
+ // Draw the last half zig-zag
273
+ doZigZag(true);
274
+ }
275
+ // Draw the right edge
276
+ d.lineTo(x + width, y);
277
+ d.lineTo(x + width, y + height);
278
+
279
+ if (bottom) {
280
+ dx = -dx;
281
+ dy = -dy;
282
+ cx = x + width;
283
+ cy = y + height;
153
284
 
154
- return [selected, onClick];
285
+ for (let i = 0; i < nZigZags; i++) {
286
+ doZigZag();
287
+ }
288
+ doZigZag(true);
289
+ }
290
+ // Draw the last line to the left edge
291
+ d.lineTo(x, y + height);
292
+ // Draw the left edge
293
+ d.closePath();
294
+
295
+ // Now render the path;
296
+ return d.toString();
155
297
  }
156
298
 
157
299
  function LabeledUnit(props: LabeledUnitProps) {
158
- const { division, label, onLabelUpdated, widthFraction, ...baseBounds } =
159
- props;
300
+ const {
301
+ division,
302
+ label,
303
+ onLabelUpdated,
304
+ widthFraction,
305
+ showLabel = true,
306
+ backgroundColor,
307
+ axisType: _, // not sure why this is brought in...
308
+ ...baseBounds
309
+ } = props;
160
310
 
161
311
  const { axisType } = useColumn();
162
312
  const bounds = {
@@ -164,21 +314,25 @@ function LabeledUnit(props: LabeledUnitProps) {
164
314
  ...baseBounds,
165
315
  };
166
316
  const { width, height } = bounds;
167
- return h(Unit, { className: "labeled-unit", division, ...bounds }, [
168
- h(
169
- ForeignObject,
170
- { ...bounds, className: "unit-label-container" },
171
- h(SizeAwareLabel, {
172
- className: "unit-overlay",
173
- labelClassName: "unit-label",
174
- style: { width, height },
175
- label,
176
- onVisibilityChanged(viz) {
177
- onLabelUpdated(label, viz);
178
- },
179
- })
180
- ),
181
- ]);
317
+ return h(
318
+ Unit,
319
+ { className: "labeled-unit", division, backgroundColor, ...bounds },
320
+ [
321
+ h.if(showLabel)(
322
+ ForeignObject,
323
+ { ...bounds, className: "unit-label-container" },
324
+ h(SizeAwareLabel, {
325
+ className: "unit-overlay",
326
+ labelClassName: "unit-label",
327
+ style: { width, height },
328
+ label,
329
+ onVisibilityChanged(viz) {
330
+ onLabelUpdated(label, viz);
331
+ },
332
+ })
333
+ ),
334
+ ]
335
+ );
182
336
  }
183
337
 
184
338
  function UnitBoxes<T>(props: {
@@ -205,7 +359,6 @@ function UnitBoxes<T>(props: {
205
359
  return h(unitComponent, {
206
360
  division,
207
361
  key: division.unit_id,
208
- axisType: ColumnAxisType.HEIGHT,
209
362
  ...unitComponentProps,
210
363
  });
211
364
  });
@@ -0,0 +1,64 @@
1
+ import chroma from "chroma-js";
2
+ import { UnitLong } from "@macrostrat/api-types";
3
+
4
+ export function getMixedUnitColor(
5
+ unit: UnitLong,
6
+ lithMap,
7
+ inDarkMode = false,
8
+ asBackground = true
9
+ ): string | null {
10
+ const liths = unit.lith;
11
+ if (liths == null) {
12
+ return "gray";
13
+ }
14
+ const lithData = liths
15
+ .map((d) => {
16
+ let prop = d.prop;
17
+ if (prop == null || isNaN(prop) || prop <= 0) {
18
+ prop = null;
19
+ }
20
+ return {
21
+ lith_id: d.lith_id,
22
+ prop,
23
+ color: lithMap?.get(d.lith_id)?.color,
24
+ };
25
+ })
26
+ .filter((d) => d.color != null);
27
+
28
+ const lithsWithProp = lithData.filter((d) => d.prop != null);
29
+ const lithsWithoutProp = lithData.filter((d) => d.prop == null);
30
+
31
+ const totalProp = lithsWithProp.reduce((sum, d) => sum + d.prop, 0);
32
+ if (totalProp < 1 && lithsWithoutProp.length > 0) {
33
+ const remainingProp = 1 - totalProp;
34
+ // Distribute remaining proportion equally among liths without prop
35
+ const equalProp = remainingProp / lithsWithoutProp.length;
36
+ lithsWithoutProp.forEach((d) => {
37
+ lithsWithProp.push({
38
+ ...d,
39
+ prop: equalProp,
40
+ });
41
+ });
42
+ }
43
+
44
+ if (lithsWithProp.length == 0) {
45
+ return null;
46
+ }
47
+
48
+ // Mix colors proportionally
49
+ const baseColor = chroma.average(
50
+ lithsWithProp.map((d) => d.color),
51
+ "lrgb",
52
+ lithsWithProp.map((d) => d.prop)
53
+ );
54
+
55
+ if (!asBackground) {
56
+ return baseColor.hex();
57
+ }
58
+
59
+ if (inDarkMode) {
60
+ return baseColor.set("hsl.l", 0.2).hex();
61
+ } else {
62
+ return baseColor.set("hsl.l", 0.9).hex();
63
+ }
64
+ }