@fundar/data-chart-telling 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/README.md +58 -19
- package/dist/configuration/config.svelte.d.ts +1 -1
- package/dist/configuration/config.svelte.js +172 -95
- package/dist/configuration/themes/index.d.ts +5 -1304
- package/dist/index.d.ts +24 -14
- package/dist/index.js +20 -10
- package/dist/layout/base/BasePlotLayout.svelte +129 -51
- package/dist/layout/base/BasePlotLayout.svelte.d.ts +1 -38
- package/dist/layout/coordinates/CoordinatesLayout.svelte +42 -40
- package/dist/layout/coordinates/CoordinatesLayout.svelte.d.ts +0 -2
- package/dist/layout/coordinates/ProjectionZoom.svelte +48 -0
- package/dist/layout/coordinates/ProjectionZoom.svelte.d.ts +10 -0
- package/dist/layout/coordinates/ZoomedProjection.d.ts +11 -0
- package/dist/layout/coordinates/ZoomedProjection.js +24 -0
- package/dist/layout/coordinates/camera.svelte.js +11 -8
- package/dist/layout/coordinates/projections/argentina.js +1 -1
- package/dist/layout/coordinates/projections/fit.d.ts +1 -1
- package/dist/layout/coordinates/projections/fit.js +1 -1
- package/dist/layout/coordinates/zoom.svelte.d.ts +4 -5
- package/dist/layout/coordinates/zoom.svelte.js +4 -5
- package/dist/layout/facet/FacetLayout.svelte +1 -1
- package/dist/layout/facet/config.js +1 -1
- package/dist/layout/figure/Figure.svelte +2 -0
- package/dist/layout/geometry/GeometryLayout.svelte +14 -9
- package/dist/layout/geometry/GeometryLayout.svelte.d.ts +0 -3
- package/dist/layout/geometry/MarkerOffset.svelte +28 -0
- package/dist/layout/geometry/MarkerOffset.svelte.d.ts +13 -0
- package/dist/layout/grid/GridCell.svelte +6 -8
- package/dist/layout/hover/HoverSettings.d.ts +20 -6
- package/dist/layout/hover/HoverSettings.js +29 -4
- package/dist/layout/legend/ContinuousSection.svelte +44 -9
- package/dist/layout/legend/DiscreteBadgeItem.svelte +2 -2
- package/dist/layout/legend/DiscreteSection.svelte +2 -2
- package/dist/layout/legend/DiscreteSymbolIcon.svelte +1 -1
- package/dist/layout/legend/LegendChannels.js +36 -12
- package/dist/layout/legend/LegendLayout.svelte +9 -1
- package/dist/layout/legend/LegendState.svelte.d.ts +9 -0
- package/dist/layout/legend/LegendState.svelte.js +24 -3
- package/dist/layout/legend/SizeSection.svelte +1 -1
- package/dist/layout/margins/PlotMargins.svelte.d.ts +2 -5
- package/dist/layout/margins/PlotMargins.svelte.js +4 -8
- package/dist/layout/plot/Plot.svelte +6 -3
- package/dist/layout/plot/PublicPlotContext.d.ts +5 -4
- package/dist/layout/plot/PublicPlotContext.js +7 -3
- package/dist/layout/plot/Slice.d.ts +5 -1
- package/dist/layout/plot/Slice.js +18 -6
- package/dist/layout/scales/EdgeTicks.d.ts +39 -0
- package/dist/layout/scales/EdgeTicks.js +82 -0
- package/dist/layout/scales/NiceTicks.d.ts +43 -0
- package/dist/layout/scales/NiceTicks.js +76 -0
- package/dist/layout/scales/ScalesLayout.svelte +133 -34
- package/dist/layout/scales/ScalesLayout.svelte.d.ts +10 -0
- package/dist/layout/scales/SveltePlotScale.d.ts +15 -0
- package/dist/layout/scales/SveltePlotScale.js +86 -0
- package/dist/layout/scales/TickLabels.d.ts +32 -0
- package/dist/layout/scales/TickLabels.js +55 -0
- package/dist/layout/styles/StylesLayout.svelte +2 -2
- package/dist/layout/styles/ValueLabels.d.ts +33 -5
- package/dist/layout/styles/ValueLabels.js +83 -23
- package/dist/layout/timeline/Timeline.svelte +5 -2
- package/dist/layout/timeline/Timeline.svelte.d.ts +2 -0
- package/dist/layout/timeline/TimelineLayout.svelte +39 -13
- package/dist/layout/timeline/TimelineLayout.svelte.d.ts +7 -5
- package/dist/layout/timeline/TimelineRule.svelte +1 -0
- package/dist/layout/timeline/TimelineState.svelte.d.ts +13 -5
- package/dist/layout/timeline/TimelineState.svelte.js +42 -8
- package/dist/layout/timeline/TimelineTime.d.ts +18 -0
- package/dist/layout/timeline/TimelineTime.js +117 -0
- package/dist/layout/tooltip/Tooltip.svelte +10 -7
- package/dist/layout/tooltip/Tooltip.svelte.d.ts +6 -4
- package/dist/layout/tooltip/TooltipState.svelte.d.ts +8 -2
- package/dist/layout/tooltip/TooltipState.svelte.js +23 -4
- package/dist/markers/MarkerKinds.d.ts +5 -0
- package/dist/markers/MarkerKinds.js +1 -0
- package/dist/markers/area/AreaMarker.svelte +15 -63
- package/dist/markers/arrow/ArrowMarker.svelte +51 -9
- package/dist/markers/bar/BarMarker.svelte +8 -4
- package/dist/markers/bollinger/BollingerMarker.svelte +33 -18
- package/dist/markers/box/BoxMarker.svelte +40 -9
- package/dist/markers/delta/Delta.js +1 -1
- package/dist/markers/delta/DeltaMarker.svelte +9 -7
- package/dist/markers/dot/DotMarker.svelte +24 -27
- package/dist/markers/image/ImageMarker.svelte +17 -12
- package/dist/markers/inset/InsetMarker.svelte +2 -2
- package/dist/markers/line/LineMarker.svelte +1 -0
- package/dist/markers/link/LinkMarker.svelte +174 -29
- package/dist/markers/regression/RegressionMarker.svelte +16 -33
- package/dist/markers/rule/RuleMarker.svelte +9 -3
- package/dist/markers/text/Declutter.d.ts +4 -0
- package/dist/markers/text/Declutter.js +26 -11
- package/dist/markers/text/TextMarker.svelte +91 -48
- package/dist/markers/tick/TickMarker.svelte +27 -25
- package/dist/markers/utils/MarkerChannels.d.ts +24 -0
- package/dist/markers/utils/MarkerChannels.js +42 -7
- package/dist/markers/utils/RowOffset.d.ts +23 -0
- package/dist/markers/utils/RowOffset.js +23 -0
- package/dist/markers/utils/RowOffsetMarks.svelte +30 -0
- package/dist/markers/utils/RowOffsetMarks.svelte.d.ts +33 -0
- package/dist/markers/utils/RowStroke.d.ts +31 -0
- package/dist/markers/utils/RowStroke.js +28 -0
- package/dist/markers/violin/ViolinMarker.svelte +75 -0
- package/dist/markers/violin/ViolinMarker.svelte.d.ts +7 -0
- package/dist/markers/violin/ViolinProfiles.d.ts +29 -0
- package/dist/markers/violin/ViolinProfiles.js +55 -0
- package/dist/markers/waffle/WaffleMarker.svelte +17 -37
- package/dist/phases/Pipeline.d.ts +5 -0
- package/dist/phases/Pipeline.js +8 -2
- package/dist/phases/data/DataPhase.d.ts +5 -11
- package/dist/phases/data/DataPhase.js +14 -11
- package/dist/phases/data/PlotAxes.d.ts +10 -0
- package/dist/phases/data/PlotAxes.js +14 -1
- package/dist/phases/facet/FacetPanels.d.ts +55 -0
- package/dist/phases/facet/FacetPanels.js +96 -0
- package/dist/phases/facet/FacetPhase.d.ts +1 -42
- package/dist/phases/facet/FacetPhase.js +1 -87
- package/dist/phases/hover/HoverPhase.d.ts +6 -43
- package/dist/phases/hover/HoverPhase.js +19 -54
- package/dist/phases/mapping/MappingPhase.d.ts +1 -1
- package/dist/phases/mapping/MappingPhase.js +3 -5
- package/dist/phases/markers/MarkersPhase.js +2 -1
- package/dist/phases/scales/CategoryOrder.d.ts +23 -0
- package/dist/phases/scales/CategoryOrder.js +73 -0
- package/dist/phases/scales/ScalesPhase.d.ts +1 -3
- package/dist/phases/scales/ScalesPhase.js +37 -27
- package/dist/phases/sharedScales/SharedScalesPhase.d.ts +6 -2
- package/dist/phases/sharedScales/SharedScalesPhase.js +14 -8
- package/dist/phases/statistics/Statistics.d.ts +10 -6
- package/dist/phases/statistics/Statistics.js +20 -10
- package/dist/phases/statistics/StatisticsPhase.js +10 -6
- package/dist/phases/statistics/methods/BollingerStatistic.d.ts +1 -1
- package/dist/phases/statistics/methods/BollingerStatistic.js +13 -11
- package/dist/phases/statistics/methods/BoxStatistic.d.ts +1 -1
- package/dist/phases/statistics/methods/BoxStatistic.js +14 -12
- package/dist/phases/statistics/methods/Density2dStatistic.d.ts +1 -1
- package/dist/phases/statistics/methods/Density2dStatistic.js +13 -11
- package/dist/phases/statistics/methods/DensityStatistic.d.ts +1 -1
- package/dist/phases/statistics/methods/DensityStatistic.js +11 -9
- package/dist/phases/statistics/methods/DeviationStatistic.d.ts +8 -0
- package/dist/phases/statistics/methods/DeviationStatistic.js +111 -0
- package/dist/phases/statistics/methods/MovingAverageStatistic.d.ts +1 -1
- package/dist/phases/statistics/methods/MovingAverageStatistic.js +11 -9
- package/dist/phases/statistics/methods/RegressionStatistic.d.ts +1 -1
- package/dist/phases/statistics/methods/RegressionStatistic.js +16 -14
- package/dist/phases/tooltip/TooltipPhase.d.ts +4 -2
- package/dist/phases/tooltip/TooltipPhase.js +10 -3
- package/dist/phases/transforms/ProcessedPositions.d.ts +30 -0
- package/dist/phases/transforms/ProcessedPositions.js +74 -0
- package/dist/phases/transforms/TransformsPhase.d.ts +5 -42
- package/dist/phases/transforms/TransformsPhase.js +67 -58
- package/dist/phases/transforms/ValueSelection.d.ts +30 -0
- package/dist/phases/transforms/ValueSelection.js +53 -0
- package/dist/plots/{heatmap → correlation/heatmap}/Plot.svelte +5 -2
- package/dist/plots/{heatmap → correlation/heatmap}/Plot.svelte.d.ts +2 -2
- package/dist/plots/{heatmap → correlation/heatmap}/defaults.d.ts +2 -2
- package/dist/plots/{heatmap → correlation/heatmap}/defaults.js +5 -5
- package/dist/plots/{heatmap → correlation/heatmap}/markers.d.ts +4 -4
- package/dist/plots/{heatmap → correlation/heatmap}/markers.js +4 -3
- package/dist/plots/{scatter → correlation/scatter}/Plot.svelte +5 -2
- package/dist/plots/{scatter → correlation/scatter}/Plot.svelte.d.ts +2 -2
- package/dist/plots/{scatter → correlation/scatter}/defaults.d.ts +2 -2
- package/dist/plots/{scatter → correlation/scatter}/defaults.js +6 -5
- package/dist/plots/{scatter → correlation/scatter}/markers.d.ts +4 -4
- package/dist/plots/{scatter → correlation/scatter}/markers.js +5 -4
- package/dist/plots/distribution/box/BoxSummaries.d.ts +19 -0
- package/dist/plots/distribution/box/BoxSummaries.js +101 -0
- package/dist/plots/distribution/box/Plot.svelte +42 -0
- package/dist/plots/distribution/box/Plot.svelte.d.ts +26 -0
- package/dist/plots/distribution/box/defaults.d.ts +12 -0
- package/dist/plots/distribution/box/defaults.js +34 -0
- package/dist/plots/distribution/box/markers.d.ts +12 -0
- package/dist/plots/distribution/box/markers.js +34 -0
- package/dist/plots/distribution/density/Plot.svelte +45 -0
- package/dist/plots/distribution/density/Plot.svelte.d.ts +26 -0
- package/dist/plots/distribution/density/defaults.d.ts +9 -0
- package/dist/plots/distribution/density/defaults.js +29 -0
- package/dist/plots/distribution/density/markers.d.ts +9 -0
- package/dist/plots/distribution/density/markers.js +42 -0
- package/dist/plots/{histogram → distribution/histogram}/Plot.svelte +2 -2
- package/dist/plots/{histogram → distribution/histogram}/Plot.svelte.d.ts +2 -2
- package/dist/plots/{histogram → distribution/histogram}/defaults.d.ts +2 -2
- package/dist/plots/{histogram → distribution/histogram}/defaults.js +4 -4
- package/dist/plots/{histogram → distribution/histogram}/markers.d.ts +3 -3
- package/dist/plots/{histogram → distribution/histogram}/markers.js +7 -7
- package/dist/plots/{pyramid → distribution/pyramid}/Plot.svelte +5 -2
- package/dist/plots/{pyramid → distribution/pyramid}/Plot.svelte.d.ts +2 -2
- package/dist/plots/{pyramid → distribution/pyramid}/defaults.d.ts +2 -2
- package/dist/plots/{pyramid → distribution/pyramid}/defaults.js +7 -6
- package/dist/plots/{pyramid → distribution/pyramid}/markers.d.ts +4 -4
- package/dist/plots/{pyramid → distribution/pyramid}/markers.js +8 -11
- package/dist/plots/distribution/violin/Plot.svelte +45 -0
- package/dist/plots/distribution/violin/Plot.svelte.d.ts +26 -0
- package/dist/plots/distribution/violin/defaults.d.ts +10 -0
- package/dist/plots/distribution/violin/defaults.js +58 -0
- package/dist/plots/distribution/violin/markers.d.ts +10 -0
- package/dist/plots/distribution/violin/markers.js +71 -0
- package/dist/plots/{area → evolution/area}/Plot.svelte +2 -2
- package/dist/plots/{area → evolution/area}/Plot.svelte.d.ts +2 -2
- package/dist/plots/{area → evolution/area}/defaults.d.ts +2 -2
- package/dist/plots/{area → evolution/area}/defaults.js +2 -0
- package/dist/plots/{area → evolution/area}/markers.d.ts +2 -2
- package/dist/plots/{area → evolution/area}/markers.js +2 -3
- package/dist/plots/{line → evolution/line}/Plot.svelte +2 -2
- package/dist/plots/{line → evolution/line}/Plot.svelte.d.ts +2 -2
- package/dist/plots/{line → evolution/line}/defaults.d.ts +2 -2
- package/dist/plots/{line → evolution/line}/defaults.js +2 -0
- package/dist/plots/{line → evolution/line}/markers.d.ts +11 -8
- package/dist/plots/{line → evolution/line}/markers.js +7 -6
- package/dist/plots/evolution/slope/Plot.svelte +42 -0
- package/dist/plots/evolution/slope/Plot.svelte.d.ts +26 -0
- package/dist/plots/evolution/slope/defaults.d.ts +8 -0
- package/dist/plots/evolution/slope/defaults.js +31 -0
- package/dist/plots/evolution/slope/markers.d.ts +16 -0
- package/dist/plots/evolution/slope/markers.js +79 -0
- package/dist/plots/evolution/sparkline/Plot.svelte +45 -0
- package/dist/plots/evolution/sparkline/Plot.svelte.d.ts +26 -0
- package/dist/plots/evolution/sparkline/defaults.d.ts +7 -0
- package/dist/plots/evolution/sparkline/defaults.js +23 -0
- package/dist/plots/evolution/sparkline/markers.d.ts +7 -0
- package/dist/plots/evolution/sparkline/markers.js +56 -0
- package/dist/plots/{geo → map/geo}/Core.svelte +11 -10
- package/dist/plots/{geo → map/geo}/Core.svelte.d.ts +1 -1
- package/dist/plots/map/geo/GeoFeatures.svelte.d.ts +9 -0
- package/dist/plots/map/geo/GeoFeatures.svelte.js +55 -0
- package/dist/plots/map/geo/GeoGeometry.d.ts +27 -0
- package/dist/plots/map/geo/GeoGeometry.js +142 -0
- package/dist/plots/map/geo/GeoSegments.d.ts +16 -0
- package/dist/plots/map/geo/GeoSegments.js +23 -0
- package/dist/plots/{geo → map/geo}/Plot.svelte +10 -10
- package/dist/plots/{geo → map/geo}/Plot.svelte.d.ts +2 -2
- package/dist/plots/{geo → map/geo}/defaults.d.ts +2 -2
- package/dist/plots/{geo → map/geo}/defaults.js +1 -1
- package/dist/plots/{geo → map/geo}/phases/data.d.ts +1 -1
- package/dist/plots/{geo → map/geo}/phases/data.js +7 -6
- package/dist/plots/{geo → map/geo}/phases/hover.d.ts +1 -1
- package/dist/plots/{geo → map/geo}/phases/hover.js +5 -5
- package/dist/plots/{geo → map/geo}/phases/markers.d.ts +1 -1
- package/dist/plots/{geo → map/geo}/phases/markers.js +8 -13
- package/dist/plots/{geo → map/geo}/phases/scales.d.ts +2 -2
- package/dist/plots/{geo → map/geo}/phases/scales.js +28 -12
- package/dist/plots/{geo → map/geo}/phases/tooltip.d.ts +1 -1
- package/dist/plots/map/geo/phases/tooltip.js +5 -0
- package/dist/plots/{geo → map/geo}/slices.d.ts +2 -2
- package/dist/plots/{geo → map/geo}/slices.js +7 -4
- package/dist/plots/{bar → ranking/bar}/Plot.svelte +2 -2
- package/dist/plots/{bar → ranking/bar}/Plot.svelte.d.ts +2 -2
- package/dist/plots/ranking/bar/defaults.d.ts +16 -0
- package/dist/plots/{bar → ranking/bar}/defaults.js +17 -15
- package/dist/plots/{bar → ranking/bar}/markers.d.ts +8 -8
- package/dist/plots/{bar → ranking/bar}/markers.js +11 -19
- package/dist/plots/ranking/bullet/Plot.svelte +42 -0
- package/dist/plots/ranking/bullet/Plot.svelte.d.ts +26 -0
- package/dist/plots/ranking/bullet/defaults.d.ts +8 -0
- package/dist/plots/ranking/bullet/defaults.js +24 -0
- package/dist/plots/ranking/bullet/markers.d.ts +10 -0
- package/dist/plots/ranking/bullet/markers.js +90 -0
- package/dist/plots/ranking/cleveland/ClevelandConnector.d.ts +48 -0
- package/dist/plots/ranking/cleveland/ClevelandConnector.js +140 -0
- package/dist/plots/ranking/cleveland/ClevelandMarkers.d.ts +33 -0
- package/dist/plots/ranking/cleveland/ClevelandMarkers.js +375 -0
- package/dist/plots/ranking/cleveland/ClevelandRanges.d.ts +31 -0
- package/dist/plots/ranking/cleveland/ClevelandRanges.js +116 -0
- package/dist/plots/ranking/cleveland/Plot.svelte +45 -0
- package/dist/plots/ranking/cleveland/Plot.svelte.d.ts +26 -0
- package/dist/plots/ranking/cleveland/defaults.d.ts +13 -0
- package/dist/plots/ranking/cleveland/defaults.js +66 -0
- package/dist/plots/ranking/dumbbell/Plot.svelte +45 -0
- package/dist/plots/ranking/dumbbell/Plot.svelte.d.ts +26 -0
- package/dist/plots/ranking/dumbbell/defaults.d.ts +9 -0
- package/dist/plots/ranking/dumbbell/defaults.js +19 -0
- package/dist/plots/ranking/forest/Plot.svelte +42 -0
- package/dist/plots/ranking/forest/Plot.svelte.d.ts +26 -0
- package/dist/plots/ranking/forest/defaults.d.ts +11 -0
- package/dist/plots/ranking/forest/defaults.js +20 -0
- package/dist/plots/ranking/lollipop/Plot.svelte +45 -0
- package/dist/plots/ranking/lollipop/Plot.svelte.d.ts +26 -0
- package/dist/plots/ranking/lollipop/defaults.d.ts +9 -0
- package/dist/plots/ranking/lollipop/defaults.js +18 -0
- package/dist/plots/utils/RowNumbers.d.ts +16 -0
- package/dist/plots/utils/RowNumbers.js +24 -0
- package/dist/plots/utils/gaps.js +1 -1
- package/dist/plots/utils/segments.js +1 -1
- package/dist/types/configuration/styling.d.ts +287 -132
- package/dist/types/layout/composer.d.ts +5 -2
- package/dist/types/layout/coordinates.d.ts +5 -4
- package/dist/types/layout/legend.d.ts +21 -5
- package/dist/types/layout/plot.d.ts +44 -1
- package/dist/types/layout/scales.d.ts +51 -3
- package/dist/types/layout/statistics/deviation.d.ts +40 -0
- package/dist/types/layout/statistics/index.d.ts +7 -2
- package/dist/types/layout/styles/base.d.ts +18 -0
- package/dist/types/layout/styles/bullet.d.ts +25 -0
- package/dist/types/layout/styles/connector.d.ts +98 -0
- package/dist/types/layout/styles/curve.d.ts +11 -0
- package/dist/types/layout/styles/frame.d.ts +17 -0
- package/dist/types/layout/styles/gaps.d.ts +12 -0
- package/dist/types/layout/styles/geo.d.ts +55 -0
- package/dist/types/layout/styles/index.d.ts +8 -0
- package/dist/types/layout/styles/index.js +8 -0
- package/dist/types/layout/styles/values.d.ts +47 -0
- package/dist/types/layout/timeline.d.ts +19 -7
- package/dist/types/layout/tooltip.d.ts +6 -2
- package/dist/types/markers/axis/area.d.ts +2 -2
- package/dist/types/markers/axis/arrow.d.ts +3 -0
- package/dist/types/markers/axis/axisBasedMarkersConfig.d.ts +2 -1
- package/dist/types/markers/axis/bar.d.ts +1 -1
- package/dist/types/markers/axis/box.d.ts +5 -0
- package/dist/types/markers/axis/difference.d.ts +2 -2
- package/dist/types/markers/axis/image.d.ts +3 -2
- package/dist/types/markers/axis/line.d.ts +2 -0
- package/dist/types/markers/axis/rule.d.ts +9 -0
- package/dist/types/markers/axis/trail.d.ts +2 -3
- package/dist/types/markers/axis/violin.d.ts +25 -0
- package/dist/types/markers/basic/dot.d.ts +3 -2
- package/dist/types/markers/basic/text.d.ts +13 -3
- package/dist/types/markers/channels/commonMarkerConfig.d.ts +7 -3
- package/dist/types/markers/channels/commonMarkerConfigWithRowOffset.d.ts +13 -0
- package/dist/types/markers/common.d.ts +1 -1
- package/dist/types/markers/common.js +1 -0
- package/dist/types/markers/geo/link.d.ts +5 -1
- package/dist/types/phases/hover/phase.d.ts +6 -0
- package/dist/types/phases/index.d.ts +1 -1
- package/dist/types/phases/scales/phase.d.ts +5 -1
- package/dist/types/phases/state.d.ts +20 -4
- package/dist/types/phases/statistics/phase.d.ts +3 -1
- package/dist/types/phases/statistics/source.d.ts +3 -1
- package/dist/types/phases/transforms/phase.d.ts +32 -0
- package/dist/types/plots/{heatmap → correlation/heatmap}/props.d.ts +6 -6
- package/dist/types/plots/{heatmap → correlation/heatmap}/state.d.ts +4 -4
- package/dist/types/plots/{scatter → correlation/scatter}/props.d.ts +6 -6
- package/dist/types/plots/{scatter → correlation/scatter}/state.d.ts +2 -2
- package/dist/types/plots/distribution/box/props.d.ts +10 -0
- package/dist/types/plots/distribution/box/state.d.ts +23 -0
- package/dist/types/plots/distribution/density/props.d.ts +23 -0
- package/dist/types/plots/distribution/density/state.d.ts +6 -0
- package/dist/types/plots/distribution/density/state.js +1 -0
- package/dist/types/plots/{histogram → distribution/histogram}/props.d.ts +7 -7
- package/dist/types/plots/distribution/histogram/props.js +1 -0
- package/dist/types/plots/{histogram → distribution/histogram}/state.d.ts +2 -2
- package/dist/types/plots/distribution/histogram/state.js +1 -0
- package/dist/types/plots/{pyramid → distribution/pyramid}/props.d.ts +6 -6
- package/dist/types/plots/distribution/pyramid/props.js +1 -0
- package/dist/types/plots/{pyramid → distribution/pyramid}/state.d.ts +3 -3
- package/dist/types/plots/distribution/pyramid/state.js +1 -0
- package/dist/types/plots/distribution/violin/props.d.ts +23 -0
- package/dist/types/plots/distribution/violin/props.js +1 -0
- package/dist/types/plots/distribution/violin/state.d.ts +6 -0
- package/dist/types/plots/distribution/violin/state.js +1 -0
- package/dist/types/plots/{area → evolution/area}/props.d.ts +6 -6
- package/dist/types/plots/evolution/area/props.js +1 -0
- package/dist/types/plots/{area → evolution/area}/state.d.ts +2 -2
- package/dist/types/plots/evolution/area/state.js +1 -0
- package/dist/types/plots/evolution/line/props.d.ts +10 -0
- package/dist/types/plots/evolution/line/props.js +1 -0
- package/dist/types/plots/{line → evolution/line}/state.d.ts +3 -3
- package/dist/types/plots/evolution/line/state.js +1 -0
- package/dist/types/plots/evolution/slope/props.d.ts +5 -0
- package/dist/types/plots/evolution/slope/props.js +1 -0
- package/dist/types/plots/evolution/slope/state.d.ts +5 -0
- package/dist/types/plots/evolution/slope/state.js +1 -0
- package/dist/types/plots/evolution/sparkline/props.d.ts +5 -0
- package/dist/types/plots/evolution/sparkline/props.js +1 -0
- package/dist/types/plots/evolution/sparkline/state.d.ts +5 -0
- package/dist/types/plots/evolution/sparkline/state.js +1 -0
- package/dist/types/plots/{geo → map/geo}/props.d.ts +8 -8
- package/dist/types/plots/map/geo/props.js +1 -0
- package/dist/types/plots/{geo → map/geo}/state.d.ts +18 -11
- package/dist/types/plots/map/geo/state.js +1 -0
- package/dist/types/plots/props.d.ts +3 -1
- package/dist/types/plots/{bar → ranking/bar}/props.d.ts +6 -6
- package/dist/types/plots/ranking/bar/props.js +1 -0
- package/dist/types/plots/{bar → ranking/bar}/state.d.ts +2 -2
- package/dist/types/plots/ranking/bar/state.js +1 -0
- package/dist/types/plots/ranking/bullet/props.d.ts +22 -0
- package/dist/types/plots/ranking/bullet/props.js +1 -0
- package/dist/types/plots/ranking/bullet/state.d.ts +5 -0
- package/dist/types/plots/ranking/bullet/state.js +1 -0
- package/dist/types/plots/ranking/cleveland/props.d.ts +10 -0
- package/dist/types/plots/ranking/cleveland/props.js +1 -0
- package/dist/types/plots/ranking/cleveland/state.d.ts +49 -0
- package/dist/types/plots/ranking/cleveland/state.js +1 -0
- package/dist/types/plots/ranking/dumbbell/props.d.ts +10 -0
- package/dist/types/plots/ranking/dumbbell/props.js +1 -0
- package/dist/types/plots/ranking/dumbbell/state.d.ts +5 -0
- package/dist/types/plots/ranking/dumbbell/state.js +1 -0
- package/dist/types/plots/ranking/forest/props.d.ts +23 -0
- package/dist/types/plots/ranking/forest/props.js +1 -0
- package/dist/types/plots/ranking/forest/state.d.ts +5 -0
- package/dist/types/plots/ranking/forest/state.js +1 -0
- package/dist/types/plots/ranking/lollipop/props.d.ts +10 -0
- package/dist/types/plots/ranking/lollipop/props.js +1 -0
- package/dist/types/plots/ranking/lollipop/state.d.ts +5 -0
- package/dist/types/plots/ranking/lollipop/state.js +1 -0
- package/dist/types/plots/segments/common.d.ts +4 -1
- package/dist/utils/OpacityScale.d.ts +14 -0
- package/dist/utils/OpacityScale.js +43 -0
- package/dist/utils/{symbol.d.ts → SymbolPath.d.ts} +0 -12
- package/dist/utils/{symbol.js → SymbolPath.js} +0 -24
- package/dist/utils/SymbolScale.d.ts +18 -0
- package/dist/utils/SymbolScale.js +29 -0
- package/dist/utils/color/ColorRamp.d.ts +27 -0
- package/dist/utils/color/ColorRamp.js +120 -0
- package/dist/utils/color/CssColor.d.ts +19 -0
- package/dist/utils/color/CssColor.js +114 -0
- package/dist/utils/color/Palette.d.ts +21 -0
- package/dist/utils/color/Palette.js +52 -0
- package/dist/utils/color/index.d.ts +11 -3
- package/dist/utils/color/index.js +14 -3
- package/dist/utils/grouping.js +1 -1
- package/docs/architecture.md +1 -1
- package/docs/chrome.md +39 -8
- package/docs/composer.md +19 -3
- package/docs/concepts.md +1 -1
- package/docs/development.md +14 -5
- package/docs/facets.md +62 -8
- package/docs/getting-started.md +8 -9
- package/docs/legend.md +73 -24
- package/docs/markers.md +45 -32
- package/docs/plots/correlation/heatmap.md +26 -0
- package/docs/plots/correlation/scatter.md +35 -0
- package/docs/plots/distribution/box.md +28 -0
- package/docs/plots/distribution/density.md +26 -0
- package/docs/plots/distribution/histogram.md +33 -0
- package/docs/plots/distribution/pyramid.md +31 -0
- package/docs/plots/distribution/violin.md +35 -0
- package/docs/plots/evolution/area.md +32 -0
- package/docs/plots/evolution/line.md +93 -0
- package/docs/plots/evolution/slope.md +39 -0
- package/docs/plots/evolution/sparkline.md +34 -0
- package/docs/plots/ranking/bar.md +59 -0
- package/docs/plots/ranking/bullet.md +37 -0
- package/docs/plots/ranking/cleveland.md +54 -0
- package/docs/plots/ranking/dumbbell.md +39 -0
- package/docs/plots/ranking/forest.md +40 -0
- package/docs/plots/ranking/lollipop.md +39 -0
- package/docs/plots.md +22 -154
- package/docs/scales.md +50 -27
- package/docs/state.md +1 -1
- package/docs/styles-and-segments.md +96 -39
- package/docs/theming.md +33 -19
- package/docs/timeline.md +62 -28
- package/docs/tooltip-and-hover.md +72 -24
- package/docs/transforms-and-statistics.md +56 -25
- package/examples/BarValues.svelte +2 -2
- package/examples/Box.svelte +7 -0
- package/examples/Bullet.svelte +17 -0
- package/examples/Chrome.svelte +17 -0
- package/examples/ChromeOrder.svelte +18 -0
- package/examples/Cleveland.svelte +15 -0
- package/examples/Composer.svelte +23 -0
- package/examples/CustomTooltip.svelte +21 -14
- package/examples/Density.svelte +7 -0
- package/examples/Dumbbell.svelte +16 -0
- package/examples/Facets.svelte +3 -3
- package/examples/FacetsCarousel.svelte +14 -0
- package/examples/FacetsRowsCols.svelte +23 -0
- package/examples/FirstPlot.svelte +7 -0
- package/examples/Forest.svelte +17 -0
- package/examples/Gaps.svelte +21 -0
- package/examples/GroupedBars.svelte +15 -0
- package/examples/Heatmap.svelte +7 -0
- package/examples/HeatmapSegments.svelte +26 -0
- package/examples/Histogram.svelte +14 -0
- package/examples/HorizontalBars.svelte +15 -0
- package/examples/LegendSections.svelte +27 -0
- package/examples/LegendToggle.svelte +3 -3
- package/examples/LineByRegion.svelte +18 -0
- package/examples/LineDates.svelte +15 -0
- package/examples/LineStep.svelte +16 -0
- package/examples/LineStepSegment.svelte +18 -0
- package/examples/Lollipop.svelte +17 -0
- package/examples/Markers.svelte +27 -0
- package/examples/MovingAverage.svelte +15 -0
- package/examples/Pyramid.svelte +14 -0
- package/examples/Regression.svelte +14 -0
- package/examples/ResponsiveLine.svelte +7 -7
- package/examples/Scales.svelte +26 -0
- package/examples/Scatter.svelte +16 -0
- package/examples/SegmentHighlight.svelte +22 -0
- package/examples/Segments.svelte +11 -3
- package/examples/SegmentsBySeries.svelte +25 -0
- package/examples/Slope.svelte +17 -0
- package/examples/Sparkline.svelte +14 -0
- package/examples/StackedArea.svelte +16 -0
- package/examples/StackedBars.svelte +15 -0
- package/examples/TimelinePlayer.svelte +8 -7
- package/examples/TimelineRule.svelte +19 -0
- package/examples/Tooltip.svelte +3 -3
- package/examples/ValueLabels.svelte +21 -0
- package/examples/Violin.svelte +14 -0
- package/examples/datasets/argentina-chile-trends.ts +34 -0
- package/examples/datasets/commodity-prices.ts +48 -0
- package/examples/datasets/countries-over-time.ts +368 -0
- package/examples/datasets/daily-temperature.ts +121 -0
- package/examples/datasets/earthquakes.ts +977 -0
- package/examples/datasets/flight-routes.ts +29 -0
- package/examples/datasets/height-density.ts +37 -0
- package/examples/datasets/heights.ts +370 -0
- package/examples/datasets/index.ts +24 -0
- package/examples/datasets/inflation-by-region.ts +44 -0
- package/examples/datasets/inflation-ranges.ts +34 -0
- package/examples/datasets/iris-flower.ts +207 -0
- package/examples/datasets/life-expectancy.ts +95 -0
- package/examples/datasets/napoleons-march.ts +182 -0
- package/examples/datasets/penguins.ts +54 -0
- package/examples/datasets/population-by-age-with-gaps.ts +23 -0
- package/examples/datasets/population-by-age.ts +890 -0
- package/examples/datasets/province-population.ts +521 -0
- package/examples/datasets/stock-prices.ts +63 -0
- package/examples/datasets/weather-stations-over-time.ts +31 -0
- package/examples/datasets/weather-stations.ts +22 -0
- package/examples/datasets/wind-vectors.ts +30 -0
- package/examples/datasets/world-temperature.ts +400 -0
- package/llms-full.txt +51 -12
- package/llms.txt +60 -4
- package/package.json +12 -2
- package/dist/layout/scales/buildScale.d.ts +0 -8
- package/dist/layout/scales/buildScale.js +0 -67
- package/dist/layout/scales/niceDomain.d.ts +0 -23
- package/dist/layout/scales/niceDomain.js +0 -59
- package/dist/plots/bar/defaults.d.ts +0 -9
- package/dist/plots/geo/features.svelte.d.ts +0 -5
- package/dist/plots/geo/features.svelte.js +0 -44
- package/dist/plots/geo/phases/tooltip.js +0 -5
- package/dist/plots/utils/geoAccessors.d.ts +0 -72
- package/dist/plots/utils/geoAccessors.js +0 -220
- package/dist/plots/utils/geoSegments.d.ts +0 -29
- package/dist/plots/utils/geoSegments.js +0 -37
- package/dist/types/layout/styles.d.ts +0 -122
- package/dist/types/markers/axis/curveName.d.ts +0 -2
- package/dist/types/plots/line/props.d.ts +0 -10
- package/dist/utils/color/contrast.d.ts +0 -9
- package/dist/utils/color/contrast.js +0 -40
- package/dist/utils/color/cssColor.d.ts +0 -4
- package/dist/utils/color/cssColor.js +0 -77
- package/dist/utils/color/ramp.d.ts +0 -17
- package/dist/utils/color/ramp.js +0 -110
- package/dist/utils/opacity.d.ts +0 -9
- package/dist/utils/opacity.js +0 -38
- package/examples/data.ts +0 -12
- /package/dist/types/layout/{styles.js → statistics/deviation.js} +0 -0
- /package/dist/types/{markers/axis/curveName.js → layout/styles/base.js} +0 -0
- /package/dist/types/{plots/area/props.js → layout/styles/bullet.js} +0 -0
- /package/dist/types/{plots/area/state.js → layout/styles/connector.js} +0 -0
- /package/dist/types/{plots/bar/props.js → layout/styles/curve.js} +0 -0
- /package/dist/types/{plots/bar/state.js → layout/styles/frame.js} +0 -0
- /package/dist/types/{plots/geo/props.js → layout/styles/gaps.js} +0 -0
- /package/dist/types/{plots/geo/state.js → layout/styles/geo.js} +0 -0
- /package/dist/types/{plots/heatmap/props.js → layout/styles/values.js} +0 -0
- /package/dist/types/{plots/heatmap/state.js → markers/axis/violin.js} +0 -0
- /package/dist/types/{plots/histogram/props.js → markers/channels/commonMarkerConfigWithRowOffset.js} +0 -0
- /package/dist/types/plots/{line → correlation/heatmap}/props.js +0 -0
- /package/dist/types/plots/{histogram → correlation/heatmap}/state.js +0 -0
- /package/dist/types/plots/{pyramid → correlation/scatter}/props.js +0 -0
- /package/dist/types/plots/{line → correlation/scatter}/state.js +0 -0
- /package/dist/types/plots/{scatter → distribution/box}/props.js +0 -0
- /package/dist/types/plots/{pyramid → distribution/box}/state.js +0 -0
- /package/dist/types/plots/{scatter/state.js → distribution/density/props.js} +0 -0
- /package/dist/{plots/utils → utils}/accessors.d.ts +0 -0
- /package/dist/{plots/utils → utils}/accessors.js +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { ProcessedPositions } from '../../phases/transforms/ProcessedPositions';
|
|
1
2
|
import { Box } from '../margins/Box';
|
|
2
|
-
import { resolveAccessor } from '../../
|
|
3
|
-
import { SERIES_ID_KEY, SERIES_KEY
|
|
3
|
+
import { resolveAccessor } from '../../utils/accessors';
|
|
4
|
+
import { SERIES_ID_KEY, SERIES_KEY } from '../../phases/transforms/TransformsPhase';
|
|
4
5
|
import { seriesIdOf } from '../../utils/grouping';
|
|
5
|
-
import { Transforms } from '../../phases/transforms/Transforms';
|
|
6
6
|
import { isGapValue } from '../../plots/utils/gaps';
|
|
7
7
|
import { PlotAxes } from '../../phases/data/PlotAxes';
|
|
8
8
|
/**
|
|
@@ -20,6 +20,8 @@ export class ValueLabels {
|
|
|
20
20
|
fontSize;
|
|
21
21
|
/** The connectors of labels that had to move apart. */
|
|
22
22
|
strokeStyle;
|
|
23
|
+
/** `'series'` writes each label in its series' color; any other CSS color writes them all in it. */
|
|
24
|
+
color;
|
|
23
25
|
/** How labels that would overlap move apart - the configuration's `text.declutter`. */
|
|
24
26
|
declutter;
|
|
25
27
|
/** Where the labels are expected to sit: boxes around their points, on the edges those can reach. */
|
|
@@ -33,6 +35,7 @@ export class ValueLabels {
|
|
|
33
35
|
this.font = values?.fontStyle;
|
|
34
36
|
this.fontSize = typeof this.font?.fontSize === 'number' ? this.font.fontSize : 12;
|
|
35
37
|
this.strokeStyle = values?.strokeStyle;
|
|
38
|
+
this.color = values?.color;
|
|
36
39
|
this.declutter = cfg.text.declutter;
|
|
37
40
|
this.#cfg = cfg;
|
|
38
41
|
this.reach = (this.show && reach?.(this)) || [];
|
|
@@ -42,6 +45,18 @@ export class ValueLabels {
|
|
|
42
45
|
const { reach } = options;
|
|
43
46
|
return new ValueLabels(values, cfg, options, reach && ((labels) => reach(labels, state)));
|
|
44
47
|
}
|
|
48
|
+
/** The configuration the labels were built under, for a plot kind's own label defaults. */
|
|
49
|
+
get config() {
|
|
50
|
+
return this.#cfg;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The fill every label takes whatever its series: the author's own
|
|
54
|
+
* `fontStyle.fill`, else a literal `color`. `undefined` leaves each label to
|
|
55
|
+
* its plot's default (its series' color, or the axis').
|
|
56
|
+
*/
|
|
57
|
+
get fill() {
|
|
58
|
+
return this.font?.fill ?? (this.color === 'series' ? undefined : this.color);
|
|
59
|
+
}
|
|
45
60
|
/** One line of label text's height. */
|
|
46
61
|
get lineHeight() {
|
|
47
62
|
return this.fontSize * 1.2;
|
|
@@ -132,14 +147,46 @@ export class ValueLabels {
|
|
|
132
147
|
* (`filter` + `selectLast`, per series), at its top (a stacked row's
|
|
133
148
|
* `y2`), labelled with its own value and placed by `anchor`. Labels that
|
|
134
149
|
* would overlap fan out into a shared column (`declutter`), colored by the
|
|
135
|
-
* segment the row falls in.
|
|
150
|
+
* segment the row falls in. A plot that labels each end of its series apart
|
|
151
|
+
* passes the `rows` and `anchor` of one end, and `lane` to route its labels
|
|
152
|
+
* out to a lane whether or not they overlap (`flip: false` keeps one on the
|
|
153
|
+
* left in the margin instead of flipping it over its points).
|
|
136
154
|
*/
|
|
137
|
-
atSeriesEnds(state) {
|
|
155
|
+
atSeriesEnds(state, end = {}) {
|
|
156
|
+
if (end.rows)
|
|
157
|
+
return this.#seriesEnds(state, end);
|
|
158
|
+
// A label on a series' first point would sit on its own line: it goes out to a lane instead.
|
|
159
|
+
const firsts = ValueLabels.#firstRows(state);
|
|
160
|
+
const labelled = state.labelled ?? [];
|
|
161
|
+
return [
|
|
162
|
+
...this.#seriesEnds(state, { rows: labelled.filter((row) => !firsts.has(row)) }),
|
|
163
|
+
...this.#seriesEnds(state, {
|
|
164
|
+
rows: labelled.filter((row) => firsts.has(row)),
|
|
165
|
+
lane: { elbowGap: ValueLabels.FIRST_LANE_GAP }
|
|
166
|
+
})
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
/** How far (px) a lane takes the label of a series' first point from it - clear of the line that leaves it. */
|
|
170
|
+
static FIRST_LANE_GAP = 28;
|
|
171
|
+
/** The first row of every series that has more than one. */
|
|
172
|
+
static #firstRows(state) {
|
|
173
|
+
const first = new Map();
|
|
174
|
+
const counts = new Map();
|
|
175
|
+
for (const row of state.processedData?.data ?? []) {
|
|
176
|
+
const id = String(row[SERIES_ID_KEY]);
|
|
177
|
+
if (!first.has(id))
|
|
178
|
+
first.set(id, row);
|
|
179
|
+
counts.set(id, (counts.get(id) ?? 0) + 1);
|
|
180
|
+
}
|
|
181
|
+
return new Set([...first].filter(([id]) => (counts.get(id) ?? 0) > 1).map(([, row]) => row));
|
|
182
|
+
}
|
|
183
|
+
#seriesEnds(state, end) {
|
|
138
184
|
const processed = state.processedData;
|
|
139
185
|
if (!processed)
|
|
140
186
|
return [];
|
|
141
|
-
const { font,
|
|
142
|
-
const
|
|
187
|
+
const { font, format } = this;
|
|
188
|
+
const anchor = end.anchor ?? this.anchor;
|
|
189
|
+
const position = ProcessedPositions.of(processed);
|
|
143
190
|
const topOf = (d) => position.y(d);
|
|
144
191
|
const nameOf = (d) => String(d[SERIES_KEY]);
|
|
145
192
|
const valueOf = ValueLabels.valueOf(state);
|
|
@@ -152,33 +199,39 @@ export class ValueLabels {
|
|
|
152
199
|
group?.color ??
|
|
153
200
|
state.colorForSeries?.(nameOf(d)));
|
|
154
201
|
};
|
|
155
|
-
const marker =
|
|
202
|
+
const marker = {
|
|
156
203
|
type: 'text',
|
|
157
|
-
|
|
204
|
+
// The rows the "transforms" phase picked for the labels: by default each series' last.
|
|
205
|
+
data: end.rows ?? state.labelled ?? [],
|
|
158
206
|
x: (processed.channels.x ?? position.x),
|
|
159
207
|
y: (processed.channels.y2 ?? processed.channels.y ?? topOf),
|
|
160
208
|
grouping: SERIES_ID_KEY,
|
|
161
|
-
transforms: [
|
|
162
|
-
{
|
|
163
|
-
type: 'filter',
|
|
164
|
-
filter: (d) => !isGapValue(valueOf(d)) && !isGapValue(topOf(d))
|
|
165
|
-
},
|
|
166
|
-
{ type: 'selectLast' }
|
|
167
|
-
],
|
|
168
209
|
text: (d) => format(Number(valueOf(d)), nameOf(d)),
|
|
169
210
|
styles: {
|
|
170
211
|
...font,
|
|
212
|
+
...(this.fill ? { fill: this.fill } : {}),
|
|
171
213
|
fontSize: font?.fontSize ?? 12,
|
|
172
214
|
dx: font?.dx ?? (anchor === 'start' ? 6 : anchor === 'end' ? -6 : 0),
|
|
173
215
|
dy: font?.dy ?? (anchor === 'outside' ? -8 : 0),
|
|
174
216
|
textAnchor: this.textAnchor ?? (anchor === 'start' || anchor === 'end' ? anchor : 'middle'),
|
|
175
217
|
lineAnchor: font?.lineAnchor ?? (anchor === 'outside' ? 'bottom' : 'middle')
|
|
176
218
|
},
|
|
177
|
-
fill:
|
|
178
|
-
declutter: {
|
|
179
|
-
|
|
219
|
+
fill: this.fill ? undefined : colorOf,
|
|
220
|
+
declutter: {
|
|
221
|
+
connector: this.strokeStyle,
|
|
222
|
+
aligned: !!end.lane && (anchor === 'start' || anchor === 'end'),
|
|
223
|
+
elbowGap: typeof end.lane === 'object' ? end.lane.elbowGap : undefined,
|
|
224
|
+
flip: end.flip
|
|
225
|
+
}
|
|
226
|
+
};
|
|
180
227
|
return marker.data?.length ? [marker] : [];
|
|
181
228
|
}
|
|
229
|
+
/** The rows of a series-over-`x` plot that cannot be labelled: a gap, or a stack with no top. For the "transforms" phase's `labels.skip`. */
|
|
230
|
+
static skipGaps(state) {
|
|
231
|
+
const valueOf = ValueLabels.valueOf(state);
|
|
232
|
+
const top = ProcessedPositions.of(state.processedData).y;
|
|
233
|
+
return (row) => isGapValue(valueOf(row)) || isGapValue(top(row));
|
|
234
|
+
}
|
|
182
235
|
/**
|
|
183
236
|
* Where {@link atSeriesEnds}' labels are expected to sit: past each
|
|
184
237
|
* series' last point, at the right edge (or the left, for labels set
|
|
@@ -187,9 +240,9 @@ export class ValueLabels {
|
|
|
187
240
|
* domain when the scales set one, so it holds across a timeline; else off
|
|
188
241
|
* every value.
|
|
189
242
|
*/
|
|
190
|
-
reachAtSeriesEnds(state) {
|
|
243
|
+
reachAtSeriesEnds(state, anchor = this.anchor) {
|
|
191
244
|
const series = state.resolvedSeries ?? [];
|
|
192
|
-
const {
|
|
245
|
+
const { font, format } = this;
|
|
193
246
|
const dx = typeof font?.dx === 'number' ? font.dx : anchor === 'start' ? 6 : anchor === 'end' ? -6 : 0;
|
|
194
247
|
const dy = typeof font?.dy === 'number' ? font.dy : anchor === 'outside' ? -8 : 0;
|
|
195
248
|
const textAnchor = this.textAnchor ?? (anchor === 'start' ? 'start' : anchor === 'end' ? 'end' : 'middle');
|
|
@@ -202,11 +255,18 @@ export class ValueLabels {
|
|
|
202
255
|
const { elbowGap, laneStep, labelGap } = this.declutter;
|
|
203
256
|
const lanes = elbowGap + (series.length - 1) * laneStep + labelGap;
|
|
204
257
|
const at = { x: series.length > 1 ? (Math.sign(dx) || 1) * lanes : dx, y: dy };
|
|
258
|
+
// Only a label that can sit at the plot's right end - any but a first point's - reaches that edge.
|
|
259
|
+
const selects = state.labelSelects ?? [];
|
|
260
|
+
const atRight = selects.length === 0 || selects.some((select) => select !== 'first');
|
|
261
|
+
// Likewise a label set before its point reaches the left edge only from a point that can sit there: any but a last one - or a last one that is also the first, of a series with a single point.
|
|
262
|
+
const atLeft = selects.length === 0 ||
|
|
263
|
+
selects.some((select) => select !== 'last') ||
|
|
264
|
+
series.some((s) => s.data.length < 2);
|
|
205
265
|
const edges = [
|
|
206
266
|
'top',
|
|
207
267
|
'bottom',
|
|
208
|
-
...(dx < 0 ? ['left'] : []),
|
|
209
|
-
...(dx >= 0 || series.length > 1 ? ['right'] : [])
|
|
268
|
+
...(dx < 0 && atLeft ? ['left'] : []),
|
|
269
|
+
...((dx >= 0 || series.length > 1) && atRight ? ['right'] : [])
|
|
210
270
|
];
|
|
211
271
|
const texts = [];
|
|
212
272
|
const domain = state.scales.y?.domain;
|
|
@@ -15,12 +15,15 @@
|
|
|
15
15
|
currentValue,
|
|
16
16
|
values,
|
|
17
17
|
orientation = 'vertical',
|
|
18
|
+
format = (value: TimeValue) => String(value),
|
|
18
19
|
width,
|
|
19
20
|
height
|
|
20
21
|
}: {
|
|
21
22
|
currentValue: TimeValue;
|
|
22
23
|
values: TimeValue[];
|
|
23
24
|
orientation?: Orientation;
|
|
25
|
+
/** How a step's label reads. */
|
|
26
|
+
format?: (value: TimeValue) => string;
|
|
24
27
|
width: number;
|
|
25
28
|
height: number;
|
|
26
29
|
} = $props();
|
|
@@ -72,7 +75,7 @@
|
|
|
72
75
|
<Text
|
|
73
76
|
data={baseValues}
|
|
74
77
|
{...isHorizontal ? { x: identity, y: 0 } : { x: 0, y: identity }}
|
|
75
|
-
text={(d: TimeValue) =>
|
|
78
|
+
text={(d: TimeValue) => format(d)}
|
|
76
79
|
{...textOffset}
|
|
77
80
|
fontSize={rule.fontSize}
|
|
78
81
|
fill="var(--dct-timeline-axis, currentColor)"
|
|
@@ -82,7 +85,7 @@
|
|
|
82
85
|
<Text
|
|
83
86
|
data={[currentValue]}
|
|
84
87
|
{...isHorizontal ? { x: identity, y: 0 } : { x: 0, y: identity }}
|
|
85
|
-
text={(d: TimeValue) =>
|
|
88
|
+
text={(d: TimeValue) => format(d)}
|
|
86
89
|
{...textOffset}
|
|
87
90
|
fontSize={rule.activeFontSize}
|
|
88
91
|
fontWeight={rule.activeFontWeight}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
<script lang="ts" generics="TRow extends Record<string, unknown>">
|
|
2
2
|
import { untrack } from 'svelte';
|
|
3
|
-
import { resolveAccessor } from '../../
|
|
3
|
+
import { resolveAccessor } from '../../utils/accessors';
|
|
4
4
|
import TimelineFrame from './TimelineFrame.svelte';
|
|
5
5
|
import { TimelineSteps } from './TimelineSteps';
|
|
6
|
+
import { TimelineTime } from './TimelineTime';
|
|
6
7
|
import { Interpolation } from '../../utils/Interpolation';
|
|
7
8
|
import type {
|
|
8
9
|
Orientation,
|
|
10
|
+
TimeInput,
|
|
9
11
|
TimeValue,
|
|
10
12
|
TimelineChildSnippet,
|
|
11
13
|
TimelineInterpolation
|
|
@@ -22,6 +24,7 @@
|
|
|
22
24
|
let {
|
|
23
25
|
data,
|
|
24
26
|
accessor,
|
|
27
|
+
dateFormat,
|
|
25
28
|
progress,
|
|
26
29
|
values,
|
|
27
30
|
orientation = 'vertical',
|
|
@@ -35,28 +38,44 @@
|
|
|
35
38
|
child
|
|
36
39
|
}: {
|
|
37
40
|
data: TRow[];
|
|
38
|
-
accessor: Accessor<TRow,
|
|
41
|
+
accessor: Accessor<TRow, TimeInput>;
|
|
42
|
+
/** How a non-ISO date string reads. */
|
|
43
|
+
dateFormat?: string;
|
|
39
44
|
progress: number;
|
|
40
|
-
values?:
|
|
45
|
+
values?: TimeInput[];
|
|
41
46
|
orientation?: Orientation;
|
|
42
47
|
show?: boolean;
|
|
43
48
|
thickness?: number;
|
|
44
49
|
filterMode?: 'exact' | 'upTo';
|
|
45
50
|
interpolate?: TimelineInterpolation<TRow>;
|
|
46
|
-
/** Told the steps,
|
|
47
|
-
onsteps?: (values: TimeValue[]) => void;
|
|
51
|
+
/** Told the steps, and whether they are dates, when they change. */
|
|
52
|
+
onsteps?: (values: TimeValue[], temporal: boolean) => void;
|
|
48
53
|
width: number;
|
|
49
54
|
height: number;
|
|
50
55
|
child: TimelineChildSnippet<TRow>;
|
|
51
56
|
} = $props();
|
|
52
57
|
|
|
53
|
-
const
|
|
58
|
+
const time = $derived(new TimelineTime(dateFormat));
|
|
59
|
+
const getRaw = $derived(resolveAccessor<TRow>(accessor) as (row: TRow) => unknown);
|
|
60
|
+
/** A row's step, or `undefined` when its value reads as none. */
|
|
61
|
+
const getTime = $derived((row: TRow) => time.toTime(getRaw(row)));
|
|
62
|
+
/** The rows with a step; one without shows at every step. */
|
|
63
|
+
const timed = $derived(data.filter((row) => getTime(row) !== undefined));
|
|
64
|
+
const untimed = $derived(data.filter((row) => getTime(row) === undefined));
|
|
54
65
|
|
|
55
|
-
const steps = $derived(
|
|
66
|
+
const steps = $derived(
|
|
67
|
+
TimelineSteps.of(
|
|
68
|
+
values?.map((value) => time.toTime(value)).filter((v): v is TimeValue => v !== undefined),
|
|
69
|
+
timed,
|
|
70
|
+
getTime as (row: TRow) => TimeValue
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
const temporal = $derived(time.isTemporal(values?.length ? values : timed.map(getRaw)));
|
|
56
74
|
|
|
57
75
|
$effect(() => {
|
|
58
76
|
const found = steps.values;
|
|
59
|
-
|
|
77
|
+
const dates = temporal;
|
|
78
|
+
untrack(() => onsteps?.(found, dates));
|
|
60
79
|
});
|
|
61
80
|
|
|
62
81
|
const progressEasingFn = $derived(Interpolation.buildEasing(interpolate?.progressEasing));
|
|
@@ -77,12 +96,19 @@
|
|
|
77
96
|
);
|
|
78
97
|
return upper;
|
|
79
98
|
}
|
|
80
|
-
return {
|
|
99
|
+
return {
|
|
100
|
+
...upper,
|
|
101
|
+
[accessor]: time.toValueLike(x, upper[accessor]),
|
|
102
|
+
[valueField]: value
|
|
103
|
+
} as TRow;
|
|
81
104
|
}
|
|
82
105
|
|
|
83
106
|
const filtered = $derived.by(() => {
|
|
84
107
|
const discrete = () =>
|
|
85
|
-
data.filter((d) =>
|
|
108
|
+
data.filter((d) => {
|
|
109
|
+
const at = getTime(d);
|
|
110
|
+
return at === undefined || TimelineSteps.matches(at, selectedValue, filterMode);
|
|
111
|
+
});
|
|
86
112
|
|
|
87
113
|
if (!interpolate) return discrete();
|
|
88
114
|
if (!interpolate.value) {
|
|
@@ -96,14 +122,14 @@
|
|
|
96
122
|
const getValue = resolveAccessor<TRow>(interpolate.value) as (d: TRow) => number;
|
|
97
123
|
const create = interpolate.create ?? defaultCreate;
|
|
98
124
|
|
|
99
|
-
const groups = Map.groupBy(
|
|
125
|
+
const groups = Map.groupBy(timed, (row) => String(getKey(row)));
|
|
100
126
|
|
|
101
|
-
const result: TRow[] = [];
|
|
127
|
+
const result: TRow[] = [...untimed];
|
|
102
128
|
for (const rows of groups.values()) {
|
|
103
129
|
const tweened = Interpolation.tweenSeries({
|
|
104
130
|
rows,
|
|
105
131
|
x: currentTime,
|
|
106
|
-
getTime,
|
|
132
|
+
getTime: getTime as (row: TRow) => TimeValue,
|
|
107
133
|
getValue,
|
|
108
134
|
create,
|
|
109
135
|
segmentEasing: segmentEasingFn
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import type { Orientation, TimeValue, TimelineChildSnippet, TimelineInterpolation } from '../../types/layout/timeline';
|
|
1
|
+
import type { Orientation, TimeInput, TimeValue, TimelineChildSnippet, TimelineInterpolation } from '../../types/layout/timeline';
|
|
2
2
|
import type { Accessor } from '../../types/plots/data/common';
|
|
3
3
|
declare function $$render<TRow extends Record<string, unknown>>(): {
|
|
4
4
|
props: {
|
|
5
5
|
data: TRow[];
|
|
6
|
-
accessor: Accessor<TRow,
|
|
6
|
+
accessor: Accessor<TRow, TimeInput>;
|
|
7
|
+
/** How a non-ISO date string reads. */
|
|
8
|
+
dateFormat?: string;
|
|
7
9
|
progress: number;
|
|
8
|
-
values?:
|
|
10
|
+
values?: TimeInput[];
|
|
9
11
|
orientation?: Orientation;
|
|
10
12
|
show?: boolean;
|
|
11
13
|
thickness?: number;
|
|
12
14
|
filterMode?: "exact" | "upTo";
|
|
13
15
|
interpolate?: TimelineInterpolation<TRow>;
|
|
14
|
-
/** Told the steps,
|
|
15
|
-
onsteps?: (values: TimeValue[]) => void;
|
|
16
|
+
/** Told the steps, and whether they are dates, when they change. */
|
|
17
|
+
onsteps?: (values: TimeValue[], temporal: boolean) => void;
|
|
16
18
|
width: number;
|
|
17
19
|
height: number;
|
|
18
20
|
child: TimelineChildSnippet<TRow>;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import type { PlayerConfig, PlayerControl, Orientation, TimeValue, TimelineCallbacks, TimelineType } from '../../types/layout/timeline';
|
|
1
|
+
import type { PlayerConfig, PlayerControl, Orientation, TimeInput, TimeValue, TimelineStep, TimelineCallbacks, TimelineType } from '../../types/layout/timeline';
|
|
2
2
|
/** What a {@link TimelineState} reads from the timeline's owner, each time it needs it. */
|
|
3
3
|
export type TimelineSettings = TimelineCallbacks & {
|
|
4
4
|
type?: TimelineType;
|
|
5
5
|
player?: PlayerConfig;
|
|
6
6
|
progress?: number;
|
|
7
|
-
values?:
|
|
7
|
+
values?: TimeInput[];
|
|
8
|
+
/** How a non-ISO date string in `values` reads. */
|
|
9
|
+
dateFormat?: string;
|
|
8
10
|
show?: boolean;
|
|
9
11
|
orientation?: Orientation;
|
|
10
12
|
thickness?: number;
|
|
@@ -37,8 +39,10 @@ export declare class TimelineState {
|
|
|
37
39
|
get shown(): boolean;
|
|
38
40
|
/** The steps it moves across, ascending: the owner's `values`, else those its plots report. */
|
|
39
41
|
get steps(): TimeValue[];
|
|
40
|
-
/**
|
|
41
|
-
|
|
42
|
+
/** Whether the steps are dates. */
|
|
43
|
+
get temporal(): boolean;
|
|
44
|
+
/** Reports the steps the plots found in their rows, and whether they are dates. */
|
|
45
|
+
setSteps(values: TimeValue[], temporal?: boolean): void;
|
|
42
46
|
/** The position across the steps, `0`-`1`. */
|
|
43
47
|
get progress(): number;
|
|
44
48
|
/** The step the position lands on, as an index; `-1` without steps. */
|
|
@@ -55,8 +59,12 @@ export declare class TimelineState {
|
|
|
55
59
|
get speeds(): number[];
|
|
56
60
|
/** Milliseconds each step lasts at speed `1`. */
|
|
57
61
|
get stepDuration(): number;
|
|
58
|
-
/** How the
|
|
62
|
+
/** How a step reads: the player's `format`, else a date label or the number. */
|
|
59
63
|
get format(): (value: TimeValue) => string;
|
|
64
|
+
/** A step as authors see it. */
|
|
65
|
+
step(value: TimeValue): TimelineStep;
|
|
66
|
+
/** An author's step as the timeline's own, or `undefined` when it reads as none. */
|
|
67
|
+
timeOf(value: TimeInput): TimeValue | undefined;
|
|
60
68
|
/** Moves to `progress` (`0`-`1`), and tells the owner. */
|
|
61
69
|
seek(progress: number): void;
|
|
62
70
|
/** Moves to the step at `index`. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getContext, setContext, untrack } from 'svelte';
|
|
2
2
|
import { getConfiguration } from '../../configuration/config.svelte';
|
|
3
3
|
import { TimelineSteps } from './TimelineSteps';
|
|
4
|
+
import { TimelineTime } from './TimelineTime';
|
|
4
5
|
const TIMELINE_KEY = Symbol('dct-timeline');
|
|
5
6
|
/** The longest a frame counts for while playing, so a hidden tab doesn't jump ahead when it comes back. */
|
|
6
7
|
const MAX_FRAME_MS = 250;
|
|
@@ -17,6 +18,7 @@ const MAX_FRAME_MS = 250;
|
|
|
17
18
|
export class TimelineState {
|
|
18
19
|
#settings;
|
|
19
20
|
#steps = $state([]);
|
|
21
|
+
#temporal = $state(false);
|
|
20
22
|
#own = $state(null);
|
|
21
23
|
#playing = $state(false);
|
|
22
24
|
#loop = $state(false);
|
|
@@ -58,14 +60,33 @@ export class TimelineState {
|
|
|
58
60
|
}
|
|
59
61
|
/** The steps it moves across, ascending: the owner's `values`, else those its plots report. */
|
|
60
62
|
get steps() {
|
|
61
|
-
const values = this.#
|
|
62
|
-
return values
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
|
|
63
|
+
const values = this.#ownerValues;
|
|
64
|
+
return values ? new TimelineSteps(values).values : this.#steps;
|
|
65
|
+
}
|
|
66
|
+
/** Whether the steps are dates. */
|
|
67
|
+
get temporal() {
|
|
68
|
+
const settings = this.#settings();
|
|
69
|
+
if (!settings?.values?.length)
|
|
70
|
+
return this.#temporal;
|
|
71
|
+
return new TimelineTime(settings.dateFormat).isTemporal(settings.values);
|
|
72
|
+
}
|
|
73
|
+
/** Reports the steps the plots found in their rows, and whether they are dates. */
|
|
74
|
+
setSteps(values, temporal = false) {
|
|
66
75
|
const same = values.length === this.#steps.length && values.every((v, i) => v === this.#steps[i]);
|
|
67
76
|
if (!same)
|
|
68
77
|
this.#steps = values;
|
|
78
|
+
if (temporal !== this.#temporal)
|
|
79
|
+
this.#temporal = temporal;
|
|
80
|
+
}
|
|
81
|
+
/** The owner's `values` as steps, or `undefined` without any. */
|
|
82
|
+
get #ownerValues() {
|
|
83
|
+
const settings = this.#settings();
|
|
84
|
+
if (!settings?.values?.length)
|
|
85
|
+
return undefined;
|
|
86
|
+
const time = new TimelineTime(settings.dateFormat);
|
|
87
|
+
return settings.values
|
|
88
|
+
.map((value) => time.toTime(value))
|
|
89
|
+
.filter((value) => value !== undefined);
|
|
69
90
|
}
|
|
70
91
|
/** The position across the steps, `0`-`1`. */
|
|
71
92
|
get progress() {
|
|
@@ -103,9 +124,22 @@ export class TimelineState {
|
|
|
103
124
|
get stepDuration() {
|
|
104
125
|
return (this.#settings()?.player?.stepDuration ?? getConfiguration().timeline.player.stepDuration);
|
|
105
126
|
}
|
|
106
|
-
/** How the
|
|
127
|
+
/** How a step reads: the player's `format`, else a date label or the number. */
|
|
107
128
|
get format() {
|
|
108
|
-
|
|
129
|
+
const own = this.#settings()?.player?.format;
|
|
130
|
+
if (own)
|
|
131
|
+
return (value) => own(this.step(value));
|
|
132
|
+
if (this.temporal)
|
|
133
|
+
return TimelineTime.dateLabel(this.steps, getConfiguration().axis.locale);
|
|
134
|
+
return (value) => String(value);
|
|
135
|
+
}
|
|
136
|
+
/** A step as authors see it. */
|
|
137
|
+
step(value) {
|
|
138
|
+
return TimelineTime.toStep(value, this.temporal);
|
|
139
|
+
}
|
|
140
|
+
/** An author's step as the timeline's own, or `undefined` when it reads as none. */
|
|
141
|
+
timeOf(value) {
|
|
142
|
+
return new TimelineTime(this.#settings()?.dateFormat).toTime(value);
|
|
109
143
|
}
|
|
110
144
|
/** Moves to `progress` (`0`-`1`), and tells the owner. */
|
|
111
145
|
seek(progress) {
|
|
@@ -196,7 +230,7 @@ export class TimelineState {
|
|
|
196
230
|
const value = this.value;
|
|
197
231
|
untrack(() => {
|
|
198
232
|
if (last !== undefined && value !== undefined && value !== last) {
|
|
199
|
-
this.#settings()?.onvalue?.(value);
|
|
233
|
+
this.#settings()?.onvalue?.(this.step(value));
|
|
200
234
|
}
|
|
201
235
|
last = value;
|
|
202
236
|
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TimeValue, TimelineStep } from '../../types/layout/timeline';
|
|
2
|
+
/** Reads a timeline's values (numbers, `Date`s, ISO or `dateFormat` strings) as numeric steps, and back. */
|
|
3
|
+
export declare class TimelineTime {
|
|
4
|
+
#private;
|
|
5
|
+
readonly dateFormat?: string | undefined;
|
|
6
|
+
/** @param dateFormat How a non-ISO date string reads, e.g. `'DD/MM/YYYY'`. */
|
|
7
|
+
constructor(dateFormat?: string | undefined);
|
|
8
|
+
/** A value as its step, or `undefined` when it reads as none. */
|
|
9
|
+
toTime(value: unknown): TimeValue | undefined;
|
|
10
|
+
/** A step as authors see it: a `Date` when `temporal`, else the number. */
|
|
11
|
+
static toStep(value: TimeValue, temporal: boolean): TimelineStep;
|
|
12
|
+
/** Whether `values` hold dates rather than plain numbers. */
|
|
13
|
+
isTemporal(values: unknown[]): boolean;
|
|
14
|
+
/** A step written back in the same form as `like`, for interpolated rows. */
|
|
15
|
+
toValueLike(time: TimeValue, like: unknown): unknown;
|
|
16
|
+
/** A date label as precise as the steps need: year, month, day or time. */
|
|
17
|
+
static dateLabel(steps: TimeValue[], locale?: string): (time: TimeValue) => string;
|
|
18
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/** The `dateFormat` tokens and the UTC date part each reads or writes. */
|
|
2
|
+
const TOKENS = {
|
|
3
|
+
YYYY: { group: '(\\d{4})', get: (date) => date.getUTCFullYear(), width: 4 },
|
|
4
|
+
MM: { group: '(\\d{1,2})', get: (date) => date.getUTCMonth() + 1, width: 2 },
|
|
5
|
+
DD: { group: '(\\d{1,2})', get: (date) => date.getUTCDate(), width: 2 },
|
|
6
|
+
HH: { group: '(\\d{1,2})', get: (date) => date.getUTCHours(), width: 2 },
|
|
7
|
+
mm: { group: '(\\d{1,2})', get: (date) => date.getUTCMinutes(), width: 2 },
|
|
8
|
+
ss: { group: '(\\d{1,2})', get: (date) => date.getUTCSeconds(), width: 2 }
|
|
9
|
+
};
|
|
10
|
+
const TOKEN_PATTERN = /YYYY|MM|DD|HH|mm|ss/g;
|
|
11
|
+
/** An ISO 8601 date, from a bare year to a full date-time. */
|
|
12
|
+
const ISO_DATE = /^\d{4}(-\d{2}(-\d{2}([T ]\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?)?)?)?$/;
|
|
13
|
+
const DAY = 24 * 60 * 60 * 1000;
|
|
14
|
+
/** Reads a timeline's values (numbers, `Date`s, ISO or `dateFormat` strings) as numeric steps, and back. */
|
|
15
|
+
export class TimelineTime {
|
|
16
|
+
dateFormat;
|
|
17
|
+
/** @param dateFormat How a non-ISO date string reads, e.g. `'DD/MM/YYYY'`. */
|
|
18
|
+
constructor(dateFormat) {
|
|
19
|
+
this.dateFormat = dateFormat;
|
|
20
|
+
}
|
|
21
|
+
/** A value as its step, or `undefined` when it reads as none. */
|
|
22
|
+
toTime(value) {
|
|
23
|
+
if (typeof value === 'number')
|
|
24
|
+
return Number.isFinite(value) ? value : undefined;
|
|
25
|
+
if (value instanceof Date) {
|
|
26
|
+
const time = value.getTime();
|
|
27
|
+
return Number.isFinite(time) ? time : undefined;
|
|
28
|
+
}
|
|
29
|
+
if (typeof value !== 'string')
|
|
30
|
+
return undefined;
|
|
31
|
+
const text = value.trim();
|
|
32
|
+
if (this.dateFormat) {
|
|
33
|
+
const parsed = TimelineTime.#parse(text, this.dateFormat);
|
|
34
|
+
if (parsed !== undefined)
|
|
35
|
+
return parsed;
|
|
36
|
+
}
|
|
37
|
+
if (text !== '' && Number.isFinite(Number(text)) && !ISO_DATE.test(text))
|
|
38
|
+
return Number(text);
|
|
39
|
+
if (ISO_DATE.test(text)) {
|
|
40
|
+
// A bare year stays a year, like a number.
|
|
41
|
+
if (/^\d{4}$/.test(text))
|
|
42
|
+
return Number(text);
|
|
43
|
+
const time = Date.parse(/^\d{4}-\d{2}$/.test(text) ? `${text}-01` : text);
|
|
44
|
+
return Number.isFinite(time) ? time : undefined;
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
/** A step as authors see it: a `Date` when `temporal`, else the number. */
|
|
49
|
+
static toStep(value, temporal) {
|
|
50
|
+
return temporal ? new Date(value) : value;
|
|
51
|
+
}
|
|
52
|
+
/** Whether `values` hold dates rather than plain numbers. */
|
|
53
|
+
isTemporal(values) {
|
|
54
|
+
return values.some((value) => {
|
|
55
|
+
if (value instanceof Date)
|
|
56
|
+
return true;
|
|
57
|
+
if (typeof value !== 'string')
|
|
58
|
+
return false;
|
|
59
|
+
const text = value.trim();
|
|
60
|
+
return !/^-?\d+(\.\d+)?$/.test(text) && this.toTime(text) !== undefined;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/** A step written back in the same form as `like`, for interpolated rows. */
|
|
64
|
+
toValueLike(time, like) {
|
|
65
|
+
if (like instanceof Date)
|
|
66
|
+
return new Date(time);
|
|
67
|
+
if (typeof like !== 'string')
|
|
68
|
+
return time;
|
|
69
|
+
const text = like.trim();
|
|
70
|
+
if (this.dateFormat && TimelineTime.#parse(text, this.dateFormat) !== undefined) {
|
|
71
|
+
return TimelineTime.#write(new Date(time), this.dateFormat);
|
|
72
|
+
}
|
|
73
|
+
if (ISO_DATE.test(text) && !/^\d{4}$/.test(text)) {
|
|
74
|
+
return new Date(time).toISOString().slice(0, text.length);
|
|
75
|
+
}
|
|
76
|
+
return String(time);
|
|
77
|
+
}
|
|
78
|
+
/** A date label as precise as the steps need: year, month, day or time. */
|
|
79
|
+
static dateLabel(steps, locale) {
|
|
80
|
+
const dates = steps.map((time) => new Date(time));
|
|
81
|
+
const options = dates.every((d) => d.getUTCMonth() === 0 && d.getUTCDate() === 1 && d.getTime() % DAY === 0)
|
|
82
|
+
? { year: 'numeric' }
|
|
83
|
+
: dates.every((d) => d.getUTCDate() === 1 && d.getTime() % DAY === 0)
|
|
84
|
+
? { month: 'short', year: 'numeric' }
|
|
85
|
+
: dates.every((d) => d.getTime() % DAY === 0)
|
|
86
|
+
? { day: 'numeric', month: 'short', year: 'numeric' }
|
|
87
|
+
: { dateStyle: 'medium', timeStyle: 'short' };
|
|
88
|
+
const format = new Intl.DateTimeFormat(locale, { ...options, timeZone: 'UTC' });
|
|
89
|
+
return (time) => format.format(new Date(time));
|
|
90
|
+
}
|
|
91
|
+
/** `text` read through `format`, or `undefined` when it does not match. */
|
|
92
|
+
static #parse(text, format) {
|
|
93
|
+
const order = [];
|
|
94
|
+
const pattern = format
|
|
95
|
+
.split(TOKEN_PATTERN)
|
|
96
|
+
.map((literal) => literal.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
|
|
97
|
+
const tokens = format.match(TOKEN_PATTERN) ?? [];
|
|
98
|
+
let source = pattern[0];
|
|
99
|
+
tokens.forEach((token, index) => {
|
|
100
|
+
order.push(token);
|
|
101
|
+
source += TOKENS[token].group + pattern[index + 1];
|
|
102
|
+
});
|
|
103
|
+
const match = new RegExp(`^${source}$`).exec(text);
|
|
104
|
+
if (!match || !order.length)
|
|
105
|
+
return undefined;
|
|
106
|
+
const parts = { YYYY: 1970, MM: 1, DD: 1, HH: 0, mm: 0, ss: 0 };
|
|
107
|
+
order.forEach((token, index) => (parts[token] = Number(match[index + 1])));
|
|
108
|
+
return Date.UTC(parts.YYYY, parts.MM - 1, parts.DD, parts.HH, parts.mm, parts.ss);
|
|
109
|
+
}
|
|
110
|
+
/** `date` written through `format`. */
|
|
111
|
+
static #write(date, format) {
|
|
112
|
+
return format.replace(TOKEN_PATTERN, (token) => {
|
|
113
|
+
const { get, width } = TOKENS[token];
|
|
114
|
+
return String(get(date)).padStart(width, '0');
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|