@genome-spy/core 0.78.0 → 0.79.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle/{browser-KWU9rWZT.js → browser-CETrb2cm.js} +53 -33
- package/dist/bundle/esm-BdLYkz-m.js +248 -0
- package/dist/bundle/esm-BwiDsqSb.js +1367 -0
- package/dist/bundle/esm-CDFd1cjk.js +441 -0
- package/dist/bundle/{esm-DVOHLB1e.js → esm-CTUHLDbv.js} +30 -30
- package/dist/bundle/{esm-NIYEaYkc.js → esm-Cx-EbkOj.js} +13 -13
- package/dist/bundle/esm-DlYGqi79.js +128 -0
- package/dist/bundle/{esm-BygJiwh0.js → esm-k9p3oHkt.js} +133 -158
- package/dist/bundle/{esm-CT3ygiMq.js → esm-zAZJQO6D.js} +226 -212
- package/dist/bundle/index.es.js +14840 -11661
- package/dist/bundle/index.js +119 -108
- package/dist/bundle/{parquetRead-DG_-F5j5.js → parquetRead-Cad1SOVV.js} +473 -399
- package/dist/schema.json +18940 -6914
- package/dist/src/config/axisConfig.d.ts +2 -2
- package/dist/src/config/axisConfig.d.ts.map +1 -1
- package/dist/src/config/axisConfig.js +28 -44
- package/dist/src/config/configLayers.d.ts +45 -0
- package/dist/src/config/configLayers.d.ts.map +1 -0
- package/dist/src/config/configLayers.js +110 -0
- package/dist/src/config/defaultConfig.d.ts.map +1 -1
- package/dist/src/config/defaultConfig.js +8 -1
- package/dist/src/config/defaults/legendDefaults.d.ts +14 -0
- package/dist/src/config/defaults/legendDefaults.d.ts.map +1 -0
- package/dist/src/config/defaults/legendDefaults.js +46 -0
- package/dist/src/config/defaults/titleDefaults.d.ts.map +1 -1
- package/dist/src/config/defaults/titleDefaults.js +26 -18
- package/dist/src/config/legendConfig.d.ts +11 -0
- package/dist/src/config/legendConfig.d.ts.map +1 -0
- package/dist/src/config/legendConfig.js +63 -0
- package/dist/src/config/styleUtils.d.ts +8 -2
- package/dist/src/config/styleUtils.d.ts.map +1 -1
- package/dist/src/config/styleUtils.js +25 -1
- package/dist/src/config/themes.d.ts.map +1 -1
- package/dist/src/config/themes.js +21 -2
- package/dist/src/config/titleConfig.d.ts.map +1 -1
- package/dist/src/config/titleConfig.js +2 -18
- package/dist/src/data/collector.d.ts.map +1 -1
- package/dist/src/data/collector.js +40 -18
- package/dist/src/data/flowInit.d.ts +6 -0
- package/dist/src/data/flowInit.d.ts.map +1 -1
- package/dist/src/data/flowInit.js +1 -1
- package/dist/src/data/flowNode.d.ts +32 -0
- package/dist/src/data/flowNode.d.ts.map +1 -1
- package/dist/src/data/flowNode.js +59 -0
- package/dist/src/data/sources/lazy/bamSource.d.ts +0 -1
- package/dist/src/data/sources/lazy/bamSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/bamSource.js +39 -30
- package/dist/src/data/sources/lazy/bigBedSource.d.ts +0 -10
- package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/bigBedSource.js +127 -62
- package/dist/src/data/sources/lazy/bigWigSource.d.ts +2 -2
- package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/bigWigSource.js +234 -81
- package/dist/src/data/sources/lazy/gff3Source.d.ts +7 -3
- package/dist/src/data/sources/lazy/gff3Source.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/gff3Source.js +7 -8
- package/dist/src/data/sources/lazy/indexedFastaSource.d.ts +1 -1
- package/dist/src/data/sources/lazy/indexedFastaSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/indexedFastaSource.js +28 -19
- package/dist/src/data/sources/lazy/legendEntriesSource.d.ts +24 -0
- package/dist/src/data/sources/lazy/legendEntriesSource.d.ts.map +1 -0
- package/dist/src/data/sources/lazy/legendEntriesSource.js +217 -0
- package/dist/src/data/sources/lazy/legendGradientSource.d.ts +30 -0
- package/dist/src/data/sources/lazy/legendGradientSource.d.ts.map +1 -0
- package/dist/src/data/sources/lazy/legendGradientSource.js +388 -0
- package/dist/src/data/sources/lazy/mockLazySource.d.ts +4 -1
- package/dist/src/data/sources/lazy/mockLazySource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/mockLazySource.js +49 -4
- package/dist/src/data/sources/lazy/registerCoreLazySources.js +2 -0
- package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +3 -4
- package/dist/src/data/sources/lazy/tabixSource.d.ts +9 -4
- package/dist/src/data/sources/lazy/tabixSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/tabixSource.js +201 -70
- package/dist/src/data/sources/lazy/tabixTsvSource.d.ts +2 -3
- package/dist/src/data/sources/lazy/tabixTsvSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/tabixTsvSource.js +14 -12
- package/dist/src/data/sources/lazy/vcfSource.d.ts +7 -3
- package/dist/src/data/sources/lazy/vcfSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/vcfSource.js +7 -8
- package/dist/src/data/sources/urlDescriptor.d.ts +165 -0
- package/dist/src/data/sources/urlDescriptor.d.ts.map +1 -0
- package/dist/src/data/sources/urlDescriptor.js +473 -0
- package/dist/src/data/sources/urlDescriptorController.d.ts +25 -0
- package/dist/src/data/sources/urlDescriptorController.d.ts.map +1 -0
- package/dist/src/data/sources/urlDescriptorController.js +72 -0
- package/dist/src/data/sources/urlDescriptorState.d.ts +47 -0
- package/dist/src/data/sources/urlDescriptorState.d.ts.map +1 -0
- package/dist/src/data/sources/urlDescriptorState.js +129 -0
- package/dist/src/data/sources/urlSource.d.ts.map +1 -1
- package/dist/src/data/sources/urlSource.js +101 -61
- package/dist/src/data/transforms/packLegendLabels.d.ts +21 -0
- package/dist/src/data/transforms/packLegendLabels.d.ts.map +1 -0
- package/dist/src/data/transforms/packLegendLabels.js +189 -0
- package/dist/src/data/transforms/transformFactory.d.ts.map +1 -1
- package/dist/src/data/transforms/transformFactory.js +4 -0
- package/dist/src/data/transforms/truncateText.d.ts +27 -0
- package/dist/src/data/transforms/truncateText.d.ts.map +1 -0
- package/dist/src/data/transforms/truncateText.js +94 -0
- package/dist/src/debug/dataflowDebugSnapshot.d.ts +58 -0
- package/dist/src/debug/dataflowDebugSnapshot.d.ts.map +1 -0
- package/dist/src/debug/dataflowDebugSnapshot.js +159 -0
- package/dist/src/debug/markDebugSnapshot.d.ts +54 -0
- package/dist/src/debug/markDebugSnapshot.d.ts.map +1 -0
- package/dist/src/debug/markDebugSnapshot.js +100 -0
- package/dist/src/debug/paramDebugSnapshot.d.ts +53 -0
- package/dist/src/debug/paramDebugSnapshot.d.ts.map +1 -0
- package/dist/src/debug/paramDebugSnapshot.js +86 -0
- package/dist/src/debug/resolutionDebugSnapshot.d.ts +155 -0
- package/dist/src/debug/resolutionDebugSnapshot.d.ts.map +1 -0
- package/dist/src/debug/resolutionDebugSnapshot.js +291 -0
- package/dist/src/debug/valuePreview.d.ts +9 -0
- package/dist/src/debug/valuePreview.d.ts.map +1 -0
- package/dist/src/debug/valuePreview.js +57 -0
- package/dist/src/debug/viewDebugSnapshot.d.ts +131 -0
- package/dist/src/debug/viewDebugSnapshot.d.ts.map +1 -0
- package/dist/src/debug/viewDebugSnapshot.js +390 -0
- package/dist/src/embedFactory.d.ts.map +1 -1
- package/dist/src/embedFactory.js +6 -1
- package/dist/src/encoder/encoder.d.ts +2 -2
- package/dist/src/encoder/encoder.d.ts.map +1 -1
- package/dist/src/encoder/encoder.js +5 -4
- package/dist/src/fonts/bmFontManager.d.ts +1 -1
- package/dist/src/fonts/bmFontManager.d.ts.map +1 -1
- package/dist/src/fonts/bmFontManager.js +45 -10
- package/dist/src/fonts/textMetrics.d.ts +69 -0
- package/dist/src/fonts/textMetrics.d.ts.map +1 -0
- package/dist/src/fonts/textMetrics.js +73 -0
- package/dist/src/genomeSpy/headlessBootstrap.d.ts.map +1 -1
- package/dist/src/genomeSpy/headlessBootstrap.js +6 -0
- package/dist/src/genomeSpy/renderCoordinator.d.ts.map +1 -1
- package/dist/src/genomeSpy/renderCoordinator.js +25 -3
- package/dist/src/genomeSpy/viewDataInit.d.ts +14 -0
- package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -1
- package/dist/src/genomeSpy/viewDataInit.js +45 -8
- package/dist/src/genomeSpyBase.d.ts +6 -0
- package/dist/src/genomeSpyBase.d.ts.map +1 -1
- package/dist/src/genomeSpyBase.js +20 -3
- package/dist/src/gl/glslScaleGenerator.d.ts +17 -0
- package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
- package/dist/src/gl/glslScaleGenerator.js +39 -2
- package/dist/src/gl/includes/common.glsl.js +1 -1
- package/dist/src/gl/vertexRangeIndex.d.ts.map +1 -1
- package/dist/src/gl/vertexRangeIndex.js +4 -2
- package/dist/src/gl/webGLHelper.d.ts +1 -1
- package/dist/src/gl/webGLHelper.d.ts.map +1 -1
- package/dist/src/gl/webGLHelper.js +13 -8
- package/dist/src/marks/__snapshots__/shaderSnapshot.test.js.snap +140 -3
- package/dist/src/marks/mark.d.ts +47 -4
- package/dist/src/marks/mark.d.ts.map +1 -1
- package/dist/src/marks/mark.js +158 -54
- package/dist/src/marks/point.d.ts.map +1 -1
- package/dist/src/marks/point.js +4 -0
- package/dist/src/marks/point.vertex.glsl.js +1 -1
- package/dist/src/marks/text.d.ts +1 -1
- package/dist/src/marks/text.d.ts.map +1 -1
- package/dist/src/marks/text.js +2 -7
- package/dist/src/marks/text.vertex.glsl.js +1 -1
- package/dist/src/paramRuntime/paramUtils.d.ts +43 -9
- package/dist/src/paramRuntime/paramUtils.d.ts.map +1 -1
- package/dist/src/paramRuntime/paramUtils.js +61 -1
- package/dist/src/paramRuntime/viewParamRuntime.d.ts +32 -0
- package/dist/src/paramRuntime/viewParamRuntime.d.ts.map +1 -1
- package/dist/src/paramRuntime/viewParamRuntime.js +63 -0
- package/dist/src/scales/axisResolution.d.ts +35 -0
- package/dist/src/scales/axisResolution.d.ts.map +1 -1
- package/dist/src/scales/axisResolution.js +115 -7
- package/dist/src/scales/legendResolution.d.ts +83 -0
- package/dist/src/scales/legendResolution.d.ts.map +1 -0
- package/dist/src/scales/legendResolution.js +461 -0
- package/dist/src/scales/scaleResolution.d.ts +36 -0
- package/dist/src/scales/scaleResolution.d.ts.map +1 -1
- package/dist/src/scales/scaleResolution.js +59 -0
- package/dist/src/scales/viewLevelGuideConfig.d.ts +53 -0
- package/dist/src/scales/viewLevelGuideConfig.d.ts.map +1 -0
- package/dist/src/scales/viewLevelGuideConfig.js +224 -0
- package/dist/src/scales/viewLevelScaleConfig.d.ts.map +1 -1
- package/dist/src/scales/viewLevelScaleConfig.js +13 -2
- package/dist/src/spec/axis.d.ts +109 -3
- package/dist/src/spec/channel.d.ts +23 -4
- package/dist/src/spec/config.d.ts +59 -4
- package/dist/src/spec/data.d.ts +177 -17
- package/dist/src/spec/legend.d.ts +246 -0
- package/dist/src/spec/mark.d.ts +16 -4
- package/dist/src/spec/title.d.ts +58 -1
- package/dist/src/spec/transform.d.ts +149 -0
- package/dist/src/spec/view.d.ts +39 -6
- package/dist/src/types/embedApi.d.ts +262 -6
- package/dist/src/types/rendering.d.ts +19 -3
- package/dist/src/types/viewContext.d.ts +18 -2
- package/dist/src/utils/arrayUtils.d.ts +11 -0
- package/dist/src/utils/arrayUtils.d.ts.map +1 -1
- package/dist/src/utils/arrayUtils.js +23 -0
- package/dist/src/utils/suspension.d.ts +17 -0
- package/dist/src/utils/suspension.d.ts.map +1 -0
- package/dist/src/utils/suspension.js +41 -0
- package/dist/src/view/axisGridView.d.ts.map +1 -1
- package/dist/src/view/axisGridView.js +1 -4
- package/dist/src/view/axisView.d.ts +18 -2
- package/dist/src/view/axisView.d.ts.map +1 -1
- package/dist/src/view/axisView.js +180 -75
- package/dist/src/view/concatView.d.ts +10 -2
- package/dist/src/view/concatView.d.ts.map +1 -1
- package/dist/src/view/concatView.js +46 -9
- package/dist/src/view/containerMutationHelper.d.ts +20 -1
- package/dist/src/view/containerMutationHelper.d.ts.map +1 -1
- package/dist/src/view/containerMutationHelper.js +196 -33
- package/dist/src/view/facetView.d.ts +1 -1
- package/dist/src/view/gridView/gridChild.d.ts +54 -4
- package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
- package/dist/src/view/gridView/gridChild.js +301 -120
- package/dist/src/view/gridView/gridChildLegends.d.ts +57 -0
- package/dist/src/view/gridView/gridChildLegends.d.ts.map +1 -0
- package/dist/src/view/gridView/gridChildLegends.js +503 -0
- package/dist/src/view/gridView/gridView.d.ts +25 -0
- package/dist/src/view/gridView/gridView.d.ts.map +1 -1
- package/dist/src/view/gridView/gridView.js +454 -78
- package/dist/src/view/gridView/legendLayout.d.ts +26 -0
- package/dist/src/view/gridView/legendLayout.d.ts.map +1 -0
- package/dist/src/view/gridView/legendLayout.js +111 -0
- package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
- package/dist/src/view/gridView/scrollbar.js +1 -4
- package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
- package/dist/src/view/gridView/selectionRect.js +1 -4
- package/dist/src/view/gridView/separatorView.d.ts.map +1 -1
- package/dist/src/view/gridView/separatorView.js +1 -4
- package/dist/src/view/layerView.d.ts +9 -2
- package/dist/src/view/layerView.d.ts.map +1 -1
- package/dist/src/view/layerView.js +18 -1
- package/dist/src/view/layout/flexLayout.d.ts +20 -4
- package/dist/src/view/layout/flexLayout.d.ts.map +1 -1
- package/dist/src/view/layout/flexLayout.js +331 -31
- package/dist/src/view/layout/rectangle.d.ts +14 -0
- package/dist/src/view/layout/rectangle.d.ts.map +1 -1
- package/dist/src/view/layout/rectangle.js +40 -0
- package/dist/src/view/legend/legendEntries.d.ts +20 -0
- package/dist/src/view/legend/legendEntries.d.ts.map +1 -0
- package/dist/src/view/legend/legendEntries.js +21 -0
- package/dist/src/view/legendView.d.ts +134 -0
- package/dist/src/view/legendView.d.ts.map +1 -0
- package/dist/src/view/legendView.js +1611 -0
- package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts.map +1 -1
- package/dist/src/view/renderingContext/bufferedViewRenderingContext.js +26 -4
- package/dist/src/view/renderingContext/clipOptions.d.ts +44 -0
- package/dist/src/view/renderingContext/clipOptions.d.ts.map +1 -0
- package/dist/src/view/renderingContext/clipOptions.js +140 -0
- package/dist/src/view/renderingContext/simpleViewRenderingContext.d.ts.map +1 -1
- package/dist/src/view/renderingContext/simpleViewRenderingContext.js +12 -1
- package/dist/src/view/resolutionPlanner.d.ts +2 -1
- package/dist/src/view/resolutionPlanner.d.ts.map +1 -1
- package/dist/src/view/resolutionPlanner.js +89 -25
- package/dist/src/view/testUtils.d.ts +4 -2
- package/dist/src/view/testUtils.d.ts.map +1 -1
- package/dist/src/view/testUtils.js +29 -7
- package/dist/src/view/titleView.d.ts +37 -0
- package/dist/src/view/titleView.d.ts.map +1 -0
- package/dist/src/view/titleView.js +584 -0
- package/dist/src/view/unitView.d.ts +3 -3
- package/dist/src/view/unitView.d.ts.map +1 -1
- package/dist/src/view/unitView.js +3 -2
- package/dist/src/view/view.d.ts +25 -24
- package/dist/src/view/view.d.ts.map +1 -1
- package/dist/src/view/view.js +121 -16
- package/dist/src/view/viewFactory.d.ts +2 -5
- package/dist/src/view/viewFactory.d.ts.map +1 -1
- package/dist/src/view/viewFactory.js +1 -2
- package/dist/src/view/viewIdentityRegistry.d.ts +37 -0
- package/dist/src/view/viewIdentityRegistry.d.ts.map +1 -0
- package/dist/src/view/viewIdentityRegistry.js +71 -0
- package/dist/src/view/viewMutationAcidTestUtils.d.ts +112 -0
- package/dist/src/view/viewMutationAcidTestUtils.d.ts.map +1 -0
- package/dist/src/view/viewMutationAcidTestUtils.js +234 -0
- package/dist/src/view/viewMutationApi.d.ts +42 -0
- package/dist/src/view/viewMutationApi.d.ts.map +1 -0
- package/dist/src/view/viewMutationApi.js +811 -0
- package/dist/src/view/viewSelectors.d.ts +10 -0
- package/dist/src/view/viewSelectors.d.ts.map +1 -1
- package/dist/src/view/viewSelectors.js +23 -1
- package/package.json +4 -4
- package/dist/bundle/esm-CuMSzCHy.js +0 -298
- package/dist/bundle/esm-DAnOffpD.js +0 -1426
- package/dist/bundle/esm-DMXpJXM4.js +0 -369
- package/dist/bundle/esm-DNtC3H80.js +0 -121
- package/dist/src/view/title.d.ts +0 -13
- package/dist/src/view/title.d.ts.map +0 -1
- package/dist/src/view/title.js +0 -154
- /package/dist/bundle/{AbortablePromiseCache-3gHJdF3E.js → AbortablePromiseCache-BTmAcN-t.js} +0 -0
- /package/dist/bundle/{esm-CuVa5T98.js → esm-VvpZ9hsq.js} +0 -0
- /package/dist/bundle/{chunk-DmhlhrBa.js → rolldown-runtime-Dy4uBu1J.js} +0 -0
|
@@ -2,6 +2,8 @@ import { primaryPositionalChannels } from "../../encoder/encoder.js";
|
|
|
2
2
|
import {
|
|
3
3
|
FlexDimensions,
|
|
4
4
|
getLargestSize,
|
|
5
|
+
getSizeDefMaxPx,
|
|
6
|
+
getSizeDefMinPx,
|
|
5
7
|
mapToPixelCoords,
|
|
6
8
|
parseSizeDef,
|
|
7
9
|
ZERO_SIZEDEF,
|
|
@@ -9,7 +11,11 @@ import {
|
|
|
9
11
|
import Grid from "../layout/grid.js";
|
|
10
12
|
import Padding from "../layout/padding.js";
|
|
11
13
|
import Rectangle from "../layout/rectangle.js";
|
|
12
|
-
import AxisView, {
|
|
14
|
+
import AxisView, {
|
|
15
|
+
CHANNEL_ORIENTS,
|
|
16
|
+
ORIENT_CHANNELS,
|
|
17
|
+
getExternalAxisOverhang,
|
|
18
|
+
} from "../axisView.js";
|
|
13
19
|
import ContainerView from "../containerView.js";
|
|
14
20
|
import {
|
|
15
21
|
propagateInteraction,
|
|
@@ -20,9 +26,26 @@ import UnitView from "../unitView.js";
|
|
|
20
26
|
import { interactionToZoom } from "../zoom.js";
|
|
21
27
|
import GridChild from "./gridChild.js";
|
|
22
28
|
import KeyboardZoomController from "./keyboardZoomController.js";
|
|
29
|
+
import { renderLocalLegends } from "./legendLayout.js";
|
|
30
|
+
import {
|
|
31
|
+
addLegendView,
|
|
32
|
+
createGridChildLegend,
|
|
33
|
+
disposeLegendViews,
|
|
34
|
+
getLegendOverhang,
|
|
35
|
+
getOrderedLegendEntries,
|
|
36
|
+
iterateLegendViews,
|
|
37
|
+
isActiveLegendRegion,
|
|
38
|
+
} from "./gridChildLegends.js";
|
|
23
39
|
import SeparatorView, { resolveSeparatorProps } from "./separatorView.js";
|
|
24
40
|
import { getZoomableResolutions } from "./zoomNavigationUtils.js";
|
|
41
|
+
import { moveArrayItem } from "../../utils/arrayUtils.js";
|
|
25
42
|
import { isHConcatSpec, isVConcatSpec } from "../viewSpecGuards.js";
|
|
43
|
+
import {
|
|
44
|
+
clipCoords,
|
|
45
|
+
combineClipOptions,
|
|
46
|
+
createClipOptions,
|
|
47
|
+
normalizeClipOptions,
|
|
48
|
+
} from "../renderingContext/clipOptions.js";
|
|
26
49
|
|
|
27
50
|
// Secondary ordering within a z-index bucket for GridView-owned decorations.
|
|
28
51
|
// These are not z-indices themselves: actual layering is decided first by the
|
|
@@ -34,6 +57,7 @@ const DECORATION_ORDER = Object.freeze({
|
|
|
34
57
|
grid: 20,
|
|
35
58
|
backgroundStroke: 30,
|
|
36
59
|
axis: 40,
|
|
60
|
+
legend: 50,
|
|
37
61
|
selectionRect: 80,
|
|
38
62
|
scrollbar: 90,
|
|
39
63
|
title: 100,
|
|
@@ -44,6 +68,76 @@ const DECORATION_ORDER = Object.freeze({
|
|
|
44
68
|
// letting an explicit user zindex override the default.
|
|
45
69
|
const CLIPPED_DECORATION_ZINDEX = 10;
|
|
46
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Legends are rendered as guide regions, not grid children. Their thickness is
|
|
73
|
+
* handled as overhang, but their parallel min/max constraints still affect the
|
|
74
|
+
* grid dimension that the parent concat sees.
|
|
75
|
+
*
|
|
76
|
+
* @param {import("./gridChildLegends.js").GridChildLegends} legends
|
|
77
|
+
* @returns {FlexDimensions}
|
|
78
|
+
*/
|
|
79
|
+
function getLegendParallelSizeConstraints(legends) {
|
|
80
|
+
/** @type {import("../layout/flexLayout.js").SizeDef[]} */
|
|
81
|
+
const widths = [];
|
|
82
|
+
/** @type {import("../layout/flexLayout.js").SizeDef[]} */
|
|
83
|
+
const heights = [];
|
|
84
|
+
|
|
85
|
+
for (const [orient, region] of Object.entries(legends)) {
|
|
86
|
+
if (!isActiveLegendRegion(region)) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const size = region.legendView.getSize();
|
|
91
|
+
if (orient == "top" || orient == "bottom") {
|
|
92
|
+
widths.push(size.width);
|
|
93
|
+
} else {
|
|
94
|
+
heights.push(size.height);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return new FlexDimensions(getLargestSize(widths), getLargestSize(heights));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Treat an explicit concat/grid size as preferred available space while still
|
|
103
|
+
* letting fixed children and guide chrome establish a larger minimum. This
|
|
104
|
+
* mirrors flexbox behavior more closely than treating the explicit size as a
|
|
105
|
+
* hard clipping bound.
|
|
106
|
+
*
|
|
107
|
+
* @param {import("../layout/flexLayout.js").SizeDef} preferred
|
|
108
|
+
* @param {import("../layout/flexLayout.js").SizeDef} content
|
|
109
|
+
* @returns {import("../layout/flexLayout.js").SizeDef}
|
|
110
|
+
*/
|
|
111
|
+
function combinePreferredAndContentSize(preferred, content) {
|
|
112
|
+
const preferredGrow = preferred.grow ?? 0;
|
|
113
|
+
const preferredPx = preferred.px ?? 0;
|
|
114
|
+
const minPx = Math.max(
|
|
115
|
+
getSizeDefMinPx(preferred),
|
|
116
|
+
getSizeDefMinPx(content)
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
if (!preferredGrow) {
|
|
120
|
+
return { px: Math.max(preferredPx, minPx), grow: 0 };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** @type {import("../layout/flexLayout.js").SizeDef} */
|
|
124
|
+
const size = {
|
|
125
|
+
px: Math.max(preferredPx, content.px ?? 0),
|
|
126
|
+
grow: preferredGrow,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
if (minPx > (size.px ?? 0)) {
|
|
130
|
+
size.minPx = minPx;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const preferredMaxPx = getSizeDefMaxPx(preferred);
|
|
134
|
+
if (preferredMaxPx !== undefined && preferredMaxPx >= minPx) {
|
|
135
|
+
size.maxPx = preferredMaxPx;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return size;
|
|
139
|
+
}
|
|
140
|
+
|
|
47
141
|
/**
|
|
48
142
|
* Modeled after: https://vega.github.io/vega/docs/layout/
|
|
49
143
|
*
|
|
@@ -97,6 +191,9 @@ export default class GridView extends ContainerView {
|
|
|
97
191
|
*/
|
|
98
192
|
#sharedAxes = {};
|
|
99
193
|
|
|
194
|
+
/** @type {import("./gridChildLegends.js").GridChildLegends} */
|
|
195
|
+
#sharedLegends = {};
|
|
196
|
+
|
|
100
197
|
#childSerial = 0;
|
|
101
198
|
|
|
102
199
|
/** @type {Partial<Record<"horizontal" | "vertical", SeparatorView>>} */
|
|
@@ -223,6 +320,17 @@ export default class GridView extends ContainerView {
|
|
|
223
320
|
this.invalidateSizeCache();
|
|
224
321
|
}
|
|
225
322
|
|
|
323
|
+
/**
|
|
324
|
+
* Moves a child within the grid without disposing it.
|
|
325
|
+
*
|
|
326
|
+
* @param {number} fromIndex
|
|
327
|
+
* @param {number} index Destination index after temporarily removing the child.
|
|
328
|
+
*/
|
|
329
|
+
moveChildAt(fromIndex, index) {
|
|
330
|
+
moveArrayItem(this.#children, fromIndex, index);
|
|
331
|
+
this.invalidateSizeCache();
|
|
332
|
+
}
|
|
333
|
+
|
|
226
334
|
get #visibleChildren() {
|
|
227
335
|
return this.#children.filter((gridChild) =>
|
|
228
336
|
gridChild.view.isConfiguredVisible()
|
|
@@ -275,10 +383,25 @@ export default class GridView extends ContainerView {
|
|
|
275
383
|
* @protected
|
|
276
384
|
*/
|
|
277
385
|
async createAxes() {
|
|
386
|
+
await this.syncGuideViews();
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Recreates guide and chrome views that depend on the child hierarchy.
|
|
391
|
+
* Shared guides always depend on the whole container. Grid-child guides can
|
|
392
|
+
* be limited to newly inserted children during mutations.
|
|
393
|
+
*
|
|
394
|
+
* @param {{ gridChildren?: GridChild[] }} [options]
|
|
395
|
+
*/
|
|
396
|
+
async syncGuideViews(options = {}) {
|
|
397
|
+
const gridChildren = options.gridChildren ?? this.#children;
|
|
398
|
+
|
|
278
399
|
await this.syncSharedAxes();
|
|
400
|
+
await this.syncSharedLegends();
|
|
279
401
|
await Promise.all(
|
|
280
|
-
|
|
402
|
+
gridChildren.map((gridChild) => gridChild.createAxes())
|
|
281
403
|
);
|
|
404
|
+
this.invalidateSizeCache();
|
|
282
405
|
}
|
|
283
406
|
|
|
284
407
|
/**
|
|
@@ -325,6 +448,25 @@ export default class GridView extends ContainerView {
|
|
|
325
448
|
await Promise.all(promises);
|
|
326
449
|
}
|
|
327
450
|
|
|
451
|
+
/**
|
|
452
|
+
* Recreates shared legends based on current legend resolutions.
|
|
453
|
+
*
|
|
454
|
+
* Shared legends are GridView-owned for the same reason as shared axes:
|
|
455
|
+
* their placement is relative to the whole child grid, not any individual
|
|
456
|
+
* GridChild.
|
|
457
|
+
*/
|
|
458
|
+
async syncSharedLegends() {
|
|
459
|
+
disposeLegendViews(this.#sharedLegends);
|
|
460
|
+
this.#sharedLegends = {};
|
|
461
|
+
|
|
462
|
+
for (const { definition, resolution } of getOrderedLegendEntries([
|
|
463
|
+
this,
|
|
464
|
+
])) {
|
|
465
|
+
const legend = await createGridChildLegend(definition, this);
|
|
466
|
+
await addLegendView(this.#sharedLegends, legend, resolution);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
328
470
|
/**
|
|
329
471
|
* @returns {IterableIterator<View>}
|
|
330
472
|
*/
|
|
@@ -340,6 +482,8 @@ export default class GridView extends ContainerView {
|
|
|
340
482
|
for (const axisView of Object.values(this.#sharedAxes)) {
|
|
341
483
|
yield axisView;
|
|
342
484
|
}
|
|
485
|
+
|
|
486
|
+
yield* iterateLegendViews(this.#sharedLegends);
|
|
343
487
|
}
|
|
344
488
|
|
|
345
489
|
/**
|
|
@@ -367,17 +511,48 @@ export default class GridView extends ContainerView {
|
|
|
367
511
|
})
|
|
368
512
|
.reduce((a, b) => Math.max(a, b), 0);
|
|
369
513
|
|
|
514
|
+
/**
|
|
515
|
+
* @param {GridChild} child
|
|
516
|
+
* @returns {import("../layout/flexLayout.js").SizeDef}
|
|
517
|
+
*/
|
|
518
|
+
const getPlotSize = (child) => {
|
|
519
|
+
// External overhang is represented by axis/padding slots. The
|
|
520
|
+
// growable view slot should contain only the child's plot area.
|
|
521
|
+
const size = child.view.getViewportSize()[dim];
|
|
522
|
+
const overhang = child.view.getOverhang();
|
|
523
|
+
const overhangSize =
|
|
524
|
+
direction == "column" ? overhang.width : overhang.height;
|
|
525
|
+
|
|
526
|
+
const plotSize = {
|
|
527
|
+
px: Math.max((size.px ?? 0) - overhangSize, 0),
|
|
528
|
+
grow: size.grow,
|
|
529
|
+
minPx:
|
|
530
|
+
size.minPx === undefined
|
|
531
|
+
? undefined
|
|
532
|
+
: Math.max(size.minPx - overhangSize, 0),
|
|
533
|
+
maxPx:
|
|
534
|
+
size.maxPx === undefined
|
|
535
|
+
? undefined
|
|
536
|
+
: Math.max(size.maxPx - overhangSize, 0),
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
const legendSize = getLegendParallelSizeConstraints(child.legends);
|
|
540
|
+
// Side legends constrain row height, while top/bottom legends
|
|
541
|
+
// constrain column width. Their perpendicular size is overhang.
|
|
542
|
+
return getLargestSize([
|
|
543
|
+
plotSize,
|
|
544
|
+
direction == "column" ? legendSize.width : legendSize.height,
|
|
545
|
+
]);
|
|
546
|
+
};
|
|
547
|
+
|
|
370
548
|
return this._cache(`size/directionSizes/${direction}`, () =>
|
|
371
549
|
this.#grid[direction == "column" ? "colIndices" : "rowIndices"].map(
|
|
372
550
|
(col) => ({
|
|
373
551
|
axisBefore: getMaxAxisSize(col, 0),
|
|
374
552
|
axisAfter: getMaxAxisSize(col, 1),
|
|
375
553
|
view: getLargestSize(
|
|
376
|
-
col.map(
|
|
377
|
-
(rowIndex)
|
|
378
|
-
this.#visibleChildren[
|
|
379
|
-
rowIndex
|
|
380
|
-
].view.getViewportSize()[dim]
|
|
554
|
+
col.map((rowIndex) =>
|
|
555
|
+
getPlotSize(this.#visibleChildren[rowIndex])
|
|
381
556
|
)
|
|
382
557
|
),
|
|
383
558
|
})
|
|
@@ -448,12 +623,21 @@ export default class GridView extends ContainerView {
|
|
|
448
623
|
#getFlexSize(direction) {
|
|
449
624
|
let grow = 0;
|
|
450
625
|
let px = 0;
|
|
626
|
+
let minPx = 0;
|
|
627
|
+
let maxPx = 0;
|
|
628
|
+
let hasMaxPx = true;
|
|
451
629
|
|
|
452
630
|
const explicitSize =
|
|
453
631
|
direction == "row" ? this.spec.height : this.spec.width;
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
632
|
+
const preferredSize =
|
|
633
|
+
explicitSize || explicitSize === 0
|
|
634
|
+
? parseSizeDef(explicitSize)
|
|
635
|
+
: undefined;
|
|
636
|
+
const usePreferredAsViewSlot =
|
|
637
|
+
preferredSize &&
|
|
638
|
+
(direction == "column"
|
|
639
|
+
? this.#grid.colIndices.length == 1
|
|
640
|
+
: this.#grid.rowIndices.length == 1);
|
|
457
641
|
|
|
458
642
|
const sizes = this.#getSizes(direction);
|
|
459
643
|
|
|
@@ -461,6 +645,8 @@ export default class GridView extends ContainerView {
|
|
|
461
645
|
if (i > 0) {
|
|
462
646
|
// Spacing
|
|
463
647
|
px += this.#spacing;
|
|
648
|
+
minPx += this.#spacing;
|
|
649
|
+
maxPx += this.#spacing;
|
|
464
650
|
}
|
|
465
651
|
|
|
466
652
|
if (i == 0 || this.wrappingFacet) {
|
|
@@ -470,13 +656,28 @@ export default class GridView extends ContainerView {
|
|
|
470
656
|
|
|
471
657
|
// Axis/padding
|
|
472
658
|
px += size.axisBefore;
|
|
659
|
+
minPx += size.axisBefore;
|
|
660
|
+
maxPx += size.axisBefore;
|
|
473
661
|
|
|
474
662
|
// View
|
|
475
|
-
|
|
476
|
-
|
|
663
|
+
const viewSize = usePreferredAsViewSlot
|
|
664
|
+
? combinePreferredAndContentSize(preferredSize, size.view)
|
|
665
|
+
: size.view;
|
|
666
|
+
px += viewSize.px ?? 0;
|
|
667
|
+
grow += viewSize.grow ?? 0;
|
|
668
|
+
minPx += getSizeDefMinPx(viewSize);
|
|
669
|
+
|
|
670
|
+
const viewMaxPx = getSizeDefMaxPx(viewSize);
|
|
671
|
+
if (viewMaxPx === undefined) {
|
|
672
|
+
hasMaxPx = false;
|
|
673
|
+
} else {
|
|
674
|
+
maxPx += viewMaxPx;
|
|
675
|
+
}
|
|
477
676
|
|
|
478
677
|
// Axis/padding
|
|
479
678
|
px += size.axisAfter;
|
|
679
|
+
minPx += size.axisAfter;
|
|
680
|
+
maxPx += size.axisAfter;
|
|
480
681
|
|
|
481
682
|
if (i == sizes.length - 1 || this.wrappingFacet) {
|
|
482
683
|
//Footer
|
|
@@ -484,7 +685,16 @@ export default class GridView extends ContainerView {
|
|
|
484
685
|
}
|
|
485
686
|
}
|
|
486
687
|
|
|
487
|
-
|
|
688
|
+
const measuredSize = {
|
|
689
|
+
px,
|
|
690
|
+
grow,
|
|
691
|
+
minPx: minPx || undefined,
|
|
692
|
+
maxPx: sizes.length && hasMaxPx ? maxPx : undefined,
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
return preferredSize && !usePreferredAsViewSlot
|
|
696
|
+
? combinePreferredAndContentSize(preferredSize, measuredSize)
|
|
697
|
+
: measuredSize;
|
|
488
698
|
}
|
|
489
699
|
|
|
490
700
|
/**
|
|
@@ -505,7 +715,7 @@ export default class GridView extends ContainerView {
|
|
|
505
715
|
* @return {Padding}
|
|
506
716
|
*/
|
|
507
717
|
getOverhang() {
|
|
508
|
-
return this.#getGridOverhang().
|
|
718
|
+
return this.#getGridOverhang().add(this.#getSharedGuideOverhang());
|
|
509
719
|
}
|
|
510
720
|
|
|
511
721
|
#getGridOverhang() {
|
|
@@ -535,11 +745,7 @@ export default class GridView extends ContainerView {
|
|
|
535
745
|
return 0;
|
|
536
746
|
}
|
|
537
747
|
|
|
538
|
-
return
|
|
539
|
-
axisView.getPerpendicularSize() +
|
|
540
|
-
(axisView.axisProps.offset ?? 0),
|
|
541
|
-
0
|
|
542
|
-
);
|
|
748
|
+
return getExternalAxisOverhang(axisView);
|
|
543
749
|
};
|
|
544
750
|
|
|
545
751
|
return new Padding(
|
|
@@ -550,16 +756,58 @@ export default class GridView extends ContainerView {
|
|
|
550
756
|
);
|
|
551
757
|
}
|
|
552
758
|
|
|
759
|
+
#getSharedLegendOverhang() {
|
|
760
|
+
const getSharedLegendSize = (
|
|
761
|
+
/** @type {import("../../spec/legend.js").LegendOrient} */ orient
|
|
762
|
+
) => getLegendOverhang(this.#sharedLegends, orient);
|
|
763
|
+
|
|
764
|
+
return new Padding(
|
|
765
|
+
getSharedLegendSize("top"),
|
|
766
|
+
getSharedLegendSize("right"),
|
|
767
|
+
getSharedLegendSize("bottom"),
|
|
768
|
+
getSharedLegendSize("left")
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
#getSharedGuideOverhang() {
|
|
773
|
+
return this.#getSharedAxisOverhang().add(
|
|
774
|
+
this.#getSharedLegendOverhang()
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
#getSharedAxesByOrient() {
|
|
779
|
+
/** @type {Partial<Record<import("../../spec/axis.js").AxisOrient, AxisView>>} */
|
|
780
|
+
const axes = {};
|
|
781
|
+
for (const axisView of Object.values(this.#sharedAxes)) {
|
|
782
|
+
axes[axisView.axisProps.orient] = axisView;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
return axes;
|
|
786
|
+
}
|
|
787
|
+
|
|
553
788
|
/**
|
|
554
789
|
* @returns {FlexDimensions}
|
|
555
790
|
*/
|
|
556
791
|
getSize() {
|
|
557
|
-
return this._cache("size", () =>
|
|
558
|
-
|
|
559
|
-
this.#
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
792
|
+
return this._cache("size", () => {
|
|
793
|
+
const parallelLegendSize = getLegendParallelSizeConstraints(
|
|
794
|
+
this.#sharedLegends
|
|
795
|
+
);
|
|
796
|
+
|
|
797
|
+
// Shared legends are placed around the whole grid, so combine their
|
|
798
|
+
// parallel constraints with the child-grid size before adding
|
|
799
|
+
// guide overhang.
|
|
800
|
+
return new FlexDimensions(
|
|
801
|
+
getLargestSize([
|
|
802
|
+
this.#getFlexSize("column"),
|
|
803
|
+
parallelLegendSize.width,
|
|
804
|
+
]),
|
|
805
|
+
getLargestSize([
|
|
806
|
+
this.#getFlexSize("row"),
|
|
807
|
+
parallelLegendSize.height,
|
|
808
|
+
])
|
|
809
|
+
).addPadding(this.#getSharedGuideOverhang());
|
|
810
|
+
});
|
|
563
811
|
}
|
|
564
812
|
|
|
565
813
|
/**
|
|
@@ -578,7 +826,8 @@ export default class GridView extends ContainerView {
|
|
|
578
826
|
// Usually padding is applied by the parent GridView, but if this is the root view, we need to apply it here
|
|
579
827
|
coords = coords.shrink(this.getPadding());
|
|
580
828
|
}
|
|
581
|
-
|
|
829
|
+
const sharedGuideOverhang = this.#getSharedGuideOverhang();
|
|
830
|
+
coords = coords.shrink(sharedGuideOverhang);
|
|
582
831
|
|
|
583
832
|
context.pushView(this, coords);
|
|
584
833
|
|
|
@@ -587,7 +836,7 @@ export default class GridView extends ContainerView {
|
|
|
587
836
|
const flexOpts = {
|
|
588
837
|
devicePixelRatio,
|
|
589
838
|
};
|
|
590
|
-
|
|
839
|
+
let columnFlexCoords = mapToPixelCoords(
|
|
591
840
|
this.#makeFlexItems("column"),
|
|
592
841
|
coords.width,
|
|
593
842
|
flexOpts
|
|
@@ -604,6 +853,33 @@ export default class GridView extends ContainerView {
|
|
|
604
853
|
this.#columns ?? Infinity
|
|
605
854
|
);
|
|
606
855
|
|
|
856
|
+
let columnLayoutDirty = false;
|
|
857
|
+
for (const [i, gridChild] of this.#visibleChildren.entries()) {
|
|
858
|
+
const [col, row] = grid.getCellCoords(i);
|
|
859
|
+
const colLocSize =
|
|
860
|
+
columnFlexCoords[this.#getViewSlot("column", col)];
|
|
861
|
+
const rowLocSize = rowFlexCoords[this.#getViewSlot("row", row)];
|
|
862
|
+
|
|
863
|
+
// Some child views have side overhang that depends on the final
|
|
864
|
+
// row height, such as SampleView's repeated y-axis threshold. Row
|
|
865
|
+
// slots are known here, but final columns may need one more pass if
|
|
866
|
+
// a child reports that its height-dependent overhang changed.
|
|
867
|
+
const layoutChanged =
|
|
868
|
+
/** @type {{ prepareLayoutSize?: (width: number, height: number) => boolean }} */ (
|
|
869
|
+
gridChild.view
|
|
870
|
+
).prepareLayoutSize?.(colLocSize.size, rowLocSize.size);
|
|
871
|
+
columnLayoutDirty ||= layoutChanged === true;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
if (columnLayoutDirty) {
|
|
875
|
+
this._invalidateCacheByPrefix("size/directionSizes/column");
|
|
876
|
+
columnFlexCoords = mapToPixelCoords(
|
|
877
|
+
this.#makeFlexItems("column"),
|
|
878
|
+
coords.width,
|
|
879
|
+
flexOpts
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
|
|
607
883
|
/** @param {number} x */
|
|
608
884
|
const round = (x) =>
|
|
609
885
|
Math.round(x * devicePixelRatio) / devicePixelRatio;
|
|
@@ -641,16 +917,36 @@ export default class GridView extends ContainerView {
|
|
|
641
917
|
/**
|
|
642
918
|
* @param {FlexDimensions} size
|
|
643
919
|
* @param {"width" | "height"} dimension
|
|
920
|
+
* @param {boolean} explicitViewport
|
|
644
921
|
*/
|
|
645
|
-
const getLen = (size, dimension) =>
|
|
646
|
-
|
|
647
|
-
?
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const
|
|
922
|
+
const getLen = (size, dimension, explicitViewport = false) =>
|
|
923
|
+
explicitViewport
|
|
924
|
+
? size[dimension].grow
|
|
925
|
+
? (dimension == "width" ? colLocSize : rowLocSize).size
|
|
926
|
+
: size[dimension].px
|
|
927
|
+
: (dimension == "width" ? colLocSize : rowLocSize).size +
|
|
928
|
+
overhang[dimension];
|
|
929
|
+
|
|
930
|
+
const viewportWidth = getLen(
|
|
931
|
+
viewportSize,
|
|
932
|
+
"width",
|
|
933
|
+
view.spec.viewportWidth != null
|
|
934
|
+
);
|
|
935
|
+
const viewportHeight = getLen(
|
|
936
|
+
viewportSize,
|
|
937
|
+
"height",
|
|
938
|
+
view.spec.viewportHeight != null
|
|
939
|
+
);
|
|
940
|
+
const viewWidth = getLen(
|
|
941
|
+
viewSize,
|
|
942
|
+
"width",
|
|
943
|
+
view.spec.viewportWidth != null
|
|
944
|
+
);
|
|
945
|
+
const viewHeight = getLen(
|
|
946
|
+
viewSize,
|
|
947
|
+
"height",
|
|
948
|
+
view.spec.viewportHeight != null
|
|
949
|
+
);
|
|
654
950
|
|
|
655
951
|
const hScrollbar = gridChild.scrollbars.horizontal;
|
|
656
952
|
const vScrollbar = gridChild.scrollbars.vertical;
|
|
@@ -684,9 +980,8 @@ export default class GridView extends ContainerView {
|
|
|
684
980
|
|
|
685
981
|
gridChild.coords = viewportCoords;
|
|
686
982
|
|
|
687
|
-
const
|
|
688
|
-
|
|
689
|
-
: viewportCoords;
|
|
983
|
+
const parentClip = normalizeClipOptions(options);
|
|
984
|
+
const visibleChildCoords = clipCoords(viewportCoords, parentClip);
|
|
690
985
|
|
|
691
986
|
renderItems.push({
|
|
692
987
|
col,
|
|
@@ -700,7 +995,8 @@ export default class GridView extends ContainerView {
|
|
|
700
995
|
selectionRect,
|
|
701
996
|
viewportCoords,
|
|
702
997
|
viewCoords,
|
|
703
|
-
|
|
998
|
+
parentClip,
|
|
999
|
+
visibleChildCoords,
|
|
704
1000
|
viewWidth,
|
|
705
1001
|
viewHeight,
|
|
706
1002
|
scrollable,
|
|
@@ -755,7 +1051,7 @@ export default class GridView extends ContainerView {
|
|
|
755
1051
|
() =>
|
|
756
1052
|
item.background?.render(
|
|
757
1053
|
context,
|
|
758
|
-
item.
|
|
1054
|
+
item.visibleChildCoords,
|
|
759
1055
|
{
|
|
760
1056
|
...options,
|
|
761
1057
|
clipRect: undefined,
|
|
@@ -809,7 +1105,8 @@ export default class GridView extends ContainerView {
|
|
|
809
1105
|
selectionRect,
|
|
810
1106
|
viewportCoords,
|
|
811
1107
|
viewCoords,
|
|
812
|
-
|
|
1108
|
+
parentClip,
|
|
1109
|
+
visibleChildCoords,
|
|
813
1110
|
viewWidth,
|
|
814
1111
|
viewHeight,
|
|
815
1112
|
scrollable,
|
|
@@ -818,7 +1115,9 @@ export default class GridView extends ContainerView {
|
|
|
818
1115
|
row,
|
|
819
1116
|
} = item;
|
|
820
1117
|
|
|
821
|
-
const
|
|
1118
|
+
const clippedChildren = isClippedChildren(view);
|
|
1119
|
+
const clipped = clippedChildren || scrollable;
|
|
1120
|
+
const clippedDecorations = hasClippedChildren(view) || scrollable;
|
|
822
1121
|
|
|
823
1122
|
for (const gridLineView of Object.values(gridLines)) {
|
|
824
1123
|
queueDecoration(
|
|
@@ -828,6 +1127,19 @@ export default class GridView extends ContainerView {
|
|
|
828
1127
|
);
|
|
829
1128
|
}
|
|
830
1129
|
|
|
1130
|
+
const childClip = clipped
|
|
1131
|
+
? combineClipOptions(
|
|
1132
|
+
parentClip,
|
|
1133
|
+
createClipOptions(
|
|
1134
|
+
visibleChildCoords,
|
|
1135
|
+
clippedChildren ||
|
|
1136
|
+
Boolean(gridChild.scrollbars.horizontal),
|
|
1137
|
+
clippedChildren ||
|
|
1138
|
+
Boolean(gridChild.scrollbars.vertical)
|
|
1139
|
+
)
|
|
1140
|
+
)
|
|
1141
|
+
: options.clip;
|
|
1142
|
+
|
|
831
1143
|
const renderContent = () =>
|
|
832
1144
|
view.render(
|
|
833
1145
|
context,
|
|
@@ -835,7 +1147,8 @@ export default class GridView extends ContainerView {
|
|
|
835
1147
|
clipped
|
|
836
1148
|
? {
|
|
837
1149
|
...options,
|
|
838
|
-
clipRect:
|
|
1150
|
+
clipRect: childClip?.rect,
|
|
1151
|
+
clip: childClip,
|
|
839
1152
|
}
|
|
840
1153
|
: options
|
|
841
1154
|
);
|
|
@@ -846,11 +1159,11 @@ export default class GridView extends ContainerView {
|
|
|
846
1159
|
queueDecoration(
|
|
847
1160
|
defaultBackgroundStrokeZindex(
|
|
848
1161
|
gridChild.backgroundStrokeZindex,
|
|
849
|
-
|
|
1162
|
+
clippedDecorations
|
|
850
1163
|
),
|
|
851
1164
|
DECORATION_ORDER.backgroundStroke,
|
|
852
1165
|
() =>
|
|
853
|
-
backgroundStroke?.render(context,
|
|
1166
|
+
backgroundStroke?.render(context, visibleChildCoords, {
|
|
854
1167
|
...options,
|
|
855
1168
|
clipRect: undefined,
|
|
856
1169
|
})
|
|
@@ -888,39 +1201,51 @@ export default class GridView extends ContainerView {
|
|
|
888
1201
|
axisView
|
|
889
1202
|
);
|
|
890
1203
|
|
|
891
|
-
let
|
|
1204
|
+
let clip = normalizeClipOptions(options);
|
|
1205
|
+
let clipRect = clip?.rect;
|
|
892
1206
|
|
|
893
1207
|
// Scrollable axes must be clipped along the scroll direction.
|
|
894
1208
|
if (scrollable) {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
direction == "vertical"
|
|
900
|
-
? {
|
|
901
|
-
x: -100000,
|
|
902
|
-
width: 200000,
|
|
903
|
-
}
|
|
904
|
-
: {
|
|
905
|
-
y: -100000,
|
|
906
|
-
height: 200000,
|
|
907
|
-
}
|
|
908
|
-
)
|
|
909
|
-
: undefined
|
|
1209
|
+
const axisClip = createClipOptions(
|
|
1210
|
+
viewportCoords,
|
|
1211
|
+
direction == "horizontal",
|
|
1212
|
+
direction == "vertical"
|
|
910
1213
|
);
|
|
1214
|
+
clip = combineClipOptions(clip, axisClip);
|
|
1215
|
+
clipRect = clip?.rect;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
if (clip && axisView.labelClipPolicy === "anchor") {
|
|
1219
|
+
clip = createClipOptions(
|
|
1220
|
+
clip.rect,
|
|
1221
|
+
ORIENT_CHANNELS[orient] === "x",
|
|
1222
|
+
ORIENT_CHANNELS[orient] === "y"
|
|
1223
|
+
);
|
|
1224
|
+
clipRect = clip?.rect;
|
|
911
1225
|
}
|
|
912
1226
|
|
|
913
1227
|
queueDecoration(
|
|
914
|
-
defaultAxisZindex(axisView.axisProps
|
|
1228
|
+
defaultAxisZindex(axisView.axisProps, clippedDecorations),
|
|
915
1229
|
DECORATION_ORDER.axis,
|
|
916
1230
|
() =>
|
|
917
1231
|
axisView.render(context, translatedCoords, {
|
|
918
1232
|
...options,
|
|
919
1233
|
clipRect,
|
|
1234
|
+
clip,
|
|
920
1235
|
})
|
|
921
1236
|
);
|
|
922
1237
|
}
|
|
923
1238
|
|
|
1239
|
+
renderLocalLegends(
|
|
1240
|
+
gridChild.legends,
|
|
1241
|
+
axes,
|
|
1242
|
+
viewportCoords,
|
|
1243
|
+
context,
|
|
1244
|
+
options,
|
|
1245
|
+
queueDecoration,
|
|
1246
|
+
DECORATION_ORDER.legend
|
|
1247
|
+
);
|
|
1248
|
+
|
|
924
1249
|
// Axes shared between children
|
|
925
1250
|
// TODO: What if some have scrollable viewports?
|
|
926
1251
|
// Should throw an error because cannot have shared axes in such cases.
|
|
@@ -934,7 +1259,10 @@ export default class GridView extends ContainerView {
|
|
|
934
1259
|
(orient == "bottom" && row == grid.nRows - 1)
|
|
935
1260
|
) {
|
|
936
1261
|
queueDecoration(
|
|
937
|
-
defaultAxisZindex(
|
|
1262
|
+
defaultAxisZindex(
|
|
1263
|
+
axisView.axisProps,
|
|
1264
|
+
clippedDecorations
|
|
1265
|
+
),
|
|
938
1266
|
DECORATION_ORDER.axis,
|
|
939
1267
|
() =>
|
|
940
1268
|
axisView.render(
|
|
@@ -969,13 +1297,24 @@ export default class GridView extends ContainerView {
|
|
|
969
1297
|
|
|
970
1298
|
if (title) {
|
|
971
1299
|
queueDecoration(
|
|
972
|
-
gridChild.
|
|
1300
|
+
gridChild.getTitleZindex(),
|
|
973
1301
|
DECORATION_ORDER.title,
|
|
974
|
-
() =>
|
|
1302
|
+
() =>
|
|
1303
|
+
gridChild.renderTitle(context, viewportCoords, options)
|
|
975
1304
|
);
|
|
976
1305
|
}
|
|
977
1306
|
}
|
|
978
1307
|
|
|
1308
|
+
renderLocalLegends(
|
|
1309
|
+
this.#sharedLegends,
|
|
1310
|
+
this.#getSharedAxesByOrient(),
|
|
1311
|
+
coords,
|
|
1312
|
+
context,
|
|
1313
|
+
options,
|
|
1314
|
+
queueDecoration,
|
|
1315
|
+
DECORATION_ORDER.legend
|
|
1316
|
+
);
|
|
1317
|
+
|
|
979
1318
|
renderDecorations(underlays);
|
|
980
1319
|
|
|
981
1320
|
for (const renderContent of contents) {
|
|
@@ -1302,6 +1641,22 @@ export function isClippedChildren(view) {
|
|
|
1302
1641
|
return clipped;
|
|
1303
1642
|
}
|
|
1304
1643
|
|
|
1644
|
+
/**
|
|
1645
|
+
* @param {View} view
|
|
1646
|
+
*/
|
|
1647
|
+
function hasClippedChildren(view) {
|
|
1648
|
+
let clipped = false;
|
|
1649
|
+
|
|
1650
|
+
view.visit((v) => {
|
|
1651
|
+
if (v instanceof UnitView) {
|
|
1652
|
+
const clip = v.mark.properties.clip;
|
|
1653
|
+
clipped ||= clip === true || clip === "x" || clip === "y";
|
|
1654
|
+
}
|
|
1655
|
+
});
|
|
1656
|
+
|
|
1657
|
+
return clipped;
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1305
1660
|
/**
|
|
1306
1661
|
* @param {View} view
|
|
1307
1662
|
* @returns {boolean}
|
|
@@ -1337,15 +1692,24 @@ function getSeparatorDirections(spec) {
|
|
|
1337
1692
|
}
|
|
1338
1693
|
|
|
1339
1694
|
/**
|
|
1340
|
-
* Default z-index for axes.
|
|
1695
|
+
* Default z-index for axes. Inside axes default to overlays because they share
|
|
1696
|
+
* plot space with marks. Clipped or scrollable outside axes get a higher
|
|
1341
1697
|
* default to keep guides above visible edge artifacts.
|
|
1342
1698
|
*
|
|
1343
|
-
* @param {
|
|
1699
|
+
* @param {import("../../spec/axis.js").Axis} axisProps
|
|
1344
1700
|
* @param {boolean} clipped
|
|
1345
1701
|
* @returns {number}
|
|
1346
1702
|
*/
|
|
1347
|
-
function defaultAxisZindex(
|
|
1348
|
-
|
|
1703
|
+
function defaultAxisZindex(axisProps, clipped) {
|
|
1704
|
+
if (axisProps.zindex !== undefined) {
|
|
1705
|
+
return axisProps.zindex;
|
|
1706
|
+
} else if (axisProps.placement === "inside") {
|
|
1707
|
+
return 1;
|
|
1708
|
+
} else if (clipped) {
|
|
1709
|
+
return CLIPPED_DECORATION_ZINDEX;
|
|
1710
|
+
} else {
|
|
1711
|
+
return 0;
|
|
1712
|
+
}
|
|
1349
1713
|
}
|
|
1350
1714
|
|
|
1351
1715
|
/**
|
|
@@ -1369,18 +1733,30 @@ function defaultBackgroundStrokeZindex(zindex, clipped) {
|
|
|
1369
1733
|
export function translateAxisCoords(coords, orient, axisView) {
|
|
1370
1734
|
const props = axisView.axisProps;
|
|
1371
1735
|
const ps = axisView.getPerpendicularSize();
|
|
1736
|
+
const inside = props.placement === "inside";
|
|
1737
|
+
const offset = props.offset ?? 0;
|
|
1372
1738
|
|
|
1373
1739
|
if (orient == "bottom") {
|
|
1374
|
-
return
|
|
1375
|
-
.translate(0, coords.height
|
|
1376
|
-
|
|
1740
|
+
return inside
|
|
1741
|
+
? coords.translate(0, coords.height - ps - offset).modify({
|
|
1742
|
+
height: ps,
|
|
1743
|
+
})
|
|
1744
|
+
: coords.translate(0, coords.height + offset).modify({
|
|
1745
|
+
height: ps,
|
|
1746
|
+
});
|
|
1377
1747
|
} else if (orient == "top") {
|
|
1378
|
-
return
|
|
1748
|
+
return inside
|
|
1749
|
+
? coords.translate(0, offset).modify({ height: ps })
|
|
1750
|
+
: coords.translate(0, -ps - offset).modify({ height: ps });
|
|
1379
1751
|
} else if (orient == "left") {
|
|
1380
|
-
return
|
|
1752
|
+
return inside
|
|
1753
|
+
? coords.translate(offset, 0).modify({ width: ps })
|
|
1754
|
+
: coords.translate(-ps - offset, 0).modify({ width: ps });
|
|
1381
1755
|
} else if (orient == "right") {
|
|
1382
|
-
return
|
|
1383
|
-
.translate(coords.width
|
|
1384
|
-
|
|
1756
|
+
return inside
|
|
1757
|
+
? coords.translate(coords.width - ps - offset, 0).modify({
|
|
1758
|
+
width: ps,
|
|
1759
|
+
})
|
|
1760
|
+
: coords.translate(coords.width + offset, 0).modify({ width: ps });
|
|
1385
1761
|
}
|
|
1386
1762
|
}
|