@macrostrat/column-views 3.10.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 +188 -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 +398 -56
- 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/correlation-chart/main.cjs +11 -3
- package/dist/correlation-chart/main.cjs.map +1 -1
- package/dist/correlation-chart/main.d.ts +1 -1
- package/dist/correlation-chart/main.js +11 -3
- package/dist/correlation-chart/main.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 +57 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +57 -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/unit-details/age-window-tag.cjs +68 -0
- package/dist/unit-details/age-window-tag.cjs.map +1 -0
- package/dist/unit-details/age-window-tag.d.ts +26 -0
- package/dist/unit-details/age-window-tag.js +66 -0
- package/dist/unit-details/age-window-tag.js.map +1 -0
- package/dist/{age-model-overlay.module.sass.cjs → unit-details/age-window-tag.module.sass.cjs} +3 -3
- package/dist/unit-details/age-window-tag.module.sass.cjs.map +1 -0
- package/dist/unit-details/age-window-tag.module.sass.js +11 -0
- package/dist/unit-details/age-window-tag.module.sass.js.map +1 -0
- package/dist/unit-details/index.d.ts +1 -0
- 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/correlation-chart/main.ts +14 -2
- 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/unit-details/age-window-tag.module.sass +10 -0
- package/src/unit-details/age-window-tag.ts +102 -0
- package/src/unit-details/index.ts +1 -0
- 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.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":"index.js","sources":["../../src/prepare-units/index.ts"],"sourcesContent":["import {\n getSectionAgeRange,\n getSectionPosRange,\n groupUnitsIntoSectionsByOverlap,\n groupUnitsIntoSectionsBySectionID,\n mergeOverlappingSections,\n preprocessSectionUnit,\n preprocessUnits,\n UnitWithLayoutHints,\n} from \"./helpers\";\nimport { ColumnAxisType } from \"@macrostrat/column-components\";\nimport { useMemo } from \"react\";\nimport { UnitLong } from \"@macrostrat/api-types\";\nimport {\n collapseUnconformitiesByPixelHeight,\n computeSectionHeights,\n finalizeSectionHeights,\n padWindowByPixels,\n resolveWindowScales,\n trimSectionsToWindow,\n type CompositeColumnScale,\n} from \"./composite-scale\";\nimport {\n agesOverlap,\n MergeSectionsMode,\n PrepareColumnOptions,\n PreparedColumnData,\n unitsOverlap,\n} from \"./utils\";\nimport { SectionInfo } from \"./types\";\n\nexport * from \"./utils\";\nexport * from \"./types\";\nexport { preprocessUnits };\nexport type { CompositeColumnScale };\n\nexport function usePreparedColumnUnits(\n data: UnitLong[],\n options: PrepareColumnOptions,\n): PreparedColumnData {\n /** This function wraps and memoizes all preparation steps for converting\n * an array of units from the /units route to a form ready for usage.\n */\n return useMemo(() => {\n return prepareColumnUnits(data, options);\n }, [data, ...Object.values(options)]);\n}\n\nexport function prepareColumnUnits(\n units: UnitWithLayoutHints<UnitLong>[],\n options: PrepareColumnOptions,\n): PreparedColumnData {\n /** Prepare units for rendering into Macrostrat columns */\n\n let { t_age, b_age, t_pos, b_pos } = options;\n\n const {\n mergeSections = MergeSectionsMode.OVERLAPPING,\n axisType,\n unconformityHeight,\n collapseSmallUnconformities = false,\n hybridScale,\n scale,\n windowPadding = 0,\n } = options;\n\n let _totalHeight: number | null = null;\n\n if (scale != null) {\n // Set t_age and b_age based on scale domain if not already set\n const domain = scale.domain();\n if (axisType == ColumnAxisType.AGE) {\n if (t_age == null) t_age = Math.min(...domain);\n if (b_age == null) b_age = Math.max(...domain);\n _totalHeight = Math.abs(scale(b_age) - scale(t_age));\n } else {\n if (t_pos == null) t_pos = Math.min(...domain);\n if (b_pos == null) b_pos = Math.max(...domain);\n _totalHeight = Math.abs(scale(b_pos) - scale(t_pos));\n }\n }\n\n /** Age columns lay every section out at its full extent and clip to the\n * window at the end (see below), so that a section abutting the window is\n * sized by its own content rather than by the sliver that survives the clip.\n * Hybrid and externally-supplied scales build their own mapping and can't be\n * re-derived that way, so they keep the original clip-then-lay-out path. */\n const clipBeforeLayout =\n axisType != ColumnAxisType.AGE || hybridScale != null || scale != null;\n\n // Start by ensuring that ages and positions are numbers\n // also set up some values for eODP-style columns\n let units1 = units.map(preprocessSectionUnit);\n\n if (clipBeforeLayout) {\n /** Prototype filtering to age range */\n units1 = units1.filter((d) => {\n // Filter units by t_age and b_age, inclusive\n if (axisType == ColumnAxisType.AGE) {\n return agesOverlap(d, { t_age, b_age });\n } else {\n return unitsOverlap(d, { t_pos, b_pos } as any, axisType);\n }\n });\n }\n\n let mergeMode = mergeSections;\n // if (axisType != ColumnAxisType.AGE) {\n // // For non-age columns, we always merge sections.\n // // This is because the \"groupUnitsIntoSections\" function is not well-defined\n // // for non-age columns.\n // mergeMode = MergeSectionsMode.ALL;\n // }\n\n let sections0: SectionInfo<UnitLong>[];\n if (mergeMode == MergeSectionsMode.ALL) {\n // For the \"merge sections\" mode, we need to create a single section\n const [b_unit_pos, t_unit_pos] = getSectionPosRange(units1, axisType);\n const [b_unit_age, t_unit_age] = getSectionAgeRange(units1);\n sections0 = [\n {\n section_id: 0,\n /**\n * If ages limits are directly specified, use them to define the section bounds.\n * */\n t_pos: t_unit_pos,\n b_pos: b_unit_pos,\n t_age: t_unit_age,\n b_age: b_unit_age,\n units: units1,\n },\n ];\n } else if (axisType == ColumnAxisType.AGE) {\n sections0 = groupUnitsIntoSectionsBySectionID(units1, axisType);\n } else {\n sections0 = groupUnitsIntoSectionsByOverlap(units1, axisType);\n }\n\n // Limit sections to the range specified by t_age/b_age or t_pos/b_pos global options\n for (let section of clipBeforeLayout ? sections0 : []) {\n if (axisType == ColumnAxisType.AGE) {\n section.t_age = Math.max(section.t_age, t_age ?? -Infinity);\n section.b_age = Math.min(section.b_age, b_age ?? Infinity);\n } else if (axisType == ColumnAxisType.DEPTH) {\n section.t_pos = Math.max(section.t_pos, t_pos ?? -Infinity);\n section.b_pos = Math.min(section.b_pos, b_pos ?? Infinity);\n } else if (axisType == ColumnAxisType.HEIGHT) {\n section.t_pos = Math.max(section.t_pos, t_pos ?? -Infinity);\n section.b_pos = Math.min(section.b_pos, b_pos ?? Infinity);\n }\n }\n\n /** Merging overlapping sections really only makes sense for age/height/depth\n * columns. Ordinal columns are numbered by section so merging them\n * results in collisions.\n */\n let sections = sections0;\n if (\n mergeSections == MergeSectionsMode.OVERLAPPING &&\n axisType == ColumnAxisType.AGE\n ) {\n sections = mergeOverlappingSections(sections);\n }\n // Filter out undefined sections just in case\n sections = sections.filter((d) => d != null);\n\n // SCALES\n\n /** The window we've been asked to render. Unit density is derived from what\n * it shows (see `findAverageUnitHeight`), so it has to be known before any\n * section is laid out — but nothing is *clipped* to it until the very end.\n */\n const focalWindow: [number, number] | null = clipBeforeLayout\n ? null\n : [b_age ?? Infinity, t_age ?? -Infinity];\n\n const layoutOptions = { ...options, visibleWindow: focalWindow };\n\n /* Compute pixel scales etc. for sections\n * We need to do this now to determine which unconformities\n * are small enough to collapse.\n */\n let sectionsWithScales = computeSectionHeights(sections, layoutOptions);\n\n if (collapseSmallUnconformities && hybridScale == null) {\n // Collapse small unconformities in pixel height space\n // TODO: this doesn't seem to work properly for non-age columns?\n let threshold = unconformityHeight ?? 30;\n if (typeof collapseSmallUnconformities == \"number\") {\n threshold = collapseSmallUnconformities;\n }\n\n sectionsWithScales = collapseUnconformitiesByPixelHeight(\n sectionsWithScales,\n threshold,\n layoutOptions,\n );\n }\n\n /** Now that every section is laid out at full extent — with its own density\n * and `minSectionHeight` already settled — apply the rendered window. Padding\n * is spent here, against real pixel heights, so `windowPadding` px of an\n * abutting section is exactly that many pixels.\n */\n if (focalWindow != null && (t_age != null || b_age != null)) {\n // Resolve final densities first (a section the window cuts short is\n // stretched to `minSectionHeight`), then spend the padding budget against\n // them, so a margin is the pixels asked for rather than those pixels times\n // whatever stretch its neighbor happened to need.\n const floor = options.minSectionHeight ?? options.targetUnitHeight ?? 0;\n const scales = resolveWindowScales(sectionsWithScales, focalWindow, floor);\n const scaleFor = (section) =>\n scales.get(section) ?? section.scaleInfo.pixelScale;\n\n const window =\n windowPadding > 0\n ? padWindowByPixels(\n sectionsWithScales,\n focalWindow,\n windowPadding,\n scaleFor,\n )\n : focalWindow;\n\n sectionsWithScales = trimSectionsToWindow(\n sectionsWithScales,\n window,\n scaleFor,\n );\n }\n\n /** Prepare section scale information using groups.\n * Total height is computed from section scales.\n * */\n let { totalHeight, sections: sections2 } = finalizeSectionHeights(\n sectionsWithScales,\n unconformityHeight,\n );\n\n /** For each section, find units that are overlapping.\n * We do this after merging sections so that we can\n * handle cases where there are overlapping units across sections\n * */\n const sectionsOut = sections2.map((section) => {\n return {\n ...section,\n units: preprocessUnits(section, axisType),\n };\n });\n\n /** Reconstitute the units so that they are sorted by section and properly enhanced.\n * This is mostly important so that unit keyboard navigation\n * predictably selects adjacent units.\n */\n const units2 = sectionsOut.reduce((acc, group) => {\n const { units } = group;\n for (const unit of units) {\n acc.push(unit);\n }\n return acc;\n }, []);\n\n return {\n units: units2,\n totalHeight: _totalHeight ?? totalHeight,\n sections: sectionsOut,\n };\n}\n"],"names":["units"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/prepare-units/index.ts"],"sourcesContent":["import {\n getSectionAgeRange,\n getSectionPosRange,\n groupUnitsIntoSectionsByOverlap,\n groupUnitsIntoSectionsBySectionID,\n mergeOverlappingSections,\n preprocessSectionUnit,\n preprocessUnits,\n UnitWithLayoutHints,\n} from \"./helpers\";\nimport { ColumnAxisType } from \"@macrostrat/column-components\";\nimport { useMemo } from \"react\";\nimport { UnitLong } from \"@macrostrat/api-types\";\nimport {\n collapseUnconformitiesByPixelHeight,\n computeSectionHeights,\n finalizeSectionHeights,\n padWindowByPixels,\n resolveWindowScales,\n trimSectionsToWindow,\n type CompositeColumnScale,\n} from \"./composite-scale\";\nimport {\n agesOverlap,\n MergeSectionsMode,\n PrepareColumnOptions,\n PreparedColumnData,\n unitsOverlap,\n} from \"./utils\";\nimport { type ColumnHeightScaleOptions, SectionInfo } from \"./types\";\n\nexport * from \"./utils\";\nexport * from \"./types\";\nexport * from \"./density\";\nexport { preprocessUnits };\nexport type { CompositeColumnScale };\n\nexport function usePreparedColumnUnits(\n data: UnitLong[],\n options: PrepareColumnOptions,\n): PreparedColumnData {\n /** This function wraps and memoizes all preparation steps for converting\n * an array of units from the /units route to a form ready for usage.\n */\n return useMemo(() => {\n return prepareColumnUnits(data, options);\n }, [data, ...Object.values(options)]);\n}\n\nexport function prepareColumnUnits(\n units: UnitWithLayoutHints<UnitLong>[],\n options: PrepareColumnOptions,\n): PreparedColumnData {\n /** Prepare units for rendering into Macrostrat columns */\n\n let { t_age, b_age, t_pos, b_pos } = options;\n\n const {\n mergeSections = MergeSectionsMode.OVERLAPPING,\n axisType,\n unconformityHeight,\n collapseSmallUnconformities = false,\n hybridScale,\n scale,\n windowPadding = 0,\n } = options;\n\n let _totalHeight: number | null = null;\n\n if (scale != null) {\n // Set t_age and b_age based on scale domain if not already set\n const domain = scale.domain();\n if (axisType == ColumnAxisType.AGE) {\n if (t_age == null) t_age = Math.min(...domain);\n if (b_age == null) b_age = Math.max(...domain);\n _totalHeight = Math.abs(scale(b_age) - scale(t_age));\n } else {\n if (t_pos == null) t_pos = Math.min(...domain);\n if (b_pos == null) b_pos = Math.max(...domain);\n _totalHeight = Math.abs(scale(b_pos) - scale(t_pos));\n }\n }\n\n /** Age columns lay every section out at its full extent and clip to the\n * window at the end (see below), so that a section abutting the window is\n * sized by its own content rather than by the sliver that survives the clip.\n * Hybrid and externally-supplied scales build their own mapping and can't be\n * re-derived that way, so they keep the original clip-then-lay-out path. */\n const clipBeforeLayout =\n axisType != ColumnAxisType.AGE || hybridScale != null || scale != null;\n\n // Start by ensuring that ages and positions are numbers\n // also set up some values for eODP-style columns\n let units1 = units.map(preprocessSectionUnit);\n\n /** A bound that isn't set doesn't bound anything. Passing `null` for one is\n * the ordinary way to say \"no window\", and comparing against it as though\n * it were an age would throw every unit out. */\n const window = {\n t_age: t_age ?? -Infinity,\n b_age: b_age ?? Infinity,\n t_pos: t_pos ?? -Infinity,\n b_pos: b_pos ?? Infinity,\n };\n const isWindowed =\n axisType == ColumnAxisType.AGE\n ? t_age != null || b_age != null\n : t_pos != null || b_pos != null;\n\n if (clipBeforeLayout && isWindowed) {\n /** Prototype filtering to age range */\n units1 = units1.filter((d) => {\n // Filter units by t_age and b_age, inclusive\n if (axisType == ColumnAxisType.AGE) {\n return agesOverlap(d, window);\n } else {\n return unitsOverlap(d, window as any, axisType);\n }\n });\n }\n\n let mergeMode = mergeSections;\n // if (axisType != ColumnAxisType.AGE) {\n // // For non-age columns, we always merge sections.\n // // This is because the \"groupUnitsIntoSections\" function is not well-defined\n // // for non-age columns.\n // mergeMode = MergeSectionsMode.ALL;\n // }\n\n let sections0: SectionInfo<UnitLong>[];\n if (mergeMode == MergeSectionsMode.ALL) {\n // For the \"merge sections\" mode, we need to create a single section\n const [b_unit_pos, t_unit_pos] = getSectionPosRange(units1, axisType);\n const [b_unit_age, t_unit_age] = getSectionAgeRange(units1);\n sections0 = [\n {\n section_id: 0,\n /**\n * If ages limits are directly specified, use them to define the section bounds.\n * */\n t_pos: t_unit_pos,\n b_pos: b_unit_pos,\n t_age: t_unit_age,\n b_age: b_unit_age,\n units: units1,\n },\n ];\n } else if (axisType == ColumnAxisType.AGE) {\n sections0 = groupUnitsIntoSectionsBySectionID(units1, axisType);\n } else {\n sections0 = groupUnitsIntoSectionsByOverlap(units1, axisType);\n }\n\n // Limit sections to the range specified by t_age/b_age or t_pos/b_pos global options\n for (let section of clipBeforeLayout ? sections0 : []) {\n if (axisType == ColumnAxisType.AGE) {\n section.t_age = Math.max(section.t_age, t_age ?? -Infinity);\n section.b_age = Math.min(section.b_age, b_age ?? Infinity);\n } else if (axisType == ColumnAxisType.DEPTH) {\n section.t_pos = Math.max(section.t_pos, t_pos ?? -Infinity);\n section.b_pos = Math.min(section.b_pos, b_pos ?? Infinity);\n } else if (axisType == ColumnAxisType.HEIGHT) {\n section.t_pos = Math.max(section.t_pos, t_pos ?? -Infinity);\n section.b_pos = Math.min(section.b_pos, b_pos ?? Infinity);\n }\n }\n\n /** Merging overlapping sections really only makes sense for age/height/depth\n * columns. Ordinal columns are numbered by section so merging them\n * results in collisions.\n */\n let sections = sections0;\n if (\n mergeSections == MergeSectionsMode.OVERLAPPING &&\n axisType == ColumnAxisType.AGE\n ) {\n sections = mergeOverlappingSections(sections);\n }\n // Filter out undefined sections just in case\n sections = sections.filter((d) => d != null);\n\n // SCALES\n\n /** The window we've been asked to render. Unit density is derived from what\n * it shows (see `findAverageUnitHeight`), so it has to be known before any\n * section is laid out — but nothing is *clipped* to it until the very end.\n */\n const focalWindow: [number, number] | null = clipBeforeLayout\n ? null\n : [b_age ?? Infinity, t_age ?? -Infinity];\n\n const layoutOptions = { ...options, visibleWindow: focalWindow };\n\n /* Compute pixel scales etc. for sections\n * We need to do this now to determine which unconformities\n * are small enough to collapse.\n */\n let sectionsWithScales = computeSectionHeights(sections, layoutOptions);\n\n if (collapseSmallUnconformities && hybridScale == null) {\n // Collapse small unconformities in pixel height space\n // TODO: this doesn't seem to work properly for non-age columns?\n let threshold = unconformityHeight ?? 30;\n if (typeof collapseSmallUnconformities == \"number\") {\n threshold = collapseSmallUnconformities;\n }\n\n sectionsWithScales = collapseUnconformitiesByPixelHeight(\n sectionsWithScales,\n threshold,\n layoutOptions,\n );\n }\n\n /** Now that every section is laid out at full extent — with its own density\n * and `minSectionHeight` already settled — apply the rendered window. Padding\n * is spent here, against real pixel heights, so `windowPadding` px of an\n * abutting section is exactly that many pixels.\n */\n if (focalWindow != null && (t_age != null || b_age != null)) {\n // Resolve final densities first (a section the window cuts short is\n // stretched to `minSectionHeight`), then spend the padding budget against\n // them, so a margin is the pixels asked for rather than those pixels times\n // whatever stretch its neighbor happened to need.\n const floor =\n layoutOptions.minSectionHeight ?? layoutOptions.targetUnitHeight ?? 0;\n const scales = resolveWindowScales(sectionsWithScales, focalWindow, floor);\n const natural = (section) =>\n scales.get(section) ?? section.scaleInfo.pixelScale;\n\n\n const scaleFor = natural;\n\n const window =\n windowPadding > 0\n ? padWindowByPixels(\n sectionsWithScales,\n focalWindow,\n windowPadding,\n scaleFor,\n )\n : focalWindow;\n\n sectionsWithScales = trimSectionsToWindow(\n sectionsWithScales,\n window,\n scaleFor,\n );\n }\n\n /** Prepare section scale information using groups.\n * Total height is computed from section scales.\n * */\n let { totalHeight, sections: sections2 } = finalizeSectionHeights(\n sectionsWithScales,\n unconformityHeight,\n );\n\n /** For each section, find units that are overlapping.\n * We do this after merging sections so that we can\n * handle cases where there are overlapping units across sections\n * */\n const sectionsOut = sections2.map((section) => {\n return {\n ...section,\n units: preprocessUnits(section, axisType),\n };\n });\n\n /** Reconstitute the units so that they are sorted by section and properly enhanced.\n * This is mostly important so that unit keyboard navigation\n * predictably selects adjacent units.\n */\n const units2 = sectionsOut.reduce((acc, group) => {\n const { units } = group;\n for (const unit of units) {\n acc.push(unit);\n }\n return acc;\n }, []);\n\n return {\n units: units2,\n totalHeight: _totalHeight ?? totalHeight,\n sections: sectionsOut,\n };\n}\n"],"names":["window","units"],"mappings":";;;;;;AAqCO,SAAS,uBACd,MACA,SACoB;AAIpB,SAAO,QAAQ,MAAM;AACnB,WAAO,mBAAmB,MAAM,OAAO;AAAA,EACzC,GAAG,CAAC,MAAM,GAAG,OAAO,OAAO,OAAO,CAAC,CAAC;AACtC;AAEO,SAAS,mBACd,OACA,SACoB;AAGpB,MAAI,EAAE,OAAO,OAAO,OAAO,UAAU;AAErC,QAAM;AAAA,IACJ,gBAAgB,kBAAkB;AAAA,IAClC;AAAA,IACA;AAAA,IACA,8BAA8B;AAAA,IAC9B;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,EAAA,IACd;AAEJ,MAAI,eAA8B;AAElC,MAAI,SAAS,MAAM;AAEjB,UAAM,SAAS,MAAM,OAAA;AACrB,QAAI,YAAY,eAAe,KAAK;AAClC,UAAI,SAAS,KAAM,SAAQ,KAAK,IAAI,GAAG,MAAM;AAC7C,UAAI,SAAS,KAAM,SAAQ,KAAK,IAAI,GAAG,MAAM;AAC7C,qBAAe,KAAK,IAAI,MAAM,KAAK,IAAI,MAAM,KAAK,CAAC;AAAA,IACrD,OAAO;AACL,UAAI,SAAS,KAAM,SAAQ,KAAK,IAAI,GAAG,MAAM;AAC7C,UAAI,SAAS,KAAM,SAAQ,KAAK,IAAI,GAAG,MAAM;AAC7C,qBAAe,KAAK,IAAI,MAAM,KAAK,IAAI,MAAM,KAAK,CAAC;AAAA,IACrD;AAAA,EACF;AAOA,QAAM,mBACJ,YAAY,eAAe,OAAO,eAAe,QAAQ,SAAS;AAIpE,MAAI,SAAS,MAAM,IAAI,qBAAqB;AAK5C,QAAM,SAAS;AAAA,IACb,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,IAChB,OAAO,SAAS;AAAA,EAAA;AAElB,QAAM,aACJ,YAAY,eAAe,MACvB,SAAS,QAAQ,SAAS,OAC1B,SAAS,QAAQ,SAAS;AAEhC,MAAI,oBAAoB,YAAY;AAElC,aAAS,OAAO,OAAO,CAAC,MAAM;AAE5B,UAAI,YAAY,eAAe,KAAK;AAClC,eAAO,YAAY,GAAG,MAAM;AAAA,MAC9B,OAAO;AACL,eAAO,aAAa,GAAG,QAAe,QAAQ;AAAA,MAChD;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,YAAY;AAQhB,MAAI;AACJ,MAAI,aAAa,kBAAkB,KAAK;AAEtC,UAAM,CAAC,YAAY,UAAU,IAAI,mBAAmB,QAAQ,QAAQ;AACpE,UAAM,CAAC,YAAY,UAAU,IAAI,mBAAmB,MAAM;AAC1D,gBAAY;AAAA,MACV;AAAA,QACE,YAAY;AAAA;AAAA;AAAA;AAAA,QAIZ,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,EAEJ,WAAW,YAAY,eAAe,KAAK;AACzC,gBAAY,kCAAkC,QAAQ,QAAQ;AAAA,EAChE,OAAO;AACL,gBAAY,gCAAgC,QAAQ,QAAQ;AAAA,EAC9D;AAGA,WAAS,WAAW,mBAAmB,YAAY,CAAA,GAAI;AACrD,QAAI,YAAY,eAAe,KAAK;AAClC,cAAQ,QAAQ,KAAK,IAAI,QAAQ,OAAO,SAAS,SAAS;AAC1D,cAAQ,QAAQ,KAAK,IAAI,QAAQ,OAAO,SAAS,QAAQ;AAAA,IAC3D,WAAW,YAAY,eAAe,OAAO;AAC3C,cAAQ,QAAQ,KAAK,IAAI,QAAQ,OAAO,SAAS,SAAS;AAC1D,cAAQ,QAAQ,KAAK,IAAI,QAAQ,OAAO,SAAS,QAAQ;AAAA,IAC3D,WAAW,YAAY,eAAe,QAAQ;AAC5C,cAAQ,QAAQ,KAAK,IAAI,QAAQ,OAAO,SAAS,SAAS;AAC1D,cAAQ,QAAQ,KAAK,IAAI,QAAQ,OAAO,SAAS,QAAQ;AAAA,IAC3D;AAAA,EACF;AAMA,MAAI,WAAW;AACf,MACE,iBAAiB,kBAAkB,eACnC,YAAY,eAAe,KAC3B;AACA,eAAW,yBAAyB,QAAQ;AAAA,EAC9C;AAEA,aAAW,SAAS,OAAO,CAAC,MAAM,KAAK,IAAI;AAQ3C,QAAM,cAAuC,mBACzC,OACA,CAAC,SAAS,UAAU,SAAS,SAAS;AAE1C,QAAM,gBAAgB,EAAE,GAAG,SAAS,eAAe,YAAA;AAMnD,MAAI,qBAAqB,sBAAsB,UAAU,aAAa;AAEtE,MAAI,+BAA+B,eAAe,MAAM;AAGtD,QAAI,YAAY,sBAAsB;AACtC,QAAI,OAAO,+BAA+B,UAAU;AAClD,kBAAY;AAAA,IACd;AAEA,yBAAqB;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAOA,MAAI,eAAe,SAAS,SAAS,QAAQ,SAAS,OAAO;AAK3D,UAAM,QACJ,cAAc,oBAAoB,cAAc,oBAAoB;AACtE,UAAM,SAAS,oBAAoB,oBAAoB,aAAa,KAAK;AACzE,UAAM,UAAU,CAAC,YACf,OAAO,IAAI,OAAO,KAAK,QAAQ,UAAU;AAG3C,UAAM,WAAW;AAEjB,UAAMA,UACJ,gBAAgB,IACZ;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,IAEF;AAEN,yBAAqB;AAAA,MACnB;AAAA,MACAA;AAAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAKA,MAAI,EAAE,aAAa,UAAU,UAAA,IAAc;AAAA,IACzC;AAAA,IACA;AAAA,EAAA;AAOF,QAAM,cAAc,UAAU,IAAI,CAAC,YAAY;AAC7C,WAAO;AAAA,MACL,GAAG;AAAA,MACH,OAAO,gBAAgB,SAAS,QAAQ;AAAA,IAAA;AAAA,EAE5C,CAAC;AAMD,QAAM,SAAS,YAAY,OAAO,CAAC,KAAK,UAAU;AAChD,UAAM,EAAE,OAAAC,OAAAA,IAAU;AAClB,eAAW,QAAQA,QAAO;AACxB,UAAI,KAAK,IAAI;AAAA,IACf;AACA,WAAO;AAAA,EACT,GAAG,CAAA,CAAE;AAEL,SAAO;AAAA,IACL,OAAO;AAAA,IACP,aAAa,gBAAgB;AAAA,IAC7B,UAAU;AAAA,EAAA;AAEd;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs","sources":["../../src/prepare-units/types.ts"],"sourcesContent":["import type { UnitLong } from \"@macrostrat/api-types\";\nimport type { ColumnAxisType } from \"@macrostrat/column-components\";\nimport type { ScaleContinuousNumeric } from \"d3-scale\";\n\nexport interface ColumnHeightScaleOptions {\n /** A
|
|
1
|
+
{"version":3,"file":"types.cjs","sources":["../../src/prepare-units/types.ts"],"sourcesContent":["import type { UnitLong } from \"@macrostrat/api-types\";\nimport type { ColumnAxisType } from \"@macrostrat/column-components\";\nimport type { ScaleContinuousNumeric } from \"d3-scale\";\nimport type { SectionDensityLike, SectionOptionsLike } from \"./density\";\n\nexport interface ColumnHeightScaleOptions {\n /** A density stated outright: pixels per Myr on an age column, per metre\n * otherwise, every section drawn to the same scale whatever it holds.\n * Rarely what you want within one column, and the only way to make several\n * of them comparable.\n *\n * It also takes a rule — a function of the section's context — for the\n * cases the options here can't describe. A rule is in sole charge of its\n * section: the floors don't apply to it. */\n pixelScale?: SectionDensityLike;\n /** Room for a typical unit the render window shows: this many pixels tall,\n * whatever its duration. The knob that usually decides a column — reach for\n * it to draw one larger or smaller — and the one that expands it as you\n * zoom in, since the units on screen keep their size while the time they\n * cover shrinks. See `./density` for what \"typical\" means. */\n targetUnitHeight?: number;\n /** Room for a section: at least this many pixels tall, whatever its extent.\n * Small sections have a unit or two and little room for axis labels. */\n minSectionHeight?: number;\n /** A floor on the density itself, in pixels per axis unit. */\n minPixelScale?: number;\n /** Sizing for a section in particular, or a rule that works it out from\n * what the section holds. Whatever it returns overrides the options above\n * for that section; anything it leaves out keeps the column's value. */\n sectionOptions?: SectionOptionsLike;\n /** Padding around the `t_age`/`b_age` window, in **pixels** of neighboring\n * column: how much of the abutting sections to reveal past the window.\n *\n * Resolved after every section is laid out at full extent, so it's exact —\n * each section's own density and each crossed unconformity's fixed height are\n * spent from the pixel budget. Padding collapses where the column runs out.\n * Ignored for hybrid or externally-supplied scales. */\n windowPadding?: number;\n // Axis scale type\n axisType?: ColumnAxisType;\n // Unconformity height in pixels\n unconformityHeight?: number;\n // Whether to collapse unconformities that are less than a height threshold\n collapseSmallUnconformities?: boolean | number;\n // A continuous scale to use instead of generating one\n // TODO: discontinuous scales are not yet supported\n scale?: ScaleContinuousNumeric<number, number>;\n // Hybrid scale type.\n // This overrides parameters such as the axis type\n hybridScale?: HybridScaleDefinition;\n}\n\nexport enum HybridScaleType {\n // An age-domain scale that puts equal vertical space between surfaces\n EquidistantSurfaces = \"equidistant-surfaces\",\n // A height-domain scale that is based on the average height of units between surfaces\n ApproximateHeight = \"approximate-height\",\n}\n\nexport enum HeightMethod {\n Minimum = \"minimum\",\n Average = \"average\",\n Maximum = \"maximum\",\n}\n\nexport interface HybridScaleOptions {\n pixelOffset?: number;\n pixelScale?: number;\n}\n\nexport type ApproxHeightScaleOptions = {\n minHeight?: number;\n defaultHeight?: number;\n heightMethod?: HeightMethod;\n};\n\nexport type HybridScaleDefinition =\n | ({\n type: HybridScaleType.ApproximateHeight;\n } & ApproxHeightScaleOptions)\n | {\n type: HybridScaleType.EquidistantSurfaces;\n };\n\nexport interface SectionScaleOptions extends ColumnHeightScaleOptions {\n axisType: ColumnAxisType;\n domain: [number, number];\n /** Named in the context a per-section rule sees */\n sectionID?: number;\n /** The requested render window, `[b_age, t_age]`, if there is one. Set\n * internally by `prepareColumnUnits`: unit density is derived from the units\n * this window actually shows, so `targetUnitHeight` describes the units you\n * can see at any zoom depth rather than the section's overall average. */\n visibleWindow?: [number, number];\n}\n\n/** Output of a section scale. For now, this assumes that the\n * mapping is linear, but it could be extended to support arbitrary\n * scale functions.\n */\nexport interface PackageScaleInfo {\n domain: [number, number];\n pixelHeight: number;\n // TODO: add a function\n scale: ScaleContinuousNumeric<number, number>;\n pixelScale?: number; // if it's a linear scale, this could be defined\n // Subsidiary scale for height mapping (for hybrid scales)\n heightScale?: ScaleContinuousNumeric<number, number>;\n}\n\nexport type PackageScaleLayoutData = PackageScaleInfo & {\n // A unique key for the section to use in React\n key: string;\n offset: number;\n // How much to\n paddingTop: number;\n};\nexport interface StratigraphicPackage {\n /** A collection of stratigraphic information organized in time, corresponding\n * to single or multiple columns. */\n t_age: number;\n b_age: number;\n}\n\nexport interface SectionInfo<\n T extends UnitLong = ExtUnit,\n> extends StratigraphicPackage {\n /** A time-bounded part of a single stratigraphic column. */\n section_id: number | number[];\n units: T[];\n b_pos?: number;\n t_pos?: number;\n}\n\nexport interface ExtUnit extends UnitLong {\n bottomOverlap: boolean;\n overlappingUnits: number[];\n column?: number;\n /* Positions (ages or heights) where the unit is clipped to its containing section.\n * This is relevant if we are filtering by age/height/depth range.\n */\n t_clip_pos?: number;\n b_clip_pos?: number;\n}\n\nexport type PackageLayoutData<T extends UnitLong = ExtUnit> = SectionInfo<T> & {\n scaleInfo: PackageScaleLayoutData;\n // A unique key for the section to use in React\n key: string;\n};\n\nexport interface CompositeScaleData {\n totalHeight: number;\n sections: PackageScaleLayoutData[];\n}\n\nexport interface ColumnScaleOptions extends ColumnHeightScaleOptions {\n axisType: ColumnAxisType;\n unconformityHeight: number;\n /** The requested render window, `[b_age, t_age]`, if there is one. Set\n * internally by `prepareColumnUnits`: unit density is derived from the units\n * this window actually shows, so `targetUnitHeight` describes the units you\n * can see at any zoom depth rather than the section's overall average. */\n visibleWindow?: [number, number];\n}\n\nexport interface CompositeColumnData<T extends UnitLong = ExtUnit> extends Omit<\n CompositeScaleData,\n \"sections\"\n> {\n sections: PackageLayoutData<T>[];\n}\n"],"names":["HybridScaleType","HeightMethod"],"mappings":";;AAoDO,IAAK,oCAAAA,qBAAL;AAELA,mBAAA,qBAAA,IAAsB;AAEtBA,mBAAA,mBAAA,IAAoB;AAJV,SAAAA;AAAA,GAAA,mBAAA,CAAA,CAAA;AAOL,IAAK,iCAAAC,kBAAL;AACLA,gBAAA,SAAA,IAAU;AACVA,gBAAA,SAAA,IAAU;AACVA,gBAAA,SAAA,IAAU;AAHA,SAAAA;AAAA,GAAA,gBAAA,CAAA,CAAA;;;"}
|
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
import { UnitLong } from '@macrostrat/api-types';
|
|
2
2
|
import { ColumnAxisType } from '@macrostrat/column-components';
|
|
3
3
|
import { ScaleContinuousNumeric } from 'd3-scale';
|
|
4
|
+
import { SectionDensityLike, SectionOptionsLike } from './density';
|
|
4
5
|
export interface ColumnHeightScaleOptions {
|
|
5
|
-
/** A
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
6
|
+
/** A density stated outright: pixels per Myr on an age column, per metre
|
|
7
|
+
* otherwise, every section drawn to the same scale whatever it holds.
|
|
8
|
+
* Rarely what you want within one column, and the only way to make several
|
|
9
|
+
* of them comparable.
|
|
10
|
+
*
|
|
11
|
+
* It also takes a rule — a function of the section's context — for the
|
|
12
|
+
* cases the options here can't describe. A rule is in sole charge of its
|
|
13
|
+
* section: the floors don't apply to it. */
|
|
14
|
+
pixelScale?: SectionDensityLike;
|
|
15
|
+
/** Room for a typical unit the render window shows: this many pixels tall,
|
|
16
|
+
* whatever its duration. The knob that usually decides a column — reach for
|
|
17
|
+
* it to draw one larger or smaller — and the one that expands it as you
|
|
18
|
+
* zoom in, since the units on screen keep their size while the time they
|
|
19
|
+
* cover shrinks. See `./density` for what "typical" means. */
|
|
9
20
|
targetUnitHeight?: number;
|
|
10
|
-
/**
|
|
21
|
+
/** Room for a section: at least this many pixels tall, whatever its extent.
|
|
22
|
+
* Small sections have a unit or two and little room for axis labels. */
|
|
11
23
|
minSectionHeight?: number;
|
|
12
|
-
/**
|
|
13
|
-
* needed because small sections (<1-2 units) don't necessarily have space to comfortably
|
|
14
|
-
* render two axis labels */
|
|
24
|
+
/** A floor on the density itself, in pixels per axis unit. */
|
|
15
25
|
minPixelScale?: number;
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
|
|
20
|
-
visibleWindow?: [number, number];
|
|
26
|
+
/** Sizing for a section in particular, or a rule that works it out from
|
|
27
|
+
* what the section holds. Whatever it returns overrides the options above
|
|
28
|
+
* for that section; anything it leaves out keeps the column's value. */
|
|
29
|
+
sectionOptions?: SectionOptionsLike;
|
|
21
30
|
/** Padding around the `t_age`/`b_age` window, in **pixels** of neighboring
|
|
22
31
|
* column: how much of the abutting sections to reveal past the window.
|
|
23
32
|
*
|
|
@@ -58,6 +67,13 @@ export type HybridScaleDefinition = ({
|
|
|
58
67
|
export interface SectionScaleOptions extends ColumnHeightScaleOptions {
|
|
59
68
|
axisType: ColumnAxisType;
|
|
60
69
|
domain: [number, number];
|
|
70
|
+
/** Named in the context a per-section rule sees */
|
|
71
|
+
sectionID?: number;
|
|
72
|
+
/** The requested render window, `[b_age, t_age]`, if there is one. Set
|
|
73
|
+
* internally by `prepareColumnUnits`: unit density is derived from the units
|
|
74
|
+
* this window actually shows, so `targetUnitHeight` describes the units you
|
|
75
|
+
* can see at any zoom depth rather than the section's overall average. */
|
|
76
|
+
visibleWindow?: [number, number];
|
|
61
77
|
}
|
|
62
78
|
/** Output of a section scale. For now, this assumes that the
|
|
63
79
|
* mapping is linear, but it could be extended to support arbitrary
|
|
@@ -106,6 +122,11 @@ export interface CompositeScaleData {
|
|
|
106
122
|
export interface ColumnScaleOptions extends ColumnHeightScaleOptions {
|
|
107
123
|
axisType: ColumnAxisType;
|
|
108
124
|
unconformityHeight: number;
|
|
125
|
+
/** The requested render window, `[b_age, t_age]`, if there is one. Set
|
|
126
|
+
* internally by `prepareColumnUnits`: unit density is derived from the units
|
|
127
|
+
* this window actually shows, so `targetUnitHeight` describes the units you
|
|
128
|
+
* can see at any zoom depth rather than the section's overall average. */
|
|
129
|
+
visibleWindow?: [number, number];
|
|
109
130
|
}
|
|
110
131
|
export interface CompositeColumnData<T extends UnitLong = ExtUnit> extends Omit<CompositeScaleData, "sections"> {
|
|
111
132
|
sections: PackageLayoutData<T>[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sources":["../../src/prepare-units/types.ts"],"sourcesContent":["import type { UnitLong } from \"@macrostrat/api-types\";\nimport type { ColumnAxisType } from \"@macrostrat/column-components\";\nimport type { ScaleContinuousNumeric } from \"d3-scale\";\n\nexport interface ColumnHeightScaleOptions {\n /** A
|
|
1
|
+
{"version":3,"file":"types.js","sources":["../../src/prepare-units/types.ts"],"sourcesContent":["import type { UnitLong } from \"@macrostrat/api-types\";\nimport type { ColumnAxisType } from \"@macrostrat/column-components\";\nimport type { ScaleContinuousNumeric } from \"d3-scale\";\nimport type { SectionDensityLike, SectionOptionsLike } from \"./density\";\n\nexport interface ColumnHeightScaleOptions {\n /** A density stated outright: pixels per Myr on an age column, per metre\n * otherwise, every section drawn to the same scale whatever it holds.\n * Rarely what you want within one column, and the only way to make several\n * of them comparable.\n *\n * It also takes a rule — a function of the section's context — for the\n * cases the options here can't describe. A rule is in sole charge of its\n * section: the floors don't apply to it. */\n pixelScale?: SectionDensityLike;\n /** Room for a typical unit the render window shows: this many pixels tall,\n * whatever its duration. The knob that usually decides a column — reach for\n * it to draw one larger or smaller — and the one that expands it as you\n * zoom in, since the units on screen keep their size while the time they\n * cover shrinks. See `./density` for what \"typical\" means. */\n targetUnitHeight?: number;\n /** Room for a section: at least this many pixels tall, whatever its extent.\n * Small sections have a unit or two and little room for axis labels. */\n minSectionHeight?: number;\n /** A floor on the density itself, in pixels per axis unit. */\n minPixelScale?: number;\n /** Sizing for a section in particular, or a rule that works it out from\n * what the section holds. Whatever it returns overrides the options above\n * for that section; anything it leaves out keeps the column's value. */\n sectionOptions?: SectionOptionsLike;\n /** Padding around the `t_age`/`b_age` window, in **pixels** of neighboring\n * column: how much of the abutting sections to reveal past the window.\n *\n * Resolved after every section is laid out at full extent, so it's exact —\n * each section's own density and each crossed unconformity's fixed height are\n * spent from the pixel budget. Padding collapses where the column runs out.\n * Ignored for hybrid or externally-supplied scales. */\n windowPadding?: number;\n // Axis scale type\n axisType?: ColumnAxisType;\n // Unconformity height in pixels\n unconformityHeight?: number;\n // Whether to collapse unconformities that are less than a height threshold\n collapseSmallUnconformities?: boolean | number;\n // A continuous scale to use instead of generating one\n // TODO: discontinuous scales are not yet supported\n scale?: ScaleContinuousNumeric<number, number>;\n // Hybrid scale type.\n // This overrides parameters such as the axis type\n hybridScale?: HybridScaleDefinition;\n}\n\nexport enum HybridScaleType {\n // An age-domain scale that puts equal vertical space between surfaces\n EquidistantSurfaces = \"equidistant-surfaces\",\n // A height-domain scale that is based on the average height of units between surfaces\n ApproximateHeight = \"approximate-height\",\n}\n\nexport enum HeightMethod {\n Minimum = \"minimum\",\n Average = \"average\",\n Maximum = \"maximum\",\n}\n\nexport interface HybridScaleOptions {\n pixelOffset?: number;\n pixelScale?: number;\n}\n\nexport type ApproxHeightScaleOptions = {\n minHeight?: number;\n defaultHeight?: number;\n heightMethod?: HeightMethod;\n};\n\nexport type HybridScaleDefinition =\n | ({\n type: HybridScaleType.ApproximateHeight;\n } & ApproxHeightScaleOptions)\n | {\n type: HybridScaleType.EquidistantSurfaces;\n };\n\nexport interface SectionScaleOptions extends ColumnHeightScaleOptions {\n axisType: ColumnAxisType;\n domain: [number, number];\n /** Named in the context a per-section rule sees */\n sectionID?: number;\n /** The requested render window, `[b_age, t_age]`, if there is one. Set\n * internally by `prepareColumnUnits`: unit density is derived from the units\n * this window actually shows, so `targetUnitHeight` describes the units you\n * can see at any zoom depth rather than the section's overall average. */\n visibleWindow?: [number, number];\n}\n\n/** Output of a section scale. For now, this assumes that the\n * mapping is linear, but it could be extended to support arbitrary\n * scale functions.\n */\nexport interface PackageScaleInfo {\n domain: [number, number];\n pixelHeight: number;\n // TODO: add a function\n scale: ScaleContinuousNumeric<number, number>;\n pixelScale?: number; // if it's a linear scale, this could be defined\n // Subsidiary scale for height mapping (for hybrid scales)\n heightScale?: ScaleContinuousNumeric<number, number>;\n}\n\nexport type PackageScaleLayoutData = PackageScaleInfo & {\n // A unique key for the section to use in React\n key: string;\n offset: number;\n // How much to\n paddingTop: number;\n};\nexport interface StratigraphicPackage {\n /** A collection of stratigraphic information organized in time, corresponding\n * to single or multiple columns. */\n t_age: number;\n b_age: number;\n}\n\nexport interface SectionInfo<\n T extends UnitLong = ExtUnit,\n> extends StratigraphicPackage {\n /** A time-bounded part of a single stratigraphic column. */\n section_id: number | number[];\n units: T[];\n b_pos?: number;\n t_pos?: number;\n}\n\nexport interface ExtUnit extends UnitLong {\n bottomOverlap: boolean;\n overlappingUnits: number[];\n column?: number;\n /* Positions (ages or heights) where the unit is clipped to its containing section.\n * This is relevant if we are filtering by age/height/depth range.\n */\n t_clip_pos?: number;\n b_clip_pos?: number;\n}\n\nexport type PackageLayoutData<T extends UnitLong = ExtUnit> = SectionInfo<T> & {\n scaleInfo: PackageScaleLayoutData;\n // A unique key for the section to use in React\n key: string;\n};\n\nexport interface CompositeScaleData {\n totalHeight: number;\n sections: PackageScaleLayoutData[];\n}\n\nexport interface ColumnScaleOptions extends ColumnHeightScaleOptions {\n axisType: ColumnAxisType;\n unconformityHeight: number;\n /** The requested render window, `[b_age, t_age]`, if there is one. Set\n * internally by `prepareColumnUnits`: unit density is derived from the units\n * this window actually shows, so `targetUnitHeight` describes the units you\n * can see at any zoom depth rather than the section's overall average. */\n visibleWindow?: [number, number];\n}\n\nexport interface CompositeColumnData<T extends UnitLong = ExtUnit> extends Omit<\n CompositeScaleData,\n \"sections\"\n> {\n sections: PackageLayoutData<T>[];\n}\n"],"names":["HybridScaleType","HeightMethod"],"mappings":"AAoDO,IAAK,oCAAAA,qBAAL;AAELA,mBAAA,qBAAA,IAAsB;AAEtBA,mBAAA,mBAAA,IAAoB;AAJV,SAAAA;AAAA,GAAA,mBAAA,CAAA,CAAA;AAOL,IAAK,iCAAAC,kBAAL;AACLA,gBAAA,SAAA,IAAU;AACVA,gBAAA,SAAA,IAAU;AACVA,gBAAA,SAAA,IAAU;AAHA,SAAAA;AAAA,GAAA,gBAAA,CAAA,CAAA;"}
|
package/dist/section.cjs
CHANGED
|
@@ -5,13 +5,13 @@ const timescale = require("@macrostrat/timescale");
|
|
|
5
5
|
const columnComponents = require("@macrostrat/column-components");
|
|
6
6
|
const h$1 = require("@macrostrat/hyper");
|
|
7
7
|
const column_module = require("./column.module.sass.cjs");
|
|
8
|
-
const dataProvider = require("@macrostrat/data-provider");
|
|
9
8
|
const dataComponents = require("@macrostrat/data-components");
|
|
10
9
|
const store = require("./data-provider/store.cjs");
|
|
11
10
|
const composite = require("./units/composite.cjs");
|
|
12
11
|
const ageRange = require("./unit-details/age-range.cjs");
|
|
13
12
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
14
13
|
const h__default = /* @__PURE__ */ _interopDefault(h$1);
|
|
14
|
+
const INTERNATIONAL_TIMESCALE_ID = 11;
|
|
15
15
|
const h = h__default.default.styled(column_module.default);
|
|
16
16
|
function SectionsColumn(props) {
|
|
17
17
|
const {
|
|
@@ -23,7 +23,8 @@ function SectionsColumn(props) {
|
|
|
23
23
|
columnWidth = 150,
|
|
24
24
|
showLabelColumn = true,
|
|
25
25
|
clipUnits = true,
|
|
26
|
-
maxInternalColumns
|
|
26
|
+
maxInternalColumns,
|
|
27
|
+
labelSuppressHeight
|
|
27
28
|
} = props;
|
|
28
29
|
const units = store.useMacrostratUnits();
|
|
29
30
|
const key = units[0]?.col_id;
|
|
@@ -38,7 +39,8 @@ function SectionsColumn(props) {
|
|
|
38
39
|
unconformityLabels
|
|
39
40
|
}),
|
|
40
41
|
h.if(showLabelColumn)(composite.SectionLabelsColumn, {
|
|
41
|
-
width: width - columnWidth
|
|
42
|
+
width: width - columnWidth,
|
|
43
|
+
labelSuppressHeight
|
|
42
44
|
})
|
|
43
45
|
]);
|
|
44
46
|
}
|
|
@@ -53,7 +55,7 @@ function SectionUnitsColumn(props) {
|
|
|
53
55
|
axisType,
|
|
54
56
|
unconformityLabels = true
|
|
55
57
|
} = props;
|
|
56
|
-
const { sections, totalHeight } = store.useMacrostratColumnData();
|
|
58
|
+
const { sections, totalHeight, axisType: columnAxisType } = store.useMacrostratColumnData();
|
|
57
59
|
const scaleData = sections.map((section) => {
|
|
58
60
|
return section.scaleInfo;
|
|
59
61
|
});
|
|
@@ -90,6 +92,9 @@ function SectionUnitsColumn(props) {
|
|
|
90
92
|
h.if(unconformityLabels)(UnconformityLabels, {
|
|
91
93
|
width,
|
|
92
94
|
sections: scaleData,
|
|
95
|
+
// A gap between sections is measured in whatever the axis is: metres
|
|
96
|
+
// down a core, Myr across a time column
|
|
97
|
+
axisType: axisType ?? columnAxisType,
|
|
93
98
|
verbose: false
|
|
94
99
|
})
|
|
95
100
|
]);
|
|
@@ -153,44 +158,71 @@ function CompositeTimescale(props) {
|
|
|
153
158
|
...props
|
|
154
159
|
});
|
|
155
160
|
}
|
|
161
|
+
function TimescaleLabel({ timescale: timescale2 }) {
|
|
162
|
+
const { label, name } = timescale2;
|
|
163
|
+
const style = levelCountStyle(levelCount(timescale2));
|
|
164
|
+
let content = label;
|
|
165
|
+
if (label == null && name != null) {
|
|
166
|
+
content = h("span.timescale-label-text", name);
|
|
167
|
+
}
|
|
168
|
+
if (content == null) return h("div.timescale-label", { style });
|
|
169
|
+
return h("div.timescale-label", { style }, content);
|
|
170
|
+
}
|
|
171
|
+
function levelCountStyle(levelCount2) {
|
|
172
|
+
return { "--timescale-level-count": levelCount2 };
|
|
173
|
+
}
|
|
156
174
|
function CompositeTimescaleCore(props) {
|
|
157
175
|
const {
|
|
158
|
-
levels = 3,
|
|
159
176
|
packages,
|
|
160
177
|
unconformityLabels = false,
|
|
161
178
|
onClickInterval,
|
|
162
|
-
intervalStyle
|
|
179
|
+
intervalStyle,
|
|
180
|
+
showLabels = false,
|
|
181
|
+
className
|
|
163
182
|
} = props;
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
183
|
+
const timescales = useColumnTimescales(props);
|
|
184
|
+
function forTimescale(id) {
|
|
185
|
+
let onClick = null;
|
|
186
|
+
if (onClickInterval != null) {
|
|
187
|
+
onClick = (event, data) => {
|
|
188
|
+
onClickInterval(event, { ...data, timescaleID: id });
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
let style = intervalStyle;
|
|
192
|
+
if (typeof intervalStyle === "function") {
|
|
193
|
+
style = (interval) => intervalStyle(interval, id);
|
|
194
|
+
}
|
|
195
|
+
return { onClick, intervalStyle: style };
|
|
171
196
|
}
|
|
172
|
-
|
|
173
|
-
|
|
197
|
+
return h("div.timescale-column", { className }, [
|
|
198
|
+
h.if(showLabels)(
|
|
199
|
+
"div.timescale-labels",
|
|
200
|
+
timescales.map(
|
|
201
|
+
(timescale2) => h(TimescaleLabel, { key: timescale2.id, timescale: timescale2 })
|
|
202
|
+
)
|
|
203
|
+
),
|
|
174
204
|
h(
|
|
175
205
|
"div.timescales",
|
|
176
206
|
packages.map((group) => {
|
|
177
207
|
const { pixelHeight, paddingTop, key, scale } = group;
|
|
178
208
|
return h(
|
|
179
|
-
"div.
|
|
180
|
-
{ style: { paddingTop
|
|
181
|
-
|
|
182
|
-
h(timescale.Timescale, {
|
|
209
|
+
"div.section-timescales",
|
|
210
|
+
{ style: { paddingTop }, key },
|
|
211
|
+
timescales.map(
|
|
212
|
+
(timescale$1) => h(timescale.Timescale, {
|
|
213
|
+
key: timescale$1.id,
|
|
183
214
|
orientation: timescale.TimescaleOrientation.VERTICAL,
|
|
184
215
|
length: pixelHeight,
|
|
185
|
-
levels:
|
|
216
|
+
levels: timescale$1.levels,
|
|
217
|
+
rootInterval: timescale$1.rootInterval,
|
|
186
218
|
absoluteAgeScale: true,
|
|
187
219
|
showAgeAxis: false,
|
|
188
220
|
scale,
|
|
189
|
-
intervals,
|
|
190
|
-
|
|
191
|
-
|
|
221
|
+
intervals: timescale$1.intervals,
|
|
222
|
+
style: levelCountStyle(levelCount(timescale$1)),
|
|
223
|
+
...forTimescale(timescale$1.id)
|
|
192
224
|
})
|
|
193
|
-
|
|
225
|
+
)
|
|
194
226
|
);
|
|
195
227
|
})
|
|
196
228
|
),
|
|
@@ -202,6 +234,58 @@ function CompositeTimescaleCore(props) {
|
|
|
202
234
|
})
|
|
203
235
|
]);
|
|
204
236
|
}
|
|
237
|
+
function useColumnTimescales(props) {
|
|
238
|
+
const { timescales, levels = 3, timescaleID, additionalTimescales } = props;
|
|
239
|
+
const specs = React.useMemo(
|
|
240
|
+
() => timescaleSpecs({ timescales, levels, timescaleID, additionalTimescales }),
|
|
241
|
+
[
|
|
242
|
+
timescales,
|
|
243
|
+
levels,
|
|
244
|
+
timescaleID,
|
|
245
|
+
additionalTimescales?.join(",")
|
|
246
|
+
]
|
|
247
|
+
);
|
|
248
|
+
const fetchIDs = React.useMemo(
|
|
249
|
+
() => specs.filter((d) => d.intervals == null).map((d) => d.id),
|
|
250
|
+
[specs]
|
|
251
|
+
);
|
|
252
|
+
const intervalSets = timescale.useMacrostratTimescales(fetchIDs);
|
|
253
|
+
return React.useMemo(
|
|
254
|
+
() => specs.map((spec) => ({
|
|
255
|
+
...spec,
|
|
256
|
+
intervals: spec.intervals ?? intervalSets.get(spec.id) ?? []
|
|
257
|
+
})),
|
|
258
|
+
[specs, intervalSets]
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
function timescaleSpecs(props) {
|
|
262
|
+
const { timescales, levels = 3, timescaleID, additionalTimescales = [] } = props;
|
|
263
|
+
if (timescales != null) {
|
|
264
|
+
return timescales.map(normalizeTimescale);
|
|
265
|
+
}
|
|
266
|
+
return [
|
|
267
|
+
{
|
|
268
|
+
id: timescaleID ?? INTERNATIONAL_TIMESCALE_ID,
|
|
269
|
+
levels: levelRange(levels)
|
|
270
|
+
},
|
|
271
|
+
...additionalTimescales.map(normalizeTimescale)
|
|
272
|
+
];
|
|
273
|
+
}
|
|
274
|
+
function normalizeTimescale(timescale2) {
|
|
275
|
+
if (typeof timescale2 === "number") {
|
|
276
|
+
return { id: timescale2, levels: FLAT_TIMESCALE_LEVELS };
|
|
277
|
+
}
|
|
278
|
+
return { levels: FLAT_TIMESCALE_LEVELS, ...timescale2 };
|
|
279
|
+
}
|
|
280
|
+
const FLAT_TIMESCALE_LEVELS = [1, 1];
|
|
281
|
+
function levelRange(levels) {
|
|
282
|
+
if (typeof levels !== "number") return levels;
|
|
283
|
+
return [2, Math.max(2 + Math.min(levels, 5) - 1, 1)];
|
|
284
|
+
}
|
|
285
|
+
function levelCount(timescale2) {
|
|
286
|
+
const [min, max] = timescale2.levels ?? FLAT_TIMESCALE_LEVELS;
|
|
287
|
+
return Math.max(max - min + 1, 1);
|
|
288
|
+
}
|
|
205
289
|
function UnconformityLabels(props) {
|
|
206
290
|
const { width, sections, className, axisType, verbose } = props;
|
|
207
291
|
return h(
|
package/dist/section.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"section.cjs","sources":["../src/section.ts"],"sourcesContent":["import {\n CompositeUnitsColumn,\n LabelTrackerProvider,\n SectionLabelsColumn,\n} from \"./units\";\nimport { ReactNode, FunctionComponent, useMemo } from \"react\";\nimport {\n Timescale,\n TimescaleOrientation,\n TimescaleClickHandler,\n useMacrostratIntervals,\n type IntervalStyleBuilder,\n} from \"@macrostrat/timescale\";\nimport { ColumnAxisType, SVG } from \"@macrostrat/column-components\";\nimport hyper from \"@macrostrat/hyper\";\nimport styles from \"./column.module.sass\";\nimport {\n useMacrostratColumnData,\n useMacrostratUnits,\n MacrostratColumnProvider,\n} from \"./data-provider\";\nimport {\n useMacrostratBaseURL,\n useMacrostratData,\n} from \"@macrostrat/data-provider\";\nimport { Duration } from \"./unit-details\";\nimport { Value } from \"@macrostrat/data-components\";\nimport type { ExtUnit, PackageScaleLayoutData } from \"./prepare-units/types\";\n\nconst h = hyper.styled(styles);\n\nexport interface SectionSharedProps {\n unitComponent?: FunctionComponent<any>;\n unitComponentProps?: any;\n showLabels?: boolean;\n width?: number;\n columnWidth?: number;\n children?: ReactNode;\n showLabelColumn?: boolean;\n axisType?: ColumnAxisType;\n className?: string;\n clipUnits?: boolean;\n maxInternalColumns?: number;\n // Space between sections\n verticalSpacing?: number;\n // Whether to render unconformity labels\n unconformityLabels?: boolean;\n}\n\nexport interface SectionProps extends SectionSharedProps {\n units: ExtUnit[];\n scaleInfo: PackageScaleLayoutData;\n}\n\nexport function SectionsColumn(props: SectionSharedProps) {\n const {\n unconformityLabels = true,\n unitComponent,\n unitComponentProps,\n showLabels = true,\n width = 300,\n columnWidth = 150,\n showLabelColumn = true,\n clipUnits = true,\n maxInternalColumns,\n } = props;\n\n const units = useMacrostratUnits();\n\n // Get a unique key for the column\n const key = units[0]?.col_id;\n\n return h(LabelTrackerProvider, { units, key }, [\n h(SectionUnitsColumn, {\n width: columnWidth,\n unitComponent,\n unitComponentProps,\n showLabels,\n clipUnits,\n maxInternalColumns,\n unconformityLabels,\n }),\n h.if(showLabelColumn)(SectionLabelsColumn, {\n width: width - columnWidth,\n }),\n ]);\n}\n\nfunction SectionUnitsColumn(props: SectionSharedProps) {\n const {\n width,\n showLabels,\n unitComponent,\n unitComponentProps,\n clipUnits,\n maxInternalColumns,\n axisType,\n unconformityLabels = true,\n } = props;\n\n const { sections, totalHeight } = useMacrostratColumnData();\n\n const scaleData: PackageScaleLayoutData[] = sections.map((section) => {\n return section.scaleInfo;\n });\n\n const innerWidth = width - 2;\n\n return h(\"div.section-units-container\", { style: { width } }, [\n h(\n SVG,\n {\n className: \"sections\",\n height: totalHeight,\n innerWidth,\n paddingH: 1,\n },\n sections.map((group) => {\n const { units, scaleInfo, section_id } = group;\n\n const key = `section-${section_id}`;\n return h(\n SectionUnits,\n {\n units,\n scaleInfo,\n key,\n unitComponent,\n unitComponentProps,\n showLabels,\n width: innerWidth,\n clipUnits,\n maxInternalColumns,\n }, // This unconformity is with the section _above_\n );\n }),\n ),\n h.if(unconformityLabels)(UnconformityLabels, {\n width,\n sections: scaleData,\n verbose: false,\n }),\n ]);\n}\n\nfunction SectionUnits(props: SectionProps) {\n // Section with \"squishy\" timescale\n const {\n units,\n scaleInfo,\n unitComponent,\n showLabels = true,\n width = 300,\n unitComponentProps,\n className,\n clipUnits = true,\n maxInternalColumns,\n } = props;\n\n const { domain, pixelScale, pixelHeight, scale } = scaleInfo;\n\n /** Ensure that we can arrange units into the maximum number\n * of columns defined by unitComponentProps, but that we don't\n * use more than necessary.\n */\n const _unitComponentProps = useMemo(() => {\n return {\n ...unitComponentProps,\n nColumns: Math.min(\n maxInternalColumns ?? Math.floor(width / 10),\n unitComponentProps?.nColumns ?? Infinity,\n ),\n //axisType,\n };\n }, [units, unitComponentProps, maxInternalColumns, width]);\n\n const style = {\n \"--section-height\": `${pixelHeight}px`,\n \"--section-width\": `${width}px`,\n };\n\n return h(\n \"g.section\",\n { className, style, transform: `translate(0 ${scaleInfo.offset})` },\n h(\n MacrostratColumnProvider,\n {\n units,\n domain,\n pixelScale, // Actually pixels per myr,\n scale,\n },\n h(CompositeUnitsColumn, {\n width,\n showLabels,\n unitComponent,\n unitComponentProps: _unitComponentProps,\n clipToFrame: clipUnits,\n }),\n ),\n );\n}\n\ninterface CompositeTimescaleProps {\n levels?: [number, number] | number;\n unconformityLabels?: boolean;\n onClickInterval?: TimescaleClickHandler;\n /** Per-interval style (e.g. to highlight the currently selected interval). */\n intervalStyle?: IntervalStyleBuilder;\n}\n\nexport function CompositeTimescale(props: CompositeTimescaleProps) {\n const { sections } = useMacrostratColumnData();\n const sectionScales = sections.map((section) => {\n return section.scaleInfo;\n });\n\n return h(CompositeTimescaleCore, {\n packages: sectionScales,\n ...props,\n });\n}\n\ntype CompositeTimescaleCoreProps = CompositeTimescaleProps & {\n packages: PackageScaleLayoutData[];\n onClickInterval?: TimescaleClickHandler;\n};\n\nexport function CompositeTimescaleCore(props: CompositeTimescaleCoreProps) {\n const {\n levels = 3,\n packages,\n unconformityLabels = false,\n onClickInterval,\n intervalStyle,\n } = props;\n\n // Use intervals from Macrostrat API\n const baseURL = useMacrostratBaseURL();\n const intervals = useMacrostratIntervals({ baseURL });\n\n let _levels: [number, number];\n if (typeof levels === \"number\") {\n // If levels is a number, use the most common starting level\n _levels = [2, Math.max(2 + Math.min(levels, 5) - 1, 1)];\n } else {\n _levels = levels;\n }\n\n const nCols = _levels[1] - _levels[0] + 1;\n\n return h(\"div.timescale-column\", [\n h(\n \"div.timescales\",\n packages.map((group) => {\n const { pixelHeight, paddingTop, key, scale } = group;\n return h(\n \"div.timescale-container\",\n { style: { paddingTop, \"--timescale-level-count\": nCols }, key },\n [\n h(Timescale, {\n orientation: TimescaleOrientation.VERTICAL,\n length: pixelHeight,\n levels: _levels,\n absoluteAgeScale: true,\n showAgeAxis: false,\n scale,\n intervals,\n onClick: onClickInterval,\n intervalStyle,\n }),\n ],\n );\n }),\n ),\n h.if(unconformityLabels)(UnconformityLabels, {\n width: \"100%\",\n sections: packages,\n className: \"unconformity-labels\",\n axisType: ColumnAxisType.AGE,\n }),\n ]);\n}\n\nexport function UnconformityLabels(props: {\n width: string | number;\n sections: PackageScaleLayoutData[];\n axisType?: ColumnAxisType;\n className?: string;\n verbose?: boolean;\n}) {\n const { width, sections, className, axisType, verbose } = props;\n\n return h(\n \"div.unconformity-labels\",\n {\n style: {\n width,\n },\n className,\n },\n sections.map((scaleInfo, i) => {\n const lastGroup = sections[i - 1];\n const top = scaleInfo.offset - scaleInfo.paddingTop;\n const upperAge = lastGroup?.domain[0];\n const lowerAge = scaleInfo.domain[1];\n return h(Unconformity, {\n axisType,\n upperAge,\n lowerAge,\n style: {\n width,\n height: scaleInfo.paddingTop,\n top,\n },\n verbose,\n });\n }),\n );\n}\n\nfunction Unconformity({\n upperAge,\n lowerAge,\n style,\n axisType,\n verbose = false,\n}) {\n if (upperAge == null || lowerAge == null) {\n return null;\n }\n\n const ageGap = Math.abs(upperAge - lowerAge);\n\n let maximumFractionDigits = 0;\n\n let className: string = null;\n if (ageGap > 1000) {\n className = \"giga\";\n } else if (ageGap > 100) {\n className = \"mega\";\n } else if (ageGap > 10) {\n className = \"large\";\n } else if (ageGap < 1) {\n className = \"small\";\n maximumFractionDigits = 2;\n } else {\n maximumFractionDigits = 1;\n }\n\n let val: ReactNode;\n if (axisType === ColumnAxisType.DEPTH || axisType === ColumnAxisType.HEIGHT) {\n const _txt = ageGap.toLocaleString(\"en-US\", { maximumFractionDigits });\n val = h(Value, { value: _txt, unit: \"m\" });\n } else {\n val = h(Duration, { value: ageGap, maximumFractionDigits });\n }\n\n let prefix: ReactNode = null;\n if (verbose) {\n prefix = h([\" \", h(\"span.prefix\", \" gap\")]);\n }\n\n return h(\"div.unconformity\", { style, className }, [\n h(\"div.unconformity-inner\", h(\"div.unconformity-text\", [val, prefix])),\n ]);\n}\n"],"names":["hyper","styles","useMacrostratUnits","LabelTrackerProvider","SectionLabelsColumn","useMacrostratColumnData","SVG","useMemo","MacrostratColumnProvider","CompositeUnitsColumn","useMacrostratBaseURL","useMacrostratIntervals","Timescale","TimescaleOrientation","ColumnAxisType","Value","Duration"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"section.cjs","sources":["../src/section.ts"],"sourcesContent":["import {\n CompositeUnitsColumn,\n LabelTrackerProvider,\n SectionLabelsColumn,\n} from \"./units\";\nimport {\n type CSSProperties,\n ReactNode,\n FunctionComponent,\n useMemo,\n} from \"react\";\nimport {\n Timescale,\n TimescaleOrientation,\n useMacrostratTimescales,\n type Interval,\n type IntervalStyleBuilder,\n type TimescaleClickData,\n} from \"@macrostrat/timescale\";\n\n/** Macrostrat's international timescale, the default for a column */\nconst INTERNATIONAL_TIMESCALE_ID = 11;\nimport { ColumnAxisType, SVG } from \"@macrostrat/column-components\";\nimport hyper from \"@macrostrat/hyper\";\nimport styles from \"./column.module.sass\";\nimport {\n useMacrostratColumnData,\n useMacrostratUnits,\n MacrostratColumnProvider,\n} from \"./data-provider\";\nimport { Duration } from \"./unit-details\";\nimport { Value } from \"@macrostrat/data-components\";\nimport type { ExtUnit, PackageScaleLayoutData } from \"./prepare-units/types\";\n\nconst h = hyper.styled(styles);\n\nexport interface SectionSharedProps {\n unitComponent?: FunctionComponent<any>;\n unitComponentProps?: any;\n showLabels?: boolean;\n width?: number;\n columnWidth?: number;\n children?: ReactNode;\n showLabelColumn?: boolean;\n /** Suppress the label for a unit drawn thinner than this many pixels */\n labelSuppressHeight?: number;\n axisType?: ColumnAxisType;\n className?: string;\n clipUnits?: boolean;\n maxInternalColumns?: number;\n // Space between sections\n verticalSpacing?: number;\n // Whether to render unconformity labels\n unconformityLabels?: boolean;\n}\n\nexport interface SectionProps extends SectionSharedProps {\n units: ExtUnit[];\n scaleInfo: PackageScaleLayoutData;\n}\n\nexport function SectionsColumn(props: SectionSharedProps) {\n const {\n unconformityLabels = true,\n unitComponent,\n unitComponentProps,\n showLabels = true,\n width = 300,\n columnWidth = 150,\n showLabelColumn = true,\n clipUnits = true,\n maxInternalColumns,\n labelSuppressHeight,\n } = props;\n\n const units = useMacrostratUnits();\n\n // Get a unique key for the column\n const key = units[0]?.col_id;\n\n return h(LabelTrackerProvider, { units, key }, [\n h(SectionUnitsColumn, {\n width: columnWidth,\n unitComponent,\n unitComponentProps,\n showLabels,\n clipUnits,\n maxInternalColumns,\n unconformityLabels,\n }),\n h.if(showLabelColumn)(SectionLabelsColumn, {\n width: width - columnWidth,\n labelSuppressHeight,\n }),\n ]);\n}\n\nfunction SectionUnitsColumn(props: SectionSharedProps) {\n const {\n width,\n showLabels,\n unitComponent,\n unitComponentProps,\n clipUnits,\n maxInternalColumns,\n axisType,\n unconformityLabels = true,\n } = props;\n\n const { sections, totalHeight, axisType: columnAxisType } =\n useMacrostratColumnData();\n\n const scaleData: PackageScaleLayoutData[] = sections.map((section) => {\n return section.scaleInfo;\n });\n\n const innerWidth = width - 2;\n\n return h(\"div.section-units-container\", { style: { width } }, [\n h(\n SVG,\n {\n className: \"sections\",\n height: totalHeight,\n innerWidth,\n paddingH: 1,\n },\n sections.map((group) => {\n const { units, scaleInfo, section_id } = group;\n\n const key = `section-${section_id}`;\n return h(\n SectionUnits,\n {\n units,\n scaleInfo,\n key,\n unitComponent,\n unitComponentProps,\n showLabels,\n width: innerWidth,\n clipUnits,\n maxInternalColumns,\n }, // This unconformity is with the section _above_\n );\n }),\n ),\n h.if(unconformityLabels)(UnconformityLabels, {\n width,\n sections: scaleData,\n // A gap between sections is measured in whatever the axis is: metres\n // down a core, Myr across a time column\n axisType: axisType ?? columnAxisType,\n verbose: false,\n }),\n ]);\n}\n\nfunction SectionUnits(props: SectionProps) {\n // Section with \"squishy\" timescale\n const {\n units,\n scaleInfo,\n unitComponent,\n showLabels = true,\n width = 300,\n unitComponentProps,\n className,\n clipUnits = true,\n maxInternalColumns,\n } = props;\n\n const { domain, pixelScale, pixelHeight, scale } = scaleInfo;\n\n /** Ensure that we can arrange units into the maximum number\n * of columns defined by unitComponentProps, but that we don't\n * use more than necessary.\n */\n const _unitComponentProps = useMemo(() => {\n return {\n ...unitComponentProps,\n nColumns: Math.min(\n maxInternalColumns ?? Math.floor(width / 10),\n unitComponentProps?.nColumns ?? Infinity,\n ),\n //axisType,\n };\n }, [units, unitComponentProps, maxInternalColumns, width]);\n\n const style = {\n \"--section-height\": `${pixelHeight}px`,\n \"--section-width\": `${width}px`,\n };\n\n return h(\n \"g.section\",\n { className, style, transform: `translate(0 ${scaleInfo.offset})` },\n h(\n MacrostratColumnProvider,\n {\n units,\n domain,\n pixelScale, // Actually pixels per myr,\n scale,\n },\n h(CompositeUnitsColumn, {\n width,\n showLabels,\n unitComponent,\n unitComponentProps: _unitComponentProps,\n clipToFrame: clipUnits,\n }),\n ),\n );\n}\n\n/** A per-interval style that also knows which timescale the interval was\n * drawn from. The same interval often appears in several of the timescales\n * beside each other, and they aren't interchangeable — only one of them is\n * the one a selection was made in. */\nexport type ColumnIntervalStyleBuilder =\n | CSSProperties\n | ((interval: Interval, timescaleID: number) => CSSProperties)\n | null;\n\n/** A timescale click, reporting which timescale was clicked in */\nexport type ColumnTimescaleClickHandler = (\n event: Event,\n data: TimescaleClickData & { timescaleID: number },\n) => void;\n\n/** A timescale to draw beside a column.\n *\n * The international timescale is one of these, not a special case: it is the\n * one that happens to be nested several levels deep. Anything with the same\n * shape can take its place or sit beside it — a regional set from the API, a\n * zonation assembled locally, or a hierarchy that isn't a timescale at all,\n * so long as its \"intervals\" carry ages.\n */\nexport interface ColumnTimescale {\n /** Integer identifier. Clicks and per-interval styles report it, so a\n * consumer can tell one column's copy of an interval from another's. For a\n * Macrostrat timescale it is the `timescale_id`. */\n id: number;\n /** Shown above the column, unless `label` says otherwise */\n name?: string;\n /** The intervals themselves, flat or already nested by `pid`. Left out,\n * the timescale `id` is fetched from the Macrostrat API. */\n intervals?: Interval[];\n /** Levels to draw, and so how many slots wide the column is (default\n * `[1, 1]`: one level, which is what a flat timescale has) */\n levels?: [number, number];\n /** `oid` of the interval the tree hangs from (default 0) */\n rootInterval?: number;\n /** Drawn above the column in place of the name — any node, so a consumer\n * can put a control or a legend there instead of text */\n label?: ReactNode;\n}\n\nexport type ColumnTimescaleLike = number | ColumnTimescale;\n\ninterface CompositeTimescaleProps {\n /** Every timescale to draw, in order. A bare number is a Macrostrat\n * timescale to fetch and draw as a single level.\n *\n * Given this, `levels`, `timescaleID` and `additionalTimescales` are\n * ignored: it says what they say and more. */\n timescales?: ColumnTimescaleLike[];\n /** Levels of the ICS hierarchy to show. If a number, the finest level is\n * `levels[0]`, the second-finest is `levels[1]`, etc. If an array, the\n * first element is the starting level, the second is the ending level. */\n levels?: [number, number] | number;\n unconformityLabels?: boolean;\n onClickInterval?: ColumnTimescaleClickHandler;\n /** Per-interval style (e.g. to highlight the currently selected interval). */\n intervalStyle?: ColumnIntervalStyleBuilder;\n /** The timescale to draw. Defaults to the international one; any other\n * Macrostrat timescale (a regional or project-specific set of intervals)\n * can be drawn in its place. */\n timescaleID?: number;\n /** Further timescales drawn as extra level columns beside the main one,\n * against the same scale. Shorthand for listing them in `timescales`. */\n additionalTimescales?: number[];\n /** Draw the names above the columns. They sit above the column proper, so\n * leave top padding for them. */\n showLabels?: boolean;\n className?: string;\n}\n\nexport function CompositeTimescale(props: CompositeTimescaleProps) {\n const { sections } = useMacrostratColumnData();\n const sectionScales = sections.map((section) => {\n return section.scaleInfo;\n });\n\n return h(CompositeTimescaleCore, {\n packages: sectionScales,\n ...props,\n });\n}\n\ntype CompositeTimescaleCoreProps = CompositeTimescaleProps & {\n packages: PackageScaleLayoutData[];\n};\n\n/** What is drawn above a timescale: its name, reading up the page, or\n * whatever node the consumer gave instead. */\nfunction TimescaleLabel({ timescale }: { timescale: ColumnTimescale }) {\n const { label, name } = timescale;\n const style = levelCountStyle(levelCount(timescale));\n\n let content: ReactNode = label;\n if (label == null && name != null) {\n content = h(\"span.timescale-label-text\", name);\n }\n if (content == null) return h(\"div.timescale-label\", { style });\n\n return h(\"div.timescale-label\", { style }, content);\n}\n\n/** How wide a timescale draws: one slot per level it shows. */\nfunction levelCountStyle(levelCount: number): CSSProperties {\n return { \"--timescale-level-count\": levelCount } as CSSProperties;\n}\n\nexport function CompositeTimescaleCore(props: CompositeTimescaleCoreProps) {\n const {\n packages,\n unconformityLabels = false,\n onClickInterval,\n intervalStyle,\n showLabels = false,\n className,\n } = props;\n\n const timescales = useColumnTimescales(props);\n\n /** Clicks and styles carry the timescale they came from, so a consumer can\n * tell one column's copy of an interval from another's. */\n function forTimescale(id: number) {\n let onClick = null;\n if (onClickInterval != null) {\n onClick = (event: Event, data: TimescaleClickData) => {\n onClickInterval(event, { ...data, timescaleID: id });\n };\n }\n let style = intervalStyle as IntervalStyleBuilder;\n if (typeof intervalStyle === \"function\") {\n style = (interval: Interval) => intervalStyle(interval, id);\n }\n return { onClick, intervalStyle: style };\n }\n\n return h(\"div.timescale-column\", { className }, [\n h.if(showLabels)(\n \"div.timescale-labels\",\n timescales.map((timescale) =>\n h(TimescaleLabel, { key: timescale.id, timescale }),\n ),\n ),\n h(\n \"div.timescales\",\n packages.map((group) => {\n const { pixelHeight, paddingTop, key, scale } = group;\n return h(\n \"div.section-timescales\",\n { style: { paddingTop }, key },\n timescales.map((timescale) =>\n h(Timescale, {\n key: timescale.id,\n orientation: TimescaleOrientation.VERTICAL,\n length: pixelHeight,\n levels: timescale.levels,\n rootInterval: timescale.rootInterval,\n absoluteAgeScale: true,\n showAgeAxis: false,\n scale,\n intervals: timescale.intervals,\n style: levelCountStyle(levelCount(timescale)),\n ...forTimescale(timescale.id),\n }),\n ),\n );\n }),\n ),\n h.if(unconformityLabels)(UnconformityLabels, {\n width: \"100%\",\n sections: packages,\n className: \"unconformity-labels\",\n axisType: ColumnAxisType.AGE,\n }),\n ]);\n}\n\n/** The timescales to draw, with their intervals.\n *\n * Every timescale a column draws is fetched in one place: a column is split\n * into sections, and fetching per section would ask for the same timescale\n * once per section per timescale.\n */\nfunction useColumnTimescales(props: CompositeTimescaleProps): ColumnTimescale[] {\n const { timescales, levels = 3, timescaleID, additionalTimescales } = props;\n\n const specs = useMemo(\n () => timescaleSpecs({ timescales, levels, timescaleID, additionalTimescales }),\n [\n timescales,\n levels,\n timescaleID,\n additionalTimescales?.join(\",\"),\n ],\n );\n\n // Only the ones that didn't come with their own intervals need fetching\n const fetchIDs = useMemo(\n () => specs.filter((d) => d.intervals == null).map((d) => d.id),\n [specs],\n );\n const intervalSets = useMacrostratTimescales(fetchIDs);\n\n return useMemo(\n () =>\n specs.map((spec) => ({\n ...spec,\n intervals: spec.intervals ?? intervalSets.get(spec.id) ?? [],\n })),\n [specs, intervalSets],\n );\n}\n\n/** The `timescales` list, or one built from the older props that name the\n * leveled timescale and the flat ones beside it. */\nfunction timescaleSpecs(props: CompositeTimescaleProps): ColumnTimescale[] {\n const { timescales, levels = 3, timescaleID, additionalTimescales = [] } = props;\n\n if (timescales != null) {\n return timescales.map(normalizeTimescale);\n }\n\n return [\n {\n id: timescaleID ?? INTERNATIONAL_TIMESCALE_ID,\n levels: levelRange(levels),\n },\n ...additionalTimescales.map(normalizeTimescale),\n ];\n}\n\nfunction normalizeTimescale(timescale: ColumnTimescaleLike): ColumnTimescale {\n if (typeof timescale === \"number\") {\n return { id: timescale, levels: FLAT_TIMESCALE_LEVELS };\n }\n return { levels: FLAT_TIMESCALE_LEVELS, ...timescale };\n}\n\n/** Regional and project timescales come back flat: one level of intervals. */\nconst FLAT_TIMESCALE_LEVELS: [number, number] = [1, 1];\n\nfunction levelRange(levels: [number, number] | number): [number, number] {\n if (typeof levels !== \"number\") return levels;\n // A count, rather than a range: start at the level most columns start at\n return [2, Math.max(2 + Math.min(levels, 5) - 1, 1)];\n}\n\n/** How many slots wide a timescale draws: one per level it shows. */\nfunction levelCount(timescale: ColumnTimescale): number {\n const [min, max] = timescale.levels ?? FLAT_TIMESCALE_LEVELS;\n return Math.max(max - min + 1, 1);\n}\n\nexport function UnconformityLabels(props: {\n width: string | number;\n sections: PackageScaleLayoutData[];\n axisType?: ColumnAxisType;\n className?: string;\n verbose?: boolean;\n}) {\n const { width, sections, className, axisType, verbose } = props;\n\n return h(\n \"div.unconformity-labels\",\n {\n style: {\n width,\n },\n className,\n },\n sections.map((scaleInfo, i) => {\n const lastGroup = sections[i - 1];\n const top = scaleInfo.offset - scaleInfo.paddingTop;\n const upperAge = lastGroup?.domain[0];\n const lowerAge = scaleInfo.domain[1];\n return h(Unconformity, {\n axisType,\n upperAge,\n lowerAge,\n style: {\n width,\n height: scaleInfo.paddingTop,\n top,\n },\n verbose,\n });\n }),\n );\n}\n\nfunction Unconformity({\n upperAge,\n lowerAge,\n style,\n axisType,\n verbose = false,\n}) {\n if (upperAge == null || lowerAge == null) {\n return null;\n }\n\n const ageGap = Math.abs(upperAge - lowerAge);\n\n let maximumFractionDigits = 0;\n\n let className: string = null;\n if (ageGap > 1000) {\n className = \"giga\";\n } else if (ageGap > 100) {\n className = \"mega\";\n } else if (ageGap > 10) {\n className = \"large\";\n } else if (ageGap < 1) {\n className = \"small\";\n maximumFractionDigits = 2;\n } else {\n maximumFractionDigits = 1;\n }\n\n let val: ReactNode;\n if (axisType === ColumnAxisType.DEPTH || axisType === ColumnAxisType.HEIGHT) {\n const _txt = ageGap.toLocaleString(\"en-US\", { maximumFractionDigits });\n val = h(Value, { value: _txt, unit: \"m\" });\n } else {\n val = h(Duration, { value: ageGap, maximumFractionDigits });\n }\n\n let prefix: ReactNode = null;\n if (verbose) {\n prefix = h([\" \", h(\"span.prefix\", \" gap\")]);\n }\n\n return h(\"div.unconformity\", { style, className }, [\n h(\"div.unconformity-inner\", h(\"div.unconformity-text\", [val, prefix])),\n ]);\n}\n"],"names":["hyper","styles","useMacrostratUnits","LabelTrackerProvider","SectionLabelsColumn","useMacrostratColumnData","SVG","useMemo","MacrostratColumnProvider","CompositeUnitsColumn","timescale","levelCount","Timescale","TimescaleOrientation","ColumnAxisType","useMacrostratTimescales","Value","Duration"],"mappings":"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"}
|
package/dist/section.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReactNode, FunctionComponent } from 'react';
|
|
2
|
-
import {
|
|
1
|
+
import { CSSProperties, ReactNode, FunctionComponent } from 'react';
|
|
2
|
+
import { Interval, TimescaleClickData } from '@macrostrat/timescale';
|
|
3
3
|
import { ColumnAxisType } from '@macrostrat/column-components';
|
|
4
4
|
import { ExtUnit, PackageScaleLayoutData } from './prepare-units/types';
|
|
5
5
|
export interface SectionSharedProps {
|
|
@@ -10,6 +10,8 @@ export interface SectionSharedProps {
|
|
|
10
10
|
columnWidth?: number;
|
|
11
11
|
children?: ReactNode;
|
|
12
12
|
showLabelColumn?: boolean;
|
|
13
|
+
/** Suppress the label for a unit drawn thinner than this many pixels */
|
|
14
|
+
labelSuppressHeight?: number;
|
|
13
15
|
axisType?: ColumnAxisType;
|
|
14
16
|
className?: string;
|
|
15
17
|
clipUnits?: boolean;
|
|
@@ -22,19 +24,77 @@ export interface SectionProps extends SectionSharedProps {
|
|
|
22
24
|
scaleInfo: PackageScaleLayoutData;
|
|
23
25
|
}
|
|
24
26
|
export declare function SectionsColumn(props: SectionSharedProps): import('react').FunctionComponentElement<any>;
|
|
27
|
+
/** A per-interval style that also knows which timescale the interval was
|
|
28
|
+
* drawn from. The same interval often appears in several of the timescales
|
|
29
|
+
* beside each other, and they aren't interchangeable — only one of them is
|
|
30
|
+
* the one a selection was made in. */
|
|
31
|
+
export type ColumnIntervalStyleBuilder = CSSProperties | ((interval: Interval, timescaleID: number) => CSSProperties) | null;
|
|
32
|
+
/** A timescale click, reporting which timescale was clicked in */
|
|
33
|
+
export type ColumnTimescaleClickHandler = (event: Event, data: TimescaleClickData & {
|
|
34
|
+
timescaleID: number;
|
|
35
|
+
}) => void;
|
|
36
|
+
/** A timescale to draw beside a column.
|
|
37
|
+
*
|
|
38
|
+
* The international timescale is one of these, not a special case: it is the
|
|
39
|
+
* one that happens to be nested several levels deep. Anything with the same
|
|
40
|
+
* shape can take its place or sit beside it — a regional set from the API, a
|
|
41
|
+
* zonation assembled locally, or a hierarchy that isn't a timescale at all,
|
|
42
|
+
* so long as its "intervals" carry ages.
|
|
43
|
+
*/
|
|
44
|
+
export interface ColumnTimescale {
|
|
45
|
+
/** Integer identifier. Clicks and per-interval styles report it, so a
|
|
46
|
+
* consumer can tell one column's copy of an interval from another's. For a
|
|
47
|
+
* Macrostrat timescale it is the `timescale_id`. */
|
|
48
|
+
id: number;
|
|
49
|
+
/** Shown above the column, unless `label` says otherwise */
|
|
50
|
+
name?: string;
|
|
51
|
+
/** The intervals themselves, flat or already nested by `pid`. Left out,
|
|
52
|
+
* the timescale `id` is fetched from the Macrostrat API. */
|
|
53
|
+
intervals?: Interval[];
|
|
54
|
+
/** Levels to draw, and so how many slots wide the column is (default
|
|
55
|
+
* `[1, 1]`: one level, which is what a flat timescale has) */
|
|
56
|
+
levels?: [number, number];
|
|
57
|
+
/** `oid` of the interval the tree hangs from (default 0) */
|
|
58
|
+
rootInterval?: number;
|
|
59
|
+
/** Drawn above the column in place of the name — any node, so a consumer
|
|
60
|
+
* can put a control or a legend there instead of text */
|
|
61
|
+
label?: ReactNode;
|
|
62
|
+
}
|
|
63
|
+
export type ColumnTimescaleLike = number | ColumnTimescale;
|
|
25
64
|
interface CompositeTimescaleProps {
|
|
65
|
+
/** Every timescale to draw, in order. A bare number is a Macrostrat
|
|
66
|
+
* timescale to fetch and draw as a single level.
|
|
67
|
+
*
|
|
68
|
+
* Given this, `levels`, `timescaleID` and `additionalTimescales` are
|
|
69
|
+
* ignored: it says what they say and more. */
|
|
70
|
+
timescales?: ColumnTimescaleLike[];
|
|
71
|
+
/** Levels of the ICS hierarchy to show. If a number, the finest level is
|
|
72
|
+
* `levels[0]`, the second-finest is `levels[1]`, etc. If an array, the
|
|
73
|
+
* first element is the starting level, the second is the ending level. */
|
|
26
74
|
levels?: [number, number] | number;
|
|
27
75
|
unconformityLabels?: boolean;
|
|
28
|
-
onClickInterval?:
|
|
76
|
+
onClickInterval?: ColumnTimescaleClickHandler;
|
|
29
77
|
/** Per-interval style (e.g. to highlight the currently selected interval). */
|
|
30
|
-
intervalStyle?:
|
|
78
|
+
intervalStyle?: ColumnIntervalStyleBuilder;
|
|
79
|
+
/** The timescale to draw. Defaults to the international one; any other
|
|
80
|
+
* Macrostrat timescale (a regional or project-specific set of intervals)
|
|
81
|
+
* can be drawn in its place. */
|
|
82
|
+
timescaleID?: number;
|
|
83
|
+
/** Further timescales drawn as extra level columns beside the main one,
|
|
84
|
+
* against the same scale. Shorthand for listing them in `timescales`. */
|
|
85
|
+
additionalTimescales?: number[];
|
|
86
|
+
/** Draw the names above the columns. They sit above the column proper, so
|
|
87
|
+
* leave top padding for them. */
|
|
88
|
+
showLabels?: boolean;
|
|
89
|
+
className?: string;
|
|
31
90
|
}
|
|
32
91
|
export declare function CompositeTimescale(props: CompositeTimescaleProps): import('react').FunctionComponentElement<CompositeTimescaleCoreProps>;
|
|
33
92
|
type CompositeTimescaleCoreProps = CompositeTimescaleProps & {
|
|
34
93
|
packages: PackageScaleLayoutData[];
|
|
35
|
-
onClickInterval?: TimescaleClickHandler;
|
|
36
94
|
};
|
|
37
|
-
export declare function CompositeTimescaleCore(props: CompositeTimescaleCoreProps): import('react').
|
|
95
|
+
export declare function CompositeTimescaleCore(props: CompositeTimescaleCoreProps): import('react').ReactElement<{
|
|
96
|
+
className: string | undefined;
|
|
97
|
+
}, string | import('react').JSXElementConstructor<any>>;
|
|
38
98
|
export declare function UnconformityLabels(props: {
|
|
39
99
|
width: string | number;
|
|
40
100
|
sections: PackageScaleLayoutData[];
|