matterviz 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EmptyState.svelte +10 -2
- package/dist/FilePicker.svelte +123 -82
- package/dist/Icon.svelte +18 -12
- package/dist/MillerIndexInput.svelte +27 -21
- package/dist/api/optimade.js +6 -6
- package/dist/app.css +216 -207
- package/dist/brillouin/BrillouinZone.svelte +292 -149
- package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
- package/dist/brillouin/BrillouinZoneExportPane.svelte +69 -42
- package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
- package/dist/brillouin/BrillouinZoneScene.svelte +275 -163
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
- package/dist/brillouin/compute.js +11 -6
- package/dist/chempot-diagram/ChemPotDiagram.svelte +162 -27
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +451 -281
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2148 -1642
- package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -5
- package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
- package/dist/chempot-diagram/async-compute.svelte.js +77 -0
- package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
- package/dist/chempot-diagram/chempot-worker.js +11 -0
- package/dist/chempot-diagram/color.js +1 -2
- package/dist/chempot-diagram/compute.d.ts +10 -0
- package/dist/chempot-diagram/compute.js +250 -88
- package/dist/chempot-diagram/index.d.ts +2 -1
- package/dist/chempot-diagram/index.js +2 -1
- package/dist/chempot-diagram/temperature.js +8 -9
- package/dist/chempot-diagram/types.d.ts +3 -0
- package/dist/chempot-diagram/types.js +1 -0
- package/dist/colors/index.d.ts +1 -1
- package/dist/colors/index.js +5 -3
- package/dist/composition/BarChart.svelte +128 -55
- package/dist/composition/BubbleChart.svelte +102 -49
- package/dist/composition/Composition.svelte +100 -79
- package/dist/composition/Formula.svelte +108 -62
- package/dist/composition/FormulaFilter.svelte +665 -537
- package/dist/composition/PieChart.svelte +183 -108
- package/dist/composition/format.d.ts +5 -0
- package/dist/composition/format.js +20 -3
- package/dist/composition/parse.js +14 -9
- package/dist/convex-hull/ConvexHull.svelte +93 -40
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +549 -360
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +1296 -827
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +1004 -688
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullControls.svelte +115 -28
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
- package/dist/convex-hull/ConvexHullStats.svelte +425 -328
- package/dist/convex-hull/ConvexHullTooltip.svelte +40 -16
- package/dist/convex-hull/GasPressureControls.svelte +104 -61
- package/dist/convex-hull/StructurePopup.svelte +25 -4
- package/dist/convex-hull/TemperatureSlider.svelte +45 -25
- package/dist/convex-hull/barycentric-coords.js +13 -7
- package/dist/convex-hull/demo-temperature.js +8 -4
- package/dist/convex-hull/gas-thermodynamics.js +17 -12
- package/dist/convex-hull/helpers.d.ts +9 -0
- package/dist/convex-hull/helpers.js +77 -34
- package/dist/convex-hull/thermodynamics.js +61 -56
- package/dist/convex-hull/types.d.ts +9 -14
- package/dist/convex-hull/types.js +0 -17
- package/dist/coordination/CoordinationBarPlot.svelte +227 -154
- package/dist/element/BohrAtom.svelte +55 -12
- package/dist/element/ElementHeading.svelte +7 -2
- package/dist/element/ElementPhoto.svelte +15 -9
- package/dist/element/ElementStats.svelte +10 -4
- package/dist/element/ElementTile.svelte +137 -73
- package/dist/element/Nucleus.svelte +39 -11
- package/dist/element/data.js +1 -1
- package/dist/feedback/ClickFeedback.svelte +16 -5
- package/dist/feedback/DragOverlay.svelte +10 -2
- package/dist/feedback/Spinner.svelte +4 -2
- package/dist/feedback/StatusMessage.svelte +8 -2
- package/dist/fermi-surface/FermiSlice.svelte +118 -88
- package/dist/fermi-surface/FermiSurface.svelte +328 -187
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +535 -342
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
- package/dist/fermi-surface/compute.js +16 -20
- package/dist/fermi-surface/parse.js +24 -14
- package/dist/fermi-surface/symmetry.js +2 -7
- package/dist/fermi-surface/types.d.ts +3 -5
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +1019 -765
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +1 -1
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +76 -22
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +2 -3
- package/dist/icons.js +47 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/io/decompress.js +1 -1
- package/dist/io/export.d.ts +3 -0
- package/dist/io/export.js +129 -143
- package/dist/io/is-binary.js +2 -3
- package/dist/io/url-drop.js +1 -2
- package/dist/isosurface/Isosurface.svelte +202 -148
- package/dist/isosurface/IsosurfaceControls.svelte +46 -28
- package/dist/isosurface/parse.js +34 -29
- package/dist/isosurface/slice.js +5 -10
- package/dist/isosurface/types.d.ts +2 -1
- package/dist/isosurface/types.js +61 -12
- package/dist/labels.js +11 -8
- package/dist/layout/FullscreenToggle.svelte +11 -2
- package/dist/layout/InfoCard.svelte +38 -6
- package/dist/layout/InfoTag.svelte +63 -32
- package/dist/layout/PropertyFilter.svelte +82 -37
- package/dist/layout/SettingsSection.svelte +85 -55
- package/dist/layout/SubpageGrid.svelte +10 -2
- package/dist/layout/json-tree/JsonNode.svelte +183 -138
- package/dist/layout/json-tree/JsonTree.svelte +499 -413
- package/dist/layout/json-tree/JsonValue.svelte +127 -99
- package/dist/layout/json-tree/utils.js +4 -2
- package/dist/marching-cubes.js +25 -2
- package/dist/math.d.ts +13 -17
- package/dist/math.js +133 -67
- package/dist/overlays/ContextMenu.svelte +65 -40
- package/dist/overlays/DraggablePane.svelte +211 -139
- package/dist/periodic-table/PeriodicTable.svelte +278 -145
- package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
- package/dist/periodic-table/PropertySelect.svelte +25 -7
- package/dist/periodic-table/TableInset.svelte +8 -3
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +446 -309
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramControls.svelte +102 -43
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +63 -40
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +71 -28
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +158 -101
- package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
- package/dist/phase-diagram/build-diagram.js +9 -9
- package/dist/phase-diagram/colors.js +1 -3
- package/dist/phase-diagram/parse.js +10 -9
- package/dist/phase-diagram/svg-to-diagram.js +53 -49
- package/dist/phase-diagram/utils.d.ts +1 -0
- package/dist/phase-diagram/utils.js +80 -25
- package/dist/plot/AxisLabel.svelte +28 -3
- package/dist/plot/BarPlot.svelte +1182 -734
- package/dist/plot/BarPlot.svelte.d.ts +2 -2
- package/dist/plot/BarPlotControls.svelte +31 -5
- package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ColorBar.svelte +479 -329
- package/dist/plot/ColorScaleSelect.svelte +27 -6
- package/dist/plot/ElementScatter.svelte +36 -15
- package/dist/plot/FillArea.svelte +152 -95
- package/dist/plot/Histogram.svelte +934 -571
- package/dist/plot/Histogram.svelte.d.ts +1 -1
- package/dist/plot/HistogramControls.svelte +53 -9
- package/dist/plot/HistogramControls.svelte.d.ts +1 -1
- package/dist/plot/InteractiveAxisLabel.svelte +34 -11
- package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/Line.svelte +63 -28
- package/dist/plot/PlotControls.svelte +157 -114
- package/dist/plot/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/PlotLegend.svelte +174 -91
- package/dist/plot/PlotTooltip.svelte +45 -6
- package/dist/plot/PortalSelect.svelte +175 -147
- package/dist/plot/ReferenceLine.svelte +76 -22
- package/dist/plot/ReferenceLine3D.svelte +132 -107
- package/dist/plot/ReferencePlane.svelte +146 -121
- package/dist/plot/ScatterPlot.svelte +1681 -1091
- package/dist/plot/ScatterPlot.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3D.svelte +256 -131
- package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3DControls.svelte +113 -63
- package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
- package/dist/plot/ScatterPlot3DScene.svelte +608 -403
- package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlotControls.svelte +65 -25
- package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ScatterPoint.svelte +98 -26
- package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
- package/dist/plot/SpacegroupBarPlot.svelte +142 -85
- package/dist/plot/Surface3D.svelte +159 -108
- package/dist/plot/ZeroLines.svelte +55 -3
- package/dist/plot/ZoomRect.svelte +4 -2
- package/dist/plot/axis-utils.js +1 -3
- package/dist/plot/data-cleaning.js +12 -28
- package/dist/plot/data-transform.js +2 -1
- package/dist/plot/fill-utils.js +2 -0
- package/dist/plot/layout.d.ts +4 -1
- package/dist/plot/layout.js +33 -14
- package/dist/plot/reference-line.d.ts +2 -2
- package/dist/plot/reference-line.js +7 -5
- package/dist/plot/scales.js +24 -36
- package/dist/plot/types.d.ts +11 -23
- package/dist/plot/types.js +6 -11
- package/dist/plot/utils/label-placement.d.ts +32 -15
- package/dist/plot/utils/label-placement.js +227 -66
- package/dist/plot/utils/series-visibility.js +2 -3
- package/dist/rdf/RdfPlot.svelte +143 -91
- package/dist/rdf/calc-rdf.js +4 -5
- package/dist/sanitize.d.ts +4 -0
- package/dist/sanitize.js +107 -0
- package/dist/settings.d.ts +18 -6
- package/dist/settings.js +46 -16
- package/dist/spectral/Bands.svelte +632 -453
- package/dist/spectral/BandsAndDos.svelte +90 -49
- package/dist/spectral/BrillouinBandsDos.svelte +151 -93
- package/dist/spectral/Dos.svelte +389 -258
- package/dist/spectral/helpers.js +55 -43
- package/dist/state.svelte.d.ts +1 -1
- package/dist/state.svelte.js +3 -2
- package/dist/structure/Arrow.svelte +59 -20
- package/dist/structure/AtomLegend.svelte +215 -134
- package/dist/structure/Bond.svelte +73 -47
- package/dist/structure/CanvasTooltip.svelte +10 -2
- package/dist/structure/CellSelect.svelte +72 -45
- package/dist/structure/Cylinder.svelte +33 -17
- package/dist/structure/Lattice.svelte +88 -33
- package/dist/structure/Structure.svelte +1063 -797
- package/dist/structure/Structure.svelte.d.ts +1 -1
- package/dist/structure/StructureControls.svelte +349 -118
- package/dist/structure/StructureExportPane.svelte +124 -89
- package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +304 -237
- package/dist/structure/StructureScene.svelte +879 -443
- package/dist/structure/StructureScene.svelte.d.ts +15 -7
- package/dist/structure/atom-properties.js +8 -8
- package/dist/structure/bonding.js +6 -7
- package/dist/structure/export.js +14 -29
- package/dist/structure/ferrox-wasm.js +1 -1
- package/dist/structure/index.d.ts +13 -3
- package/dist/structure/index.js +83 -23
- package/dist/structure/measure.d.ts +2 -2
- package/dist/structure/measure.js +4 -44
- package/dist/structure/parse.js +113 -141
- package/dist/structure/partial-occupancy.js +7 -10
- package/dist/structure/pbc.d.ts +1 -0
- package/dist/structure/pbc.js +16 -6
- package/dist/structure/supercell.d.ts +2 -2
- package/dist/structure/supercell.js +12 -22
- package/dist/structure/validation.js +1 -2
- package/dist/symmetry/SymmetryStats.svelte +84 -41
- package/dist/symmetry/WyckoffTable.svelte +26 -6
- package/dist/symmetry/cell-transform.js +5 -3
- package/dist/symmetry/index.js +8 -7
- package/dist/symmetry/spacegroups.js +148 -148
- package/dist/table/HeatmapTable.svelte +790 -554
- package/dist/table/HeatmapTable.svelte.d.ts +1 -1
- package/dist/table/ToggleMenu.svelte +125 -92
- package/dist/table/index.js +2 -4
- package/dist/theme/ThemeControl.svelte +21 -12
- package/dist/time.js +4 -1
- package/dist/tooltip/TooltipContent.svelte +33 -8
- package/dist/trajectory/Trajectory.svelte +758 -558
- package/dist/trajectory/TrajectoryError.svelte +14 -3
- package/dist/trajectory/TrajectoryExportPane.svelte +137 -83
- package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
- package/dist/trajectory/extract.js +10 -26
- package/dist/trajectory/format-detect.js +5 -5
- package/dist/trajectory/frame-reader.d.ts +1 -1
- package/dist/trajectory/frame-reader.js +5 -12
- package/dist/trajectory/helpers.d.ts +0 -1
- package/dist/trajectory/helpers.js +2 -17
- package/dist/trajectory/index.js +14 -12
- package/dist/trajectory/parse/ase.js +5 -4
- package/dist/trajectory/parse/hdf5.js +26 -18
- package/dist/trajectory/parse/index.js +13 -18
- package/dist/trajectory/parse/lammps.js +17 -7
- package/dist/trajectory/parse/vasp.js +5 -2
- package/dist/trajectory/parse/xyz.js +8 -7
- package/dist/trajectory/plotting.js +13 -8
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +13 -0
- package/dist/xrd/XrdPlot.svelte +337 -247
- package/dist/xrd/broadening.js +14 -9
- package/dist/xrd/calc-xrd.js +12 -18
- package/dist/xrd/parse.d.ts +1 -1
- package/dist/xrd/parse.js +17 -17
- package/package.json +99 -103
- package/readme.md +1 -1
- /package/dist/theme/{themes.js → themes.mjs} +0 -0
|
@@ -1,100 +1,183 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { LegendItem, Orientation } from './'
|
|
3
|
+
import { sanitize_html } from '../sanitize'
|
|
4
|
+
import { strip_html } from '../table'
|
|
5
|
+
import { onDestroy } from 'svelte'
|
|
6
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
7
|
+
import { SvelteMap, SvelteSet } from 'svelte/reactivity'
|
|
8
|
+
|
|
9
|
+
// Unique instance ID to prevent gradient ID collisions when multiple legends render on the same page
|
|
10
|
+
const instance_id = crypto.randomUUID().slice(0, 8)
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
series_data = [],
|
|
14
|
+
layout = `vertical`,
|
|
15
|
+
layout_tracks = 1, // Default to 1 column/row
|
|
16
|
+
style = ``,
|
|
17
|
+
item_style = ``,
|
|
18
|
+
collapsed_groups = $bindable(new SvelteSet<string>()),
|
|
19
|
+
on_toggle = () => {},
|
|
20
|
+
on_double_click = () => {},
|
|
21
|
+
on_fill_toggle,
|
|
22
|
+
on_fill_double_click,
|
|
23
|
+
on_group_toggle,
|
|
24
|
+
on_group_double_click,
|
|
25
|
+
on_drag_start = () => {},
|
|
26
|
+
on_drag = () => {},
|
|
27
|
+
on_drag_end = () => {},
|
|
28
|
+
on_hover_change,
|
|
29
|
+
draggable = true,
|
|
30
|
+
root_element = $bindable<HTMLDivElement | undefined>(undefined),
|
|
31
|
+
...rest
|
|
32
|
+
}: Omit<HTMLAttributes<HTMLDivElement>, `style`> & {
|
|
33
|
+
series_data: LegendItem[]
|
|
34
|
+
layout?: Orientation
|
|
35
|
+
layout_tracks?: number // Number of columns for horizontal, rows for vertical
|
|
36
|
+
style?: string // Inline styles forwarded to wrapper div
|
|
37
|
+
item_style?: string
|
|
38
|
+
// Bindable set of collapsed group names (pass initial values to collapse groups by default)
|
|
39
|
+
collapsed_groups?: Set<string>
|
|
40
|
+
on_toggle?: (series_idx: number) => void
|
|
41
|
+
on_double_click?: (series_idx: number) => void
|
|
42
|
+
on_fill_toggle?: (
|
|
43
|
+
source_type: `fill_region` | `error_band`,
|
|
44
|
+
source_idx: number,
|
|
45
|
+
) => void
|
|
46
|
+
on_fill_double_click?: (
|
|
47
|
+
source_type: `fill_region` | `error_band`,
|
|
48
|
+
source_idx: number,
|
|
49
|
+
) => void
|
|
50
|
+
on_group_toggle?: (group_name: string, series_indices: number[]) => void
|
|
51
|
+
on_group_double_click?: (group_name: string, series_indices: number[]) => void
|
|
52
|
+
on_drag_start?: (event: MouseEvent) => void
|
|
53
|
+
on_drag?: (event: MouseEvent) => void
|
|
54
|
+
on_drag_end?: (event: MouseEvent) => void
|
|
55
|
+
// Callback when hover state changes (for placement stability)
|
|
56
|
+
on_hover_change?: (is_hovered: boolean) => void
|
|
57
|
+
draggable?: boolean
|
|
58
|
+
// Bindable reference to the root DOM element for size measurements
|
|
59
|
+
root_element?: HTMLDivElement
|
|
60
|
+
} = $props()
|
|
61
|
+
|
|
62
|
+
let is_dragging = $state(false)
|
|
63
|
+
let drag_start_coords = $state<{ x: number; y: number } | null>(null)
|
|
64
|
+
|
|
65
|
+
// Group series by legend_group, preserving order
|
|
66
|
+
type GroupedData = { group_name: string | null; items: LegendItem[] }
|
|
67
|
+
let grouped_series = $derived.by<GroupedData[]>(() => {
|
|
68
|
+
const groups: GroupedData[] = []
|
|
69
|
+
const group_map = new SvelteMap<string | null, LegendItem[]>()
|
|
70
|
+
|
|
12
71
|
for (const item of series_data) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
72
|
+
const group_key = item.legend_group ?? null
|
|
73
|
+
let group_items = group_map.get(group_key)
|
|
74
|
+
if (!group_items) {
|
|
75
|
+
group_items = []
|
|
76
|
+
group_map.set(group_key, group_items)
|
|
77
|
+
groups.push({ group_name: group_key, items: group_items })
|
|
78
|
+
}
|
|
79
|
+
group_items.push(item)
|
|
19
80
|
}
|
|
20
|
-
return groups
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
81
|
+
return groups
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
// Check if any grouping is present
|
|
85
|
+
let has_groups = $derived(
|
|
86
|
+
grouped_series.some((group) =>
|
|
87
|
+
group.group_name !== null && group.items.length > 0
|
|
88
|
+
),
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
function toggle_group_collapse(group_name: string) {
|
|
25
92
|
// Normalize to SvelteSet if a plain Set was passed (ensures reactivity)
|
|
26
93
|
if (!(collapsed_groups instanceof SvelteSet)) {
|
|
27
|
-
|
|
94
|
+
collapsed_groups = new SvelteSet(collapsed_groups)
|
|
28
95
|
}
|
|
29
96
|
// Set.delete returns true if element existed, so add if delete failed
|
|
30
|
-
if (!collapsed_groups.delete(group_name))
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const handle_group_click = (group_name, items
|
|
34
|
-
|
|
97
|
+
if (!collapsed_groups.delete(group_name)) collapsed_groups.add(group_name)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const handle_group_click = (group_name: string, items: LegendItem[]) =>
|
|
101
|
+
on_group_toggle?.(group_name, items.map((item) => item.series_idx))
|
|
102
|
+
|
|
103
|
+
function cleanup_drag_listeners() {
|
|
35
104
|
if (is_dragging) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
105
|
+
// Remove global event listeners
|
|
106
|
+
window.removeEventListener(`mousemove`, handle_window_mouse_move)
|
|
107
|
+
window.removeEventListener(`mouseup`, handle_window_mouse_up)
|
|
108
|
+
|
|
109
|
+
// Reset cursor and text selection
|
|
110
|
+
document.body.style.cursor = `default`
|
|
111
|
+
document.body.style.userSelect = `auto`
|
|
42
112
|
}
|
|
43
|
-
}
|
|
44
|
-
onDestroy(cleanup_drag_listeners)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
113
|
+
}
|
|
114
|
+
onDestroy(cleanup_drag_listeners)
|
|
115
|
+
|
|
116
|
+
function handle_legend_mouse_down(event: MouseEvent) {
|
|
117
|
+
if (!draggable) return
|
|
118
|
+
|
|
48
119
|
// Only start drag if clicking on empty areas (not on legend items)
|
|
49
|
-
const target = event.target
|
|
50
|
-
if (target instanceof Element && target.closest(`.legend-item`))
|
|
51
|
-
|
|
52
|
-
event.preventDefault()
|
|
53
|
-
event.stopPropagation()
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
120
|
+
const target = event.target
|
|
121
|
+
if (target instanceof Element && target.closest(`.legend-item`)) return
|
|
122
|
+
|
|
123
|
+
event.preventDefault()
|
|
124
|
+
event.stopPropagation()
|
|
125
|
+
|
|
126
|
+
is_dragging = true
|
|
127
|
+
drag_start_coords = { x: event.clientX, y: event.clientY }
|
|
128
|
+
|
|
129
|
+
on_drag_start(event)
|
|
130
|
+
|
|
57
131
|
// Add global event listeners
|
|
58
|
-
window.addEventListener(`mousemove`, handle_window_mouse_move)
|
|
59
|
-
window.addEventListener(`mouseup`, handle_window_mouse_up)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
is_dragging
|
|
71
|
-
|
|
72
|
-
|
|
132
|
+
window.addEventListener(`mousemove`, handle_window_mouse_move)
|
|
133
|
+
window.addEventListener(`mouseup`, handle_window_mouse_up)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function handle_window_mouse_move(event: MouseEvent) {
|
|
137
|
+
if (!is_dragging || !drag_start_coords) return
|
|
138
|
+
|
|
139
|
+
event.preventDefault()
|
|
140
|
+
on_drag(event)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function handle_window_mouse_up(event: MouseEvent) {
|
|
144
|
+
if (!is_dragging) return
|
|
145
|
+
|
|
146
|
+
is_dragging = false
|
|
147
|
+
drag_start_coords = null
|
|
148
|
+
|
|
149
|
+
on_drag_end(event)
|
|
150
|
+
|
|
73
151
|
// Remove global event listeners
|
|
74
|
-
window.removeEventListener(`mousemove`, handle_window_mouse_move)
|
|
75
|
-
window.removeEventListener(`mouseup`, handle_window_mouse_up)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
152
|
+
window.removeEventListener(`mousemove`, handle_window_mouse_move)
|
|
153
|
+
window.removeEventListener(`mouseup`, handle_window_mouse_up)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
let div_style = $derived(
|
|
157
|
+
{
|
|
158
|
+
horizontal: `grid-template-columns: repeat(${layout_tracks}, auto);`,
|
|
159
|
+
vertical:
|
|
160
|
+
`grid-template-rows: repeat(${layout_tracks}, auto); grid-template-columns: auto;`,
|
|
161
|
+
}[layout] + style,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
// Extracted toggle handlers to reduce duplication
|
|
165
|
+
function toggle_item(item: LegendItem) {
|
|
166
|
+
if (
|
|
167
|
+
item.item_type === `fill` && on_fill_toggle && item.fill_source_type &&
|
|
168
|
+
item.fill_source_idx !== undefined
|
|
169
|
+
) {
|
|
170
|
+
on_fill_toggle(item.fill_source_type, item.fill_source_idx)
|
|
171
|
+
} else on_toggle(item.series_idx)
|
|
172
|
+
}
|
|
173
|
+
function double_click_item(item: LegendItem) {
|
|
174
|
+
if (
|
|
175
|
+
item.item_type === `fill` && on_fill_double_click && item.fill_source_type &&
|
|
176
|
+
item.fill_source_idx !== undefined
|
|
177
|
+
) {
|
|
178
|
+
on_fill_double_click(item.fill_source_type, item.fill_source_idx)
|
|
179
|
+
} else on_double_click(item.series_idx)
|
|
180
|
+
}
|
|
98
181
|
</script>
|
|
99
182
|
|
|
100
183
|
{#snippet legend_item(series: LegendItem, indent: boolean = false)}
|
|
@@ -124,7 +207,7 @@ function double_click_item(item) {
|
|
|
124
207
|
role="button"
|
|
125
208
|
tabindex="0"
|
|
126
209
|
aria-pressed={series.visible}
|
|
127
|
-
aria-label="Toggle visibility for {series.label}"
|
|
210
|
+
aria-label="Toggle visibility for {strip_html(series.label)}"
|
|
128
211
|
>
|
|
129
212
|
<span class="legend-marker">
|
|
130
213
|
<!-- Fill region swatch -->
|
|
@@ -213,7 +296,7 @@ function double_click_item(item) {
|
|
|
213
296
|
{/if}
|
|
214
297
|
{/if}
|
|
215
298
|
</span>
|
|
216
|
-
<span class="legend-label">{@html series.label}</span>
|
|
299
|
+
<span class="legend-label">{@html sanitize_html(series.label)}</span>
|
|
217
300
|
</div>
|
|
218
301
|
{/snippet}
|
|
219
302
|
|
|
@@ -256,7 +339,7 @@ function double_click_item(item) {
|
|
|
256
339
|
role="button"
|
|
257
340
|
tabindex="0"
|
|
258
341
|
aria-expanded={!is_collapsed}
|
|
259
|
-
aria-label="Toggle group {group_name}"
|
|
342
|
+
aria-label="Toggle group {strip_html(group_name)}"
|
|
260
343
|
>
|
|
261
344
|
<span
|
|
262
345
|
class="group-chevron"
|
|
@@ -275,11 +358,11 @@ function double_click_item(item) {
|
|
|
275
358
|
}}
|
|
276
359
|
role="button"
|
|
277
360
|
tabindex="0"
|
|
278
|
-
aria-label="{is_collapsed ? `Expand` : `Collapse`} group {group_name}"
|
|
361
|
+
aria-label="{is_collapsed ? `Expand` : `Collapse`} group {strip_html(group_name)}"
|
|
279
362
|
>
|
|
280
363
|
▶
|
|
281
364
|
</span>
|
|
282
|
-
<span class="group-label">{@html group_name}</span>
|
|
365
|
+
<span class="group-label">{@html sanitize_html(group_name)}</span>
|
|
283
366
|
</div>
|
|
284
367
|
<!-- Group items (collapsible) -->
|
|
285
368
|
{#if !is_collapsed}
|
|
@@ -1,9 +1,48 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { luminance } from '../colors'
|
|
3
|
+
import type { Snippet } from 'svelte'
|
|
4
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
x,
|
|
8
|
+
y,
|
|
9
|
+
bg_color,
|
|
10
|
+
offset = { x: 6, y: 0 },
|
|
11
|
+
fixed = false,
|
|
12
|
+
wrapper = $bindable(),
|
|
13
|
+
children,
|
|
14
|
+
...rest
|
|
15
|
+
}: HTMLAttributes<HTMLDivElement> & {
|
|
16
|
+
x: number
|
|
17
|
+
y: number
|
|
18
|
+
bg_color?: string | null
|
|
19
|
+
offset?: { x: number; y: number }
|
|
20
|
+
fixed?: boolean // Use position: fixed (for viewport coords) vs absolute
|
|
21
|
+
wrapper?: HTMLDivElement // Bindable reference for measuring tooltip size
|
|
22
|
+
children: Snippet
|
|
23
|
+
} = $props()
|
|
24
|
+
|
|
25
|
+
// Auto-compute contrasting text color based on background luminance only if bg_color is defined
|
|
26
|
+
const text_color = $derived(
|
|
27
|
+
bg_color != null ? (luminance(bg_color) > 0.5 ? `#000000` : `#ffffff`) : null,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
// For fixed positioning (viewport coords), flip to opposite side when near viewport edges
|
|
31
|
+
const pos = $derived.by(() => {
|
|
32
|
+
const raw_x = x + offset.x
|
|
33
|
+
const raw_y = y + offset.y
|
|
34
|
+
if (!fixed) return { x: raw_x, y: raw_y }
|
|
35
|
+
const tw = wrapper?.offsetWidth ?? 0
|
|
36
|
+
const th = wrapper?.offsetHeight ?? 0
|
|
37
|
+
const cx = raw_x + tw > globalThis.innerWidth ? x - Math.abs(offset.x) - tw : raw_x
|
|
38
|
+
const cy = raw_y + th > globalThis.innerHeight ? y - Math.abs(offset.y) - th : raw_y
|
|
39
|
+
return { x: Math.max(0, cx), y: Math.max(0, cy) }
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const style = $derived(
|
|
43
|
+
`position: ${fixed ? `fixed` : `absolute`}; pointer-events: none;
|
|
44
|
+
left: ${pos.x}px; top: ${pos.y}px; ${rest.style ?? ``}`,
|
|
45
|
+
)
|
|
7
46
|
</script>
|
|
8
47
|
|
|
9
48
|
<div
|