@macrostrat/column-views 3.12.0 → 3.12.2

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 (55) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/age-axis.cjs +1 -2
  3. package/dist/age-axis.cjs.map +1 -1
  4. package/dist/age-axis.js +1 -2
  5. package/dist/age-axis.js.map +1 -1
  6. package/dist/age-model/details.cjs +2 -3
  7. package/dist/age-model/details.cjs.map +1 -1
  8. package/dist/age-model/details.js +2 -3
  9. package/dist/age-model/details.js.map +1 -1
  10. package/dist/age-model/surfaces.cjs +1 -2
  11. package/dist/age-model/surfaces.cjs.map +1 -1
  12. package/dist/age-model/surfaces.js +1 -2
  13. package/dist/age-model/surfaces.js.map +1 -1
  14. package/dist/column-views.css +17 -17
  15. package/dist/column.cjs +11 -1
  16. package/dist/column.cjs.map +1 -1
  17. package/dist/column.js +11 -1
  18. package/dist/column.js.map +1 -1
  19. package/dist/index.cjs +25 -16
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.js +3 -3
  22. package/dist/prepare-units/composite-scale.cjs +16 -6
  23. package/dist/prepare-units/composite-scale.cjs.map +1 -1
  24. package/dist/prepare-units/composite-scale.d.ts +1 -1
  25. package/dist/prepare-units/composite-scale.js +16 -6
  26. package/dist/prepare-units/composite-scale.js.map +1 -1
  27. package/dist/prepare-units/density.cjs +21 -13
  28. package/dist/prepare-units/density.cjs.map +1 -1
  29. package/dist/prepare-units/density.d.ts +18 -11
  30. package/dist/prepare-units/density.js +21 -13
  31. package/dist/prepare-units/density.js.map +1 -1
  32. package/dist/prepare-units/helpers.cjs +16 -1
  33. package/dist/prepare-units/helpers.cjs.map +1 -1
  34. package/dist/prepare-units/helpers.js +16 -1
  35. package/dist/prepare-units/helpers.js.map +1 -1
  36. package/dist/prepare-units/index.cjs.map +1 -1
  37. package/dist/prepare-units/index.js.map +1 -1
  38. package/dist/unit-details/age-range.cjs +14 -44
  39. package/dist/unit-details/age-range.cjs.map +1 -1
  40. package/dist/unit-details/age-range.d.ts +2 -18
  41. package/dist/unit-details/age-range.js +6 -44
  42. package/dist/unit-details/age-range.js.map +1 -1
  43. package/dist/unit-details/utils.cjs +0 -5
  44. package/dist/unit-details/utils.cjs.map +1 -1
  45. package/dist/unit-details/utils.js +0 -5
  46. package/dist/unit-details/utils.js.map +1 -1
  47. package/package.json +3 -3
  48. package/src/age-model/details.ts +2 -2
  49. package/src/age-model/surfaces.ts +2 -2
  50. package/src/column.ts +17 -1
  51. package/src/prepare-units/composite-scale.ts +22 -9
  52. package/src/prepare-units/density.ts +36 -25
  53. package/src/prepare-units/helpers.ts +35 -1
  54. package/src/prepare-units/index.ts +0 -1
  55. package/src/unit-details/age-range.ts +13 -59
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.12.2] - 2026-09-25 [_changes_](https://github.com/UW-Macrostrat/web-components/compare/@macrostrat/column-views-v3.12.1...@macrostrat/column-views-v3.12.2)
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix unit ordering for height axes
8
+ [bdcb8223](https://github.com/UW-Macrostrat/web-components/commit/bdcb82232b87da5b1dbb922c9258b24eba66529c)
9
+ - Add a default sectionOptions that increases scale when sections are zoomed
10
+ [bdcb8223](https://github.com/UW-Macrostrat/web-components/commit/bdcb82232b87da5b1dbb922c9258b24eba66529c)
11
+ - Updated dependencies
12
+ [bdcb8223](https://github.com/UW-Macrostrat/web-components/commit/bdcb82232b87da5b1dbb922c9258b24eba66529c)
13
+ - @macrostrat/data-provider@1.4.1
14
+
15
+ ## [3.12.1] - 2026-09-25 [_changes_](https://github.com/UW-Macrostrat/web-components/compare/@macrostrat/column-views-v3.12.0...@macrostrat/column-views-v3.12.1)
16
+
17
+ ### Patch Changes
18
+
19
+ - - `Proportion`, `AgeLabel` and `getAge` are re-exported from
20
+ `@macrostrat/data-components`; surface calibration tags use `IntervalTag`'s
21
+ `proportion`
22
+ [5be3d4c9](https://github.com/UW-Macrostrat/web-components/commit/5be3d4c9f3fcf4442720a7ed3bdb72abca4db4ab)
23
+ - Updated dependencies
24
+ [5be3d4c9](https://github.com/UW-Macrostrat/web-components/commit/5be3d4c9f3fcf4442720a7ed3bdb72abca4db4ab)
25
+ - Updated dependencies
26
+ [dc1feb79](https://github.com/UW-Macrostrat/web-components/commit/dc1feb7961e6f901fe6a3dbb2d3f3bdba03cc32c)
27
+ - @macrostrat/data-provider@1.4.0
28
+ - @macrostrat/data-components@1.7.0
29
+
3
30
  ## [3.12.0] - 2026-09-21 [_changes_](https://github.com/UW-Macrostrat/web-components/compare/@macrostrat/column-views-v3.11.0...@macrostrat/column-views-v3.12.0)
4
31
 
5
32
  ### Minor Changes
package/dist/age-axis.cjs CHANGED
@@ -5,7 +5,6 @@ const columnComponents = require("@macrostrat/column-components");
5
5
  require("react");
6
6
  const ageAxis_module = require("./age-axis.module.sass.cjs");
7
7
  const dataComponents = require("@macrostrat/data-components");
8
- const ageRange = require("./unit-details/age-range.cjs");
9
8
  const store = require("./data-provider/store.cjs");
10
9
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
11
10
  const h__default = /* @__PURE__ */ _interopDefault(h$1);
@@ -114,7 +113,7 @@ function AgeCursor({ age }) {
114
113
  top: heightPx
115
114
  }
116
115
  },
117
- [h("div.line"), h(ageRange.AgeLabel, { age, className: "label" })]
116
+ [h("div.line"), h(dataComponents.AgeLabel, { age, className: "label" })]
118
117
  );
119
118
  }
120
119
  exports.AgeCursor = AgeCursor;
@@ -1 +1 @@
1
- {"version":3,"file":"age-axis.cjs","sources":["../src/age-axis.ts"],"sourcesContent":["import hyper from \"@macrostrat/hyper\";\nimport {\n SVG,\n ColumnAxis,\n ColumnContext,\n ColumnAxisType,\n AgeAxis,\n} from \"@macrostrat/column-components\";\nimport { useContext } from \"react\";\nimport styles from \"./age-axis.module.sass\";\nimport { useCompositeScale, useMacrostratColumnData } from \"./data-provider\";\nimport { Parenthetical } from \"@macrostrat/data-components\";\nimport { AgeLabel } from \"./unit-details\";\nimport { PackageScaleLayoutData } from \"./prepare-units\";\n\nconst h = hyper.styled(styles);\n\nconst AgeAxisCore = ({ ticks, tickSpacing = 40, showDomain = false }) => {\n const { pixelHeight } = useContext(ColumnContext);\n // A tick roughly every 40 pixels\n let v = Math.max(Math.round(pixelHeight / tickSpacing), 1);\n\n return h(\"g.axis\", { transform: \"translate(20 0)\" }, [\n h(ColumnAxis, {\n ticks: v,\n showDomain,\n }),\n ]);\n};\n\nexport function VerticalAxisLabel(props) {\n const { label = \"Age\", unit = \"Ma\", className, height } = props;\n return h(\n \"div.column-axis-label.age-axis-label\",\n { className, style: { height } },\n [\n label,\n \" \",\n h.if(unit)(Parenthetical, { className: \"age-axis-unit\" }, unit),\n ],\n );\n}\n\ninterface CompositeAgeAxisProps {\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport function CompositeAgeAxis(rest: CompositeAgeAxisProps) {\n const { axisType, sections, totalHeight } = useMacrostratColumnData();\n\n const packages = sections.map((section) => {\n return {\n key: `section-${section.section_id}`,\n ...section.scaleInfo,\n };\n });\n\n return h(CompositeAgeAxisCore, {\n axisType,\n packages,\n totalHeight,\n ...rest,\n });\n}\n\nexport function ApproximateHeightAxis(rest: CompositeAgeAxisProps) {\n /** Axis to show approximate height based on dynamic column scales */\n const { axisType, sections, totalHeight } = useMacrostratColumnData();\n\n const packages = sections.map((section) => {\n const { scaleInfo } = section;\n if (scaleInfo.heightScale == null) {\n throw new Error(\"No height scale available for section\");\n }\n return {\n key: `section-${section.section_id}`,\n ...scaleInfo,\n scale: scaleInfo.heightScale, // Use height scale instead of age scale\n // This only works with dynamic columns\n };\n });\n\n return h(CompositeAgeAxisCore, {\n axisType,\n axisLabel: \"Approx. height\",\n axisUnit: \"m\",\n packages,\n totalHeight,\n ...rest,\n });\n}\n\nexport interface CompositeStratigraphicScaleInfo extends CompositeAgeAxisProps {\n axisType: ColumnAxisType;\n axisLabel?: string;\n axisUnit?: string;\n totalHeight: number;\n packages: PackageScaleLayoutData[];\n}\n\nexport function CompositeAgeAxisCore(props: CompositeStratigraphicScaleInfo) {\n const { axisType, axisLabel, axisUnit, totalHeight, packages, ...rest } =\n props;\n\n if (axisType == ColumnAxisType.ORDINAL) {\n return null;\n }\n\n let _axisLabel: string = axisLabel ?? \"Age\";\n let _axisUnit = axisUnit ?? \"Ma\";\n if (axisType == ColumnAxisType.DEPTH) {\n _axisLabel = \"Depth\";\n _axisUnit = \"m\";\n } else if (axisType == ColumnAxisType.HEIGHT) {\n _axisLabel = \"Height\";\n _axisUnit = \"m\";\n }\n\n return h(\"div.composite-age-axis\", rest, [\n h(VerticalAxisLabel, {\n label: _axisLabel,\n unit: _axisUnit,\n height: totalHeight,\n }),\n h(\n SVG,\n {\n className: \"age-axis-column\",\n style: { width: `22px`, height: `${totalHeight}px` },\n width: 22,\n height: totalHeight,\n },\n packages.map((group, i) => {\n const { key, scale } = group;\n\n return h(AgeAxis, {\n key,\n className: \"age-axis\",\n scale,\n tickSizeOuter: 3,\n });\n }),\n ),\n ]);\n}\n\nexport function AgeCursor({ age }) {\n /** A cursor that shows the age at a specific point on the age axis. */\n const scale = useCompositeScale();\n const heightPx = scale(age);\n\n if (age == null || heightPx == null) {\n return null;\n }\n\n return h(\n \"div.age-cursor\",\n {\n style: {\n top: heightPx,\n },\n },\n [h(\"div.line\"), h(AgeLabel, { age, className: \"label\" })],\n );\n}\n"],"names":["hyper","styles","Parenthetical","useMacrostratColumnData","ColumnAxisType","SVG","AgeAxis","useCompositeScale","AgeLabel"],"mappings":"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"}
1
+ {"version":3,"file":"age-axis.cjs","sources":["../src/age-axis.ts"],"sourcesContent":["import hyper from \"@macrostrat/hyper\";\nimport {\n SVG,\n ColumnAxis,\n ColumnContext,\n ColumnAxisType,\n AgeAxis,\n} from \"@macrostrat/column-components\";\nimport { useContext } from \"react\";\nimport styles from \"./age-axis.module.sass\";\nimport { useCompositeScale, useMacrostratColumnData } from \"./data-provider\";\nimport { Parenthetical } from \"@macrostrat/data-components\";\nimport { AgeLabel } from \"./unit-details\";\nimport { PackageScaleLayoutData } from \"./prepare-units\";\n\nconst h = hyper.styled(styles);\n\nconst AgeAxisCore = ({ ticks, tickSpacing = 40, showDomain = false }) => {\n const { pixelHeight } = useContext(ColumnContext);\n // A tick roughly every 40 pixels\n let v = Math.max(Math.round(pixelHeight / tickSpacing), 1);\n\n return h(\"g.axis\", { transform: \"translate(20 0)\" }, [\n h(ColumnAxis, {\n ticks: v,\n showDomain,\n }),\n ]);\n};\n\nexport function VerticalAxisLabel(props) {\n const { label = \"Age\", unit = \"Ma\", className, height } = props;\n return h(\n \"div.column-axis-label.age-axis-label\",\n { className, style: { height } },\n [\n label,\n \" \",\n h.if(unit)(Parenthetical, { className: \"age-axis-unit\" }, unit),\n ],\n );\n}\n\ninterface CompositeAgeAxisProps {\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport function CompositeAgeAxis(rest: CompositeAgeAxisProps) {\n const { axisType, sections, totalHeight } = useMacrostratColumnData();\n\n const packages = sections.map((section) => {\n return {\n key: `section-${section.section_id}`,\n ...section.scaleInfo,\n };\n });\n\n return h(CompositeAgeAxisCore, {\n axisType,\n packages,\n totalHeight,\n ...rest,\n });\n}\n\nexport function ApproximateHeightAxis(rest: CompositeAgeAxisProps) {\n /** Axis to show approximate height based on dynamic column scales */\n const { axisType, sections, totalHeight } = useMacrostratColumnData();\n\n const packages = sections.map((section) => {\n const { scaleInfo } = section;\n if (scaleInfo.heightScale == null) {\n throw new Error(\"No height scale available for section\");\n }\n return {\n key: `section-${section.section_id}`,\n ...scaleInfo,\n scale: scaleInfo.heightScale, // Use height scale instead of age scale\n // This only works with dynamic columns\n };\n });\n\n return h(CompositeAgeAxisCore, {\n axisType,\n axisLabel: \"Approx. height\",\n axisUnit: \"m\",\n packages,\n totalHeight,\n ...rest,\n });\n}\n\nexport interface CompositeStratigraphicScaleInfo extends CompositeAgeAxisProps {\n axisType: ColumnAxisType;\n axisLabel?: string;\n axisUnit?: string;\n totalHeight: number;\n packages: PackageScaleLayoutData[];\n}\n\nexport function CompositeAgeAxisCore(props: CompositeStratigraphicScaleInfo) {\n const { axisType, axisLabel, axisUnit, totalHeight, packages, ...rest } =\n props;\n\n if (axisType == ColumnAxisType.ORDINAL) {\n return null;\n }\n\n let _axisLabel: string = axisLabel ?? \"Age\";\n let _axisUnit = axisUnit ?? \"Ma\";\n if (axisType == ColumnAxisType.DEPTH) {\n _axisLabel = \"Depth\";\n _axisUnit = \"m\";\n } else if (axisType == ColumnAxisType.HEIGHT) {\n _axisLabel = \"Height\";\n _axisUnit = \"m\";\n }\n\n return h(\"div.composite-age-axis\", rest, [\n h(VerticalAxisLabel, {\n label: _axisLabel,\n unit: _axisUnit,\n height: totalHeight,\n }),\n h(\n SVG,\n {\n className: \"age-axis-column\",\n style: { width: `22px`, height: `${totalHeight}px` },\n width: 22,\n height: totalHeight,\n },\n packages.map((group, i) => {\n const { key, scale } = group;\n\n return h(AgeAxis, {\n key,\n className: \"age-axis\",\n scale,\n tickSizeOuter: 3,\n });\n }),\n ),\n ]);\n}\n\nexport function AgeCursor({ age }) {\n /** A cursor that shows the age at a specific point on the age axis. */\n const scale = useCompositeScale();\n const heightPx = scale(age);\n\n if (age == null || heightPx == null) {\n return null;\n }\n\n return h(\n \"div.age-cursor\",\n {\n style: {\n top: heightPx,\n },\n },\n [h(\"div.line\"), h(AgeLabel, { age, className: \"label\" })],\n );\n}\n"],"names":["hyper","styles","Parenthetical","useMacrostratColumnData","ColumnAxisType","SVG","AgeAxis","useCompositeScale","AgeLabel"],"mappings":"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"}
package/dist/age-axis.js CHANGED
@@ -2,8 +2,7 @@ import h$1 from "@macrostrat/hyper";
2
2
  import { ColumnAxisType, SVG, AgeAxis } from "@macrostrat/column-components";
3
3
  import "react";
4
4
  import h$2 from "./age-axis.module.sass.js";
5
- import { Parenthetical } from "@macrostrat/data-components";
6
- import { AgeLabel } from "./unit-details/age-range.js";
5
+ import { AgeLabel, Parenthetical } from "@macrostrat/data-components";
7
6
  import { useCompositeScale, useMacrostratColumnData } from "./data-provider/store.js";
8
7
  const h = h$1.styled(h$2);
9
8
  function VerticalAxisLabel(props) {
@@ -1 +1 @@
1
- {"version":3,"file":"age-axis.js","sources":["../src/age-axis.ts"],"sourcesContent":["import hyper from \"@macrostrat/hyper\";\nimport {\n SVG,\n ColumnAxis,\n ColumnContext,\n ColumnAxisType,\n AgeAxis,\n} from \"@macrostrat/column-components\";\nimport { useContext } from \"react\";\nimport styles from \"./age-axis.module.sass\";\nimport { useCompositeScale, useMacrostratColumnData } from \"./data-provider\";\nimport { Parenthetical } from \"@macrostrat/data-components\";\nimport { AgeLabel } from \"./unit-details\";\nimport { PackageScaleLayoutData } from \"./prepare-units\";\n\nconst h = hyper.styled(styles);\n\nconst AgeAxisCore = ({ ticks, tickSpacing = 40, showDomain = false }) => {\n const { pixelHeight } = useContext(ColumnContext);\n // A tick roughly every 40 pixels\n let v = Math.max(Math.round(pixelHeight / tickSpacing), 1);\n\n return h(\"g.axis\", { transform: \"translate(20 0)\" }, [\n h(ColumnAxis, {\n ticks: v,\n showDomain,\n }),\n ]);\n};\n\nexport function VerticalAxisLabel(props) {\n const { label = \"Age\", unit = \"Ma\", className, height } = props;\n return h(\n \"div.column-axis-label.age-axis-label\",\n { className, style: { height } },\n [\n label,\n \" \",\n h.if(unit)(Parenthetical, { className: \"age-axis-unit\" }, unit),\n ],\n );\n}\n\ninterface CompositeAgeAxisProps {\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport function CompositeAgeAxis(rest: CompositeAgeAxisProps) {\n const { axisType, sections, totalHeight } = useMacrostratColumnData();\n\n const packages = sections.map((section) => {\n return {\n key: `section-${section.section_id}`,\n ...section.scaleInfo,\n };\n });\n\n return h(CompositeAgeAxisCore, {\n axisType,\n packages,\n totalHeight,\n ...rest,\n });\n}\n\nexport function ApproximateHeightAxis(rest: CompositeAgeAxisProps) {\n /** Axis to show approximate height based on dynamic column scales */\n const { axisType, sections, totalHeight } = useMacrostratColumnData();\n\n const packages = sections.map((section) => {\n const { scaleInfo } = section;\n if (scaleInfo.heightScale == null) {\n throw new Error(\"No height scale available for section\");\n }\n return {\n key: `section-${section.section_id}`,\n ...scaleInfo,\n scale: scaleInfo.heightScale, // Use height scale instead of age scale\n // This only works with dynamic columns\n };\n });\n\n return h(CompositeAgeAxisCore, {\n axisType,\n axisLabel: \"Approx. height\",\n axisUnit: \"m\",\n packages,\n totalHeight,\n ...rest,\n });\n}\n\nexport interface CompositeStratigraphicScaleInfo extends CompositeAgeAxisProps {\n axisType: ColumnAxisType;\n axisLabel?: string;\n axisUnit?: string;\n totalHeight: number;\n packages: PackageScaleLayoutData[];\n}\n\nexport function CompositeAgeAxisCore(props: CompositeStratigraphicScaleInfo) {\n const { axisType, axisLabel, axisUnit, totalHeight, packages, ...rest } =\n props;\n\n if (axisType == ColumnAxisType.ORDINAL) {\n return null;\n }\n\n let _axisLabel: string = axisLabel ?? \"Age\";\n let _axisUnit = axisUnit ?? \"Ma\";\n if (axisType == ColumnAxisType.DEPTH) {\n _axisLabel = \"Depth\";\n _axisUnit = \"m\";\n } else if (axisType == ColumnAxisType.HEIGHT) {\n _axisLabel = \"Height\";\n _axisUnit = \"m\";\n }\n\n return h(\"div.composite-age-axis\", rest, [\n h(VerticalAxisLabel, {\n label: _axisLabel,\n unit: _axisUnit,\n height: totalHeight,\n }),\n h(\n SVG,\n {\n className: \"age-axis-column\",\n style: { width: `22px`, height: `${totalHeight}px` },\n width: 22,\n height: totalHeight,\n },\n packages.map((group, i) => {\n const { key, scale } = group;\n\n return h(AgeAxis, {\n key,\n className: \"age-axis\",\n scale,\n tickSizeOuter: 3,\n });\n }),\n ),\n ]);\n}\n\nexport function AgeCursor({ age }) {\n /** A cursor that shows the age at a specific point on the age axis. */\n const scale = useCompositeScale();\n const heightPx = scale(age);\n\n if (age == null || heightPx == null) {\n return null;\n }\n\n return h(\n \"div.age-cursor\",\n {\n style: {\n top: heightPx,\n },\n },\n [h(\"div.line\"), h(AgeLabel, { age, className: \"label\" })],\n );\n}\n"],"names":["hyper","styles"],"mappings":";;;;;;;AAeA,MAAM,IAAIA,IAAM,OAAOC,GAAM;AAetB,SAAS,kBAAkB,OAAO;AACvC,QAAM,EAAE,QAAQ,OAAO,OAAO,MAAM,WAAW,WAAW;AAC1D,SAAO;AAAA,IACL;AAAA,IACA,EAAE,WAAW,OAAO,EAAE,SAAO;AAAA,IAC7B;AAAA,MACE;AAAA,MACA;AAAA,MACA,EAAE,GAAG,IAAI,EAAE,eAAe,EAAE,WAAW,gBAAA,GAAmB,IAAI;AAAA,IAAA;AAAA,EAChE;AAEJ;AAOO,SAAS,iBAAiB,MAA6B;AAC5D,QAAM,EAAE,UAAU,UAAU,YAAA,IAAgB,wBAAA;AAE5C,QAAM,WAAW,SAAS,IAAI,CAAC,YAAY;AACzC,WAAO;AAAA,MACL,KAAK,WAAW,QAAQ,UAAU;AAAA,MAClC,GAAG,QAAQ;AAAA,IAAA;AAAA,EAEf,CAAC;AAED,SAAO,EAAE,sBAAsB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,CACJ;AACH;AAEO,SAAS,sBAAsB,MAA6B;AAEjE,QAAM,EAAE,UAAU,UAAU,YAAA,IAAgB,wBAAA;AAE5C,QAAM,WAAW,SAAS,IAAI,CAAC,YAAY;AACzC,UAAM,EAAE,cAAc;AACtB,QAAI,UAAU,eAAe,MAAM;AACjC,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AACA,WAAO;AAAA,MACL,KAAK,WAAW,QAAQ,UAAU;AAAA,MAClC,GAAG;AAAA,MACH,OAAO,UAAU;AAAA;AAAA;AAAA,IAAA;AAAA,EAGrB,CAAC;AAED,SAAO,EAAE,sBAAsB;AAAA,IAC7B;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,CACJ;AACH;AAUO,SAAS,qBAAqB,OAAwC;AAC3E,QAAM,EAAE,UAAU,WAAW,UAAU,aAAa,UAAU,GAAG,SAC/D;AAEF,MAAI,YAAY,eAAe,SAAS;AACtC,WAAO;AAAA,EACT;AAEA,MAAI,aAAqB,aAAa;AACtC,MAAI,YAAY,YAAY;AAC5B,MAAI,YAAY,eAAe,OAAO;AACpC,iBAAa;AACb,gBAAY;AAAA,EACd,WAAW,YAAY,eAAe,QAAQ;AAC5C,iBAAa;AACb,gBAAY;AAAA,EACd;AAEA,SAAO,EAAE,0BAA0B,MAAM;AAAA,IACvC,EAAE,mBAAmB;AAAA,MACnB,OAAO;AAAA,MACP,MAAM;AAAA,MACN,QAAQ;AAAA,IAAA,CACT;AAAA,IACD;AAAA,MACE;AAAA,MACA;AAAA,QACE,WAAW;AAAA,QACX,OAAO,EAAE,OAAO,QAAQ,QAAQ,GAAG,WAAW,KAAA;AAAA,QAC9C,OAAO;AAAA,QACP,QAAQ;AAAA,MAAA;AAAA,MAEV,SAAS,IAAI,CAAC,OAAO,MAAM;AACzB,cAAM,EAAE,KAAK,MAAA,IAAU;AAEvB,eAAO,EAAE,SAAS;AAAA,UAChB;AAAA,UACA,WAAW;AAAA,UACX;AAAA,UACA,eAAe;AAAA,QAAA,CAChB;AAAA,MACH,CAAC;AAAA,IAAA;AAAA,EACH,CACD;AACH;AAEO,SAAS,UAAU,EAAE,OAAO;AAEjC,QAAM,QAAQ,kBAAA;AACd,QAAM,WAAW,MAAM,GAAG;AAE1B,MAAI,OAAO,QAAQ,YAAY,MAAM;AACnC,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,QACL,KAAK;AAAA,MAAA;AAAA,IACP;AAAA,IAEF,CAAC,EAAE,UAAU,GAAG,EAAE,UAAU,EAAE,KAAK,WAAW,SAAS,CAAC;AAAA,EAAA;AAE5D;"}
1
+ {"version":3,"file":"age-axis.js","sources":["../src/age-axis.ts"],"sourcesContent":["import hyper from \"@macrostrat/hyper\";\nimport {\n SVG,\n ColumnAxis,\n ColumnContext,\n ColumnAxisType,\n AgeAxis,\n} from \"@macrostrat/column-components\";\nimport { useContext } from \"react\";\nimport styles from \"./age-axis.module.sass\";\nimport { useCompositeScale, useMacrostratColumnData } from \"./data-provider\";\nimport { Parenthetical } from \"@macrostrat/data-components\";\nimport { AgeLabel } from \"./unit-details\";\nimport { PackageScaleLayoutData } from \"./prepare-units\";\n\nconst h = hyper.styled(styles);\n\nconst AgeAxisCore = ({ ticks, tickSpacing = 40, showDomain = false }) => {\n const { pixelHeight } = useContext(ColumnContext);\n // A tick roughly every 40 pixels\n let v = Math.max(Math.round(pixelHeight / tickSpacing), 1);\n\n return h(\"g.axis\", { transform: \"translate(20 0)\" }, [\n h(ColumnAxis, {\n ticks: v,\n showDomain,\n }),\n ]);\n};\n\nexport function VerticalAxisLabel(props) {\n const { label = \"Age\", unit = \"Ma\", className, height } = props;\n return h(\n \"div.column-axis-label.age-axis-label\",\n { className, style: { height } },\n [\n label,\n \" \",\n h.if(unit)(Parenthetical, { className: \"age-axis-unit\" }, unit),\n ],\n );\n}\n\ninterface CompositeAgeAxisProps {\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport function CompositeAgeAxis(rest: CompositeAgeAxisProps) {\n const { axisType, sections, totalHeight } = useMacrostratColumnData();\n\n const packages = sections.map((section) => {\n return {\n key: `section-${section.section_id}`,\n ...section.scaleInfo,\n };\n });\n\n return h(CompositeAgeAxisCore, {\n axisType,\n packages,\n totalHeight,\n ...rest,\n });\n}\n\nexport function ApproximateHeightAxis(rest: CompositeAgeAxisProps) {\n /** Axis to show approximate height based on dynamic column scales */\n const { axisType, sections, totalHeight } = useMacrostratColumnData();\n\n const packages = sections.map((section) => {\n const { scaleInfo } = section;\n if (scaleInfo.heightScale == null) {\n throw new Error(\"No height scale available for section\");\n }\n return {\n key: `section-${section.section_id}`,\n ...scaleInfo,\n scale: scaleInfo.heightScale, // Use height scale instead of age scale\n // This only works with dynamic columns\n };\n });\n\n return h(CompositeAgeAxisCore, {\n axisType,\n axisLabel: \"Approx. height\",\n axisUnit: \"m\",\n packages,\n totalHeight,\n ...rest,\n });\n}\n\nexport interface CompositeStratigraphicScaleInfo extends CompositeAgeAxisProps {\n axisType: ColumnAxisType;\n axisLabel?: string;\n axisUnit?: string;\n totalHeight: number;\n packages: PackageScaleLayoutData[];\n}\n\nexport function CompositeAgeAxisCore(props: CompositeStratigraphicScaleInfo) {\n const { axisType, axisLabel, axisUnit, totalHeight, packages, ...rest } =\n props;\n\n if (axisType == ColumnAxisType.ORDINAL) {\n return null;\n }\n\n let _axisLabel: string = axisLabel ?? \"Age\";\n let _axisUnit = axisUnit ?? \"Ma\";\n if (axisType == ColumnAxisType.DEPTH) {\n _axisLabel = \"Depth\";\n _axisUnit = \"m\";\n } else if (axisType == ColumnAxisType.HEIGHT) {\n _axisLabel = \"Height\";\n _axisUnit = \"m\";\n }\n\n return h(\"div.composite-age-axis\", rest, [\n h(VerticalAxisLabel, {\n label: _axisLabel,\n unit: _axisUnit,\n height: totalHeight,\n }),\n h(\n SVG,\n {\n className: \"age-axis-column\",\n style: { width: `22px`, height: `${totalHeight}px` },\n width: 22,\n height: totalHeight,\n },\n packages.map((group, i) => {\n const { key, scale } = group;\n\n return h(AgeAxis, {\n key,\n className: \"age-axis\",\n scale,\n tickSizeOuter: 3,\n });\n }),\n ),\n ]);\n}\n\nexport function AgeCursor({ age }) {\n /** A cursor that shows the age at a specific point on the age axis. */\n const scale = useCompositeScale();\n const heightPx = scale(age);\n\n if (age == null || heightPx == null) {\n return null;\n }\n\n return h(\n \"div.age-cursor\",\n {\n style: {\n top: heightPx,\n },\n },\n [h(\"div.line\"), h(AgeLabel, { age, className: \"label\" })],\n );\n}\n"],"names":["hyper","styles"],"mappings":";;;;;;AAeA,MAAM,IAAIA,IAAM,OAAOC,GAAM;AAetB,SAAS,kBAAkB,OAAO;AACvC,QAAM,EAAE,QAAQ,OAAO,OAAO,MAAM,WAAW,WAAW;AAC1D,SAAO;AAAA,IACL;AAAA,IACA,EAAE,WAAW,OAAO,EAAE,SAAO;AAAA,IAC7B;AAAA,MACE;AAAA,MACA;AAAA,MACA,EAAE,GAAG,IAAI,EAAE,eAAe,EAAE,WAAW,gBAAA,GAAmB,IAAI;AAAA,IAAA;AAAA,EAChE;AAEJ;AAOO,SAAS,iBAAiB,MAA6B;AAC5D,QAAM,EAAE,UAAU,UAAU,YAAA,IAAgB,wBAAA;AAE5C,QAAM,WAAW,SAAS,IAAI,CAAC,YAAY;AACzC,WAAO;AAAA,MACL,KAAK,WAAW,QAAQ,UAAU;AAAA,MAClC,GAAG,QAAQ;AAAA,IAAA;AAAA,EAEf,CAAC;AAED,SAAO,EAAE,sBAAsB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,CACJ;AACH;AAEO,SAAS,sBAAsB,MAA6B;AAEjE,QAAM,EAAE,UAAU,UAAU,YAAA,IAAgB,wBAAA;AAE5C,QAAM,WAAW,SAAS,IAAI,CAAC,YAAY;AACzC,UAAM,EAAE,cAAc;AACtB,QAAI,UAAU,eAAe,MAAM;AACjC,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AACA,WAAO;AAAA,MACL,KAAK,WAAW,QAAQ,UAAU;AAAA,MAClC,GAAG;AAAA,MACH,OAAO,UAAU;AAAA;AAAA;AAAA,IAAA;AAAA,EAGrB,CAAC;AAED,SAAO,EAAE,sBAAsB;AAAA,IAC7B;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,CACJ;AACH;AAUO,SAAS,qBAAqB,OAAwC;AAC3E,QAAM,EAAE,UAAU,WAAW,UAAU,aAAa,UAAU,GAAG,SAC/D;AAEF,MAAI,YAAY,eAAe,SAAS;AACtC,WAAO;AAAA,EACT;AAEA,MAAI,aAAqB,aAAa;AACtC,MAAI,YAAY,YAAY;AAC5B,MAAI,YAAY,eAAe,OAAO;AACpC,iBAAa;AACb,gBAAY;AAAA,EACd,WAAW,YAAY,eAAe,QAAQ;AAC5C,iBAAa;AACb,gBAAY;AAAA,EACd;AAEA,SAAO,EAAE,0BAA0B,MAAM;AAAA,IACvC,EAAE,mBAAmB;AAAA,MACnB,OAAO;AAAA,MACP,MAAM;AAAA,MACN,QAAQ;AAAA,IAAA,CACT;AAAA,IACD;AAAA,MACE;AAAA,MACA;AAAA,QACE,WAAW;AAAA,QACX,OAAO,EAAE,OAAO,QAAQ,QAAQ,GAAG,WAAW,KAAA;AAAA,QAC9C,OAAO;AAAA,QACP,QAAQ;AAAA,MAAA;AAAA,MAEV,SAAS,IAAI,CAAC,OAAO,MAAM;AACzB,cAAM,EAAE,KAAK,MAAA,IAAU;AAEvB,eAAO,EAAE,SAAS;AAAA,UAChB;AAAA,UACA,WAAW;AAAA,UACX;AAAA,UACA,eAAe;AAAA,QAAA,CAChB;AAAA,MACH,CAAC;AAAA,IAAA;AAAA,EACH,CACD;AACH;AAEO,SAAS,UAAU,EAAE,OAAO;AAEjC,QAAM,QAAQ,kBAAA;AACd,QAAM,WAAW,MAAM,GAAG;AAE1B,MAAI,OAAO,QAAQ,YAAY,MAAM;AACnC,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,QACL,KAAK;AAAA,MAAA;AAAA,IACP;AAAA,IAEF,CAAC,EAAE,UAAU,GAAG,EAAE,UAAU,EAAE,KAAK,WAAW,SAAS,CAAC;AAAA,EAAA;AAE5D;"}
@@ -6,7 +6,6 @@ const React = require("react");
6
6
  const core = require("@blueprintjs/core");
7
7
  const dataComponents = require("@macrostrat/data-components");
8
8
  const dataProvider = require("@macrostrat/data-provider");
9
- const ageRange = require("../unit-details/age-range.cjs");
10
9
  const panel = require("../unit-details/panel.cjs");
11
10
  const surfaces = require("./surfaces.cjs");
12
11
  const surfaces_module = require("./surfaces.module.sass.cjs");
@@ -86,7 +85,7 @@ function SurfaceDetailsPanel(props) {
86
85
  closeButton
87
86
  ]),
88
87
  h("div.surface-details-content", [
89
- h(dataComponents.DataField, { label: "Model age" }, h(ageRange.AgeLabel, { age: surface.age })),
88
+ h(dataComponents.DataField, { label: "Model age" }, h(dataComponents.AgeLabel, { age: surface.age })),
90
89
  h(SurfaceCalibrationField, { surface }),
91
90
  positionField,
92
91
  h(SurfaceUnitsField, {
@@ -139,7 +138,7 @@ function SurfaceCalibrationField({ surface }) {
139
138
  "div.calibration-interval",
140
139
  h(dataComponents.IntervalTag, {
141
140
  interval,
142
- prefix: h(ageRange.Proportion, { value: proportion })
141
+ proportion
143
142
  })
144
143
  )
145
144
  ]);
@@ -1 +1 @@
1
- {"version":3,"file":"details.cjs","sources":["../../src/age-model/details.ts"],"sourcesContent":["/** The inspector for a selected surface, and the small tags and legend that\n * explain surface statuses and types. */\nimport hyper from \"@macrostrat/hyper\";\nimport classNames from \"classnames\";\nimport { type ReactNode, useMemo } from \"react\";\nimport { Button, Tag } from \"@blueprintjs/core\";\nimport {\n DataField,\n Identifier,\n type IntervalShort,\n IntervalTag,\n UnitIdentifier,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport type { UnitLong } from \"@macrostrat/api-types\";\nimport { useColumnUnitsMap } from \"../data-provider\";\nimport { AgeLabel, Proportion } from \"../unit-details/age-range\";\nimport { formatRange } from \"../unit-details/utils\";\nimport { ReferencesField } from \"../unit-details/panel\";\nimport { surfaceClasses } from \"./surfaces\";\nimport surfaceStyles from \"./surfaces.module.sass\";\nimport styles from \"./details.module.sass\";\nimport {\n type BoundaryType,\n type ColumnSurface,\n type SurfaceStatus,\n formatProportion,\n surfaceStatuses,\n surfaceStatusDescriptions,\n surfaceStatusLabels,\n} from \"./types\";\n\nconst h = hyper.styled({ ...surfaceStyles, ...styles });\n\nexport interface SurfaceDetailsPanelProps {\n /** The surface to inspect; `null` renders the panel's empty state */\n surface: ColumnSurface | null;\n onClose?: () => void;\n /** Called when a unit above or below the surface is clicked */\n onSelectUnit?: (unitID: number) => void;\n /** Extra controls for the header */\n actions?: ReactNode;\n /** Label for the measured-position field (\"Height\" or \"Depth\") */\n positionLabel?: string;\n className?: string;\n}\n\n/** Details of one surface: its age, calibration, the units it separates, and\n * provenance. A companion to `UnitDetailsPanel`. */\nexport function SurfaceDetailsPanel(props: SurfaceDetailsPanelProps) {\n const {\n surface,\n onClose,\n onSelectUnit,\n actions,\n positionLabel = \"Position\",\n className,\n } = props;\n\n // A selection that hasn't been made yet is an ordinary state for a panel\n // bound to one, not a caller error\n if (surface == null) {\n return h(\n \"div.surface-details-panel.no-surface\",\n { className },\n h(\"p.placeholder\", \"No surface selected.\"),\n );\n }\n\n let closeButton: ReactNode = null;\n if (onClose != null) {\n closeButton = h(Button, {\n icon: \"cross\",\n variant: \"minimal\",\n size: \"small\",\n onClick: onClose,\n \"aria-label\": \"Close\",\n });\n }\n\n let positionField: ReactNode = null;\n if (surface.position != null) {\n positionField = h(DataField, {\n label: positionLabel,\n value: surface.position.toLocaleString(\"en-US\", {\n maximumFractionDigits: 2,\n }),\n unit: \"m\",\n });\n }\n\n let sectionField: ReactNode = null;\n if (surface.section_id != null) {\n sectionField = h(\n DataField,\n { label: \"Section\" },\n h(Identifier, { id: surface.section_id }),\n );\n }\n\n let refsField: ReactNode = null;\n if (surface.ref_id != null) {\n refsField = h(ReferencesField, { refs: [surface.ref_id] });\n }\n\n return h(\n \"div.surface-details-panel\",\n { className: classNames(className, surfaceClasses(surface)) },\n [\n h(\"div.surface-details-header\", [\n h(\"h3.surface-details-title\", [\n \"Surface \",\n h(SurfaceIdentifier, { id: surface.id }),\n ]),\n h(\"div.surface-details-tags\", [\n h(SurfaceStatusTag, {\n status: surface.status,\n inferred: surface.statusInferred,\n }),\n h(SurfaceTypeTag, { type: surface.type }),\n ]),\n h(\"div.spacer\"),\n actions,\n closeButton,\n ]),\n h(\"div.surface-details-content\", [\n h(DataField, { label: \"Model age\" }, h(AgeLabel, { age: surface.age })),\n h(SurfaceCalibrationField, { surface }),\n positionField,\n h(SurfaceUnitsField, {\n label: \"Unit above\",\n unitIDs: surface.unitsAbove,\n onSelectUnit,\n }),\n h(SurfaceUnitsField, {\n label: \"Unit below\",\n unitIDs: surface.unitsBelow,\n onSelectUnit,\n }),\n sectionField,\n refsField,\n ]),\n ],\n );\n}\n\nfunction SurfaceIdentifier({ id }: { id: ColumnSurface[\"id\"] }) {\n if (typeof id === \"number\") {\n return h(Identifier, { id });\n }\n return h(\"code.surface-id\", String(id));\n}\n\n/** The calibration interval as a colored tag, with the surface's position in\n * it: \"Calymmian (1600–1400 Ma), 85% above base\". */\nfunction SurfaceCalibrationField({ surface }: { surface: ColumnSurface }) {\n const { calibration, proportion } = surface;\n const ids = useMemo(() => {\n if (calibration == null) return [];\n return [calibration.id];\n }, [calibration?.id]);\n // Interval colors come from the definitions table; the age model itself\n // doesn't carry them\n const intervalMap = useMacrostratDefs(\"intervals\", ids, null);\n\n if (calibration == null) {\n return h(DataField, {\n label: \"Calibration\",\n value: \"None\",\n className: \"no-calibration\",\n });\n }\n\n const def = intervalMap?.get(calibration.id);\n const interval: IntervalShort = {\n id: calibration.id,\n name: calibration.name,\n b_age: calibration.b_age,\n t_age: calibration.t_age,\n color: def?.color,\n rank: def?.rank,\n };\n\n return h(DataField, { label: \"Calibration\" }, [\n h(\n \"div.calibration-interval\",\n h(IntervalTag, {\n interval,\n prefix: h(Proportion, { value: proportion }),\n }),\n ),\n ]);\n}\n\nfunction SurfaceUnitsField({\n label,\n unitIDs,\n onSelectUnit,\n}: {\n label: string;\n unitIDs: number[];\n onSelectUnit?: (unitID: number) => void;\n}) {\n const unitsMap = useColumnUnitsMap();\n if (unitIDs.length === 0) {\n return h(DataField, { label, value: \"None\", className: \"no-units\" });\n }\n return h(\n DataField,\n { label, className: \"surface-units-field\" },\n h(\n \"ul.surface-units-list\",\n unitIDs.map((unitID) => {\n const unit = unitsMap?.get(unitID) as UnitLong | undefined;\n let onClick: (() => void) | undefined = undefined;\n if (onSelectUnit != null) {\n onClick = () => onSelectUnit(unitID);\n }\n return h(\n \"li\",\n { key: unitID },\n h(UnitIdentifier, {\n unitID,\n colID: unit?.col_id,\n name: unit?.unit_name,\n onClick,\n }),\n );\n }),\n ),\n );\n}\n\nexport function SurfaceStatusTag({\n status,\n inferred = false,\n className,\n}: {\n status: SurfaceStatus;\n /** The status was inferred rather than recorded (see\n * `inferTiePointStatuses`); the tag says so. */\n inferred?: boolean;\n className?: string;\n}) {\n let label: ReactNode = surfaceStatusLabels[status] ?? status;\n let title = surfaceStatusDescriptions[status];\n if (inferred) {\n label = [label, h(\"span.inferred-marker\", \"*\")];\n title = INFERRED_STATUS_DESCRIPTION;\n }\n\n return h(\n Tag,\n {\n variant: \"minimal\",\n className: classNames(\n \"surface-tag\",\n className,\n surfaceClasses({ status }),\n { inferred },\n ),\n title,\n },\n label,\n );\n}\n\nconst INFERRED_STATUS_DESCRIPTION =\n \"Recorded as modeled, but this surface cannot have been interpolated — it \" +\n \"sits on the base or top of its interval, or is the edge of a gap-bound \" +\n \"package — so it constrains the age model rather than falling out of it\";\n\nexport function SurfaceTypeTag({\n type,\n className,\n}: {\n type: BoundaryType | null | undefined;\n className?: string;\n}) {\n if (type == null || type === \"\") return null;\n return h(\n Tag,\n {\n variant: \"minimal\",\n className: classNames(\"surface-tag\", \"surface-type-tag\", className),\n },\n type,\n );\n}\n\nexport interface SurfaceStatusLegendProps {\n statuses?: SurfaceStatus[];\n showDescriptions?: boolean;\n className?: string;\n}\n\n/** A legend of surface line styles, one entry per boundary status. */\nexport function SurfaceStatusLegend(props: SurfaceStatusLegendProps) {\n const {\n statuses = surfaceStatuses,\n showDescriptions = false,\n className,\n } = props;\n return h(\n \"ul.surface-status-legend\",\n {\n className: classNames(className, {\n \"with-descriptions\": showDescriptions,\n }),\n },\n statuses.map((status) => {\n let description: ReactNode = null;\n if (showDescriptions) {\n description = h(\n \"div.legend-description\",\n surfaceStatusDescriptions[status],\n );\n }\n return h(\n \"li.legend-item\",\n { key: status, className: surfaceClasses({ status }) },\n [\n h(\"div.surface-label-marker\"),\n h(\"div.legend-text\", [\n h(\"div.legend-label\", surfaceStatusLabels[status]),\n description,\n ]),\n ],\n );\n }),\n );\n}\n"],"names":["hyper","surfaceStyles","styles","Button","DataField","Identifier","ReferencesField","classNames","surfaceClasses","AgeLabel","useMemo","useMacrostratDefs","IntervalTag","Proportion","useColumnUnitsMap","UnitIdentifier","surfaceStatusLabels","surfaceStatusDescriptions","Tag","surfaceStatuses"],"mappings":"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"}
1
+ {"version":3,"file":"details.cjs","sources":["../../src/age-model/details.ts"],"sourcesContent":["/** The inspector for a selected surface, and the small tags and legend that\n * explain surface statuses and types. */\nimport hyper from \"@macrostrat/hyper\";\nimport classNames from \"classnames\";\nimport { type ReactNode, useMemo } from \"react\";\nimport { Button, Tag } from \"@blueprintjs/core\";\nimport {\n DataField,\n Identifier,\n type IntervalShort,\n IntervalTag,\n UnitIdentifier,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport type { UnitLong } from \"@macrostrat/api-types\";\nimport { useColumnUnitsMap } from \"../data-provider\";\nimport { AgeLabel } from \"../unit-details/age-range\";\nimport { formatRange } from \"../unit-details/utils\";\nimport { ReferencesField } from \"../unit-details/panel\";\nimport { surfaceClasses } from \"./surfaces\";\nimport surfaceStyles from \"./surfaces.module.sass\";\nimport styles from \"./details.module.sass\";\nimport {\n type BoundaryType,\n type ColumnSurface,\n type SurfaceStatus,\n formatProportion,\n surfaceStatuses,\n surfaceStatusDescriptions,\n surfaceStatusLabels,\n} from \"./types\";\n\nconst h = hyper.styled({ ...surfaceStyles, ...styles });\n\nexport interface SurfaceDetailsPanelProps {\n /** The surface to inspect; `null` renders the panel's empty state */\n surface: ColumnSurface | null;\n onClose?: () => void;\n /** Called when a unit above or below the surface is clicked */\n onSelectUnit?: (unitID: number) => void;\n /** Extra controls for the header */\n actions?: ReactNode;\n /** Label for the measured-position field (\"Height\" or \"Depth\") */\n positionLabel?: string;\n className?: string;\n}\n\n/** Details of one surface: its age, calibration, the units it separates, and\n * provenance. A companion to `UnitDetailsPanel`. */\nexport function SurfaceDetailsPanel(props: SurfaceDetailsPanelProps) {\n const {\n surface,\n onClose,\n onSelectUnit,\n actions,\n positionLabel = \"Position\",\n className,\n } = props;\n\n // A selection that hasn't been made yet is an ordinary state for a panel\n // bound to one, not a caller error\n if (surface == null) {\n return h(\n \"div.surface-details-panel.no-surface\",\n { className },\n h(\"p.placeholder\", \"No surface selected.\"),\n );\n }\n\n let closeButton: ReactNode = null;\n if (onClose != null) {\n closeButton = h(Button, {\n icon: \"cross\",\n variant: \"minimal\",\n size: \"small\",\n onClick: onClose,\n \"aria-label\": \"Close\",\n });\n }\n\n let positionField: ReactNode = null;\n if (surface.position != null) {\n positionField = h(DataField, {\n label: positionLabel,\n value: surface.position.toLocaleString(\"en-US\", {\n maximumFractionDigits: 2,\n }),\n unit: \"m\",\n });\n }\n\n let sectionField: ReactNode = null;\n if (surface.section_id != null) {\n sectionField = h(\n DataField,\n { label: \"Section\" },\n h(Identifier, { id: surface.section_id }),\n );\n }\n\n let refsField: ReactNode = null;\n if (surface.ref_id != null) {\n refsField = h(ReferencesField, { refs: [surface.ref_id] });\n }\n\n return h(\n \"div.surface-details-panel\",\n { className: classNames(className, surfaceClasses(surface)) },\n [\n h(\"div.surface-details-header\", [\n h(\"h3.surface-details-title\", [\n \"Surface \",\n h(SurfaceIdentifier, { id: surface.id }),\n ]),\n h(\"div.surface-details-tags\", [\n h(SurfaceStatusTag, {\n status: surface.status,\n inferred: surface.statusInferred,\n }),\n h(SurfaceTypeTag, { type: surface.type }),\n ]),\n h(\"div.spacer\"),\n actions,\n closeButton,\n ]),\n h(\"div.surface-details-content\", [\n h(DataField, { label: \"Model age\" }, h(AgeLabel, { age: surface.age })),\n h(SurfaceCalibrationField, { surface }),\n positionField,\n h(SurfaceUnitsField, {\n label: \"Unit above\",\n unitIDs: surface.unitsAbove,\n onSelectUnit,\n }),\n h(SurfaceUnitsField, {\n label: \"Unit below\",\n unitIDs: surface.unitsBelow,\n onSelectUnit,\n }),\n sectionField,\n refsField,\n ]),\n ],\n );\n}\n\nfunction SurfaceIdentifier({ id }: { id: ColumnSurface[\"id\"] }) {\n if (typeof id === \"number\") {\n return h(Identifier, { id });\n }\n return h(\"code.surface-id\", String(id));\n}\n\n/** The calibration interval as a colored tag, with the surface's position in\n * it: \"Calymmian (1600–1400 Ma), 85% above base\". */\nfunction SurfaceCalibrationField({ surface }: { surface: ColumnSurface }) {\n const { calibration, proportion } = surface;\n const ids = useMemo(() => {\n if (calibration == null) return [];\n return [calibration.id];\n }, [calibration?.id]);\n // Interval colors come from the definitions table; the age model itself\n // doesn't carry them\n const intervalMap = useMacrostratDefs(\"intervals\", ids, null);\n\n if (calibration == null) {\n return h(DataField, {\n label: \"Calibration\",\n value: \"None\",\n className: \"no-calibration\",\n });\n }\n\n const def = intervalMap?.get(calibration.id);\n const interval: IntervalShort = {\n id: calibration.id,\n name: calibration.name,\n b_age: calibration.b_age,\n t_age: calibration.t_age,\n color: def?.color,\n rank: def?.rank,\n };\n\n return h(DataField, { label: \"Calibration\" }, [\n h(\n \"div.calibration-interval\",\n h(IntervalTag, {\n interval,\n proportion,\n }),\n ),\n ]);\n}\n\nfunction SurfaceUnitsField({\n label,\n unitIDs,\n onSelectUnit,\n}: {\n label: string;\n unitIDs: number[];\n onSelectUnit?: (unitID: number) => void;\n}) {\n const unitsMap = useColumnUnitsMap();\n if (unitIDs.length === 0) {\n return h(DataField, { label, value: \"None\", className: \"no-units\" });\n }\n return h(\n DataField,\n { label, className: \"surface-units-field\" },\n h(\n \"ul.surface-units-list\",\n unitIDs.map((unitID) => {\n const unit = unitsMap?.get(unitID) as UnitLong | undefined;\n let onClick: (() => void) | undefined = undefined;\n if (onSelectUnit != null) {\n onClick = () => onSelectUnit(unitID);\n }\n return h(\n \"li\",\n { key: unitID },\n h(UnitIdentifier, {\n unitID,\n colID: unit?.col_id,\n name: unit?.unit_name,\n onClick,\n }),\n );\n }),\n ),\n );\n}\n\nexport function SurfaceStatusTag({\n status,\n inferred = false,\n className,\n}: {\n status: SurfaceStatus;\n /** The status was inferred rather than recorded (see\n * `inferTiePointStatuses`); the tag says so. */\n inferred?: boolean;\n className?: string;\n}) {\n let label: ReactNode = surfaceStatusLabels[status] ?? status;\n let title = surfaceStatusDescriptions[status];\n if (inferred) {\n label = [label, h(\"span.inferred-marker\", \"*\")];\n title = INFERRED_STATUS_DESCRIPTION;\n }\n\n return h(\n Tag,\n {\n variant: \"minimal\",\n className: classNames(\n \"surface-tag\",\n className,\n surfaceClasses({ status }),\n { inferred },\n ),\n title,\n },\n label,\n );\n}\n\nconst INFERRED_STATUS_DESCRIPTION =\n \"Recorded as modeled, but this surface cannot have been interpolated — it \" +\n \"sits on the base or top of its interval, or is the edge of a gap-bound \" +\n \"package — so it constrains the age model rather than falling out of it\";\n\nexport function SurfaceTypeTag({\n type,\n className,\n}: {\n type: BoundaryType | null | undefined;\n className?: string;\n}) {\n if (type == null || type === \"\") return null;\n return h(\n Tag,\n {\n variant: \"minimal\",\n className: classNames(\"surface-tag\", \"surface-type-tag\", className),\n },\n type,\n );\n}\n\nexport interface SurfaceStatusLegendProps {\n statuses?: SurfaceStatus[];\n showDescriptions?: boolean;\n className?: string;\n}\n\n/** A legend of surface line styles, one entry per boundary status. */\nexport function SurfaceStatusLegend(props: SurfaceStatusLegendProps) {\n const {\n statuses = surfaceStatuses,\n showDescriptions = false,\n className,\n } = props;\n return h(\n \"ul.surface-status-legend\",\n {\n className: classNames(className, {\n \"with-descriptions\": showDescriptions,\n }),\n },\n statuses.map((status) => {\n let description: ReactNode = null;\n if (showDescriptions) {\n description = h(\n \"div.legend-description\",\n surfaceStatusDescriptions[status],\n );\n }\n return h(\n \"li.legend-item\",\n { key: status, className: surfaceClasses({ status }) },\n [\n h(\"div.surface-label-marker\"),\n h(\"div.legend-text\", [\n h(\"div.legend-label\", surfaceStatusLabels[status]),\n description,\n ]),\n ],\n );\n }),\n );\n}\n"],"names":["hyper","surfaceStyles","styles","Button","DataField","Identifier","ReferencesField","classNames","surfaceClasses","AgeLabel","useMemo","useMacrostratDefs","IntervalTag","useColumnUnitsMap","UnitIdentifier","surfaceStatusLabels","surfaceStatusDescriptions","Tag","surfaceStatuses"],"mappings":"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"}
@@ -2,9 +2,8 @@ import h$1 from "@macrostrat/hyper";
2
2
  import classNames from "classnames";
3
3
  import { useMemo } from "react";
4
4
  import { Button, Tag } from "@blueprintjs/core";
5
- import { DataField, Identifier, IntervalTag, UnitIdentifier } from "@macrostrat/data-components";
5
+ import { DataField, Identifier, AgeLabel, IntervalTag, UnitIdentifier } from "@macrostrat/data-components";
6
6
  import { useMacrostratDefs } from "@macrostrat/data-provider";
7
- import { AgeLabel, Proportion } from "../unit-details/age-range.js";
8
7
  import { ReferencesField } from "../unit-details/panel.js";
9
8
  import { surfaceClasses } from "./surfaces.js";
10
9
  import h$3 from "./surfaces.module.sass.js";
@@ -134,7 +133,7 @@ function SurfaceCalibrationField({ surface }) {
134
133
  "div.calibration-interval",
135
134
  h(IntervalTag, {
136
135
  interval,
137
- prefix: h(Proportion, { value: proportion })
136
+ proportion
138
137
  })
139
138
  )
140
139
  ]);
@@ -1 +1 @@
1
- {"version":3,"file":"details.js","sources":["../../src/age-model/details.ts"],"sourcesContent":["/** The inspector for a selected surface, and the small tags and legend that\n * explain surface statuses and types. */\nimport hyper from \"@macrostrat/hyper\";\nimport classNames from \"classnames\";\nimport { type ReactNode, useMemo } from \"react\";\nimport { Button, Tag } from \"@blueprintjs/core\";\nimport {\n DataField,\n Identifier,\n type IntervalShort,\n IntervalTag,\n UnitIdentifier,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport type { UnitLong } from \"@macrostrat/api-types\";\nimport { useColumnUnitsMap } from \"../data-provider\";\nimport { AgeLabel, Proportion } from \"../unit-details/age-range\";\nimport { formatRange } from \"../unit-details/utils\";\nimport { ReferencesField } from \"../unit-details/panel\";\nimport { surfaceClasses } from \"./surfaces\";\nimport surfaceStyles from \"./surfaces.module.sass\";\nimport styles from \"./details.module.sass\";\nimport {\n type BoundaryType,\n type ColumnSurface,\n type SurfaceStatus,\n formatProportion,\n surfaceStatuses,\n surfaceStatusDescriptions,\n surfaceStatusLabels,\n} from \"./types\";\n\nconst h = hyper.styled({ ...surfaceStyles, ...styles });\n\nexport interface SurfaceDetailsPanelProps {\n /** The surface to inspect; `null` renders the panel's empty state */\n surface: ColumnSurface | null;\n onClose?: () => void;\n /** Called when a unit above or below the surface is clicked */\n onSelectUnit?: (unitID: number) => void;\n /** Extra controls for the header */\n actions?: ReactNode;\n /** Label for the measured-position field (\"Height\" or \"Depth\") */\n positionLabel?: string;\n className?: string;\n}\n\n/** Details of one surface: its age, calibration, the units it separates, and\n * provenance. A companion to `UnitDetailsPanel`. */\nexport function SurfaceDetailsPanel(props: SurfaceDetailsPanelProps) {\n const {\n surface,\n onClose,\n onSelectUnit,\n actions,\n positionLabel = \"Position\",\n className,\n } = props;\n\n // A selection that hasn't been made yet is an ordinary state for a panel\n // bound to one, not a caller error\n if (surface == null) {\n return h(\n \"div.surface-details-panel.no-surface\",\n { className },\n h(\"p.placeholder\", \"No surface selected.\"),\n );\n }\n\n let closeButton: ReactNode = null;\n if (onClose != null) {\n closeButton = h(Button, {\n icon: \"cross\",\n variant: \"minimal\",\n size: \"small\",\n onClick: onClose,\n \"aria-label\": \"Close\",\n });\n }\n\n let positionField: ReactNode = null;\n if (surface.position != null) {\n positionField = h(DataField, {\n label: positionLabel,\n value: surface.position.toLocaleString(\"en-US\", {\n maximumFractionDigits: 2,\n }),\n unit: \"m\",\n });\n }\n\n let sectionField: ReactNode = null;\n if (surface.section_id != null) {\n sectionField = h(\n DataField,\n { label: \"Section\" },\n h(Identifier, { id: surface.section_id }),\n );\n }\n\n let refsField: ReactNode = null;\n if (surface.ref_id != null) {\n refsField = h(ReferencesField, { refs: [surface.ref_id] });\n }\n\n return h(\n \"div.surface-details-panel\",\n { className: classNames(className, surfaceClasses(surface)) },\n [\n h(\"div.surface-details-header\", [\n h(\"h3.surface-details-title\", [\n \"Surface \",\n h(SurfaceIdentifier, { id: surface.id }),\n ]),\n h(\"div.surface-details-tags\", [\n h(SurfaceStatusTag, {\n status: surface.status,\n inferred: surface.statusInferred,\n }),\n h(SurfaceTypeTag, { type: surface.type }),\n ]),\n h(\"div.spacer\"),\n actions,\n closeButton,\n ]),\n h(\"div.surface-details-content\", [\n h(DataField, { label: \"Model age\" }, h(AgeLabel, { age: surface.age })),\n h(SurfaceCalibrationField, { surface }),\n positionField,\n h(SurfaceUnitsField, {\n label: \"Unit above\",\n unitIDs: surface.unitsAbove,\n onSelectUnit,\n }),\n h(SurfaceUnitsField, {\n label: \"Unit below\",\n unitIDs: surface.unitsBelow,\n onSelectUnit,\n }),\n sectionField,\n refsField,\n ]),\n ],\n );\n}\n\nfunction SurfaceIdentifier({ id }: { id: ColumnSurface[\"id\"] }) {\n if (typeof id === \"number\") {\n return h(Identifier, { id });\n }\n return h(\"code.surface-id\", String(id));\n}\n\n/** The calibration interval as a colored tag, with the surface's position in\n * it: \"Calymmian (1600–1400 Ma), 85% above base\". */\nfunction SurfaceCalibrationField({ surface }: { surface: ColumnSurface }) {\n const { calibration, proportion } = surface;\n const ids = useMemo(() => {\n if (calibration == null) return [];\n return [calibration.id];\n }, [calibration?.id]);\n // Interval colors come from the definitions table; the age model itself\n // doesn't carry them\n const intervalMap = useMacrostratDefs(\"intervals\", ids, null);\n\n if (calibration == null) {\n return h(DataField, {\n label: \"Calibration\",\n value: \"None\",\n className: \"no-calibration\",\n });\n }\n\n const def = intervalMap?.get(calibration.id);\n const interval: IntervalShort = {\n id: calibration.id,\n name: calibration.name,\n b_age: calibration.b_age,\n t_age: calibration.t_age,\n color: def?.color,\n rank: def?.rank,\n };\n\n return h(DataField, { label: \"Calibration\" }, [\n h(\n \"div.calibration-interval\",\n h(IntervalTag, {\n interval,\n prefix: h(Proportion, { value: proportion }),\n }),\n ),\n ]);\n}\n\nfunction SurfaceUnitsField({\n label,\n unitIDs,\n onSelectUnit,\n}: {\n label: string;\n unitIDs: number[];\n onSelectUnit?: (unitID: number) => void;\n}) {\n const unitsMap = useColumnUnitsMap();\n if (unitIDs.length === 0) {\n return h(DataField, { label, value: \"None\", className: \"no-units\" });\n }\n return h(\n DataField,\n { label, className: \"surface-units-field\" },\n h(\n \"ul.surface-units-list\",\n unitIDs.map((unitID) => {\n const unit = unitsMap?.get(unitID) as UnitLong | undefined;\n let onClick: (() => void) | undefined = undefined;\n if (onSelectUnit != null) {\n onClick = () => onSelectUnit(unitID);\n }\n return h(\n \"li\",\n { key: unitID },\n h(UnitIdentifier, {\n unitID,\n colID: unit?.col_id,\n name: unit?.unit_name,\n onClick,\n }),\n );\n }),\n ),\n );\n}\n\nexport function SurfaceStatusTag({\n status,\n inferred = false,\n className,\n}: {\n status: SurfaceStatus;\n /** The status was inferred rather than recorded (see\n * `inferTiePointStatuses`); the tag says so. */\n inferred?: boolean;\n className?: string;\n}) {\n let label: ReactNode = surfaceStatusLabels[status] ?? status;\n let title = surfaceStatusDescriptions[status];\n if (inferred) {\n label = [label, h(\"span.inferred-marker\", \"*\")];\n title = INFERRED_STATUS_DESCRIPTION;\n }\n\n return h(\n Tag,\n {\n variant: \"minimal\",\n className: classNames(\n \"surface-tag\",\n className,\n surfaceClasses({ status }),\n { inferred },\n ),\n title,\n },\n label,\n );\n}\n\nconst INFERRED_STATUS_DESCRIPTION =\n \"Recorded as modeled, but this surface cannot have been interpolated — it \" +\n \"sits on the base or top of its interval, or is the edge of a gap-bound \" +\n \"package — so it constrains the age model rather than falling out of it\";\n\nexport function SurfaceTypeTag({\n type,\n className,\n}: {\n type: BoundaryType | null | undefined;\n className?: string;\n}) {\n if (type == null || type === \"\") return null;\n return h(\n Tag,\n {\n variant: \"minimal\",\n className: classNames(\"surface-tag\", \"surface-type-tag\", className),\n },\n type,\n );\n}\n\nexport interface SurfaceStatusLegendProps {\n statuses?: SurfaceStatus[];\n showDescriptions?: boolean;\n className?: string;\n}\n\n/** A legend of surface line styles, one entry per boundary status. */\nexport function SurfaceStatusLegend(props: SurfaceStatusLegendProps) {\n const {\n statuses = surfaceStatuses,\n showDescriptions = false,\n className,\n } = props;\n return h(\n \"ul.surface-status-legend\",\n {\n className: classNames(className, {\n \"with-descriptions\": showDescriptions,\n }),\n },\n statuses.map((status) => {\n let description: ReactNode = null;\n if (showDescriptions) {\n description = h(\n \"div.legend-description\",\n surfaceStatusDescriptions[status],\n );\n }\n return h(\n \"li.legend-item\",\n { key: status, className: surfaceClasses({ status }) },\n [\n h(\"div.surface-label-marker\"),\n h(\"div.legend-text\", [\n h(\"div.legend-label\", surfaceStatusLabels[status]),\n description,\n ]),\n ],\n );\n }),\n );\n}\n"],"names":["hyper","surfaceStyles","styles"],"mappings":"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"}
1
+ {"version":3,"file":"details.js","sources":["../../src/age-model/details.ts"],"sourcesContent":["/** The inspector for a selected surface, and the small tags and legend that\n * explain surface statuses and types. */\nimport hyper from \"@macrostrat/hyper\";\nimport classNames from \"classnames\";\nimport { type ReactNode, useMemo } from \"react\";\nimport { Button, Tag } from \"@blueprintjs/core\";\nimport {\n DataField,\n Identifier,\n type IntervalShort,\n IntervalTag,\n UnitIdentifier,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport type { UnitLong } from \"@macrostrat/api-types\";\nimport { useColumnUnitsMap } from \"../data-provider\";\nimport { AgeLabel } from \"../unit-details/age-range\";\nimport { formatRange } from \"../unit-details/utils\";\nimport { ReferencesField } from \"../unit-details/panel\";\nimport { surfaceClasses } from \"./surfaces\";\nimport surfaceStyles from \"./surfaces.module.sass\";\nimport styles from \"./details.module.sass\";\nimport {\n type BoundaryType,\n type ColumnSurface,\n type SurfaceStatus,\n formatProportion,\n surfaceStatuses,\n surfaceStatusDescriptions,\n surfaceStatusLabels,\n} from \"./types\";\n\nconst h = hyper.styled({ ...surfaceStyles, ...styles });\n\nexport interface SurfaceDetailsPanelProps {\n /** The surface to inspect; `null` renders the panel's empty state */\n surface: ColumnSurface | null;\n onClose?: () => void;\n /** Called when a unit above or below the surface is clicked */\n onSelectUnit?: (unitID: number) => void;\n /** Extra controls for the header */\n actions?: ReactNode;\n /** Label for the measured-position field (\"Height\" or \"Depth\") */\n positionLabel?: string;\n className?: string;\n}\n\n/** Details of one surface: its age, calibration, the units it separates, and\n * provenance. A companion to `UnitDetailsPanel`. */\nexport function SurfaceDetailsPanel(props: SurfaceDetailsPanelProps) {\n const {\n surface,\n onClose,\n onSelectUnit,\n actions,\n positionLabel = \"Position\",\n className,\n } = props;\n\n // A selection that hasn't been made yet is an ordinary state for a panel\n // bound to one, not a caller error\n if (surface == null) {\n return h(\n \"div.surface-details-panel.no-surface\",\n { className },\n h(\"p.placeholder\", \"No surface selected.\"),\n );\n }\n\n let closeButton: ReactNode = null;\n if (onClose != null) {\n closeButton = h(Button, {\n icon: \"cross\",\n variant: \"minimal\",\n size: \"small\",\n onClick: onClose,\n \"aria-label\": \"Close\",\n });\n }\n\n let positionField: ReactNode = null;\n if (surface.position != null) {\n positionField = h(DataField, {\n label: positionLabel,\n value: surface.position.toLocaleString(\"en-US\", {\n maximumFractionDigits: 2,\n }),\n unit: \"m\",\n });\n }\n\n let sectionField: ReactNode = null;\n if (surface.section_id != null) {\n sectionField = h(\n DataField,\n { label: \"Section\" },\n h(Identifier, { id: surface.section_id }),\n );\n }\n\n let refsField: ReactNode = null;\n if (surface.ref_id != null) {\n refsField = h(ReferencesField, { refs: [surface.ref_id] });\n }\n\n return h(\n \"div.surface-details-panel\",\n { className: classNames(className, surfaceClasses(surface)) },\n [\n h(\"div.surface-details-header\", [\n h(\"h3.surface-details-title\", [\n \"Surface \",\n h(SurfaceIdentifier, { id: surface.id }),\n ]),\n h(\"div.surface-details-tags\", [\n h(SurfaceStatusTag, {\n status: surface.status,\n inferred: surface.statusInferred,\n }),\n h(SurfaceTypeTag, { type: surface.type }),\n ]),\n h(\"div.spacer\"),\n actions,\n closeButton,\n ]),\n h(\"div.surface-details-content\", [\n h(DataField, { label: \"Model age\" }, h(AgeLabel, { age: surface.age })),\n h(SurfaceCalibrationField, { surface }),\n positionField,\n h(SurfaceUnitsField, {\n label: \"Unit above\",\n unitIDs: surface.unitsAbove,\n onSelectUnit,\n }),\n h(SurfaceUnitsField, {\n label: \"Unit below\",\n unitIDs: surface.unitsBelow,\n onSelectUnit,\n }),\n sectionField,\n refsField,\n ]),\n ],\n );\n}\n\nfunction SurfaceIdentifier({ id }: { id: ColumnSurface[\"id\"] }) {\n if (typeof id === \"number\") {\n return h(Identifier, { id });\n }\n return h(\"code.surface-id\", String(id));\n}\n\n/** The calibration interval as a colored tag, with the surface's position in\n * it: \"Calymmian (1600–1400 Ma), 85% above base\". */\nfunction SurfaceCalibrationField({ surface }: { surface: ColumnSurface }) {\n const { calibration, proportion } = surface;\n const ids = useMemo(() => {\n if (calibration == null) return [];\n return [calibration.id];\n }, [calibration?.id]);\n // Interval colors come from the definitions table; the age model itself\n // doesn't carry them\n const intervalMap = useMacrostratDefs(\"intervals\", ids, null);\n\n if (calibration == null) {\n return h(DataField, {\n label: \"Calibration\",\n value: \"None\",\n className: \"no-calibration\",\n });\n }\n\n const def = intervalMap?.get(calibration.id);\n const interval: IntervalShort = {\n id: calibration.id,\n name: calibration.name,\n b_age: calibration.b_age,\n t_age: calibration.t_age,\n color: def?.color,\n rank: def?.rank,\n };\n\n return h(DataField, { label: \"Calibration\" }, [\n h(\n \"div.calibration-interval\",\n h(IntervalTag, {\n interval,\n proportion,\n }),\n ),\n ]);\n}\n\nfunction SurfaceUnitsField({\n label,\n unitIDs,\n onSelectUnit,\n}: {\n label: string;\n unitIDs: number[];\n onSelectUnit?: (unitID: number) => void;\n}) {\n const unitsMap = useColumnUnitsMap();\n if (unitIDs.length === 0) {\n return h(DataField, { label, value: \"None\", className: \"no-units\" });\n }\n return h(\n DataField,\n { label, className: \"surface-units-field\" },\n h(\n \"ul.surface-units-list\",\n unitIDs.map((unitID) => {\n const unit = unitsMap?.get(unitID) as UnitLong | undefined;\n let onClick: (() => void) | undefined = undefined;\n if (onSelectUnit != null) {\n onClick = () => onSelectUnit(unitID);\n }\n return h(\n \"li\",\n { key: unitID },\n h(UnitIdentifier, {\n unitID,\n colID: unit?.col_id,\n name: unit?.unit_name,\n onClick,\n }),\n );\n }),\n ),\n );\n}\n\nexport function SurfaceStatusTag({\n status,\n inferred = false,\n className,\n}: {\n status: SurfaceStatus;\n /** The status was inferred rather than recorded (see\n * `inferTiePointStatuses`); the tag says so. */\n inferred?: boolean;\n className?: string;\n}) {\n let label: ReactNode = surfaceStatusLabels[status] ?? status;\n let title = surfaceStatusDescriptions[status];\n if (inferred) {\n label = [label, h(\"span.inferred-marker\", \"*\")];\n title = INFERRED_STATUS_DESCRIPTION;\n }\n\n return h(\n Tag,\n {\n variant: \"minimal\",\n className: classNames(\n \"surface-tag\",\n className,\n surfaceClasses({ status }),\n { inferred },\n ),\n title,\n },\n label,\n );\n}\n\nconst INFERRED_STATUS_DESCRIPTION =\n \"Recorded as modeled, but this surface cannot have been interpolated — it \" +\n \"sits on the base or top of its interval, or is the edge of a gap-bound \" +\n \"package — so it constrains the age model rather than falling out of it\";\n\nexport function SurfaceTypeTag({\n type,\n className,\n}: {\n type: BoundaryType | null | undefined;\n className?: string;\n}) {\n if (type == null || type === \"\") return null;\n return h(\n Tag,\n {\n variant: \"minimal\",\n className: classNames(\"surface-tag\", \"surface-type-tag\", className),\n },\n type,\n );\n}\n\nexport interface SurfaceStatusLegendProps {\n statuses?: SurfaceStatus[];\n showDescriptions?: boolean;\n className?: string;\n}\n\n/** A legend of surface line styles, one entry per boundary status. */\nexport function SurfaceStatusLegend(props: SurfaceStatusLegendProps) {\n const {\n statuses = surfaceStatuses,\n showDescriptions = false,\n className,\n } = props;\n return h(\n \"ul.surface-status-legend\",\n {\n className: classNames(className, {\n \"with-descriptions\": showDescriptions,\n }),\n },\n statuses.map((status) => {\n let description: ReactNode = null;\n if (showDescriptions) {\n description = h(\n \"div.legend-description\",\n surfaceStatusDescriptions[status],\n );\n }\n return h(\n \"li.legend-item\",\n { key: status, className: surfaceClasses({ status }) },\n [\n h(\"div.surface-label-marker\"),\n h(\"div.legend-text\", [\n h(\"div.legend-label\", surfaceStatusLabels[status]),\n description,\n ]),\n ],\n );\n }),\n );\n}\n"],"names":["hyper","surfaceStyles","styles"],"mappings":"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"}
@@ -6,7 +6,6 @@ const React = require("react");
6
6
  const dataComponents = require("@macrostrat/data-components");
7
7
  const dataProvider = require("@macrostrat/data-provider");
8
8
  const notes = require("../notes.cjs");
9
- const ageRange = require("../unit-details/age-range.cjs");
10
9
  const column_module = require("../column.module.sass.cjs");
11
10
  const surfaces_module = require("./surfaces.module.sass.cjs");
12
11
  const types = require("./types.cjs");
@@ -221,7 +220,7 @@ function SurfaceNoteLabel({ note }) {
221
220
  primary = h(dataComponents.IntervalTag, {
222
221
  interval,
223
222
  size: dataComponents.TagSize.Small,
224
- prefix: h(ageRange.Proportion, { value: surface.proportion }),
223
+ proportion: surface.proportion,
225
224
  className: "surface-interval-tag"
226
225
  });
227
226
  } else {
@@ -1 +1 @@
1
- {"version":3,"file":"surfaces.cjs","sources":["../../src/age-model/surfaces.ts"],"sourcesContent":["/** The surfaces view: age-model calibration surfaces drawn on a column.\n *\n * `ColumnSurfaces` is dropped into a `Column` as a child. It draws one line\n * per surface across the units (`ColumnSurfaceLines`) and a notes column of\n * labels beside them (`ColumnSurfaceLabels`), styled by `boundary_status` and\n * `boundary_type`, with hover and selection.\n */\nimport hyper from \"@macrostrat/hyper\";\nimport classNames from \"classnames\";\nimport {\n type CSSProperties,\n type RefObject,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { NoteData } from \"@macrostrat/column-components\";\nimport {\n type IntervalShort,\n IntervalTag,\n TagSize,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport {\n useClaimLabelColumn,\n useCompositeScale,\n useMacrostratColumnData,\n} from \"../data-provider\";\nimport { ColumnNotes } from \"../notes\";\nimport { AgeLabel, Proportion } from \"../unit-details/age-range\";\nimport columnStyles from \"../column.module.sass\";\nimport styles from \"./surfaces.module.sass\";\nimport {\n type ColumnSurface,\n type SurfaceStatus,\n formatProportion,\n surfaceLabel,\n surfacePosition,\n surfaceStatusLabels,\n surfaceToken,\n TIE_POINT_STATUSES,\n} from \"./types\";\nimport { type UseColumnSurfacesOptions, useColumnSurfaces } from \"./data\";\n\nconst h = hyper.styled(styles);\n\n/** How far the surface lines extend: across the units column only, or the\n * full width of the column including its axes. */\nexport type SurfaceLinesExtent = \"units\" | \"column\";\n\nexport type SurfaceSelectionHandler = (surface: ColumnSurface | null) => void;\n\nexport interface SurfaceSelectionProps {\n /** The selected surface's id. Pass `null` for a controlled, empty\n * selection; leave undefined for the component to manage selection. */\n selectedSurface?: ColumnSurface[\"id\"] | null;\n onSelectSurface?: SurfaceSelectionHandler;\n}\n\nexport interface ColumnSurfacesProps\n extends UseColumnSurfacesOptions, SurfaceSelectionProps {\n showLines?: boolean;\n showLabels?: boolean;\n extent?: SurfaceLinesExtent;\n /** Width of the labels column, connector included (default 200) */\n labelWidth?: number;\n labelPaddingLeft?: number;\n /** Only show surfaces with these statuses */\n statuses?: SurfaceStatus[] | null;\n /** Which surfaces get a label. Defaults to the tie points — the statuses\n * at which the age model was constrained — so interpolated (`modeled`),\n * unspecified and unit-derived surfaces are drawn as lines only. Pass\n * `null` to label every surface shown. */\n labelStatuses?: SurfaceStatus[] | null;\n /** Labels closer than this (in pixels) are thinned out, since the column\n * has finite room; the selected surface's label is always kept. */\n minLabelSpacing?: number;\n className?: string;\n}\n\nexport function ColumnSurfaces(props: ColumnSurfacesProps) {\n const {\n showLines = true,\n showLabels = true,\n extent = \"units\",\n labelWidth,\n labelPaddingLeft,\n statuses,\n labelStatuses = TIE_POINT_STATUSES,\n minLabelSpacing,\n selectedSurface,\n onSelectSurface,\n className,\n ...dataOptions\n } = props;\n\n const { surfaces: allSurfaces } = useColumnSurfaces(dataOptions);\n const surfaces = useMemo(\n () => filterByStatus(allSurfaces, statuses),\n [allSurfaces, statuses],\n );\n\n const [selectedID, select] = useSurfaceSelection(\n selectedSurface,\n onSelectSurface,\n );\n\n return h([\n h.if(showLines)(ColumnSurfaceLines, {\n surfaces,\n extent,\n selectedSurface: selectedID,\n onSelectSurface: select,\n className,\n }),\n h.if(showLabels)(ColumnSurfaceLabels, {\n surfaces,\n labelStatuses,\n minLabelSpacing,\n width: labelWidth,\n paddingLeft: labelPaddingLeft,\n selectedSurface: selectedID,\n onSelectSurface: select,\n className,\n }),\n ]);\n}\n\nexport interface ColumnSurfaceLinesProps extends SurfaceSelectionProps {\n surfaces: ColumnSurface[];\n extent?: SurfaceLinesExtent;\n className?: string;\n}\n\n/** One horizontal line per surface, overlaid on the column at the surface's\n * age (or measured position, for height and depth columns). */\nexport function ColumnSurfaceLines(props: ColumnSurfaceLinesProps) {\n const {\n surfaces,\n extent = \"units\",\n selectedSurface,\n onSelectSurface,\n className,\n } = props;\n const scale = useCompositeScale();\n const { axisType, totalHeight } = useMacrostratColumnData();\n const intervalMap = useSurfaceIntervalDefs(surfaces);\n\n const ref = useRef<HTMLDivElement>(null);\n const unitsExtent = useUnitsColumnExtent(ref, extent === \"units\");\n\n let style: CSSProperties = { height: totalHeight };\n if (unitsExtent != null) {\n style = { ...style, left: unitsExtent.left, width: unitsExtent.width };\n }\n const measuring = extent === \"units\" && unitsExtent == null;\n\n return h(\n \"div.column-surface-lines\",\n { ref, style, className: classNames(className, { measuring }) },\n surfaces.map((surface) => {\n const position = surfacePosition(surface, axisType);\n if (position == null) return null;\n const y = scale(position);\n if (y == null) return null;\n return h(SurfaceLine, {\n key: surface.id,\n surface,\n y,\n color: surfaceIntervalColor(surface, intervalMap),\n selected: surface.id === selectedSurface,\n onSelect: onSelectSurface,\n });\n }),\n );\n}\n\nfunction SurfaceLine({\n surface,\n y,\n color,\n selected,\n onSelect,\n}: {\n surface: ColumnSurface;\n y: number;\n /** The interval color, when known; otherwise the status color is used */\n color?: string | null;\n selected: boolean;\n onSelect?: SurfaceSelectionHandler;\n}) {\n const onClick = useCallback(\n (evt: MouseEvent) => {\n // Don't let the column deselect its unit\n evt.stopPropagation();\n if (selected) {\n onSelect?.(null);\n } else {\n onSelect?.(surface);\n }\n },\n [surface, selected, onSelect],\n );\n\n let style: CSSProperties = { top: y };\n if (color != null) {\n style = { ...style, \"--surface-color\": color } as CSSProperties;\n }\n\n return h(\n \"div.surface-line\",\n {\n style,\n className: classNames(surfaceClasses(surface), {\n selected,\n interactive: onSelect != null,\n }),\n title: surfaceLabel(surface),\n onClick,\n },\n h(\"div.surface-line-inner\"),\n );\n}\n\nexport interface ColumnSurfaceLabelsProps extends SurfaceSelectionProps {\n surfaces: ColumnSurface[];\n /** Which surfaces get a label (see `ColumnSurfacesProps.labelStatuses`) */\n labelStatuses?: SurfaceStatus[] | null;\n /** Minimum pixel spacing between labels (see `ColumnSurfacesProps`) */\n minLabelSpacing?: number;\n /** Total width, connector included */\n width?: number;\n paddingLeft?: number;\n className?: string;\n}\n\ninterface SurfaceNote extends NoteData {\n /** The interval color, which the note's connector picks up */\n color?: string;\n surface: ColumnSurface;\n /** The calibration interval, with color and rank from the definitions */\n interval: IntervalShort | null;\n selected: boolean;\n}\n\n/** A notes column of surface labels, laid out beside the units with the\n * collision avoidance of `NotesColumn`. It takes the label column over from\n * the unit labels while mounted: labels are one or the other. */\nexport function ColumnSurfaceLabels(props: ColumnSurfaceLabelsProps) {\n const {\n surfaces,\n labelStatuses = TIE_POINT_STATUSES,\n minLabelSpacing = 22,\n width = 200,\n paddingLeft = 24,\n selectedSurface,\n onSelectSurface,\n className,\n } = props;\n const { axisType } = useMacrostratColumnData();\n const scale = useCompositeScale();\n const intervalMap = useSurfaceIntervalDefs(surfaces);\n useClaimLabelColumn();\n\n const labeled = useMemo(() => {\n const byStatus = filterByStatus(surfaces, labelStatuses);\n return thinByPixelSpacing(\n byStatus,\n (s) => scale(surfacePosition(s, axisType) ?? NaN),\n minLabelSpacing,\n selectedSurface,\n );\n }, [\n surfaces,\n labelStatuses,\n minLabelSpacing,\n selectedSurface,\n scale,\n axisType,\n ]);\n\n const notes: SurfaceNote[] = useMemo(() => {\n const _notes: SurfaceNote[] = [];\n for (const surface of labeled) {\n const position = surfacePosition(surface, axisType);\n if (position == null) continue;\n _notes.push({\n id: surface.id,\n height: position,\n note: surfaceLabel(surface),\n // The note's color reaches its connector, so a label's leader line\n // matches the surface line it points at\n color: surfaceIntervalColor(surface, intervalMap) ?? undefined,\n surface,\n interval: calibrationInterval(surface, intervalMap),\n selected: surface.id === selectedSurface,\n });\n }\n return _notes;\n }, [labeled, axisType, selectedSurface, intervalMap]);\n\n const onClickNote = useCallback(\n (note: NoteData) => {\n const { surface, selected } = note as SurfaceNote;\n if (selected) {\n onSelectSurface?.(null);\n } else {\n onSelectSurface?.(surface);\n }\n },\n [onSelectSurface],\n );\n\n return h(\n \"div.column-surface-labels\",\n { className },\n h(ColumnNotes, {\n notes,\n width,\n paddingLeft,\n noteComponent: SurfaceNoteLabel,\n onClickNote,\n forceOptions: LABEL_FORCE_OPTIONS,\n // The leader runs from the surface line in the column to the tag body,\n // continuing a little past both ends rather than stopping in the gap —\n // so it needs no endpoint marker of its own\n connectorOverhang: LABEL_CONNECTOR_OVERHANG,\n showPointMarker: false,\n }),\n );\n}\n\n/** Breathing room between stacked labels, in pixels */\nconst LABEL_FORCE_OPTIONS = { nodeSpacing: 2 };\n\n/** How far the label's leader line continues past each end, in pixels: left\n * into the column to meet the surface line, right under the tag body. */\nconst LABEL_CONNECTOR_OVERHANG: [number, number] = [8, 6];\n\n/** A surface's label: its calibration interval as the standard interval tag\n * (with the position within the interval as the tag's detail), and the\n * modeled age beneath. Surfaces without a calibration show their status. */\nfunction SurfaceNoteLabel({ note }: { note: SurfaceNote }) {\n const { surface, interval, selected } = note;\n\n let primary: any;\n if (interval != null) {\n primary = h(IntervalTag, {\n interval,\n size: TagSize.Small,\n prefix: h(Proportion, { value: surface.proportion }),\n className: \"surface-interval-tag\",\n });\n } else {\n primary = h(\n \"span.surface-label-status\",\n `${surfaceStatusLabels[surface.status]} surface`,\n );\n }\n\n return h(\n \"div.surface-label\",\n { className: classNames(surfaceClasses(surface), { selected }) },\n h(\"div.surface-label-primary\", primary),\n );\n}\n\n/** The interval definitions for the surfaces' calibration intervals. The age\n * model carries interval ids and names but no colors, so they come from the\n * definitions store (which holds them all, and fetches once). */\nfunction useSurfaceIntervalDefs(\n surfaces: ColumnSurface[],\n): Map<number, any> | null {\n const intervalIDs = useMemo(() => {\n const ids = new Set<number>();\n for (const surface of surfaces) {\n if (surface.calibration != null) ids.add(surface.calibration.id);\n }\n return Array.from(ids);\n }, [surfaces]);\n return useMacrostratDefs(\"intervals\", intervalIDs, null);\n}\n\n/** The color a surface is drawn in: its calibration interval's, so the line\n * and its label's leader read as the interval the surface is tied to. `null`\n * for an uncalibrated surface, or before the definitions load — the status\n * color stands in. */\nfunction surfaceIntervalColor(\n surface: ColumnSurface,\n intervalMap: Map<number, any> | null,\n): string | null {\n const id = surface.calibration?.id;\n if (id == null) return null;\n return intervalMap?.get(id)?.color ?? null;\n}\n\n/** The calibration interval in the shape the interval tag takes, colored\n * from the definitions when they have loaded. */\nfunction calibrationInterval(\n surface: ColumnSurface,\n intervalMap: Map<number, any> | null,\n): IntervalShort | null {\n const { calibration } = surface;\n if (calibration == null) return null;\n const def = intervalMap?.get(calibration.id);\n return {\n id: calibration.id,\n name: calibration.name,\n b_age: calibration.b_age,\n t_age: calibration.t_age,\n color: def?.color,\n rank: def?.rank,\n };\n}\n\n/** Class names shared by the lines, labels, legend and tags, so a status or\n * type reads the same everywhere. */\nexport function surfaceClasses(surface: {\n status?: SurfaceStatus | null;\n type?: string | null;\n}): string {\n return classNames(\n `status-${surfaceToken(surface.status)}`,\n `type-${surfaceToken(surface.type)}`,\n );\n}\n\n/** Walk the surfaces down the column and drop any whose label would sit\n * within `minSpacing` pixels of the last one kept. The selected surface is\n * always kept (and displaces a neighbor if need be). */\nfunction thinByPixelSpacing(\n surfaces: ColumnSurface[],\n pixelPosition: (s: ColumnSurface) => number | null,\n minSpacing: number,\n selectedSurface: ColumnSurface[\"id\"] | null | undefined,\n): ColumnSurface[] {\n if (minSpacing <= 0) return surfaces;\n const positioned = surfaces\n .map((surface) => ({ surface, y: pixelPosition(surface) }))\n .filter((d) => d.y != null && !Number.isNaN(d.y))\n .sort((a, b) => a.y - b.y);\n\n const kept: { surface: ColumnSurface; y: number }[] = [];\n for (const item of positioned) {\n const selected = item.surface.id === selectedSurface;\n const last = kept[kept.length - 1];\n if (last == null || item.y - last.y >= minSpacing) {\n kept.push(item);\n } else if (selected) {\n // The selection wins its slot\n kept[kept.length - 1] = item;\n }\n }\n return kept.map((d) => d.surface);\n}\n\nfunction filterByStatus(\n surfaces: ColumnSurface[],\n statuses: SurfaceStatus[] | null | undefined,\n): ColumnSurface[] {\n if (statuses == null) return surfaces;\n const allowed = new Set(statuses);\n return surfaces.filter((d) => allowed.has(d.status));\n}\n\n/** Controlled-or-uncontrolled selection: when `selectedID` is passed (even as\n * `null`) the consumer owns it; otherwise it is kept internally. */\nfunction useSurfaceSelection(\n selectedID: ColumnSurface[\"id\"] | null | undefined,\n onSelect: SurfaceSelectionHandler | undefined,\n): [ColumnSurface[\"id\"] | null, SurfaceSelectionHandler] {\n const [internal, setInternal] = useState<ColumnSurface[\"id\"] | null>(null);\n const isControlled = selectedID !== undefined;\n\n const select: SurfaceSelectionHandler = useCallback(\n (surface) => {\n setInternal(surface?.id ?? null);\n onSelect?.(surface);\n },\n [onSelect],\n );\n\n let current = internal;\n if (isControlled) {\n current = selectedID;\n }\n return [current, select];\n}\n\ninterface HorizontalExtent {\n left: number;\n width: number;\n}\n\n/** `useLayoutEffect` in the browser, `useEffect` on the server — where it\n * would warn and has nothing to measure anyway. */\nconst useMeasureEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\n/** Measure where the units column sits within the `Column`, so an overlay\n * can cover exactly the units rather than the axes. `null` while unmeasured,\n * when disabled, or when the units column can't be found. */\nfunction useUnitsColumnExtent(\n ref: RefObject<HTMLDivElement | null>,\n enabled: boolean,\n): HorizontalExtent | null {\n const [extent, setExtent] = useState<HorizontalExtent | null>(null);\n\n const measure = useCallback(() => {\n if (!enabled) return;\n const parent = ref.current?.parentElement;\n const target = parent?.querySelector<HTMLElement>(\n `.${unitsContainerClass()}`,\n );\n if (parent == null || target == null) return;\n\n const p = parent.getBoundingClientRect();\n const t = target.getBoundingClientRect();\n const next = { left: t.left - p.left, width: t.width };\n setExtent((prev) => {\n if (prev?.left === next.left && prev?.width === next.width) {\n return prev;\n }\n return next;\n });\n }, [enabled]);\n\n // Re-measure on every render as a backstop: cheap, and it catches layout\n // changes that no observer reports.\n useMeasureEffect(measure);\n\n useMeasureEffect(() => {\n if (!enabled) {\n setExtent(null);\n return;\n }\n const parent = ref.current?.parentElement;\n if (parent == null) return;\n if (typeof ResizeObserver === \"undefined\") return;\n\n const observer = new ResizeObserver(measure);\n // The units column *moves* when a sibling changes width — the timescale\n // widening once its intervals load, or its level count changing — and\n // that is not a resize of the units column or of the column itself, so\n // the siblings have to be watched too.\n observer.observe(parent);\n for (const child of Array.from(parent.children)) {\n observer.observe(child);\n }\n return () => observer.disconnect();\n }, [enabled, measure]);\n\n return extent;\n}\n\n/** The (module-scoped) class of the units container rendered by\n * `SectionsColumn`. */\nfunction unitsContainerClass(): string {\n const s = columnStyles as any;\n return (\n s[\"section-units-container\"] ??\n s.sectionUnitsContainer ??\n \"section-units-container\"\n );\n}\n"],"names":["hyper","styles","TIE_POINT_STATUSES","useColumnSurfaces","useMemo","useCompositeScale","useMacrostratColumnData","useRef","classNames","surfacePosition","useCallback","surfaceLabel","useClaimLabelColumn","notes","ColumnNotes","IntervalTag","TagSize","Proportion","surfaceStatusLabels","useMacrostratDefs","surfaceToken","useState","useEffect","useLayoutEffect","columnStyles"],"mappings":"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"}
1
+ {"version":3,"file":"surfaces.cjs","sources":["../../src/age-model/surfaces.ts"],"sourcesContent":["/** The surfaces view: age-model calibration surfaces drawn on a column.\n *\n * `ColumnSurfaces` is dropped into a `Column` as a child. It draws one line\n * per surface across the units (`ColumnSurfaceLines`) and a notes column of\n * labels beside them (`ColumnSurfaceLabels`), styled by `boundary_status` and\n * `boundary_type`, with hover and selection.\n */\nimport hyper from \"@macrostrat/hyper\";\nimport classNames from \"classnames\";\nimport {\n type CSSProperties,\n type RefObject,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { NoteData } from \"@macrostrat/column-components\";\nimport {\n type IntervalShort,\n IntervalTag,\n TagSize,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport {\n useClaimLabelColumn,\n useCompositeScale,\n useMacrostratColumnData,\n} from \"../data-provider\";\nimport { ColumnNotes } from \"../notes\";\nimport { AgeLabel } from \"../unit-details/age-range\";\nimport columnStyles from \"../column.module.sass\";\nimport styles from \"./surfaces.module.sass\";\nimport {\n type ColumnSurface,\n type SurfaceStatus,\n formatProportion,\n surfaceLabel,\n surfacePosition,\n surfaceStatusLabels,\n surfaceToken,\n TIE_POINT_STATUSES,\n} from \"./types\";\nimport { type UseColumnSurfacesOptions, useColumnSurfaces } from \"./data\";\n\nconst h = hyper.styled(styles);\n\n/** How far the surface lines extend: across the units column only, or the\n * full width of the column including its axes. */\nexport type SurfaceLinesExtent = \"units\" | \"column\";\n\nexport type SurfaceSelectionHandler = (surface: ColumnSurface | null) => void;\n\nexport interface SurfaceSelectionProps {\n /** The selected surface's id. Pass `null` for a controlled, empty\n * selection; leave undefined for the component to manage selection. */\n selectedSurface?: ColumnSurface[\"id\"] | null;\n onSelectSurface?: SurfaceSelectionHandler;\n}\n\nexport interface ColumnSurfacesProps\n extends UseColumnSurfacesOptions, SurfaceSelectionProps {\n showLines?: boolean;\n showLabels?: boolean;\n extent?: SurfaceLinesExtent;\n /** Width of the labels column, connector included (default 200) */\n labelWidth?: number;\n labelPaddingLeft?: number;\n /** Only show surfaces with these statuses */\n statuses?: SurfaceStatus[] | null;\n /** Which surfaces get a label. Defaults to the tie points — the statuses\n * at which the age model was constrained — so interpolated (`modeled`),\n * unspecified and unit-derived surfaces are drawn as lines only. Pass\n * `null` to label every surface shown. */\n labelStatuses?: SurfaceStatus[] | null;\n /** Labels closer than this (in pixels) are thinned out, since the column\n * has finite room; the selected surface's label is always kept. */\n minLabelSpacing?: number;\n className?: string;\n}\n\nexport function ColumnSurfaces(props: ColumnSurfacesProps) {\n const {\n showLines = true,\n showLabels = true,\n extent = \"units\",\n labelWidth,\n labelPaddingLeft,\n statuses,\n labelStatuses = TIE_POINT_STATUSES,\n minLabelSpacing,\n selectedSurface,\n onSelectSurface,\n className,\n ...dataOptions\n } = props;\n\n const { surfaces: allSurfaces } = useColumnSurfaces(dataOptions);\n const surfaces = useMemo(\n () => filterByStatus(allSurfaces, statuses),\n [allSurfaces, statuses],\n );\n\n const [selectedID, select] = useSurfaceSelection(\n selectedSurface,\n onSelectSurface,\n );\n\n return h([\n h.if(showLines)(ColumnSurfaceLines, {\n surfaces,\n extent,\n selectedSurface: selectedID,\n onSelectSurface: select,\n className,\n }),\n h.if(showLabels)(ColumnSurfaceLabels, {\n surfaces,\n labelStatuses,\n minLabelSpacing,\n width: labelWidth,\n paddingLeft: labelPaddingLeft,\n selectedSurface: selectedID,\n onSelectSurface: select,\n className,\n }),\n ]);\n}\n\nexport interface ColumnSurfaceLinesProps extends SurfaceSelectionProps {\n surfaces: ColumnSurface[];\n extent?: SurfaceLinesExtent;\n className?: string;\n}\n\n/** One horizontal line per surface, overlaid on the column at the surface's\n * age (or measured position, for height and depth columns). */\nexport function ColumnSurfaceLines(props: ColumnSurfaceLinesProps) {\n const {\n surfaces,\n extent = \"units\",\n selectedSurface,\n onSelectSurface,\n className,\n } = props;\n const scale = useCompositeScale();\n const { axisType, totalHeight } = useMacrostratColumnData();\n const intervalMap = useSurfaceIntervalDefs(surfaces);\n\n const ref = useRef<HTMLDivElement>(null);\n const unitsExtent = useUnitsColumnExtent(ref, extent === \"units\");\n\n let style: CSSProperties = { height: totalHeight };\n if (unitsExtent != null) {\n style = { ...style, left: unitsExtent.left, width: unitsExtent.width };\n }\n const measuring = extent === \"units\" && unitsExtent == null;\n\n return h(\n \"div.column-surface-lines\",\n { ref, style, className: classNames(className, { measuring }) },\n surfaces.map((surface) => {\n const position = surfacePosition(surface, axisType);\n if (position == null) return null;\n const y = scale(position);\n if (y == null) return null;\n return h(SurfaceLine, {\n key: surface.id,\n surface,\n y,\n color: surfaceIntervalColor(surface, intervalMap),\n selected: surface.id === selectedSurface,\n onSelect: onSelectSurface,\n });\n }),\n );\n}\n\nfunction SurfaceLine({\n surface,\n y,\n color,\n selected,\n onSelect,\n}: {\n surface: ColumnSurface;\n y: number;\n /** The interval color, when known; otherwise the status color is used */\n color?: string | null;\n selected: boolean;\n onSelect?: SurfaceSelectionHandler;\n}) {\n const onClick = useCallback(\n (evt: MouseEvent) => {\n // Don't let the column deselect its unit\n evt.stopPropagation();\n if (selected) {\n onSelect?.(null);\n } else {\n onSelect?.(surface);\n }\n },\n [surface, selected, onSelect],\n );\n\n let style: CSSProperties = { top: y };\n if (color != null) {\n style = { ...style, \"--surface-color\": color } as CSSProperties;\n }\n\n return h(\n \"div.surface-line\",\n {\n style,\n className: classNames(surfaceClasses(surface), {\n selected,\n interactive: onSelect != null,\n }),\n title: surfaceLabel(surface),\n onClick,\n },\n h(\"div.surface-line-inner\"),\n );\n}\n\nexport interface ColumnSurfaceLabelsProps extends SurfaceSelectionProps {\n surfaces: ColumnSurface[];\n /** Which surfaces get a label (see `ColumnSurfacesProps.labelStatuses`) */\n labelStatuses?: SurfaceStatus[] | null;\n /** Minimum pixel spacing between labels (see `ColumnSurfacesProps`) */\n minLabelSpacing?: number;\n /** Total width, connector included */\n width?: number;\n paddingLeft?: number;\n className?: string;\n}\n\ninterface SurfaceNote extends NoteData {\n /** The interval color, which the note's connector picks up */\n color?: string;\n surface: ColumnSurface;\n /** The calibration interval, with color and rank from the definitions */\n interval: IntervalShort | null;\n selected: boolean;\n}\n\n/** A notes column of surface labels, laid out beside the units with the\n * collision avoidance of `NotesColumn`. It takes the label column over from\n * the unit labels while mounted: labels are one or the other. */\nexport function ColumnSurfaceLabels(props: ColumnSurfaceLabelsProps) {\n const {\n surfaces,\n labelStatuses = TIE_POINT_STATUSES,\n minLabelSpacing = 22,\n width = 200,\n paddingLeft = 24,\n selectedSurface,\n onSelectSurface,\n className,\n } = props;\n const { axisType } = useMacrostratColumnData();\n const scale = useCompositeScale();\n const intervalMap = useSurfaceIntervalDefs(surfaces);\n useClaimLabelColumn();\n\n const labeled = useMemo(() => {\n const byStatus = filterByStatus(surfaces, labelStatuses);\n return thinByPixelSpacing(\n byStatus,\n (s) => scale(surfacePosition(s, axisType) ?? NaN),\n minLabelSpacing,\n selectedSurface,\n );\n }, [\n surfaces,\n labelStatuses,\n minLabelSpacing,\n selectedSurface,\n scale,\n axisType,\n ]);\n\n const notes: SurfaceNote[] = useMemo(() => {\n const _notes: SurfaceNote[] = [];\n for (const surface of labeled) {\n const position = surfacePosition(surface, axisType);\n if (position == null) continue;\n _notes.push({\n id: surface.id,\n height: position,\n note: surfaceLabel(surface),\n // The note's color reaches its connector, so a label's leader line\n // matches the surface line it points at\n color: surfaceIntervalColor(surface, intervalMap) ?? undefined,\n surface,\n interval: calibrationInterval(surface, intervalMap),\n selected: surface.id === selectedSurface,\n });\n }\n return _notes;\n }, [labeled, axisType, selectedSurface, intervalMap]);\n\n const onClickNote = useCallback(\n (note: NoteData) => {\n const { surface, selected } = note as SurfaceNote;\n if (selected) {\n onSelectSurface?.(null);\n } else {\n onSelectSurface?.(surface);\n }\n },\n [onSelectSurface],\n );\n\n return h(\n \"div.column-surface-labels\",\n { className },\n h(ColumnNotes, {\n notes,\n width,\n paddingLeft,\n noteComponent: SurfaceNoteLabel,\n onClickNote,\n forceOptions: LABEL_FORCE_OPTIONS,\n // The leader runs from the surface line in the column to the tag body,\n // continuing a little past both ends rather than stopping in the gap —\n // so it needs no endpoint marker of its own\n connectorOverhang: LABEL_CONNECTOR_OVERHANG,\n showPointMarker: false,\n }),\n );\n}\n\n/** Breathing room between stacked labels, in pixels */\nconst LABEL_FORCE_OPTIONS = { nodeSpacing: 2 };\n\n/** How far the label's leader line continues past each end, in pixels: left\n * into the column to meet the surface line, right under the tag body. */\nconst LABEL_CONNECTOR_OVERHANG: [number, number] = [8, 6];\n\n/** A surface's label: its calibration interval as the standard interval tag\n * (with the position within the interval as the tag's detail), and the\n * modeled age beneath. Surfaces without a calibration show their status. */\nfunction SurfaceNoteLabel({ note }: { note: SurfaceNote }) {\n const { surface, interval, selected } = note;\n\n let primary: any;\n if (interval != null) {\n primary = h(IntervalTag, {\n interval,\n size: TagSize.Small,\n proportion: surface.proportion,\n className: \"surface-interval-tag\",\n });\n } else {\n primary = h(\n \"span.surface-label-status\",\n `${surfaceStatusLabels[surface.status]} surface`,\n );\n }\n\n return h(\n \"div.surface-label\",\n { className: classNames(surfaceClasses(surface), { selected }) },\n h(\"div.surface-label-primary\", primary),\n );\n}\n\n/** The interval definitions for the surfaces' calibration intervals. The age\n * model carries interval ids and names but no colors, so they come from the\n * definitions store (which holds them all, and fetches once). */\nfunction useSurfaceIntervalDefs(\n surfaces: ColumnSurface[],\n): Map<number, any> | null {\n const intervalIDs = useMemo(() => {\n const ids = new Set<number>();\n for (const surface of surfaces) {\n if (surface.calibration != null) ids.add(surface.calibration.id);\n }\n return Array.from(ids);\n }, [surfaces]);\n return useMacrostratDefs(\"intervals\", intervalIDs, null);\n}\n\n/** The color a surface is drawn in: its calibration interval's, so the line\n * and its label's leader read as the interval the surface is tied to. `null`\n * for an uncalibrated surface, or before the definitions load — the status\n * color stands in. */\nfunction surfaceIntervalColor(\n surface: ColumnSurface,\n intervalMap: Map<number, any> | null,\n): string | null {\n const id = surface.calibration?.id;\n if (id == null) return null;\n return intervalMap?.get(id)?.color ?? null;\n}\n\n/** The calibration interval in the shape the interval tag takes, colored\n * from the definitions when they have loaded. */\nfunction calibrationInterval(\n surface: ColumnSurface,\n intervalMap: Map<number, any> | null,\n): IntervalShort | null {\n const { calibration } = surface;\n if (calibration == null) return null;\n const def = intervalMap?.get(calibration.id);\n return {\n id: calibration.id,\n name: calibration.name,\n b_age: calibration.b_age,\n t_age: calibration.t_age,\n color: def?.color,\n rank: def?.rank,\n };\n}\n\n/** Class names shared by the lines, labels, legend and tags, so a status or\n * type reads the same everywhere. */\nexport function surfaceClasses(surface: {\n status?: SurfaceStatus | null;\n type?: string | null;\n}): string {\n return classNames(\n `status-${surfaceToken(surface.status)}`,\n `type-${surfaceToken(surface.type)}`,\n );\n}\n\n/** Walk the surfaces down the column and drop any whose label would sit\n * within `minSpacing` pixels of the last one kept. The selected surface is\n * always kept (and displaces a neighbor if need be). */\nfunction thinByPixelSpacing(\n surfaces: ColumnSurface[],\n pixelPosition: (s: ColumnSurface) => number | null,\n minSpacing: number,\n selectedSurface: ColumnSurface[\"id\"] | null | undefined,\n): ColumnSurface[] {\n if (minSpacing <= 0) return surfaces;\n const positioned = surfaces\n .map((surface) => ({ surface, y: pixelPosition(surface) }))\n .filter((d) => d.y != null && !Number.isNaN(d.y))\n .sort((a, b) => a.y - b.y);\n\n const kept: { surface: ColumnSurface; y: number }[] = [];\n for (const item of positioned) {\n const selected = item.surface.id === selectedSurface;\n const last = kept[kept.length - 1];\n if (last == null || item.y - last.y >= minSpacing) {\n kept.push(item);\n } else if (selected) {\n // The selection wins its slot\n kept[kept.length - 1] = item;\n }\n }\n return kept.map((d) => d.surface);\n}\n\nfunction filterByStatus(\n surfaces: ColumnSurface[],\n statuses: SurfaceStatus[] | null | undefined,\n): ColumnSurface[] {\n if (statuses == null) return surfaces;\n const allowed = new Set(statuses);\n return surfaces.filter((d) => allowed.has(d.status));\n}\n\n/** Controlled-or-uncontrolled selection: when `selectedID` is passed (even as\n * `null`) the consumer owns it; otherwise it is kept internally. */\nfunction useSurfaceSelection(\n selectedID: ColumnSurface[\"id\"] | null | undefined,\n onSelect: SurfaceSelectionHandler | undefined,\n): [ColumnSurface[\"id\"] | null, SurfaceSelectionHandler] {\n const [internal, setInternal] = useState<ColumnSurface[\"id\"] | null>(null);\n const isControlled = selectedID !== undefined;\n\n const select: SurfaceSelectionHandler = useCallback(\n (surface) => {\n setInternal(surface?.id ?? null);\n onSelect?.(surface);\n },\n [onSelect],\n );\n\n let current = internal;\n if (isControlled) {\n current = selectedID;\n }\n return [current, select];\n}\n\ninterface HorizontalExtent {\n left: number;\n width: number;\n}\n\n/** `useLayoutEffect` in the browser, `useEffect` on the server — where it\n * would warn and has nothing to measure anyway. */\nconst useMeasureEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\n/** Measure where the units column sits within the `Column`, so an overlay\n * can cover exactly the units rather than the axes. `null` while unmeasured,\n * when disabled, or when the units column can't be found. */\nfunction useUnitsColumnExtent(\n ref: RefObject<HTMLDivElement | null>,\n enabled: boolean,\n): HorizontalExtent | null {\n const [extent, setExtent] = useState<HorizontalExtent | null>(null);\n\n const measure = useCallback(() => {\n if (!enabled) return;\n const parent = ref.current?.parentElement;\n const target = parent?.querySelector<HTMLElement>(\n `.${unitsContainerClass()}`,\n );\n if (parent == null || target == null) return;\n\n const p = parent.getBoundingClientRect();\n const t = target.getBoundingClientRect();\n const next = { left: t.left - p.left, width: t.width };\n setExtent((prev) => {\n if (prev?.left === next.left && prev?.width === next.width) {\n return prev;\n }\n return next;\n });\n }, [enabled]);\n\n // Re-measure on every render as a backstop: cheap, and it catches layout\n // changes that no observer reports.\n useMeasureEffect(measure);\n\n useMeasureEffect(() => {\n if (!enabled) {\n setExtent(null);\n return;\n }\n const parent = ref.current?.parentElement;\n if (parent == null) return;\n if (typeof ResizeObserver === \"undefined\") return;\n\n const observer = new ResizeObserver(measure);\n // The units column *moves* when a sibling changes width — the timescale\n // widening once its intervals load, or its level count changing — and\n // that is not a resize of the units column or of the column itself, so\n // the siblings have to be watched too.\n observer.observe(parent);\n for (const child of Array.from(parent.children)) {\n observer.observe(child);\n }\n return () => observer.disconnect();\n }, [enabled, measure]);\n\n return extent;\n}\n\n/** The (module-scoped) class of the units container rendered by\n * `SectionsColumn`. */\nfunction unitsContainerClass(): string {\n const s = columnStyles as any;\n return (\n s[\"section-units-container\"] ??\n s.sectionUnitsContainer ??\n \"section-units-container\"\n );\n}\n"],"names":["hyper","styles","TIE_POINT_STATUSES","useColumnSurfaces","useMemo","useCompositeScale","useMacrostratColumnData","useRef","classNames","surfacePosition","useCallback","surfaceLabel","useClaimLabelColumn","notes","ColumnNotes","IntervalTag","TagSize","surfaceStatusLabels","useMacrostratDefs","surfaceToken","useState","useEffect","useLayoutEffect","columnStyles"],"mappings":"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"}
@@ -4,7 +4,6 @@ import { useMemo, useCallback, useRef, useState, useEffect, useLayoutEffect } fr
4
4
  import { IntervalTag, TagSize } from "@macrostrat/data-components";
5
5
  import { useMacrostratDefs } from "@macrostrat/data-provider";
6
6
  import { ColumnNotes } from "../notes.js";
7
- import { Proportion } from "../unit-details/age-range.js";
8
7
  import h$3 from "../column.module.sass.js";
9
8
  import h$2 from "./surfaces.module.sass.js";
10
9
  import { TIE_POINT_STATUSES, surfacePosition, surfaceLabel, surfaceToken, surfaceStatusLabels } from "./types.js";
@@ -216,7 +215,7 @@ function SurfaceNoteLabel({ note }) {
216
215
  primary = h(IntervalTag, {
217
216
  interval,
218
217
  size: TagSize.Small,
219
- prefix: h(Proportion, { value: surface.proportion }),
218
+ proportion: surface.proportion,
220
219
  className: "surface-interval-tag"
221
220
  });
222
221
  } else {