@ggts-sh/svelte 0.43.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/LICENSE +21 -0
- package/README.md +97 -0
- package/bin/ggts-codemod.js +47 -0
- package/dist/GGPlot.svelte +491 -0
- package/dist/GGPlot.svelte.d.ts +67 -0
- package/dist/a11y/CanvasA11y.svelte +115 -0
- package/dist/a11y/CanvasA11y.svelte.d.ts +15 -0
- package/dist/a11y/canvas-a11y.d.ts +1 -0
- package/dist/a11y/canvas-a11y.js +2 -0
- package/dist/assembly/assemble.d.ts +1 -0
- package/dist/assembly/assemble.js +1 -0
- package/dist/assembly/labels.d.ts +43 -0
- package/dist/assembly/labels.js +126 -0
- package/dist/assembly/layout.d.ts +158 -0
- package/dist/assembly/layout.js +175 -0
- package/dist/chrome/StatusChrome.svelte +125 -0
- package/dist/chrome/StatusChrome.svelte.d.ts +16 -0
- package/dist/chrome/ToolRail.svelte +293 -0
- package/dist/chrome/ToolRail.svelte.d.ts +26 -0
- package/dist/chrome/chrome-state.svelte.d.ts +63 -0
- package/dist/chrome/chrome-state.svelte.js +158 -0
- package/dist/chrome/theme-css.d.ts +16 -0
- package/dist/chrome/theme-css.js +16 -0
- package/dist/codemod/cli.d.ts +16 -0
- package/dist/codemod/cli.js +150 -0
- package/dist/codemod/edits.d.ts +28 -0
- package/dist/codemod/edits.js +36 -0
- package/dist/codemod/index.d.ts +10 -0
- package/dist/codemod/index.js +10 -0
- package/dist/codemod/migrate-plot-props-rewrite.d.ts +86 -0
- package/dist/codemod/migrate-plot-props-rewrite.js +228 -0
- package/dist/codemod/migrate-plot-props.d.ts +38 -0
- package/dist/codemod/migrate-plot-props.js +159 -0
- package/dist/coord/Coord.svelte +21 -0
- package/dist/coord/Coord.svelte.d.ts +16 -0
- package/dist/coord/CoordCartesian.svelte +11 -0
- package/dist/coord/CoordCartesian.svelte.d.ts +18 -0
- package/dist/coord/CoordFixed.svelte +17 -0
- package/dist/coord/CoordFixed.svelte.d.ts +10 -0
- package/dist/coord/CoordFlip.svelte +11 -0
- package/dist/coord/CoordFlip.svelte.d.ts +18 -0
- package/dist/coord/CoordPolar.svelte +16 -0
- package/dist/coord/CoordPolar.svelte.d.ts +9 -0
- package/dist/coord/CoordRadial.svelte +16 -0
- package/dist/coord/CoordRadial.svelte.d.ts +9 -0
- package/dist/coord/CoordSf.svelte +16 -0
- package/dist/coord/CoordSf.svelte.d.ts +9 -0
- package/dist/coord/CoordTransform.svelte +16 -0
- package/dist/coord/CoordTransform.svelte.d.ts +9 -0
- package/dist/data/index.d.ts +1 -0
- package/dist/data/index.js +2 -0
- package/dist/diagnostics/composition.d.ts +112 -0
- package/dist/diagnostics/composition.js +203 -0
- package/dist/diagnostics/deprecation.d.ts +58 -0
- package/dist/diagnostics/deprecation.js +27 -0
- package/dist/diagnostics/plot-engine-diagnostics.svelte.d.ts +44 -0
- package/dist/diagnostics/plot-engine-diagnostics.svelte.js +193 -0
- package/dist/facet/Facet.svelte +23 -0
- package/dist/facet/Facet.svelte.d.ts +16 -0
- package/dist/facet/FacetGrid.svelte +32 -0
- package/dist/facet/FacetGrid.svelte.d.ts +16 -0
- package/dist/facet/FacetWrap.svelte +32 -0
- package/dist/facet/FacetWrap.svelte.d.ts +16 -0
- package/dist/fonts/RobotoCondensed-Bold.ttf +0 -0
- package/dist/fonts/RobotoCondensed-Light.ttf +0 -0
- package/dist/fonts/RobotoCondensed-Regular.ttf +0 -0
- package/dist/fonts/THIRD_PARTY_NOTICES.txt +416 -0
- package/dist/geoms/GeomAbline.svelte +25 -0
- package/dist/geoms/GeomAbline.svelte.d.ts +7 -0
- package/dist/geoms/GeomArea.svelte +12 -0
- package/dist/geoms/GeomArea.svelte.d.ts +7 -0
- package/dist/geoms/GeomBar.svelte +12 -0
- package/dist/geoms/GeomBar.svelte.d.ts +7 -0
- package/dist/geoms/GeomBin2d.svelte +21 -0
- package/dist/geoms/GeomBin2d.svelte.d.ts +7 -0
- package/dist/geoms/GeomBlank.svelte +12 -0
- package/dist/geoms/GeomBlank.svelte.d.ts +7 -0
- package/dist/geoms/GeomBoxplot.svelte +25 -0
- package/dist/geoms/GeomBoxplot.svelte.d.ts +7 -0
- package/dist/geoms/GeomCol.svelte +12 -0
- package/dist/geoms/GeomCol.svelte.d.ts +7 -0
- package/dist/geoms/GeomContour.svelte +25 -0
- package/dist/geoms/GeomContour.svelte.d.ts +7 -0
- package/dist/geoms/GeomCount.svelte +12 -0
- package/dist/geoms/GeomCount.svelte.d.ts +7 -0
- package/dist/geoms/GeomCrossbar.svelte +25 -0
- package/dist/geoms/GeomCrossbar.svelte.d.ts +7 -0
- package/dist/geoms/GeomCurve.svelte +21 -0
- package/dist/geoms/GeomCurve.svelte.d.ts +7 -0
- package/dist/geoms/GeomDensity.svelte +25 -0
- package/dist/geoms/GeomDensity.svelte.d.ts +7 -0
- package/dist/geoms/GeomDensity2d.svelte +25 -0
- package/dist/geoms/GeomDensity2d.svelte.d.ts +7 -0
- package/dist/geoms/GeomDensity2dFilled.svelte +25 -0
- package/dist/geoms/GeomDensity2dFilled.svelte.d.ts +7 -0
- package/dist/geoms/GeomDotplot.svelte +25 -0
- package/dist/geoms/GeomDotplot.svelte.d.ts +7 -0
- package/dist/geoms/GeomErrorbar.svelte +25 -0
- package/dist/geoms/GeomErrorbar.svelte.d.ts +7 -0
- package/dist/geoms/GeomFreqpoly.svelte +25 -0
- package/dist/geoms/GeomFreqpoly.svelte.d.ts +7 -0
- package/dist/geoms/GeomFunction.svelte +25 -0
- package/dist/geoms/GeomFunction.svelte.d.ts +7 -0
- package/dist/geoms/GeomHex.svelte +21 -0
- package/dist/geoms/GeomHex.svelte.d.ts +7 -0
- package/dist/geoms/GeomHistogram.svelte +25 -0
- package/dist/geoms/GeomHistogram.svelte.d.ts +7 -0
- package/dist/geoms/GeomHline.svelte +12 -0
- package/dist/geoms/GeomHline.svelte.d.ts +7 -0
- package/dist/geoms/GeomJitter.svelte +35 -0
- package/dist/geoms/GeomJitter.svelte.d.ts +13 -0
- package/dist/geoms/GeomLabel.svelte +12 -0
- package/dist/geoms/GeomLabel.svelte.d.ts +7 -0
- package/dist/geoms/GeomLine.svelte +12 -0
- package/dist/geoms/GeomLine.svelte.d.ts +7 -0
- package/dist/geoms/GeomLinerange.svelte +25 -0
- package/dist/geoms/GeomLinerange.svelte.d.ts +7 -0
- package/dist/geoms/GeomMap.svelte +21 -0
- package/dist/geoms/GeomMap.svelte.d.ts +7 -0
- package/dist/geoms/GeomPath.svelte +12 -0
- package/dist/geoms/GeomPath.svelte.d.ts +7 -0
- package/dist/geoms/GeomPoint.svelte +12 -0
- package/dist/geoms/GeomPoint.svelte.d.ts +7 -0
- package/dist/geoms/GeomPointrange.svelte +25 -0
- package/dist/geoms/GeomPointrange.svelte.d.ts +7 -0
- package/dist/geoms/GeomPolygon.svelte +25 -0
- package/dist/geoms/GeomPolygon.svelte.d.ts +7 -0
- package/dist/geoms/GeomQq.svelte +21 -0
- package/dist/geoms/GeomQq.svelte.d.ts +7 -0
- package/dist/geoms/GeomQqLine.svelte +25 -0
- package/dist/geoms/GeomQqLine.svelte.d.ts +7 -0
- package/dist/geoms/GeomQuantile.svelte +25 -0
- package/dist/geoms/GeomQuantile.svelte.d.ts +7 -0
- package/dist/geoms/GeomRaster.svelte +25 -0
- package/dist/geoms/GeomRaster.svelte.d.ts +7 -0
- package/dist/geoms/GeomRect.svelte +12 -0
- package/dist/geoms/GeomRect.svelte.d.ts +7 -0
- package/dist/geoms/GeomRibbon.svelte +16 -0
- package/dist/geoms/GeomRibbon.svelte.d.ts +7 -0
- package/dist/geoms/GeomRug.svelte +21 -0
- package/dist/geoms/GeomRug.svelte.d.ts +7 -0
- package/dist/geoms/GeomRule.svelte +12 -0
- package/dist/geoms/GeomRule.svelte.d.ts +7 -0
- package/dist/geoms/GeomSegment.svelte +16 -0
- package/dist/geoms/GeomSegment.svelte.d.ts +7 -0
- package/dist/geoms/GeomSf.svelte +21 -0
- package/dist/geoms/GeomSf.svelte.d.ts +7 -0
- package/dist/geoms/GeomSfLabel.svelte +25 -0
- package/dist/geoms/GeomSfLabel.svelte.d.ts +7 -0
- package/dist/geoms/GeomSfText.svelte +25 -0
- package/dist/geoms/GeomSfText.svelte.d.ts +7 -0
- package/dist/geoms/GeomSmooth.svelte +25 -0
- package/dist/geoms/GeomSmooth.svelte.d.ts +7 -0
- package/dist/geoms/GeomSpoke.svelte +21 -0
- package/dist/geoms/GeomSpoke.svelte.d.ts +7 -0
- package/dist/geoms/GeomStep.svelte +12 -0
- package/dist/geoms/GeomStep.svelte.d.ts +7 -0
- package/dist/geoms/GeomText.svelte +12 -0
- package/dist/geoms/GeomText.svelte.d.ts +7 -0
- package/dist/geoms/GeomTile.svelte +21 -0
- package/dist/geoms/GeomTile.svelte.d.ts +7 -0
- package/dist/geoms/GeomViolin.svelte +25 -0
- package/dist/geoms/GeomViolin.svelte.d.ts +7 -0
- package/dist/geoms/GeomVline.svelte +12 -0
- package/dist/geoms/GeomVline.svelte.d.ts +7 -0
- package/dist/geoms/factory.svelte.d.ts +41 -0
- package/dist/geoms/factory.svelte.js +60 -0
- package/dist/geoms/registry.svelte.d.ts +71 -0
- package/dist/geoms/registry.svelte.js +177 -0
- package/dist/guides/GuideAxis.svelte +20 -0
- package/dist/guides/GuideAxis.svelte.d.ts +14 -0
- package/dist/guides/GuideColorbar.svelte +22 -0
- package/dist/guides/GuideColorbar.svelte.d.ts +13 -0
- package/dist/guides/GuideColorsteps.svelte +22 -0
- package/dist/guides/GuideColorsteps.svelte.d.ts +13 -0
- package/dist/guides/GuideLegend.svelte +90 -0
- package/dist/guides/GuideLegend.svelte.d.ts +37 -0
- package/dist/guides/GuideNone.svelte +19 -0
- package/dist/guides/GuideNone.svelte.d.ts +7 -0
- package/dist/guides/Guides.svelte +14 -0
- package/dist/guides/Guides.svelte.d.ts +13 -0
- package/dist/guides/factory.svelte.d.ts +36 -0
- package/dist/guides/factory.svelte.js +15 -0
- package/dist/index.d.ts +418 -0
- package/dist/index.js +376 -0
- package/dist/inspection/Inspect.svelte +71 -0
- package/dist/inspection/Inspect.svelte.d.ts +36 -0
- package/dist/inspection/Tooltip.svelte +439 -0
- package/dist/inspection/Tooltip.svelte.d.ts +32 -0
- package/dist/inspection/apply.d.ts +120 -0
- package/dist/inspection/apply.js +99 -0
- package/dist/inspection/coordinator.d.ts +51 -0
- package/dist/inspection/coordinator.js +354 -0
- package/dist/inspection/display-members.d.ts +1 -0
- package/dist/inspection/display-members.js +2 -0
- package/dist/inspection/frame.d.ts +90 -0
- package/dist/inspection/frame.js +76 -0
- package/dist/inspection/group-total.d.ts +1 -0
- package/dist/inspection/group-total.js +2 -0
- package/dist/inspection/inspect-guide-axes.d.ts +10 -0
- package/dist/inspection/inspect-guide-axes.js +24 -0
- package/dist/inspection/inspection-reconcile.svelte.d.ts +37 -0
- package/dist/inspection/inspection-reconcile.svelte.js +33 -0
- package/dist/inspection/inspection-state.svelte.d.ts +86 -0
- package/dist/inspection/inspection-state.svelte.js +347 -0
- package/dist/inspection/inspection-traversal.svelte.d.ts +29 -0
- package/dist/inspection/inspection-traversal.svelte.js +52 -0
- package/dist/inspection/pointer-inspect.d.ts +74 -0
- package/dist/inspection/pointer-inspect.js +158 -0
- package/dist/inspection/resolver.d.ts +3 -0
- package/dist/inspection/resolver.js +4 -0
- package/dist/inspection/teardown.d.ts +199 -0
- package/dist/inspection/teardown.js +181 -0
- package/dist/inspection/tooltip-chrome.d.ts +19 -0
- package/dist/inspection/tooltip-chrome.js +17 -0
- package/dist/inspection/tooltip-motion.d.ts +25 -0
- package/dist/inspection/tooltip-motion.js +32 -0
- package/dist/inspection/tooltip-presence.svelte.d.ts +49 -0
- package/dist/inspection/tooltip-presence.svelte.js +110 -0
- package/dist/inspection/tooltip-total.d.ts +1 -0
- package/dist/inspection/tooltip-total.js +2 -0
- package/dist/interaction/capability-resolution.svelte.d.ts +42 -0
- package/dist/interaction/capability-resolution.svelte.js +40 -0
- package/dist/interaction/capability.d.ts +129 -0
- package/dist/interaction/capability.js +134 -0
- package/dist/interaction/controller.svelte.d.ts +4 -0
- package/dist/interaction/controller.svelte.js +43 -0
- package/dist/interaction/inspect-geom-advisories.d.ts +10 -0
- package/dist/interaction/inspect-geom-advisories.js +10 -0
- package/dist/interaction/interaction-context.svelte.d.ts +57 -0
- package/dist/interaction/interaction-context.svelte.js +4 -0
- package/dist/interaction/interaction-diagnostics.d.ts +11 -0
- package/dist/interaction/interaction-diagnostics.js +173 -0
- package/dist/interaction/interaction-states.svelte.d.ts +84 -0
- package/dist/interaction/interaction-states.svelte.js +55 -0
- package/dist/interaction/interaction.d.ts +304 -0
- package/dist/interaction/interaction.js +7 -0
- package/dist/interaction/normalize-interaction-config.d.ts +9 -0
- package/dist/interaction/normalize-interaction-config.js +112 -0
- package/dist/interaction/reducer.d.ts +97 -0
- package/dist/interaction/reducer.js +117 -0
- package/dist/interaction/resolve-inspect-capability.d.ts +40 -0
- package/dist/interaction/resolve-inspect-capability.js +50 -0
- package/dist/interaction/scoped-store.svelte.d.ts +73 -0
- package/dist/interaction/scoped-store.svelte.js +93 -0
- package/dist/interaction/target.d.ts +91 -0
- package/dist/interaction/target.js +68 -0
- package/dist/interaction/transition-owner.d.ts +19 -0
- package/dist/interaction/transition-owner.js +10 -0
- package/dist/interaction/wiring-advisories.d.ts +33 -0
- package/dist/interaction/wiring-advisories.js +46 -0
- package/dist/interval/BoundsEditor.svelte +332 -0
- package/dist/interval/BoundsEditor.svelte.d.ts +10 -0
- package/dist/interval/bounds-editor.d.ts +1 -0
- package/dist/interval/bounds-editor.js +2 -0
- package/dist/interval/consumption.d.ts +1 -0
- package/dist/interval/consumption.js +2 -0
- package/dist/interval/interval-bounds-state.svelte.d.ts +53 -0
- package/dist/interval/interval-bounds-state.svelte.js +117 -0
- package/dist/interval/interval-state-helpers.d.ts +10 -0
- package/dist/interval/interval-state-helpers.js +34 -0
- package/dist/interval/interval-state.svelte.d.ts +60 -0
- package/dist/interval/interval-state.svelte.js +360 -0
- package/dist/interval/interval.d.ts +1 -0
- package/dist/interval/interval.js +2 -0
- package/dist/interval/precise-bounds.d.ts +1 -0
- package/dist/interval/precise-bounds.js +2 -0
- package/dist/interval/query.d.ts +1 -0
- package/dist/interval/query.js +2 -0
- package/dist/labs/Labs.svelte +29 -0
- package/dist/labs/Labs.svelte.d.ts +16 -0
- package/dist/layers/fold.d.ts +2 -0
- package/dist/layers/fold.js +1 -0
- package/dist/layers/grammar-families.d.ts +2 -0
- package/dist/layers/grammar-families.js +1 -0
- package/dist/layers/plot-layer-contract.d.ts +1 -0
- package/dist/layers/plot-layer-contract.js +29 -0
- package/dist/layers/plot-layer.svelte.d.ts +42 -0
- package/dist/layers/plot-layer.svelte.js +34 -0
- package/dist/layers/types.d.ts +2 -0
- package/dist/layers/types.js +1 -0
- package/dist/legend/Legend.svelte +24 -0
- package/dist/legend/Legend.svelte.d.ts +5 -0
- package/dist/legend/LegendFilters.svelte +196 -0
- package/dist/legend/LegendFilters.svelte.d.ts +8 -0
- package/dist/legend/LegendTargets.svelte +393 -0
- package/dist/legend/LegendTargets.svelte.d.ts +31 -0
- package/dist/legend/entry-key-index.d.ts +1 -0
- package/dist/legend/entry-key-index.js +2 -0
- package/dist/legend/entry-key-index.svelte.d.ts +34 -0
- package/dist/legend/entry-key-index.svelte.js +35 -0
- package/dist/legend/filter-state.svelte.d.ts +66 -0
- package/dist/legend/filter-state.svelte.js +284 -0
- package/dist/legend/filter.d.ts +1 -0
- package/dist/legend/filter.js +2 -0
- package/dist/legend/focus-emphasis.d.ts +72 -0
- package/dist/legend/focus-emphasis.js +91 -0
- package/dist/legend/focus-plans.d.ts +89 -0
- package/dist/legend/focus-plans.js +72 -0
- package/dist/legend/focus-reconcile.svelte.d.ts +53 -0
- package/dist/legend/focus-reconcile.svelte.js +113 -0
- package/dist/legend/focus-state.svelte.d.ts +73 -0
- package/dist/legend/focus-state.svelte.js +338 -0
- package/dist/legend/focus.d.ts +1 -0
- package/dist/legend/focus.js +2 -0
- package/dist/legend/resolve-legend-capability.d.ts +52 -0
- package/dist/legend/resolve-legend-capability.js +68 -0
- package/dist/legend/resolve-legend-filter.d.ts +65 -0
- package/dist/legend/resolve-legend-filter.js +54 -0
- package/dist/legend/resolve-legend-focus.d.ts +58 -0
- package/dist/legend/resolve-legend-focus.js +36 -0
- package/dist/legend/surface.d.ts +190 -0
- package/dist/legend/surface.js +158 -0
- package/dist/plot-engine-deriveds.svelte.d.ts +75 -0
- package/dist/plot-engine-deriveds.svelte.js +166 -0
- package/dist/plot-engine.svelte.d.ts +116 -0
- package/dist/plot-engine.svelte.js +316 -0
- package/dist/plot-props.d.ts +144 -0
- package/dist/plot-props.js +81 -0
- package/dist/runtime/announcer.svelte.d.ts +17 -0
- package/dist/runtime/announcer.svelte.js +28 -0
- package/dist/runtime/paint.d.ts +38 -0
- package/dist/runtime/paint.js +45 -0
- package/dist/runtime/resolve-datum-key.d.ts +53 -0
- package/dist/runtime/resolve-datum-key.js +73 -0
- package/dist/runtime/runtime.svelte.d.ts +37 -0
- package/dist/runtime/runtime.svelte.js +233 -0
- package/dist/runtime/semantic-candidate-projection.svelte.d.ts +29 -0
- package/dist/runtime/semantic-candidate-projection.svelte.js +137 -0
- package/dist/runtime/semantic-data-identity.d.ts +64 -0
- package/dist/runtime/semantic-data-identity.js +153 -0
- package/dist/runtime/semantic-keys-projection.d.ts +22 -0
- package/dist/runtime/semantic-keys-projection.js +40 -0
- package/dist/runtime/semantic-keys-resolve.d.ts +69 -0
- package/dist/runtime/semantic-keys-resolve.js +122 -0
- package/dist/runtime/semantic-keys.svelte.d.ts +30 -0
- package/dist/runtime/semantic-keys.svelte.js +69 -0
- package/dist/runtime/semantic-source-identity.d.ts +9 -0
- package/dist/runtime/semantic-source-identity.js +16 -0
- package/dist/scale/Scale.svelte +26 -0
- package/dist/scale/Scale.svelte.d.ts +21 -0
- package/dist/scale/ScaleAlphaBinned.svelte +14 -0
- package/dist/scale/ScaleAlphaBinned.svelte.d.ts +4 -0
- package/dist/scale/ScaleAlphaContinuous.svelte +14 -0
- package/dist/scale/ScaleAlphaContinuous.svelte.d.ts +4 -0
- package/dist/scale/ScaleAlphaDate.svelte +15 -0
- package/dist/scale/ScaleAlphaDate.svelte.d.ts +5 -0
- package/dist/scale/ScaleAlphaDatetime.svelte +15 -0
- package/dist/scale/ScaleAlphaDatetime.svelte.d.ts +5 -0
- package/dist/scale/ScaleAlphaDiscrete.svelte +14 -0
- package/dist/scale/ScaleAlphaDiscrete.svelte.d.ts +4 -0
- package/dist/scale/ScaleAlphaIdentity.svelte +14 -0
- package/dist/scale/ScaleAlphaIdentity.svelte.d.ts +4 -0
- package/dist/scale/ScaleAlphaManual.svelte +14 -0
- package/dist/scale/ScaleAlphaManual.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorBinned.svelte +14 -0
- package/dist/scale/ScaleColorBinned.svelte.d.ts +3 -0
- package/dist/scale/ScaleColorBrewer.svelte +14 -0
- package/dist/scale/ScaleColorBrewer.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorContinuous.svelte +14 -0
- package/dist/scale/ScaleColorContinuous.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorDate.svelte +15 -0
- package/dist/scale/ScaleColorDate.svelte.d.ts +5 -0
- package/dist/scale/ScaleColorDatetime.svelte +15 -0
- package/dist/scale/ScaleColorDatetime.svelte.d.ts +5 -0
- package/dist/scale/ScaleColorDiscrete.svelte +14 -0
- package/dist/scale/ScaleColorDiscrete.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorDistiller.svelte +14 -0
- package/dist/scale/ScaleColorDistiller.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorFermenter.svelte +14 -0
- package/dist/scale/ScaleColorFermenter.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorGradient.svelte +11 -0
- package/dist/scale/ScaleColorGradient.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorGradient2.svelte +14 -0
- package/dist/scale/ScaleColorGradient2.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorGradientn.svelte +14 -0
- package/dist/scale/ScaleColorGradientn.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorGrey.svelte +11 -0
- package/dist/scale/ScaleColorGrey.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorHue.svelte +11 -0
- package/dist/scale/ScaleColorHue.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorIdentity.svelte +14 -0
- package/dist/scale/ScaleColorIdentity.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorLog10.svelte +14 -0
- package/dist/scale/ScaleColorLog10.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorManual.svelte +14 -0
- package/dist/scale/ScaleColorManual.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorOrdinal.svelte +14 -0
- package/dist/scale/ScaleColorOrdinal.svelte.d.ts +3 -0
- package/dist/scale/ScaleColorSqrt.svelte +14 -0
- package/dist/scale/ScaleColorSqrt.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorSteps.svelte +11 -0
- package/dist/scale/ScaleColorSteps.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorSteps2.svelte +11 -0
- package/dist/scale/ScaleColorSteps2.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorStepsn.svelte +11 -0
- package/dist/scale/ScaleColorStepsn.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorViridisB.svelte +11 -0
- package/dist/scale/ScaleColorViridisB.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorViridisC.svelte +11 -0
- package/dist/scale/ScaleColorViridisC.svelte.d.ts +4 -0
- package/dist/scale/ScaleColorViridisD.svelte +11 -0
- package/dist/scale/ScaleColorViridisD.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillBinned.svelte +11 -0
- package/dist/scale/ScaleFillBinned.svelte.d.ts +3 -0
- package/dist/scale/ScaleFillBrewer.svelte +11 -0
- package/dist/scale/ScaleFillBrewer.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillContinuous.svelte +14 -0
- package/dist/scale/ScaleFillContinuous.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillDate.svelte +12 -0
- package/dist/scale/ScaleFillDate.svelte.d.ts +5 -0
- package/dist/scale/ScaleFillDatetime.svelte +15 -0
- package/dist/scale/ScaleFillDatetime.svelte.d.ts +5 -0
- package/dist/scale/ScaleFillDiscrete.svelte +14 -0
- package/dist/scale/ScaleFillDiscrete.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillDistiller.svelte +14 -0
- package/dist/scale/ScaleFillDistiller.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillFermenter.svelte +14 -0
- package/dist/scale/ScaleFillFermenter.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillGradient.svelte +11 -0
- package/dist/scale/ScaleFillGradient.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillGradient2.svelte +14 -0
- package/dist/scale/ScaleFillGradient2.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillGradientn.svelte +14 -0
- package/dist/scale/ScaleFillGradientn.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillGrey.svelte +11 -0
- package/dist/scale/ScaleFillGrey.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillHue.svelte +11 -0
- package/dist/scale/ScaleFillHue.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillIdentity.svelte +14 -0
- package/dist/scale/ScaleFillIdentity.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillLog10.svelte +14 -0
- package/dist/scale/ScaleFillLog10.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillManual.svelte +11 -0
- package/dist/scale/ScaleFillManual.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillOrdinal.svelte +14 -0
- package/dist/scale/ScaleFillOrdinal.svelte.d.ts +3 -0
- package/dist/scale/ScaleFillSqrt.svelte +14 -0
- package/dist/scale/ScaleFillSqrt.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillSteps.svelte +11 -0
- package/dist/scale/ScaleFillSteps.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillSteps2.svelte +11 -0
- package/dist/scale/ScaleFillSteps2.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillStepsn.svelte +11 -0
- package/dist/scale/ScaleFillStepsn.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillViridisB.svelte +11 -0
- package/dist/scale/ScaleFillViridisB.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillViridisC.svelte +11 -0
- package/dist/scale/ScaleFillViridisC.svelte.d.ts +4 -0
- package/dist/scale/ScaleFillViridisD.svelte +11 -0
- package/dist/scale/ScaleFillViridisD.svelte.d.ts +4 -0
- package/dist/scale/ScaleLinetypeBinned.svelte +15 -0
- package/dist/scale/ScaleLinetypeBinned.svelte.d.ts +4 -0
- package/dist/scale/ScaleLinetypeDiscrete.svelte +15 -0
- package/dist/scale/ScaleLinetypeDiscrete.svelte.d.ts +4 -0
- package/dist/scale/ScaleLinetypeIdentity.svelte +15 -0
- package/dist/scale/ScaleLinetypeIdentity.svelte.d.ts +4 -0
- package/dist/scale/ScaleLinetypeManual.svelte +15 -0
- package/dist/scale/ScaleLinetypeManual.svelte.d.ts +4 -0
- package/dist/scale/ScaleLinewidthBinned.svelte +14 -0
- package/dist/scale/ScaleLinewidthBinned.svelte.d.ts +4 -0
- package/dist/scale/ScaleLinewidthContinuous.svelte +14 -0
- package/dist/scale/ScaleLinewidthContinuous.svelte.d.ts +4 -0
- package/dist/scale/ScaleLinewidthDate.svelte +15 -0
- package/dist/scale/ScaleLinewidthDate.svelte.d.ts +5 -0
- package/dist/scale/ScaleLinewidthDatetime.svelte +15 -0
- package/dist/scale/ScaleLinewidthDatetime.svelte.d.ts +5 -0
- package/dist/scale/ScaleLinewidthDiscrete.svelte +14 -0
- package/dist/scale/ScaleLinewidthDiscrete.svelte.d.ts +4 -0
- package/dist/scale/ScaleLinewidthIdentity.svelte +14 -0
- package/dist/scale/ScaleLinewidthIdentity.svelte.d.ts +4 -0
- package/dist/scale/ScaleLinewidthManual.svelte +14 -0
- package/dist/scale/ScaleLinewidthManual.svelte.d.ts +4 -0
- package/dist/scale/ScaleRadius.svelte +11 -0
- package/dist/scale/ScaleRadius.svelte.d.ts +4 -0
- package/dist/scale/ScaleShapeBinned.svelte +15 -0
- package/dist/scale/ScaleShapeBinned.svelte.d.ts +4 -0
- package/dist/scale/ScaleShapeDiscrete.svelte +15 -0
- package/dist/scale/ScaleShapeDiscrete.svelte.d.ts +4 -0
- package/dist/scale/ScaleShapeIdentity.svelte +15 -0
- package/dist/scale/ScaleShapeIdentity.svelte.d.ts +4 -0
- package/dist/scale/ScaleShapeManual.svelte +15 -0
- package/dist/scale/ScaleShapeManual.svelte.d.ts +4 -0
- package/dist/scale/ScaleSizeArea.svelte +11 -0
- package/dist/scale/ScaleSizeArea.svelte.d.ts +4 -0
- package/dist/scale/ScaleSizeBinned.svelte +14 -0
- package/dist/scale/ScaleSizeBinned.svelte.d.ts +4 -0
- package/dist/scale/ScaleSizeBinnedArea.svelte +14 -0
- package/dist/scale/ScaleSizeBinnedArea.svelte.d.ts +4 -0
- package/dist/scale/ScaleSizeContinuous.svelte +14 -0
- package/dist/scale/ScaleSizeContinuous.svelte.d.ts +4 -0
- package/dist/scale/ScaleSizeDate.svelte +15 -0
- package/dist/scale/ScaleSizeDate.svelte.d.ts +5 -0
- package/dist/scale/ScaleSizeDatetime.svelte +15 -0
- package/dist/scale/ScaleSizeDatetime.svelte.d.ts +5 -0
- package/dist/scale/ScaleSizeDiscrete.svelte +14 -0
- package/dist/scale/ScaleSizeDiscrete.svelte.d.ts +4 -0
- package/dist/scale/ScaleSizeIdentity.svelte +14 -0
- package/dist/scale/ScaleSizeIdentity.svelte.d.ts +4 -0
- package/dist/scale/ScaleSizeManual.svelte +14 -0
- package/dist/scale/ScaleSizeManual.svelte.d.ts +4 -0
- package/dist/scale/ScaleXBinned.svelte +14 -0
- package/dist/scale/ScaleXBinned.svelte.d.ts +4 -0
- package/dist/scale/ScaleXContinuous.svelte +14 -0
- package/dist/scale/ScaleXContinuous.svelte.d.ts +4 -0
- package/dist/scale/ScaleXDate.svelte +12 -0
- package/dist/scale/ScaleXDate.svelte.d.ts +5 -0
- package/dist/scale/ScaleXDatetime.svelte +12 -0
- package/dist/scale/ScaleXDatetime.svelte.d.ts +5 -0
- package/dist/scale/ScaleXDiscrete.svelte +14 -0
- package/dist/scale/ScaleXDiscrete.svelte.d.ts +4 -0
- package/dist/scale/ScaleXLog10.svelte +14 -0
- package/dist/scale/ScaleXLog10.svelte.d.ts +4 -0
- package/dist/scale/ScaleXMonthDay.svelte +12 -0
- package/dist/scale/ScaleXMonthDay.svelte.d.ts +5 -0
- package/dist/scale/ScaleXReverse.svelte +15 -0
- package/dist/scale/ScaleXReverse.svelte.d.ts +4 -0
- package/dist/scale/ScaleXSqrt.svelte +14 -0
- package/dist/scale/ScaleXSqrt.svelte.d.ts +4 -0
- package/dist/scale/ScaleXTime.svelte +12 -0
- package/dist/scale/ScaleXTime.svelte.d.ts +5 -0
- package/dist/scale/ScaleYBinned.svelte +14 -0
- package/dist/scale/ScaleYBinned.svelte.d.ts +4 -0
- package/dist/scale/ScaleYContinuous.svelte +14 -0
- package/dist/scale/ScaleYContinuous.svelte.d.ts +4 -0
- package/dist/scale/ScaleYDate.svelte +12 -0
- package/dist/scale/ScaleYDate.svelte.d.ts +5 -0
- package/dist/scale/ScaleYDatetime.svelte +12 -0
- package/dist/scale/ScaleYDatetime.svelte.d.ts +5 -0
- package/dist/scale/ScaleYDiscrete.svelte +14 -0
- package/dist/scale/ScaleYDiscrete.svelte.d.ts +4 -0
- package/dist/scale/ScaleYLog10.svelte +14 -0
- package/dist/scale/ScaleYLog10.svelte.d.ts +4 -0
- package/dist/scale/ScaleYMonthDay.svelte +12 -0
- package/dist/scale/ScaleYMonthDay.svelte.d.ts +5 -0
- package/dist/scale/ScaleYReverse.svelte +15 -0
- package/dist/scale/ScaleYReverse.svelte.d.ts +4 -0
- package/dist/scale/ScaleYSqrt.svelte +14 -0
- package/dist/scale/ScaleYSqrt.svelte.d.ts +4 -0
- package/dist/scale/ScaleYTime.svelte +12 -0
- package/dist/scale/ScaleYTime.svelte.d.ts +5 -0
- package/dist/scene/Axis.svelte +159 -0
- package/dist/scene/Axis.svelte.d.ts +12 -0
- package/dist/scene/Batch.svelte +252 -0
- package/dist/scene/Batch.svelte.d.ts +23 -0
- package/dist/scene/InteractionOverlay.svelte +402 -0
- package/dist/scene/InteractionOverlay.svelte.d.ts +44 -0
- package/dist/scene/Legend.svelte +278 -0
- package/dist/scene/Legend.svelte.d.ts +8 -0
- package/dist/scene/MarkStrata.svelte +129 -0
- package/dist/scene/MarkStrata.svelte.d.ts +15 -0
- package/dist/scene/SceneOverlays.svelte +118 -0
- package/dist/scene/SceneOverlays.svelte.d.ts +49 -0
- package/dist/scene/SceneView.svelte +478 -0
- package/dist/scene/SceneView.svelte.d.ts +32 -0
- package/dist/scene/batch-presentation.svelte.d.ts +111 -0
- package/dist/scene/batch-presentation.svelte.js +207 -0
- package/dist/scene/geometry.d.ts +2 -0
- package/dist/scene/geometry.js +3 -0
- package/dist/scene/stratum-paint.d.ts +25 -0
- package/dist/scene/stratum-paint.js +40 -0
- package/dist/selection/selection-state.svelte.d.ts +23 -0
- package/dist/selection/selection-state.svelte.js +73 -0
- package/dist/selection/selection.d.ts +1 -0
- package/dist/selection/selection.js +2 -0
- package/dist/surface/CaptureSurface.svelte +109 -0
- package/dist/surface/CaptureSurface.svelte.d.ts +27 -0
- package/dist/surface/area-brush.d.ts +48 -0
- package/dist/surface/area-brush.js +44 -0
- package/dist/surface/brush-finish.d.ts +49 -0
- package/dist/surface/brush-finish.js +44 -0
- package/dist/surface/keyboard.d.ts +97 -0
- package/dist/surface/keyboard.js +105 -0
- package/dist/surface/pointer.d.ts +241 -0
- package/dist/surface/pointer.js +179 -0
- package/dist/surface/surface-description.d.ts +10 -0
- package/dist/surface/surface-description.js +11 -0
- package/dist/surface/surface-handlers.svelte.d.ts +53 -0
- package/dist/surface/surface-handlers.svelte.js +418 -0
- package/dist/surface/surface-state.svelte.d.ts +90 -0
- package/dist/surface/surface-state.svelte.js +161 -0
- package/dist/theme/Theme.svelte +27 -0
- package/dist/theme/Theme.svelte.d.ts +23 -0
- package/dist/theme/ThemeBase.svelte +13 -0
- package/dist/theme/ThemeBase.svelte.d.ts +8 -0
- package/dist/theme/ThemeBw.svelte +13 -0
- package/dist/theme/ThemeBw.svelte.d.ts +8 -0
- package/dist/theme/ThemeClassic.svelte +13 -0
- package/dist/theme/ThemeClassic.svelte.d.ts +8 -0
- package/dist/theme/ThemeClean.svelte +13 -0
- package/dist/theme/ThemeClean.svelte.d.ts +8 -0
- package/dist/theme/ThemeDark.svelte +13 -0
- package/dist/theme/ThemeDark.svelte.d.ts +8 -0
- package/dist/theme/ThemeDefault.svelte +13 -0
- package/dist/theme/ThemeDefault.svelte.d.ts +8 -0
- package/dist/theme/ThemeEconomist.svelte +13 -0
- package/dist/theme/ThemeEconomist.svelte.d.ts +8 -0
- package/dist/theme/ThemeEconomistwhite.svelte +13 -0
- package/dist/theme/ThemeEconomistwhite.svelte.d.ts +8 -0
- package/dist/theme/ThemeFew.svelte +13 -0
- package/dist/theme/ThemeFew.svelte.d.ts +8 -0
- package/dist/theme/ThemeFivethirtyeight.svelte +14 -0
- package/dist/theme/ThemeFivethirtyeight.svelte.d.ts +9 -0
- package/dist/theme/ThemeGgplot2.svelte +13 -0
- package/dist/theme/ThemeGgplot2.svelte.d.ts +8 -0
- package/dist/theme/ThemeGray.svelte +13 -0
- package/dist/theme/ThemeGray.svelte.d.ts +8 -0
- package/dist/theme/ThemeGrey.svelte +13 -0
- package/dist/theme/ThemeGrey.svelte.d.ts +8 -0
- package/dist/theme/ThemeHc.svelte +13 -0
- package/dist/theme/ThemeHc.svelte.d.ts +8 -0
- package/dist/theme/ThemeHcdark.svelte +13 -0
- package/dist/theme/ThemeHcdark.svelte.d.ts +8 -0
- package/dist/theme/ThemeHrbr.svelte +13 -0
- package/dist/theme/ThemeHrbr.svelte.d.ts +8 -0
- package/dist/theme/ThemeIgray.svelte +13 -0
- package/dist/theme/ThemeIgray.svelte.d.ts +8 -0
- package/dist/theme/ThemeLight.svelte +13 -0
- package/dist/theme/ThemeLight.svelte.d.ts +8 -0
- package/dist/theme/ThemeLinedraw.svelte +13 -0
- package/dist/theme/ThemeLinedraw.svelte.d.ts +8 -0
- package/dist/theme/ThemeMap.svelte +13 -0
- package/dist/theme/ThemeMap.svelte.d.ts +8 -0
- package/dist/theme/ThemeMinimal.svelte +13 -0
- package/dist/theme/ThemeMinimal.svelte.d.ts +8 -0
- package/dist/theme/ThemePander.svelte +13 -0
- package/dist/theme/ThemePander.svelte.d.ts +8 -0
- package/dist/theme/ThemeSolarized.svelte +13 -0
- package/dist/theme/ThemeSolarized.svelte.d.ts +8 -0
- package/dist/theme/ThemeSolarized2.svelte +13 -0
- package/dist/theme/ThemeSolarized2.svelte.d.ts +8 -0
- package/dist/theme/ThemeSolarized2dark.svelte +13 -0
- package/dist/theme/ThemeSolarized2dark.svelte.d.ts +8 -0
- package/dist/theme/ThemeSolarizeddark.svelte +14 -0
- package/dist/theme/ThemeSolarizeddark.svelte.d.ts +9 -0
- package/dist/theme/ThemeSolid.svelte +13 -0
- package/dist/theme/ThemeSolid.svelte.d.ts +8 -0
- package/dist/theme/ThemeStata.svelte +13 -0
- package/dist/theme/ThemeStata.svelte.d.ts +8 -0
- package/dist/theme/ThemeStatas1color.svelte +13 -0
- package/dist/theme/ThemeStatas1color.svelte.d.ts +8 -0
- package/dist/theme/ThemeTest.svelte +14 -0
- package/dist/theme/ThemeTest.svelte.d.ts +9 -0
- package/dist/theme/ThemeTufte.svelte +13 -0
- package/dist/theme/ThemeTufte.svelte.d.ts +8 -0
- package/dist/theme/ThemeVoid.svelte +14 -0
- package/dist/theme/ThemeVoid.svelte.d.ts +9 -0
- package/dist/theme/ThemeWsj.svelte +13 -0
- package/dist/theme/ThemeWsj.svelte.d.ts +8 -0
- package/dist/theme/factory.svelte.d.ts +36 -0
- package/dist/theme/factory.svelte.js +100 -0
- package/dist/zoom/zoom-state.svelte.d.ts +44 -0
- package/dist/zoom/zoom-state.svelte.js +121 -0
- package/dist/zoom/zoom.d.ts +1 -0
- package/dist/zoom/zoom.js +2 -0
- package/package.json +83 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { encodeKey } from "@ggts-sh/core";
|
|
2
|
+
import { isLegendValueKeyVisible, isLegendValueVisible, legendFilterValueKeys, nextLegendFilterValues, reconcileLegendFilterValues, } from "./filter.js";
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Public types
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
const FILTERABLE_LEGEND_SCALES = [
|
|
7
|
+
"color",
|
|
8
|
+
"fill",
|
|
9
|
+
"size",
|
|
10
|
+
"linewidth",
|
|
11
|
+
"alpha",
|
|
12
|
+
"shape",
|
|
13
|
+
"linetype",
|
|
14
|
+
];
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Factory
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/**
|
|
19
|
+
* Create the legend-filter controller. Construction registers capability-reset,
|
|
20
|
+
* mode-reset, and catalog-reconcile effects (#627).
|
|
21
|
+
*/
|
|
22
|
+
export function createLegendFilterState(deps) {
|
|
23
|
+
const legendFilterOptions = $derived.by(() => {
|
|
24
|
+
const legendFilter = deps.legendFilterProp();
|
|
25
|
+
if (legendFilter === false)
|
|
26
|
+
return null;
|
|
27
|
+
return {
|
|
28
|
+
mode: typeof legendFilter === "object" ? (legendFilter.mode ?? "exclude") : "exclude",
|
|
29
|
+
multiple: typeof legendFilter === "object" ? (legendFilter.multiple ?? true) : true,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
let localLegendFilters = $state([]);
|
|
33
|
+
let appliedLegendFilterMode = $state(null);
|
|
34
|
+
const legendCatalogFingerprints = new Map();
|
|
35
|
+
const activeLegendFilterBindings = $derived.by(() => {
|
|
36
|
+
const bindings = new Set();
|
|
37
|
+
const effectiveSpec = deps.effectiveSpec();
|
|
38
|
+
if (effectiveSpec === null)
|
|
39
|
+
return bindings;
|
|
40
|
+
for (const layer of effectiveSpec.layers) {
|
|
41
|
+
for (const scale of FILTERABLE_LEGEND_SCALES) {
|
|
42
|
+
const own = layer.aes?.[scale];
|
|
43
|
+
// Explicit null is an unset (normalize's null-unset semantics): the
|
|
44
|
+
// layer deliberately removed the plot-level binding — never inherit.
|
|
45
|
+
if (own === null)
|
|
46
|
+
continue;
|
|
47
|
+
const channel = own ?? effectiveSpec.aes?.[scale];
|
|
48
|
+
if (channel !== null && channel !== undefined && "field" in channel)
|
|
49
|
+
bindings.add(`${scale}:${channel.field}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return bindings;
|
|
53
|
+
});
|
|
54
|
+
const effectiveLegendFilters = $derived(legendFilterOptions === null
|
|
55
|
+
? []
|
|
56
|
+
: localLegendFilters.filter((clause) => activeLegendFilterBindings.has(`${clause.scale}:${clause.field}`)));
|
|
57
|
+
let legendFilterPointerType = null;
|
|
58
|
+
function emitLegendFilter(event) {
|
|
59
|
+
deps.onlegendfilter()?.(event);
|
|
60
|
+
deps.oninteraction()?.(event);
|
|
61
|
+
}
|
|
62
|
+
// A disabled capability or a remapped spec must never leave an invisible
|
|
63
|
+
// filter active. Reset the chart-local filter set atomically so the public
|
|
64
|
+
// `clear` event always describes the actual resulting state.
|
|
65
|
+
$effect(() => {
|
|
66
|
+
if (effectiveLegendFilters.length === localLegendFilters.length)
|
|
67
|
+
return;
|
|
68
|
+
localLegendFilters = [];
|
|
69
|
+
emitLegendFilter({
|
|
70
|
+
type: "legend-filter",
|
|
71
|
+
phase: "clear",
|
|
72
|
+
source: "programmatic",
|
|
73
|
+
clause: null,
|
|
74
|
+
});
|
|
75
|
+
deps.announce("Legend filters reset after the filter capability changed.");
|
|
76
|
+
});
|
|
77
|
+
// Mode changes are controlled API changes, not reinterpretations of old
|
|
78
|
+
// state. Reset active clauses so an exclude set can never become a stale
|
|
79
|
+
// include set (or vice versa).
|
|
80
|
+
$effect(() => {
|
|
81
|
+
const mode = legendFilterOptions?.mode ?? null;
|
|
82
|
+
if (appliedLegendFilterMode === null) {
|
|
83
|
+
appliedLegendFilterMode = mode;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (mode === appliedLegendFilterMode)
|
|
87
|
+
return;
|
|
88
|
+
appliedLegendFilterMode = mode;
|
|
89
|
+
if (localLegendFilters.length === 0)
|
|
90
|
+
return;
|
|
91
|
+
localLegendFilters = [];
|
|
92
|
+
emitLegendFilter({
|
|
93
|
+
type: "legend-filter",
|
|
94
|
+
phase: "clear",
|
|
95
|
+
source: "programmatic",
|
|
96
|
+
clause: null,
|
|
97
|
+
});
|
|
98
|
+
deps.announce("Legend filters reset after the filter mode changed.");
|
|
99
|
+
});
|
|
100
|
+
function computeEntries(model) {
|
|
101
|
+
if (model === null || legendFilterOptions === null)
|
|
102
|
+
return [];
|
|
103
|
+
return model.scene.legends.flatMap((sceneLegend) => {
|
|
104
|
+
if (sceneLegend.type !== "discrete" || sceneLegend.interactive === false)
|
|
105
|
+
return [];
|
|
106
|
+
if (!FILTERABLE_LEGEND_SCALES.some((scale) => scale === sceneLegend.scale))
|
|
107
|
+
return [];
|
|
108
|
+
const fields = new Set(model.layerFields
|
|
109
|
+
.flat()
|
|
110
|
+
.filter((mapped) => mapped.channel === sceneLegend.scale && mapped.source !== "stat")
|
|
111
|
+
.map((mapped) => mapped.field));
|
|
112
|
+
const field = fields.values().next().value;
|
|
113
|
+
// One combined scale fed by unlike fields has no honest one-toggle
|
|
114
|
+
// filtering semantics. Keep the static legend rather than filtering
|
|
115
|
+
// only whichever field happened to be encountered first.
|
|
116
|
+
if (field === undefined || fields.size !== 1)
|
|
117
|
+
return [];
|
|
118
|
+
// A scaled constant (aes { value, scale: true }) feeds this legend
|
|
119
|
+
// without a field: toggling its entry would filter an unrelated field
|
|
120
|
+
// while the constant-colored layer stays rendered. Keep it static —
|
|
121
|
+
// but only when that constant is actually a *visible* legend entry.
|
|
122
|
+
// Rowless annotation constants train the scale and appear on
|
|
123
|
+
// layerScaledConstants for focus/index, yet are excluded from the
|
|
124
|
+
// interactive legend domain (#598); those must not disable filters.
|
|
125
|
+
const scaledConstantKeys = new Set(model.layerScaledConstants
|
|
126
|
+
.map((constants) => constants[sceneLegend.scale])
|
|
127
|
+
.filter((value) => value !== undefined)
|
|
128
|
+
.map((value) => encodeKey(value)));
|
|
129
|
+
if (scaledConstantKeys.size > 0 &&
|
|
130
|
+
sceneLegend.entries.some((entry) => scaledConstantKeys.has(encodeKey(entry.value))))
|
|
131
|
+
return [];
|
|
132
|
+
const current = localLegendFilters.find((clause) => clause.scale === sceneLegend.scale && clause.field === field);
|
|
133
|
+
if (current === undefined) {
|
|
134
|
+
return sceneLegend.entries.map((entry) => ({
|
|
135
|
+
legend: sceneLegend,
|
|
136
|
+
entry,
|
|
137
|
+
field,
|
|
138
|
+
visible: true,
|
|
139
|
+
}));
|
|
140
|
+
}
|
|
141
|
+
// One Set per clause, then O(1) membership per entry (O(E+V) not O(E×V)).
|
|
142
|
+
const valueKeys = legendFilterValueKeys(current.values);
|
|
143
|
+
const mode = current.mode;
|
|
144
|
+
return sceneLegend.entries.map((entry) => ({
|
|
145
|
+
legend: sceneLegend,
|
|
146
|
+
entry,
|
|
147
|
+
field,
|
|
148
|
+
visible: isLegendValueKeyVisible(valueKeys, entry.value, mode),
|
|
149
|
+
}));
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function legendFilterSource(event) {
|
|
153
|
+
if (event.detail === 0)
|
|
154
|
+
return "keyboard";
|
|
155
|
+
return legendFilterPointerType === "touch" ? "touch" : "pointer";
|
|
156
|
+
}
|
|
157
|
+
function toggle(target, event) {
|
|
158
|
+
if (legendFilterOptions === null)
|
|
159
|
+
return target.visible;
|
|
160
|
+
// Controlled checkbox: cancel the UA toggle when this still runs inside
|
|
161
|
+
// the click event. Delegated/async handlers can miss that window — the
|
|
162
|
+
// host forces input.checked from the returned visibility.
|
|
163
|
+
event.preventDefault();
|
|
164
|
+
const catalog = target.legend.entries.map((entry) => entry.value);
|
|
165
|
+
const index = localLegendFilters.findIndex((clause) => clause.scale === target.legend.scale && clause.field === target.field);
|
|
166
|
+
const current = localLegendFilters[index];
|
|
167
|
+
const baseline = current?.values ?? (legendFilterOptions.mode === "include" ? catalog : []);
|
|
168
|
+
const values = nextLegendFilterValues(baseline, target.entry.value, catalog, legendFilterOptions.mode, legendFilterOptions.multiple);
|
|
169
|
+
const clause = Object.freeze({
|
|
170
|
+
scale: target.legend.scale,
|
|
171
|
+
field: target.field,
|
|
172
|
+
values,
|
|
173
|
+
mode: legendFilterOptions.mode,
|
|
174
|
+
});
|
|
175
|
+
localLegendFilters =
|
|
176
|
+
index < 0
|
|
177
|
+
? [...localLegendFilters, clause]
|
|
178
|
+
: localLegendFilters.map((candidate, candidateIndex) => candidateIndex === index ? clause : candidate);
|
|
179
|
+
const source = legendFilterSource(event);
|
|
180
|
+
legendFilterPointerType = null;
|
|
181
|
+
const visible = isLegendValueVisible(values, target.entry.value, legendFilterOptions.mode);
|
|
182
|
+
const filterEvent = Object.freeze({
|
|
183
|
+
type: "legend-filter",
|
|
184
|
+
phase: "change",
|
|
185
|
+
source,
|
|
186
|
+
clause,
|
|
187
|
+
});
|
|
188
|
+
emitLegendFilter(filterEvent);
|
|
189
|
+
deps.announce(`${target.entry.label} ${visible ? "shown" : "hidden"}.`);
|
|
190
|
+
return visible;
|
|
191
|
+
}
|
|
192
|
+
function reset(event) {
|
|
193
|
+
if (localLegendFilters.length === 0)
|
|
194
|
+
return;
|
|
195
|
+
// Focus restoration is owned by the child component (zero DOM here).
|
|
196
|
+
const source = legendFilterSource(event);
|
|
197
|
+
localLegendFilters = [];
|
|
198
|
+
legendFilterPointerType = null;
|
|
199
|
+
emitLegendFilter(Object.freeze({
|
|
200
|
+
type: "legend-filter",
|
|
201
|
+
phase: "clear",
|
|
202
|
+
source,
|
|
203
|
+
clause: null,
|
|
204
|
+
}));
|
|
205
|
+
}
|
|
206
|
+
function setPointerType(type) {
|
|
207
|
+
legendFilterPointerType = type;
|
|
208
|
+
}
|
|
209
|
+
// Catalog changes prune values that no longer exist. An emptied clause is
|
|
210
|
+
// removed, so a category that disappears and later returns is visible by
|
|
211
|
+
// default. resetScales() deliberately does not alter this filter state.
|
|
212
|
+
$effect(() => {
|
|
213
|
+
const catalogs = new Map();
|
|
214
|
+
for (const target of deps.catalogEntries()) {
|
|
215
|
+
const key = `${target.legend.scale}:${target.field}`;
|
|
216
|
+
const catalog = catalogs.get(key) ?? [];
|
|
217
|
+
catalog.push(target.entry.value);
|
|
218
|
+
catalogs.set(key, catalog);
|
|
219
|
+
}
|
|
220
|
+
let next = localLegendFilters;
|
|
221
|
+
const reconciled = [];
|
|
222
|
+
// A clause whose field is still mapped but whose legend stopped being
|
|
223
|
+
// filterable (second unlike field on the scale, a scaled constant, a
|
|
224
|
+
// non-discrete legend) has no checkbox or reset control left — remove it
|
|
225
|
+
// rather than filtering rows invisibly. Unmapped fields are handled by
|
|
226
|
+
// the capability reset above.
|
|
227
|
+
if (deps.model() !== null && legendFilterOptions !== null) {
|
|
228
|
+
for (const clause of next.filter((candidate) => activeLegendFilterBindings.has(`${candidate.scale}:${candidate.field}`) &&
|
|
229
|
+
!catalogs.has(`${candidate.scale}:${candidate.field}`))) {
|
|
230
|
+
next = next.filter((candidate) => candidate !== clause);
|
|
231
|
+
reconciled.push({ clause, removed: true });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
for (const [key, catalog] of catalogs) {
|
|
235
|
+
const fingerprint = JSON.stringify(catalog.map((value) => encodeKey(value)));
|
|
236
|
+
const priorFingerprint = legendCatalogFingerprints.get(key);
|
|
237
|
+
legendCatalogFingerprints.set(key, fingerprint);
|
|
238
|
+
if (priorFingerprint === undefined || priorFingerprint === fingerprint)
|
|
239
|
+
continue;
|
|
240
|
+
const index = next.findIndex((clause) => `${clause.scale}:${clause.field}` === key);
|
|
241
|
+
if (index < 0)
|
|
242
|
+
continue;
|
|
243
|
+
const clause = next[index];
|
|
244
|
+
const values = reconcileLegendFilterValues(clause.values, catalog);
|
|
245
|
+
reconciled.push({
|
|
246
|
+
clause: Object.freeze({ ...clause, values }),
|
|
247
|
+
removed: values.length === 0,
|
|
248
|
+
});
|
|
249
|
+
next =
|
|
250
|
+
values.length === 0
|
|
251
|
+
? next.filter((_, candidateIndex) => candidateIndex !== index)
|
|
252
|
+
: next.map((candidate, candidateIndex) => candidateIndex === index ? Object.freeze({ ...candidate, values }) : candidate);
|
|
253
|
+
}
|
|
254
|
+
for (const key of legendCatalogFingerprints.keys())
|
|
255
|
+
if (!catalogs.has(key))
|
|
256
|
+
legendCatalogFingerprints.delete(key);
|
|
257
|
+
if (next === localLegendFilters)
|
|
258
|
+
return;
|
|
259
|
+
localLegendFilters = [...next];
|
|
260
|
+
for (const { clause, removed } of reconciled)
|
|
261
|
+
emitLegendFilter({
|
|
262
|
+
type: "legend-filter",
|
|
263
|
+
phase: removed ? "remove" : "change",
|
|
264
|
+
source: "programmatic",
|
|
265
|
+
clause,
|
|
266
|
+
});
|
|
267
|
+
deps.announce("Legend filters reconciled with the available groups.");
|
|
268
|
+
});
|
|
269
|
+
return {
|
|
270
|
+
get options() {
|
|
271
|
+
return legendFilterOptions;
|
|
272
|
+
},
|
|
273
|
+
get filters() {
|
|
274
|
+
return effectiveLegendFilters;
|
|
275
|
+
},
|
|
276
|
+
get hasActiveFilters() {
|
|
277
|
+
return localLegendFilters.length > 0;
|
|
278
|
+
},
|
|
279
|
+
computeEntries,
|
|
280
|
+
toggle,
|
|
281
|
+
reset,
|
|
282
|
+
setPointerType,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { type LegendFilterClause, type LegendFilterOptions, type LegendFilterInput, type LegendFilterEvent, legendFilterValueKeys, isLegendValueKeyVisible, isLegendValueVisible, reconcileLegendFilterValues, nextLegendFilterValues, } from "@ggts-sh/core/interaction";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure legend emphasis helpers: pressed-identity, preview decisions, and
|
|
3
|
+
* effective emphasis key precedence (preview / controller / local).
|
|
4
|
+
*
|
|
5
|
+
* Identity/roving: `focus.ts`. Host `$effect` plans: `focus-plans.ts`.
|
|
6
|
+
*/
|
|
7
|
+
import type { InteractionSource } from "../interaction/interaction.js";
|
|
8
|
+
import { type InteractiveLegendEntry, type LegendEntryIdentity, type LegendInteractionSource } from "./focus.js";
|
|
9
|
+
export type FindLegendPressedIdentityInput = {
|
|
10
|
+
readonly keys: readonly PropertyKey[];
|
|
11
|
+
readonly entries: readonly InteractiveLegendEntry[];
|
|
12
|
+
readonly keyIndex: ReadonlyMap<string, readonly PropertyKey[]>;
|
|
13
|
+
readonly committed: {
|
|
14
|
+
readonly identity: LegendEntryIdentity;
|
|
15
|
+
readonly keys: readonly PropertyKey[];
|
|
16
|
+
} | null;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Resolve which legend entry should appear pressed.
|
|
20
|
+
* Committed identity wins when its key set still matches (even if multiple
|
|
21
|
+
* entries share the same keys). Otherwise require exactly one matching entry.
|
|
22
|
+
*
|
|
23
|
+
* Complexity: O(K + E) — one Set for the emphasis keys, then per-entry size
|
|
24
|
+
* short-circuit + membership (no Set rebuild per entry). Multi-match returns
|
|
25
|
+
* null as soon as a second hit is found. Empty keys, or empty entries with no
|
|
26
|
+
* committed identity, return before allocating the Set.
|
|
27
|
+
*/
|
|
28
|
+
export declare function findLegendPressedIdentity(input: FindLegendPressedIdentityInput): LegendEntryIdentity | null;
|
|
29
|
+
/**
|
|
30
|
+
* Decide what a legend preview attempt should do with resolved keys.
|
|
31
|
+
* Empty key sets clear any active preview (empty domain entry / stale target)
|
|
32
|
+
* rather than leaving the previous entry highlighted.
|
|
33
|
+
*
|
|
34
|
+
* Non-empty `set` carries mapped InteractionSource via `legendInteractionSource`
|
|
35
|
+
* so the host does not re-map `action.source` after the pure decision.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveLegendPreviewKeysDecision(input: {
|
|
38
|
+
readonly keys: readonly PropertyKey[];
|
|
39
|
+
/** Host: `action.source` (legend entry interaction source). */
|
|
40
|
+
readonly entrySource: LegendInteractionSource;
|
|
41
|
+
}): {
|
|
42
|
+
readonly type: "clear";
|
|
43
|
+
} | {
|
|
44
|
+
readonly type: "set";
|
|
45
|
+
readonly keys: readonly PropertyKey[];
|
|
46
|
+
readonly source: InteractionSource;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Emphasis keys shown while legend focus is enabled vs disabled.
|
|
50
|
+
* When disabled, chart-local preview and local commits must not mute the plot
|
|
51
|
+
* (controls are gone). Controller emphasis still flows through when present.
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveLegendEmphasisKeys(input: {
|
|
54
|
+
readonly legendFocusEnabled: boolean;
|
|
55
|
+
readonly previewKeys: readonly PropertyKey[] | null;
|
|
56
|
+
readonly controllerKeys: readonly PropertyKey[] | null;
|
|
57
|
+
readonly localKeys: readonly PropertyKey[];
|
|
58
|
+
}): readonly PropertyKey[];
|
|
59
|
+
export type LegendPreviewState = {
|
|
60
|
+
readonly identity: LegendEntryIdentity;
|
|
61
|
+
readonly keys: readonly PropertyKey[];
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Reconcile a transient preview against the current entry list / key index.
|
|
65
|
+
* Clears when the identity disappears or its keys empty; refreshes keys when
|
|
66
|
+
* membership changes for the same identity.
|
|
67
|
+
*/
|
|
68
|
+
export declare function reconcileLegendPreview(input: {
|
|
69
|
+
readonly preview: LegendPreviewState | null;
|
|
70
|
+
readonly entries: readonly InteractiveLegendEntry[];
|
|
71
|
+
readonly keyIndex: ReadonlyMap<string, readonly PropertyKey[]>;
|
|
72
|
+
}): LegendPreviewState | null;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { keysForLegendEntry, legendInteractionSource, samePropertyKeySet, } from "./focus.js";
|
|
2
|
+
/**
|
|
3
|
+
* Whether a first-seen-unique key array matches a Set's membership.
|
|
4
|
+
* Used by pressed-identity resolution so entry compares stay O(K) without
|
|
5
|
+
* allocating a Set per legend entry. Entry-key index values and committed
|
|
6
|
+
* keys are frozen unique arrays from `buildLegendEntryKeyIndex`.
|
|
7
|
+
*/
|
|
8
|
+
function uniqueKeysMatchSet(keys, keySet) {
|
|
9
|
+
if (keys.length !== keySet.size)
|
|
10
|
+
return false;
|
|
11
|
+
for (const key of keys)
|
|
12
|
+
if (!keySet.has(key))
|
|
13
|
+
return false;
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolve which legend entry should appear pressed.
|
|
18
|
+
* Committed identity wins when its key set still matches (even if multiple
|
|
19
|
+
* entries share the same keys). Otherwise require exactly one matching entry.
|
|
20
|
+
*
|
|
21
|
+
* Complexity: O(K + E) — one Set for the emphasis keys, then per-entry size
|
|
22
|
+
* short-circuit + membership (no Set rebuild per entry). Multi-match returns
|
|
23
|
+
* null as soon as a second hit is found. Empty keys, or empty entries with no
|
|
24
|
+
* committed identity, return before allocating the Set.
|
|
25
|
+
*/
|
|
26
|
+
export function findLegendPressedIdentity(input) {
|
|
27
|
+
if (input.keys.length === 0)
|
|
28
|
+
return null;
|
|
29
|
+
// Ramp-only / no discrete legends and no commit: nothing to match (issue #209).
|
|
30
|
+
if (input.entries.length === 0 && input.committed === null)
|
|
31
|
+
return null;
|
|
32
|
+
const inputSet = new Set(input.keys);
|
|
33
|
+
if (input.committed !== null && uniqueKeysMatchSet(input.committed.keys, inputSet))
|
|
34
|
+
return input.committed.identity;
|
|
35
|
+
let match = null;
|
|
36
|
+
for (const entry of input.entries) {
|
|
37
|
+
const entryKeys = keysForLegendEntry(input.keyIndex, entry.identity);
|
|
38
|
+
if (!uniqueKeysMatchSet(entryKeys, inputSet))
|
|
39
|
+
continue;
|
|
40
|
+
if (match !== null)
|
|
41
|
+
return null;
|
|
42
|
+
match = entry.identity;
|
|
43
|
+
}
|
|
44
|
+
return match;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Decide what a legend preview attempt should do with resolved keys.
|
|
48
|
+
* Empty key sets clear any active preview (empty domain entry / stale target)
|
|
49
|
+
* rather than leaving the previous entry highlighted.
|
|
50
|
+
*
|
|
51
|
+
* Non-empty `set` carries mapped InteractionSource via `legendInteractionSource`
|
|
52
|
+
* so the host does not re-map `action.source` after the pure decision.
|
|
53
|
+
*/
|
|
54
|
+
export function resolveLegendPreviewKeysDecision(input) {
|
|
55
|
+
if (input.keys.length === 0)
|
|
56
|
+
return { type: "clear" };
|
|
57
|
+
return {
|
|
58
|
+
type: "set",
|
|
59
|
+
keys: input.keys,
|
|
60
|
+
source: legendInteractionSource(input.entrySource),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Emphasis keys shown while legend focus is enabled vs disabled.
|
|
65
|
+
* When disabled, chart-local preview and local commits must not mute the plot
|
|
66
|
+
* (controls are gone). Controller emphasis still flows through when present.
|
|
67
|
+
*/
|
|
68
|
+
export function resolveLegendEmphasisKeys(input) {
|
|
69
|
+
if (!input.legendFocusEnabled)
|
|
70
|
+
return input.controllerKeys ?? [];
|
|
71
|
+
return input.previewKeys ?? input.controllerKeys ?? input.localKeys;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Reconcile a transient preview against the current entry list / key index.
|
|
75
|
+
* Clears when the identity disappears or its keys empty; refreshes keys when
|
|
76
|
+
* membership changes for the same identity.
|
|
77
|
+
*/
|
|
78
|
+
export function reconcileLegendPreview(input) {
|
|
79
|
+
if (input.preview === null)
|
|
80
|
+
return null;
|
|
81
|
+
const current = input.entries.find(({ identity }) => identity.scale === input.preview.identity.scale &&
|
|
82
|
+
identity.entryIndex === input.preview.identity.entryIndex);
|
|
83
|
+
if (current === undefined)
|
|
84
|
+
return null;
|
|
85
|
+
const keys = keysForLegendEntry(input.keyIndex, current.identity);
|
|
86
|
+
if (keys.length === 0)
|
|
87
|
+
return null;
|
|
88
|
+
if (samePropertyKeySet(keys, input.preview.keys))
|
|
89
|
+
return input.preview;
|
|
90
|
+
return { identity: current.identity, keys };
|
|
91
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure host `$effect` plans for legend focus (committed reconcile, disable
|
|
3
|
+
* clear, roving focus sync). Controllers own DOM / emission side effects.
|
|
4
|
+
*
|
|
5
|
+
* Identity/roving: `focus.ts`. Emphasis/preview: `focus-emphasis.ts`.
|
|
6
|
+
*/
|
|
7
|
+
import { type InteractiveLegendEntry, type LegendEntryIdentity } from "./focus.js";
|
|
8
|
+
export type LegendCommittedState = {
|
|
9
|
+
readonly identity: LegendEntryIdentity;
|
|
10
|
+
readonly keys: readonly PropertyKey[];
|
|
11
|
+
};
|
|
12
|
+
export type LegendCommittedReconcilePlan = {
|
|
13
|
+
readonly type: "noop";
|
|
14
|
+
} | {
|
|
15
|
+
readonly type: "clear-committed";
|
|
16
|
+
} | {
|
|
17
|
+
readonly type: "clear-committed-local-emit";
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Pure plan for the committed-legend reconcile effect after data reshuffle.
|
|
21
|
+
*
|
|
22
|
+
* Owns entry lookup + key compare (same shape as `reconcileLegendPreview`).
|
|
23
|
+
* Host on non-noop: always nulls `legendCommitted`. On local-emit also clears
|
|
24
|
+
* chart-local emphasis keys and emits legend-focus clear.
|
|
25
|
+
*
|
|
26
|
+
* 1. no commit → noop
|
|
27
|
+
* 2. live keys still match → noop
|
|
28
|
+
* 3. mismatch + local emphasis active → clear-committed-local-emit
|
|
29
|
+
* 4. mismatch otherwise → clear-committed
|
|
30
|
+
*/
|
|
31
|
+
export declare function planLegendCommittedReconcile(input: {
|
|
32
|
+
readonly committed: LegendCommittedState | null;
|
|
33
|
+
readonly entries: readonly InteractiveLegendEntry[];
|
|
34
|
+
readonly keyIndex: ReadonlyMap<string, readonly PropertyKey[]>;
|
|
35
|
+
/** Host: `interaction === undefined`. */
|
|
36
|
+
readonly usesLocalEmphasis: boolean;
|
|
37
|
+
readonly localEmphasisCount: number;
|
|
38
|
+
}): LegendCommittedReconcilePlan;
|
|
39
|
+
export type LegendFocusDisabledClearPlan = {
|
|
40
|
+
readonly type: "noop";
|
|
41
|
+
} | {
|
|
42
|
+
readonly type: "clear-host";
|
|
43
|
+
} | {
|
|
44
|
+
readonly type: "clear-host-local";
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Pure plan when legend focus is turned off at runtime.
|
|
48
|
+
*
|
|
49
|
+
* 1. still enabled → noop
|
|
50
|
+
* 2. host legend state already empty → noop
|
|
51
|
+
* 3. chart-local mode → clear preview+committed+localEmphasisKeys
|
|
52
|
+
* 4. controller mode → clear preview+committed only (controller emphasis stays)
|
|
53
|
+
*/
|
|
54
|
+
export declare function planLegendFocusDisabledClear(input: {
|
|
55
|
+
readonly legendFocusEnabled: boolean;
|
|
56
|
+
readonly hasPreview: boolean;
|
|
57
|
+
readonly hasCommitted: boolean;
|
|
58
|
+
readonly hasLocalEmphasis: boolean;
|
|
59
|
+
/** Host: `interaction === undefined`. */
|
|
60
|
+
readonly usesLocalEmphasis: boolean;
|
|
61
|
+
}): LegendFocusDisabledClearPlan;
|
|
62
|
+
export type LegendRovingFocusSyncPlan = {
|
|
63
|
+
readonly type: "noop";
|
|
64
|
+
readonly nextIndex: number;
|
|
65
|
+
} | {
|
|
66
|
+
readonly type: "clamp-roving";
|
|
67
|
+
readonly nextIndex: number;
|
|
68
|
+
} | {
|
|
69
|
+
readonly type: "refocus";
|
|
70
|
+
readonly nextIndex: number;
|
|
71
|
+
readonly returnIndex: number;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Pure plan for the legend roving-index `$effect.pre`.
|
|
75
|
+
*
|
|
76
|
+
* Host owns `document.activeElement` / dataset parse for `focusedIndex`.
|
|
77
|
+
* `Number(dataset.index)` yields NaN when missing — pass that through so
|
|
78
|
+
* `clampLegendRovingIndex` maps non-finite → 0 (refocus first entry).
|
|
79
|
+
*
|
|
80
|
+
* - focusedIndex === null OR entryCount === 0 → no DOM refocus
|
|
81
|
+
* (clamp-roving when nextIndex differs from current, else noop)
|
|
82
|
+
* - otherwise → refocus with returnIndex = clamp(focusedIndex, count)
|
|
83
|
+
*/
|
|
84
|
+
export declare function planLegendRovingFocusSync(input: {
|
|
85
|
+
readonly currentRoving: number;
|
|
86
|
+
readonly entryCount: number;
|
|
87
|
+
/** null = focus not on a legend target inside root; may be NaN. */
|
|
88
|
+
readonly focusedIndex: number | null;
|
|
89
|
+
}): LegendRovingFocusSyncPlan;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure host `$effect` plans for legend focus (committed reconcile, disable
|
|
3
|
+
* clear, roving focus sync). Controllers own DOM / emission side effects.
|
|
4
|
+
*
|
|
5
|
+
* Identity/roving: `focus.ts`. Emphasis/preview: `focus-emphasis.ts`.
|
|
6
|
+
*/
|
|
7
|
+
import { clampLegendRovingIndex, keysForLegendEntry, samePropertyKeySet, } from "./focus.js";
|
|
8
|
+
/**
|
|
9
|
+
* Pure plan for the committed-legend reconcile effect after data reshuffle.
|
|
10
|
+
*
|
|
11
|
+
* Owns entry lookup + key compare (same shape as `reconcileLegendPreview`).
|
|
12
|
+
* Host on non-noop: always nulls `legendCommitted`. On local-emit also clears
|
|
13
|
+
* chart-local emphasis keys and emits legend-focus clear.
|
|
14
|
+
*
|
|
15
|
+
* 1. no commit → noop
|
|
16
|
+
* 2. live keys still match → noop
|
|
17
|
+
* 3. mismatch + local emphasis active → clear-committed-local-emit
|
|
18
|
+
* 4. mismatch otherwise → clear-committed
|
|
19
|
+
*/
|
|
20
|
+
export function planLegendCommittedReconcile(input) {
|
|
21
|
+
if (input.committed === null)
|
|
22
|
+
return { type: "noop" };
|
|
23
|
+
const current = input.entries.find(({ identity }) => identity.scale === input.committed.identity.scale &&
|
|
24
|
+
identity.entryIndex === input.committed.identity.entryIndex);
|
|
25
|
+
const currentKeys = current === undefined ? [] : keysForLegendEntry(input.keyIndex, current.identity);
|
|
26
|
+
if (samePropertyKeySet(currentKeys, input.committed.keys))
|
|
27
|
+
return { type: "noop" };
|
|
28
|
+
if (input.usesLocalEmphasis && input.localEmphasisCount > 0) {
|
|
29
|
+
return { type: "clear-committed-local-emit" };
|
|
30
|
+
}
|
|
31
|
+
return { type: "clear-committed" };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Pure plan when legend focus is turned off at runtime.
|
|
35
|
+
*
|
|
36
|
+
* 1. still enabled → noop
|
|
37
|
+
* 2. host legend state already empty → noop
|
|
38
|
+
* 3. chart-local mode → clear preview+committed+localEmphasisKeys
|
|
39
|
+
* 4. controller mode → clear preview+committed only (controller emphasis stays)
|
|
40
|
+
*/
|
|
41
|
+
export function planLegendFocusDisabledClear(input) {
|
|
42
|
+
if (input.legendFocusEnabled)
|
|
43
|
+
return { type: "noop" };
|
|
44
|
+
if (!input.hasPreview && !input.hasCommitted && !input.hasLocalEmphasis) {
|
|
45
|
+
return { type: "noop" };
|
|
46
|
+
}
|
|
47
|
+
return input.usesLocalEmphasis ? { type: "clear-host-local" } : { type: "clear-host" };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Pure plan for the legend roving-index `$effect.pre`.
|
|
51
|
+
*
|
|
52
|
+
* Host owns `document.activeElement` / dataset parse for `focusedIndex`.
|
|
53
|
+
* `Number(dataset.index)` yields NaN when missing — pass that through so
|
|
54
|
+
* `clampLegendRovingIndex` maps non-finite → 0 (refocus first entry).
|
|
55
|
+
*
|
|
56
|
+
* - focusedIndex === null OR entryCount === 0 → no DOM refocus
|
|
57
|
+
* (clamp-roving when nextIndex differs from current, else noop)
|
|
58
|
+
* - otherwise → refocus with returnIndex = clamp(focusedIndex, count)
|
|
59
|
+
*/
|
|
60
|
+
export function planLegendRovingFocusSync(input) {
|
|
61
|
+
const nextIndex = clampLegendRovingIndex(input.currentRoving, input.entryCount);
|
|
62
|
+
if (input.focusedIndex === null || input.entryCount === 0) {
|
|
63
|
+
return nextIndex === input.currentRoving
|
|
64
|
+
? { type: "noop", nextIndex }
|
|
65
|
+
: { type: "clamp-roving", nextIndex };
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
type: "refocus",
|
|
69
|
+
nextIndex,
|
|
70
|
+
returnIndex: clampLegendRovingIndex(input.focusedIndex, input.entryCount),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-derived reconcile effects for the legend-focus controller (S5).
|
|
3
|
+
*
|
|
4
|
+
* Hosts the four reconcile effects previously registered inside
|
|
5
|
+
* focus-state.installHostDerivedEffects: roving-index sync ($effect.pre),
|
|
6
|
+
* committed reconcile, preview reconcile, and focus-disabled clear.
|
|
7
|
+
*
|
|
8
|
+
* Registration happens synchronously inside installHostDerivedEffects — the
|
|
9
|
+
* late-hook ordering is intentional: these effects must not register before
|
|
10
|
+
* the host declares the entry/pressed deriveds that the controller's compute*
|
|
11
|
+
* methods feed (#627).
|
|
12
|
+
*
|
|
13
|
+
* Ports are LIVE getters/setters over the controller's rune state — never
|
|
14
|
+
* snapshots. Shared controller emphasis survives disable while local emphasis
|
|
15
|
+
* clears (planLegendFocusDisabledClear "clear-host" vs "clear-host-local").
|
|
16
|
+
*/
|
|
17
|
+
import type { PlotInteractionController } from "../interaction/controller.svelte.js";
|
|
18
|
+
import type { LegendFocusEvent } from "../interaction/interaction.js";
|
|
19
|
+
import type { ScopedStore } from "../interaction/scoped-store.svelte.js";
|
|
20
|
+
import { type InteractiveLegendEntry, type LegendEntryAction, type LegendEntryIdentity } from "./focus.js";
|
|
21
|
+
import type { LegendEntryKeyAccess } from "./entry-key-index.svelte.js";
|
|
22
|
+
export type LegendFocusPreviewState = {
|
|
23
|
+
action: LegendEntryAction;
|
|
24
|
+
keys: readonly PropertyKey[];
|
|
25
|
+
} | null;
|
|
26
|
+
export type LegendFocusCommittedState = {
|
|
27
|
+
identity: LegendEntryIdentity;
|
|
28
|
+
keys: readonly PropertyKey[];
|
|
29
|
+
} | null;
|
|
30
|
+
export type LegendFocusReconcilePorts = {
|
|
31
|
+
readonly entries: () => readonly InteractiveLegendEntry[];
|
|
32
|
+
readonly entryKeys: () => LegendEntryKeyAccess;
|
|
33
|
+
readonly root: () => HTMLElement | null;
|
|
34
|
+
readonly interaction: () => PlotInteractionController | undefined;
|
|
35
|
+
readonly legendFocusEnabled: () => boolean;
|
|
36
|
+
/** Emphasis store — local shadow when controller-driven, source of truth local. */
|
|
37
|
+
readonly emphasisKeys: ScopedStore<readonly PropertyKey[]>;
|
|
38
|
+
/** Live accessors over the controller's rune state (never snapshotted). */
|
|
39
|
+
readonly rovingIndex: () => number;
|
|
40
|
+
readonly setRovingIndex: (next: number) => void;
|
|
41
|
+
readonly committed: () => LegendFocusCommittedState;
|
|
42
|
+
readonly setCommitted: (next: LegendFocusCommittedState) => void;
|
|
43
|
+
readonly preview: () => LegendFocusPreviewState;
|
|
44
|
+
readonly setPreview: (next: LegendFocusPreviewState) => void;
|
|
45
|
+
readonly emitLegendFocus: (event: LegendFocusEvent) => void;
|
|
46
|
+
readonly previewLegend: (action: LegendEntryAction | null) => void;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Register the four reconcile effects. Called synchronously from
|
|
50
|
+
* `installHostDerivedEffects` while the component initializes — never from a
|
|
51
|
+
* callback or after init.
|
|
52
|
+
*/
|
|
53
|
+
export declare function installLegendFocusReconcileEffects(ports: LegendFocusReconcilePorts): void;
|