@macrostrat/column-views 3.12.0 → 3.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/age-axis.cjs +1 -2
- package/dist/age-axis.cjs.map +1 -1
- package/dist/age-axis.js +1 -2
- package/dist/age-axis.js.map +1 -1
- package/dist/age-model/details.cjs +2 -3
- package/dist/age-model/details.cjs.map +1 -1
- package/dist/age-model/details.js +2 -3
- package/dist/age-model/details.js.map +1 -1
- package/dist/age-model/surfaces.cjs +1 -2
- package/dist/age-model/surfaces.cjs.map +1 -1
- package/dist/age-model/surfaces.js +1 -2
- package/dist/age-model/surfaces.js.map +1 -1
- package/dist/column-views.css +17 -17
- package/dist/column.cjs +11 -1
- package/dist/column.cjs.map +1 -1
- package/dist/column.js +11 -1
- package/dist/column.js.map +1 -1
- package/dist/index.cjs +25 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/prepare-units/composite-scale.cjs +16 -6
- package/dist/prepare-units/composite-scale.cjs.map +1 -1
- package/dist/prepare-units/composite-scale.d.ts +1 -1
- package/dist/prepare-units/composite-scale.js +16 -6
- package/dist/prepare-units/composite-scale.js.map +1 -1
- package/dist/prepare-units/density.cjs +21 -13
- package/dist/prepare-units/density.cjs.map +1 -1
- package/dist/prepare-units/density.d.ts +18 -11
- package/dist/prepare-units/density.js +21 -13
- package/dist/prepare-units/density.js.map +1 -1
- package/dist/prepare-units/helpers.cjs +16 -1
- package/dist/prepare-units/helpers.cjs.map +1 -1
- package/dist/prepare-units/helpers.js +16 -1
- package/dist/prepare-units/helpers.js.map +1 -1
- package/dist/prepare-units/index.cjs.map +1 -1
- package/dist/prepare-units/index.js.map +1 -1
- package/dist/unit-details/age-range.cjs +14 -44
- package/dist/unit-details/age-range.cjs.map +1 -1
- package/dist/unit-details/age-range.d.ts +2 -18
- package/dist/unit-details/age-range.js +6 -44
- package/dist/unit-details/age-range.js.map +1 -1
- package/dist/unit-details/utils.cjs +0 -5
- package/dist/unit-details/utils.cjs.map +1 -1
- package/dist/unit-details/utils.js +0 -5
- package/dist/unit-details/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/age-model/details.ts +2 -2
- package/src/age-model/surfaces.ts +2 -2
- package/src/column.ts +17 -1
- package/src/prepare-units/composite-scale.ts +22 -9
- package/src/prepare-units/density.ts +36 -25
- package/src/prepare-units/helpers.ts +35 -1
- package/src/prepare-units/index.ts +0 -1
- package/src/unit-details/age-range.ts +13 -59
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surfaces.js","sources":["../../src/age-model/surfaces.ts"],"sourcesContent":["/** The surfaces view: age-model calibration surfaces drawn on a column.\n *\n * `ColumnSurfaces` is dropped into a `Column` as a child. It draws one line\n * per surface across the units (`ColumnSurfaceLines`) and a notes column of\n * labels beside them (`ColumnSurfaceLabels`), styled by `boundary_status` and\n * `boundary_type`, with hover and selection.\n */\nimport hyper from \"@macrostrat/hyper\";\nimport classNames from \"classnames\";\nimport {\n type CSSProperties,\n type RefObject,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { NoteData } from \"@macrostrat/column-components\";\nimport {\n type IntervalShort,\n IntervalTag,\n TagSize,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport {\n useClaimLabelColumn,\n useCompositeScale,\n useMacrostratColumnData,\n} from \"../data-provider\";\nimport { ColumnNotes } from \"../notes\";\nimport { AgeLabel, Proportion } from \"../unit-details/age-range\";\nimport columnStyles from \"../column.module.sass\";\nimport styles from \"./surfaces.module.sass\";\nimport {\n type ColumnSurface,\n type SurfaceStatus,\n formatProportion,\n surfaceLabel,\n surfacePosition,\n surfaceStatusLabels,\n surfaceToken,\n TIE_POINT_STATUSES,\n} from \"./types\";\nimport { type UseColumnSurfacesOptions, useColumnSurfaces } from \"./data\";\n\nconst h = hyper.styled(styles);\n\n/** How far the surface lines extend: across the units column only, or the\n * full width of the column including its axes. */\nexport type SurfaceLinesExtent = \"units\" | \"column\";\n\nexport type SurfaceSelectionHandler = (surface: ColumnSurface | null) => void;\n\nexport interface SurfaceSelectionProps {\n /** The selected surface's id. Pass `null` for a controlled, empty\n * selection; leave undefined for the component to manage selection. */\n selectedSurface?: ColumnSurface[\"id\"] | null;\n onSelectSurface?: SurfaceSelectionHandler;\n}\n\nexport interface ColumnSurfacesProps\n extends UseColumnSurfacesOptions, SurfaceSelectionProps {\n showLines?: boolean;\n showLabels?: boolean;\n extent?: SurfaceLinesExtent;\n /** Width of the labels column, connector included (default 200) */\n labelWidth?: number;\n labelPaddingLeft?: number;\n /** Only show surfaces with these statuses */\n statuses?: SurfaceStatus[] | null;\n /** Which surfaces get a label. Defaults to the tie points — the statuses\n * at which the age model was constrained — so interpolated (`modeled`),\n * unspecified and unit-derived surfaces are drawn as lines only. Pass\n * `null` to label every surface shown. */\n labelStatuses?: SurfaceStatus[] | null;\n /** Labels closer than this (in pixels) are thinned out, since the column\n * has finite room; the selected surface's label is always kept. */\n minLabelSpacing?: number;\n className?: string;\n}\n\nexport function ColumnSurfaces(props: ColumnSurfacesProps) {\n const {\n showLines = true,\n showLabels = true,\n extent = \"units\",\n labelWidth,\n labelPaddingLeft,\n statuses,\n labelStatuses = TIE_POINT_STATUSES,\n minLabelSpacing,\n selectedSurface,\n onSelectSurface,\n className,\n ...dataOptions\n } = props;\n\n const { surfaces: allSurfaces } = useColumnSurfaces(dataOptions);\n const surfaces = useMemo(\n () => filterByStatus(allSurfaces, statuses),\n [allSurfaces, statuses],\n );\n\n const [selectedID, select] = useSurfaceSelection(\n selectedSurface,\n onSelectSurface,\n );\n\n return h([\n h.if(showLines)(ColumnSurfaceLines, {\n surfaces,\n extent,\n selectedSurface: selectedID,\n onSelectSurface: select,\n className,\n }),\n h.if(showLabels)(ColumnSurfaceLabels, {\n surfaces,\n labelStatuses,\n minLabelSpacing,\n width: labelWidth,\n paddingLeft: labelPaddingLeft,\n selectedSurface: selectedID,\n onSelectSurface: select,\n className,\n }),\n ]);\n}\n\nexport interface ColumnSurfaceLinesProps extends SurfaceSelectionProps {\n surfaces: ColumnSurface[];\n extent?: SurfaceLinesExtent;\n className?: string;\n}\n\n/** One horizontal line per surface, overlaid on the column at the surface's\n * age (or measured position, for height and depth columns). */\nexport function ColumnSurfaceLines(props: ColumnSurfaceLinesProps) {\n const {\n surfaces,\n extent = \"units\",\n selectedSurface,\n onSelectSurface,\n className,\n } = props;\n const scale = useCompositeScale();\n const { axisType, totalHeight } = useMacrostratColumnData();\n const intervalMap = useSurfaceIntervalDefs(surfaces);\n\n const ref = useRef<HTMLDivElement>(null);\n const unitsExtent = useUnitsColumnExtent(ref, extent === \"units\");\n\n let style: CSSProperties = { height: totalHeight };\n if (unitsExtent != null) {\n style = { ...style, left: unitsExtent.left, width: unitsExtent.width };\n }\n const measuring = extent === \"units\" && unitsExtent == null;\n\n return h(\n \"div.column-surface-lines\",\n { ref, style, className: classNames(className, { measuring }) },\n surfaces.map((surface) => {\n const position = surfacePosition(surface, axisType);\n if (position == null) return null;\n const y = scale(position);\n if (y == null) return null;\n return h(SurfaceLine, {\n key: surface.id,\n surface,\n y,\n color: surfaceIntervalColor(surface, intervalMap),\n selected: surface.id === selectedSurface,\n onSelect: onSelectSurface,\n });\n }),\n );\n}\n\nfunction SurfaceLine({\n surface,\n y,\n color,\n selected,\n onSelect,\n}: {\n surface: ColumnSurface;\n y: number;\n /** The interval color, when known; otherwise the status color is used */\n color?: string | null;\n selected: boolean;\n onSelect?: SurfaceSelectionHandler;\n}) {\n const onClick = useCallback(\n (evt: MouseEvent) => {\n // Don't let the column deselect its unit\n evt.stopPropagation();\n if (selected) {\n onSelect?.(null);\n } else {\n onSelect?.(surface);\n }\n },\n [surface, selected, onSelect],\n );\n\n let style: CSSProperties = { top: y };\n if (color != null) {\n style = { ...style, \"--surface-color\": color } as CSSProperties;\n }\n\n return h(\n \"div.surface-line\",\n {\n style,\n className: classNames(surfaceClasses(surface), {\n selected,\n interactive: onSelect != null,\n }),\n title: surfaceLabel(surface),\n onClick,\n },\n h(\"div.surface-line-inner\"),\n );\n}\n\nexport interface ColumnSurfaceLabelsProps extends SurfaceSelectionProps {\n surfaces: ColumnSurface[];\n /** Which surfaces get a label (see `ColumnSurfacesProps.labelStatuses`) */\n labelStatuses?: SurfaceStatus[] | null;\n /** Minimum pixel spacing between labels (see `ColumnSurfacesProps`) */\n minLabelSpacing?: number;\n /** Total width, connector included */\n width?: number;\n paddingLeft?: number;\n className?: string;\n}\n\ninterface SurfaceNote extends NoteData {\n /** The interval color, which the note's connector picks up */\n color?: string;\n surface: ColumnSurface;\n /** The calibration interval, with color and rank from the definitions */\n interval: IntervalShort | null;\n selected: boolean;\n}\n\n/** A notes column of surface labels, laid out beside the units with the\n * collision avoidance of `NotesColumn`. It takes the label column over from\n * the unit labels while mounted: labels are one or the other. */\nexport function ColumnSurfaceLabels(props: ColumnSurfaceLabelsProps) {\n const {\n surfaces,\n labelStatuses = TIE_POINT_STATUSES,\n minLabelSpacing = 22,\n width = 200,\n paddingLeft = 24,\n selectedSurface,\n onSelectSurface,\n className,\n } = props;\n const { axisType } = useMacrostratColumnData();\n const scale = useCompositeScale();\n const intervalMap = useSurfaceIntervalDefs(surfaces);\n useClaimLabelColumn();\n\n const labeled = useMemo(() => {\n const byStatus = filterByStatus(surfaces, labelStatuses);\n return thinByPixelSpacing(\n byStatus,\n (s) => scale(surfacePosition(s, axisType) ?? NaN),\n minLabelSpacing,\n selectedSurface,\n );\n }, [\n surfaces,\n labelStatuses,\n minLabelSpacing,\n selectedSurface,\n scale,\n axisType,\n ]);\n\n const notes: SurfaceNote[] = useMemo(() => {\n const _notes: SurfaceNote[] = [];\n for (const surface of labeled) {\n const position = surfacePosition(surface, axisType);\n if (position == null) continue;\n _notes.push({\n id: surface.id,\n height: position,\n note: surfaceLabel(surface),\n // The note's color reaches its connector, so a label's leader line\n // matches the surface line it points at\n color: surfaceIntervalColor(surface, intervalMap) ?? undefined,\n surface,\n interval: calibrationInterval(surface, intervalMap),\n selected: surface.id === selectedSurface,\n });\n }\n return _notes;\n }, [labeled, axisType, selectedSurface, intervalMap]);\n\n const onClickNote = useCallback(\n (note: NoteData) => {\n const { surface, selected } = note as SurfaceNote;\n if (selected) {\n onSelectSurface?.(null);\n } else {\n onSelectSurface?.(surface);\n }\n },\n [onSelectSurface],\n );\n\n return h(\n \"div.column-surface-labels\",\n { className },\n h(ColumnNotes, {\n notes,\n width,\n paddingLeft,\n noteComponent: SurfaceNoteLabel,\n onClickNote,\n forceOptions: LABEL_FORCE_OPTIONS,\n // The leader runs from the surface line in the column to the tag body,\n // continuing a little past both ends rather than stopping in the gap —\n // so it needs no endpoint marker of its own\n connectorOverhang: LABEL_CONNECTOR_OVERHANG,\n showPointMarker: false,\n }),\n );\n}\n\n/** Breathing room between stacked labels, in pixels */\nconst LABEL_FORCE_OPTIONS = { nodeSpacing: 2 };\n\n/** How far the label's leader line continues past each end, in pixels: left\n * into the column to meet the surface line, right under the tag body. */\nconst LABEL_CONNECTOR_OVERHANG: [number, number] = [8, 6];\n\n/** A surface's label: its calibration interval as the standard interval tag\n * (with the position within the interval as the tag's detail), and the\n * modeled age beneath. Surfaces without a calibration show their status. */\nfunction SurfaceNoteLabel({ note }: { note: SurfaceNote }) {\n const { surface, interval, selected } = note;\n\n let primary: any;\n if (interval != null) {\n primary = h(IntervalTag, {\n interval,\n size: TagSize.Small,\n prefix: h(Proportion, { value: surface.proportion }),\n className: \"surface-interval-tag\",\n });\n } else {\n primary = h(\n \"span.surface-label-status\",\n `${surfaceStatusLabels[surface.status]} surface`,\n );\n }\n\n return h(\n \"div.surface-label\",\n { className: classNames(surfaceClasses(surface), { selected }) },\n h(\"div.surface-label-primary\", primary),\n );\n}\n\n/** The interval definitions for the surfaces' calibration intervals. The age\n * model carries interval ids and names but no colors, so they come from the\n * definitions store (which holds them all, and fetches once). */\nfunction useSurfaceIntervalDefs(\n surfaces: ColumnSurface[],\n): Map<number, any> | null {\n const intervalIDs = useMemo(() => {\n const ids = new Set<number>();\n for (const surface of surfaces) {\n if (surface.calibration != null) ids.add(surface.calibration.id);\n }\n return Array.from(ids);\n }, [surfaces]);\n return useMacrostratDefs(\"intervals\", intervalIDs, null);\n}\n\n/** The color a surface is drawn in: its calibration interval's, so the line\n * and its label's leader read as the interval the surface is tied to. `null`\n * for an uncalibrated surface, or before the definitions load — the status\n * color stands in. */\nfunction surfaceIntervalColor(\n surface: ColumnSurface,\n intervalMap: Map<number, any> | null,\n): string | null {\n const id = surface.calibration?.id;\n if (id == null) return null;\n return intervalMap?.get(id)?.color ?? null;\n}\n\n/** The calibration interval in the shape the interval tag takes, colored\n * from the definitions when they have loaded. */\nfunction calibrationInterval(\n surface: ColumnSurface,\n intervalMap: Map<number, any> | null,\n): IntervalShort | null {\n const { calibration } = surface;\n if (calibration == null) return null;\n const def = intervalMap?.get(calibration.id);\n return {\n id: calibration.id,\n name: calibration.name,\n b_age: calibration.b_age,\n t_age: calibration.t_age,\n color: def?.color,\n rank: def?.rank,\n };\n}\n\n/** Class names shared by the lines, labels, legend and tags, so a status or\n * type reads the same everywhere. */\nexport function surfaceClasses(surface: {\n status?: SurfaceStatus | null;\n type?: string | null;\n}): string {\n return classNames(\n `status-${surfaceToken(surface.status)}`,\n `type-${surfaceToken(surface.type)}`,\n );\n}\n\n/** Walk the surfaces down the column and drop any whose label would sit\n * within `minSpacing` pixels of the last one kept. The selected surface is\n * always kept (and displaces a neighbor if need be). */\nfunction thinByPixelSpacing(\n surfaces: ColumnSurface[],\n pixelPosition: (s: ColumnSurface) => number | null,\n minSpacing: number,\n selectedSurface: ColumnSurface[\"id\"] | null | undefined,\n): ColumnSurface[] {\n if (minSpacing <= 0) return surfaces;\n const positioned = surfaces\n .map((surface) => ({ surface, y: pixelPosition(surface) }))\n .filter((d) => d.y != null && !Number.isNaN(d.y))\n .sort((a, b) => a.y - b.y);\n\n const kept: { surface: ColumnSurface; y: number }[] = [];\n for (const item of positioned) {\n const selected = item.surface.id === selectedSurface;\n const last = kept[kept.length - 1];\n if (last == null || item.y - last.y >= minSpacing) {\n kept.push(item);\n } else if (selected) {\n // The selection wins its slot\n kept[kept.length - 1] = item;\n }\n }\n return kept.map((d) => d.surface);\n}\n\nfunction filterByStatus(\n surfaces: ColumnSurface[],\n statuses: SurfaceStatus[] | null | undefined,\n): ColumnSurface[] {\n if (statuses == null) return surfaces;\n const allowed = new Set(statuses);\n return surfaces.filter((d) => allowed.has(d.status));\n}\n\n/** Controlled-or-uncontrolled selection: when `selectedID` is passed (even as\n * `null`) the consumer owns it; otherwise it is kept internally. */\nfunction useSurfaceSelection(\n selectedID: ColumnSurface[\"id\"] | null | undefined,\n onSelect: SurfaceSelectionHandler | undefined,\n): [ColumnSurface[\"id\"] | null, SurfaceSelectionHandler] {\n const [internal, setInternal] = useState<ColumnSurface[\"id\"] | null>(null);\n const isControlled = selectedID !== undefined;\n\n const select: SurfaceSelectionHandler = useCallback(\n (surface) => {\n setInternal(surface?.id ?? null);\n onSelect?.(surface);\n },\n [onSelect],\n );\n\n let current = internal;\n if (isControlled) {\n current = selectedID;\n }\n return [current, select];\n}\n\ninterface HorizontalExtent {\n left: number;\n width: number;\n}\n\n/** `useLayoutEffect` in the browser, `useEffect` on the server — where it\n * would warn and has nothing to measure anyway. */\nconst useMeasureEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\n/** Measure where the units column sits within the `Column`, so an overlay\n * can cover exactly the units rather than the axes. `null` while unmeasured,\n * when disabled, or when the units column can't be found. */\nfunction useUnitsColumnExtent(\n ref: RefObject<HTMLDivElement | null>,\n enabled: boolean,\n): HorizontalExtent | null {\n const [extent, setExtent] = useState<HorizontalExtent | null>(null);\n\n const measure = useCallback(() => {\n if (!enabled) return;\n const parent = ref.current?.parentElement;\n const target = parent?.querySelector<HTMLElement>(\n `.${unitsContainerClass()}`,\n );\n if (parent == null || target == null) return;\n\n const p = parent.getBoundingClientRect();\n const t = target.getBoundingClientRect();\n const next = { left: t.left - p.left, width: t.width };\n setExtent((prev) => {\n if (prev?.left === next.left && prev?.width === next.width) {\n return prev;\n }\n return next;\n });\n }, [enabled]);\n\n // Re-measure on every render as a backstop: cheap, and it catches layout\n // changes that no observer reports.\n useMeasureEffect(measure);\n\n useMeasureEffect(() => {\n if (!enabled) {\n setExtent(null);\n return;\n }\n const parent = ref.current?.parentElement;\n if (parent == null) return;\n if (typeof ResizeObserver === \"undefined\") return;\n\n const observer = new ResizeObserver(measure);\n // The units column *moves* when a sibling changes width — the timescale\n // widening once its intervals load, or its level count changing — and\n // that is not a resize of the units column or of the column itself, so\n // the siblings have to be watched too.\n observer.observe(parent);\n for (const child of Array.from(parent.children)) {\n observer.observe(child);\n }\n return () => observer.disconnect();\n }, [enabled, measure]);\n\n return extent;\n}\n\n/** The (module-scoped) class of the units container rendered by\n * `SectionsColumn`. */\nfunction unitsContainerClass(): string {\n const s = columnStyles as any;\n return (\n s[\"section-units-container\"] ??\n s.sectionUnitsContainer ??\n \"section-units-container\"\n );\n}\n"],"names":["hyper","styles","columnStyles"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"surfaces.js","sources":["../../src/age-model/surfaces.ts"],"sourcesContent":["/** The surfaces view: age-model calibration surfaces drawn on a column.\n *\n * `ColumnSurfaces` is dropped into a `Column` as a child. It draws one line\n * per surface across the units (`ColumnSurfaceLines`) and a notes column of\n * labels beside them (`ColumnSurfaceLabels`), styled by `boundary_status` and\n * `boundary_type`, with hover and selection.\n */\nimport hyper from \"@macrostrat/hyper\";\nimport classNames from \"classnames\";\nimport {\n type CSSProperties,\n type RefObject,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { NoteData } from \"@macrostrat/column-components\";\nimport {\n type IntervalShort,\n IntervalTag,\n TagSize,\n} from \"@macrostrat/data-components\";\nimport { useMacrostratDefs } from \"@macrostrat/data-provider\";\nimport {\n useClaimLabelColumn,\n useCompositeScale,\n useMacrostratColumnData,\n} from \"../data-provider\";\nimport { ColumnNotes } from \"../notes\";\nimport { AgeLabel } from \"../unit-details/age-range\";\nimport columnStyles from \"../column.module.sass\";\nimport styles from \"./surfaces.module.sass\";\nimport {\n type ColumnSurface,\n type SurfaceStatus,\n formatProportion,\n surfaceLabel,\n surfacePosition,\n surfaceStatusLabels,\n surfaceToken,\n TIE_POINT_STATUSES,\n} from \"./types\";\nimport { type UseColumnSurfacesOptions, useColumnSurfaces } from \"./data\";\n\nconst h = hyper.styled(styles);\n\n/** How far the surface lines extend: across the units column only, or the\n * full width of the column including its axes. */\nexport type SurfaceLinesExtent = \"units\" | \"column\";\n\nexport type SurfaceSelectionHandler = (surface: ColumnSurface | null) => void;\n\nexport interface SurfaceSelectionProps {\n /** The selected surface's id. Pass `null` for a controlled, empty\n * selection; leave undefined for the component to manage selection. */\n selectedSurface?: ColumnSurface[\"id\"] | null;\n onSelectSurface?: SurfaceSelectionHandler;\n}\n\nexport interface ColumnSurfacesProps\n extends UseColumnSurfacesOptions, SurfaceSelectionProps {\n showLines?: boolean;\n showLabels?: boolean;\n extent?: SurfaceLinesExtent;\n /** Width of the labels column, connector included (default 200) */\n labelWidth?: number;\n labelPaddingLeft?: number;\n /** Only show surfaces with these statuses */\n statuses?: SurfaceStatus[] | null;\n /** Which surfaces get a label. Defaults to the tie points — the statuses\n * at which the age model was constrained — so interpolated (`modeled`),\n * unspecified and unit-derived surfaces are drawn as lines only. Pass\n * `null` to label every surface shown. */\n labelStatuses?: SurfaceStatus[] | null;\n /** Labels closer than this (in pixels) are thinned out, since the column\n * has finite room; the selected surface's label is always kept. */\n minLabelSpacing?: number;\n className?: string;\n}\n\nexport function ColumnSurfaces(props: ColumnSurfacesProps) {\n const {\n showLines = true,\n showLabels = true,\n extent = \"units\",\n labelWidth,\n labelPaddingLeft,\n statuses,\n labelStatuses = TIE_POINT_STATUSES,\n minLabelSpacing,\n selectedSurface,\n onSelectSurface,\n className,\n ...dataOptions\n } = props;\n\n const { surfaces: allSurfaces } = useColumnSurfaces(dataOptions);\n const surfaces = useMemo(\n () => filterByStatus(allSurfaces, statuses),\n [allSurfaces, statuses],\n );\n\n const [selectedID, select] = useSurfaceSelection(\n selectedSurface,\n onSelectSurface,\n );\n\n return h([\n h.if(showLines)(ColumnSurfaceLines, {\n surfaces,\n extent,\n selectedSurface: selectedID,\n onSelectSurface: select,\n className,\n }),\n h.if(showLabels)(ColumnSurfaceLabels, {\n surfaces,\n labelStatuses,\n minLabelSpacing,\n width: labelWidth,\n paddingLeft: labelPaddingLeft,\n selectedSurface: selectedID,\n onSelectSurface: select,\n className,\n }),\n ]);\n}\n\nexport interface ColumnSurfaceLinesProps extends SurfaceSelectionProps {\n surfaces: ColumnSurface[];\n extent?: SurfaceLinesExtent;\n className?: string;\n}\n\n/** One horizontal line per surface, overlaid on the column at the surface's\n * age (or measured position, for height and depth columns). */\nexport function ColumnSurfaceLines(props: ColumnSurfaceLinesProps) {\n const {\n surfaces,\n extent = \"units\",\n selectedSurface,\n onSelectSurface,\n className,\n } = props;\n const scale = useCompositeScale();\n const { axisType, totalHeight } = useMacrostratColumnData();\n const intervalMap = useSurfaceIntervalDefs(surfaces);\n\n const ref = useRef<HTMLDivElement>(null);\n const unitsExtent = useUnitsColumnExtent(ref, extent === \"units\");\n\n let style: CSSProperties = { height: totalHeight };\n if (unitsExtent != null) {\n style = { ...style, left: unitsExtent.left, width: unitsExtent.width };\n }\n const measuring = extent === \"units\" && unitsExtent == null;\n\n return h(\n \"div.column-surface-lines\",\n { ref, style, className: classNames(className, { measuring }) },\n surfaces.map((surface) => {\n const position = surfacePosition(surface, axisType);\n if (position == null) return null;\n const y = scale(position);\n if (y == null) return null;\n return h(SurfaceLine, {\n key: surface.id,\n surface,\n y,\n color: surfaceIntervalColor(surface, intervalMap),\n selected: surface.id === selectedSurface,\n onSelect: onSelectSurface,\n });\n }),\n );\n}\n\nfunction SurfaceLine({\n surface,\n y,\n color,\n selected,\n onSelect,\n}: {\n surface: ColumnSurface;\n y: number;\n /** The interval color, when known; otherwise the status color is used */\n color?: string | null;\n selected: boolean;\n onSelect?: SurfaceSelectionHandler;\n}) {\n const onClick = useCallback(\n (evt: MouseEvent) => {\n // Don't let the column deselect its unit\n evt.stopPropagation();\n if (selected) {\n onSelect?.(null);\n } else {\n onSelect?.(surface);\n }\n },\n [surface, selected, onSelect],\n );\n\n let style: CSSProperties = { top: y };\n if (color != null) {\n style = { ...style, \"--surface-color\": color } as CSSProperties;\n }\n\n return h(\n \"div.surface-line\",\n {\n style,\n className: classNames(surfaceClasses(surface), {\n selected,\n interactive: onSelect != null,\n }),\n title: surfaceLabel(surface),\n onClick,\n },\n h(\"div.surface-line-inner\"),\n );\n}\n\nexport interface ColumnSurfaceLabelsProps extends SurfaceSelectionProps {\n surfaces: ColumnSurface[];\n /** Which surfaces get a label (see `ColumnSurfacesProps.labelStatuses`) */\n labelStatuses?: SurfaceStatus[] | null;\n /** Minimum pixel spacing between labels (see `ColumnSurfacesProps`) */\n minLabelSpacing?: number;\n /** Total width, connector included */\n width?: number;\n paddingLeft?: number;\n className?: string;\n}\n\ninterface SurfaceNote extends NoteData {\n /** The interval color, which the note's connector picks up */\n color?: string;\n surface: ColumnSurface;\n /** The calibration interval, with color and rank from the definitions */\n interval: IntervalShort | null;\n selected: boolean;\n}\n\n/** A notes column of surface labels, laid out beside the units with the\n * collision avoidance of `NotesColumn`. It takes the label column over from\n * the unit labels while mounted: labels are one or the other. */\nexport function ColumnSurfaceLabels(props: ColumnSurfaceLabelsProps) {\n const {\n surfaces,\n labelStatuses = TIE_POINT_STATUSES,\n minLabelSpacing = 22,\n width = 200,\n paddingLeft = 24,\n selectedSurface,\n onSelectSurface,\n className,\n } = props;\n const { axisType } = useMacrostratColumnData();\n const scale = useCompositeScale();\n const intervalMap = useSurfaceIntervalDefs(surfaces);\n useClaimLabelColumn();\n\n const labeled = useMemo(() => {\n const byStatus = filterByStatus(surfaces, labelStatuses);\n return thinByPixelSpacing(\n byStatus,\n (s) => scale(surfacePosition(s, axisType) ?? NaN),\n minLabelSpacing,\n selectedSurface,\n );\n }, [\n surfaces,\n labelStatuses,\n minLabelSpacing,\n selectedSurface,\n scale,\n axisType,\n ]);\n\n const notes: SurfaceNote[] = useMemo(() => {\n const _notes: SurfaceNote[] = [];\n for (const surface of labeled) {\n const position = surfacePosition(surface, axisType);\n if (position == null) continue;\n _notes.push({\n id: surface.id,\n height: position,\n note: surfaceLabel(surface),\n // The note's color reaches its connector, so a label's leader line\n // matches the surface line it points at\n color: surfaceIntervalColor(surface, intervalMap) ?? undefined,\n surface,\n interval: calibrationInterval(surface, intervalMap),\n selected: surface.id === selectedSurface,\n });\n }\n return _notes;\n }, [labeled, axisType, selectedSurface, intervalMap]);\n\n const onClickNote = useCallback(\n (note: NoteData) => {\n const { surface, selected } = note as SurfaceNote;\n if (selected) {\n onSelectSurface?.(null);\n } else {\n onSelectSurface?.(surface);\n }\n },\n [onSelectSurface],\n );\n\n return h(\n \"div.column-surface-labels\",\n { className },\n h(ColumnNotes, {\n notes,\n width,\n paddingLeft,\n noteComponent: SurfaceNoteLabel,\n onClickNote,\n forceOptions: LABEL_FORCE_OPTIONS,\n // The leader runs from the surface line in the column to the tag body,\n // continuing a little past both ends rather than stopping in the gap —\n // so it needs no endpoint marker of its own\n connectorOverhang: LABEL_CONNECTOR_OVERHANG,\n showPointMarker: false,\n }),\n );\n}\n\n/** Breathing room between stacked labels, in pixels */\nconst LABEL_FORCE_OPTIONS = { nodeSpacing: 2 };\n\n/** How far the label's leader line continues past each end, in pixels: left\n * into the column to meet the surface line, right under the tag body. */\nconst LABEL_CONNECTOR_OVERHANG: [number, number] = [8, 6];\n\n/** A surface's label: its calibration interval as the standard interval tag\n * (with the position within the interval as the tag's detail), and the\n * modeled age beneath. Surfaces without a calibration show their status. */\nfunction SurfaceNoteLabel({ note }: { note: SurfaceNote }) {\n const { surface, interval, selected } = note;\n\n let primary: any;\n if (interval != null) {\n primary = h(IntervalTag, {\n interval,\n size: TagSize.Small,\n proportion: surface.proportion,\n className: \"surface-interval-tag\",\n });\n } else {\n primary = h(\n \"span.surface-label-status\",\n `${surfaceStatusLabels[surface.status]} surface`,\n );\n }\n\n return h(\n \"div.surface-label\",\n { className: classNames(surfaceClasses(surface), { selected }) },\n h(\"div.surface-label-primary\", primary),\n );\n}\n\n/** The interval definitions for the surfaces' calibration intervals. The age\n * model carries interval ids and names but no colors, so they come from the\n * definitions store (which holds them all, and fetches once). */\nfunction useSurfaceIntervalDefs(\n surfaces: ColumnSurface[],\n): Map<number, any> | null {\n const intervalIDs = useMemo(() => {\n const ids = new Set<number>();\n for (const surface of surfaces) {\n if (surface.calibration != null) ids.add(surface.calibration.id);\n }\n return Array.from(ids);\n }, [surfaces]);\n return useMacrostratDefs(\"intervals\", intervalIDs, null);\n}\n\n/** The color a surface is drawn in: its calibration interval's, so the line\n * and its label's leader read as the interval the surface is tied to. `null`\n * for an uncalibrated surface, or before the definitions load — the status\n * color stands in. */\nfunction surfaceIntervalColor(\n surface: ColumnSurface,\n intervalMap: Map<number, any> | null,\n): string | null {\n const id = surface.calibration?.id;\n if (id == null) return null;\n return intervalMap?.get(id)?.color ?? null;\n}\n\n/** The calibration interval in the shape the interval tag takes, colored\n * from the definitions when they have loaded. */\nfunction calibrationInterval(\n surface: ColumnSurface,\n intervalMap: Map<number, any> | null,\n): IntervalShort | null {\n const { calibration } = surface;\n if (calibration == null) return null;\n const def = intervalMap?.get(calibration.id);\n return {\n id: calibration.id,\n name: calibration.name,\n b_age: calibration.b_age,\n t_age: calibration.t_age,\n color: def?.color,\n rank: def?.rank,\n };\n}\n\n/** Class names shared by the lines, labels, legend and tags, so a status or\n * type reads the same everywhere. */\nexport function surfaceClasses(surface: {\n status?: SurfaceStatus | null;\n type?: string | null;\n}): string {\n return classNames(\n `status-${surfaceToken(surface.status)}`,\n `type-${surfaceToken(surface.type)}`,\n );\n}\n\n/** Walk the surfaces down the column and drop any whose label would sit\n * within `minSpacing` pixels of the last one kept. The selected surface is\n * always kept (and displaces a neighbor if need be). */\nfunction thinByPixelSpacing(\n surfaces: ColumnSurface[],\n pixelPosition: (s: ColumnSurface) => number | null,\n minSpacing: number,\n selectedSurface: ColumnSurface[\"id\"] | null | undefined,\n): ColumnSurface[] {\n if (minSpacing <= 0) return surfaces;\n const positioned = surfaces\n .map((surface) => ({ surface, y: pixelPosition(surface) }))\n .filter((d) => d.y != null && !Number.isNaN(d.y))\n .sort((a, b) => a.y - b.y);\n\n const kept: { surface: ColumnSurface; y: number }[] = [];\n for (const item of positioned) {\n const selected = item.surface.id === selectedSurface;\n const last = kept[kept.length - 1];\n if (last == null || item.y - last.y >= minSpacing) {\n kept.push(item);\n } else if (selected) {\n // The selection wins its slot\n kept[kept.length - 1] = item;\n }\n }\n return kept.map((d) => d.surface);\n}\n\nfunction filterByStatus(\n surfaces: ColumnSurface[],\n statuses: SurfaceStatus[] | null | undefined,\n): ColumnSurface[] {\n if (statuses == null) return surfaces;\n const allowed = new Set(statuses);\n return surfaces.filter((d) => allowed.has(d.status));\n}\n\n/** Controlled-or-uncontrolled selection: when `selectedID` is passed (even as\n * `null`) the consumer owns it; otherwise it is kept internally. */\nfunction useSurfaceSelection(\n selectedID: ColumnSurface[\"id\"] | null | undefined,\n onSelect: SurfaceSelectionHandler | undefined,\n): [ColumnSurface[\"id\"] | null, SurfaceSelectionHandler] {\n const [internal, setInternal] = useState<ColumnSurface[\"id\"] | null>(null);\n const isControlled = selectedID !== undefined;\n\n const select: SurfaceSelectionHandler = useCallback(\n (surface) => {\n setInternal(surface?.id ?? null);\n onSelect?.(surface);\n },\n [onSelect],\n );\n\n let current = internal;\n if (isControlled) {\n current = selectedID;\n }\n return [current, select];\n}\n\ninterface HorizontalExtent {\n left: number;\n width: number;\n}\n\n/** `useLayoutEffect` in the browser, `useEffect` on the server — where it\n * would warn and has nothing to measure anyway. */\nconst useMeasureEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\n/** Measure where the units column sits within the `Column`, so an overlay\n * can cover exactly the units rather than the axes. `null` while unmeasured,\n * when disabled, or when the units column can't be found. */\nfunction useUnitsColumnExtent(\n ref: RefObject<HTMLDivElement | null>,\n enabled: boolean,\n): HorizontalExtent | null {\n const [extent, setExtent] = useState<HorizontalExtent | null>(null);\n\n const measure = useCallback(() => {\n if (!enabled) return;\n const parent = ref.current?.parentElement;\n const target = parent?.querySelector<HTMLElement>(\n `.${unitsContainerClass()}`,\n );\n if (parent == null || target == null) return;\n\n const p = parent.getBoundingClientRect();\n const t = target.getBoundingClientRect();\n const next = { left: t.left - p.left, width: t.width };\n setExtent((prev) => {\n if (prev?.left === next.left && prev?.width === next.width) {\n return prev;\n }\n return next;\n });\n }, [enabled]);\n\n // Re-measure on every render as a backstop: cheap, and it catches layout\n // changes that no observer reports.\n useMeasureEffect(measure);\n\n useMeasureEffect(() => {\n if (!enabled) {\n setExtent(null);\n return;\n }\n const parent = ref.current?.parentElement;\n if (parent == null) return;\n if (typeof ResizeObserver === \"undefined\") return;\n\n const observer = new ResizeObserver(measure);\n // The units column *moves* when a sibling changes width — the timescale\n // widening once its intervals load, or its level count changing — and\n // that is not a resize of the units column or of the column itself, so\n // the siblings have to be watched too.\n observer.observe(parent);\n for (const child of Array.from(parent.children)) {\n observer.observe(child);\n }\n return () => observer.disconnect();\n }, [enabled, measure]);\n\n return extent;\n}\n\n/** The (module-scoped) class of the units container rendered by\n * `SectionsColumn`. */\nfunction unitsContainerClass(): string {\n const s = columnStyles as any;\n return (\n s[\"section-units-container\"] ??\n s.sectionUnitsContainer ??\n \"section-units-container\"\n );\n}\n"],"names":["hyper","styles","columnStyles"],"mappings":";;;;;;;;;;;AA+CA,MAAM,IAAIA,IAAM,OAAOC,GAAM;AAoCtB,SAAS,eAAe,OAA4B;AACzD,QAAM;AAAA,IACJ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,IACD;AAEJ,QAAM,EAAE,UAAU,gBAAgB,kBAAkB,WAAW;AAC/D,QAAM,WAAW;AAAA,IACf,MAAM,eAAe,aAAa,QAAQ;AAAA,IAC1C,CAAC,aAAa,QAAQ;AAAA,EAAA;AAGxB,QAAM,CAAC,YAAY,MAAM,IAAI;AAAA,IAC3B;AAAA,IACA;AAAA,EAAA;AAGF,SAAO,EAAE;AAAA,IACP,EAAE,GAAG,SAAS,EAAE,oBAAoB;AAAA,MAClC;AAAA,MACA;AAAA,MACA,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB;AAAA,IAAA,CACD;AAAA,IACD,EAAE,GAAG,UAAU,EAAE,qBAAqB;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,aAAa;AAAA,MACb,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB;AAAA,IAAA,CACD;AAAA,EAAA,CACF;AACH;AAUO,SAAS,mBAAmB,OAAgC;AACjE,QAAM;AAAA,IACJ;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACE;AACJ,QAAM,QAAQ,kBAAA;AACd,QAAM,EAAE,UAAU,YAAA,IAAgB,wBAAA;AAClC,QAAM,cAAc,uBAAuB,QAAQ;AAEnD,QAAM,MAAM,OAAuB,IAAI;AACvC,QAAM,cAAc,qBAAqB,KAAK,WAAW,OAAO;AAEhE,MAAI,QAAuB,EAAE,QAAQ,YAAA;AACrC,MAAI,eAAe,MAAM;AACvB,YAAQ,EAAE,GAAG,OAAO,MAAM,YAAY,MAAM,OAAO,YAAY,MAAA;AAAA,EACjE;AACA,QAAM,YAAY,WAAW,WAAW,eAAe;AAEvD,SAAO;AAAA,IACL;AAAA,IACA,EAAE,KAAK,OAAO,WAAW,WAAW,WAAW,EAAE,UAAA,CAAW,EAAA;AAAA,IAC5D,SAAS,IAAI,CAAC,YAAY;AACxB,YAAM,WAAW,gBAAgB,SAAS,QAAQ;AAClD,UAAI,YAAY,KAAM,QAAO;AAC7B,YAAM,IAAI,MAAM,QAAQ;AACxB,UAAI,KAAK,KAAM,QAAO;AACtB,aAAO,EAAE,aAAa;AAAA,QACpB,KAAK,QAAQ;AAAA,QACb;AAAA,QACA;AAAA,QACA,OAAO,qBAAqB,SAAS,WAAW;AAAA,QAChD,UAAU,QAAQ,OAAO;AAAA,QACzB,UAAU;AAAA,MAAA,CACX;AAAA,IACH,CAAC;AAAA,EAAA;AAEL;AAEA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,UAAU;AAAA,IACd,CAAC,QAAoB;AAEnB,UAAI,gBAAA;AACJ,UAAI,UAAU;AACZ,mBAAW,IAAI;AAAA,MACjB,OAAO;AACL,mBAAW,OAAO;AAAA,MACpB;AAAA,IACF;AAAA,IACA,CAAC,SAAS,UAAU,QAAQ;AAAA,EAAA;AAG9B,MAAI,QAAuB,EAAE,KAAK,EAAA;AAClC,MAAI,SAAS,MAAM;AACjB,YAAQ,EAAE,GAAG,OAAO,mBAAmB,MAAA;AAAA,EACzC;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE;AAAA,MACA,WAAW,WAAW,eAAe,OAAO,GAAG;AAAA,QAC7C;AAAA,QACA,aAAa,YAAY;AAAA,MAAA,CAC1B;AAAA,MACD,OAAO,aAAa,OAAO;AAAA,MAC3B;AAAA,IAAA;AAAA,IAEF,EAAE,wBAAwB;AAAA,EAAA;AAE9B;AA0BO,SAAS,oBAAoB,OAAiC;AACnE,QAAM;AAAA,IACJ;AAAA,IACA,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACE;AACJ,QAAM,EAAE,SAAA,IAAa,wBAAA;AACrB,QAAM,QAAQ,kBAAA;AACd,QAAM,cAAc,uBAAuB,QAAQ;AACnD,sBAAA;AAEA,QAAM,UAAU,QAAQ,MAAM;AAC5B,UAAM,WAAW,eAAe,UAAU,aAAa;AACvD,WAAO;AAAA,MACL;AAAA,MACA,CAAC,MAAM,MAAM,gBAAgB,GAAG,QAAQ,KAAK,GAAG;AAAA,MAChD;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AAED,QAAM,QAAuB,QAAQ,MAAM;AACzC,UAAM,SAAwB,CAAA;AAC9B,eAAW,WAAW,SAAS;AAC7B,YAAM,WAAW,gBAAgB,SAAS,QAAQ;AAClD,UAAI,YAAY,KAAM;AACtB,aAAO,KAAK;AAAA,QACV,IAAI,QAAQ;AAAA,QACZ,QAAQ;AAAA,QACR,MAAM,aAAa,OAAO;AAAA;AAAA;AAAA,QAG1B,OAAO,qBAAqB,SAAS,WAAW,KAAK;AAAA,QACrD;AAAA,QACA,UAAU,oBAAoB,SAAS,WAAW;AAAA,QAClD,UAAU,QAAQ,OAAO;AAAA,MAAA,CAC1B;AAAA,IACH;AACA,WAAO;AAAA,EACT,GAAG,CAAC,SAAS,UAAU,iBAAiB,WAAW,CAAC;AAEpD,QAAM,cAAc;AAAA,IAClB,CAAC,SAAmB;AAClB,YAAM,EAAE,SAAS,SAAA,IAAa;AAC9B,UAAI,UAAU;AACZ,0BAAkB,IAAI;AAAA,MACxB,OAAO;AACL,0BAAkB,OAAO;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,CAAC,eAAe;AAAA,EAAA;AAGlB,SAAO;AAAA,IACL;AAAA,IACA,EAAE,UAAA;AAAA,IACF,EAAE,aAAa;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe;AAAA,MACf;AAAA,MACA,cAAc;AAAA;AAAA;AAAA;AAAA,MAId,mBAAmB;AAAA,MACnB,iBAAiB;AAAA,IAAA,CAClB;AAAA,EAAA;AAEL;AAGA,MAAM,sBAAsB,EAAE,aAAa,EAAA;AAI3C,MAAM,2BAA6C,CAAC,GAAG,CAAC;AAKxD,SAAS,iBAAiB,EAAE,QAA+B;AACzD,QAAM,EAAE,SAAS,UAAU,SAAA,IAAa;AAExC,MAAI;AACJ,MAAI,YAAY,MAAM;AACpB,cAAU,EAAE,aAAa;AAAA,MACvB;AAAA,MACA,MAAM,QAAQ;AAAA,MACd,YAAY,QAAQ;AAAA,MACpB,WAAW;AAAA,IAAA,CACZ;AAAA,EACH,OAAO;AACL,cAAU;AAAA,MACR;AAAA,MACA,GAAG,oBAAoB,QAAQ,MAAM,CAAC;AAAA,IAAA;AAAA,EAE1C;AAEA,SAAO;AAAA,IACL;AAAA,IACA,EAAE,WAAW,WAAW,eAAe,OAAO,GAAG,EAAE,SAAA,CAAU,EAAA;AAAA,IAC7D,EAAE,6BAA6B,OAAO;AAAA,EAAA;AAE1C;AAKA,SAAS,uBACP,UACyB;AACzB,QAAM,cAAc,QAAQ,MAAM;AAChC,UAAM,0BAAU,IAAA;AAChB,eAAW,WAAW,UAAU;AAC9B,UAAI,QAAQ,eAAe,UAAU,IAAI,QAAQ,YAAY,EAAE;AAAA,IACjE;AACA,WAAO,MAAM,KAAK,GAAG;AAAA,EACvB,GAAG,CAAC,QAAQ,CAAC;AACb,SAAO,kBAAkB,aAAa,aAAa,IAAI;AACzD;AAMA,SAAS,qBACP,SACA,aACe;AACf,QAAM,KAAK,QAAQ,aAAa;AAChC,MAAI,MAAM,KAAM,QAAO;AACvB,SAAO,aAAa,IAAI,EAAE,GAAG,SAAS;AACxC;AAIA,SAAS,oBACP,SACA,aACsB;AACtB,QAAM,EAAE,gBAAgB;AACxB,MAAI,eAAe,KAAM,QAAO;AAChC,QAAM,MAAM,aAAa,IAAI,YAAY,EAAE;AAC3C,SAAO;AAAA,IACL,IAAI,YAAY;AAAA,IAChB,MAAM,YAAY;AAAA,IAClB,OAAO,YAAY;AAAA,IACnB,OAAO,YAAY;AAAA,IACnB,OAAO,KAAK;AAAA,IACZ,MAAM,KAAK;AAAA,EAAA;AAEf;AAIO,SAAS,eAAe,SAGpB;AACT,SAAO;AAAA,IACL,UAAU,aAAa,QAAQ,MAAM,CAAC;AAAA,IACtC,QAAQ,aAAa,QAAQ,IAAI,CAAC;AAAA,EAAA;AAEtC;AAKA,SAAS,mBACP,UACA,eACA,YACA,iBACiB;AACjB,MAAI,cAAc,EAAG,QAAO;AAC5B,QAAM,aAAa,SAChB,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,cAAc,OAAO,EAAA,EAAI,EACzD,OAAO,CAAC,MAAM,EAAE,KAAK,QAAQ,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC,EAC/C,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC;AAE3B,QAAM,OAAgD,CAAA;AACtD,aAAW,QAAQ,YAAY;AAC7B,UAAM,WAAW,KAAK,QAAQ,OAAO;AACrC,UAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AACjC,QAAI,QAAQ,QAAQ,KAAK,IAAI,KAAK,KAAK,YAAY;AACjD,WAAK,KAAK,IAAI;AAAA,IAChB,WAAW,UAAU;AAEnB,WAAK,KAAK,SAAS,CAAC,IAAI;AAAA,IAC1B;AAAA,EACF;AACA,SAAO,KAAK,IAAI,CAAC,MAAM,EAAE,OAAO;AAClC;AAEA,SAAS,eACP,UACA,UACiB;AACjB,MAAI,YAAY,KAAM,QAAO;AAC7B,QAAM,UAAU,IAAI,IAAI,QAAQ;AAChC,SAAO,SAAS,OAAO,CAAC,MAAM,QAAQ,IAAI,EAAE,MAAM,CAAC;AACrD;AAIA,SAAS,oBACP,YACA,UACuD;AACvD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAqC,IAAI;AACzE,QAAM,eAAe,eAAe;AAEpC,QAAM,SAAkC;AAAA,IACtC,CAAC,YAAY;AACX,kBAAY,SAAS,MAAM,IAAI;AAC/B,iBAAW,OAAO;AAAA,IACpB;AAAA,IACA,CAAC,QAAQ;AAAA,EAAA;AAGX,MAAI,UAAU;AACd,MAAI,cAAc;AAChB,cAAU;AAAA,EACZ;AACA,SAAO,CAAC,SAAS,MAAM;AACzB;AASA,MAAM,mBACJ,OAAO,WAAW,cAAc,YAAY;AAK9C,SAAS,qBACP,KACA,SACyB;AACzB,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAkC,IAAI;AAElE,QAAM,UAAU,YAAY,MAAM;AAChC,QAAI,CAAC,QAAS;AACd,UAAM,SAAS,IAAI,SAAS;AAC5B,UAAM,SAAS,QAAQ;AAAA,MACrB,IAAI,qBAAqB;AAAA,IAAA;AAE3B,QAAI,UAAU,QAAQ,UAAU,KAAM;AAEtC,UAAM,IAAI,OAAO,sBAAA;AACjB,UAAM,IAAI,OAAO,sBAAA;AACjB,UAAM,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,EAAE,MAAA;AAC/C,cAAU,CAAC,SAAS;AAClB,UAAI,MAAM,SAAS,KAAK,QAAQ,MAAM,UAAU,KAAK,OAAO;AAC1D,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,OAAO,CAAC;AAIZ,mBAAiB,OAAO;AAExB,mBAAiB,MAAM;AACrB,QAAI,CAAC,SAAS;AACZ,gBAAU,IAAI;AACd;AAAA,IACF;AACA,UAAM,SAAS,IAAI,SAAS;AAC5B,QAAI,UAAU,KAAM;AACpB,QAAI,OAAO,mBAAmB,YAAa;AAE3C,UAAM,WAAW,IAAI,eAAe,OAAO;AAK3C,aAAS,QAAQ,MAAM;AACvB,eAAW,SAAS,MAAM,KAAK,OAAO,QAAQ,GAAG;AAC/C,eAAS,QAAQ,KAAK;AAAA,IACxB;AACA,WAAO,MAAM,SAAS,WAAA;AAAA,EACxB,GAAG,CAAC,SAAS,OAAO,CAAC;AAErB,SAAO;AACT;AAIA,SAAS,sBAA8B;AACrC,QAAM,IAAIC;AACV,SACE,EAAE,yBAAyB,KAC3B,EAAE,yBACF;AAEJ;"}
|
package/dist/column-views.css
CHANGED
|
@@ -74,23 +74,6 @@
|
|
|
74
74
|
position: relative;
|
|
75
75
|
display: flex;
|
|
76
76
|
flex-direction: row;
|
|
77
|
-
}._interval-proportions_1ibvp_1 {
|
|
78
|
-
display: inline-flex;
|
|
79
|
-
flex-flow: row wrap;
|
|
80
|
-
gap: 0.5em;
|
|
81
|
-
text-align: right;
|
|
82
|
-
align-items: baseline;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
._interval-proportions_1ibvp_1, ._discourage-break_1ibvp_9 {
|
|
86
|
-
align-items: baseline;
|
|
87
|
-
white-space: nowrap;
|
|
88
|
-
display: inline-flex;
|
|
89
|
-
gap: 0.5em;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
._sep_1ibvp_16 {
|
|
93
|
-
color: var(--secondary-color);
|
|
94
77
|
}._column-container_hmbev_1, body.light-mode ._column-container_hmbev_1 {
|
|
95
78
|
--column-selection-color: var(--column-cursor-color, var(--pz-accent-color, #7961db));
|
|
96
79
|
--column-background-color: var(--background-color, #fff);
|
|
@@ -322,6 +305,23 @@ body.dark-mode ._column-container_hmbev_1 svg pattern image {
|
|
|
322
305
|
gap: 1em;
|
|
323
306
|
justify-content: space-between;
|
|
324
307
|
align-items: baseline;
|
|
308
|
+
}._interval-proportions_1ibvp_1 {
|
|
309
|
+
display: inline-flex;
|
|
310
|
+
flex-flow: row wrap;
|
|
311
|
+
gap: 0.5em;
|
|
312
|
+
text-align: right;
|
|
313
|
+
align-items: baseline;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
._interval-proportions_1ibvp_1, ._discourage-break_1ibvp_9 {
|
|
317
|
+
align-items: baseline;
|
|
318
|
+
white-space: nowrap;
|
|
319
|
+
display: inline-flex;
|
|
320
|
+
gap: 0.5em;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
._sep_1ibvp_16 {
|
|
324
|
+
color: var(--secondary-color);
|
|
325
325
|
}._popover-main_4jzei_1 {
|
|
326
326
|
position: absolute;
|
|
327
327
|
pointer-events: none;
|
package/dist/column.cjs
CHANGED
|
@@ -56,6 +56,16 @@ function Column(props) {
|
|
|
56
56
|
ageAxisComponent = ageAxis.ApproximateHeightAxis;
|
|
57
57
|
_axisType = columnComponents.ColumnAxisType.AGE;
|
|
58
58
|
}
|
|
59
|
+
let _sectionOptions = sectionOptions;
|
|
60
|
+
if (_sectionOptions == void 0) {
|
|
61
|
+
_sectionOptions = (ctx) => {
|
|
62
|
+
const n = ctx.units.length;
|
|
63
|
+
const expansionFactor = 8 / Math.min(Math.max(n, 1), 8);
|
|
64
|
+
return {
|
|
65
|
+
targetUnitHeight: targetUnitHeight * expansionFactor
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
}
|
|
59
69
|
const { sections, units, totalHeight } = index.usePreparedColumnUnits(rawUnits, {
|
|
60
70
|
axisType: _axisType,
|
|
61
71
|
t_age,
|
|
@@ -64,7 +74,7 @@ function Column(props) {
|
|
|
64
74
|
b_pos,
|
|
65
75
|
mergeSections,
|
|
66
76
|
targetUnitHeight,
|
|
67
|
-
sectionOptions,
|
|
77
|
+
sectionOptions: _sectionOptions,
|
|
68
78
|
unconformityHeight,
|
|
69
79
|
pixelScale,
|
|
70
80
|
pixelsPerMyr,
|
package/dist/column.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column.cjs","sources":["../src/column.ts"],"sourcesContent":["import { ColumnAxisType } from \"@macrostrat/column-components\";\nimport {\n Box,\n extractPadding,\n Padding,\n useDarkMode,\n} from \"@macrostrat/ui-components\";\nimport classNames from \"classnames\";\nimport {\n HTMLAttributes,\n useCallback,\n CSSProperties,\n ComponentType,\n RefObject,\n} from \"react\";\nimport h from \"./column.module.sass\";\nimport { UnitComponent } from \"./units\";\nimport {\n ColumnRef,\n UnitKeyboardNavigation,\n useColumnRef,\n useUnitSelectionDispatch,\n} from \"./data-provider\";\n\nimport {\n Identifier,\n ReferencesField,\n UnitSelectionPopover,\n} from \"./unit-details\";\nimport {\n MacrostratColumnDataProvider,\n useCompositeScale,\n useLabelColumnClaimed,\n useMacrostratColumnData,\n} from \"./data-provider\";\nimport {\n SectionSharedProps,\n CompositeTimescale,\n type ColumnIntervalStyleBuilder,\n type ColumnTimescaleClickHandler,\n type ColumnTimescaleLike,\n SectionsColumn,\n} from \"./section\";\nimport { ApproximateHeightAxis, CompositeAgeAxis } from \"./age-axis\";\nimport {\n MergeSectionsMode,\n usePreparedColumnUnits,\n HybridScaleType,\n ColumnHeightScaleOptions,\n} from \"./prepare-units\";\nimport { UnitLong } from \"@macrostrat/api-types\";\nimport { NonIdealState } from \"@blueprintjs/core\";\nimport { DataField } from \"@macrostrat/data-components\";\nimport { ScaleContinuousNumeric } from \"d3-scale\";\n\ninterface BaseColumnProps extends Omit<\n SectionSharedProps,\n \"unconformityLabels\"\n> {\n className?: string;\n showLabelColumn?: boolean;\n /** Suppress the label for a unit drawn thinner than this many pixels\n * (default 2) */\n labelSuppressHeight?: number;\n keyboardNavigation?: boolean;\n showLabels?: boolean;\n maxInternalColumns?: number;\n // Timescale properties\n showTimescale?: boolean;\n timescaleLevels?: number | [number, number];\n /** Regional or project timescales drawn as extra columns beside the\n * international one (see `CompositeTimescale`). Narrow `timescaleLevels` by\n * as many to swap the finest level for them rather than widen the column. */\n additionalTimescales?: number[];\n /** Every timescale to draw beside the column, in order: a Macrostrat\n * timescale ID, or a timescale with its own intervals (see\n * `CompositeTimescale`). Supersedes `timescaleLevels` and\n * `additionalTimescales`. */\n timescales?: ColumnTimescaleLike[];\n /** Draw each timescale's name above it */\n showTimescaleLabels?: boolean;\n /** Called when a timescale interval is clicked (e.g. to zoom the age range).\n * The data says which timescale it was clicked in. */\n onClickTimescaleInterval?: ColumnTimescaleClickHandler;\n /** Per-interval style for the timescale (e.g. to bold the selected\n * interval), by interval and the timescale it was drawn from. */\n timescaleIntervalStyle?: ColumnIntervalStyleBuilder;\n unconformityLabels?: boolean | UnconformityLabelPlacement;\n onMouseOver?: (\n unit: UnitLong | null,\n height: number | null,\n evt: MouseEvent,\n ) => void;\n}\n\nexport type UnconformityLabelPlacement = \"minimal\" | \"prominent\" | \"none\";\n\nexport interface ColumnProps\n extends Padding, BaseColumnProps, ColumnHeightScaleOptions {\n // Macrostrat units\n units: UnitLong[];\n t_age?: number;\n b_age?: number;\n t_pos?: number;\n b_pos?: number;\n mergeSections?: MergeSectionsMode;\n showUnitPopover?: boolean;\n allowUnitSelection?: boolean;\n selectedUnit?: number | null;\n onUnitSelected?: (unitID: number | null, unit: any) => void;\n // Unconformity height in pixels\n unconformityHeight?: number;\n scale?: ScaleContinuousNumeric<number, number>;\n /** True while the age window is animating (e.g. from `useAnimatedAgeWindow`),\n * so per-frame label/pattern recalculation can be skipped. */\n isTransitioning?: boolean;\n /** Hide unit labels while transitioning (perf escape hatch; default false —\n * labels stay visible through the animation). */\n hideLabelsWhileTransitioning?: boolean;\n ref?: RefObject<ColumnRef>;\n}\n\nexport function Column(props: ColumnProps) {\n const {\n showUnitPopover = false,\n keyboardNavigation = false,\n mergeSections,\n onUnitSelected,\n selectedUnit,\n children,\n units: rawUnits,\n t_age,\n b_age,\n t_pos,\n b_pos,\n unconformityHeight = 30,\n targetUnitHeight = 20,\n sectionOptions,\n pixelScale,\n pixelsPerMyr,\n pixelsPerMeter,\n minPixelScale = 0.2,\n minSectionHeight = 50,\n windowPadding = 0,\n collapseSmallUnconformities = true,\n allowUnitSelection = false,\n hybridScale,\n scale,\n axisType,\n isTransitioning,\n hideLabelsWhileTransitioning,\n ref,\n ...rest\n } = props;\n\n /* `pixelScale` and `targetUnitHeight` are alternatives: a density stated\n * outright takes over from the one a section's units imply, floors and all.\n * That is settled in `prepare-units/density`, so nothing is adjusted here. */\n\n // Handle special cases for hybrid scales (WIP, we need to regularize this)\n let _axisType = axisType ?? ColumnAxisType.AGE;\n let ageAxisComponent = CompositeAgeAxis;\n if (\n hybridScale?.type === HybridScaleType.ApproximateHeight &&\n _axisType != ColumnAxisType.AGE\n ) {\n // Use approximate height axis for non-age columns if a non-age axis type is requested\n ageAxisComponent = ApproximateHeightAxis;\n _axisType = ColumnAxisType.AGE;\n }\n\n const { sections, units, totalHeight } = usePreparedColumnUnits(rawUnits, {\n axisType: _axisType,\n t_age,\n b_age,\n t_pos,\n b_pos,\n mergeSections,\n targetUnitHeight,\n sectionOptions,\n unconformityHeight,\n pixelScale,\n pixelsPerMyr,\n pixelsPerMeter,\n minPixelScale,\n minSectionHeight,\n windowPadding,\n collapseSmallUnconformities,\n // TODO: consider unifying scale and hybridScale options\n scale,\n hybridScale,\n });\n\n if (sections.length === 0) {\n return h(\n \"div.column-container.empty\",\n h(NonIdealState, {\n title: \"Empty column\",\n description: \"No sections found in this column.\",\n icon: \"warning-sign\",\n }),\n );\n }\n\n return h(\n MacrostratColumnDataProvider,\n {\n units,\n sections,\n totalHeight,\n axisType: _axisType,\n allowUnitSelection: showUnitPopover || allowUnitSelection,\n onUnitSelected,\n selectedUnit,\n isTransitioning,\n hideLabelsWhileTransitioning,\n ref,\n },\n h(ColumnInner, { ageAxisComponent, ...rest }, [\n children,\n h.if(showUnitPopover)(UnitSelectionPopover),\n h.if(keyboardNavigation)(UnitKeyboardNavigation, { units }),\n ]),\n );\n}\n\ninterface ColumnInnerProps extends BaseColumnProps {\n ageAxisComponent?: ComponentType;\n}\n\nfunction ColumnInner(props: ColumnInnerProps) {\n const padding = extractPadding(props);\n\n // TODO: integrate padding vars more closely with the rest of the spacing (right now padding is a bit ad-hoc)\n const paddingVars: any = {\n \"--column-padding-top\": `${padding.paddingTop}px`,\n \"--column-padding-bottom\": `${padding.paddingBottom}px`,\n \"--column-padding-left\": `${padding.paddingLeft}px`,\n \"--column-padding-right\": `${padding.paddingRight}px`,\n };\n\n const {\n unitComponent = UnitComponent,\n unconformityLabels = \"minimal\",\n showLabels = true,\n width: _width = 300,\n columnWidth: _columnWidth = 150,\n showLabelColumn: _showLabelColumn = true,\n labelSuppressHeight,\n className,\n clipUnits = false,\n children,\n showTimescale,\n timescaleLevels,\n additionalTimescales,\n timescales,\n showTimescaleLabels,\n maxInternalColumns,\n onMouseOver,\n onClickTimescaleInterval,\n timescaleIntervalStyle,\n ageAxisComponent = CompositeAgeAxis,\n } = props;\n\n const { axisType } = useMacrostratColumnData();\n // A child layer drawing its own labels (the surfaces view) takes the label\n // column over from the unit labels\n const labelColumnClaimed = useLabelColumnClaimed();\n\n const columnRef = useColumnRef();\n\n // Coalesce unconformity label setting to a boolean\n let _timescaleUnconformityLabels = false;\n let _sectionUnconformityLabels = false;\n if (unconformityLabels === true || unconformityLabels === \"prominent\") {\n _sectionUnconformityLabels = true;\n } else if (unconformityLabels === \"minimal\") {\n _timescaleUnconformityLabels = true;\n }\n\n let width = _width;\n let columnWidth = _columnWidth;\n if (columnWidth > width) {\n columnWidth = width;\n }\n let showLabelColumn = _showLabelColumn;\n if (columnWidth > width - 10 || labelColumnClaimed) {\n showLabelColumn = false;\n }\n\n let _showTimescale = showTimescale ?? true;\n if (timescaleLevels != null || timescales != null) {\n _showTimescale = true;\n }\n _showTimescale = axisType == ColumnAxisType.AGE && _showTimescale;\n\n return h(\n ColumnContainer,\n {\n ...useMouseEventHandlers(onMouseOver),\n style: paddingVars,\n className,\n },\n h(\"div.column\", { ref: columnRef }, [\n h(ageAxisComponent),\n h.if(_showTimescale)(CompositeTimescale, {\n levels: timescaleLevels,\n additionalTimescales,\n timescales,\n showLabels: showTimescaleLabels,\n unconformityLabels: _timescaleUnconformityLabels,\n onClickInterval: onClickTimescaleInterval,\n intervalStyle: timescaleIntervalStyle,\n }),\n h(SectionsColumn, {\n unitComponent,\n showLabels,\n width,\n columnWidth,\n showLabelColumn,\n labelSuppressHeight,\n clipUnits,\n unconformityLabels: _sectionUnconformityLabels,\n maxInternalColumns,\n }),\n children,\n ]),\n );\n}\n\ntype ColumnMouseOverHandler = (\n unit: UnitLong | null,\n height: number | null,\n evt: MouseEvent,\n) => void;\n\nfunction useMouseEventHandlers(\n _onMouseOver: ColumnMouseOverHandler | null = null,\n) {\n /** Click event handler */\n\n // Click handler for unit selection\n const dispatch = useUnitSelectionDispatch();\n const onClick = useCallback(\n (evt) => {\n dispatch?.(null, null);\n },\n [dispatch],\n );\n\n /** Hover event handlers */\n const scale = useCompositeScale();\n\n const onMouseOver = useCallback(\n (evt) => {\n const height = scale.invert(\n evt.clientY - evt.currentTarget.getBoundingClientRect().top,\n );\n _onMouseOver?.(null, height, evt);\n },\n [scale, _onMouseOver],\n );\n\n const onMouseOut = useCallback(() => {\n _onMouseOver?.(null, null, null);\n }, [_onMouseOver]);\n\n if (_onMouseOver == null) {\n return {\n onClick,\n onMouseOver: undefined,\n onMouseMove: undefined,\n onMouseOut: undefined,\n };\n }\n\n return { onMouseOver, onMouseMove: onMouseOver, onMouseOut, onClick };\n}\n\nexport interface ColumnContainerProps extends HTMLAttributes<HTMLDivElement> {\n className?: string;\n style?: CSSProperties;\n}\n\nexport function ColumnContainer(props: ColumnContainerProps) {\n const { className, ...rest } = props;\n const darkMode = useDarkMode();\n\n return h(Box, {\n className: classNames(\n className,\n {\n \"dark-mode\": darkMode?.isEnabled ?? false,\n },\n \"column-container\",\n ),\n ...rest,\n });\n}\n\nexport function ColumnBasicInfo({\n data,\n showColumnID = true,\n showReferences = true,\n}) {\n if (data == null) return null;\n return h(\"div.column-info\", [\n h(\"div.column-title-row\", [\n h(\"h2\", data.col_name),\n h.if(showColumnID)(\"h4\", h(Identifier, { id: data.col_id })),\n ]),\n h(DataField, { row: true, label: \"Group\", value: data.col_group }),\n h.if(showReferences)(ReferencesField, {\n refs: data.refs,\n inline: false,\n row: false,\n className: \"column-refs\",\n }),\n ]);\n}\n"],"names":["ColumnAxisType","CompositeAgeAxis","HybridScaleType","ApproximateHeightAxis","usePreparedColumnUnits","h","NonIdealState","MacrostratColumnDataProvider","UnitSelectionPopover","UnitKeyboardNavigation","extractPadding","UnitComponent","useMacrostratColumnData","useLabelColumnClaimed","useColumnRef","CompositeTimescale","SectionsColumn","useUnitSelectionDispatch","useCallback","useCompositeScale","useDarkMode","Box","classNames","Identifier","DataField","ReferencesField"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"column.cjs","sources":["../src/column.ts"],"sourcesContent":["import { ColumnAxisType } from \"@macrostrat/column-components\";\nimport {\n Box,\n extractPadding,\n Padding,\n useDarkMode,\n} from \"@macrostrat/ui-components\";\nimport classNames from \"classnames\";\nimport {\n HTMLAttributes,\n useCallback,\n CSSProperties,\n ComponentType,\n RefObject,\n} from \"react\";\nimport h from \"./column.module.sass\";\nimport { UnitComponent } from \"./units\";\nimport {\n ColumnRef,\n UnitKeyboardNavigation,\n useColumnRef,\n useUnitSelectionDispatch,\n} from \"./data-provider\";\n\nimport {\n Identifier,\n ReferencesField,\n UnitSelectionPopover,\n} from \"./unit-details\";\nimport {\n MacrostratColumnDataProvider,\n useCompositeScale,\n useLabelColumnClaimed,\n useMacrostratColumnData,\n} from \"./data-provider\";\nimport {\n SectionSharedProps,\n CompositeTimescale,\n type ColumnIntervalStyleBuilder,\n type ColumnTimescaleClickHandler,\n type ColumnTimescaleLike,\n SectionsColumn,\n} from \"./section\";\nimport { ApproximateHeightAxis, CompositeAgeAxis } from \"./age-axis\";\nimport {\n MergeSectionsMode,\n usePreparedColumnUnits,\n HybridScaleType,\n ColumnHeightScaleOptions,\n} from \"./prepare-units\";\nimport { UnitLong } from \"@macrostrat/api-types\";\nimport { NonIdealState } from \"@blueprintjs/core\";\nimport { DataField } from \"@macrostrat/data-components\";\nimport { ScaleContinuousNumeric } from \"d3-scale\";\n\ninterface BaseColumnProps extends Omit<\n SectionSharedProps,\n \"unconformityLabels\"\n> {\n className?: string;\n showLabelColumn?: boolean;\n /** Suppress the label for a unit drawn thinner than this many pixels\n * (default 2) */\n labelSuppressHeight?: number;\n keyboardNavigation?: boolean;\n showLabels?: boolean;\n maxInternalColumns?: number;\n // Timescale properties\n showTimescale?: boolean;\n timescaleLevels?: number | [number, number];\n /** Regional or project timescales drawn as extra columns beside the\n * international one (see `CompositeTimescale`). Narrow `timescaleLevels` by\n * as many to swap the finest level for them rather than widen the column. */\n additionalTimescales?: number[];\n /** Every timescale to draw beside the column, in order: a Macrostrat\n * timescale ID, or a timescale with its own intervals (see\n * `CompositeTimescale`). Supersedes `timescaleLevels` and\n * `additionalTimescales`. */\n timescales?: ColumnTimescaleLike[];\n /** Draw each timescale's name above it */\n showTimescaleLabels?: boolean;\n /** Called when a timescale interval is clicked (e.g. to zoom the age range).\n * The data says which timescale it was clicked in. */\n onClickTimescaleInterval?: ColumnTimescaleClickHandler;\n /** Per-interval style for the timescale (e.g. to bold the selected\n * interval), by interval and the timescale it was drawn from. */\n timescaleIntervalStyle?: ColumnIntervalStyleBuilder;\n unconformityLabels?: boolean | UnconformityLabelPlacement;\n onMouseOver?: (\n unit: UnitLong | null,\n height: number | null,\n evt: MouseEvent,\n ) => void;\n}\n\nexport type UnconformityLabelPlacement = \"minimal\" | \"prominent\" | \"none\";\n\nexport interface ColumnProps\n extends Padding, BaseColumnProps, ColumnHeightScaleOptions {\n // Macrostrat units\n units: UnitLong[];\n t_age?: number;\n b_age?: number;\n t_pos?: number;\n b_pos?: number;\n mergeSections?: MergeSectionsMode;\n showUnitPopover?: boolean;\n allowUnitSelection?: boolean;\n selectedUnit?: number | null;\n onUnitSelected?: (unitID: number | null, unit: any) => void;\n // Unconformity height in pixels\n unconformityHeight?: number;\n scale?: ScaleContinuousNumeric<number, number>;\n /** True while the age window is animating (e.g. from `useAnimatedAgeWindow`),\n * so per-frame label/pattern recalculation can be skipped. */\n isTransitioning?: boolean;\n /** Hide unit labels while transitioning (perf escape hatch; default false —\n * labels stay visible through the animation). */\n hideLabelsWhileTransitioning?: boolean;\n ref?: RefObject<ColumnRef>;\n}\n\nexport function Column(props: ColumnProps) {\n const {\n showUnitPopover = false,\n keyboardNavigation = false,\n mergeSections,\n onUnitSelected,\n selectedUnit,\n children,\n units: rawUnits,\n t_age,\n b_age,\n t_pos,\n b_pos,\n unconformityHeight = 30,\n targetUnitHeight = 20,\n sectionOptions,\n pixelScale,\n pixelsPerMyr,\n pixelsPerMeter,\n minPixelScale = 0.2,\n minSectionHeight = 50,\n windowPadding = 0,\n collapseSmallUnconformities = true,\n allowUnitSelection = false,\n hybridScale,\n scale,\n axisType,\n isTransitioning,\n hideLabelsWhileTransitioning,\n ref,\n ...rest\n } = props;\n\n /* `pixelScale` and `targetUnitHeight` are alternatives: a density stated\n * outright takes over from the one a section's units imply, floors and all.\n * That is settled in `prepare-units/density`, so nothing is adjusted here. */\n\n // Handle special cases for hybrid scales (WIP, we need to regularize this)\n let _axisType = axisType ?? ColumnAxisType.AGE;\n let ageAxisComponent = CompositeAgeAxis;\n if (\n hybridScale?.type === HybridScaleType.ApproximateHeight &&\n _axisType != ColumnAxisType.AGE\n ) {\n // Use approximate height axis for non-age columns if a non-age axis type is requested\n ageAxisComponent = ApproximateHeightAxis;\n _axisType = ColumnAxisType.AGE;\n }\n\n let _sectionOptions = sectionOptions;\n if (_sectionOptions == undefined) {\n // Build our own section options function based on targetUnitHeight\n _sectionOptions = (ctx) => {\n /** Scale targetUnitHeight by the number of units, so that a section with just a few units\n * is drawn taller than a section with many units.\n */\n const n = ctx.units.length;\n const expansionFactor = 8 / Math.min(Math.max(n, 1), 8);\n\n return {\n targetUnitHeight: targetUnitHeight * expansionFactor,\n };\n };\n }\n\n const { sections, units, totalHeight } = usePreparedColumnUnits(rawUnits, {\n axisType: _axisType,\n t_age,\n b_age,\n t_pos,\n b_pos,\n mergeSections,\n targetUnitHeight,\n sectionOptions: _sectionOptions,\n unconformityHeight,\n pixelScale,\n pixelsPerMyr,\n pixelsPerMeter,\n minPixelScale,\n minSectionHeight,\n windowPadding,\n collapseSmallUnconformities,\n // TODO: consider unifying scale and hybridScale options\n scale,\n hybridScale,\n });\n\n if (sections.length === 0) {\n return h(\n \"div.column-container.empty\",\n h(NonIdealState, {\n title: \"Empty column\",\n description: \"No sections found in this column.\",\n icon: \"warning-sign\",\n }),\n );\n }\n\n return h(\n MacrostratColumnDataProvider,\n {\n units,\n sections,\n totalHeight,\n axisType: _axisType,\n allowUnitSelection: showUnitPopover || allowUnitSelection,\n onUnitSelected,\n selectedUnit,\n isTransitioning,\n hideLabelsWhileTransitioning,\n ref,\n },\n h(ColumnInner, { ageAxisComponent, ...rest }, [\n children,\n h.if(showUnitPopover)(UnitSelectionPopover),\n h.if(keyboardNavigation)(UnitKeyboardNavigation, { units }),\n ]),\n );\n}\n\ninterface ColumnInnerProps extends BaseColumnProps {\n ageAxisComponent?: ComponentType;\n}\n\nfunction ColumnInner(props: ColumnInnerProps) {\n const padding = extractPadding(props);\n\n // TODO: integrate padding vars more closely with the rest of the spacing (right now padding is a bit ad-hoc)\n const paddingVars: any = {\n \"--column-padding-top\": `${padding.paddingTop}px`,\n \"--column-padding-bottom\": `${padding.paddingBottom}px`,\n \"--column-padding-left\": `${padding.paddingLeft}px`,\n \"--column-padding-right\": `${padding.paddingRight}px`,\n };\n\n const {\n unitComponent = UnitComponent,\n unconformityLabels = \"minimal\",\n showLabels = true,\n width: _width = 300,\n columnWidth: _columnWidth = 150,\n showLabelColumn: _showLabelColumn = true,\n labelSuppressHeight,\n className,\n clipUnits = false,\n children,\n showTimescale,\n timescaleLevels,\n additionalTimescales,\n timescales,\n showTimescaleLabels,\n maxInternalColumns,\n onMouseOver,\n onClickTimescaleInterval,\n timescaleIntervalStyle,\n ageAxisComponent = CompositeAgeAxis,\n } = props;\n\n const { axisType } = useMacrostratColumnData();\n // A child layer drawing its own labels (the surfaces view) takes the label\n // column over from the unit labels\n const labelColumnClaimed = useLabelColumnClaimed();\n\n const columnRef = useColumnRef();\n\n // Coalesce unconformity label setting to a boolean\n let _timescaleUnconformityLabels = false;\n let _sectionUnconformityLabels = false;\n if (unconformityLabels === true || unconformityLabels === \"prominent\") {\n _sectionUnconformityLabels = true;\n } else if (unconformityLabels === \"minimal\") {\n _timescaleUnconformityLabels = true;\n }\n\n let width = _width;\n let columnWidth = _columnWidth;\n if (columnWidth > width) {\n columnWidth = width;\n }\n let showLabelColumn = _showLabelColumn;\n if (columnWidth > width - 10 || labelColumnClaimed) {\n showLabelColumn = false;\n }\n\n let _showTimescale = showTimescale ?? true;\n if (timescaleLevels != null || timescales != null) {\n _showTimescale = true;\n }\n _showTimescale = axisType == ColumnAxisType.AGE && _showTimescale;\n\n return h(\n ColumnContainer,\n {\n ...useMouseEventHandlers(onMouseOver),\n style: paddingVars,\n className,\n },\n h(\"div.column\", { ref: columnRef }, [\n h(ageAxisComponent),\n h.if(_showTimescale)(CompositeTimescale, {\n levels: timescaleLevels,\n additionalTimescales,\n timescales,\n showLabels: showTimescaleLabels,\n unconformityLabels: _timescaleUnconformityLabels,\n onClickInterval: onClickTimescaleInterval,\n intervalStyle: timescaleIntervalStyle,\n }),\n h(SectionsColumn, {\n unitComponent,\n showLabels,\n width,\n columnWidth,\n showLabelColumn,\n labelSuppressHeight,\n clipUnits,\n unconformityLabels: _sectionUnconformityLabels,\n maxInternalColumns,\n }),\n children,\n ]),\n );\n}\n\ntype ColumnMouseOverHandler = (\n unit: UnitLong | null,\n height: number | null,\n evt: MouseEvent,\n) => void;\n\nfunction useMouseEventHandlers(\n _onMouseOver: ColumnMouseOverHandler | null = null,\n) {\n /** Click event handler */\n\n // Click handler for unit selection\n const dispatch = useUnitSelectionDispatch();\n const onClick = useCallback(\n (evt) => {\n dispatch?.(null, null);\n },\n [dispatch],\n );\n\n /** Hover event handlers */\n const scale = useCompositeScale();\n\n const onMouseOver = useCallback(\n (evt) => {\n const height = scale.invert(\n evt.clientY - evt.currentTarget.getBoundingClientRect().top,\n );\n _onMouseOver?.(null, height, evt);\n },\n [scale, _onMouseOver],\n );\n\n const onMouseOut = useCallback(() => {\n _onMouseOver?.(null, null, null);\n }, [_onMouseOver]);\n\n if (_onMouseOver == null) {\n return {\n onClick,\n onMouseOver: undefined,\n onMouseMove: undefined,\n onMouseOut: undefined,\n };\n }\n\n return { onMouseOver, onMouseMove: onMouseOver, onMouseOut, onClick };\n}\n\nexport interface ColumnContainerProps extends HTMLAttributes<HTMLDivElement> {\n className?: string;\n style?: CSSProperties;\n}\n\nexport function ColumnContainer(props: ColumnContainerProps) {\n const { className, ...rest } = props;\n const darkMode = useDarkMode();\n\n return h(Box, {\n className: classNames(\n className,\n {\n \"dark-mode\": darkMode?.isEnabled ?? false,\n },\n \"column-container\",\n ),\n ...rest,\n });\n}\n\nexport function ColumnBasicInfo({\n data,\n showColumnID = true,\n showReferences = true,\n}) {\n if (data == null) return null;\n return h(\"div.column-info\", [\n h(\"div.column-title-row\", [\n h(\"h2\", data.col_name),\n h.if(showColumnID)(\"h4\", h(Identifier, { id: data.col_id })),\n ]),\n h(DataField, { row: true, label: \"Group\", value: data.col_group }),\n h.if(showReferences)(ReferencesField, {\n refs: data.refs,\n inline: false,\n row: false,\n className: \"column-refs\",\n }),\n ]);\n}\n"],"names":["ColumnAxisType","CompositeAgeAxis","HybridScaleType","ApproximateHeightAxis","usePreparedColumnUnits","h","NonIdealState","MacrostratColumnDataProvider","UnitSelectionPopover","UnitKeyboardNavigation","extractPadding","UnitComponent","useMacrostratColumnData","useLabelColumnClaimed","useColumnRef","CompositeTimescale","SectionsColumn","useUnitSelectionDispatch","useCallback","useCompositeScale","useDarkMode","Box","classNames","Identifier","DataField","ReferencesField"],"mappings":"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"}
|
package/dist/column.js
CHANGED
|
@@ -52,6 +52,16 @@ function Column(props) {
|
|
|
52
52
|
ageAxisComponent = ApproximateHeightAxis;
|
|
53
53
|
_axisType = ColumnAxisType.AGE;
|
|
54
54
|
}
|
|
55
|
+
let _sectionOptions = sectionOptions;
|
|
56
|
+
if (_sectionOptions == void 0) {
|
|
57
|
+
_sectionOptions = (ctx) => {
|
|
58
|
+
const n = ctx.units.length;
|
|
59
|
+
const expansionFactor = 8 / Math.min(Math.max(n, 1), 8);
|
|
60
|
+
return {
|
|
61
|
+
targetUnitHeight: targetUnitHeight * expansionFactor
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
}
|
|
55
65
|
const { sections, units, totalHeight } = usePreparedColumnUnits(rawUnits, {
|
|
56
66
|
axisType: _axisType,
|
|
57
67
|
t_age,
|
|
@@ -60,7 +70,7 @@ function Column(props) {
|
|
|
60
70
|
b_pos,
|
|
61
71
|
mergeSections,
|
|
62
72
|
targetUnitHeight,
|
|
63
|
-
sectionOptions,
|
|
73
|
+
sectionOptions: _sectionOptions,
|
|
64
74
|
unconformityHeight,
|
|
65
75
|
pixelScale,
|
|
66
76
|
pixelsPerMyr,
|
package/dist/column.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column.js","sources":["../src/column.ts"],"sourcesContent":["import { ColumnAxisType } from \"@macrostrat/column-components\";\nimport {\n Box,\n extractPadding,\n Padding,\n useDarkMode,\n} from \"@macrostrat/ui-components\";\nimport classNames from \"classnames\";\nimport {\n HTMLAttributes,\n useCallback,\n CSSProperties,\n ComponentType,\n RefObject,\n} from \"react\";\nimport h from \"./column.module.sass\";\nimport { UnitComponent } from \"./units\";\nimport {\n ColumnRef,\n UnitKeyboardNavigation,\n useColumnRef,\n useUnitSelectionDispatch,\n} from \"./data-provider\";\n\nimport {\n Identifier,\n ReferencesField,\n UnitSelectionPopover,\n} from \"./unit-details\";\nimport {\n MacrostratColumnDataProvider,\n useCompositeScale,\n useLabelColumnClaimed,\n useMacrostratColumnData,\n} from \"./data-provider\";\nimport {\n SectionSharedProps,\n CompositeTimescale,\n type ColumnIntervalStyleBuilder,\n type ColumnTimescaleClickHandler,\n type ColumnTimescaleLike,\n SectionsColumn,\n} from \"./section\";\nimport { ApproximateHeightAxis, CompositeAgeAxis } from \"./age-axis\";\nimport {\n MergeSectionsMode,\n usePreparedColumnUnits,\n HybridScaleType,\n ColumnHeightScaleOptions,\n} from \"./prepare-units\";\nimport { UnitLong } from \"@macrostrat/api-types\";\nimport { NonIdealState } from \"@blueprintjs/core\";\nimport { DataField } from \"@macrostrat/data-components\";\nimport { ScaleContinuousNumeric } from \"d3-scale\";\n\ninterface BaseColumnProps extends Omit<\n SectionSharedProps,\n \"unconformityLabels\"\n> {\n className?: string;\n showLabelColumn?: boolean;\n /** Suppress the label for a unit drawn thinner than this many pixels\n * (default 2) */\n labelSuppressHeight?: number;\n keyboardNavigation?: boolean;\n showLabels?: boolean;\n maxInternalColumns?: number;\n // Timescale properties\n showTimescale?: boolean;\n timescaleLevels?: number | [number, number];\n /** Regional or project timescales drawn as extra columns beside the\n * international one (see `CompositeTimescale`). Narrow `timescaleLevels` by\n * as many to swap the finest level for them rather than widen the column. */\n additionalTimescales?: number[];\n /** Every timescale to draw beside the column, in order: a Macrostrat\n * timescale ID, or a timescale with its own intervals (see\n * `CompositeTimescale`). Supersedes `timescaleLevels` and\n * `additionalTimescales`. */\n timescales?: ColumnTimescaleLike[];\n /** Draw each timescale's name above it */\n showTimescaleLabels?: boolean;\n /** Called when a timescale interval is clicked (e.g. to zoom the age range).\n * The data says which timescale it was clicked in. */\n onClickTimescaleInterval?: ColumnTimescaleClickHandler;\n /** Per-interval style for the timescale (e.g. to bold the selected\n * interval), by interval and the timescale it was drawn from. */\n timescaleIntervalStyle?: ColumnIntervalStyleBuilder;\n unconformityLabels?: boolean | UnconformityLabelPlacement;\n onMouseOver?: (\n unit: UnitLong | null,\n height: number | null,\n evt: MouseEvent,\n ) => void;\n}\n\nexport type UnconformityLabelPlacement = \"minimal\" | \"prominent\" | \"none\";\n\nexport interface ColumnProps\n extends Padding, BaseColumnProps, ColumnHeightScaleOptions {\n // Macrostrat units\n units: UnitLong[];\n t_age?: number;\n b_age?: number;\n t_pos?: number;\n b_pos?: number;\n mergeSections?: MergeSectionsMode;\n showUnitPopover?: boolean;\n allowUnitSelection?: boolean;\n selectedUnit?: number | null;\n onUnitSelected?: (unitID: number | null, unit: any) => void;\n // Unconformity height in pixels\n unconformityHeight?: number;\n scale?: ScaleContinuousNumeric<number, number>;\n /** True while the age window is animating (e.g. from `useAnimatedAgeWindow`),\n * so per-frame label/pattern recalculation can be skipped. */\n isTransitioning?: boolean;\n /** Hide unit labels while transitioning (perf escape hatch; default false —\n * labels stay visible through the animation). */\n hideLabelsWhileTransitioning?: boolean;\n ref?: RefObject<ColumnRef>;\n}\n\nexport function Column(props: ColumnProps) {\n const {\n showUnitPopover = false,\n keyboardNavigation = false,\n mergeSections,\n onUnitSelected,\n selectedUnit,\n children,\n units: rawUnits,\n t_age,\n b_age,\n t_pos,\n b_pos,\n unconformityHeight = 30,\n targetUnitHeight = 20,\n sectionOptions,\n pixelScale,\n pixelsPerMyr,\n pixelsPerMeter,\n minPixelScale = 0.2,\n minSectionHeight = 50,\n windowPadding = 0,\n collapseSmallUnconformities = true,\n allowUnitSelection = false,\n hybridScale,\n scale,\n axisType,\n isTransitioning,\n hideLabelsWhileTransitioning,\n ref,\n ...rest\n } = props;\n\n /* `pixelScale` and `targetUnitHeight` are alternatives: a density stated\n * outright takes over from the one a section's units imply, floors and all.\n * That is settled in `prepare-units/density`, so nothing is adjusted here. */\n\n // Handle special cases for hybrid scales (WIP, we need to regularize this)\n let _axisType = axisType ?? ColumnAxisType.AGE;\n let ageAxisComponent = CompositeAgeAxis;\n if (\n hybridScale?.type === HybridScaleType.ApproximateHeight &&\n _axisType != ColumnAxisType.AGE\n ) {\n // Use approximate height axis for non-age columns if a non-age axis type is requested\n ageAxisComponent = ApproximateHeightAxis;\n _axisType = ColumnAxisType.AGE;\n }\n\n const { sections, units, totalHeight } = usePreparedColumnUnits(rawUnits, {\n axisType: _axisType,\n t_age,\n b_age,\n t_pos,\n b_pos,\n mergeSections,\n targetUnitHeight,\n sectionOptions,\n unconformityHeight,\n pixelScale,\n pixelsPerMyr,\n pixelsPerMeter,\n minPixelScale,\n minSectionHeight,\n windowPadding,\n collapseSmallUnconformities,\n // TODO: consider unifying scale and hybridScale options\n scale,\n hybridScale,\n });\n\n if (sections.length === 0) {\n return h(\n \"div.column-container.empty\",\n h(NonIdealState, {\n title: \"Empty column\",\n description: \"No sections found in this column.\",\n icon: \"warning-sign\",\n }),\n );\n }\n\n return h(\n MacrostratColumnDataProvider,\n {\n units,\n sections,\n totalHeight,\n axisType: _axisType,\n allowUnitSelection: showUnitPopover || allowUnitSelection,\n onUnitSelected,\n selectedUnit,\n isTransitioning,\n hideLabelsWhileTransitioning,\n ref,\n },\n h(ColumnInner, { ageAxisComponent, ...rest }, [\n children,\n h.if(showUnitPopover)(UnitSelectionPopover),\n h.if(keyboardNavigation)(UnitKeyboardNavigation, { units }),\n ]),\n );\n}\n\ninterface ColumnInnerProps extends BaseColumnProps {\n ageAxisComponent?: ComponentType;\n}\n\nfunction ColumnInner(props: ColumnInnerProps) {\n const padding = extractPadding(props);\n\n // TODO: integrate padding vars more closely with the rest of the spacing (right now padding is a bit ad-hoc)\n const paddingVars: any = {\n \"--column-padding-top\": `${padding.paddingTop}px`,\n \"--column-padding-bottom\": `${padding.paddingBottom}px`,\n \"--column-padding-left\": `${padding.paddingLeft}px`,\n \"--column-padding-right\": `${padding.paddingRight}px`,\n };\n\n const {\n unitComponent = UnitComponent,\n unconformityLabels = \"minimal\",\n showLabels = true,\n width: _width = 300,\n columnWidth: _columnWidth = 150,\n showLabelColumn: _showLabelColumn = true,\n labelSuppressHeight,\n className,\n clipUnits = false,\n children,\n showTimescale,\n timescaleLevels,\n additionalTimescales,\n timescales,\n showTimescaleLabels,\n maxInternalColumns,\n onMouseOver,\n onClickTimescaleInterval,\n timescaleIntervalStyle,\n ageAxisComponent = CompositeAgeAxis,\n } = props;\n\n const { axisType } = useMacrostratColumnData();\n // A child layer drawing its own labels (the surfaces view) takes the label\n // column over from the unit labels\n const labelColumnClaimed = useLabelColumnClaimed();\n\n const columnRef = useColumnRef();\n\n // Coalesce unconformity label setting to a boolean\n let _timescaleUnconformityLabels = false;\n let _sectionUnconformityLabels = false;\n if (unconformityLabels === true || unconformityLabels === \"prominent\") {\n _sectionUnconformityLabels = true;\n } else if (unconformityLabels === \"minimal\") {\n _timescaleUnconformityLabels = true;\n }\n\n let width = _width;\n let columnWidth = _columnWidth;\n if (columnWidth > width) {\n columnWidth = width;\n }\n let showLabelColumn = _showLabelColumn;\n if (columnWidth > width - 10 || labelColumnClaimed) {\n showLabelColumn = false;\n }\n\n let _showTimescale = showTimescale ?? true;\n if (timescaleLevels != null || timescales != null) {\n _showTimescale = true;\n }\n _showTimescale = axisType == ColumnAxisType.AGE && _showTimescale;\n\n return h(\n ColumnContainer,\n {\n ...useMouseEventHandlers(onMouseOver),\n style: paddingVars,\n className,\n },\n h(\"div.column\", { ref: columnRef }, [\n h(ageAxisComponent),\n h.if(_showTimescale)(CompositeTimescale, {\n levels: timescaleLevels,\n additionalTimescales,\n timescales,\n showLabels: showTimescaleLabels,\n unconformityLabels: _timescaleUnconformityLabels,\n onClickInterval: onClickTimescaleInterval,\n intervalStyle: timescaleIntervalStyle,\n }),\n h(SectionsColumn, {\n unitComponent,\n showLabels,\n width,\n columnWidth,\n showLabelColumn,\n labelSuppressHeight,\n clipUnits,\n unconformityLabels: _sectionUnconformityLabels,\n maxInternalColumns,\n }),\n children,\n ]),\n );\n}\n\ntype ColumnMouseOverHandler = (\n unit: UnitLong | null,\n height: number | null,\n evt: MouseEvent,\n) => void;\n\nfunction useMouseEventHandlers(\n _onMouseOver: ColumnMouseOverHandler | null = null,\n) {\n /** Click event handler */\n\n // Click handler for unit selection\n const dispatch = useUnitSelectionDispatch();\n const onClick = useCallback(\n (evt) => {\n dispatch?.(null, null);\n },\n [dispatch],\n );\n\n /** Hover event handlers */\n const scale = useCompositeScale();\n\n const onMouseOver = useCallback(\n (evt) => {\n const height = scale.invert(\n evt.clientY - evt.currentTarget.getBoundingClientRect().top,\n );\n _onMouseOver?.(null, height, evt);\n },\n [scale, _onMouseOver],\n );\n\n const onMouseOut = useCallback(() => {\n _onMouseOver?.(null, null, null);\n }, [_onMouseOver]);\n\n if (_onMouseOver == null) {\n return {\n onClick,\n onMouseOver: undefined,\n onMouseMove: undefined,\n onMouseOut: undefined,\n };\n }\n\n return { onMouseOver, onMouseMove: onMouseOver, onMouseOut, onClick };\n}\n\nexport interface ColumnContainerProps extends HTMLAttributes<HTMLDivElement> {\n className?: string;\n style?: CSSProperties;\n}\n\nexport function ColumnContainer(props: ColumnContainerProps) {\n const { className, ...rest } = props;\n const darkMode = useDarkMode();\n\n return h(Box, {\n className: classNames(\n className,\n {\n \"dark-mode\": darkMode?.isEnabled ?? false,\n },\n \"column-container\",\n ),\n ...rest,\n });\n}\n\nexport function ColumnBasicInfo({\n data,\n showColumnID = true,\n showReferences = true,\n}) {\n if (data == null) return null;\n return h(\"div.column-info\", [\n h(\"div.column-title-row\", [\n h(\"h2\", data.col_name),\n h.if(showColumnID)(\"h4\", h(Identifier, { id: data.col_id })),\n ]),\n h(DataField, { row: true, label: \"Group\", value: data.col_group }),\n h.if(showReferences)(ReferencesField, {\n refs: data.refs,\n inline: false,\n row: false,\n className: \"column-refs\",\n }),\n ]);\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"column.js","sources":["../src/column.ts"],"sourcesContent":["import { ColumnAxisType } from \"@macrostrat/column-components\";\nimport {\n Box,\n extractPadding,\n Padding,\n useDarkMode,\n} from \"@macrostrat/ui-components\";\nimport classNames from \"classnames\";\nimport {\n HTMLAttributes,\n useCallback,\n CSSProperties,\n ComponentType,\n RefObject,\n} from \"react\";\nimport h from \"./column.module.sass\";\nimport { UnitComponent } from \"./units\";\nimport {\n ColumnRef,\n UnitKeyboardNavigation,\n useColumnRef,\n useUnitSelectionDispatch,\n} from \"./data-provider\";\n\nimport {\n Identifier,\n ReferencesField,\n UnitSelectionPopover,\n} from \"./unit-details\";\nimport {\n MacrostratColumnDataProvider,\n useCompositeScale,\n useLabelColumnClaimed,\n useMacrostratColumnData,\n} from \"./data-provider\";\nimport {\n SectionSharedProps,\n CompositeTimescale,\n type ColumnIntervalStyleBuilder,\n type ColumnTimescaleClickHandler,\n type ColumnTimescaleLike,\n SectionsColumn,\n} from \"./section\";\nimport { ApproximateHeightAxis, CompositeAgeAxis } from \"./age-axis\";\nimport {\n MergeSectionsMode,\n usePreparedColumnUnits,\n HybridScaleType,\n ColumnHeightScaleOptions,\n} from \"./prepare-units\";\nimport { UnitLong } from \"@macrostrat/api-types\";\nimport { NonIdealState } from \"@blueprintjs/core\";\nimport { DataField } from \"@macrostrat/data-components\";\nimport { ScaleContinuousNumeric } from \"d3-scale\";\n\ninterface BaseColumnProps extends Omit<\n SectionSharedProps,\n \"unconformityLabels\"\n> {\n className?: string;\n showLabelColumn?: boolean;\n /** Suppress the label for a unit drawn thinner than this many pixels\n * (default 2) */\n labelSuppressHeight?: number;\n keyboardNavigation?: boolean;\n showLabels?: boolean;\n maxInternalColumns?: number;\n // Timescale properties\n showTimescale?: boolean;\n timescaleLevels?: number | [number, number];\n /** Regional or project timescales drawn as extra columns beside the\n * international one (see `CompositeTimescale`). Narrow `timescaleLevels` by\n * as many to swap the finest level for them rather than widen the column. */\n additionalTimescales?: number[];\n /** Every timescale to draw beside the column, in order: a Macrostrat\n * timescale ID, or a timescale with its own intervals (see\n * `CompositeTimescale`). Supersedes `timescaleLevels` and\n * `additionalTimescales`. */\n timescales?: ColumnTimescaleLike[];\n /** Draw each timescale's name above it */\n showTimescaleLabels?: boolean;\n /** Called when a timescale interval is clicked (e.g. to zoom the age range).\n * The data says which timescale it was clicked in. */\n onClickTimescaleInterval?: ColumnTimescaleClickHandler;\n /** Per-interval style for the timescale (e.g. to bold the selected\n * interval), by interval and the timescale it was drawn from. */\n timescaleIntervalStyle?: ColumnIntervalStyleBuilder;\n unconformityLabels?: boolean | UnconformityLabelPlacement;\n onMouseOver?: (\n unit: UnitLong | null,\n height: number | null,\n evt: MouseEvent,\n ) => void;\n}\n\nexport type UnconformityLabelPlacement = \"minimal\" | \"prominent\" | \"none\";\n\nexport interface ColumnProps\n extends Padding, BaseColumnProps, ColumnHeightScaleOptions {\n // Macrostrat units\n units: UnitLong[];\n t_age?: number;\n b_age?: number;\n t_pos?: number;\n b_pos?: number;\n mergeSections?: MergeSectionsMode;\n showUnitPopover?: boolean;\n allowUnitSelection?: boolean;\n selectedUnit?: number | null;\n onUnitSelected?: (unitID: number | null, unit: any) => void;\n // Unconformity height in pixels\n unconformityHeight?: number;\n scale?: ScaleContinuousNumeric<number, number>;\n /** True while the age window is animating (e.g. from `useAnimatedAgeWindow`),\n * so per-frame label/pattern recalculation can be skipped. */\n isTransitioning?: boolean;\n /** Hide unit labels while transitioning (perf escape hatch; default false —\n * labels stay visible through the animation). */\n hideLabelsWhileTransitioning?: boolean;\n ref?: RefObject<ColumnRef>;\n}\n\nexport function Column(props: ColumnProps) {\n const {\n showUnitPopover = false,\n keyboardNavigation = false,\n mergeSections,\n onUnitSelected,\n selectedUnit,\n children,\n units: rawUnits,\n t_age,\n b_age,\n t_pos,\n b_pos,\n unconformityHeight = 30,\n targetUnitHeight = 20,\n sectionOptions,\n pixelScale,\n pixelsPerMyr,\n pixelsPerMeter,\n minPixelScale = 0.2,\n minSectionHeight = 50,\n windowPadding = 0,\n collapseSmallUnconformities = true,\n allowUnitSelection = false,\n hybridScale,\n scale,\n axisType,\n isTransitioning,\n hideLabelsWhileTransitioning,\n ref,\n ...rest\n } = props;\n\n /* `pixelScale` and `targetUnitHeight` are alternatives: a density stated\n * outright takes over from the one a section's units imply, floors and all.\n * That is settled in `prepare-units/density`, so nothing is adjusted here. */\n\n // Handle special cases for hybrid scales (WIP, we need to regularize this)\n let _axisType = axisType ?? ColumnAxisType.AGE;\n let ageAxisComponent = CompositeAgeAxis;\n if (\n hybridScale?.type === HybridScaleType.ApproximateHeight &&\n _axisType != ColumnAxisType.AGE\n ) {\n // Use approximate height axis for non-age columns if a non-age axis type is requested\n ageAxisComponent = ApproximateHeightAxis;\n _axisType = ColumnAxisType.AGE;\n }\n\n let _sectionOptions = sectionOptions;\n if (_sectionOptions == undefined) {\n // Build our own section options function based on targetUnitHeight\n _sectionOptions = (ctx) => {\n /** Scale targetUnitHeight by the number of units, so that a section with just a few units\n * is drawn taller than a section with many units.\n */\n const n = ctx.units.length;\n const expansionFactor = 8 / Math.min(Math.max(n, 1), 8);\n\n return {\n targetUnitHeight: targetUnitHeight * expansionFactor,\n };\n };\n }\n\n const { sections, units, totalHeight } = usePreparedColumnUnits(rawUnits, {\n axisType: _axisType,\n t_age,\n b_age,\n t_pos,\n b_pos,\n mergeSections,\n targetUnitHeight,\n sectionOptions: _sectionOptions,\n unconformityHeight,\n pixelScale,\n pixelsPerMyr,\n pixelsPerMeter,\n minPixelScale,\n minSectionHeight,\n windowPadding,\n collapseSmallUnconformities,\n // TODO: consider unifying scale and hybridScale options\n scale,\n hybridScale,\n });\n\n if (sections.length === 0) {\n return h(\n \"div.column-container.empty\",\n h(NonIdealState, {\n title: \"Empty column\",\n description: \"No sections found in this column.\",\n icon: \"warning-sign\",\n }),\n );\n }\n\n return h(\n MacrostratColumnDataProvider,\n {\n units,\n sections,\n totalHeight,\n axisType: _axisType,\n allowUnitSelection: showUnitPopover || allowUnitSelection,\n onUnitSelected,\n selectedUnit,\n isTransitioning,\n hideLabelsWhileTransitioning,\n ref,\n },\n h(ColumnInner, { ageAxisComponent, ...rest }, [\n children,\n h.if(showUnitPopover)(UnitSelectionPopover),\n h.if(keyboardNavigation)(UnitKeyboardNavigation, { units }),\n ]),\n );\n}\n\ninterface ColumnInnerProps extends BaseColumnProps {\n ageAxisComponent?: ComponentType;\n}\n\nfunction ColumnInner(props: ColumnInnerProps) {\n const padding = extractPadding(props);\n\n // TODO: integrate padding vars more closely with the rest of the spacing (right now padding is a bit ad-hoc)\n const paddingVars: any = {\n \"--column-padding-top\": `${padding.paddingTop}px`,\n \"--column-padding-bottom\": `${padding.paddingBottom}px`,\n \"--column-padding-left\": `${padding.paddingLeft}px`,\n \"--column-padding-right\": `${padding.paddingRight}px`,\n };\n\n const {\n unitComponent = UnitComponent,\n unconformityLabels = \"minimal\",\n showLabels = true,\n width: _width = 300,\n columnWidth: _columnWidth = 150,\n showLabelColumn: _showLabelColumn = true,\n labelSuppressHeight,\n className,\n clipUnits = false,\n children,\n showTimescale,\n timescaleLevels,\n additionalTimescales,\n timescales,\n showTimescaleLabels,\n maxInternalColumns,\n onMouseOver,\n onClickTimescaleInterval,\n timescaleIntervalStyle,\n ageAxisComponent = CompositeAgeAxis,\n } = props;\n\n const { axisType } = useMacrostratColumnData();\n // A child layer drawing its own labels (the surfaces view) takes the label\n // column over from the unit labels\n const labelColumnClaimed = useLabelColumnClaimed();\n\n const columnRef = useColumnRef();\n\n // Coalesce unconformity label setting to a boolean\n let _timescaleUnconformityLabels = false;\n let _sectionUnconformityLabels = false;\n if (unconformityLabels === true || unconformityLabels === \"prominent\") {\n _sectionUnconformityLabels = true;\n } else if (unconformityLabels === \"minimal\") {\n _timescaleUnconformityLabels = true;\n }\n\n let width = _width;\n let columnWidth = _columnWidth;\n if (columnWidth > width) {\n columnWidth = width;\n }\n let showLabelColumn = _showLabelColumn;\n if (columnWidth > width - 10 || labelColumnClaimed) {\n showLabelColumn = false;\n }\n\n let _showTimescale = showTimescale ?? true;\n if (timescaleLevels != null || timescales != null) {\n _showTimescale = true;\n }\n _showTimescale = axisType == ColumnAxisType.AGE && _showTimescale;\n\n return h(\n ColumnContainer,\n {\n ...useMouseEventHandlers(onMouseOver),\n style: paddingVars,\n className,\n },\n h(\"div.column\", { ref: columnRef }, [\n h(ageAxisComponent),\n h.if(_showTimescale)(CompositeTimescale, {\n levels: timescaleLevels,\n additionalTimescales,\n timescales,\n showLabels: showTimescaleLabels,\n unconformityLabels: _timescaleUnconformityLabels,\n onClickInterval: onClickTimescaleInterval,\n intervalStyle: timescaleIntervalStyle,\n }),\n h(SectionsColumn, {\n unitComponent,\n showLabels,\n width,\n columnWidth,\n showLabelColumn,\n labelSuppressHeight,\n clipUnits,\n unconformityLabels: _sectionUnconformityLabels,\n maxInternalColumns,\n }),\n children,\n ]),\n );\n}\n\ntype ColumnMouseOverHandler = (\n unit: UnitLong | null,\n height: number | null,\n evt: MouseEvent,\n) => void;\n\nfunction useMouseEventHandlers(\n _onMouseOver: ColumnMouseOverHandler | null = null,\n) {\n /** Click event handler */\n\n // Click handler for unit selection\n const dispatch = useUnitSelectionDispatch();\n const onClick = useCallback(\n (evt) => {\n dispatch?.(null, null);\n },\n [dispatch],\n );\n\n /** Hover event handlers */\n const scale = useCompositeScale();\n\n const onMouseOver = useCallback(\n (evt) => {\n const height = scale.invert(\n evt.clientY - evt.currentTarget.getBoundingClientRect().top,\n );\n _onMouseOver?.(null, height, evt);\n },\n [scale, _onMouseOver],\n );\n\n const onMouseOut = useCallback(() => {\n _onMouseOver?.(null, null, null);\n }, [_onMouseOver]);\n\n if (_onMouseOver == null) {\n return {\n onClick,\n onMouseOver: undefined,\n onMouseMove: undefined,\n onMouseOut: undefined,\n };\n }\n\n return { onMouseOver, onMouseMove: onMouseOver, onMouseOut, onClick };\n}\n\nexport interface ColumnContainerProps extends HTMLAttributes<HTMLDivElement> {\n className?: string;\n style?: CSSProperties;\n}\n\nexport function ColumnContainer(props: ColumnContainerProps) {\n const { className, ...rest } = props;\n const darkMode = useDarkMode();\n\n return h(Box, {\n className: classNames(\n className,\n {\n \"dark-mode\": darkMode?.isEnabled ?? false,\n },\n \"column-container\",\n ),\n ...rest,\n });\n}\n\nexport function ColumnBasicInfo({\n data,\n showColumnID = true,\n showReferences = true,\n}) {\n if (data == null) return null;\n return h(\"div.column-info\", [\n h(\"div.column-title-row\", [\n h(\"h2\", data.col_name),\n h.if(showColumnID)(\"h4\", h(Identifier, { id: data.col_id })),\n ]),\n h(DataField, { row: true, label: \"Group\", value: data.col_group }),\n h.if(showReferences)(ReferencesField, {\n refs: data.refs,\n inline: false,\n row: false,\n className: \"column-refs\",\n }),\n ]);\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -11,11 +11,11 @@ const notes = require("./notes.cjs");
|
|
|
11
11
|
const mapViews = require("@macrostrat/map-views");
|
|
12
12
|
const data = require("./age-model/data.cjs");
|
|
13
13
|
const ageRange = require("./unit-details/age-range.cjs");
|
|
14
|
+
const dataComponents = require("@macrostrat/data-components");
|
|
14
15
|
const ageWindowTag = require("./unit-details/age-window-tag.cjs");
|
|
15
16
|
const composite = require("./units/composite.cjs");
|
|
16
17
|
const base = require("./facets/measurements/base.cjs");
|
|
17
18
|
const legacy = require("./age-model/legacy.cjs");
|
|
18
|
-
const dataComponents = require("@macrostrat/data-components");
|
|
19
19
|
const columnNav = require("./data-provider/column-nav.cjs");
|
|
20
20
|
const surfaces = require("./age-model/surfaces.cjs");
|
|
21
21
|
const main = require("./correlation-chart/main.cjs");
|
|
@@ -68,13 +68,34 @@ exports.AGE_MODEL_ROUTE = data.AGE_MODEL_ROUTE;
|
|
|
68
68
|
exports.useColumnAgeModel = data.useColumnAgeModel;
|
|
69
69
|
exports.useColumnSurfaces = data.useColumnSurfaces;
|
|
70
70
|
exports.AgeField = ageRange.AgeField;
|
|
71
|
-
exports.AgeLabel = ageRange.AgeLabel;
|
|
72
71
|
exports.AgeRange = ageRange.AgeRange;
|
|
73
72
|
exports.Duration = ageRange.Duration;
|
|
74
73
|
exports.IntervalProportions = ageRange.IntervalProportions;
|
|
75
|
-
exports.Proportion = ageRange.Proportion;
|
|
76
|
-
exports.getAge = ageRange.getAge;
|
|
77
74
|
exports.getAgeRange = ageRange.getAgeRange;
|
|
75
|
+
Object.defineProperty(exports, "AgeLabel", {
|
|
76
|
+
enumerable: true,
|
|
77
|
+
get: () => dataComponents.AgeLabel
|
|
78
|
+
});
|
|
79
|
+
Object.defineProperty(exports, "ClickableText", {
|
|
80
|
+
enumerable: true,
|
|
81
|
+
get: () => dataComponents.ClickableText
|
|
82
|
+
});
|
|
83
|
+
Object.defineProperty(exports, "Identifier", {
|
|
84
|
+
enumerable: true,
|
|
85
|
+
get: () => dataComponents.Identifier
|
|
86
|
+
});
|
|
87
|
+
Object.defineProperty(exports, "Proportion", {
|
|
88
|
+
enumerable: true,
|
|
89
|
+
get: () => dataComponents.IntervalProportion
|
|
90
|
+
});
|
|
91
|
+
Object.defineProperty(exports, "UnitIdentifier", {
|
|
92
|
+
enumerable: true,
|
|
93
|
+
get: () => dataComponents.UnitIdentifier
|
|
94
|
+
});
|
|
95
|
+
Object.defineProperty(exports, "getAge", {
|
|
96
|
+
enumerable: true,
|
|
97
|
+
get: () => dataComponents.getAge
|
|
98
|
+
});
|
|
78
99
|
exports.AgeWindowTag = ageWindowTag.AgeWindowTag;
|
|
79
100
|
exports.intervalShortFromTimescale = ageWindowTag.intervalShortFromTimescale;
|
|
80
101
|
exports.AnnotatedUnitsColumn = composite.AnnotatedUnitsColumn;
|
|
@@ -91,18 +112,6 @@ exports.mergeHeightRanges = base.mergeHeightRanges;
|
|
|
91
112
|
exports.standardizeMeasurementHeight = base.standardizeMeasurementHeight;
|
|
92
113
|
exports.BoundaryAgeModelOverlay = legacy.BoundaryAgeModelOverlay;
|
|
93
114
|
exports.ComputedSurfacesOverlay = legacy.ComputedSurfacesOverlay;
|
|
94
|
-
Object.defineProperty(exports, "ClickableText", {
|
|
95
|
-
enumerable: true,
|
|
96
|
-
get: () => dataComponents.ClickableText
|
|
97
|
-
});
|
|
98
|
-
Object.defineProperty(exports, "Identifier", {
|
|
99
|
-
enumerable: true,
|
|
100
|
-
get: () => dataComponents.Identifier
|
|
101
|
-
});
|
|
102
|
-
Object.defineProperty(exports, "UnitIdentifier", {
|
|
103
|
-
enumerable: true,
|
|
104
|
-
get: () => dataComponents.UnitIdentifier
|
|
105
|
-
});
|
|
106
115
|
exports.ColumnNavProvider = columnNav.ColumnNavProvider;
|
|
107
116
|
exports.useColumnNav = columnNav.useColumnNav;
|
|
108
117
|
exports.ColumnSurfaceLabels = surfaces.ColumnSurfaceLabels;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.js
CHANGED
|
@@ -8,12 +8,12 @@ import { CompositeTimescale, CompositeTimescaleCore } from "./section.js";
|
|
|
8
8
|
import { ColumnNotes } from "./notes.js";
|
|
9
9
|
export * from "@macrostrat/map-views";
|
|
10
10
|
import { AGE_MODEL_ROUTE, useColumnAgeModel, useColumnSurfaces } from "./age-model/data.js";
|
|
11
|
-
import { AgeField,
|
|
11
|
+
import { AgeField, AgeRange, Duration, IntervalProportions, getAgeRange } from "./unit-details/age-range.js";
|
|
12
|
+
import { AgeLabel, ClickableText, Identifier, IntervalProportion, UnitIdentifier, getAge } from "@macrostrat/data-components";
|
|
12
13
|
import { AgeWindowTag, intervalShortFromTimescale } from "./unit-details/age-window-tag.js";
|
|
13
14
|
import { AnnotatedUnitsColumn, ColumnNotesProvider, CompositeUnitComponent, CompositeUnitsColumn, LabelTrackerProvider, SectionLabelsColumn, TrackedLabeledUnit } from "./units/composite.js";
|
|
14
15
|
import { BaseMeasurementsColumn, TruncatedList, groupNotesByPixelDistance, mergeHeightRanges, standardizeMeasurementHeight } from "./facets/measurements/base.js";
|
|
15
16
|
import { BoundaryAgeModelOverlay, ComputedSurfacesOverlay } from "./age-model/legacy.js";
|
|
16
|
-
import { ClickableText, Identifier, UnitIdentifier } from "@macrostrat/data-components";
|
|
17
17
|
import { ColumnNavProvider, useColumnNav } from "./data-provider/column-nav.js";
|
|
18
18
|
import { ColumnSurfaceLabels, ColumnSurfaceLines, ColumnSurfaces, surfaceClasses } from "./age-model/surfaces.js";
|
|
19
19
|
import { CorrelationChart } from "./correlation-chart/main.js";
|
|
@@ -92,7 +92,7 @@ export {
|
|
|
92
92
|
MergeSectionsMode,
|
|
93
93
|
PBDBFossilsColumn,
|
|
94
94
|
PBDBOccurrencesMatrix,
|
|
95
|
-
Proportion,
|
|
95
|
+
IntervalProportion as Proportion,
|
|
96
96
|
ReferencesField,
|
|
97
97
|
SGPMeasurementsColumn,
|
|
98
98
|
SectionLabelsColumn,
|
|
@@ -6,6 +6,7 @@ const d3Scale = require("d3-scale");
|
|
|
6
6
|
const dynamicScales = require("./dynamic-scales.cjs");
|
|
7
7
|
const density = require("./density.cjs");
|
|
8
8
|
const types = require("./types.cjs");
|
|
9
|
+
const stratigraphyUtils = require("@macrostrat/stratigraphy-utils");
|
|
9
10
|
function buildCompositeScaleInfo(inputScales, unconformityHeight) {
|
|
10
11
|
let totalHeight = unconformityHeight / 2;
|
|
11
12
|
let lastSectionTopHeight = 0;
|
|
@@ -86,7 +87,13 @@ function buildSectionScale(data, opts) {
|
|
|
86
87
|
sectionID
|
|
87
88
|
} = opts;
|
|
88
89
|
const domain = opts.domain ?? findSectionHeightRange(data, axisType);
|
|
89
|
-
const dAge =
|
|
90
|
+
const dAge = dx(domain);
|
|
91
|
+
let visibleExtent = dAge;
|
|
92
|
+
if (visibleWindow != null) {
|
|
93
|
+
visibleExtent = dx(
|
|
94
|
+
stratigraphyUtils.mergeAgeRanges([domain, visibleWindow], stratigraphyUtils.MergeMode.Inner)
|
|
95
|
+
);
|
|
96
|
+
}
|
|
90
97
|
let _pixelScale = opts.pixelScale;
|
|
91
98
|
let pixelHeight;
|
|
92
99
|
if (hybridScale != null) {
|
|
@@ -103,6 +110,7 @@ function buildSectionScale(data, opts) {
|
|
|
103
110
|
if (scale == null) {
|
|
104
111
|
_pixelScale = density.sectionDensity(opts)({
|
|
105
112
|
extent: dAge,
|
|
113
|
+
visibleExtent,
|
|
106
114
|
unitExtents: visibleUnitExtents(data, axisType, visibleWindow),
|
|
107
115
|
units: data,
|
|
108
116
|
sectionID,
|
|
@@ -117,6 +125,9 @@ function buildSectionScale(data, opts) {
|
|
|
117
125
|
0
|
|
118
126
|
);
|
|
119
127
|
}
|
|
128
|
+
function dx(range) {
|
|
129
|
+
return Math.abs(range[0] - range[1]);
|
|
130
|
+
}
|
|
120
131
|
function resolveWindowScales(sections, focalWindow, floor) {
|
|
121
132
|
const [b_focal, t_focal] = focalWindow;
|
|
122
133
|
const scales = /* @__PURE__ */ new Map();
|
|
@@ -143,7 +154,9 @@ function padWindowByPixels(sections, window, padding, scaleFor) {
|
|
|
143
154
|
function spendOutward(sections, edge, direction, padding, scaleFor) {
|
|
144
155
|
const beyond = sections.filter(
|
|
145
156
|
(s) => direction * (s.b_age - edge) > 0 || direction * (s.t_age - edge) > 0
|
|
146
|
-
).sort(
|
|
157
|
+
).sort(
|
|
158
|
+
(a, b) => direction * (nearEdge(a, direction) - nearEdge(b, direction))
|
|
159
|
+
);
|
|
147
160
|
let bound = edge;
|
|
148
161
|
let budget = padding;
|
|
149
162
|
for (const section of beyond) {
|
|
@@ -241,10 +254,7 @@ function visibleUnitExtents(data, axisType, visibleWindow) {
|
|
|
241
254
|
const [b_pos, t_pos] = utils.getUnitHeightRange(d, axisType);
|
|
242
255
|
if (!clip) return Math.abs(b_pos - t_pos);
|
|
243
256
|
const [b_win, t_win] = visibleWindow;
|
|
244
|
-
return Math.max(
|
|
245
|
-
0,
|
|
246
|
-
Math.min(b_pos, b_win) - Math.max(t_pos, t_win)
|
|
247
|
-
);
|
|
257
|
+
return Math.max(0, Math.min(b_pos, b_win) - Math.max(t_pos, t_win));
|
|
248
258
|
}).filter((d) => d > 0);
|
|
249
259
|
const useWindow = visibleWindow != null && axisType === columnComponents.ColumnAxisType.AGE;
|
|
250
260
|
let heights = useWindow ? durations(true) : [];
|