@macrostrat/column-views 3.11.0 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +169 -0
- package/dist/age-model/data.cjs +57 -0
- package/dist/age-model/data.cjs.map +1 -0
- package/dist/age-model/data.d.ts +29 -0
- package/dist/age-model/data.js +57 -0
- package/dist/age-model/data.js.map +1 -0
- package/dist/age-model/details.cjs +261 -0
- package/dist/age-model/details.cjs.map +1 -0
- package/dist/age-model/details.d.ts +39 -0
- package/dist/age-model/details.js +258 -0
- package/dist/age-model/details.js.map +1 -0
- package/dist/age-model/details.module.sass.cjs +42 -0
- package/dist/age-model/details.module.sass.cjs.map +1 -0
- package/dist/age-model/details.module.sass.js +40 -0
- package/dist/age-model/details.module.sass.js.map +1 -0
- package/dist/age-model/index.d.ts +5 -0
- package/dist/age-model/legacy.cjs +28 -0
- package/dist/age-model/legacy.cjs.map +1 -0
- package/dist/age-model/legacy.d.ts +6 -0
- package/dist/age-model/legacy.js +26 -0
- package/dist/age-model/legacy.js.map +1 -0
- package/dist/age-model/surfaces.cjs +355 -0
- package/dist/age-model/surfaces.cjs.map +1 -0
- package/dist/age-model/surfaces.d.ts +68 -0
- package/dist/age-model/surfaces.js +352 -0
- package/dist/age-model/surfaces.js.map +1 -0
- package/dist/age-model/surfaces.module.sass.cjs +45 -0
- package/dist/age-model/surfaces.module.sass.cjs.map +1 -0
- package/dist/age-model/surfaces.module.sass.js +43 -0
- package/dist/age-model/surfaces.module.sass.js.map +1 -0
- package/dist/age-model/types.cjs +229 -0
- package/dist/age-model/types.cjs.map +1 -0
- package/dist/age-model/types.d.ts +112 -0
- package/dist/age-model/types.js +229 -0
- package/dist/age-model/types.js.map +1 -0
- package/dist/column-views.css +389 -57
- package/dist/column.cjs +20 -13
- package/dist/column.cjs.map +1 -1
- package/dist/column.d.ts +21 -6
- package/dist/column.js +21 -14
- package/dist/column.js.map +1 -1
- package/dist/column.module.sass.cjs +19 -15
- package/dist/column.module.sass.cjs.map +1 -1
- package/dist/column.module.sass.js +19 -15
- package/dist/column.module.sass.js.map +1 -1
- package/dist/data-provider/store.cjs +34 -1
- package/dist/data-provider/store.cjs.map +1 -1
- package/dist/data-provider/store.d.ts +5 -0
- package/dist/data-provider/store.js +35 -2
- package/dist/data-provider/store.js.map +1 -1
- package/dist/index.cjs +54 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +54 -3
- package/dist/index.js.map +1 -1
- package/dist/notes.cjs +11 -2
- package/dist/notes.cjs.map +1 -1
- package/dist/notes.d.ts +11 -1
- package/dist/notes.js +11 -2
- package/dist/notes.js.map +1 -1
- package/dist/prepare-units/composite-scale.cjs +18 -16
- package/dist/prepare-units/composite-scale.cjs.map +1 -1
- package/dist/prepare-units/composite-scale.js +18 -16
- package/dist/prepare-units/composite-scale.js.map +1 -1
- package/dist/prepare-units/density.cjs +83 -0
- package/dist/prepare-units/density.cjs.map +1 -0
- package/dist/prepare-units/density.d.ts +92 -0
- package/dist/prepare-units/density.js +83 -0
- package/dist/prepare-units/density.js.map +1 -0
- package/dist/prepare-units/index.cjs +15 -7
- package/dist/prepare-units/index.cjs.map +1 -1
- package/dist/prepare-units/index.d.ts +1 -0
- package/dist/prepare-units/index.js +15 -7
- package/dist/prepare-units/index.js.map +1 -1
- package/dist/prepare-units/types.cjs.map +1 -1
- package/dist/prepare-units/types.d.ts +34 -13
- package/dist/prepare-units/types.js.map +1 -1
- package/dist/section.cjs +108 -24
- package/dist/section.cjs.map +1 -1
- package/dist/section.d.ts +66 -6
- package/dist/section.js +109 -25
- package/dist/section.js.map +1 -1
- package/dist/timescale-zoom.cjs +191 -0
- package/dist/timescale-zoom.cjs.map +1 -0
- package/dist/timescale-zoom.d.ts +74 -0
- package/dist/timescale-zoom.js +191 -0
- package/dist/timescale-zoom.js.map +1 -0
- package/dist/unit-details/age-range.cjs +1 -0
- package/dist/unit-details/age-range.cjs.map +1 -1
- package/dist/unit-details/age-range.d.ts +5 -1
- package/dist/unit-details/age-range.js +1 -0
- package/dist/unit-details/age-range.js.map +1 -1
- package/dist/units/composite.cjs +4 -1
- package/dist/units/composite.cjs.map +1 -1
- package/dist/units/composite.d.ts +2 -0
- package/dist/units/composite.js +4 -1
- package/dist/units/composite.js.map +1 -1
- package/package.json +7 -7
- package/src/age-model/data.ts +98 -0
- package/src/age-model/details.module.sass +108 -0
- package/src/age-model/details.ts +333 -0
- package/src/age-model/index.ts +5 -0
- package/src/age-model/legacy.ts +30 -0
- package/src/age-model/surfaces.module.sass +168 -0
- package/src/age-model/surfaces.ts +568 -0
- package/src/age-model/types.ts +392 -0
- package/src/column.module.sass +59 -8
- package/src/column.ts +49 -23
- package/src/data-provider/store.ts +50 -1
- package/src/index.ts +5 -1
- package/src/notes.ts +20 -2
- package/src/prepare-units/composite-scale.ts +34 -31
- package/src/prepare-units/density.ts +197 -0
- package/src/prepare-units/index.ts +25 -6
- package/src/prepare-units/types.ts +34 -13
- package/src/section.ts +219 -33
- package/src/timescale-zoom.ts +341 -0
- package/src/unit-details/age-range.ts +3 -3
- package/src/units/composite.ts +11 -0
- package/dist/age-model-overlay.cjs +0 -50
- package/dist/age-model-overlay.cjs.map +0 -1
- package/dist/age-model-overlay.d.ts +0 -24
- package/dist/age-model-overlay.js +0 -48
- package/dist/age-model-overlay.js.map +0 -1
- package/dist/age-model-overlay.module.sass.cjs +0 -12
- package/dist/age-model-overlay.module.sass.cjs.map +0 -1
- package/dist/age-model-overlay.module.sass.js +0 -11
- package/dist/age-model-overlay.module.sass.js.map +0 -1
- package/src/age-model-overlay.module.sass +0 -11
- package/src/age-model-overlay.ts +0 -96
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"age-range.cjs","sources":["../../src/unit-details/age-range.ts"],"sourcesContent":["import {\n DataField,\n IntervalShort,\n IntervalTag,\n type IntervalTagProps,\n ItemList,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport h from \"./age-range.module.sass\";\nimport { formatProportion, formatRange } from \"./utils\";\nimport classNames from \"classnames\";\nimport { useMemo } from \"react\";\n\nexport function AgeField({ unit, children, ...rest }) {\n const [_b_age, _t_age, _unit] = getAgeRange(unit);\n\n return h(\n DataField,\n {\n label: \"Age\",\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n ...rest,\n },\n children,\n );\n}\n\nexport function AgeRange({\n data,\n className,\n}: {\n data: {\n t_age: number;\n b_age: number;\n };\n className?: string;\n}) {\n const [_b_age, _t_age, _unit] = getAgeRange(data);\n\n return h(Value, {\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n className,\n });\n}\n\nexport function AgeLabel({\n age,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n className,\n}: {\n age: number;\n className?: string;\n maximumFractionDigits?: number;\n minimumFractionDigits?: number;\n}) {\n /** Component to display a single age value with unit conversion from\n * Ma to ka or Ga as appropriate.\n */\n const [value, unit] = getAge(age);\n\n const _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit, className });\n}\n\nexport function Duration({\n value,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n}) {\n let unit = \"Myr\";\n if (value < 0.8) {\n unit = \"kyr\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Gyr\";\n value /= 1000;\n }\n\n let _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit });\n}\n\ninterface UnitIntervalConstraints {\n b_int_id?: number;\n t_int_id?: number;\n b_prop?: number;\n t_prop?: number;\n b_int_name?: string;\n t_int_name?: string;\n b_age?: number;\n t_age?: number;\n}\n\nexport interface IntervalProportionsProps extends Omit<\n IntervalTagProps,\n \"interval\"\n> {\n unit: UnitIntervalConstraints;\n showProportions?: boolean;\n calculateProportionsFromAges?: boolean;\n onClickItem?: any;\n}\n\nexport function IntervalProportions({\n unit,\n className,\n showProportions,\n calculateProportionsFromAges = true,\n ...rest\n}: IntervalProportionsProps) {\n /** Display the proportions of the unit that belong to the base and top intervals, if they are different */\n if (unit.b_int_id == null && unit.t_int_id == null) return null;\n\n let _showProps = showProportions;\n\n const i0 = unit.b_int_id;\n const i1 = unit.t_int_id;\n\n const ints = new Set([i0, i1]);\n\n /** Get interval information */\n const intervalMap = useMacrostratDefs(\"intervals\", Array.from(ints), null);\n const [int0, int1] = useMemo(() => {\n const int0 = intervalMap?.get(i0) ?? {};\n if (i0 === i1) {\n return [int0, int0];\n }\n const int1 = intervalMap?.get(i1) ?? {};\n return [int0, int1];\n }, [intervalMap, i0, i1]);\n\n const interval0: IntervalShort = {\n id: i0,\n name: unit.b_int_name,\n ...int0,\n };\n\n let b_prop = unit.b_prop;\n let t_prop = unit.t_prop;\n\n // If we have b_age and t_age, then we can calculate proportions if they are not given\n if (b_prop == null && unit.b_age != null && calculateProportionsFromAges) {\n b_prop = getProportion(unit.b_age, int0);\n }\n if (t_prop == null && unit.t_age != null && calculateProportionsFromAges) {\n t_prop = getProportion(unit.t_age, int1);\n }\n\n // If there are no proportions given and we are not explicitly directed to show them,\n // then we set them to hidden.\n if (b_prop == null && t_prop == null) {\n _showProps ??= false;\n }\n\n /*\n Set default proportions to 0 and 1 if they are not given,\n so that we can display \"base\" and \"top\" labels\n */\n b_prop ??= 0;\n t_prop ??= 1;\n\n let p0: any = null;\n let p1: any = null;\n\n if (_showProps !== false) {\n p1 = h(Proportion, { value: t_prop });\n\n if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {\n // We have a single interval with undefined proportions\n p0 = h(Proportion, { value: b_prop });\n }\n\n if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {\n p0 = h(\"span.joint-proportion\", [p0, \" \", h(\"span.sep\", \"to\"), \" \", p1]);\n }\n }\n\n return h(\n ItemList,\n { className: classNames(\"interval-proportions\", className) },\n [\n h(IntervalTag, {\n interval: interval0,\n prefix: p0,\n ...rest,\n }),\n h.if(i0 != i1)(\"span.discourage-break\", [\n h(\"span.sep\", \" to \"),\n h(IntervalTag, {\n interval: {\n id: i1,\n name: unit.t_int_name,\n ...int1,\n },\n prefix: p1,\n ...rest,\n }),\n ]),\n ],\n );\n}\n\nfunction getProportion(age: number, interval: IntervalShort): number | null {\n /** Get proportion with the age */\n return (interval.b_age - age) / (interval.b_age - interval.t_age);\n}\n\nfunction Proportion({ value }) {\n let content = null;\n if (value == 0) {\n content = \"base\";\n } else if (value == 1) {\n content = \"top\";\n } else {\n content = formatProportion(value * 100) + \"%\";\n }\n\n return h(\"span.proportion\", content);\n}\n\nexport function getAgeRange(_unit) {\n let b_age = _unit.b_age;\n let t_age = _unit.t_age;\n let unit = \"Ma\";\n\n if (b_age < 0.8 && t_age < 1.2) {\n b_age *= 1000;\n t_age *= 1000;\n unit = \"ka\";\n } else if (b_age > 800 && t_age > 1200) {\n b_age /= 1000;\n t_age /= 1000;\n unit = \"Ga\";\n }\n\n return [b_age, t_age, unit];\n}\n\nexport function getAge(value) {\n /** Get the age value in Ma, ka, or Ga as appropriate */\n let unit = \"Ma\";\n if (value < 0.8) {\n unit = \"ka\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Ga\";\n value /= 1000;\n }\n\n return [value, unit];\n}\n"],"names":["h","DataField","formatRange","Value","useMacrostratDefs","useMemo","int0","int1","ItemList","classNames","IntervalTag","formatProportion"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"age-range.cjs","sources":["../../src/unit-details/age-range.ts"],"sourcesContent":["import {\n DataField,\n IntervalShort,\n IntervalTag,\n type IntervalTagProps,\n ItemList,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport h from \"./age-range.module.sass\";\nimport { formatProportion, formatRange } from \"./utils\";\nimport classNames from \"classnames\";\nimport { ReactNode, useMemo } from \"react\";\n\nexport function AgeField({ unit, children, ...rest }) {\n const [_b_age, _t_age, _unit] = getAgeRange(unit);\n\n return h(\n DataField,\n {\n label: \"Age\",\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n ...rest,\n },\n children,\n );\n}\n\nexport function AgeRange({\n data,\n className,\n}: {\n data: {\n t_age: number;\n b_age: number;\n };\n className?: string;\n}) {\n const [_b_age, _t_age, _unit] = getAgeRange(data);\n\n return h(Value, {\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n className,\n });\n}\n\nexport function AgeLabel({\n age,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n className,\n}: {\n age: number;\n className?: string;\n maximumFractionDigits?: number;\n minimumFractionDigits?: number;\n}) {\n /** Component to display a single age value with unit conversion from\n * Ma to ka or Ga as appropriate.\n */\n const [value, unit] = getAge(age);\n\n const _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit, className });\n}\n\nexport function Duration({\n value,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n}) {\n let unit = \"Myr\";\n if (value < 0.8) {\n unit = \"kyr\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Gyr\";\n value /= 1000;\n }\n\n let _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit });\n}\n\ninterface UnitIntervalConstraints {\n b_int_id?: number;\n t_int_id?: number;\n b_prop?: number;\n t_prop?: number;\n b_int_name?: string;\n t_int_name?: string;\n b_age?: number;\n t_age?: number;\n}\n\nexport interface IntervalProportionsProps extends Omit<\n IntervalTagProps,\n \"interval\"\n> {\n unit: UnitIntervalConstraints;\n showProportions?: boolean;\n calculateProportionsFromAges?: boolean;\n onClickItem?: any;\n}\n\nexport function IntervalProportions({\n unit,\n className,\n showProportions,\n calculateProportionsFromAges = true,\n ...rest\n}: IntervalProportionsProps) {\n /** Display the proportions of the unit that belong to the base and top intervals, if they are different */\n if (unit.b_int_id == null && unit.t_int_id == null) return null;\n\n let _showProps = showProportions;\n\n const i0 = unit.b_int_id;\n const i1 = unit.t_int_id;\n\n const ints = new Set([i0, i1]);\n\n /** Get interval information */\n const intervalMap = useMacrostratDefs(\"intervals\", Array.from(ints), null);\n const [int0, int1] = useMemo(() => {\n const int0 = intervalMap?.get(i0) ?? {};\n if (i0 === i1) {\n return [int0, int0];\n }\n const int1 = intervalMap?.get(i1) ?? {};\n return [int0, int1];\n }, [intervalMap, i0, i1]);\n\n const interval0: IntervalShort = {\n id: i0,\n name: unit.b_int_name,\n ...int0,\n };\n\n let b_prop = unit.b_prop;\n let t_prop = unit.t_prop;\n\n // If we have b_age and t_age, then we can calculate proportions if they are not given\n if (b_prop == null && unit.b_age != null && calculateProportionsFromAges) {\n b_prop = getProportion(unit.b_age, int0);\n }\n if (t_prop == null && unit.t_age != null && calculateProportionsFromAges) {\n t_prop = getProportion(unit.t_age, int1);\n }\n\n // If there are no proportions given and we are not explicitly directed to show them,\n // then we set them to hidden.\n if (b_prop == null && t_prop == null) {\n _showProps ??= false;\n }\n\n /*\n Set default proportions to 0 and 1 if they are not given,\n so that we can display \"base\" and \"top\" labels\n */\n b_prop ??= 0;\n t_prop ??= 1;\n\n let p0: any = null;\n let p1: any = null;\n\n if (_showProps !== false) {\n p1 = h(Proportion, { value: t_prop });\n\n if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {\n // We have a single interval with undefined proportions\n p0 = h(Proportion, { value: b_prop });\n }\n\n if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {\n p0 = h(\"span.joint-proportion\", [p0, \" \", h(\"span.sep\", \"to\"), \" \", p1]);\n }\n }\n\n return h(\n ItemList,\n { className: classNames(\"interval-proportions\", className) },\n [\n h(IntervalTag, {\n interval: interval0,\n prefix: p0,\n ...rest,\n }),\n h.if(i0 != i1)(\"span.discourage-break\", [\n h(\"span.sep\", \" to \"),\n h(IntervalTag, {\n interval: {\n id: i1,\n name: unit.t_int_name,\n ...int1,\n },\n prefix: p1,\n ...rest,\n }),\n ]),\n ],\n );\n}\n\nfunction getProportion(age: number, interval: IntervalShort): number | null {\n /** Get proportion with the age */\n return (interval.b_age - age) / (interval.b_age - interval.t_age);\n}\n\nexport function Proportion({ value }: { value: number }) {\n let content: ReactNode | null = null;\n if (value == 0) {\n content = \"base\";\n } else if (value == 1) {\n content = \"top\";\n } else {\n content = formatProportion(value * 100) + \"%\";\n }\n\n return h(\"span.proportion\", content);\n}\n\nexport function getAgeRange(_unit) {\n let b_age = _unit.b_age;\n let t_age = _unit.t_age;\n let unit = \"Ma\";\n\n if (b_age < 0.8 && t_age < 1.2) {\n b_age *= 1000;\n t_age *= 1000;\n unit = \"ka\";\n } else if (b_age > 800 && t_age > 1200) {\n b_age /= 1000;\n t_age /= 1000;\n unit = \"Ga\";\n }\n\n return [b_age, t_age, unit];\n}\n\nexport function getAge(value) {\n /** Get the age value in Ma, ka, or Ga as appropriate */\n let unit = \"Ma\";\n if (value < 0.8) {\n unit = \"ka\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Ga\";\n value /= 1000;\n }\n\n return [value, unit];\n}\n"],"names":["h","DataField","formatRange","Value","useMacrostratDefs","useMemo","int0","int1","ItemList","classNames","IntervalTag","formatProportion"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IntervalTagProps } from '@macrostrat/data-components';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
export declare function AgeField({ unit, children, ...rest }: {
|
|
3
4
|
[x: string]: any;
|
|
4
5
|
unit: any;
|
|
@@ -63,9 +64,12 @@ export interface IntervalProportionsProps extends Omit<IntervalTagProps, "interv
|
|
|
63
64
|
onClickItem?: any;
|
|
64
65
|
}
|
|
65
66
|
export declare function IntervalProportions({ unit, className, showProportions, calculateProportionsFromAges, ...rest }: IntervalProportionsProps): import('react').FunctionComponentElement<{
|
|
66
|
-
children?:
|
|
67
|
+
children?: ReactNode;
|
|
67
68
|
className: string;
|
|
68
69
|
}> | null;
|
|
70
|
+
export declare function Proportion({ value }: {
|
|
71
|
+
value: number;
|
|
72
|
+
}): import('react').DOMElement<import('react').DOMAttributes<Element>, Element>;
|
|
69
73
|
export declare function getAgeRange(_unit: any): any[];
|
|
70
74
|
export declare function getAge(value: any): any[];
|
|
71
75
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"age-range.js","sources":["../../src/unit-details/age-range.ts"],"sourcesContent":["import {\n DataField,\n IntervalShort,\n IntervalTag,\n type IntervalTagProps,\n ItemList,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport h from \"./age-range.module.sass\";\nimport { formatProportion, formatRange } from \"./utils\";\nimport classNames from \"classnames\";\nimport { useMemo } from \"react\";\n\nexport function AgeField({ unit, children, ...rest }) {\n const [_b_age, _t_age, _unit] = getAgeRange(unit);\n\n return h(\n DataField,\n {\n label: \"Age\",\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n ...rest,\n },\n children,\n );\n}\n\nexport function AgeRange({\n data,\n className,\n}: {\n data: {\n t_age: number;\n b_age: number;\n };\n className?: string;\n}) {\n const [_b_age, _t_age, _unit] = getAgeRange(data);\n\n return h(Value, {\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n className,\n });\n}\n\nexport function AgeLabel({\n age,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n className,\n}: {\n age: number;\n className?: string;\n maximumFractionDigits?: number;\n minimumFractionDigits?: number;\n}) {\n /** Component to display a single age value with unit conversion from\n * Ma to ka or Ga as appropriate.\n */\n const [value, unit] = getAge(age);\n\n const _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit, className });\n}\n\nexport function Duration({\n value,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n}) {\n let unit = \"Myr\";\n if (value < 0.8) {\n unit = \"kyr\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Gyr\";\n value /= 1000;\n }\n\n let _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit });\n}\n\ninterface UnitIntervalConstraints {\n b_int_id?: number;\n t_int_id?: number;\n b_prop?: number;\n t_prop?: number;\n b_int_name?: string;\n t_int_name?: string;\n b_age?: number;\n t_age?: number;\n}\n\nexport interface IntervalProportionsProps extends Omit<\n IntervalTagProps,\n \"interval\"\n> {\n unit: UnitIntervalConstraints;\n showProportions?: boolean;\n calculateProportionsFromAges?: boolean;\n onClickItem?: any;\n}\n\nexport function IntervalProportions({\n unit,\n className,\n showProportions,\n calculateProportionsFromAges = true,\n ...rest\n}: IntervalProportionsProps) {\n /** Display the proportions of the unit that belong to the base and top intervals, if they are different */\n if (unit.b_int_id == null && unit.t_int_id == null) return null;\n\n let _showProps = showProportions;\n\n const i0 = unit.b_int_id;\n const i1 = unit.t_int_id;\n\n const ints = new Set([i0, i1]);\n\n /** Get interval information */\n const intervalMap = useMacrostratDefs(\"intervals\", Array.from(ints), null);\n const [int0, int1] = useMemo(() => {\n const int0 = intervalMap?.get(i0) ?? {};\n if (i0 === i1) {\n return [int0, int0];\n }\n const int1 = intervalMap?.get(i1) ?? {};\n return [int0, int1];\n }, [intervalMap, i0, i1]);\n\n const interval0: IntervalShort = {\n id: i0,\n name: unit.b_int_name,\n ...int0,\n };\n\n let b_prop = unit.b_prop;\n let t_prop = unit.t_prop;\n\n // If we have b_age and t_age, then we can calculate proportions if they are not given\n if (b_prop == null && unit.b_age != null && calculateProportionsFromAges) {\n b_prop = getProportion(unit.b_age, int0);\n }\n if (t_prop == null && unit.t_age != null && calculateProportionsFromAges) {\n t_prop = getProportion(unit.t_age, int1);\n }\n\n // If there are no proportions given and we are not explicitly directed to show them,\n // then we set them to hidden.\n if (b_prop == null && t_prop == null) {\n _showProps ??= false;\n }\n\n /*\n Set default proportions to 0 and 1 if they are not given,\n so that we can display \"base\" and \"top\" labels\n */\n b_prop ??= 0;\n t_prop ??= 1;\n\n let p0: any = null;\n let p1: any = null;\n\n if (_showProps !== false) {\n p1 = h(Proportion, { value: t_prop });\n\n if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {\n // We have a single interval with undefined proportions\n p0 = h(Proportion, { value: b_prop });\n }\n\n if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {\n p0 = h(\"span.joint-proportion\", [p0, \" \", h(\"span.sep\", \"to\"), \" \", p1]);\n }\n }\n\n return h(\n ItemList,\n { className: classNames(\"interval-proportions\", className) },\n [\n h(IntervalTag, {\n interval: interval0,\n prefix: p0,\n ...rest,\n }),\n h.if(i0 != i1)(\"span.discourage-break\", [\n h(\"span.sep\", \" to \"),\n h(IntervalTag, {\n interval: {\n id: i1,\n name: unit.t_int_name,\n ...int1,\n },\n prefix: p1,\n ...rest,\n }),\n ]),\n ],\n );\n}\n\nfunction getProportion(age: number, interval: IntervalShort): number | null {\n /** Get proportion with the age */\n return (interval.b_age - age) / (interval.b_age - interval.t_age);\n}\n\
|
|
1
|
+
{"version":3,"file":"age-range.js","sources":["../../src/unit-details/age-range.ts"],"sourcesContent":["import {\n DataField,\n IntervalShort,\n IntervalTag,\n type IntervalTagProps,\n ItemList,\n Value,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport h from \"./age-range.module.sass\";\nimport { formatProportion, formatRange } from \"./utils\";\nimport classNames from \"classnames\";\nimport { ReactNode, useMemo } from \"react\";\n\nexport function AgeField({ unit, children, ...rest }) {\n const [_b_age, _t_age, _unit] = getAgeRange(unit);\n\n return h(\n DataField,\n {\n label: \"Age\",\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n ...rest,\n },\n children,\n );\n}\n\nexport function AgeRange({\n data,\n className,\n}: {\n data: {\n t_age: number;\n b_age: number;\n };\n className?: string;\n}) {\n const [_b_age, _t_age, _unit] = getAgeRange(data);\n\n return h(Value, {\n value: formatRange(_b_age, _t_age),\n unit: _unit,\n className,\n });\n}\n\nexport function AgeLabel({\n age,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n className,\n}: {\n age: number;\n className?: string;\n maximumFractionDigits?: number;\n minimumFractionDigits?: number;\n}) {\n /** Component to display a single age value with unit conversion from\n * Ma to ka or Ga as appropriate.\n */\n const [value, unit] = getAge(age);\n\n const _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit, className });\n}\n\nexport function Duration({\n value,\n maximumFractionDigits = 2,\n minimumFractionDigits = 0,\n}) {\n let unit = \"Myr\";\n if (value < 0.8) {\n unit = \"kyr\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Gyr\";\n value /= 1000;\n }\n\n let _value = value.toLocaleString(\"en-US\", {\n maximumFractionDigits,\n minimumFractionDigits,\n });\n\n return h(Value, { value: _value, unit });\n}\n\ninterface UnitIntervalConstraints {\n b_int_id?: number;\n t_int_id?: number;\n b_prop?: number;\n t_prop?: number;\n b_int_name?: string;\n t_int_name?: string;\n b_age?: number;\n t_age?: number;\n}\n\nexport interface IntervalProportionsProps extends Omit<\n IntervalTagProps,\n \"interval\"\n> {\n unit: UnitIntervalConstraints;\n showProportions?: boolean;\n calculateProportionsFromAges?: boolean;\n onClickItem?: any;\n}\n\nexport function IntervalProportions({\n unit,\n className,\n showProportions,\n calculateProportionsFromAges = true,\n ...rest\n}: IntervalProportionsProps) {\n /** Display the proportions of the unit that belong to the base and top intervals, if they are different */\n if (unit.b_int_id == null && unit.t_int_id == null) return null;\n\n let _showProps = showProportions;\n\n const i0 = unit.b_int_id;\n const i1 = unit.t_int_id;\n\n const ints = new Set([i0, i1]);\n\n /** Get interval information */\n const intervalMap = useMacrostratDefs(\"intervals\", Array.from(ints), null);\n const [int0, int1] = useMemo(() => {\n const int0 = intervalMap?.get(i0) ?? {};\n if (i0 === i1) {\n return [int0, int0];\n }\n const int1 = intervalMap?.get(i1) ?? {};\n return [int0, int1];\n }, [intervalMap, i0, i1]);\n\n const interval0: IntervalShort = {\n id: i0,\n name: unit.b_int_name,\n ...int0,\n };\n\n let b_prop = unit.b_prop;\n let t_prop = unit.t_prop;\n\n // If we have b_age and t_age, then we can calculate proportions if they are not given\n if (b_prop == null && unit.b_age != null && calculateProportionsFromAges) {\n b_prop = getProportion(unit.b_age, int0);\n }\n if (t_prop == null && unit.t_age != null && calculateProportionsFromAges) {\n t_prop = getProportion(unit.t_age, int1);\n }\n\n // If there are no proportions given and we are not explicitly directed to show them,\n // then we set them to hidden.\n if (b_prop == null && t_prop == null) {\n _showProps ??= false;\n }\n\n /*\n Set default proportions to 0 and 1 if they are not given,\n so that we can display \"base\" and \"top\" labels\n */\n b_prop ??= 0;\n t_prop ??= 1;\n\n let p0: any = null;\n let p1: any = null;\n\n if (_showProps !== false) {\n p1 = h(Proportion, { value: t_prop });\n\n if (i0 !== i1 || b_prop !== 0 || t_prop !== 1) {\n // We have a single interval with undefined proportions\n p0 = h(Proportion, { value: b_prop });\n }\n\n if (i0 === i1 && (b_prop !== 0 || t_prop !== 1)) {\n p0 = h(\"span.joint-proportion\", [p0, \" \", h(\"span.sep\", \"to\"), \" \", p1]);\n }\n }\n\n return h(\n ItemList,\n { className: classNames(\"interval-proportions\", className) },\n [\n h(IntervalTag, {\n interval: interval0,\n prefix: p0,\n ...rest,\n }),\n h.if(i0 != i1)(\"span.discourage-break\", [\n h(\"span.sep\", \" to \"),\n h(IntervalTag, {\n interval: {\n id: i1,\n name: unit.t_int_name,\n ...int1,\n },\n prefix: p1,\n ...rest,\n }),\n ]),\n ],\n );\n}\n\nfunction getProportion(age: number, interval: IntervalShort): number | null {\n /** Get proportion with the age */\n return (interval.b_age - age) / (interval.b_age - interval.t_age);\n}\n\nexport function Proportion({ value }: { value: number }) {\n let content: ReactNode | null = null;\n if (value == 0) {\n content = \"base\";\n } else if (value == 1) {\n content = \"top\";\n } else {\n content = formatProportion(value * 100) + \"%\";\n }\n\n return h(\"span.proportion\", content);\n}\n\nexport function getAgeRange(_unit) {\n let b_age = _unit.b_age;\n let t_age = _unit.t_age;\n let unit = \"Ma\";\n\n if (b_age < 0.8 && t_age < 1.2) {\n b_age *= 1000;\n t_age *= 1000;\n unit = \"ka\";\n } else if (b_age > 800 && t_age > 1200) {\n b_age /= 1000;\n t_age /= 1000;\n unit = \"Ga\";\n }\n\n return [b_age, t_age, unit];\n}\n\nexport function getAge(value) {\n /** Get the age value in Ma, ka, or Ga as appropriate */\n let unit = \"Ma\";\n if (value < 0.8) {\n unit = \"ka\";\n value *= 1000;\n if (value < 5) {\n unit = \"yr\";\n value *= 1000;\n }\n } else if (value > 1000) {\n unit = \"Ga\";\n value /= 1000;\n }\n\n return [value, unit];\n}\n"],"names":["int0","int1"],"mappings":"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"}
|
package/dist/units/composite.cjs
CHANGED
|
@@ -83,13 +83,15 @@ function AnnotatedUnitsColumn(props) {
|
|
|
83
83
|
}, []);
|
|
84
84
|
return null;
|
|
85
85
|
}
|
|
86
|
+
const DEFAULT_LABEL_SUPPRESS_HEIGHT = 2;
|
|
86
87
|
function SectionLabelsColumn(props) {
|
|
87
88
|
const {
|
|
88
89
|
width = 300,
|
|
89
90
|
noteMode = "unlabeled",
|
|
90
91
|
labelOffset = 30,
|
|
91
92
|
noteComponent,
|
|
92
|
-
shouldRenderNote
|
|
93
|
+
shouldRenderNote,
|
|
94
|
+
labelSuppressHeight = DEFAULT_LABEL_SUPPRESS_HEIGHT
|
|
93
95
|
} = props;
|
|
94
96
|
const { totalHeight, axisType } = store.useMacrostratColumnData();
|
|
95
97
|
const _compositeScale = store.useCompositeScale();
|
|
@@ -117,6 +119,7 @@ function SectionLabelsColumn(props) {
|
|
|
117
119
|
divisions: unitsToLabel,
|
|
118
120
|
paddingLeft: labelOffset,
|
|
119
121
|
width,
|
|
122
|
+
minimumHeight: labelSuppressHeight,
|
|
120
123
|
noteComponent,
|
|
121
124
|
shouldRenderNote,
|
|
122
125
|
scale: _compositeScale,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composite.cjs","sources":["../../src/units/composite.ts"],"sourcesContent":["import { hyperStyled } from \"@macrostrat/hyper\";\nimport {\n ColumnContext,\n LithologyColumn,\n SVG,\n} from \"@macrostrat/column-components\";\nimport { defaultNameFunction, UnitNamesColumn } from \"./names\";\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { BaseUnit } from \"@macrostrat/api-types\";\nimport { LabeledUnit, UnitBoxes } from \"./boxes\";\nimport styles from \"./composite.module.sass\";\nimport {\n useCompositeScale,\n useMacrostratColumnData,\n useUnitSelectionDispatch,\n} from \"../data-provider\";\n\nconst h = hyperStyled(styles);\n\ninterface LabelTracker {\n [key: number]: boolean;\n}\n\nconst LabelTrackerContext = createContext(null);\nconst UnlabeledDivisionsContext = createContext(null);\n\nconst findMacrostratUnitID = (u) => u.unit_id;\n\nexport function LabelTrackerProvider(props) {\n /** Tracker for units to handle state for whether their labels fit inline or not.\n * Designed to work for single or composite columns.\n */\n const { children, units, findUnitID = findMacrostratUnitID } = props;\n const [unlabeledDivisions, setUnlabeledDivisions] = useState<\n BaseUnit[] | null\n >(null);\n const labelTrackerRef = useRef<LabelTracker>({});\n\n const recompute = useCallback(() => {\n // Recompute over the *current* unit set (which changes as the column zooms).\n // The tracker ref accumulates entries for units seen at any zoom level, so\n // we gate on whether every currently-visible unit has reported — not on the\n // total number of tracked units, which would go stale and freeze the notes.\n const tracker = labelTrackerRef.current;\n const allReported = units.every((d) => findUnitID(d) in tracker);\n if (!allReported) return;\n setUnlabeledDivisions(units.filter((d) => tracker[findUnitID(d)] === false));\n }, [units, findUnitID]);\n\n const trackLabelVisibility = useCallback(\n (div, visible) => {\n labelTrackerRef.current[findUnitID(div)] = visible;\n recompute();\n },\n [recompute, findUnitID],\n );\n\n // Re-sync when the visible unit set changes (e.g. on zoom), so a unit whose\n // label now fits inline stops also rendering as a note, and vice versa.\n useEffect(() => {\n recompute();\n }, [recompute]);\n\n const value = trackLabelVisibility;\n return h(\n LabelTrackerContext.Provider,\n { value },\n h(\n UnlabeledDivisionsContext.Provider,\n { value: unlabeledDivisions },\n children,\n ),\n );\n}\n\nfunction TrackedLabeledUnit({\n division,\n nameForDivision = defaultNameFunction,\n ...rest\n}) {\n const trackLabelVisibility = useContext(LabelTrackerContext);\n return h(LabeledUnit, {\n division,\n label: nameForDivision(division),\n onLabelUpdated(label, visible) {\n // If there is al LabelTrackerContext, update the label visibility\n trackLabelVisibility?.(division, visible);\n },\n ...rest,\n });\n}\n\nexport const CompositeUnitComponent = TrackedLabeledUnit;\n\ntype BaseUnitProps = {\n width: number;\n showLabels?: boolean;\n columnWidth?: number;\n clipToFrame?: boolean;\n};\n\ntype ICompositeUnitProps = BaseUnitProps & {\n gutterWidth?: number;\n labelOffset?: number;\n paddingLeft?: number;\n nameForDivision?: (division: BaseUnit) => string;\n children?: React.ReactNode;\n unitComponent?: React.FC<any>;\n unitComponentProps?: any;\n noteMode?: \"labeled\" | \"unlabeled\";\n showLabelColumn?: boolean;\n noteComponent?: React.FC<any>;\n shouldRenderNote?: (d: any) => boolean;\n};\n\ninterface CompositeUnitProps {\n unitComponent: React.FC<any>;\n unitComponentProps?: any;\n width: number;\n showLabels?: boolean;\n clipToFrame?: boolean;\n}\n\nexport function CompositeUnitsColumn(props: CompositeUnitProps) {\n /*\n A column with units and names either\n overlapping or offset to the right\n */\n const {\n width,\n unitComponent = TrackedLabeledUnit,\n unitComponentProps,\n clipToFrame,\n ...rest\n } = props;\n\n return h(LithologyColumn, { width, clipToFrame }, [\n h(UnitBoxes, {\n unitComponent,\n unitComponentProps,\n ...rest,\n }),\n ]);\n}\n\nexport function AnnotatedUnitsColumn(props: ICompositeUnitProps) {\n useEffect(() => {\n console.warn(\n \"AnnotatedUnitsColumn is deprecated and currently renders a no-op for transition purposes\",\n );\n }, []);\n return null;\n}\n\nexport function SectionLabelsColumn(props: ICompositeUnitProps) {\n // Section with \"squishy\" time scale\n const {\n width = 300,\n noteMode = \"unlabeled\",\n labelOffset = 30,\n noteComponent,\n shouldRenderNote,\n } = props;\n\n const { totalHeight, axisType } = useMacrostratColumnData();\n const _compositeScale = useCompositeScale();\n\n const unlabeledUnits = useContext(UnlabeledDivisionsContext);\n const unitsToLabel = noteMode == \"unlabeled\" ? unlabeledUnits : undefined;\n\n const selectUnit = useUnitSelectionDispatch();\n\n return h(\"div.section-labels-column\", [\n h(\n ColumnNotesProvider,\n {\n units: [],\n scale: _compositeScale,\n totalHeight,\n axisType,\n },\n h(\n SVG,\n {\n height: totalHeight,\n innerWidth: width - 4,\n paddingH: 1,\n paddingLeft: 3,\n },\n h(UnitNamesColumn, {\n divisions: unitsToLabel,\n paddingLeft: labelOffset,\n width,\n noteComponent,\n shouldRenderNote,\n scale: _compositeScale,\n onClickNote(note) {\n selectUnit(note.data, null, null);\n },\n }),\n ),\n ),\n ]);\n}\n\nexport function ColumnNotesProvider(props) {\n // A fake column axis provider that allows scales to cross\n const { children, scale, totalHeight, pixelScale } = props;\n\n const { axisType } = useMacrostratColumnData();\n\n return h(\n ColumnContext.Provider,\n {\n value: {\n divisions: [],\n scale,\n scaleClamped: scale,\n pixelHeight: totalHeight,\n pixelsPerMeter: pixelScale,\n axisType,\n zoom: 1,\n },\n },\n children,\n );\n}\n\nexport { TrackedLabeledUnit, ICompositeUnitProps };\n"],"names":["hyperStyled","styles","createContext","useState","useRef","useCallback","useEffect","defaultNameFunction","useContext","LabeledUnit","LithologyColumn","UnitBoxes","useMacrostratColumnData","useCompositeScale","useUnitSelectionDispatch","SVG","UnitNamesColumn","ColumnContext"],"mappings":";;;;;;;;;;AAwBA,MAAM,IAAIA,IAAAA,YAAYC,gBAAM;AAM5B,MAAM,sBAAsBC,MAAAA,cAAc,IAAI;AAC9C,MAAM,4BAA4BA,MAAAA,cAAc,IAAI;AAEpD,MAAM,uBAAuB,CAAC,MAAM,EAAE;AAE/B,SAAS,qBAAqB,OAAO;AAI1C,QAAM,EAAE,UAAU,OAAO,aAAa,yBAAyB;AAC/D,QAAM,CAAC,oBAAoB,qBAAqB,IAAIC,MAAAA,SAElD,IAAI;AACN,QAAM,kBAAkBC,MAAAA,OAAqB,EAAE;AAE/C,QAAM,YAAYC,MAAAA,YAAY,MAAM;AAKlC,UAAM,UAAU,gBAAgB;AAChC,UAAM,cAAc,MAAM,MAAM,CAAC,MAAM,WAAW,CAAC,KAAK,OAAO;AAC/D,QAAI,CAAC,YAAa;AAClB,0BAAsB,MAAM,OAAO,CAAC,MAAM,QAAQ,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC;AAAA,EAC7E,GAAG,CAAC,OAAO,UAAU,CAAC;AAEtB,QAAM,uBAAuBA,MAAAA;AAAAA,IAC3B,CAAC,KAAK,YAAY;AAChB,sBAAgB,QAAQ,WAAW,GAAG,CAAC,IAAI;AAC3C,gBAAA;AAAA,IACF;AAAA,IACA,CAAC,WAAW,UAAU;AAAA,EAAA;AAKxBC,QAAAA,UAAU,MAAM;AACd,cAAA;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,QAAQ;AACd,SAAO;AAAA,IACL,oBAAoB;AAAA,IACpB,EAAE,MAAA;AAAA,IACF;AAAA,MACE,0BAA0B;AAAA,MAC1B,EAAE,OAAO,mBAAA;AAAA,MACT;AAAA,IAAA;AAAA,EACF;AAEJ;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA,kBAAkBC,MAAAA;AAAAA,EAClB,GAAG;AACL,GAAG;AACD,QAAM,uBAAuBC,MAAAA,WAAW,mBAAmB;AAC3D,SAAO,EAAEC,MAAAA,aAAa;AAAA,IACpB;AAAA,IACA,OAAO,gBAAgB,QAAQ;AAAA,IAC/B,eAAe,OAAO,SAAS;AAE7B,6BAAuB,UAAU,OAAO;AAAA,IAC1C;AAAA,IACA,GAAG;AAAA,EAAA,CACJ;AACH;AAEO,MAAM,yBAAyB;
|
|
1
|
+
{"version":3,"file":"composite.cjs","sources":["../../src/units/composite.ts"],"sourcesContent":["import { hyperStyled } from \"@macrostrat/hyper\";\nimport {\n ColumnContext,\n LithologyColumn,\n SVG,\n} from \"@macrostrat/column-components\";\nimport { defaultNameFunction, UnitNamesColumn } from \"./names\";\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { BaseUnit } from \"@macrostrat/api-types\";\nimport { LabeledUnit, UnitBoxes } from \"./boxes\";\nimport styles from \"./composite.module.sass\";\nimport {\n useCompositeScale,\n useMacrostratColumnData,\n useUnitSelectionDispatch,\n} from \"../data-provider\";\n\nconst h = hyperStyled(styles);\n\ninterface LabelTracker {\n [key: number]: boolean;\n}\n\nconst LabelTrackerContext = createContext(null);\nconst UnlabeledDivisionsContext = createContext(null);\n\nconst findMacrostratUnitID = (u) => u.unit_id;\n\nexport function LabelTrackerProvider(props) {\n /** Tracker for units to handle state for whether their labels fit inline or not.\n * Designed to work for single or composite columns.\n */\n const { children, units, findUnitID = findMacrostratUnitID } = props;\n const [unlabeledDivisions, setUnlabeledDivisions] = useState<\n BaseUnit[] | null\n >(null);\n const labelTrackerRef = useRef<LabelTracker>({});\n\n const recompute = useCallback(() => {\n // Recompute over the *current* unit set (which changes as the column zooms).\n // The tracker ref accumulates entries for units seen at any zoom level, so\n // we gate on whether every currently-visible unit has reported — not on the\n // total number of tracked units, which would go stale and freeze the notes.\n const tracker = labelTrackerRef.current;\n const allReported = units.every((d) => findUnitID(d) in tracker);\n if (!allReported) return;\n setUnlabeledDivisions(units.filter((d) => tracker[findUnitID(d)] === false));\n }, [units, findUnitID]);\n\n const trackLabelVisibility = useCallback(\n (div, visible) => {\n labelTrackerRef.current[findUnitID(div)] = visible;\n recompute();\n },\n [recompute, findUnitID],\n );\n\n // Re-sync when the visible unit set changes (e.g. on zoom), so a unit whose\n // label now fits inline stops also rendering as a note, and vice versa.\n useEffect(() => {\n recompute();\n }, [recompute]);\n\n const value = trackLabelVisibility;\n return h(\n LabelTrackerContext.Provider,\n { value },\n h(\n UnlabeledDivisionsContext.Provider,\n { value: unlabeledDivisions },\n children,\n ),\n );\n}\n\nfunction TrackedLabeledUnit({\n division,\n nameForDivision = defaultNameFunction,\n ...rest\n}) {\n const trackLabelVisibility = useContext(LabelTrackerContext);\n return h(LabeledUnit, {\n division,\n label: nameForDivision(division),\n onLabelUpdated(label, visible) {\n // If there is al LabelTrackerContext, update the label visibility\n trackLabelVisibility?.(division, visible);\n },\n ...rest,\n });\n}\n\nexport const CompositeUnitComponent = TrackedLabeledUnit;\n\ntype BaseUnitProps = {\n width: number;\n showLabels?: boolean;\n columnWidth?: number;\n clipToFrame?: boolean;\n};\n\ntype ICompositeUnitProps = BaseUnitProps & {\n gutterWidth?: number;\n labelOffset?: number;\n paddingLeft?: number;\n nameForDivision?: (division: BaseUnit) => string;\n children?: React.ReactNode;\n unitComponent?: React.FC<any>;\n unitComponentProps?: any;\n noteMode?: \"labeled\" | \"unlabeled\";\n showLabelColumn?: boolean;\n noteComponent?: React.FC<any>;\n shouldRenderNote?: (d: any) => boolean;\n /** Suppress the label for a unit drawn thinner than this many pixels */\n labelSuppressHeight?: number;\n};\n\ninterface CompositeUnitProps {\n unitComponent: React.FC<any>;\n unitComponentProps?: any;\n width: number;\n showLabels?: boolean;\n clipToFrame?: boolean;\n}\n\nexport function CompositeUnitsColumn(props: CompositeUnitProps) {\n /*\n A column with units and names either\n overlapping or offset to the right\n */\n const {\n width,\n unitComponent = TrackedLabeledUnit,\n unitComponentProps,\n clipToFrame,\n ...rest\n } = props;\n\n return h(LithologyColumn, { width, clipToFrame }, [\n h(UnitBoxes, {\n unitComponent,\n unitComponentProps,\n ...rest,\n }),\n ]);\n}\n\nexport function AnnotatedUnitsColumn(props: ICompositeUnitProps) {\n useEffect(() => {\n console.warn(\n \"AnnotatedUnitsColumn is deprecated and currently renders a no-op for transition purposes\",\n );\n }, []);\n return null;\n}\n\n/** A unit drawn thinner than this gets no label. The notes column can place\n * a label away from its unit and run a leader line back, so a thin unit is\n * labelable in principle — but below a pixel or two there is nothing on the\n * page to lead back to, and a dense column spends its labels on units the\n * reader cannot see. */\nconst DEFAULT_LABEL_SUPPRESS_HEIGHT = 2;\n\nexport function SectionLabelsColumn(props: ICompositeUnitProps) {\n // Section with \"squishy\" time scale\n const {\n width = 300,\n noteMode = \"unlabeled\",\n labelOffset = 30,\n noteComponent,\n shouldRenderNote,\n labelSuppressHeight = DEFAULT_LABEL_SUPPRESS_HEIGHT,\n } = props;\n\n const { totalHeight, axisType } = useMacrostratColumnData();\n const _compositeScale = useCompositeScale();\n\n const unlabeledUnits = useContext(UnlabeledDivisionsContext);\n const unitsToLabel = noteMode == \"unlabeled\" ? unlabeledUnits : undefined;\n\n const selectUnit = useUnitSelectionDispatch();\n\n return h(\"div.section-labels-column\", [\n h(\n ColumnNotesProvider,\n {\n units: [],\n scale: _compositeScale,\n totalHeight,\n axisType,\n },\n h(\n SVG,\n {\n height: totalHeight,\n innerWidth: width - 4,\n paddingH: 1,\n paddingLeft: 3,\n },\n h(UnitNamesColumn, {\n divisions: unitsToLabel,\n paddingLeft: labelOffset,\n width,\n minimumHeight: labelSuppressHeight,\n noteComponent,\n shouldRenderNote,\n scale: _compositeScale,\n onClickNote(note) {\n selectUnit(note.data, null, null);\n },\n }),\n ),\n ),\n ]);\n}\n\nexport function ColumnNotesProvider(props) {\n // A fake column axis provider that allows scales to cross\n const { children, scale, totalHeight, pixelScale } = props;\n\n const { axisType } = useMacrostratColumnData();\n\n return h(\n ColumnContext.Provider,\n {\n value: {\n divisions: [],\n scale,\n scaleClamped: scale,\n pixelHeight: totalHeight,\n pixelsPerMeter: pixelScale,\n axisType,\n zoom: 1,\n },\n },\n children,\n );\n}\n\nexport { TrackedLabeledUnit, ICompositeUnitProps };\n"],"names":["hyperStyled","styles","createContext","useState","useRef","useCallback","useEffect","defaultNameFunction","useContext","LabeledUnit","LithologyColumn","UnitBoxes","useMacrostratColumnData","useCompositeScale","useUnitSelectionDispatch","SVG","UnitNamesColumn","ColumnContext"],"mappings":"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"}
|
|
@@ -24,6 +24,8 @@ type ICompositeUnitProps = BaseUnitProps & {
|
|
|
24
24
|
showLabelColumn?: boolean;
|
|
25
25
|
noteComponent?: React.FC<any>;
|
|
26
26
|
shouldRenderNote?: (d: any) => boolean;
|
|
27
|
+
/** Suppress the label for a unit drawn thinner than this many pixels */
|
|
28
|
+
labelSuppressHeight?: number;
|
|
27
29
|
};
|
|
28
30
|
interface CompositeUnitProps {
|
|
29
31
|
unitComponent: React.FC<any>;
|
package/dist/units/composite.js
CHANGED
|
@@ -81,13 +81,15 @@ function AnnotatedUnitsColumn(props) {
|
|
|
81
81
|
}, []);
|
|
82
82
|
return null;
|
|
83
83
|
}
|
|
84
|
+
const DEFAULT_LABEL_SUPPRESS_HEIGHT = 2;
|
|
84
85
|
function SectionLabelsColumn(props) {
|
|
85
86
|
const {
|
|
86
87
|
width = 300,
|
|
87
88
|
noteMode = "unlabeled",
|
|
88
89
|
labelOffset = 30,
|
|
89
90
|
noteComponent,
|
|
90
|
-
shouldRenderNote
|
|
91
|
+
shouldRenderNote,
|
|
92
|
+
labelSuppressHeight = DEFAULT_LABEL_SUPPRESS_HEIGHT
|
|
91
93
|
} = props;
|
|
92
94
|
const { totalHeight, axisType } = useMacrostratColumnData();
|
|
93
95
|
const _compositeScale = useCompositeScale();
|
|
@@ -115,6 +117,7 @@ function SectionLabelsColumn(props) {
|
|
|
115
117
|
divisions: unitsToLabel,
|
|
116
118
|
paddingLeft: labelOffset,
|
|
117
119
|
width,
|
|
120
|
+
minimumHeight: labelSuppressHeight,
|
|
118
121
|
noteComponent,
|
|
119
122
|
shouldRenderNote,
|
|
120
123
|
scale: _compositeScale,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composite.js","sources":["../../src/units/composite.ts"],"sourcesContent":["import { hyperStyled } from \"@macrostrat/hyper\";\nimport {\n ColumnContext,\n LithologyColumn,\n SVG,\n} from \"@macrostrat/column-components\";\nimport { defaultNameFunction, UnitNamesColumn } from \"./names\";\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { BaseUnit } from \"@macrostrat/api-types\";\nimport { LabeledUnit, UnitBoxes } from \"./boxes\";\nimport styles from \"./composite.module.sass\";\nimport {\n useCompositeScale,\n useMacrostratColumnData,\n useUnitSelectionDispatch,\n} from \"../data-provider\";\n\nconst h = hyperStyled(styles);\n\ninterface LabelTracker {\n [key: number]: boolean;\n}\n\nconst LabelTrackerContext = createContext(null);\nconst UnlabeledDivisionsContext = createContext(null);\n\nconst findMacrostratUnitID = (u) => u.unit_id;\n\nexport function LabelTrackerProvider(props) {\n /** Tracker for units to handle state for whether their labels fit inline or not.\n * Designed to work for single or composite columns.\n */\n const { children, units, findUnitID = findMacrostratUnitID } = props;\n const [unlabeledDivisions, setUnlabeledDivisions] = useState<\n BaseUnit[] | null\n >(null);\n const labelTrackerRef = useRef<LabelTracker>({});\n\n const recompute = useCallback(() => {\n // Recompute over the *current* unit set (which changes as the column zooms).\n // The tracker ref accumulates entries for units seen at any zoom level, so\n // we gate on whether every currently-visible unit has reported — not on the\n // total number of tracked units, which would go stale and freeze the notes.\n const tracker = labelTrackerRef.current;\n const allReported = units.every((d) => findUnitID(d) in tracker);\n if (!allReported) return;\n setUnlabeledDivisions(units.filter((d) => tracker[findUnitID(d)] === false));\n }, [units, findUnitID]);\n\n const trackLabelVisibility = useCallback(\n (div, visible) => {\n labelTrackerRef.current[findUnitID(div)] = visible;\n recompute();\n },\n [recompute, findUnitID],\n );\n\n // Re-sync when the visible unit set changes (e.g. on zoom), so a unit whose\n // label now fits inline stops also rendering as a note, and vice versa.\n useEffect(() => {\n recompute();\n }, [recompute]);\n\n const value = trackLabelVisibility;\n return h(\n LabelTrackerContext.Provider,\n { value },\n h(\n UnlabeledDivisionsContext.Provider,\n { value: unlabeledDivisions },\n children,\n ),\n );\n}\n\nfunction TrackedLabeledUnit({\n division,\n nameForDivision = defaultNameFunction,\n ...rest\n}) {\n const trackLabelVisibility = useContext(LabelTrackerContext);\n return h(LabeledUnit, {\n division,\n label: nameForDivision(division),\n onLabelUpdated(label, visible) {\n // If there is al LabelTrackerContext, update the label visibility\n trackLabelVisibility?.(division, visible);\n },\n ...rest,\n });\n}\n\nexport const CompositeUnitComponent = TrackedLabeledUnit;\n\ntype BaseUnitProps = {\n width: number;\n showLabels?: boolean;\n columnWidth?: number;\n clipToFrame?: boolean;\n};\n\ntype ICompositeUnitProps = BaseUnitProps & {\n gutterWidth?: number;\n labelOffset?: number;\n paddingLeft?: number;\n nameForDivision?: (division: BaseUnit) => string;\n children?: React.ReactNode;\n unitComponent?: React.FC<any>;\n unitComponentProps?: any;\n noteMode?: \"labeled\" | \"unlabeled\";\n showLabelColumn?: boolean;\n noteComponent?: React.FC<any>;\n shouldRenderNote?: (d: any) => boolean;\n};\n\ninterface CompositeUnitProps {\n unitComponent: React.FC<any>;\n unitComponentProps?: any;\n width: number;\n showLabels?: boolean;\n clipToFrame?: boolean;\n}\n\nexport function CompositeUnitsColumn(props: CompositeUnitProps) {\n /*\n A column with units and names either\n overlapping or offset to the right\n */\n const {\n width,\n unitComponent = TrackedLabeledUnit,\n unitComponentProps,\n clipToFrame,\n ...rest\n } = props;\n\n return h(LithologyColumn, { width, clipToFrame }, [\n h(UnitBoxes, {\n unitComponent,\n unitComponentProps,\n ...rest,\n }),\n ]);\n}\n\nexport function AnnotatedUnitsColumn(props: ICompositeUnitProps) {\n useEffect(() => {\n console.warn(\n \"AnnotatedUnitsColumn is deprecated and currently renders a no-op for transition purposes\",\n );\n }, []);\n return null;\n}\n\nexport function SectionLabelsColumn(props: ICompositeUnitProps) {\n // Section with \"squishy\" time scale\n const {\n width = 300,\n noteMode = \"unlabeled\",\n labelOffset = 30,\n noteComponent,\n shouldRenderNote,\n } = props;\n\n const { totalHeight, axisType } = useMacrostratColumnData();\n const _compositeScale = useCompositeScale();\n\n const unlabeledUnits = useContext(UnlabeledDivisionsContext);\n const unitsToLabel = noteMode == \"unlabeled\" ? unlabeledUnits : undefined;\n\n const selectUnit = useUnitSelectionDispatch();\n\n return h(\"div.section-labels-column\", [\n h(\n ColumnNotesProvider,\n {\n units: [],\n scale: _compositeScale,\n totalHeight,\n axisType,\n },\n h(\n SVG,\n {\n height: totalHeight,\n innerWidth: width - 4,\n paddingH: 1,\n paddingLeft: 3,\n },\n h(UnitNamesColumn, {\n divisions: unitsToLabel,\n paddingLeft: labelOffset,\n width,\n noteComponent,\n shouldRenderNote,\n scale: _compositeScale,\n onClickNote(note) {\n selectUnit(note.data, null, null);\n },\n }),\n ),\n ),\n ]);\n}\n\nexport function ColumnNotesProvider(props) {\n // A fake column axis provider that allows scales to cross\n const { children, scale, totalHeight, pixelScale } = props;\n\n const { axisType } = useMacrostratColumnData();\n\n return h(\n ColumnContext.Provider,\n {\n value: {\n divisions: [],\n scale,\n scaleClamped: scale,\n pixelHeight: totalHeight,\n pixelsPerMeter: pixelScale,\n axisType,\n zoom: 1,\n },\n },\n children,\n );\n}\n\nexport { TrackedLabeledUnit, ICompositeUnitProps };\n"],"names":["styles"],"mappings":";;;;;;;;AAwBA,MAAM,IAAI,YAAYA,GAAM;AAM5B,MAAM,sBAAsB,cAAc,IAAI;AAC9C,MAAM,4BAA4B,cAAc,IAAI;AAEpD,MAAM,uBAAuB,CAAC,MAAM,EAAE;AAE/B,SAAS,qBAAqB,OAAO;AAI1C,QAAM,EAAE,UAAU,OAAO,aAAa,yBAAyB;AAC/D,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAElD,IAAI;AACN,QAAM,kBAAkB,OAAqB,EAAE;AAE/C,QAAM,YAAY,YAAY,MAAM;AAKlC,UAAM,UAAU,gBAAgB;AAChC,UAAM,cAAc,MAAM,MAAM,CAAC,MAAM,WAAW,CAAC,KAAK,OAAO;AAC/D,QAAI,CAAC,YAAa;AAClB,0BAAsB,MAAM,OAAO,CAAC,MAAM,QAAQ,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC;AAAA,EAC7E,GAAG,CAAC,OAAO,UAAU,CAAC;AAEtB,QAAM,uBAAuB;AAAA,IAC3B,CAAC,KAAK,YAAY;AAChB,sBAAgB,QAAQ,WAAW,GAAG,CAAC,IAAI;AAC3C,gBAAA;AAAA,IACF;AAAA,IACA,CAAC,WAAW,UAAU;AAAA,EAAA;AAKxB,YAAU,MAAM;AACd,cAAA;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,QAAQ;AACd,SAAO;AAAA,IACL,oBAAoB;AAAA,IACpB,EAAE,MAAA;AAAA,IACF;AAAA,MACE,0BAA0B;AAAA,MAC1B,EAAE,OAAO,mBAAA;AAAA,MACT;AAAA,IAAA;AAAA,EACF;AAEJ;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA,kBAAkB;AAAA,EAClB,GAAG;AACL,GAAG;AACD,QAAM,uBAAuB,WAAW,mBAAmB;AAC3D,SAAO,EAAE,aAAa;AAAA,IACpB;AAAA,IACA,OAAO,gBAAgB,QAAQ;AAAA,IAC/B,eAAe,OAAO,SAAS;AAE7B,6BAAuB,UAAU,OAAO;AAAA,IAC1C;AAAA,IACA,GAAG;AAAA,EAAA,CACJ;AACH;AAEO,MAAM,yBAAyB;
|
|
1
|
+
{"version":3,"file":"composite.js","sources":["../../src/units/composite.ts"],"sourcesContent":["import { hyperStyled } from \"@macrostrat/hyper\";\nimport {\n ColumnContext,\n LithologyColumn,\n SVG,\n} from \"@macrostrat/column-components\";\nimport { defaultNameFunction, UnitNamesColumn } from \"./names\";\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { BaseUnit } from \"@macrostrat/api-types\";\nimport { LabeledUnit, UnitBoxes } from \"./boxes\";\nimport styles from \"./composite.module.sass\";\nimport {\n useCompositeScale,\n useMacrostratColumnData,\n useUnitSelectionDispatch,\n} from \"../data-provider\";\n\nconst h = hyperStyled(styles);\n\ninterface LabelTracker {\n [key: number]: boolean;\n}\n\nconst LabelTrackerContext = createContext(null);\nconst UnlabeledDivisionsContext = createContext(null);\n\nconst findMacrostratUnitID = (u) => u.unit_id;\n\nexport function LabelTrackerProvider(props) {\n /** Tracker for units to handle state for whether their labels fit inline or not.\n * Designed to work for single or composite columns.\n */\n const { children, units, findUnitID = findMacrostratUnitID } = props;\n const [unlabeledDivisions, setUnlabeledDivisions] = useState<\n BaseUnit[] | null\n >(null);\n const labelTrackerRef = useRef<LabelTracker>({});\n\n const recompute = useCallback(() => {\n // Recompute over the *current* unit set (which changes as the column zooms).\n // The tracker ref accumulates entries for units seen at any zoom level, so\n // we gate on whether every currently-visible unit has reported — not on the\n // total number of tracked units, which would go stale and freeze the notes.\n const tracker = labelTrackerRef.current;\n const allReported = units.every((d) => findUnitID(d) in tracker);\n if (!allReported) return;\n setUnlabeledDivisions(units.filter((d) => tracker[findUnitID(d)] === false));\n }, [units, findUnitID]);\n\n const trackLabelVisibility = useCallback(\n (div, visible) => {\n labelTrackerRef.current[findUnitID(div)] = visible;\n recompute();\n },\n [recompute, findUnitID],\n );\n\n // Re-sync when the visible unit set changes (e.g. on zoom), so a unit whose\n // label now fits inline stops also rendering as a note, and vice versa.\n useEffect(() => {\n recompute();\n }, [recompute]);\n\n const value = trackLabelVisibility;\n return h(\n LabelTrackerContext.Provider,\n { value },\n h(\n UnlabeledDivisionsContext.Provider,\n { value: unlabeledDivisions },\n children,\n ),\n );\n}\n\nfunction TrackedLabeledUnit({\n division,\n nameForDivision = defaultNameFunction,\n ...rest\n}) {\n const trackLabelVisibility = useContext(LabelTrackerContext);\n return h(LabeledUnit, {\n division,\n label: nameForDivision(division),\n onLabelUpdated(label, visible) {\n // If there is al LabelTrackerContext, update the label visibility\n trackLabelVisibility?.(division, visible);\n },\n ...rest,\n });\n}\n\nexport const CompositeUnitComponent = TrackedLabeledUnit;\n\ntype BaseUnitProps = {\n width: number;\n showLabels?: boolean;\n columnWidth?: number;\n clipToFrame?: boolean;\n};\n\ntype ICompositeUnitProps = BaseUnitProps & {\n gutterWidth?: number;\n labelOffset?: number;\n paddingLeft?: number;\n nameForDivision?: (division: BaseUnit) => string;\n children?: React.ReactNode;\n unitComponent?: React.FC<any>;\n unitComponentProps?: any;\n noteMode?: \"labeled\" | \"unlabeled\";\n showLabelColumn?: boolean;\n noteComponent?: React.FC<any>;\n shouldRenderNote?: (d: any) => boolean;\n /** Suppress the label for a unit drawn thinner than this many pixels */\n labelSuppressHeight?: number;\n};\n\ninterface CompositeUnitProps {\n unitComponent: React.FC<any>;\n unitComponentProps?: any;\n width: number;\n showLabels?: boolean;\n clipToFrame?: boolean;\n}\n\nexport function CompositeUnitsColumn(props: CompositeUnitProps) {\n /*\n A column with units and names either\n overlapping or offset to the right\n */\n const {\n width,\n unitComponent = TrackedLabeledUnit,\n unitComponentProps,\n clipToFrame,\n ...rest\n } = props;\n\n return h(LithologyColumn, { width, clipToFrame }, [\n h(UnitBoxes, {\n unitComponent,\n unitComponentProps,\n ...rest,\n }),\n ]);\n}\n\nexport function AnnotatedUnitsColumn(props: ICompositeUnitProps) {\n useEffect(() => {\n console.warn(\n \"AnnotatedUnitsColumn is deprecated and currently renders a no-op for transition purposes\",\n );\n }, []);\n return null;\n}\n\n/** A unit drawn thinner than this gets no label. The notes column can place\n * a label away from its unit and run a leader line back, so a thin unit is\n * labelable in principle — but below a pixel or two there is nothing on the\n * page to lead back to, and a dense column spends its labels on units the\n * reader cannot see. */\nconst DEFAULT_LABEL_SUPPRESS_HEIGHT = 2;\n\nexport function SectionLabelsColumn(props: ICompositeUnitProps) {\n // Section with \"squishy\" time scale\n const {\n width = 300,\n noteMode = \"unlabeled\",\n labelOffset = 30,\n noteComponent,\n shouldRenderNote,\n labelSuppressHeight = DEFAULT_LABEL_SUPPRESS_HEIGHT,\n } = props;\n\n const { totalHeight, axisType } = useMacrostratColumnData();\n const _compositeScale = useCompositeScale();\n\n const unlabeledUnits = useContext(UnlabeledDivisionsContext);\n const unitsToLabel = noteMode == \"unlabeled\" ? unlabeledUnits : undefined;\n\n const selectUnit = useUnitSelectionDispatch();\n\n return h(\"div.section-labels-column\", [\n h(\n ColumnNotesProvider,\n {\n units: [],\n scale: _compositeScale,\n totalHeight,\n axisType,\n },\n h(\n SVG,\n {\n height: totalHeight,\n innerWidth: width - 4,\n paddingH: 1,\n paddingLeft: 3,\n },\n h(UnitNamesColumn, {\n divisions: unitsToLabel,\n paddingLeft: labelOffset,\n width,\n minimumHeight: labelSuppressHeight,\n noteComponent,\n shouldRenderNote,\n scale: _compositeScale,\n onClickNote(note) {\n selectUnit(note.data, null, null);\n },\n }),\n ),\n ),\n ]);\n}\n\nexport function ColumnNotesProvider(props) {\n // A fake column axis provider that allows scales to cross\n const { children, scale, totalHeight, pixelScale } = props;\n\n const { axisType } = useMacrostratColumnData();\n\n return h(\n ColumnContext.Provider,\n {\n value: {\n divisions: [],\n scale,\n scaleClamped: scale,\n pixelHeight: totalHeight,\n pixelsPerMeter: pixelScale,\n axisType,\n zoom: 1,\n },\n },\n children,\n );\n}\n\nexport { TrackedLabeledUnit, ICompositeUnitProps };\n"],"names":["styles"],"mappings":";;;;;;;;AAwBA,MAAM,IAAI,YAAYA,GAAM;AAM5B,MAAM,sBAAsB,cAAc,IAAI;AAC9C,MAAM,4BAA4B,cAAc,IAAI;AAEpD,MAAM,uBAAuB,CAAC,MAAM,EAAE;AAE/B,SAAS,qBAAqB,OAAO;AAI1C,QAAM,EAAE,UAAU,OAAO,aAAa,yBAAyB;AAC/D,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAElD,IAAI;AACN,QAAM,kBAAkB,OAAqB,EAAE;AAE/C,QAAM,YAAY,YAAY,MAAM;AAKlC,UAAM,UAAU,gBAAgB;AAChC,UAAM,cAAc,MAAM,MAAM,CAAC,MAAM,WAAW,CAAC,KAAK,OAAO;AAC/D,QAAI,CAAC,YAAa;AAClB,0BAAsB,MAAM,OAAO,CAAC,MAAM,QAAQ,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC;AAAA,EAC7E,GAAG,CAAC,OAAO,UAAU,CAAC;AAEtB,QAAM,uBAAuB;AAAA,IAC3B,CAAC,KAAK,YAAY;AAChB,sBAAgB,QAAQ,WAAW,GAAG,CAAC,IAAI;AAC3C,gBAAA;AAAA,IACF;AAAA,IACA,CAAC,WAAW,UAAU;AAAA,EAAA;AAKxB,YAAU,MAAM;AACd,cAAA;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,QAAQ;AACd,SAAO;AAAA,IACL,oBAAoB;AAAA,IACpB,EAAE,MAAA;AAAA,IACF;AAAA,MACE,0BAA0B;AAAA,MAC1B,EAAE,OAAO,mBAAA;AAAA,MACT;AAAA,IAAA;AAAA,EACF;AAEJ;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA,kBAAkB;AAAA,EAClB,GAAG;AACL,GAAG;AACD,QAAM,uBAAuB,WAAW,mBAAmB;AAC3D,SAAO,EAAE,aAAa;AAAA,IACpB;AAAA,IACA,OAAO,gBAAgB,QAAQ;AAAA,IAC/B,eAAe,OAAO,SAAS;AAE7B,6BAAuB,UAAU,OAAO;AAAA,IAC1C;AAAA,IACA,GAAG;AAAA,EAAA,CACJ;AACH;AAEO,MAAM,yBAAyB;AAiC/B,SAAS,qBAAqB,OAA2B;AAK9D,QAAM;AAAA,IACJ;AAAA,IACA,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,IACD;AAEJ,SAAO,EAAE,iBAAiB,EAAE,OAAO,eAAe;AAAA,IAChD,EAAE,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IAAA,CACJ;AAAA,EAAA,CACF;AACH;AAEO,SAAS,qBAAqB,OAA4B;AAC/D,YAAU,MAAM;AACd,YAAQ;AAAA,MACN;AAAA,IAAA;AAAA,EAEJ,GAAG,CAAA,CAAE;AACL,SAAO;AACT;AAOA,MAAM,gCAAgC;AAE/B,SAAS,oBAAoB,OAA4B;AAE9D,QAAM;AAAA,IACJ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA,sBAAsB;AAAA,EAAA,IACpB;AAEJ,QAAM,EAAE,aAAa,SAAA,IAAa,wBAAA;AAClC,QAAM,kBAAkB,kBAAA;AAExB,QAAM,iBAAiB,WAAW,yBAAyB;AAC3D,QAAM,eAAe,YAAY,cAAc,iBAAiB;AAEhE,QAAM,aAAa,yBAAA;AAEnB,SAAO,EAAE,6BAA6B;AAAA,IACpC;AAAA,MACE;AAAA,MACA;AAAA,QACE,OAAO,CAAA;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA;AAAA,MAAA;AAAA,MAEF;AAAA,QACE;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,YAAY,QAAQ;AAAA,UACpB,UAAU;AAAA,UACV,aAAa;AAAA,QAAA;AAAA,QAEf,EAAE,iBAAiB;AAAA,UACjB,WAAW;AAAA,UACX,aAAa;AAAA,UACb;AAAA,UACA,eAAe;AAAA,UACf;AAAA,UACA;AAAA,UACA,OAAO;AAAA,UACP,YAAY,MAAM;AAChB,uBAAW,KAAK,MAAM,MAAM,IAAI;AAAA,UAClC;AAAA,QAAA,CACD;AAAA,MAAA;AAAA,IACH;AAAA,EACF,CACD;AACH;AAEO,SAAS,oBAAoB,OAAO;AAEzC,QAAM,EAAE,UAAU,OAAO,aAAa,eAAe;AAErD,QAAM,EAAE,SAAA,IAAa,wBAAA;AAErB,SAAO;AAAA,IACL,cAAc;AAAA,IACd;AAAA,MACE,OAAO;AAAA,QACL,WAAW,CAAA;AAAA,QACX;AAAA,QACA,cAAc;AAAA,QACd,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB;AAAA,QACA,MAAM;AAAA,MAAA;AAAA,IACR;AAAA,IAEF;AAAA,EAAA;AAEJ;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@macrostrat/column-views",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.12.0",
|
|
4
4
|
"description": "Data views for Macrostrat stratigraphic columns",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -46,16 +46,16 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@blueprintjs/core": "^6.14.0",
|
|
49
|
-
"@macrostrat/api-types": "^1.
|
|
49
|
+
"@macrostrat/api-types": "^1.4.0",
|
|
50
50
|
"@macrostrat/color-utils": "^1.2.2",
|
|
51
|
-
"@macrostrat/column-components": "^2.
|
|
51
|
+
"@macrostrat/column-components": "^2.2.0",
|
|
52
52
|
"@macrostrat/data-components": "^1.5.1",
|
|
53
|
-
"@macrostrat/data-provider": "^1.
|
|
53
|
+
"@macrostrat/data-provider": "^1.3.1",
|
|
54
54
|
"@macrostrat/hyper": "^3.1.1",
|
|
55
|
-
"@macrostrat/map-views": "^1.
|
|
55
|
+
"@macrostrat/map-views": "^1.1.1",
|
|
56
56
|
"@macrostrat/scoped-store": "^1.1.0",
|
|
57
|
-
"@macrostrat/stratigraphy-utils": "^1.4.
|
|
58
|
-
"@macrostrat/timescale": "^3.
|
|
57
|
+
"@macrostrat/stratigraphy-utils": "^1.4.2",
|
|
58
|
+
"@macrostrat/timescale": "^3.3.0",
|
|
59
59
|
"@macrostrat/ui-components": "^5.2.0",
|
|
60
60
|
"@types/chroma-js": "^3.1.1",
|
|
61
61
|
"@types/d3-format": "^3.0.4",
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Data hooks for a column's age model. */
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { useAPIResult } from "@macrostrat/ui-components";
|
|
4
|
+
import { useMacrostratBaseURL } from "@macrostrat/data-provider";
|
|
5
|
+
import type { UnitLong } from "@macrostrat/api-types";
|
|
6
|
+
import { useMacrostratColumnData, useMacrostratUnits } from "../data-provider";
|
|
7
|
+
import {
|
|
8
|
+
type AgeModelBoundary,
|
|
9
|
+
type ColumnSurface,
|
|
10
|
+
surfacesFromBoundaries,
|
|
11
|
+
surfacesFromUnits,
|
|
12
|
+
} from "./types";
|
|
13
|
+
|
|
14
|
+
export const AGE_MODEL_ROUTE = "/age_model";
|
|
15
|
+
|
|
16
|
+
/** The age-model boundaries of a column, from `/age_model?col_id=` on the
|
|
17
|
+
* API the enclosing `MacrostratDataProvider` points at (production when there
|
|
18
|
+
* is none). `null` while loading or when `col_id` is not set. */
|
|
19
|
+
export function useColumnAgeModel(
|
|
20
|
+
col_id: number | null | undefined,
|
|
21
|
+
): AgeModelBoundary[] | null {
|
|
22
|
+
const baseURL = useMacrostratBaseURL();
|
|
23
|
+
const params = useMemo(() => ({ col_id }), [col_id]);
|
|
24
|
+
let route: string | null = null;
|
|
25
|
+
if (col_id != null) {
|
|
26
|
+
route = baseURL + AGE_MODEL_ROUTE;
|
|
27
|
+
}
|
|
28
|
+
return useAPIResult(route, params, unwrapAgeModel) ?? null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function unwrapAgeModel(res: any): AgeModelBoundary[] {
|
|
32
|
+
return res?.success?.data ?? [];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Where a column's surfaces came from */
|
|
36
|
+
export type SurfacesSource = "provided" | "age-model" | "derived" | "loading";
|
|
37
|
+
|
|
38
|
+
export interface UseColumnSurfacesOptions {
|
|
39
|
+
/** Surfaces to show. When given, nothing is fetched. */
|
|
40
|
+
surfaces?: ColumnSurface[] | null;
|
|
41
|
+
/** The column whose age model to fetch. Defaults to the column being
|
|
42
|
+
* rendered (read from its units). */
|
|
43
|
+
col_id?: number | null;
|
|
44
|
+
/** When the age model has no boundaries, derive surfaces from the units
|
|
45
|
+
* instead (default `true`). */
|
|
46
|
+
fallbackToUnits?: boolean;
|
|
47
|
+
/** Promote `modeled` surfaces that must in fact constrain the age model to
|
|
48
|
+
* `relative` (default `true`) — see `inferTiePointStatuses`. */
|
|
49
|
+
inferTiePoints?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ColumnSurfacesData {
|
|
53
|
+
surfaces: ColumnSurface[];
|
|
54
|
+
source: SurfacesSource;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Resolve the surfaces to show for the enclosing `Column`: the ones passed
|
|
58
|
+
* in, else the column's age model, else (optionally) surfaces derived from
|
|
59
|
+
* its units. Must be used inside a `Column`. */
|
|
60
|
+
export function useColumnSurfaces(
|
|
61
|
+
options: UseColumnSurfacesOptions = {},
|
|
62
|
+
): ColumnSurfacesData {
|
|
63
|
+
const {
|
|
64
|
+
surfaces: provided,
|
|
65
|
+
col_id,
|
|
66
|
+
fallbackToUnits = true,
|
|
67
|
+
inferTiePoints = true,
|
|
68
|
+
} = options;
|
|
69
|
+
const units = useMacrostratUnits() as UnitLong[] | undefined;
|
|
70
|
+
const { axisType } = useMacrostratColumnData();
|
|
71
|
+
|
|
72
|
+
let fetchID: number | null = null;
|
|
73
|
+
if (provided == null) {
|
|
74
|
+
fetchID = col_id ?? units?.[0]?.col_id ?? null;
|
|
75
|
+
}
|
|
76
|
+
const boundaries = useColumnAgeModel(fetchID);
|
|
77
|
+
|
|
78
|
+
const fromAgeModel = useMemo(
|
|
79
|
+
() => surfacesFromBoundaries(boundaries, { inferTiePoints }),
|
|
80
|
+
[boundaries, inferTiePoints],
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const derived = useMemo(() => {
|
|
84
|
+
if (!fallbackToUnits) return [];
|
|
85
|
+
return surfacesFromUnits(units, { axisType });
|
|
86
|
+
}, [units, axisType, fallbackToUnits]);
|
|
87
|
+
|
|
88
|
+
if (provided != null) {
|
|
89
|
+
return { surfaces: provided, source: "provided" };
|
|
90
|
+
}
|
|
91
|
+
if (fetchID != null && boundaries == null) {
|
|
92
|
+
return { surfaces: [], source: "loading" };
|
|
93
|
+
}
|
|
94
|
+
if (fromAgeModel.length > 0) {
|
|
95
|
+
return { surfaces: fromAgeModel, source: "age-model" };
|
|
96
|
+
}
|
|
97
|
+
return { surfaces: derived, source: "derived" };
|
|
98
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
.surface-details-panel
|
|
2
|
+
display: flex
|
|
3
|
+
flex-direction: column
|
|
4
|
+
min-width: 0
|
|
5
|
+
|
|
6
|
+
.surface-details-header
|
|
7
|
+
display: flex
|
|
8
|
+
flex-direction: row
|
|
9
|
+
align-items: center
|
|
10
|
+
flex-wrap: wrap
|
|
11
|
+
gap: 0.5em
|
|
12
|
+
padding: 0.5em 0
|
|
13
|
+
border-bottom: 1px solid var(--pz-panel-rule-color, var(--panel-rule-color, #ddd))
|
|
14
|
+
.spacer
|
|
15
|
+
flex: 1
|
|
16
|
+
|
|
17
|
+
.surface-details-title
|
|
18
|
+
margin: 0
|
|
19
|
+
font-size: 1.1em
|
|
20
|
+
.surface-id
|
|
21
|
+
font-size: 0.85em
|
|
22
|
+
color: var(--text-subtle-color, var(--pz-text-subtle-color))
|
|
23
|
+
|
|
24
|
+
.surface-details-tags
|
|
25
|
+
display: flex
|
|
26
|
+
gap: 0.3em
|
|
27
|
+
|
|
28
|
+
.surface-details-content
|
|
29
|
+
padding: 0.5em 0
|
|
30
|
+
|
|
31
|
+
.no-surface .placeholder
|
|
32
|
+
color: var(--text-subtle-color, var(--pz-text-subtle-color))
|
|
33
|
+
margin: 0
|
|
34
|
+
|
|
35
|
+
.surface-tag
|
|
36
|
+
// A colored dot leading the status label
|
|
37
|
+
&:before
|
|
38
|
+
content: ''
|
|
39
|
+
display: inline-block
|
|
40
|
+
width: 0.6em
|
|
41
|
+
height: 0.6em
|
|
42
|
+
border-radius: 50%
|
|
43
|
+
margin-right: 0.4em
|
|
44
|
+
background-color: var(--surface-color, currentColor)
|
|
45
|
+
&.surface-type-tag:before
|
|
46
|
+
display: none
|
|
47
|
+
// An inferred status is marked, so the tag doesn't pass for a recorded one
|
|
48
|
+
&.inferred
|
|
49
|
+
font-style: italic
|
|
50
|
+
|
|
51
|
+
.inferred-marker
|
|
52
|
+
margin-left: 0.15em
|
|
53
|
+
opacity: 0.7
|
|
54
|
+
|
|
55
|
+
.calibration-interval
|
|
56
|
+
display: flex
|
|
57
|
+
align-items: baseline
|
|
58
|
+
gap: 0.5em
|
|
59
|
+
flex-wrap: wrap
|
|
60
|
+
|
|
61
|
+
.calibration-range
|
|
62
|
+
color: var(--text-subtle-color, var(--pz-text-subtle-color))
|
|
63
|
+
font-size: 0.9em
|
|
64
|
+
|
|
65
|
+
.calibration-proportion
|
|
66
|
+
margin-top: 0.2em
|
|
67
|
+
|
|
68
|
+
.surface-units-list
|
|
69
|
+
list-style: none
|
|
70
|
+
margin: 0
|
|
71
|
+
padding: 0
|
|
72
|
+
li
|
|
73
|
+
display: inline
|
|
74
|
+
&:after
|
|
75
|
+
content: ', '
|
|
76
|
+
&:last-child:after
|
|
77
|
+
content: ''
|
|
78
|
+
|
|
79
|
+
.no-units, .no-calibration
|
|
80
|
+
color: var(--text-subtle-color, var(--pz-text-subtle-color))
|
|
81
|
+
|
|
82
|
+
.surface-status-legend
|
|
83
|
+
list-style: none
|
|
84
|
+
margin: 0
|
|
85
|
+
padding: 0
|
|
86
|
+
display: flex
|
|
87
|
+
flex-direction: column
|
|
88
|
+
gap: 0.3em
|
|
89
|
+
font-size: 0.85em
|
|
90
|
+
&.with-descriptions
|
|
91
|
+
gap: 0.6em
|
|
92
|
+
|
|
93
|
+
.legend-item
|
|
94
|
+
display: flex
|
|
95
|
+
flex-direction: row
|
|
96
|
+
align-items: baseline
|
|
97
|
+
gap: 0.6em
|
|
98
|
+
.surface-label-marker
|
|
99
|
+
flex: none
|
|
100
|
+
width: 24px
|
|
101
|
+
align-self: center
|
|
102
|
+
|
|
103
|
+
.legend-label
|
|
104
|
+
font-weight: 500
|
|
105
|
+
|
|
106
|
+
.legend-description
|
|
107
|
+
color: var(--text-subtle-color, var(--pz-text-subtle-color))
|
|
108
|
+
font-size: 0.9em
|