@macrostrat/column-views 3.0.3 → 3.2.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 (181) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/age-axis.js +2 -2
  3. package/dist/age-axis.js.map +1 -1
  4. package/dist/age-axis.module.sass.cjs +6 -1
  5. package/dist/age-axis.module.sass.cjs.map +1 -1
  6. package/dist/age-axis.module.sass.js +4 -1
  7. package/dist/age-axis.module.sass.js.map +1 -1
  8. package/dist/age-model-overlay.js +2 -2
  9. package/dist/age-model-overlay.js.map +1 -1
  10. package/dist/age-model-overlay.module.sass.cjs +6 -1
  11. package/dist/age-model-overlay.module.sass.cjs.map +1 -1
  12. package/dist/age-model-overlay.module.sass.js +4 -1
  13. package/dist/age-model-overlay.module.sass.js.map +1 -1
  14. package/dist/column.js +2 -2
  15. package/dist/column.js.map +1 -1
  16. package/dist/column.module.sass.cjs +6 -1
  17. package/dist/column.module.sass.cjs.map +1 -1
  18. package/dist/column.module.sass.js +4 -1
  19. package/dist/column.module.sass.js.map +1 -1
  20. package/dist/correlation-chart/main.js +2 -2
  21. package/dist/correlation-chart/main.js.map +1 -1
  22. package/dist/correlation-chart/main.module.sass.cjs +6 -1
  23. package/dist/correlation-chart/main.module.sass.cjs.map +1 -1
  24. package/dist/correlation-chart/main.module.sass.js +4 -1
  25. package/dist/correlation-chart/main.module.sass.js.map +1 -1
  26. package/dist/data-provider/column-nav.js +1 -1
  27. package/dist/data-provider/index.d.ts +0 -2
  28. package/dist/data-provider/store.cjs +49 -6
  29. package/dist/data-provider/store.cjs.map +1 -1
  30. package/dist/data-provider/store.js +47 -4
  31. package/dist/data-provider/store.js.map +1 -1
  32. package/dist/data-provider/unit-selection.cjs +9 -9
  33. package/dist/data-provider/unit-selection.cjs.map +1 -1
  34. package/dist/data-provider/unit-selection.d.ts +1 -1
  35. package/dist/data-provider/unit-selection.js +2 -2
  36. package/dist/data-provider/unit-selection.js.map +1 -1
  37. package/dist/facets/carbon-isotopes/isotopes-column.js +2 -2
  38. package/dist/facets/carbon-isotopes/isotopes-column.js.map +1 -1
  39. package/dist/facets/carbon-isotopes/isotopes-column.module.sass.cjs +6 -1
  40. package/dist/facets/carbon-isotopes/isotopes-column.module.sass.cjs.map +1 -1
  41. package/dist/facets/carbon-isotopes/isotopes-column.module.sass.js +4 -1
  42. package/dist/facets/carbon-isotopes/isotopes-column.module.sass.js.map +1 -1
  43. package/dist/facets/detrital-zircon/index.js +2 -2
  44. package/dist/facets/detrital-zircon/index.js.map +1 -1
  45. package/dist/facets/detrital-zircon/index.module.sass.cjs +6 -1
  46. package/dist/facets/detrital-zircon/index.module.sass.cjs.map +1 -1
  47. package/dist/facets/detrital-zircon/index.module.sass.js +4 -1
  48. package/dist/facets/detrital-zircon/index.module.sass.js.map +1 -1
  49. package/dist/facets/fossils/index.js +2 -2
  50. package/dist/facets/fossils/index.js.map +1 -1
  51. package/dist/facets/fossils/taxon-ranges.js +2 -2
  52. package/dist/facets/fossils/taxon-ranges.js.map +1 -1
  53. package/dist/facets/fossils/taxon-ranges.module.sass.cjs +6 -1
  54. package/dist/facets/fossils/taxon-ranges.module.sass.cjs.map +1 -1
  55. package/dist/facets/fossils/taxon-ranges.module.sass.js +4 -1
  56. package/dist/facets/fossils/taxon-ranges.module.sass.js.map +1 -1
  57. package/dist/facets/measurements/base.js +2 -2
  58. package/dist/facets/measurements/base.js.map +1 -1
  59. package/dist/facets/measurements/base.module.sass.cjs +6 -1
  60. package/dist/facets/measurements/base.module.sass.cjs.map +1 -1
  61. package/dist/facets/measurements/base.module.sass.js +4 -1
  62. package/dist/facets/measurements/base.module.sass.js.map +1 -1
  63. package/dist/index.cjs +15 -29
  64. package/dist/index.cjs.map +1 -1
  65. package/dist/index.js +10 -24
  66. package/dist/index.js.map +1 -1
  67. package/dist/maps/_shared/styles.cjs +6 -1
  68. package/dist/maps/_shared/styles.cjs.map +1 -1
  69. package/dist/maps/_shared/styles.js +6 -1
  70. package/dist/maps/_shared/styles.js.map +1 -1
  71. package/dist/maps/column-correlation/state.cjs +2 -2
  72. package/dist/maps/column-correlation/state.cjs.map +1 -1
  73. package/dist/maps/column-correlation/state.d.ts +1 -0
  74. package/dist/maps/column-correlation/state.js +1 -1
  75. package/dist/maps/column-correlation/state.js.map +1 -1
  76. package/dist/maps/column-navigation/mapbox/keyboard-navigation.d.ts +1 -1
  77. package/dist/maps/column-navigation/mapbox/state.cjs +3 -3
  78. package/dist/maps/column-navigation/mapbox/state.cjs.map +1 -1
  79. package/dist/maps/column-navigation/mapbox/state.js +1 -1
  80. package/dist/maps/column-navigation/mapbox/state.js.map +1 -1
  81. package/dist/maps/column-navigation/svg/data-fetcher.cjs +25 -0
  82. package/dist/maps/column-navigation/svg/data-fetcher.cjs.map +1 -0
  83. package/dist/maps/column-navigation/svg/data-fetcher.d.ts +6 -0
  84. package/dist/maps/column-navigation/svg/data-fetcher.js +25 -0
  85. package/dist/maps/column-navigation/svg/data-fetcher.js.map +1 -0
  86. package/dist/maps/column-navigation/svg/layers.cjs +2 -3
  87. package/dist/maps/column-navigation/svg/layers.cjs.map +1 -1
  88. package/dist/maps/column-navigation/svg/layers.js +1 -2
  89. package/dist/maps/column-navigation/svg/layers.js.map +1 -1
  90. package/dist/maps/index.d.ts +1 -0
  91. package/dist/maps/units-overlay/index.cjs +254 -0
  92. package/dist/maps/units-overlay/index.cjs.map +1 -0
  93. package/dist/maps/units-overlay/index.d.ts +14 -0
  94. package/dist/maps/units-overlay/index.js +252 -0
  95. package/dist/maps/units-overlay/index.js.map +1 -0
  96. package/dist/section.cjs +3 -3
  97. package/dist/section.cjs.map +1 -1
  98. package/dist/section.js +4 -4
  99. package/dist/section.js.map +1 -1
  100. package/dist/unit-details/panel.cjs +76 -57
  101. package/dist/unit-details/panel.cjs.map +1 -1
  102. package/dist/unit-details/panel.js +74 -55
  103. package/dist/unit-details/panel.js.map +1 -1
  104. package/dist/unit-details/panel.module.sass.cjs +6 -1
  105. package/dist/unit-details/panel.module.sass.cjs.map +1 -1
  106. package/dist/unit-details/panel.module.sass.js +4 -1
  107. package/dist/unit-details/panel.module.sass.js.map +1 -1
  108. package/dist/unit-details/popover.js +2 -2
  109. package/dist/unit-details/popover.js.map +1 -1
  110. package/dist/unit-details/popover.module.sass.cjs +6 -1
  111. package/dist/unit-details/popover.module.sass.cjs.map +1 -1
  112. package/dist/unit-details/popover.module.sass.js +4 -1
  113. package/dist/unit-details/popover.module.sass.js.map +1 -1
  114. package/dist/units/boxes.cjs +1 -0
  115. package/dist/units/boxes.cjs.map +1 -1
  116. package/dist/units/boxes.js +3 -2
  117. package/dist/units/boxes.js.map +1 -1
  118. package/dist/units/boxes.module.sass.cjs +6 -1
  119. package/dist/units/boxes.module.sass.cjs.map +1 -1
  120. package/dist/units/boxes.module.sass.js +4 -1
  121. package/dist/units/boxes.module.sass.js.map +1 -1
  122. package/dist/units/colors.cjs +79 -18
  123. package/dist/units/colors.cjs.map +1 -1
  124. package/dist/units/colors.d.ts +17 -4
  125. package/dist/units/colors.js +79 -18
  126. package/dist/units/colors.js.map +1 -1
  127. package/dist/units/composite.js +2 -2
  128. package/dist/units/composite.js.map +1 -1
  129. package/dist/units/composite.module.sass.cjs +6 -1
  130. package/dist/units/composite.module.sass.cjs.map +1 -1
  131. package/dist/units/composite.module.sass.js +4 -1
  132. package/dist/units/composite.module.sass.js.map +1 -1
  133. package/dist/units/index.cjs +6 -4
  134. package/dist/units/index.cjs.map +1 -1
  135. package/dist/units/index.js +4 -1
  136. package/dist/units/index.js.map +1 -1
  137. package/dist/units/resolvers.cjs +11 -0
  138. package/dist/units/resolvers.cjs.map +1 -1
  139. package/dist/units/resolvers.d.ts +5 -0
  140. package/dist/units/resolvers.js +11 -0
  141. package/dist/units/resolvers.js.map +1 -1
  142. package/package.json +11 -9
  143. package/src/correlation-chart/stories/correlation-chart.stories.ts +29 -22
  144. package/src/data-provider/index.ts +0 -2
  145. package/src/data-provider/store.ts +52 -10
  146. package/src/data-provider/unit-selection.ts +4 -4
  147. package/src/maps/_shared/styles.ts +10 -3
  148. package/src/maps/column-correlation/state.ts +2 -1
  149. package/src/maps/column-navigation/mapbox/state.ts +1 -1
  150. package/src/maps/column-navigation/svg/column-navigation-svg-map.stories.ts +1 -1
  151. package/src/maps/column-navigation/svg/data-fetcher.ts +34 -0
  152. package/src/maps/column-navigation/svg/layers.ts +1 -1
  153. package/src/maps/index.ts +1 -0
  154. package/src/maps/unit-map.stories.ts +64 -0
  155. package/src/maps/units-overlay/index.ts +336 -0
  156. package/src/section.ts +1 -1
  157. package/src/unit-details/panel.ts +97 -60
  158. package/src/units/boxes.ts +2 -1
  159. package/src/units/colors.ts +137 -25
  160. package/src/units/index.ts +1 -1
  161. package/src/units/resolvers.ts +16 -0
  162. package/dist/data-provider/base.cjs +0 -352
  163. package/dist/data-provider/base.cjs.map +0 -1
  164. package/dist/data-provider/base.d.ts +0 -65
  165. package/dist/data-provider/base.js +0 -349
  166. package/dist/data-provider/base.js.map +0 -1
  167. package/dist/data-provider/core.cjs +0 -58
  168. package/dist/data-provider/core.cjs.map +0 -1
  169. package/dist/data-provider/core.d.ts +0 -31
  170. package/dist/data-provider/core.js +0 -56
  171. package/dist/data-provider/core.js.map +0 -1
  172. package/dist/data-provider/fetch.cjs +0 -212
  173. package/dist/data-provider/fetch.cjs.map +0 -1
  174. package/dist/data-provider/fetch.d.ts +0 -27
  175. package/dist/data-provider/fetch.js +0 -210
  176. package/dist/data-provider/fetch.js.map +0 -1
  177. package/dist/data-provider/store.d.ts +0 -34
  178. package/dist/unit-details/panel.d.ts +0 -87
  179. package/src/data-provider/base.ts +0 -475
  180. package/src/data-provider/core.ts +0 -89
  181. package/src/data-provider/fetch.ts +0 -278
@@ -1,8 +1,21 @@
1
- import { useMemo, useContext, createContext } from "react";
1
+ import { useEffect, useMemo, useContext, createContext } from "react";
2
2
  import h from "@macrostrat/hyper";
3
3
  import { createCompositeScale } from "../prepare-units/composite-scale.js";
4
+ import { ColumnProvider } from "@macrostrat/column-components";
4
5
  import { UnitSelectionCallbackManager, allowUnitSelectionAtom, selectedUnitIDAtom } from "./unit-selection.js";
5
- import { ScopedProvider, columnUnitsAtom, scope, columnUnitsMapAtom } from "./core.js";
6
+ import { createScopedStore } from "@macrostrat/data-components";
7
+ import { atom } from "jotai";
8
+ const scope = createScopedStore();
9
+ const columnUnitsAtom = atom();
10
+ const columnUnitsMapAtom = atom((get) => {
11
+ const units = get(columnUnitsAtom);
12
+ if (!units) return null;
13
+ const unitMap = /* @__PURE__ */ new Map();
14
+ units.forEach((unit) => {
15
+ unitMap.set(unit.unit_id, unit);
16
+ });
17
+ return unitMap;
18
+ });
6
19
  function MacrostratColumnStateProvider({
7
20
  children,
8
21
  units,
@@ -26,9 +39,11 @@ function MacrostratColumnStateProvider({
26
39
  selectionHandlers = h(UnitSelectionCallbackManager, { onUnitSelected });
27
40
  }
28
41
  return h(
29
- ScopedProvider,
42
+ scope.Provider,
30
43
  {
31
- atoms: atomMap
44
+ atoms: atomMap,
45
+ keepUpdated: true,
46
+ inherit: true
32
47
  },
33
48
  [selectionHandlers, children]
34
49
  );
@@ -95,10 +110,38 @@ function useCompositeScale() {
95
110
  [ctx.sections]
96
111
  );
97
112
  }
113
+ function MacrostratColumnProvider(props) {
114
+ const { axisType } = useMacrostratColumnData();
115
+ const { units, domain, pixelScale, scale, children } = props;
116
+ return h(
117
+ ColumnProvider,
118
+ {
119
+ axisType,
120
+ divisions: units,
121
+ range: domain,
122
+ pixelsPerMeter: pixelScale,
123
+ scale
124
+ },
125
+ children
126
+ );
127
+ }
128
+ function LithologiesProvider({ children }) {
129
+ useEffect(() => {
130
+ console.warn(
131
+ "LithologiesProvider is deprecated. Replace with MacrostratDataProvider"
132
+ );
133
+ }, []);
134
+ return children;
135
+ }
98
136
  export {
137
+ LithologiesProvider,
99
138
  MacrostratColumnDataProvider,
139
+ MacrostratColumnProvider,
100
140
  MacrostratColumnStateProvider,
101
141
  UnitSelectionProvider,
142
+ columnUnitsAtom,
143
+ columnUnitsMapAtom,
144
+ scope,
102
145
  useColumnUnitsMap,
103
146
  useCompositeScale,
104
147
  useMacrostratColumnData,
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sources":["../../src/data-provider/store.ts"],"sourcesContent":["import { createContext, ReactNode, useContext, useMemo } from \"react\";\nimport h from \"@macrostrat/hyper\";\nimport {\n CompositeColumnScale,\n createCompositeScale,\n} from \"../prepare-units/composite-scale\";\nimport { ColumnAxisType } from \"@macrostrat/column-components\";\nimport type { ExtUnit, PackageLayoutData } from \"../prepare-units\";\nimport {\n allowUnitSelectionAtom,\n selectedUnitIDAtom,\n UnitSelectionCallbacks,\n UnitSelectionCallbackManager,\n} from \"./unit-selection\";\nimport { BaseUnit } from \"@macrostrat/api-types\";\nimport {\n AtomMap,\n columnUnitsAtom,\n columnUnitsMapAtom,\n scope,\n ScopedProvider,\n} from \"./core\";\n\nexport interface ColumnStateProviderProps<\n T extends BaseUnit,\n> extends Partial<UnitSelectionCallbacks> {\n children: ReactNode;\n units: T[];\n selectedUnit: number | null;\n allowUnitSelection?: boolean;\n}\n\nexport function MacrostratColumnStateProvider<T extends BaseUnit>({\n children,\n units,\n allowUnitSelection = false,\n onUnitSelected,\n selectedUnit,\n}: ColumnStateProviderProps<T>) {\n /** Top-level provider for Macrostrat column data.\n * It is either provided by the Column component itself, or\n * can be hoisted higher in the tree to provide a common data context\n */\n\n /* By default, unit selection is disabled. However, if any related props are passed,\n we enable it.\n */\n const _allowSelection = useMemo(() => {\n if (allowUnitSelection) {\n return true;\n }\n return selectedUnit != null || onUnitSelected != null;\n }, []);\n\n const atomMap: AtomMap = [\n [columnUnitsAtom, units],\n [allowUnitSelectionAtom, _allowSelection],\n [selectedUnitIDAtom, selectedUnit],\n ];\n\n let selectionHandlers: ReactNode = null;\n if (_allowSelection) {\n selectionHandlers = h(UnitSelectionCallbackManager, { onUnitSelected });\n }\n\n return h(\n ScopedProvider,\n {\n atoms: atomMap,\n },\n [selectionHandlers, children],\n );\n}\n\nexport interface MacrostratColumnDataContext<T extends BaseUnit> {\n units: T[];\n sections: PackageLayoutData[];\n totalHeight?: number;\n axisType?: ColumnAxisType;\n allowUnitSelection?: boolean;\n}\n\nexport interface ColumnDataProviderProps<T extends BaseUnit>\n extends MacrostratColumnDataContext<T>, ColumnStateProviderProps<T> {\n children: ReactNode;\n}\n\nconst MacrostratColumnDataContext =\n createContext<MacrostratColumnDataContext<any>>(null);\n\nexport function MacrostratColumnDataProvider<T extends BaseUnit>({\n children,\n units,\n sections,\n totalHeight,\n axisType,\n allowUnitSelection,\n onUnitSelected,\n selectedUnit,\n}: ColumnDataProviderProps<T>) {\n /** Internal provider for Macrostrat column data.\n * As a general rule, we want to provide data and column-axis\n * height calculations through the context, since these need to\n * be accessed by any component that lays out information on the\n * column.\n *\n * Cross-axis layout and view configuration (e.g., showing and hiding\n * of different components or labels) should be handled through passing\n * props to the components themselves.\n * */\n\n const value = useMemo(() => {\n // For now, change ordinal axis types to age axis types\n return {\n units,\n sections,\n totalHeight,\n axisType,\n };\n }, [units, sections, totalHeight, axisType]);\n\n return h(\n MacrostratColumnStateProvider,\n {\n units,\n allowUnitSelection,\n onUnitSelected,\n selectedUnit,\n },\n h(MacrostratColumnDataContext.Provider, { value }, children),\n );\n}\n\nexport function UnitSelectionProvider(props: ColumnStateProviderProps<any>) {\n /* A basic unit selection provider without column data context.\n Mostly for use with the CorrelationChart component.\n */\n return h(MacrostratColumnStateProvider, {\n ...props,\n allowUnitSelection: true,\n });\n}\n\nexport function useMacrostratColumnData() {\n const ctx = useContext(MacrostratColumnDataContext);\n if (!ctx) {\n throw new Error(\n \"useMacrostratColumnData must be used within a MacrostratColumnDataProvider\",\n );\n }\n return ctx;\n}\n\nexport function useMacrostratUnits() {\n return scope.useAtomValue(columnUnitsAtom);\n}\n\nexport function useColumnUnitsMap(): Map<number, ExtUnit> | null {\n try {\n return scope.useAtomValue(columnUnitsMapAtom) as Map<number, ExtUnit>;\n } catch {\n return null;\n }\n}\n\nexport function useCompositeScale(): CompositeColumnScale {\n const ctx = useMacrostratColumnData();\n return useMemo(\n () => createCompositeScale(ctx.sections, true),\n [ctx.sections],\n );\n}\n"],"names":[],"mappings":";;;;;AAgCO,SAAS,8BAAkD;AAAA,EAChE;AAAA,EACA;AAAA,EACA,qBAAqB;AAAA,EACrB;AAAA,EACA;AACF,GAAgC;AAS9B,QAAM,kBAAkB,QAAQ,MAAM;AACpC,QAAI,oBAAoB;AACtB,aAAO;AAAA,IACT;AACA,WAAO,gBAAgB,QAAQ,kBAAkB;AAAA,EACnD,GAAG,CAAA,CAAE;AAEL,QAAM,UAAmB;AAAA,IACvB,CAAC,iBAAiB,KAAK;AAAA,IACvB,CAAC,wBAAwB,eAAe;AAAA,IACxC,CAAC,oBAAoB,YAAY;AAAA,EAAA;AAGnC,MAAI,oBAA+B;AACnC,MAAI,iBAAiB;AACnB,wBAAoB,EAAE,8BAA8B,EAAE,eAAA,CAAgB;AAAA,EACxE;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,IAAA;AAAA,IAET,CAAC,mBAAmB,QAAQ;AAAA,EAAA;AAEhC;AAeA,MAAM,8BACJ,cAAgD,IAAI;AAE/C,SAAS,6BAAiD;AAAA,EAC/D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA+B;AAY7B,QAAM,QAAQ,QAAQ,MAAM;AAE1B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ,GAAG,CAAC,OAAO,UAAU,aAAa,QAAQ,CAAC;AAE3C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,EAAE,4BAA4B,UAAU,EAAE,MAAA,GAAS,QAAQ;AAAA,EAAA;AAE/D;AAEO,SAAS,sBAAsB,OAAsC;AAI1E,SAAO,EAAE,+BAA+B;AAAA,IACtC,GAAG;AAAA,IACH,oBAAoB;AAAA,EAAA,CACrB;AACH;AAEO,SAAS,0BAA0B;AACxC,QAAM,MAAM,WAAW,2BAA2B;AAClD,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACA,SAAO;AACT;AAEO,SAAS,qBAAqB;AACnC,SAAO,MAAM,aAAa,eAAe;AAC3C;AAEO,SAAS,oBAAiD;AAC/D,MAAI;AACF,WAAO,MAAM,aAAa,kBAAkB;AAAA,EAC9C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,oBAA0C;AACxD,QAAM,MAAM,wBAAA;AACZ,SAAO;AAAA,IACL,MAAM,qBAAqB,IAAI,UAAU,IAAI;AAAA,IAC7C,CAAC,IAAI,QAAQ;AAAA,EAAA;AAEjB;"}
1
+ {"version":3,"file":"store.js","sources":["../../src/data-provider/store.ts"],"sourcesContent":["import { createContext, ReactNode, useContext, useMemo } from \"react\";\nimport h from \"@macrostrat/hyper\";\nimport {\n CompositeColumnScale,\n createCompositeScale,\n} from \"../prepare-units/composite-scale\";\nimport { ColumnAxisType, ColumnProvider } from \"@macrostrat/column-components\";\nimport type { ExtUnit, PackageLayoutData } from \"../prepare-units\";\nimport {\n allowUnitSelectionAtom,\n selectedUnitIDAtom,\n UnitSelectionCallbacks,\n UnitSelectionCallbackManager,\n} from \"./unit-selection\";\nimport type { BaseUnit } from \"@macrostrat/api-types\";\nimport { type AtomMap, createScopedStore } from \"@macrostrat/data-components\";\nimport { atom } from \"jotai\";\nimport { useEffect } from \"react\";\n\nexport const scope = createScopedStore();\n\nexport const columnUnitsAtom = atom<BaseUnit[]>();\n\nexport const columnUnitsMapAtom = atom<Map<number, BaseUnit> | null>((get) => {\n const units = get(columnUnitsAtom);\n if (!units) return null;\n const unitMap = new Map<number, BaseUnit>();\n units.forEach((unit) => {\n unitMap.set(unit.unit_id, unit);\n });\n return unitMap;\n});\n\nexport interface ColumnStateProviderProps<\n T extends BaseUnit,\n> extends Partial<UnitSelectionCallbacks> {\n children: ReactNode;\n units: T[];\n selectedUnit: number | null;\n allowUnitSelection?: boolean;\n}\n\nexport function MacrostratColumnStateProvider<T extends BaseUnit>({\n children,\n units,\n allowUnitSelection = false,\n onUnitSelected,\n selectedUnit,\n}: ColumnStateProviderProps<T>) {\n /** Top-level provider for Macrostrat column data.\n * It is either provided by the Column component itself, or\n * can be hoisted higher in the tree to provide a common data context\n */\n\n /* By default, unit selection is disabled. However, if any related props are passed,\n we enable it.\n */\n const _allowSelection = useMemo(() => {\n if (allowUnitSelection) {\n return true;\n }\n return selectedUnit != null || onUnitSelected != null;\n }, []);\n\n const atomMap: AtomMap = [\n [columnUnitsAtom, units],\n [allowUnitSelectionAtom, _allowSelection],\n [selectedUnitIDAtom, selectedUnit],\n ];\n\n let selectionHandlers: ReactNode = null;\n if (_allowSelection) {\n selectionHandlers = h(UnitSelectionCallbackManager, { onUnitSelected });\n }\n\n return h(\n scope.Provider,\n {\n atoms: atomMap,\n keepUpdated: true,\n inherit: true,\n },\n [selectionHandlers, children],\n );\n}\n\nexport interface MacrostratColumnDataContext<T extends BaseUnit> {\n units: T[];\n sections: PackageLayoutData[];\n totalHeight?: number;\n axisType?: ColumnAxisType;\n allowUnitSelection?: boolean;\n}\n\nexport interface ColumnDataProviderProps<T extends BaseUnit>\n extends MacrostratColumnDataContext<T>, ColumnStateProviderProps<T> {\n children: ReactNode;\n}\n\nconst MacrostratColumnDataContext =\n createContext<MacrostratColumnDataContext<any>>(null);\n\nexport function MacrostratColumnDataProvider<T extends BaseUnit>({\n children,\n units,\n sections,\n totalHeight,\n axisType,\n allowUnitSelection,\n onUnitSelected,\n selectedUnit,\n}: ColumnDataProviderProps<T>) {\n /** Internal provider for Macrostrat column data.\n * As a general rule, we want to provide data and column-axis\n * height calculations through the context, since these need to\n * be accessed by any component that lays out information on the\n * column.\n *\n * Cross-axis layout and view configuration (e.g., showing and hiding\n * of different components or labels) should be handled through passing\n * props to the components themselves.\n * */\n\n const value = useMemo(() => {\n // For now, change ordinal axis types to age axis types\n return {\n units,\n sections,\n totalHeight,\n axisType,\n };\n }, [units, sections, totalHeight, axisType]);\n\n return h(\n MacrostratColumnStateProvider,\n {\n units,\n allowUnitSelection,\n onUnitSelected,\n selectedUnit,\n },\n h(MacrostratColumnDataContext.Provider, { value }, children),\n );\n}\n\nexport function UnitSelectionProvider(props: ColumnStateProviderProps<any>) {\n /* A basic unit selection provider without column data context.\n Mostly for use with the CorrelationChart component.\n */\n return h(MacrostratColumnStateProvider, {\n ...props,\n allowUnitSelection: true,\n });\n}\n\nexport function useMacrostratColumnData() {\n const ctx = useContext(MacrostratColumnDataContext);\n if (!ctx) {\n throw new Error(\n \"useMacrostratColumnData must be used within a MacrostratColumnDataProvider\",\n );\n }\n return ctx;\n}\n\nexport function useMacrostratUnits() {\n return scope.useAtomValue(columnUnitsAtom);\n}\n\nexport function useColumnUnitsMap(): Map<number, ExtUnit> | null {\n try {\n return scope.useAtomValue(columnUnitsMapAtom) as Map<number, ExtUnit>;\n } catch {\n return null;\n }\n}\n\nexport function useCompositeScale(): CompositeColumnScale {\n const ctx = useMacrostratColumnData();\n return useMemo(\n () => createCompositeScale(ctx.sections, true),\n [ctx.sections],\n );\n}\n\nexport function MacrostratColumnProvider(props) {\n /** A column provider specialized the Macrostrat API. Maps more\n * generic concepts to Macrostrat-specific ones.\n */\n\n const { axisType } = useMacrostratColumnData();\n const { units, domain, pixelScale, scale, children } = props;\n return h(\n ColumnProvider,\n {\n axisType,\n divisions: units,\n range: domain,\n pixelsPerMeter: pixelScale,\n scale,\n },\n children,\n );\n}\n\n/** This is now a legacy provider */\nexport function LithologiesProvider({ children }) {\n useEffect(() => {\n console.warn(\n \"LithologiesProvider is deprecated. Replace with MacrostratDataProvider\",\n );\n }, []);\n return children;\n}\n"],"names":[],"mappings":"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"}
@@ -3,32 +3,32 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const uiComponents = require("@macrostrat/ui-components");
4
4
  const React = require("react");
5
5
  const jotai = require("jotai");
6
- const core = require("./core.cjs");
6
+ const store = require("./store.cjs");
7
7
  const stratigraphyUtils = require("@macrostrat/stratigraphy-utils");
8
8
  function useUnitSelectionDispatch() {
9
- return core.scope.useSetAtom(selectedUnitAtom);
9
+ return store.scope.useSetAtom(selectedUnitAtom);
10
10
  }
11
11
  function useSelectedUnit() {
12
- return core.scope.useAtomValue(selectedUnitAtom);
12
+ return store.scope.useAtomValue(selectedUnitAtom);
13
13
  }
14
14
  const allowUnitSelectionAtom = jotai.atom(true);
15
15
  const selectedUnitIDAtom = jotai.atom();
16
16
  const overlayPositionAtom = jotai.atom();
17
17
  const columnRefAtom = jotai.atom({ current: null });
18
18
  function useColumnRef() {
19
- return core.scope.useAtomValue(columnRefAtom);
19
+ return store.scope.useAtomValue(columnRefAtom);
20
20
  }
21
21
  const selectedUnitAtom = jotai.atom(
22
22
  (get) => {
23
23
  if (!get(allowUnitSelectionAtom)) return null;
24
24
  const unitID = get(selectedUnitIDAtom);
25
25
  if (unitID == null) return null;
26
- const unitsMap = get(core.columnUnitsMapAtom);
26
+ const unitsMap = get(store.columnUnitsMapAtom);
27
27
  return unitsMap?.get(unitID) || null;
28
28
  },
29
29
  (get, set, selectedUnit, target = null) => {
30
30
  if (!get(allowUnitSelectionAtom)) {
31
- throw new Error("Unit selection is disabled.");
31
+ console.error("Unit selection is disabled.");
32
32
  }
33
33
  let unitID;
34
34
  let unit = null;
@@ -40,7 +40,7 @@ const selectedUnitAtom = jotai.atom(
40
40
  unitID = selectedUnit.unit_id;
41
41
  }
42
42
  if (unitID != null) {
43
- const unitsMap = get(core.columnUnitsMapAtom);
43
+ const unitsMap = get(store.columnUnitsMapAtom);
44
44
  if (!unitsMap?.has(unitID)) {
45
45
  throw new Error(
46
46
  `Unit with ID ${unitID} not found in current column units.`
@@ -66,12 +66,12 @@ const selectedUnitAtom = jotai.atom(
66
66
  }
67
67
  );
68
68
  function useAtomOverlayPosition() {
69
- return core.scope.useAtomValue(overlayPositionAtom);
69
+ return store.scope.useAtomValue(overlayPositionAtom);
70
70
  }
71
71
  function UnitSelectionCallbackManager({
72
72
  onUnitSelected
73
73
  }) {
74
- const selectedUnit = core.scope.useAtomValue(selectedUnitAtom);
74
+ const selectedUnit = store.scope.useAtomValue(selectedUnitAtom);
75
75
  React.useEffect(() => {
76
76
  onUnitSelected?.(selectedUnit?.unit_id ?? null, selectedUnit ?? null);
77
77
  }, [selectedUnit?.unit_id]);
@@ -1 +1 @@
1
- {"version":3,"file":"unit-selection.cjs","sources":["../../src/data-provider/unit-selection.ts"],"sourcesContent":["import { BaseUnit, UnitLong } from \"@macrostrat/api-types\";\nimport { useKeyHandler } from \"@macrostrat/ui-components\";\nimport { useEffect, useRef, useCallback, useMemo } from \"react\";\nimport type { RectBounds, IUnit } from \"../units/types\";\nimport { atom } from \"jotai\";\nimport { columnUnitsMapAtom, scope } from \"./core\";\nimport { ColumnData } from \"@macrostrat/column-views\";\nimport {\n AgeRangeQuantifiedDifference,\n ageRangeQuantifiedDifference,\n AgeRangeRelationship,\n} from \"@macrostrat/stratigraphy-utils\";\n\ntype UnitSelectDispatch = (\n unit: number | BaseUnit | null,\n target: HTMLElement | null,\n) => void;\n\nexport function useUnitSelectionDispatch(): UnitSelectDispatch {\n return scope.useSetAtom(selectedUnitAtom);\n}\n\nexport function useSelectedUnit() {\n return scope.useAtomValue(selectedUnitAtom);\n}\n\nexport interface ColumnClickData {\n unitID: number | null;\n unit: BaseUnit | null;\n target: HTMLElement | null;\n height: number;\n // Room for boundary IDs eventually\n}\n\nexport interface UnitSelectionCallbacks {\n // It's sort of unfortunate that we need to pass in the column ref here\n onClickedColumn?: (columnClickData: ColumnClickData, event: Event) => void;\n onUnitSelected?: <T extends BaseUnit>(\n unitID: number | null,\n unit: T | null,\n ) => void;\n}\n\nexport const allowUnitSelectionAtom = atom<boolean>(true);\n\nexport const selectedUnitIDAtom = atom<number | null>();\n\nconst overlayPositionAtom = atom<RectBounds | null>();\n\nconst columnRefAtom = atom<{ current: HTMLElement | null }>({ current: null });\n\nexport function useColumnRef() {\n return scope.useAtomValue(columnRefAtom);\n}\n\nconst selectedUnitAtom = atom(\n (get) => {\n if (!get(allowUnitSelectionAtom)) return null;\n\n const unitID = get(selectedUnitIDAtom);\n if (unitID == null) return null;\n const unitsMap = get(columnUnitsMapAtom);\n return unitsMap?.get(unitID) || null;\n },\n (\n get,\n set,\n selectedUnit: number | BaseUnit | null,\n target: HTMLElement | null = null,\n ): BaseUnit | null => {\n if (!get(allowUnitSelectionAtom)) {\n throw new Error(\"Unit selection is disabled.\");\n }\n\n let unitID: number | null;\n let unit: BaseUnit | null = null;\n if (selectedUnit == null) {\n unitID = null;\n } else if (typeof selectedUnit === \"number\") {\n unitID = selectedUnit;\n } else if (\"unit_id\" in selectedUnit) {\n unitID = selectedUnit.unit_id;\n }\n\n if (unitID != null) {\n // Verify that the unit exists in the current colum, else throw\n const unitsMap = get(columnUnitsMapAtom);\n if (!unitsMap?.has(unitID)) {\n throw new Error(\n `Unit with ID ${unitID} not found in current column units.`,\n );\n }\n unit = unitsMap.get(unitID) ?? null;\n }\n\n let overlayPosition: RectBounds | null = null;\n\n const columnEl = get(columnRefAtom)?.current;\n\n if (unit != null && columnEl != null && target != null) {\n const rect = columnEl.getBoundingClientRect();\n const targetRect = target.getBoundingClientRect();\n overlayPosition = {\n x: targetRect.left - rect.left,\n y: targetRect.top - rect.top,\n width: targetRect.width,\n height: targetRect.height,\n };\n }\n\n set(selectedUnitIDAtom, unitID);\n set(overlayPositionAtom, overlayPosition);\n\n return unit;\n },\n);\n\nexport function useAtomOverlayPosition() {\n return scope.useAtomValue(overlayPositionAtom);\n}\n\nexport function UnitSelectionCallbackManager({\n onUnitSelected,\n}: UnitSelectionCallbacks) {\n const selectedUnit = scope.useAtomValue(selectedUnitAtom);\n useEffect(() => {\n onUnitSelected?.(selectedUnit?.unit_id ?? null, selectedUnit ?? null);\n }, [selectedUnit?.unit_id]);\n return null;\n}\n\n/** TODO: figure out if onClickedColumn is still needed\n /** This is not the natural place to get positions within the column,\n * but it will work for now.\nif (props.onClickedColumn) {\n // Infer height from top and bottom height of unit (because that's passed back with the call)\n //const py = event.y;\n //const [bottom, top] = getUnitHeightRange(unit, axisType);\n //const height = Math.abs(bottom - top);\n\n const columnClickData: ColumnClickData = {\n unitID: unit?.unit_id,\n unit,\n target,\n height: el?.getBoundingClientRect().height || 0,\n };\n props.onClickedColumn(columnClickData, event);\n}*/\n\nexport function useUnitSelectionTarget(\n unit: IUnit,\n): [React.RefObject<HTMLElement>, boolean, (evt: Event) => void] {\n const ref = useRef<HTMLElement>();\n const selectedUnit = useSelectedUnit();\n const selectUnit = useUnitSelectionDispatch();\n const selected = selectedUnit?.unit_id == unit.unit_id;\n\n const onClick = useCallback(\n (evt: Event) => {\n selectUnit?.(unit, ref.current);\n evt.stopPropagation();\n },\n [unit, selectUnit],\n );\n\n useEffect(() => {\n if (!selected || selectUnit == null) return;\n // In case we haven't set the position of the unit (if we don't have a target), set the selected unit\n selectUnit(unit, ref.current);\n\n // Scroll the unit into view\n ref.current?.scrollIntoView({\n behavior: \"smooth\",\n block: \"center\",\n inline: \"nearest\",\n });\n }, [selected, selectUnit]);\n\n return [ref, selected, onClick];\n}\n\nexport function UnitKeyboardNavigation({\n columnData,\n units,\n allowHorizontalNavigation,\n}: {\n columnData?: ColumnData[];\n units?: UnitLong[];\n allowHorizontalNavigation?: boolean;\n}) {\n if (units == null && columnData == null) {\n throw new Error(\"Either units or columnData must be provided.\");\n }\n\n let _columnData: ColumnData[] = useMemo(() => {\n if (columnData != null) return columnData;\n // Build column data from units\n const colMap = new Map<number, UnitLong[]>();\n for (const unit of units!) {\n if (!colMap.has(unit.col_id)) {\n colMap.set(unit.col_id, []);\n }\n colMap.get(unit.col_id)!.push(unit);\n }\n const cols: ColumnData[] = [];\n for (const [colID, units] of colMap) {\n cols.push({ columnID: colID, units });\n }\n // Sort columns by columnID\n cols.sort((a, b) => a.columnID - b.columnID);\n return cols;\n }, [columnData, units]);\n\n // Default to allowing horizontal navigation only if columnData is provided\n const _allowHorizontalNavigation =\n allowHorizontalNavigation ?? columnData != null;\n\n const selectedUnit = useSelectedUnit() as UnitLong | null;\n const selectUnit = useUnitSelectionDispatch();\n\n const keyMap: Record<number, Direction> = {\n 38: \"up\",\n 40: \"down\",\n };\n if (_allowHorizontalNavigation) {\n keyMap[37] = \"left\";\n keyMap[39] = \"right\";\n }\n\n useKeyHandler(\n (event) => {\n const direction = keyMap[event.keyCode];\n if (direction == null) return;\n const nextUnit = getBestUnit(_columnData, selectedUnit, direction);\n if (nextUnit == null) return;\n selectUnit(nextUnit, null);\n event.stopPropagation();\n },\n [_columnData, selectedUnit],\n );\n return null;\n}\n\ntype Direction = \"up\" | \"down\" | \"left\" | \"right\";\n\nfunction getBestUnit(\n columnData: ColumnData[],\n targetUnit: UnitLong,\n direction: Direction,\n): UnitLong | null {\n const thisColIndex = columnData.findIndex(\n (col) => col.columnID === targetUnit.col_id,\n );\n if (thisColIndex === -1) return null;\n\n // If up or down, stay in the same column\n if (direction === \"up\" || direction === \"down\") {\n const units = columnData[thisColIndex].units;\n const ix = units.findIndex((unit) => unit.unit_id === targetUnit.unit_id);\n if (ix === -1) return null;\n if (direction === \"up\") {\n return units[ix - 1] || null;\n } else {\n return units[ix + 1] || null;\n }\n }\n\n // If left or right, move to adjacent column\n let adjacentColIndex: number;\n if (direction === \"left\") {\n adjacentColIndex =\n (thisColIndex - 1 + columnData.length) % columnData.length;\n } else {\n adjacentColIndex = (thisColIndex + 1) % columnData.length;\n }\n\n const adjacentColUnits = columnData[adjacentColIndex].units;\n return getMostOverlappingUnit(targetUnit, adjacentColUnits);\n}\n\ntype UnitAgeRangeRelationship = AgeRangeQuantifiedDifference & {\n unit: UnitLong;\n};\n\nfunction getMostOverlappingUnit(\n targetUnit: UnitLong,\n candidateUnits: UnitLong[],\n): UnitLong | null {\n const targetAgeRange = [targetUnit.b_age, targetUnit.t_age];\n\n const overlaps: UnitAgeRangeRelationship[] = [];\n for (const candidate of candidateUnits) {\n const candidateAgeRange = [candidate.b_age, candidate.t_age];\n\n const rel = ageRangeQuantifiedDifference(targetAgeRange, candidateAgeRange);\n if (rel.type === AgeRangeRelationship.Identical) {\n return candidate;\n }\n overlaps.push({ ...rel, unit: candidate });\n }\n\n let bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Containing,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Contained,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.PartialOverlap,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Disjoint,\n );\n bestOverlaps.sort((a, b) => a.distance - b.distance);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n return null;\n}\n"],"names":["scope","atom","columnUnitsMapAtom","useEffect","useRef","useCallback","useMemo","units","useKeyHandler","ageRangeQuantifiedDifference","AgeRangeRelationship"],"mappings":"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"}
1
+ {"version":3,"file":"unit-selection.cjs","sources":["../../src/data-provider/unit-selection.ts"],"sourcesContent":["import type { BaseUnit, UnitLong } from \"@macrostrat/api-types\";\nimport { useKeyHandler } from \"@macrostrat/ui-components\";\nimport { useEffect, useRef, useCallback, useMemo } from \"react\";\nimport type { RectBounds, IUnit } from \"../units/types\";\nimport { atom } from \"jotai\";\nimport { scope, columnUnitsMapAtom } from \"./store\";\nimport {\n AgeRangeQuantifiedDifference,\n ageRangeQuantifiedDifference,\n AgeRangeRelationship,\n} from \"@macrostrat/stratigraphy-utils\";\nimport type { ColumnData } from \"@macrostrat/data-provider\";\n\ntype UnitSelectDispatch = (\n unit: number | BaseUnit | null,\n target: HTMLElement | null,\n) => void;\n\nexport function useUnitSelectionDispatch(): UnitSelectDispatch {\n return scope.useSetAtom(selectedUnitAtom);\n}\n\nexport function useSelectedUnit() {\n return scope.useAtomValue(selectedUnitAtom);\n}\n\nexport interface ColumnClickData {\n unitID: number | null;\n unit: BaseUnit | null;\n target: HTMLElement | null;\n height: number;\n // Room for boundary IDs eventually\n}\n\nexport interface UnitSelectionCallbacks {\n // It's sort of unfortunate that we need to pass in the column ref here\n onClickedColumn?: (columnClickData: ColumnClickData, event: Event) => void;\n onUnitSelected?: <T extends BaseUnit>(\n unitID: number | null,\n unit: T | null,\n ) => void;\n}\n\nexport const allowUnitSelectionAtom = atom<boolean>(true);\n\nexport const selectedUnitIDAtom = atom<number | null>();\n\nconst overlayPositionAtom = atom<RectBounds | null>();\n\nconst columnRefAtom = atom<{ current: HTMLElement | null }>({ current: null });\n\nexport function useColumnRef() {\n return scope.useAtomValue(columnRefAtom);\n}\n\nconst selectedUnitAtom = atom(\n (get) => {\n if (!get(allowUnitSelectionAtom)) return null;\n\n const unitID = get(selectedUnitIDAtom);\n if (unitID == null) return null;\n const unitsMap = get(columnUnitsMapAtom);\n return unitsMap?.get(unitID) || null;\n },\n (\n get,\n set,\n selectedUnit: number | BaseUnit | null,\n target: HTMLElement | null = null,\n ): BaseUnit | null => {\n if (!get(allowUnitSelectionAtom)) {\n console.error(\"Unit selection is disabled.\");\n }\n\n let unitID: number | null;\n let unit: BaseUnit | null = null;\n if (selectedUnit == null) {\n unitID = null;\n } else if (typeof selectedUnit === \"number\") {\n unitID = selectedUnit;\n } else if (\"unit_id\" in selectedUnit) {\n unitID = selectedUnit.unit_id;\n }\n\n if (unitID != null) {\n // Verify that the unit exists in the current colum, else throw\n const unitsMap = get(columnUnitsMapAtom);\n if (!unitsMap?.has(unitID)) {\n throw new Error(\n `Unit with ID ${unitID} not found in current column units.`,\n );\n }\n unit = unitsMap.get(unitID) ?? null;\n }\n\n let overlayPosition: RectBounds | null = null;\n\n const columnEl = get(columnRefAtom)?.current;\n\n if (unit != null && columnEl != null && target != null) {\n const rect = columnEl.getBoundingClientRect();\n const targetRect = target.getBoundingClientRect();\n overlayPosition = {\n x: targetRect.left - rect.left,\n y: targetRect.top - rect.top,\n width: targetRect.width,\n height: targetRect.height,\n };\n }\n\n set(selectedUnitIDAtom, unitID);\n set(overlayPositionAtom, overlayPosition);\n\n return unit;\n },\n);\n\nexport function useAtomOverlayPosition() {\n return scope.useAtomValue(overlayPositionAtom);\n}\n\nexport function UnitSelectionCallbackManager({\n onUnitSelected,\n}: UnitSelectionCallbacks) {\n const selectedUnit = scope.useAtomValue(selectedUnitAtom);\n useEffect(() => {\n onUnitSelected?.(selectedUnit?.unit_id ?? null, selectedUnit ?? null);\n }, [selectedUnit?.unit_id]);\n return null;\n}\n\n/** TODO: figure out if onClickedColumn is still needed\n /** This is not the natural place to get positions within the column,\n * but it will work for now.\nif (props.onClickedColumn) {\n // Infer height from top and bottom height of unit (because that's passed back with the call)\n //const py = event.y;\n //const [bottom, top] = getUnitHeightRange(unit, axisType);\n //const height = Math.abs(bottom - top);\n\n const columnClickData: ColumnClickData = {\n unitID: unit?.unit_id,\n unit,\n target,\n height: el?.getBoundingClientRect().height || 0,\n };\n props.onClickedColumn(columnClickData, event);\n}*/\n\nexport function useUnitSelectionTarget(\n unit: IUnit,\n): [React.RefObject<HTMLElement>, boolean, (evt: Event) => void] {\n const ref = useRef<HTMLElement>();\n const selectedUnit = useSelectedUnit();\n const selectUnit = useUnitSelectionDispatch();\n const selected = selectedUnit?.unit_id == unit.unit_id;\n\n const onClick = useCallback(\n (evt: Event) => {\n selectUnit?.(unit, ref.current);\n evt.stopPropagation();\n },\n [unit, selectUnit],\n );\n\n useEffect(() => {\n if (!selected || selectUnit == null) return;\n // In case we haven't set the position of the unit (if we don't have a target), set the selected unit\n selectUnit(unit, ref.current);\n\n // Scroll the unit into view\n ref.current?.scrollIntoView({\n behavior: \"smooth\",\n block: \"center\",\n inline: \"nearest\",\n });\n }, [selected, selectUnit]);\n\n return [ref, selected, onClick];\n}\n\nexport function UnitKeyboardNavigation({\n columnData,\n units,\n allowHorizontalNavigation,\n}: {\n columnData?: ColumnData[];\n units?: UnitLong[];\n allowHorizontalNavigation?: boolean;\n}) {\n if (units == null && columnData == null) {\n throw new Error(\"Either units or columnData must be provided.\");\n }\n\n let _columnData: ColumnData[] = useMemo(() => {\n if (columnData != null) return columnData;\n // Build column data from units\n const colMap = new Map<number, UnitLong[]>();\n for (const unit of units!) {\n if (!colMap.has(unit.col_id)) {\n colMap.set(unit.col_id, []);\n }\n colMap.get(unit.col_id)!.push(unit);\n }\n const cols: ColumnData[] = [];\n for (const [colID, units] of colMap) {\n cols.push({ columnID: colID, units });\n }\n // Sort columns by columnID\n cols.sort((a, b) => a.columnID - b.columnID);\n return cols;\n }, [columnData, units]);\n\n // Default to allowing horizontal navigation only if columnData is provided\n const _allowHorizontalNavigation =\n allowHorizontalNavigation ?? columnData != null;\n\n const selectedUnit = useSelectedUnit() as UnitLong | null;\n const selectUnit = useUnitSelectionDispatch();\n\n const keyMap: Record<number, Direction> = {\n 38: \"up\",\n 40: \"down\",\n };\n if (_allowHorizontalNavigation) {\n keyMap[37] = \"left\";\n keyMap[39] = \"right\";\n }\n\n useKeyHandler(\n (event) => {\n const direction = keyMap[event.keyCode];\n if (direction == null) return;\n const nextUnit = getBestUnit(_columnData, selectedUnit, direction);\n if (nextUnit == null) return;\n selectUnit(nextUnit, null);\n event.stopPropagation();\n },\n [_columnData, selectedUnit],\n );\n return null;\n}\n\ntype Direction = \"up\" | \"down\" | \"left\" | \"right\";\n\nfunction getBestUnit(\n columnData: ColumnData[],\n targetUnit: UnitLong,\n direction: Direction,\n): UnitLong | null {\n const thisColIndex = columnData.findIndex(\n (col) => col.columnID === targetUnit.col_id,\n );\n if (thisColIndex === -1) return null;\n\n // If up or down, stay in the same column\n if (direction === \"up\" || direction === \"down\") {\n const units = columnData[thisColIndex].units;\n const ix = units.findIndex((unit) => unit.unit_id === targetUnit.unit_id);\n if (ix === -1) return null;\n if (direction === \"up\") {\n return units[ix - 1] || null;\n } else {\n return units[ix + 1] || null;\n }\n }\n\n // If left or right, move to adjacent column\n let adjacentColIndex: number;\n if (direction === \"left\") {\n adjacentColIndex =\n (thisColIndex - 1 + columnData.length) % columnData.length;\n } else {\n adjacentColIndex = (thisColIndex + 1) % columnData.length;\n }\n\n const adjacentColUnits = columnData[adjacentColIndex].units;\n return getMostOverlappingUnit(targetUnit, adjacentColUnits);\n}\n\ntype UnitAgeRangeRelationship = AgeRangeQuantifiedDifference & {\n unit: UnitLong;\n};\n\nfunction getMostOverlappingUnit(\n targetUnit: UnitLong,\n candidateUnits: UnitLong[],\n): UnitLong | null {\n const targetAgeRange = [targetUnit.b_age, targetUnit.t_age];\n\n const overlaps: UnitAgeRangeRelationship[] = [];\n for (const candidate of candidateUnits) {\n const candidateAgeRange = [candidate.b_age, candidate.t_age];\n\n const rel = ageRangeQuantifiedDifference(targetAgeRange, candidateAgeRange);\n if (rel.type === AgeRangeRelationship.Identical) {\n return candidate;\n }\n overlaps.push({ ...rel, unit: candidate });\n }\n\n let bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Containing,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Contained,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.PartialOverlap,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Disjoint,\n );\n bestOverlaps.sort((a, b) => a.distance - b.distance);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n return null;\n}\n"],"names":["scope","atom","columnUnitsMapAtom","useEffect","useRef","useCallback","useMemo","units","useKeyHandler","ageRangeQuantifiedDifference","AgeRangeRelationship"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { BaseUnit, UnitLong } from '@macrostrat/api-types';
2
2
  import { IUnit } from '../units/types';
3
- import { ColumnData } from '@macrostrat/column-views';
3
+ import { ColumnData } from '@macrostrat/data-provider';
4
4
  type UnitSelectDispatch = (unit: number | BaseUnit | null, target: HTMLElement | null) => void;
5
5
  export declare function useUnitSelectionDispatch(): UnitSelectDispatch;
6
6
  export declare function useSelectedUnit(): any;
@@ -1,7 +1,7 @@
1
1
  import { useKeyHandler } from "@macrostrat/ui-components";
2
2
  import { useMemo, useEffect, useRef, useCallback } from "react";
3
3
  import { atom } from "jotai";
4
- import { scope, columnUnitsMapAtom } from "./core.js";
4
+ import { scope, columnUnitsMapAtom } from "./store.js";
5
5
  import { ageRangeQuantifiedDifference, AgeRangeRelationship } from "@macrostrat/stratigraphy-utils";
6
6
  function useUnitSelectionDispatch() {
7
7
  return scope.useSetAtom(selectedUnitAtom);
@@ -26,7 +26,7 @@ const selectedUnitAtom = atom(
26
26
  },
27
27
  (get, set, selectedUnit, target = null) => {
28
28
  if (!get(allowUnitSelectionAtom)) {
29
- throw new Error("Unit selection is disabled.");
29
+ console.error("Unit selection is disabled.");
30
30
  }
31
31
  let unitID;
32
32
  let unit = null;
@@ -1 +1 @@
1
- {"version":3,"file":"unit-selection.js","sources":["../../src/data-provider/unit-selection.ts"],"sourcesContent":["import { BaseUnit, UnitLong } from \"@macrostrat/api-types\";\nimport { useKeyHandler } from \"@macrostrat/ui-components\";\nimport { useEffect, useRef, useCallback, useMemo } from \"react\";\nimport type { RectBounds, IUnit } from \"../units/types\";\nimport { atom } from \"jotai\";\nimport { columnUnitsMapAtom, scope } from \"./core\";\nimport { ColumnData } from \"@macrostrat/column-views\";\nimport {\n AgeRangeQuantifiedDifference,\n ageRangeQuantifiedDifference,\n AgeRangeRelationship,\n} from \"@macrostrat/stratigraphy-utils\";\n\ntype UnitSelectDispatch = (\n unit: number | BaseUnit | null,\n target: HTMLElement | null,\n) => void;\n\nexport function useUnitSelectionDispatch(): UnitSelectDispatch {\n return scope.useSetAtom(selectedUnitAtom);\n}\n\nexport function useSelectedUnit() {\n return scope.useAtomValue(selectedUnitAtom);\n}\n\nexport interface ColumnClickData {\n unitID: number | null;\n unit: BaseUnit | null;\n target: HTMLElement | null;\n height: number;\n // Room for boundary IDs eventually\n}\n\nexport interface UnitSelectionCallbacks {\n // It's sort of unfortunate that we need to pass in the column ref here\n onClickedColumn?: (columnClickData: ColumnClickData, event: Event) => void;\n onUnitSelected?: <T extends BaseUnit>(\n unitID: number | null,\n unit: T | null,\n ) => void;\n}\n\nexport const allowUnitSelectionAtom = atom<boolean>(true);\n\nexport const selectedUnitIDAtom = atom<number | null>();\n\nconst overlayPositionAtom = atom<RectBounds | null>();\n\nconst columnRefAtom = atom<{ current: HTMLElement | null }>({ current: null });\n\nexport function useColumnRef() {\n return scope.useAtomValue(columnRefAtom);\n}\n\nconst selectedUnitAtom = atom(\n (get) => {\n if (!get(allowUnitSelectionAtom)) return null;\n\n const unitID = get(selectedUnitIDAtom);\n if (unitID == null) return null;\n const unitsMap = get(columnUnitsMapAtom);\n return unitsMap?.get(unitID) || null;\n },\n (\n get,\n set,\n selectedUnit: number | BaseUnit | null,\n target: HTMLElement | null = null,\n ): BaseUnit | null => {\n if (!get(allowUnitSelectionAtom)) {\n throw new Error(\"Unit selection is disabled.\");\n }\n\n let unitID: number | null;\n let unit: BaseUnit | null = null;\n if (selectedUnit == null) {\n unitID = null;\n } else if (typeof selectedUnit === \"number\") {\n unitID = selectedUnit;\n } else if (\"unit_id\" in selectedUnit) {\n unitID = selectedUnit.unit_id;\n }\n\n if (unitID != null) {\n // Verify that the unit exists in the current colum, else throw\n const unitsMap = get(columnUnitsMapAtom);\n if (!unitsMap?.has(unitID)) {\n throw new Error(\n `Unit with ID ${unitID} not found in current column units.`,\n );\n }\n unit = unitsMap.get(unitID) ?? null;\n }\n\n let overlayPosition: RectBounds | null = null;\n\n const columnEl = get(columnRefAtom)?.current;\n\n if (unit != null && columnEl != null && target != null) {\n const rect = columnEl.getBoundingClientRect();\n const targetRect = target.getBoundingClientRect();\n overlayPosition = {\n x: targetRect.left - rect.left,\n y: targetRect.top - rect.top,\n width: targetRect.width,\n height: targetRect.height,\n };\n }\n\n set(selectedUnitIDAtom, unitID);\n set(overlayPositionAtom, overlayPosition);\n\n return unit;\n },\n);\n\nexport function useAtomOverlayPosition() {\n return scope.useAtomValue(overlayPositionAtom);\n}\n\nexport function UnitSelectionCallbackManager({\n onUnitSelected,\n}: UnitSelectionCallbacks) {\n const selectedUnit = scope.useAtomValue(selectedUnitAtom);\n useEffect(() => {\n onUnitSelected?.(selectedUnit?.unit_id ?? null, selectedUnit ?? null);\n }, [selectedUnit?.unit_id]);\n return null;\n}\n\n/** TODO: figure out if onClickedColumn is still needed\n /** This is not the natural place to get positions within the column,\n * but it will work for now.\nif (props.onClickedColumn) {\n // Infer height from top and bottom height of unit (because that's passed back with the call)\n //const py = event.y;\n //const [bottom, top] = getUnitHeightRange(unit, axisType);\n //const height = Math.abs(bottom - top);\n\n const columnClickData: ColumnClickData = {\n unitID: unit?.unit_id,\n unit,\n target,\n height: el?.getBoundingClientRect().height || 0,\n };\n props.onClickedColumn(columnClickData, event);\n}*/\n\nexport function useUnitSelectionTarget(\n unit: IUnit,\n): [React.RefObject<HTMLElement>, boolean, (evt: Event) => void] {\n const ref = useRef<HTMLElement>();\n const selectedUnit = useSelectedUnit();\n const selectUnit = useUnitSelectionDispatch();\n const selected = selectedUnit?.unit_id == unit.unit_id;\n\n const onClick = useCallback(\n (evt: Event) => {\n selectUnit?.(unit, ref.current);\n evt.stopPropagation();\n },\n [unit, selectUnit],\n );\n\n useEffect(() => {\n if (!selected || selectUnit == null) return;\n // In case we haven't set the position of the unit (if we don't have a target), set the selected unit\n selectUnit(unit, ref.current);\n\n // Scroll the unit into view\n ref.current?.scrollIntoView({\n behavior: \"smooth\",\n block: \"center\",\n inline: \"nearest\",\n });\n }, [selected, selectUnit]);\n\n return [ref, selected, onClick];\n}\n\nexport function UnitKeyboardNavigation({\n columnData,\n units,\n allowHorizontalNavigation,\n}: {\n columnData?: ColumnData[];\n units?: UnitLong[];\n allowHorizontalNavigation?: boolean;\n}) {\n if (units == null && columnData == null) {\n throw new Error(\"Either units or columnData must be provided.\");\n }\n\n let _columnData: ColumnData[] = useMemo(() => {\n if (columnData != null) return columnData;\n // Build column data from units\n const colMap = new Map<number, UnitLong[]>();\n for (const unit of units!) {\n if (!colMap.has(unit.col_id)) {\n colMap.set(unit.col_id, []);\n }\n colMap.get(unit.col_id)!.push(unit);\n }\n const cols: ColumnData[] = [];\n for (const [colID, units] of colMap) {\n cols.push({ columnID: colID, units });\n }\n // Sort columns by columnID\n cols.sort((a, b) => a.columnID - b.columnID);\n return cols;\n }, [columnData, units]);\n\n // Default to allowing horizontal navigation only if columnData is provided\n const _allowHorizontalNavigation =\n allowHorizontalNavigation ?? columnData != null;\n\n const selectedUnit = useSelectedUnit() as UnitLong | null;\n const selectUnit = useUnitSelectionDispatch();\n\n const keyMap: Record<number, Direction> = {\n 38: \"up\",\n 40: \"down\",\n };\n if (_allowHorizontalNavigation) {\n keyMap[37] = \"left\";\n keyMap[39] = \"right\";\n }\n\n useKeyHandler(\n (event) => {\n const direction = keyMap[event.keyCode];\n if (direction == null) return;\n const nextUnit = getBestUnit(_columnData, selectedUnit, direction);\n if (nextUnit == null) return;\n selectUnit(nextUnit, null);\n event.stopPropagation();\n },\n [_columnData, selectedUnit],\n );\n return null;\n}\n\ntype Direction = \"up\" | \"down\" | \"left\" | \"right\";\n\nfunction getBestUnit(\n columnData: ColumnData[],\n targetUnit: UnitLong,\n direction: Direction,\n): UnitLong | null {\n const thisColIndex = columnData.findIndex(\n (col) => col.columnID === targetUnit.col_id,\n );\n if (thisColIndex === -1) return null;\n\n // If up or down, stay in the same column\n if (direction === \"up\" || direction === \"down\") {\n const units = columnData[thisColIndex].units;\n const ix = units.findIndex((unit) => unit.unit_id === targetUnit.unit_id);\n if (ix === -1) return null;\n if (direction === \"up\") {\n return units[ix - 1] || null;\n } else {\n return units[ix + 1] || null;\n }\n }\n\n // If left or right, move to adjacent column\n let adjacentColIndex: number;\n if (direction === \"left\") {\n adjacentColIndex =\n (thisColIndex - 1 + columnData.length) % columnData.length;\n } else {\n adjacentColIndex = (thisColIndex + 1) % columnData.length;\n }\n\n const adjacentColUnits = columnData[adjacentColIndex].units;\n return getMostOverlappingUnit(targetUnit, adjacentColUnits);\n}\n\ntype UnitAgeRangeRelationship = AgeRangeQuantifiedDifference & {\n unit: UnitLong;\n};\n\nfunction getMostOverlappingUnit(\n targetUnit: UnitLong,\n candidateUnits: UnitLong[],\n): UnitLong | null {\n const targetAgeRange = [targetUnit.b_age, targetUnit.t_age];\n\n const overlaps: UnitAgeRangeRelationship[] = [];\n for (const candidate of candidateUnits) {\n const candidateAgeRange = [candidate.b_age, candidate.t_age];\n\n const rel = ageRangeQuantifiedDifference(targetAgeRange, candidateAgeRange);\n if (rel.type === AgeRangeRelationship.Identical) {\n return candidate;\n }\n overlaps.push({ ...rel, unit: candidate });\n }\n\n let bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Containing,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Contained,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.PartialOverlap,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Disjoint,\n );\n bestOverlaps.sort((a, b) => a.distance - b.distance);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n return null;\n}\n"],"names":["units"],"mappings":";;;;;AAkBO,SAAS,2BAA+C;AAC7D,SAAO,MAAM,WAAW,gBAAgB;AAC1C;AAEO,SAAS,kBAAkB;AAChC,SAAO,MAAM,aAAa,gBAAgB;AAC5C;AAmBO,MAAM,yBAAyB,KAAc,IAAI;AAEjD,MAAM,qBAAqB,KAAA;AAElC,MAAM,sBAAsB,KAAA;AAE5B,MAAM,gBAAgB,KAAsC,EAAE,SAAS,MAAM;AAEtE,SAAS,eAAe;AAC7B,SAAO,MAAM,aAAa,aAAa;AACzC;AAEA,MAAM,mBAAmB;AAAA,EACvB,CAAC,QAAQ;AACP,QAAI,CAAC,IAAI,sBAAsB,EAAG,QAAO;AAEzC,UAAM,SAAS,IAAI,kBAAkB;AACrC,QAAI,UAAU,KAAM,QAAO;AAC3B,UAAM,WAAW,IAAI,kBAAkB;AACvC,WAAO,UAAU,IAAI,MAAM,KAAK;AAAA,EAClC;AAAA,EACA,CACE,KACA,KACA,cACA,SAA6B,SACT;AACpB,QAAI,CAAC,IAAI,sBAAsB,GAAG;AAChC,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,QAAI;AACJ,QAAI,OAAwB;AAC5B,QAAI,gBAAgB,MAAM;AACxB,eAAS;AAAA,IACX,WAAW,OAAO,iBAAiB,UAAU;AAC3C,eAAS;AAAA,IACX,WAAW,aAAa,cAAc;AACpC,eAAS,aAAa;AAAA,IACxB;AAEA,QAAI,UAAU,MAAM;AAElB,YAAM,WAAW,IAAI,kBAAkB;AACvC,UAAI,CAAC,UAAU,IAAI,MAAM,GAAG;AAC1B,cAAM,IAAI;AAAA,UACR,gBAAgB,MAAM;AAAA,QAAA;AAAA,MAE1B;AACA,aAAO,SAAS,IAAI,MAAM,KAAK;AAAA,IACjC;AAEA,QAAI,kBAAqC;AAEzC,UAAM,WAAW,IAAI,aAAa,GAAG;AAErC,QAAI,QAAQ,QAAQ,YAAY,QAAQ,UAAU,MAAM;AACtD,YAAM,OAAO,SAAS,sBAAA;AACtB,YAAM,aAAa,OAAO,sBAAA;AAC1B,wBAAkB;AAAA,QAChB,GAAG,WAAW,OAAO,KAAK;AAAA,QAC1B,GAAG,WAAW,MAAM,KAAK;AAAA,QACzB,OAAO,WAAW;AAAA,QAClB,QAAQ,WAAW;AAAA,MAAA;AAAA,IAEvB;AAEA,QAAI,oBAAoB,MAAM;AAC9B,QAAI,qBAAqB,eAAe;AAExC,WAAO;AAAA,EACT;AACF;AAEO,SAAS,yBAAyB;AACvC,SAAO,MAAM,aAAa,mBAAmB;AAC/C;AAEO,SAAS,6BAA6B;AAAA,EAC3C;AACF,GAA2B;AACzB,QAAM,eAAe,MAAM,aAAa,gBAAgB;AACxD,YAAU,MAAM;AACd,qBAAiB,cAAc,WAAW,MAAM,gBAAgB,IAAI;AAAA,EACtE,GAAG,CAAC,cAAc,OAAO,CAAC;AAC1B,SAAO;AACT;AAoBO,SAAS,uBACd,MAC+D;AAC/D,QAAM,MAAM,OAAA;AACZ,QAAM,eAAe,gBAAA;AACrB,QAAM,aAAa,yBAAA;AACnB,QAAM,WAAW,cAAc,WAAW,KAAK;AAE/C,QAAM,UAAU;AAAA,IACd,CAAC,QAAe;AACd,mBAAa,MAAM,IAAI,OAAO;AAC9B,UAAI,gBAAA;AAAA,IACN;AAAA,IACA,CAAC,MAAM,UAAU;AAAA,EAAA;AAGnB,YAAU,MAAM;AACd,QAAI,CAAC,YAAY,cAAc,KAAM;AAErC,eAAW,MAAM,IAAI,OAAO;AAG5B,QAAI,SAAS,eAAe;AAAA,MAC1B,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,IAAA,CACT;AAAA,EACH,GAAG,CAAC,UAAU,UAAU,CAAC;AAEzB,SAAO,CAAC,KAAK,UAAU,OAAO;AAChC;AAEO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,MAAI,SAAS,QAAQ,cAAc,MAAM;AACvC,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AAEA,MAAI,cAA4B,QAAQ,MAAM;AAC5C,QAAI,cAAc,KAAM,QAAO;AAE/B,UAAM,6BAAa,IAAA;AACnB,eAAW,QAAQ,OAAQ;AACzB,UAAI,CAAC,OAAO,IAAI,KAAK,MAAM,GAAG;AAC5B,eAAO,IAAI,KAAK,QAAQ,CAAA,CAAE;AAAA,MAC5B;AACA,aAAO,IAAI,KAAK,MAAM,EAAG,KAAK,IAAI;AAAA,IACpC;AACA,UAAM,OAAqB,CAAA;AAC3B,eAAW,CAAC,OAAOA,MAAK,KAAK,QAAQ;AACnC,WAAK,KAAK,EAAE,UAAU,OAAO,OAAAA,QAAO;AAAA,IACtC;AAEA,SAAK,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAC3C,WAAO;AAAA,EACT,GAAG,CAAC,YAAY,KAAK,CAAC;AAGtB,QAAM,6BACJ,6BAA6B,cAAc;AAE7C,QAAM,eAAe,gBAAA;AACrB,QAAM,aAAa,yBAAA;AAEnB,QAAM,SAAoC;AAAA,IACxC,IAAI;AAAA,IACJ,IAAI;AAAA,EAAA;AAEN,MAAI,4BAA4B;AAC9B,WAAO,EAAE,IAAI;AACb,WAAO,EAAE,IAAI;AAAA,EACf;AAEA;AAAA,IACE,CAAC,UAAU;AACT,YAAM,YAAY,OAAO,MAAM,OAAO;AACtC,UAAI,aAAa,KAAM;AACvB,YAAM,WAAW,YAAY,aAAa,cAAc,SAAS;AACjE,UAAI,YAAY,KAAM;AACtB,iBAAW,UAAU,IAAI;AACzB,YAAM,gBAAA;AAAA,IACR;AAAA,IACA,CAAC,aAAa,YAAY;AAAA,EAAA;AAE5B,SAAO;AACT;AAIA,SAAS,YACP,YACA,YACA,WACiB;AACjB,QAAM,eAAe,WAAW;AAAA,IAC9B,CAAC,QAAQ,IAAI,aAAa,WAAW;AAAA,EAAA;AAEvC,MAAI,iBAAiB,GAAI,QAAO;AAGhC,MAAI,cAAc,QAAQ,cAAc,QAAQ;AAC9C,UAAM,QAAQ,WAAW,YAAY,EAAE;AACvC,UAAM,KAAK,MAAM,UAAU,CAAC,SAAS,KAAK,YAAY,WAAW,OAAO;AACxE,QAAI,OAAO,GAAI,QAAO;AACtB,QAAI,cAAc,MAAM;AACtB,aAAO,MAAM,KAAK,CAAC,KAAK;AAAA,IAC1B,OAAO;AACL,aAAO,MAAM,KAAK,CAAC,KAAK;AAAA,IAC1B;AAAA,EACF;AAGA,MAAI;AACJ,MAAI,cAAc,QAAQ;AACxB,wBACG,eAAe,IAAI,WAAW,UAAU,WAAW;AAAA,EACxD,OAAO;AACL,wBAAoB,eAAe,KAAK,WAAW;AAAA,EACrD;AAEA,QAAM,mBAAmB,WAAW,gBAAgB,EAAE;AACtD,SAAO,uBAAuB,YAAY,gBAAgB;AAC5D;AAMA,SAAS,uBACP,YACA,gBACiB;AACjB,QAAM,iBAAiB,CAAC,WAAW,OAAO,WAAW,KAAK;AAE1D,QAAM,WAAuC,CAAA;AAC7C,aAAW,aAAa,gBAAgB;AACtC,UAAM,oBAAoB,CAAC,UAAU,OAAO,UAAU,KAAK;AAE3D,UAAM,MAAM,6BAA6B,gBAAgB,iBAAiB;AAC1E,QAAI,IAAI,SAAS,qBAAqB,WAAW;AAC/C,aAAO;AAAA,IACT;AACA,aAAS,KAAK,EAAE,GAAG,KAAK,MAAM,WAAW;AAAA,EAC3C;AAEA,MAAI,eAAe,SAAS;AAAA,IAC1B,CAAC,MAAM,EAAE,SAAS,qBAAqB;AAAA,EAAA;AAEzC,eAAa,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AACjD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,aAAa,CAAC,EAAE;AAAA,EACzB;AAEA,iBAAe,SAAS;AAAA,IACtB,CAAC,MAAM,EAAE,SAAS,qBAAqB;AAAA,EAAA;AAEzC,eAAa,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AACjD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,aAAa,CAAC,EAAE;AAAA,EACzB;AAEA,iBAAe,SAAS;AAAA,IACtB,CAAC,MAAM,EAAE,SAAS,qBAAqB;AAAA,EAAA;AAEzC,eAAa,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AACjD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,aAAa,CAAC,EAAE;AAAA,EACzB;AAEA,iBAAe,SAAS;AAAA,IACtB,CAAC,MAAM,EAAE,SAAS,qBAAqB;AAAA,EAAA;AAEzC,eAAa,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AACnD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,aAAa,CAAC,EAAE;AAAA,EACzB;AACA,SAAO;AACT;"}
1
+ {"version":3,"file":"unit-selection.js","sources":["../../src/data-provider/unit-selection.ts"],"sourcesContent":["import type { BaseUnit, UnitLong } from \"@macrostrat/api-types\";\nimport { useKeyHandler } from \"@macrostrat/ui-components\";\nimport { useEffect, useRef, useCallback, useMemo } from \"react\";\nimport type { RectBounds, IUnit } from \"../units/types\";\nimport { atom } from \"jotai\";\nimport { scope, columnUnitsMapAtom } from \"./store\";\nimport {\n AgeRangeQuantifiedDifference,\n ageRangeQuantifiedDifference,\n AgeRangeRelationship,\n} from \"@macrostrat/stratigraphy-utils\";\nimport type { ColumnData } from \"@macrostrat/data-provider\";\n\ntype UnitSelectDispatch = (\n unit: number | BaseUnit | null,\n target: HTMLElement | null,\n) => void;\n\nexport function useUnitSelectionDispatch(): UnitSelectDispatch {\n return scope.useSetAtom(selectedUnitAtom);\n}\n\nexport function useSelectedUnit() {\n return scope.useAtomValue(selectedUnitAtom);\n}\n\nexport interface ColumnClickData {\n unitID: number | null;\n unit: BaseUnit | null;\n target: HTMLElement | null;\n height: number;\n // Room for boundary IDs eventually\n}\n\nexport interface UnitSelectionCallbacks {\n // It's sort of unfortunate that we need to pass in the column ref here\n onClickedColumn?: (columnClickData: ColumnClickData, event: Event) => void;\n onUnitSelected?: <T extends BaseUnit>(\n unitID: number | null,\n unit: T | null,\n ) => void;\n}\n\nexport const allowUnitSelectionAtom = atom<boolean>(true);\n\nexport const selectedUnitIDAtom = atom<number | null>();\n\nconst overlayPositionAtom = atom<RectBounds | null>();\n\nconst columnRefAtom = atom<{ current: HTMLElement | null }>({ current: null });\n\nexport function useColumnRef() {\n return scope.useAtomValue(columnRefAtom);\n}\n\nconst selectedUnitAtom = atom(\n (get) => {\n if (!get(allowUnitSelectionAtom)) return null;\n\n const unitID = get(selectedUnitIDAtom);\n if (unitID == null) return null;\n const unitsMap = get(columnUnitsMapAtom);\n return unitsMap?.get(unitID) || null;\n },\n (\n get,\n set,\n selectedUnit: number | BaseUnit | null,\n target: HTMLElement | null = null,\n ): BaseUnit | null => {\n if (!get(allowUnitSelectionAtom)) {\n console.error(\"Unit selection is disabled.\");\n }\n\n let unitID: number | null;\n let unit: BaseUnit | null = null;\n if (selectedUnit == null) {\n unitID = null;\n } else if (typeof selectedUnit === \"number\") {\n unitID = selectedUnit;\n } else if (\"unit_id\" in selectedUnit) {\n unitID = selectedUnit.unit_id;\n }\n\n if (unitID != null) {\n // Verify that the unit exists in the current colum, else throw\n const unitsMap = get(columnUnitsMapAtom);\n if (!unitsMap?.has(unitID)) {\n throw new Error(\n `Unit with ID ${unitID} not found in current column units.`,\n );\n }\n unit = unitsMap.get(unitID) ?? null;\n }\n\n let overlayPosition: RectBounds | null = null;\n\n const columnEl = get(columnRefAtom)?.current;\n\n if (unit != null && columnEl != null && target != null) {\n const rect = columnEl.getBoundingClientRect();\n const targetRect = target.getBoundingClientRect();\n overlayPosition = {\n x: targetRect.left - rect.left,\n y: targetRect.top - rect.top,\n width: targetRect.width,\n height: targetRect.height,\n };\n }\n\n set(selectedUnitIDAtom, unitID);\n set(overlayPositionAtom, overlayPosition);\n\n return unit;\n },\n);\n\nexport function useAtomOverlayPosition() {\n return scope.useAtomValue(overlayPositionAtom);\n}\n\nexport function UnitSelectionCallbackManager({\n onUnitSelected,\n}: UnitSelectionCallbacks) {\n const selectedUnit = scope.useAtomValue(selectedUnitAtom);\n useEffect(() => {\n onUnitSelected?.(selectedUnit?.unit_id ?? null, selectedUnit ?? null);\n }, [selectedUnit?.unit_id]);\n return null;\n}\n\n/** TODO: figure out if onClickedColumn is still needed\n /** This is not the natural place to get positions within the column,\n * but it will work for now.\nif (props.onClickedColumn) {\n // Infer height from top and bottom height of unit (because that's passed back with the call)\n //const py = event.y;\n //const [bottom, top] = getUnitHeightRange(unit, axisType);\n //const height = Math.abs(bottom - top);\n\n const columnClickData: ColumnClickData = {\n unitID: unit?.unit_id,\n unit,\n target,\n height: el?.getBoundingClientRect().height || 0,\n };\n props.onClickedColumn(columnClickData, event);\n}*/\n\nexport function useUnitSelectionTarget(\n unit: IUnit,\n): [React.RefObject<HTMLElement>, boolean, (evt: Event) => void] {\n const ref = useRef<HTMLElement>();\n const selectedUnit = useSelectedUnit();\n const selectUnit = useUnitSelectionDispatch();\n const selected = selectedUnit?.unit_id == unit.unit_id;\n\n const onClick = useCallback(\n (evt: Event) => {\n selectUnit?.(unit, ref.current);\n evt.stopPropagation();\n },\n [unit, selectUnit],\n );\n\n useEffect(() => {\n if (!selected || selectUnit == null) return;\n // In case we haven't set the position of the unit (if we don't have a target), set the selected unit\n selectUnit(unit, ref.current);\n\n // Scroll the unit into view\n ref.current?.scrollIntoView({\n behavior: \"smooth\",\n block: \"center\",\n inline: \"nearest\",\n });\n }, [selected, selectUnit]);\n\n return [ref, selected, onClick];\n}\n\nexport function UnitKeyboardNavigation({\n columnData,\n units,\n allowHorizontalNavigation,\n}: {\n columnData?: ColumnData[];\n units?: UnitLong[];\n allowHorizontalNavigation?: boolean;\n}) {\n if (units == null && columnData == null) {\n throw new Error(\"Either units or columnData must be provided.\");\n }\n\n let _columnData: ColumnData[] = useMemo(() => {\n if (columnData != null) return columnData;\n // Build column data from units\n const colMap = new Map<number, UnitLong[]>();\n for (const unit of units!) {\n if (!colMap.has(unit.col_id)) {\n colMap.set(unit.col_id, []);\n }\n colMap.get(unit.col_id)!.push(unit);\n }\n const cols: ColumnData[] = [];\n for (const [colID, units] of colMap) {\n cols.push({ columnID: colID, units });\n }\n // Sort columns by columnID\n cols.sort((a, b) => a.columnID - b.columnID);\n return cols;\n }, [columnData, units]);\n\n // Default to allowing horizontal navigation only if columnData is provided\n const _allowHorizontalNavigation =\n allowHorizontalNavigation ?? columnData != null;\n\n const selectedUnit = useSelectedUnit() as UnitLong | null;\n const selectUnit = useUnitSelectionDispatch();\n\n const keyMap: Record<number, Direction> = {\n 38: \"up\",\n 40: \"down\",\n };\n if (_allowHorizontalNavigation) {\n keyMap[37] = \"left\";\n keyMap[39] = \"right\";\n }\n\n useKeyHandler(\n (event) => {\n const direction = keyMap[event.keyCode];\n if (direction == null) return;\n const nextUnit = getBestUnit(_columnData, selectedUnit, direction);\n if (nextUnit == null) return;\n selectUnit(nextUnit, null);\n event.stopPropagation();\n },\n [_columnData, selectedUnit],\n );\n return null;\n}\n\ntype Direction = \"up\" | \"down\" | \"left\" | \"right\";\n\nfunction getBestUnit(\n columnData: ColumnData[],\n targetUnit: UnitLong,\n direction: Direction,\n): UnitLong | null {\n const thisColIndex = columnData.findIndex(\n (col) => col.columnID === targetUnit.col_id,\n );\n if (thisColIndex === -1) return null;\n\n // If up or down, stay in the same column\n if (direction === \"up\" || direction === \"down\") {\n const units = columnData[thisColIndex].units;\n const ix = units.findIndex((unit) => unit.unit_id === targetUnit.unit_id);\n if (ix === -1) return null;\n if (direction === \"up\") {\n return units[ix - 1] || null;\n } else {\n return units[ix + 1] || null;\n }\n }\n\n // If left or right, move to adjacent column\n let adjacentColIndex: number;\n if (direction === \"left\") {\n adjacentColIndex =\n (thisColIndex - 1 + columnData.length) % columnData.length;\n } else {\n adjacentColIndex = (thisColIndex + 1) % columnData.length;\n }\n\n const adjacentColUnits = columnData[adjacentColIndex].units;\n return getMostOverlappingUnit(targetUnit, adjacentColUnits);\n}\n\ntype UnitAgeRangeRelationship = AgeRangeQuantifiedDifference & {\n unit: UnitLong;\n};\n\nfunction getMostOverlappingUnit(\n targetUnit: UnitLong,\n candidateUnits: UnitLong[],\n): UnitLong | null {\n const targetAgeRange = [targetUnit.b_age, targetUnit.t_age];\n\n const overlaps: UnitAgeRangeRelationship[] = [];\n for (const candidate of candidateUnits) {\n const candidateAgeRange = [candidate.b_age, candidate.t_age];\n\n const rel = ageRangeQuantifiedDifference(targetAgeRange, candidateAgeRange);\n if (rel.type === AgeRangeRelationship.Identical) {\n return candidate;\n }\n overlaps.push({ ...rel, unit: candidate });\n }\n\n let bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Containing,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Contained,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.PartialOverlap,\n );\n bestOverlaps.sort((a, b) => b.overlap - a.overlap);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n\n bestOverlaps = overlaps.filter(\n (d) => d.type === AgeRangeRelationship.Disjoint,\n );\n bestOverlaps.sort((a, b) => a.distance - b.distance);\n if (bestOverlaps.length > 0) {\n return bestOverlaps[0].unit;\n }\n return null;\n}\n"],"names":["units"],"mappings":";;;;;AAkBO,SAAS,2BAA+C;AAC7D,SAAO,MAAM,WAAW,gBAAgB;AAC1C;AAEO,SAAS,kBAAkB;AAChC,SAAO,MAAM,aAAa,gBAAgB;AAC5C;AAmBO,MAAM,yBAAyB,KAAc,IAAI;AAEjD,MAAM,qBAAqB,KAAA;AAElC,MAAM,sBAAsB,KAAA;AAE5B,MAAM,gBAAgB,KAAsC,EAAE,SAAS,MAAM;AAEtE,SAAS,eAAe;AAC7B,SAAO,MAAM,aAAa,aAAa;AACzC;AAEA,MAAM,mBAAmB;AAAA,EACvB,CAAC,QAAQ;AACP,QAAI,CAAC,IAAI,sBAAsB,EAAG,QAAO;AAEzC,UAAM,SAAS,IAAI,kBAAkB;AACrC,QAAI,UAAU,KAAM,QAAO;AAC3B,UAAM,WAAW,IAAI,kBAAkB;AACvC,WAAO,UAAU,IAAI,MAAM,KAAK;AAAA,EAClC;AAAA,EACA,CACE,KACA,KACA,cACA,SAA6B,SACT;AACpB,QAAI,CAAC,IAAI,sBAAsB,GAAG;AAChC,cAAQ,MAAM,6BAA6B;AAAA,IAC7C;AAEA,QAAI;AACJ,QAAI,OAAwB;AAC5B,QAAI,gBAAgB,MAAM;AACxB,eAAS;AAAA,IACX,WAAW,OAAO,iBAAiB,UAAU;AAC3C,eAAS;AAAA,IACX,WAAW,aAAa,cAAc;AACpC,eAAS,aAAa;AAAA,IACxB;AAEA,QAAI,UAAU,MAAM;AAElB,YAAM,WAAW,IAAI,kBAAkB;AACvC,UAAI,CAAC,UAAU,IAAI,MAAM,GAAG;AAC1B,cAAM,IAAI;AAAA,UACR,gBAAgB,MAAM;AAAA,QAAA;AAAA,MAE1B;AACA,aAAO,SAAS,IAAI,MAAM,KAAK;AAAA,IACjC;AAEA,QAAI,kBAAqC;AAEzC,UAAM,WAAW,IAAI,aAAa,GAAG;AAErC,QAAI,QAAQ,QAAQ,YAAY,QAAQ,UAAU,MAAM;AACtD,YAAM,OAAO,SAAS,sBAAA;AACtB,YAAM,aAAa,OAAO,sBAAA;AAC1B,wBAAkB;AAAA,QAChB,GAAG,WAAW,OAAO,KAAK;AAAA,QAC1B,GAAG,WAAW,MAAM,KAAK;AAAA,QACzB,OAAO,WAAW;AAAA,QAClB,QAAQ,WAAW;AAAA,MAAA;AAAA,IAEvB;AAEA,QAAI,oBAAoB,MAAM;AAC9B,QAAI,qBAAqB,eAAe;AAExC,WAAO;AAAA,EACT;AACF;AAEO,SAAS,yBAAyB;AACvC,SAAO,MAAM,aAAa,mBAAmB;AAC/C;AAEO,SAAS,6BAA6B;AAAA,EAC3C;AACF,GAA2B;AACzB,QAAM,eAAe,MAAM,aAAa,gBAAgB;AACxD,YAAU,MAAM;AACd,qBAAiB,cAAc,WAAW,MAAM,gBAAgB,IAAI;AAAA,EACtE,GAAG,CAAC,cAAc,OAAO,CAAC;AAC1B,SAAO;AACT;AAoBO,SAAS,uBACd,MAC+D;AAC/D,QAAM,MAAM,OAAA;AACZ,QAAM,eAAe,gBAAA;AACrB,QAAM,aAAa,yBAAA;AACnB,QAAM,WAAW,cAAc,WAAW,KAAK;AAE/C,QAAM,UAAU;AAAA,IACd,CAAC,QAAe;AACd,mBAAa,MAAM,IAAI,OAAO;AAC9B,UAAI,gBAAA;AAAA,IACN;AAAA,IACA,CAAC,MAAM,UAAU;AAAA,EAAA;AAGnB,YAAU,MAAM;AACd,QAAI,CAAC,YAAY,cAAc,KAAM;AAErC,eAAW,MAAM,IAAI,OAAO;AAG5B,QAAI,SAAS,eAAe;AAAA,MAC1B,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,IAAA,CACT;AAAA,EACH,GAAG,CAAC,UAAU,UAAU,CAAC;AAEzB,SAAO,CAAC,KAAK,UAAU,OAAO;AAChC;AAEO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,MAAI,SAAS,QAAQ,cAAc,MAAM;AACvC,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AAEA,MAAI,cAA4B,QAAQ,MAAM;AAC5C,QAAI,cAAc,KAAM,QAAO;AAE/B,UAAM,6BAAa,IAAA;AACnB,eAAW,QAAQ,OAAQ;AACzB,UAAI,CAAC,OAAO,IAAI,KAAK,MAAM,GAAG;AAC5B,eAAO,IAAI,KAAK,QAAQ,CAAA,CAAE;AAAA,MAC5B;AACA,aAAO,IAAI,KAAK,MAAM,EAAG,KAAK,IAAI;AAAA,IACpC;AACA,UAAM,OAAqB,CAAA;AAC3B,eAAW,CAAC,OAAOA,MAAK,KAAK,QAAQ;AACnC,WAAK,KAAK,EAAE,UAAU,OAAO,OAAAA,QAAO;AAAA,IACtC;AAEA,SAAK,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAC3C,WAAO;AAAA,EACT,GAAG,CAAC,YAAY,KAAK,CAAC;AAGtB,QAAM,6BACJ,6BAA6B,cAAc;AAE7C,QAAM,eAAe,gBAAA;AACrB,QAAM,aAAa,yBAAA;AAEnB,QAAM,SAAoC;AAAA,IACxC,IAAI;AAAA,IACJ,IAAI;AAAA,EAAA;AAEN,MAAI,4BAA4B;AAC9B,WAAO,EAAE,IAAI;AACb,WAAO,EAAE,IAAI;AAAA,EACf;AAEA;AAAA,IACE,CAAC,UAAU;AACT,YAAM,YAAY,OAAO,MAAM,OAAO;AACtC,UAAI,aAAa,KAAM;AACvB,YAAM,WAAW,YAAY,aAAa,cAAc,SAAS;AACjE,UAAI,YAAY,KAAM;AACtB,iBAAW,UAAU,IAAI;AACzB,YAAM,gBAAA;AAAA,IACR;AAAA,IACA,CAAC,aAAa,YAAY;AAAA,EAAA;AAE5B,SAAO;AACT;AAIA,SAAS,YACP,YACA,YACA,WACiB;AACjB,QAAM,eAAe,WAAW;AAAA,IAC9B,CAAC,QAAQ,IAAI,aAAa,WAAW;AAAA,EAAA;AAEvC,MAAI,iBAAiB,GAAI,QAAO;AAGhC,MAAI,cAAc,QAAQ,cAAc,QAAQ;AAC9C,UAAM,QAAQ,WAAW,YAAY,EAAE;AACvC,UAAM,KAAK,MAAM,UAAU,CAAC,SAAS,KAAK,YAAY,WAAW,OAAO;AACxE,QAAI,OAAO,GAAI,QAAO;AACtB,QAAI,cAAc,MAAM;AACtB,aAAO,MAAM,KAAK,CAAC,KAAK;AAAA,IAC1B,OAAO;AACL,aAAO,MAAM,KAAK,CAAC,KAAK;AAAA,IAC1B;AAAA,EACF;AAGA,MAAI;AACJ,MAAI,cAAc,QAAQ;AACxB,wBACG,eAAe,IAAI,WAAW,UAAU,WAAW;AAAA,EACxD,OAAO;AACL,wBAAoB,eAAe,KAAK,WAAW;AAAA,EACrD;AAEA,QAAM,mBAAmB,WAAW,gBAAgB,EAAE;AACtD,SAAO,uBAAuB,YAAY,gBAAgB;AAC5D;AAMA,SAAS,uBACP,YACA,gBACiB;AACjB,QAAM,iBAAiB,CAAC,WAAW,OAAO,WAAW,KAAK;AAE1D,QAAM,WAAuC,CAAA;AAC7C,aAAW,aAAa,gBAAgB;AACtC,UAAM,oBAAoB,CAAC,UAAU,OAAO,UAAU,KAAK;AAE3D,UAAM,MAAM,6BAA6B,gBAAgB,iBAAiB;AAC1E,QAAI,IAAI,SAAS,qBAAqB,WAAW;AAC/C,aAAO;AAAA,IACT;AACA,aAAS,KAAK,EAAE,GAAG,KAAK,MAAM,WAAW;AAAA,EAC3C;AAEA,MAAI,eAAe,SAAS;AAAA,IAC1B,CAAC,MAAM,EAAE,SAAS,qBAAqB;AAAA,EAAA;AAEzC,eAAa,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AACjD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,aAAa,CAAC,EAAE;AAAA,EACzB;AAEA,iBAAe,SAAS;AAAA,IACtB,CAAC,MAAM,EAAE,SAAS,qBAAqB;AAAA,EAAA;AAEzC,eAAa,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AACjD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,aAAa,CAAC,EAAE;AAAA,EACzB;AAEA,iBAAe,SAAS;AAAA,IACtB,CAAC,MAAM,EAAE,SAAS,qBAAqB;AAAA,EAAA;AAEzC,eAAa,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AACjD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,aAAa,CAAC,EAAE;AAAA,EACzB;AAEA,iBAAe,SAAS;AAAA,IACtB,CAAC,MAAM,EAAE,SAAS,qBAAqB;AAAA,EAAA;AAEzC,eAAa,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AACnD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,aAAa,CAAC,EAAE;AAAA,EACzB;AACA,SAAO;AACT;"}
@@ -6,10 +6,10 @@ import { useMeasurementData } from "./data-provider.js";
6
6
  import { IsotopesDataArea, IsotopeDataPoint } from "./data-area.js";
7
7
  import { referenceMeasuresToColumn } from "@macrostrat/stratigraphy-utils";
8
8
  import { SVG, ColumnLayoutProvider, useColumnLayout } from "@macrostrat/column-components";
9
- import styles from "./isotopes-column.module.sass.js";
9
+ import h$2 from "./isotopes-column.module.sass.js";
10
10
  import { scaleLinear } from "d3-scale";
11
11
  import { useMacrostratColumnData, useMacrostratUnits } from "../../data-provider/store.js";
12
- const h = h$1.styled(styles);
12
+ const h = h$1.styled(h$2);
13
13
  function ScaleLine(props) {
14
14
  let { value, className, labelBottom, labelOffset, ...rest } = props;
15
15
  const { sections } = useMacrostratColumnData();
@@ -1 +1 @@
1
- {"version":3,"file":"isotopes-column.js","sources":["../../../src/facets/carbon-isotopes/isotopes-column.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport hyper from \"@macrostrat/hyper\";\nimport classNames from \"classnames\";\nimport { AxisBottom } from \"@visx/axis\";\nimport { useMeasurementData } from \"./data-provider\";\n\nimport {\n IsotopesDataArea,\n useDataLocator,\n IsotopeDataPoint,\n} from \"./data-area\";\nimport { referenceMeasuresToColumn } from \"@macrostrat/stratigraphy-utils\";\nimport {\n SVG,\n ColumnLayoutProvider,\n useColumnLayout,\n} from \"@macrostrat/column-components\";\nimport {\n useMacrostratColumnData,\n useMacrostratUnits,\n} from \"../../data-provider\";\nimport styles from \"./isotopes-column.module.sass\";\nimport { scaleLinear } from \"d3-scale\";\n\nconst h = hyper.styled(styles);\n\ntype IsotopesTextProps = {\n datum: any;\n text: string;\n};\n\nfunction IsotopeText({ datum, text, ...rest }: IsotopesTextProps) {\n const { pointLocator } = useDataLocator();\n const [x, y] = pointLocator(datum);\n return h(\n \"text\",\n {\n x,\n y,\n ...rest,\n },\n text,\n );\n}\n\ninterface ScaleLineProps {\n value: number;\n className?: string;\n labelBottom?: boolean;\n labelOffset?: number;\n strokeDasharray?: string;\n stroke?: string | number;\n}\n\nfunction ScaleLine(props: ScaleLineProps) {\n let { value, className, labelBottom, labelOffset, ...rest } = props;\n const { sections } = useMacrostratColumnData();\n\n const { xScale } = useColumnLayout();\n const x = xScale(value);\n const transform = `translate(${x})`;\n className = classNames(className, { zero: value === 0 });\n return h(\"g.tick\", { transform, className, key: value }, [\n h(\n \"g.tick-lines\",\n sections.map((d) => {\n const { scaleInfo } = d;\n const y1 = scaleInfo.offset;\n const y2 = y1 + scaleInfo.pixelHeight;\n return h(\"line\", {\n y1,\n y2,\n strokeDasharray: props.strokeDasharray,\n strokeWidth: 1,\n });\n }),\n ),\n ]);\n}\n\nfunction unnestPoints(measures) {\n let points = [];\n for (const meas of measures) {\n const vals = meas.measure_value.map((d, i) => {\n return {\n value: d,\n age: meas.measure_age[i],\n position: meas.measure_position[i],\n unit_id: meas.unit_id,\n sample_id: meas.sample_no[i],\n measurement: meas.measurement,\n };\n });\n Array.prototype.push.apply(points, vals);\n }\n return points;\n}\n\ninterface IsotopesDatasetProps {\n color?: string;\n parameter: string;\n}\n\ninterface IsotopeColumnProps extends IsotopesDatasetProps {\n width: number;\n tickValues?: number[];\n label: string;\n domain?: [number, number];\n transform?: string;\n getHeight?: Function;\n nTicks?: number;\n showAxis?: boolean;\n}\n\nfunction IsotopesDataset(props) {\n const { parameter, color = \"dodgerblue\" } = props;\n const units = useMacrostratUnits();\n const measures = useMeasurementData() ?? [];\n\n const points = useMemo(() => {\n const data = measures.filter((d) => d.measurement === parameter);\n const refMeasures = referenceMeasuresToColumn(units, data);\n return unnestPoints(refMeasures);\n }, [measures, parameter, units]);\n\n return h(\n IsotopesDataArea,\n {\n getHeight(d) {\n return d.age;\n },\n } as any,\n h(\n \"g.data-points\",\n points.map((d) => {\n return h(IsotopeDataPoint, {\n datum: d,\n fill: color,\n });\n }),\n ),\n );\n}\n\nfunction IsotopesColumn(\n props: IsotopeColumnProps & { children?: React.ReactNode },\n) {\n const {\n width = 120,\n domain = [-14, 6],\n parameter,\n label,\n color = \"dodgerblue\",\n children = null,\n transform,\n getHeight,\n showAxis = true,\n tickValues: _tickVals,\n nTicks = 6,\n ...rest\n } = props;\n\n const { totalHeight } = useMacrostratColumnData();\n\n let _children: any = children;\n if (children == null && parameter != null) {\n _children = h(IsotopesDataset, { parameter, color, getHeight });\n }\n\n const xScale = useMemo(\n () => scaleLinear().domain(domain).range([0, width]),\n [domain, width],\n );\n\n const tickValues = _tickVals ?? xScale.ticks(nTicks);\n\n return h(\"div.isotopes-column\", [\n h(\n SVG,\n {\n height: totalHeight,\n innerWidth: width,\n paddingH: 15,\n },\n h(\n ColumnLayoutProvider,\n { width, xScale },\n h(\"g.isotopes-column\", { className: parameter, transform }, [\n h(ColumnScaleLines, {\n xScale,\n tickValues,\n width,\n ...rest,\n }),\n _children,\n ]),\n ),\n ),\n h.if(showAxis)(ColumnScaleAxis, {\n width,\n label: label ?? parameter,\n xScale,\n tickValues,\n ...rest,\n }),\n ]);\n}\n\nfunction ColumnScaleAxis(props) {\n const { label, xScale, width, showAxis = true, tickValues, ...rest } = props;\n\n return h(\"div.isotopes-scale-axis\", [\n h(\n SVG,\n {\n innerWidth: width,\n height: 45,\n paddingH: 15,\n },\n [\n h(AxisBottom, {\n scale: xScale,\n tickLength: 5,\n tickValues,\n stroke: \"var(--column-stroke-color)\",\n tickStroke: \"var(--column-stroke-color)\",\n ...rest,\n label,\n }),\n ],\n ),\n ]);\n}\n\nfunction ColumnScaleLines(props) {\n const { tickValues, xScale } = props;\n\n return h(\n \"g.scale-lines\",\n tickValues.map((value) => {\n return h(ScaleLine, { value });\n }),\n );\n}\n\nexport { IsotopesColumn, IsotopesDataset };\n"],"names":["hyper"],"mappings":";;;;;;;;;;;AAwBA,MAAM,IAAIA,IAAM,OAAO,MAAM;AA8B7B,SAAS,UAAU,OAAuB;AACxC,MAAI,EAAE,OAAO,WAAW,aAAa,aAAa,GAAG,SAAS;AAC9D,QAAM,EAAE,SAAA,IAAa,wBAAA;AAErB,QAAM,EAAE,OAAA,IAAW,gBAAA;AACnB,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,YAAY,aAAa,CAAC;AAChC,cAAY,WAAW,WAAW,EAAE,MAAM,UAAU,GAAG;AACvD,SAAO,EAAE,UAAU,EAAE,WAAW,WAAW,KAAK,SAAS;AAAA,IACvD;AAAA,MACE;AAAA,MACA,SAAS,IAAI,CAAC,MAAM;AAClB,cAAM,EAAE,cAAc;AACtB,cAAM,KAAK,UAAU;AACrB,cAAM,KAAK,KAAK,UAAU;AAC1B,eAAO,EAAE,QAAQ;AAAA,UACf;AAAA,UACA;AAAA,UACA,iBAAiB,MAAM;AAAA,UACvB,aAAa;AAAA,QAAA,CACd;AAAA,MACH,CAAC;AAAA,IAAA;AAAA,EACH,CACD;AACH;AAEA,SAAS,aAAa,UAAU;AAC9B,MAAI,SAAS,CAAA;AACb,aAAW,QAAQ,UAAU;AAC3B,UAAM,OAAO,KAAK,cAAc,IAAI,CAAC,GAAG,MAAM;AAC5C,aAAO;AAAA,QACL,OAAO;AAAA,QACP,KAAK,KAAK,YAAY,CAAC;AAAA,QACvB,UAAU,KAAK,iBAAiB,CAAC;AAAA,QACjC,SAAS,KAAK;AAAA,QACd,WAAW,KAAK,UAAU,CAAC;AAAA,QAC3B,aAAa,KAAK;AAAA,MAAA;AAAA,IAEtB,CAAC;AACD,UAAM,UAAU,KAAK,MAAM,QAAQ,IAAI;AAAA,EACzC;AACA,SAAO;AACT;AAkBA,SAAS,gBAAgB,OAAO;AAC9B,QAAM,EAAE,WAAW,QAAQ,aAAA,IAAiB;AAC5C,QAAM,QAAQ,mBAAA;AACd,QAAM,WAAW,mBAAA,KAAwB,CAAA;AAEzC,QAAM,SAAS,QAAQ,MAAM;AAC3B,UAAM,OAAO,SAAS,OAAO,CAAC,MAAM,EAAE,gBAAgB,SAAS;AAC/D,UAAM,cAAc,0BAA0B,OAAO,IAAI;AACzD,WAAO,aAAa,WAAW;AAAA,EACjC,GAAG,CAAC,UAAU,WAAW,KAAK,CAAC;AAE/B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,UAAU,GAAG;AACX,eAAO,EAAE;AAAA,MACX;AAAA,IAAA;AAAA,IAEF;AAAA,MACE;AAAA,MACA,OAAO,IAAI,CAAC,MAAM;AAChB,eAAO,EAAE,kBAAkB;AAAA,UACzB,OAAO;AAAA,UACP,MAAM;AAAA,QAAA,CACP;AAAA,MACH,CAAC;AAAA,IAAA;AAAA,EACH;AAEJ;AAEA,SAAS,eACP,OACA;AACA,QAAM;AAAA,IACJ,QAAQ;AAAA,IACR,SAAS,CAAC,KAAK,CAAC;AAAA,IAChB;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,GAAG;AAAA,EAAA,IACD;AAEJ,QAAM,EAAE,YAAA,IAAgB,wBAAA;AAExB,MAAI,YAAiB;AACrB,MAAI,YAAY,QAAQ,aAAa,MAAM;AACzC,gBAAY,EAAE,iBAAiB,EAAE,WAAW,OAAO,WAAW;AAAA,EAChE;AAEA,QAAM,SAAS;AAAA,IACb,MAAM,YAAA,EAAc,OAAO,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;AAAA,IACnD,CAAC,QAAQ,KAAK;AAAA,EAAA;AAGhB,QAAM,aAAa,aAAa,OAAO,MAAM,MAAM;AAEnD,SAAO,EAAE,uBAAuB;AAAA,IAC9B;AAAA,MACE;AAAA,MACA;AAAA,QACE,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,UAAU;AAAA,MAAA;AAAA,MAEZ;AAAA,QACE;AAAA,QACA,EAAE,OAAO,OAAA;AAAA,QACT,EAAE,qBAAqB,EAAE,WAAW,WAAW,aAAa;AAAA,UAC1D,EAAE,kBAAkB;AAAA,YAClB;AAAA,YACA;AAAA,YACA;AAAA,YACA,GAAG;AAAA,UAAA,CACJ;AAAA,UACD;AAAA,QAAA,CACD;AAAA,MAAA;AAAA,IACH;AAAA,IAEF,EAAE,GAAG,QAAQ,EAAE,iBAAiB;AAAA,MAC9B;AAAA,MACA,OAAO,SAAS;AAAA,MAChB;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IAAA,CACJ;AAAA,EAAA,CACF;AACH;AAEA,SAAS,gBAAgB,OAAO;AAC9B,QAAM,EAAE,OAAO,QAAQ,OAAO,WAAW,MAAM,YAAY,GAAG,KAAA,IAAS;AAEvE,SAAO,EAAE,2BAA2B;AAAA,IAClC;AAAA,MACE;AAAA,MACA;AAAA,QACE,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR,UAAU;AAAA,MAAA;AAAA,MAEZ;AAAA,QACE,EAAE,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,YAAY;AAAA,UACZ;AAAA,UACA,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,GAAG;AAAA,UACH;AAAA,QAAA,CACD;AAAA,MAAA;AAAA,IACH;AAAA,EACF,CACD;AACH;AAEA,SAAS,iBAAiB,OAAO;AAC/B,QAAM,EAAE,YAAY,OAAA,IAAW;AAE/B,SAAO;AAAA,IACL;AAAA,IACA,WAAW,IAAI,CAAC,UAAU;AACxB,aAAO,EAAE,WAAW,EAAE,OAAO;AAAA,IAC/B,CAAC;AAAA,EAAA;AAEL;"}
1
+ {"version":3,"file":"isotopes-column.js","sources":["../../../src/facets/carbon-isotopes/isotopes-column.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport hyper from \"@macrostrat/hyper\";\nimport classNames from \"classnames\";\nimport { AxisBottom } from \"@visx/axis\";\nimport { useMeasurementData } from \"./data-provider\";\n\nimport {\n IsotopesDataArea,\n useDataLocator,\n IsotopeDataPoint,\n} from \"./data-area\";\nimport { referenceMeasuresToColumn } from \"@macrostrat/stratigraphy-utils\";\nimport {\n SVG,\n ColumnLayoutProvider,\n useColumnLayout,\n} from \"@macrostrat/column-components\";\nimport {\n useMacrostratColumnData,\n useMacrostratUnits,\n} from \"../../data-provider\";\nimport styles from \"./isotopes-column.module.sass\";\nimport { scaleLinear } from \"d3-scale\";\n\nconst h = hyper.styled(styles);\n\ntype IsotopesTextProps = {\n datum: any;\n text: string;\n};\n\nfunction IsotopeText({ datum, text, ...rest }: IsotopesTextProps) {\n const { pointLocator } = useDataLocator();\n const [x, y] = pointLocator(datum);\n return h(\n \"text\",\n {\n x,\n y,\n ...rest,\n },\n text,\n );\n}\n\ninterface ScaleLineProps {\n value: number;\n className?: string;\n labelBottom?: boolean;\n labelOffset?: number;\n strokeDasharray?: string;\n stroke?: string | number;\n}\n\nfunction ScaleLine(props: ScaleLineProps) {\n let { value, className, labelBottom, labelOffset, ...rest } = props;\n const { sections } = useMacrostratColumnData();\n\n const { xScale } = useColumnLayout();\n const x = xScale(value);\n const transform = `translate(${x})`;\n className = classNames(className, { zero: value === 0 });\n return h(\"g.tick\", { transform, className, key: value }, [\n h(\n \"g.tick-lines\",\n sections.map((d) => {\n const { scaleInfo } = d;\n const y1 = scaleInfo.offset;\n const y2 = y1 + scaleInfo.pixelHeight;\n return h(\"line\", {\n y1,\n y2,\n strokeDasharray: props.strokeDasharray,\n strokeWidth: 1,\n });\n }),\n ),\n ]);\n}\n\nfunction unnestPoints(measures) {\n let points = [];\n for (const meas of measures) {\n const vals = meas.measure_value.map((d, i) => {\n return {\n value: d,\n age: meas.measure_age[i],\n position: meas.measure_position[i],\n unit_id: meas.unit_id,\n sample_id: meas.sample_no[i],\n measurement: meas.measurement,\n };\n });\n Array.prototype.push.apply(points, vals);\n }\n return points;\n}\n\ninterface IsotopesDatasetProps {\n color?: string;\n parameter: string;\n}\n\ninterface IsotopeColumnProps extends IsotopesDatasetProps {\n width: number;\n tickValues?: number[];\n label: string;\n domain?: [number, number];\n transform?: string;\n getHeight?: Function;\n nTicks?: number;\n showAxis?: boolean;\n}\n\nfunction IsotopesDataset(props) {\n const { parameter, color = \"dodgerblue\" } = props;\n const units = useMacrostratUnits();\n const measures = useMeasurementData() ?? [];\n\n const points = useMemo(() => {\n const data = measures.filter((d) => d.measurement === parameter);\n const refMeasures = referenceMeasuresToColumn(units, data);\n return unnestPoints(refMeasures);\n }, [measures, parameter, units]);\n\n return h(\n IsotopesDataArea,\n {\n getHeight(d) {\n return d.age;\n },\n } as any,\n h(\n \"g.data-points\",\n points.map((d) => {\n return h(IsotopeDataPoint, {\n datum: d,\n fill: color,\n });\n }),\n ),\n );\n}\n\nfunction IsotopesColumn(\n props: IsotopeColumnProps & { children?: React.ReactNode },\n) {\n const {\n width = 120,\n domain = [-14, 6],\n parameter,\n label,\n color = \"dodgerblue\",\n children = null,\n transform,\n getHeight,\n showAxis = true,\n tickValues: _tickVals,\n nTicks = 6,\n ...rest\n } = props;\n\n const { totalHeight } = useMacrostratColumnData();\n\n let _children: any = children;\n if (children == null && parameter != null) {\n _children = h(IsotopesDataset, { parameter, color, getHeight });\n }\n\n const xScale = useMemo(\n () => scaleLinear().domain(domain).range([0, width]),\n [domain, width],\n );\n\n const tickValues = _tickVals ?? xScale.ticks(nTicks);\n\n return h(\"div.isotopes-column\", [\n h(\n SVG,\n {\n height: totalHeight,\n innerWidth: width,\n paddingH: 15,\n },\n h(\n ColumnLayoutProvider,\n { width, xScale },\n h(\"g.isotopes-column\", { className: parameter, transform }, [\n h(ColumnScaleLines, {\n xScale,\n tickValues,\n width,\n ...rest,\n }),\n _children,\n ]),\n ),\n ),\n h.if(showAxis)(ColumnScaleAxis, {\n width,\n label: label ?? parameter,\n xScale,\n tickValues,\n ...rest,\n }),\n ]);\n}\n\nfunction ColumnScaleAxis(props) {\n const { label, xScale, width, showAxis = true, tickValues, ...rest } = props;\n\n return h(\"div.isotopes-scale-axis\", [\n h(\n SVG,\n {\n innerWidth: width,\n height: 45,\n paddingH: 15,\n },\n [\n h(AxisBottom, {\n scale: xScale,\n tickLength: 5,\n tickValues,\n stroke: \"var(--column-stroke-color)\",\n tickStroke: \"var(--column-stroke-color)\",\n ...rest,\n label,\n }),\n ],\n ),\n ]);\n}\n\nfunction ColumnScaleLines(props) {\n const { tickValues, xScale } = props;\n\n return h(\n \"g.scale-lines\",\n tickValues.map((value) => {\n return h(ScaleLine, { value });\n }),\n );\n}\n\nexport { IsotopesColumn, IsotopesDataset };\n"],"names":["hyper","styles"],"mappings":"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"}
@@ -1,5 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
+ const h$1 = require("@macrostrat/hyper");
4
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
5
+ const h__default = /* @__PURE__ */ _interopDefault(h$1);
3
6
  const tick = "_tick_y4y1w_24";
4
7
  const zero = "_zero_y4y1w_24";
5
8
  const styles = {
@@ -9,7 +12,9 @@ const styles = {
9
12
  tick,
10
13
  zero
11
14
  };
12
- exports.default = styles;
15
+ let h = h__default.default.styled(styles);
16
+ Object.assign(h, styles);
17
+ exports.default = h;
13
18
  exports.tick = tick;
14
19
  exports.zero = zero;
15
20
  //# sourceMappingURL=isotopes-column.module.sass.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"isotopes-column.module.sass.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"isotopes-column.module.sass.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
@@ -1,3 +1,4 @@
1
+ import h$1 from "@macrostrat/hyper";
1
2
  const tick = "_tick_y4y1w_24";
2
3
  const zero = "_zero_y4y1w_24";
3
4
  const styles = {
@@ -7,8 +8,10 @@ const styles = {
7
8
  tick,
8
9
  zero
9
10
  };
11
+ let h = h$1.styled(styles);
12
+ Object.assign(h, styles);
10
13
  export {
11
- styles as default,
14
+ h as default,
12
15
  tick,
13
16
  zero
14
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"isotopes-column.module.sass.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
1
+ {"version":3,"file":"isotopes-column.module.sass.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
@@ -2,14 +2,14 @@ import { DetritalSpectrumPlot, DetritalSeries, usePlotArea } from "@macrostrat/d
2
2
  import h$1 from "@macrostrat/hyper";
3
3
  import { useDetritalMeasurements } from "./provider.js";
4
4
  import { useMemo } from "react";
5
- import styles from "./index.module.sass.js";
5
+ import h$2 from "./index.module.sass.js";
6
6
  import classNames from "classnames";
7
7
  import { group } from "d3-array";
8
8
  import { NonIdealState, Spinner } from "@blueprintjs/core";
9
9
  import { BaseMeasurementsColumn, mergeHeightRanges } from "../measurements/base.js";
10
10
  import { useMacrostratColumnData } from "../../data-provider/store.js";
11
11
  import { getUnitHeightRange } from "../../prepare-units/utils.js";
12
- const h = h$1.styled(styles);
12
+ const h = h$1.styled(h$2);
13
13
  function prepareDetritalData(data, units, axisType) {
14
14
  const measurementsGrouped = group(data, (d) => d.measuremeta_id);
15
15
  const resMap = /* @__PURE__ */ new Map();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/facets/detrital-zircon/index.ts"],"sourcesContent":["import {\n DetritalSpectrumPlot,\n DetritalSeries,\n usePlotArea,\n} from \"@macrostrat/data-components\";\nimport type { IUnit } from \"../../units/types\";\nimport hyper from \"@macrostrat/hyper\";\nimport { useDetritalMeasurements, MeasurementInfo } from \"./provider\";\nimport { useMemo } from \"react\";\nimport styles from \"./index.module.sass\";\nimport classNames from \"classnames\";\nimport {\n BaseMeasurementsColumn,\n mergeHeightRanges,\n ColumnMeasurementData,\n} from \"../measurements\";\nimport { group } from \"d3-array\";\nimport { ColumnAxisType } from \"@macrostrat/column-components\";\nimport { useMacrostratColumnData } from \"../../data-provider\";\nimport { getUnitHeightRange } from \"../../prepare-units\";\nimport { NonIdealState, Spinner } from \"@blueprintjs/core\";\n\nconst h = hyper.styled(styles);\n\ninterface DetritalItemProps {\n note: DZMeasurementInfo;\n spacing?: {\n below?: number;\n above?: number;\n };\n width?: number;\n height?: number;\n color?: string;\n}\n\ninterface DZMeasurementInfo extends ColumnMeasurementData<MeasurementInfo[]> {\n units: IUnit[];\n}\n\nfunction prepareDetritalData(\n data: MeasurementInfo[],\n units: IUnit[],\n axisType: ColumnAxisType,\n) {\n /** Right now measurement data could be duplicated if there are multiple units linked to the same\n * measuremeta_id. THis happens because matches to units might be at a lower rank (e.g, if the column\n * contains Formations but the measurements are linked to a Group). To handle this, we group by measuremeta_id\n * and then create unique keys based on the set of units linked to each measurement.\n */\n\n // Group data by measuremeta_id\n const measurementsGrouped = group(data, (d) => d.measuremeta_id);\n\n const resMap = new Map<string, DZMeasurementInfo>();\n\n for (const measurements of measurementsGrouped.values()) {\n // Get a list of unique unit_ids for this measurement\n const unitIDs = new Set(measurements.map((m) => m.unit_id));\n const ids = Array.from(unitIDs);\n ids.sort();\n // Key is unique to the set of units\n const key = ids.join(\"-\");\n\n if (!resMap.has(key)) {\n const unitData = ids\n .map((id) => {\n return units.find((u) => u.unit_id === id);\n })\n .filter(Boolean);\n\n const positions = unitData.map((unit) => {\n const [height, top_height] = getUnitHeightRange(unit, axisType);\n return { height, top_height };\n });\n\n // merge positions (note: we could also have multiple separate notes per measurement)\n const pos = mergeHeightRanges(positions, axisType);\n\n resMap.set(key, {\n id: key,\n data: [],\n units: unitData as IUnit[],\n ...pos,\n });\n }\n resMap.get(key)!.data.push(measurements[0]);\n }\n\n return Array.from(resMap.values());\n}\n\nfunction DetritalColumn({ columnID, color = \"magenta\" }) {\n const data = useDetritalMeasurements({ col_id: columnID });\n\n const width = 400;\n const paddingLeft = 40;\n\n const spectrumWidth = width - paddingLeft;\n\n const noteComponent = useMemo(() => {\n return (props) => {\n return h(DetritalGroup, {\n width: spectrumWidth,\n height: 40,\n color,\n ...props,\n });\n };\n }, [width, color]);\n\n const { axisType, units } = useMacrostratColumnData();\n\n const data1 = useMemo(() => {\n if (data == null || units == null) return null;\n return prepareDetritalData(data, units, axisType);\n }, [data, units, axisType]);\n\n if (data1 == null) return h(NonIdealState, h(Spinner));\n\n return h(BaseMeasurementsColumn, {\n data: data1,\n noteComponent,\n deltaConnectorAttachment: 20,\n });\n}\n\nfunction DepositionalAge({ unit }) {\n const { xScale, height } = usePlotArea();\n\n const { t_age, b_age } = unit;\n const x = xScale(t_age);\n const x1 = xScale(b_age);\n\n return h(\"rect.depositional-age\", { x, width: x1 - x, y: 0, height });\n}\n\nfunction DetritalGroup(props: DetritalItemProps) {\n const { note, width, height, color, spacing } = props;\n const { data, units } = note;\n\n const _color = color;\n\n const spaceBelow = spacing?.below ?? 100;\n const hideAxisLabels = spaceBelow < 60;\n\n return h(\n \"div.detrital-group\",\n { className: classNames({ \"hide-axis\": hideAxisLabels }) },\n [\n h(\n DetritalSpectrumPlot,\n { width, innerHeight: height, showAxisLabels: true, paddingBottom: 40 },\n [\n units.map((unit) => {\n return h(DepositionalAge, { unit });\n }),\n data.map((d) => {\n return h(DetritalSeries, {\n bandwidth: 20,\n data: d.measure_value,\n color: _color,\n });\n }),\n ],\n ),\n ],\n );\n}\n\nexport { DetritalColumn, DetritalGroup };\n"],"names":["hyper"],"mappings":";;;;;;;;;;;AAsBA,MAAM,IAAIA,IAAM,OAAO,MAAM;AAiB7B,SAAS,oBACP,MACA,OACA,UACA;AAQA,QAAM,sBAAsB,MAAM,MAAM,CAAC,MAAM,EAAE,cAAc;AAE/D,QAAM,6BAAa,IAAA;AAEnB,aAAW,gBAAgB,oBAAoB,UAAU;AAEvD,UAAM,UAAU,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AAC1D,UAAM,MAAM,MAAM,KAAK,OAAO;AAC9B,QAAI,KAAA;AAEJ,UAAM,MAAM,IAAI,KAAK,GAAG;AAExB,QAAI,CAAC,OAAO,IAAI,GAAG,GAAG;AACpB,YAAM,WAAW,IACd,IAAI,CAAC,OAAO;AACX,eAAO,MAAM,KAAK,CAAC,MAAM,EAAE,YAAY,EAAE;AAAA,MAC3C,CAAC,EACA,OAAO,OAAO;AAEjB,YAAM,YAAY,SAAS,IAAI,CAAC,SAAS;AACvC,cAAM,CAAC,QAAQ,UAAU,IAAI,mBAAmB,MAAM,QAAQ;AAC9D,eAAO,EAAE,QAAQ,WAAA;AAAA,MACnB,CAAC;AAGD,YAAM,MAAM,kBAAkB,WAAW,QAAQ;AAEjD,aAAO,IAAI,KAAK;AAAA,QACd,IAAI;AAAA,QACJ,MAAM,CAAA;AAAA,QACN,OAAO;AAAA,QACP,GAAG;AAAA,MAAA,CACJ;AAAA,IACH;AACA,WAAO,IAAI,GAAG,EAAG,KAAK,KAAK,aAAa,CAAC,CAAC;AAAA,EAC5C;AAEA,SAAO,MAAM,KAAK,OAAO,OAAA,CAAQ;AACnC;AAEA,SAAS,eAAe,EAAE,UAAU,QAAQ,aAAa;AACvD,QAAM,OAAO,wBAAwB,EAAE,QAAQ,UAAU;AAEzD,QAAM,QAAQ;AACd,QAAM,cAAc;AAEpB,QAAM,gBAAgB,QAAQ;AAE9B,QAAM,gBAAgB,QAAQ,MAAM;AAClC,WAAO,CAAC,UAAU;AAChB,aAAO,EAAE,eAAe;AAAA,QACtB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR;AAAA,QACA,GAAG;AAAA,MAAA,CACJ;AAAA,IACH;AAAA,EACF,GAAG,CAAC,OAAO,KAAK,CAAC;AAEjB,QAAM,EAAE,UAAU,MAAA,IAAU,wBAAA;AAE5B,QAAM,QAAQ,QAAQ,MAAM;AAC1B,QAAI,QAAQ,QAAQ,SAAS,KAAM,QAAO;AAC1C,WAAO,oBAAoB,MAAM,OAAO,QAAQ;AAAA,EAClD,GAAG,CAAC,MAAM,OAAO,QAAQ,CAAC;AAE1B,MAAI,SAAS,KAAM,QAAO,EAAE,eAAe,EAAE,OAAO,CAAC;AAErD,SAAO,EAAE,wBAAwB;AAAA,IAC/B,MAAM;AAAA,IACN;AAAA,IACA,0BAA0B;AAAA,EAAA,CAC3B;AACH;AAEA,SAAS,gBAAgB,EAAE,QAAQ;AACjC,QAAM,EAAE,QAAQ,OAAA,IAAW,YAAA;AAE3B,QAAM,EAAE,OAAO,MAAA,IAAU;AACzB,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,KAAK,OAAO,KAAK;AAEvB,SAAO,EAAE,yBAAyB,EAAE,GAAG,OAAO,KAAK,GAAG,GAAG,GAAG,QAAQ;AACtE;AAEA,SAAS,cAAc,OAA0B;AAC/C,QAAM,EAAE,MAAM,OAAO,QAAQ,OAAO,YAAY;AAChD,QAAM,EAAE,MAAM,MAAA,IAAU;AAExB,QAAM,SAAS;AAEf,QAAM,aAAa,SAAS,SAAS;AACrC,QAAM,iBAAiB,aAAa;AAEpC,SAAO;AAAA,IACL;AAAA,IACA,EAAE,WAAW,WAAW,EAAE,aAAa,eAAA,CAAgB,EAAA;AAAA,IACvD;AAAA,MACE;AAAA,QACE;AAAA,QACA,EAAE,OAAO,aAAa,QAAQ,gBAAgB,MAAM,eAAe,GAAA;AAAA,QACnE;AAAA,UACE,MAAM,IAAI,CAAC,SAAS;AAClB,mBAAO,EAAE,iBAAiB,EAAE,MAAM;AAAA,UACpC,CAAC;AAAA,UACD,KAAK,IAAI,CAAC,MAAM;AACd,mBAAO,EAAE,gBAAgB;AAAA,cACvB,WAAW;AAAA,cACX,MAAM,EAAE;AAAA,cACR,OAAO;AAAA,YAAA,CACR;AAAA,UACH,CAAC;AAAA,QAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEJ;"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/facets/detrital-zircon/index.ts"],"sourcesContent":["import {\n DetritalSpectrumPlot,\n DetritalSeries,\n usePlotArea,\n} from \"@macrostrat/data-components\";\nimport type { IUnit } from \"../../units/types\";\nimport hyper from \"@macrostrat/hyper\";\nimport { useDetritalMeasurements, MeasurementInfo } from \"./provider\";\nimport { useMemo } from \"react\";\nimport styles from \"./index.module.sass\";\nimport classNames from \"classnames\";\nimport {\n BaseMeasurementsColumn,\n mergeHeightRanges,\n ColumnMeasurementData,\n} from \"../measurements\";\nimport { group } from \"d3-array\";\nimport { ColumnAxisType } from \"@macrostrat/column-components\";\nimport { useMacrostratColumnData } from \"../../data-provider\";\nimport { getUnitHeightRange } from \"../../prepare-units\";\nimport { NonIdealState, Spinner } from \"@blueprintjs/core\";\n\nconst h = hyper.styled(styles);\n\ninterface DetritalItemProps {\n note: DZMeasurementInfo;\n spacing?: {\n below?: number;\n above?: number;\n };\n width?: number;\n height?: number;\n color?: string;\n}\n\ninterface DZMeasurementInfo extends ColumnMeasurementData<MeasurementInfo[]> {\n units: IUnit[];\n}\n\nfunction prepareDetritalData(\n data: MeasurementInfo[],\n units: IUnit[],\n axisType: ColumnAxisType,\n) {\n /** Right now measurement data could be duplicated if there are multiple units linked to the same\n * measuremeta_id. THis happens because matches to units might be at a lower rank (e.g, if the column\n * contains Formations but the measurements are linked to a Group). To handle this, we group by measuremeta_id\n * and then create unique keys based on the set of units linked to each measurement.\n */\n\n // Group data by measuremeta_id\n const measurementsGrouped = group(data, (d) => d.measuremeta_id);\n\n const resMap = new Map<string, DZMeasurementInfo>();\n\n for (const measurements of measurementsGrouped.values()) {\n // Get a list of unique unit_ids for this measurement\n const unitIDs = new Set(measurements.map((m) => m.unit_id));\n const ids = Array.from(unitIDs);\n ids.sort();\n // Key is unique to the set of units\n const key = ids.join(\"-\");\n\n if (!resMap.has(key)) {\n const unitData = ids\n .map((id) => {\n return units.find((u) => u.unit_id === id);\n })\n .filter(Boolean);\n\n const positions = unitData.map((unit) => {\n const [height, top_height] = getUnitHeightRange(unit, axisType);\n return { height, top_height };\n });\n\n // merge positions (note: we could also have multiple separate notes per measurement)\n const pos = mergeHeightRanges(positions, axisType);\n\n resMap.set(key, {\n id: key,\n data: [],\n units: unitData as IUnit[],\n ...pos,\n });\n }\n resMap.get(key)!.data.push(measurements[0]);\n }\n\n return Array.from(resMap.values());\n}\n\nfunction DetritalColumn({ columnID, color = \"magenta\" }) {\n const data = useDetritalMeasurements({ col_id: columnID });\n\n const width = 400;\n const paddingLeft = 40;\n\n const spectrumWidth = width - paddingLeft;\n\n const noteComponent = useMemo(() => {\n return (props) => {\n return h(DetritalGroup, {\n width: spectrumWidth,\n height: 40,\n color,\n ...props,\n });\n };\n }, [width, color]);\n\n const { axisType, units } = useMacrostratColumnData();\n\n const data1 = useMemo(() => {\n if (data == null || units == null) return null;\n return prepareDetritalData(data, units, axisType);\n }, [data, units, axisType]);\n\n if (data1 == null) return h(NonIdealState, h(Spinner));\n\n return h(BaseMeasurementsColumn, {\n data: data1,\n noteComponent,\n deltaConnectorAttachment: 20,\n });\n}\n\nfunction DepositionalAge({ unit }) {\n const { xScale, height } = usePlotArea();\n\n const { t_age, b_age } = unit;\n const x = xScale(t_age);\n const x1 = xScale(b_age);\n\n return h(\"rect.depositional-age\", { x, width: x1 - x, y: 0, height });\n}\n\nfunction DetritalGroup(props: DetritalItemProps) {\n const { note, width, height, color, spacing } = props;\n const { data, units } = note;\n\n const _color = color;\n\n const spaceBelow = spacing?.below ?? 100;\n const hideAxisLabels = spaceBelow < 60;\n\n return h(\n \"div.detrital-group\",\n { className: classNames({ \"hide-axis\": hideAxisLabels }) },\n [\n h(\n DetritalSpectrumPlot,\n { width, innerHeight: height, showAxisLabels: true, paddingBottom: 40 },\n [\n units.map((unit) => {\n return h(DepositionalAge, { unit });\n }),\n data.map((d) => {\n return h(DetritalSeries, {\n bandwidth: 20,\n data: d.measure_value,\n color: _color,\n });\n }),\n ],\n ),\n ],\n );\n}\n\nexport { DetritalColumn, DetritalGroup };\n"],"names":["hyper","styles"],"mappings":";;;;;;;;;;;AAsBA,MAAM,IAAIA,IAAM,OAAOC,GAAM;AAiB7B,SAAS,oBACP,MACA,OACA,UACA;AAQA,QAAM,sBAAsB,MAAM,MAAM,CAAC,MAAM,EAAE,cAAc;AAE/D,QAAM,6BAAa,IAAA;AAEnB,aAAW,gBAAgB,oBAAoB,UAAU;AAEvD,UAAM,UAAU,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AAC1D,UAAM,MAAM,MAAM,KAAK,OAAO;AAC9B,QAAI,KAAA;AAEJ,UAAM,MAAM,IAAI,KAAK,GAAG;AAExB,QAAI,CAAC,OAAO,IAAI,GAAG,GAAG;AACpB,YAAM,WAAW,IACd,IAAI,CAAC,OAAO;AACX,eAAO,MAAM,KAAK,CAAC,MAAM,EAAE,YAAY,EAAE;AAAA,MAC3C,CAAC,EACA,OAAO,OAAO;AAEjB,YAAM,YAAY,SAAS,IAAI,CAAC,SAAS;AACvC,cAAM,CAAC,QAAQ,UAAU,IAAI,mBAAmB,MAAM,QAAQ;AAC9D,eAAO,EAAE,QAAQ,WAAA;AAAA,MACnB,CAAC;AAGD,YAAM,MAAM,kBAAkB,WAAW,QAAQ;AAEjD,aAAO,IAAI,KAAK;AAAA,QACd,IAAI;AAAA,QACJ,MAAM,CAAA;AAAA,QACN,OAAO;AAAA,QACP,GAAG;AAAA,MAAA,CACJ;AAAA,IACH;AACA,WAAO,IAAI,GAAG,EAAG,KAAK,KAAK,aAAa,CAAC,CAAC;AAAA,EAC5C;AAEA,SAAO,MAAM,KAAK,OAAO,OAAA,CAAQ;AACnC;AAEA,SAAS,eAAe,EAAE,UAAU,QAAQ,aAAa;AACvD,QAAM,OAAO,wBAAwB,EAAE,QAAQ,UAAU;AAEzD,QAAM,QAAQ;AACd,QAAM,cAAc;AAEpB,QAAM,gBAAgB,QAAQ;AAE9B,QAAM,gBAAgB,QAAQ,MAAM;AAClC,WAAO,CAAC,UAAU;AAChB,aAAO,EAAE,eAAe;AAAA,QACtB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR;AAAA,QACA,GAAG;AAAA,MAAA,CACJ;AAAA,IACH;AAAA,EACF,GAAG,CAAC,OAAO,KAAK,CAAC;AAEjB,QAAM,EAAE,UAAU,MAAA,IAAU,wBAAA;AAE5B,QAAM,QAAQ,QAAQ,MAAM;AAC1B,QAAI,QAAQ,QAAQ,SAAS,KAAM,QAAO;AAC1C,WAAO,oBAAoB,MAAM,OAAO,QAAQ;AAAA,EAClD,GAAG,CAAC,MAAM,OAAO,QAAQ,CAAC;AAE1B,MAAI,SAAS,KAAM,QAAO,EAAE,eAAe,EAAE,OAAO,CAAC;AAErD,SAAO,EAAE,wBAAwB;AAAA,IAC/B,MAAM;AAAA,IACN;AAAA,IACA,0BAA0B;AAAA,EAAA,CAC3B;AACH;AAEA,SAAS,gBAAgB,EAAE,QAAQ;AACjC,QAAM,EAAE,QAAQ,OAAA,IAAW,YAAA;AAE3B,QAAM,EAAE,OAAO,MAAA,IAAU;AACzB,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,KAAK,OAAO,KAAK;AAEvB,SAAO,EAAE,yBAAyB,EAAE,GAAG,OAAO,KAAK,GAAG,GAAG,GAAG,QAAQ;AACtE;AAEA,SAAS,cAAc,OAA0B;AAC/C,QAAM,EAAE,MAAM,OAAO,QAAQ,OAAO,YAAY;AAChD,QAAM,EAAE,MAAM,MAAA,IAAU;AAExB,QAAM,SAAS;AAEf,QAAM,aAAa,SAAS,SAAS;AACrC,QAAM,iBAAiB,aAAa;AAEpC,SAAO;AAAA,IACL;AAAA,IACA,EAAE,WAAW,WAAW,EAAE,aAAa,eAAA,CAAgB,EAAA;AAAA,IACvD;AAAA,MACE;AAAA,QACE;AAAA,QACA,EAAE,OAAO,aAAa,QAAQ,gBAAgB,MAAM,eAAe,GAAA;AAAA,QACnE;AAAA,UACE,MAAM,IAAI,CAAC,SAAS;AAClB,mBAAO,EAAE,iBAAiB,EAAE,MAAM;AAAA,UACpC,CAAC;AAAA,UACD,KAAK,IAAI,CAAC,MAAM;AACd,mBAAO,EAAE,gBAAgB;AAAA,cACvB,WAAW;AAAA,cACX,MAAM,EAAE;AAAA,cACR,OAAO;AAAA,YAAA,CACR;AAAA,UACH,CAAC;AAAA,QAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEJ;"}
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ const h$1 = require("@macrostrat/hyper");
3
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
4
+ const h__default = /* @__PURE__ */ _interopDefault(h$1);
2
5
  const styles = {
3
6
  "depositional-age": "_depositional-age_ngsgr_1",
4
7
  "detrital-group": "_detrital-group_ngsgr_8",
@@ -6,5 +9,7 @@ const styles = {
6
9
  "dz-spectra": "_dz-spectra_ngsgr_16",
7
10
  "floating-axis": "_floating-axis_ngsgr_20"
8
11
  };
9
- module.exports = styles;
12
+ let h = h__default.default.styled(styles);
13
+ Object.assign(h, styles);
14
+ module.exports = h;
10
15
  //# sourceMappingURL=index.module.sass.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.module.sass.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
1
+ {"version":3,"file":"index.module.sass.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;"}
@@ -1,3 +1,4 @@
1
+ import h$1 from "@macrostrat/hyper";
1
2
  const styles = {
2
3
  "depositional-age": "_depositional-age_ngsgr_1",
3
4
  "detrital-group": "_detrital-group_ngsgr_8",
@@ -5,7 +6,9 @@ const styles = {
5
6
  "dz-spectra": "_dz-spectra_ngsgr_16",
6
7
  "floating-axis": "_floating-axis_ngsgr_20"
7
8
  };
9
+ let h = h$1.styled(styles);
10
+ Object.assign(h, styles);
8
11
  export {
9
- styles as default
12
+ h as default
10
13
  };
11
14
  //# sourceMappingURL=index.module.sass.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.module.sass.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
1
+ {"version":3,"file":"index.module.sass.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
@@ -1,12 +1,12 @@
1
1
  import h$1 from "@macrostrat/hyper";
2
2
  import { useFossilData, FossilDataType } from "./provider.js";
3
3
  import { ColumnAxisType } from "@macrostrat/column-components";
4
- import styles from "./taxon-ranges.module.sass.js";
4
+ import h$2 from "./taxon-ranges.module.sass.js";
5
5
  import { scaleLinear } from "d3-scale";
6
6
  import { BaseMeasurementsColumn, groupNotesByPixelDistance, TruncatedList, standardizeMeasurementHeight } from "../measurements/base.js";
7
7
  import { useMacrostratColumnData, useCompositeScale } from "../../data-provider/store.js";
8
8
  import { getPositionWithinUnit, getUnitHeightRange } from "../../prepare-units/utils.js";
9
- const h = h$1.styled(styles);
9
+ const h = h$1.styled(h$2);
10
10
  function PBDBFossilsColumn({
11
11
  columnID,
12
12
  type = FossilDataType.Collections