matterviz 0.3.2 → 0.3.3
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/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
package/dist/isosurface/slice.js
CHANGED
|
@@ -74,9 +74,7 @@ export function sample_hkl_slice(volume, miller_indices, distance, n_points) {
|
|
|
74
74
|
const unit_normal = math.normalize_vec3(plane_normal);
|
|
75
75
|
// In-plane basis vectors
|
|
76
76
|
const [u_vec, v_vec] = math.compute_in_plane_basis(unit_normal);
|
|
77
|
-
|
|
78
|
-
// lattice rows are vectors [a, b, c], so cart = lattice^T * frac → frac = inv(lattice^T) * cart
|
|
79
|
-
const lattice_inv = math.matrix_inverse_3x3(math.transpose_3x3_matrix(lattice));
|
|
77
|
+
const cart_to_frac = math.create_cart_to_frac(lattice);
|
|
80
78
|
// Project all 8 unit cell corners onto the (u, v) plane to find sampling bounds.
|
|
81
79
|
// Corners are at fractional coords (0 or 1) for each axis.
|
|
82
80
|
let u_min = Infinity;
|
|
@@ -86,9 +84,9 @@ export function sample_hkl_slice(volume, miller_indices, distance, n_points) {
|
|
|
86
84
|
let normal_min = Infinity;
|
|
87
85
|
let normal_max = -Infinity;
|
|
88
86
|
for (let ci = 0; ci < 8; ci++) {
|
|
89
|
-
const fi =
|
|
90
|
-
const fj =
|
|
91
|
-
const fk =
|
|
87
|
+
const fi = ci & 1 ? 1 : 0;
|
|
88
|
+
const fj = ci & 2 ? 1 : 0;
|
|
89
|
+
const fk = ci & 4 ? 1 : 0;
|
|
92
90
|
// Corner in Cartesian: frac * lattice
|
|
93
91
|
const corner = [
|
|
94
92
|
fi * lattice[0][0] + fj * lattice[1][0] + fk * lattice[2][0],
|
|
@@ -129,10 +127,7 @@ export function sample_hkl_slice(volume, miller_indices, distance, n_points) {
|
|
|
129
127
|
const px = d_cartesian * unit_normal[0] + u_val * u_vec[0] + v_val * v_vec[0];
|
|
130
128
|
const py = d_cartesian * unit_normal[1] + u_val * u_vec[1] + v_val * v_vec[1];
|
|
131
129
|
const pz = d_cartesian * unit_normal[2] + u_val * u_vec[2] + v_val * v_vec[2];
|
|
132
|
-
|
|
133
|
-
const fx = lattice_inv[0][0] * px + lattice_inv[0][1] * py + lattice_inv[0][2] * pz;
|
|
134
|
-
const fy = lattice_inv[1][0] * px + lattice_inv[1][1] * py + lattice_inv[1][2] * pz;
|
|
135
|
-
const fz = lattice_inv[2][0] * px + lattice_inv[2][1] * py + lattice_inv[2][2] * pz;
|
|
130
|
+
const [fx, fy, fz] = cart_to_frac([px, py, pz]);
|
|
136
131
|
const val = trilinear_interpolate(grid, fx, fy, fz, periodic);
|
|
137
132
|
data[row * width + col] = val;
|
|
138
133
|
if (val < data_min)
|
|
@@ -45,7 +45,7 @@ export declare function pad_periodic_grid(grid: number[][][], dims: Vec3, pad_fr
|
|
|
45
45
|
dims: Vec3;
|
|
46
46
|
offset: Vec3;
|
|
47
47
|
};
|
|
48
|
-
export declare function downsample_grid(grid: number[][][], dims: Vec3): {
|
|
48
|
+
export declare function downsample_grid(grid: number[][][], dims: Vec3, max_points?: number): {
|
|
49
49
|
grid: number[][][];
|
|
50
50
|
dims: Vec3;
|
|
51
51
|
factor: number;
|
|
@@ -53,3 +53,4 @@ export declare function downsample_grid(grid: number[][][], dims: Vec3): {
|
|
|
53
53
|
export declare const DEFAULT_ISOSURFACE_SETTINGS: IsosurfaceSettings;
|
|
54
54
|
export declare function auto_isosurface_settings(data_range: DataRange): IsosurfaceSettings;
|
|
55
55
|
export declare function generate_layers(data_range: DataRange, n_layers: number): IsosurfaceLayer[];
|
|
56
|
+
export declare function tile_volumetric_data(volume: VolumetricData, scaling: Vec3): VolumetricData;
|
package/dist/isosurface/types.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { scale_lattice_matrix } from '../math';
|
|
1
2
|
// Categorical palette for auto-coloring isosurface layers (Tailwind-inspired)
|
|
2
3
|
export const LAYER_COLORS = [
|
|
3
4
|
`#3b82f6`, // blue
|
|
@@ -15,8 +16,7 @@ export function grid_data_range(grid) {
|
|
|
15
16
|
if (!grid.length || !grid[0]?.length || !grid[0][0]?.length) {
|
|
16
17
|
return { min: 0, max: 0, abs_max: 0, mean: 0 };
|
|
17
18
|
}
|
|
18
|
-
let min_val = Infinity;
|
|
19
|
-
let max_val = -Infinity;
|
|
19
|
+
let [min_val, max_val] = [Infinity, -Infinity];
|
|
20
20
|
let sum = 0;
|
|
21
21
|
let count = 0;
|
|
22
22
|
for (const plane of grid) {
|
|
@@ -71,35 +71,41 @@ export function pad_periodic_grid(grid, dims, pad_fraction) {
|
|
|
71
71
|
// Max total grid points before downsampling is applied for isosurface extraction.
|
|
72
72
|
// 500K balances visual quality with interactive performance (<200ms marching cubes).
|
|
73
73
|
const MAX_GRID_POINTS = 500_000;
|
|
74
|
-
// Downsample a 3D volumetric grid to keep total point count under
|
|
74
|
+
// Downsample a 3D volumetric grid to keep total point count under a budget.
|
|
75
75
|
// Uses block averaging to preserve data fidelity while reducing grid dimensions.
|
|
76
76
|
// Returns original grid/dims if already within budget.
|
|
77
|
-
export function downsample_grid(grid, dims) {
|
|
77
|
+
export function downsample_grid(grid, dims, max_points = MAX_GRID_POINTS) {
|
|
78
78
|
const [nx, ny, nz] = dims;
|
|
79
79
|
const total = nx * ny * nz;
|
|
80
|
-
if (total <=
|
|
80
|
+
if (total <= max_points)
|
|
81
81
|
return { grid, dims, factor: 1 };
|
|
82
|
+
// Floor at 1 to avoid Infinity in cbrt(total/0)
|
|
83
|
+
max_points = Math.max(1, max_points);
|
|
82
84
|
// Increase factor until the clamped output fits within budget.
|
|
83
85
|
// A single cbrt step can overshoot for anisotropic grids where max(2,...)
|
|
84
86
|
// clamping prevents a small axis from shrinking below 2.
|
|
85
87
|
// clamp_dim: returns 1 for single-cell axes, otherwise clamps to [2, src]
|
|
86
88
|
const clamp_dim = (src, fac) => Math.min(src, Math.max(2, Math.ceil(src / fac)));
|
|
87
|
-
let factor = Math.ceil(Math.cbrt(total /
|
|
89
|
+
let factor = Math.ceil(Math.cbrt(total / max_points));
|
|
88
90
|
let new_nx = clamp_dim(nx, factor);
|
|
89
91
|
let new_ny = clamp_dim(ny, factor);
|
|
90
92
|
let new_nz = clamp_dim(nz, factor);
|
|
91
|
-
while (new_nx * new_ny * new_nz >
|
|
93
|
+
while (new_nx * new_ny * new_nz > max_points) {
|
|
92
94
|
factor++;
|
|
95
|
+
const prev_total = new_nx * new_ny * new_nz;
|
|
93
96
|
new_nx = clamp_dim(nx, factor);
|
|
94
97
|
new_ny = clamp_dim(ny, factor);
|
|
95
98
|
new_nz = clamp_dim(nz, factor);
|
|
99
|
+
// dims hit their floor (2 per axis or 1 for single-cell) — stop to avoid infinite loop
|
|
100
|
+
if (new_nx * new_ny * new_nz === prev_total)
|
|
101
|
+
break;
|
|
96
102
|
}
|
|
97
103
|
// Proportional partitioning: evenly divides [0, n) into new_n non-empty blocks.
|
|
98
104
|
// Unlike fixed-stride (ix * factor), this is safe when max(2,...) clamping
|
|
99
105
|
// produces more output cells than ceil(n/factor) would — no empty blocks.
|
|
100
106
|
const partition = (n_out, n_src) => Array.from({ length: n_out }, (_, idx) => [
|
|
101
|
-
Math.round(idx * n_src / n_out),
|
|
102
|
-
Math.round((idx + 1) * n_src / n_out),
|
|
107
|
+
Math.round((idx * n_src) / n_out),
|
|
108
|
+
Math.round(((idx + 1) * n_src) / n_out),
|
|
103
109
|
]);
|
|
104
110
|
const x_ranges = partition(new_nx, nx);
|
|
105
111
|
const y_ranges = partition(new_ny, ny);
|
|
@@ -149,9 +155,7 @@ export function auto_isosurface_settings(data_range) {
|
|
|
149
155
|
return {
|
|
150
156
|
...DEFAULT_ISOSURFACE_SETTINGS,
|
|
151
157
|
// Fall back to default isovalue for all-zero grids to keep controls usable
|
|
152
|
-
isovalue: data_range.abs_max > 0
|
|
153
|
-
? data_range.abs_max * 0.2
|
|
154
|
-
: DEFAULT_ISOSURFACE_SETTINGS.isovalue,
|
|
158
|
+
isovalue: data_range.abs_max > 0 ? data_range.abs_max * 0.2 : DEFAULT_ISOSURFACE_SETTINGS.isovalue,
|
|
155
159
|
show_negative: has_negatives,
|
|
156
160
|
};
|
|
157
161
|
}
|
|
@@ -176,3 +180,48 @@ export function generate_layers(data_range, n_layers) {
|
|
|
176
180
|
};
|
|
177
181
|
});
|
|
178
182
|
}
|
|
183
|
+
// Tile (repeat) volumetric data to fill a supercell.
|
|
184
|
+
// Pre-downsamples the source grid when the tiled result would exceed MAX_GRID_POINTS
|
|
185
|
+
// to avoid large temporary allocations. Returns the original volume unchanged for
|
|
186
|
+
// [1,1,1] scaling.
|
|
187
|
+
export function tile_volumetric_data(volume, scaling) {
|
|
188
|
+
const [sx, sy, sz] = scaling;
|
|
189
|
+
if (sx === 1 && sy === 1 && sz === 1)
|
|
190
|
+
return volume;
|
|
191
|
+
const total_cells = sx * sy * sz;
|
|
192
|
+
let src_grid = volume.grid;
|
|
193
|
+
let [nx, ny, nz] = volume.grid_dims;
|
|
194
|
+
// Pre-downsample source grid so the tiled result stays within budget.
|
|
195
|
+
// Clamp budget to 8 (minimum downsample output = 2^3) to prevent infinite
|
|
196
|
+
// loops in downsample_grid when total_cells is very large.
|
|
197
|
+
if (nx * ny * nz * total_cells > MAX_GRID_POINTS) {
|
|
198
|
+
const budget = Math.max(8, Math.floor(MAX_GRID_POINTS / total_cells));
|
|
199
|
+
const ds = downsample_grid(src_grid, [nx, ny, nz], budget);
|
|
200
|
+
src_grid = ds.grid;
|
|
201
|
+
[nx, ny, nz] = ds.dims;
|
|
202
|
+
}
|
|
203
|
+
const new_nx = nx * sx;
|
|
204
|
+
const new_ny = ny * sy;
|
|
205
|
+
const new_nz = nz * sz;
|
|
206
|
+
const new_grid = new Array(new_nx);
|
|
207
|
+
for (let ix = 0; ix < new_nx; ix++) {
|
|
208
|
+
const plane = new Array(new_ny);
|
|
209
|
+
const src_x = ix % nx;
|
|
210
|
+
for (let iy = 0; iy < new_ny; iy++) {
|
|
211
|
+
const row = new Array(new_nz);
|
|
212
|
+
const src_y = iy % ny;
|
|
213
|
+
const src_row = src_grid[src_x][src_y];
|
|
214
|
+
for (let iz = 0; iz < new_nz; iz++) {
|
|
215
|
+
row[iz] = src_row[iz % nz];
|
|
216
|
+
}
|
|
217
|
+
plane[iy] = row;
|
|
218
|
+
}
|
|
219
|
+
new_grid[ix] = plane;
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
...volume,
|
|
223
|
+
grid: new_grid,
|
|
224
|
+
grid_dims: [new_nx, new_ny, new_nz],
|
|
225
|
+
lattice: scale_lattice_matrix(volume.lattice, scaling),
|
|
226
|
+
};
|
|
227
|
+
}
|
package/dist/labels.js
CHANGED
|
@@ -10,9 +10,13 @@ function name_for_symbol(sym) {
|
|
|
10
10
|
}
|
|
11
11
|
return null;
|
|
12
12
|
}
|
|
13
|
-
export const symbol_names =
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
export const symbol_names = [
|
|
14
|
+
...new Set([...d3_symbols.symbolsFill, ...d3_symbols.symbolsStroke]),
|
|
15
|
+
]
|
|
16
|
+
.map(name_for_symbol)
|
|
17
|
+
.filter((n) => n !== null);
|
|
18
|
+
export const symbol_map = Object.fromEntries(
|
|
19
|
+
// Symbol lookup from d3-shape
|
|
16
20
|
symbol_names.map((name) => [name, d3_symbols[`symbol${name}`]]));
|
|
17
21
|
// Format a value for display with optional time formatting
|
|
18
22
|
export function format_value(value, formatter) {
|
|
@@ -74,8 +78,7 @@ export const ELEM_HEATMAP_KEYS = [
|
|
|
74
78
|
`melting_point`,
|
|
75
79
|
`first_ionization`,
|
|
76
80
|
];
|
|
77
|
-
export const ELEM_HEATMAP_LABELS = Object
|
|
78
|
-
.fromEntries(ELEM_HEATMAP_KEYS.map((key) => {
|
|
81
|
+
export const ELEM_HEATMAP_LABELS = Object.fromEntries(ELEM_HEATMAP_KEYS.map((key) => {
|
|
79
82
|
const [label, unit] = ELEM_PROPERTY_LABELS[key] ?? [];
|
|
80
83
|
if (!label)
|
|
81
84
|
throw `Unexpected missing label ${label}`;
|
|
@@ -142,7 +145,7 @@ export function format_fractional(value) {
|
|
|
142
145
|
return glyph;
|
|
143
146
|
}
|
|
144
147
|
for (const [target, glyph] of FRACTION_GLYPHS) {
|
|
145
|
-
if (target !== 0 && Math.abs(
|
|
148
|
+
if (target !== 0 && Math.abs(1 - x - target) < eps)
|
|
146
149
|
return glyph;
|
|
147
150
|
}
|
|
148
151
|
return format_num(value, `.4~`);
|
|
@@ -154,7 +157,7 @@ export function parse_si_float(value) {
|
|
|
154
157
|
// Remove whitespace and commas
|
|
155
158
|
const cleaned = value.trim().replace(/(\d),(\d)/g, `$1$2`);
|
|
156
159
|
// Check if the value is a SI-formatted number (e.g. "1.23k", "4.56M", "789µ", "12n")
|
|
157
|
-
const match =
|
|
160
|
+
const match = /^([-+]?\d*\.?\d+)\s*([yzafpnµmkMGTPEZY])?$/i.exec(cleaned);
|
|
158
161
|
if (match) {
|
|
159
162
|
const [, num_part, suffix] = match;
|
|
160
163
|
let multiplier = 1;
|
|
@@ -197,7 +200,7 @@ export const ELEMENT_CATEGORIES = [
|
|
|
197
200
|
`post-transition metal`,
|
|
198
201
|
`transition metal`,
|
|
199
202
|
];
|
|
200
|
-
//
|
|
203
|
+
// oxfmt-ignore
|
|
201
204
|
export const ELEM_SYMBOLS = [`H`, `He`, `Li`, `Be`, `B`, `C`, `N`, `O`, `F`, `Ne`, `Na`, `Mg`, `Al`, `Si`, `P`, `S`, `Cl`, `Ar`, `K`, `Ca`, `Sc`, `Ti`, `V`, `Cr`, `Mn`, `Fe`, `Co`, `Ni`, `Cu`, `Zn`, `Ga`, `Ge`, `As`, `Se`, `Br`, `Kr`, `Rb`, `Sr`, `Y`, `Zr`, `Nb`, `Mo`, `Tc`, `Ru`, `Rh`, `Pd`, `Ag`, `Cd`, `In`, `Sn`, `Sb`, `Te`, `I`, `Xe`, `Cs`, `Ba`, `La`, `Ce`, `Pr`, `Nd`, `Pm`, `Sm`, `Eu`, `Gd`, `Tb`, `Dy`, `Ho`, `Er`, `Tm`, `Yb`, `Lu`, `Hf`, `Ta`, `W`, `Re`, `Os`, `Ir`, `Pt`, `Au`, `Hg`, `Tl`, `Pb`, `Bi`, `Po`, `At`, `Rn`, `Fr`, `Ra`, `Ac`, `Th`, `Pa`, `U`, `Np`, `Pu`, `Am`, `Cm`, `Bk`, `Cf`, `Es`, `Fm`, `Md`, `No`, `Lr`, `Rf`, `Db`, `Sg`, `Bh`, `Hs`, `Mt`, `Ds`, `Rg`, `Cn`, `Nh`, `Fl`, `Mc`, `Lv`, `Ts`, `Og`];
|
|
202
205
|
export const SUPERSCRIPT_MAP = {
|
|
203
206
|
'0': `⁰`,
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Icon from '../Icon.svelte'
|
|
3
|
+
import type { HTMLButtonAttributes } from 'svelte/elements'
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
fullscreen = $bindable(false),
|
|
7
|
+
class: className,
|
|
8
|
+
...rest
|
|
9
|
+
}: HTMLButtonAttributes & {
|
|
10
|
+
fullscreen?: boolean
|
|
11
|
+
} = $props()
|
|
3
12
|
</script>
|
|
4
13
|
|
|
5
14
|
<button
|
|
@@ -1,13 +1,45 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { format_num } from '../labels'
|
|
3
|
+
import { sanitize_html } from '../sanitize'
|
|
4
|
+
import type { Snippet } from 'svelte'
|
|
5
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
6
|
+
|
|
7
|
+
interface Props<T extends keyof HTMLElementTagNameMap = `section`>
|
|
8
|
+
extends HTMLAttributes<HTMLElementTagNameMap[T]> {
|
|
9
|
+
data?: {
|
|
10
|
+
title: string
|
|
11
|
+
value?: string | number | number[] | null
|
|
12
|
+
unit?: string
|
|
13
|
+
fmt?: string
|
|
14
|
+
condition?: boolean | number | null
|
|
15
|
+
tooltip?: string
|
|
16
|
+
}[]
|
|
17
|
+
title?: string
|
|
18
|
+
fallback?: string
|
|
19
|
+
fmt?: string
|
|
20
|
+
as?: T
|
|
21
|
+
title_snippet?: Snippet
|
|
22
|
+
fallback_snippet?: Snippet
|
|
23
|
+
}
|
|
24
|
+
let {
|
|
25
|
+
data = [],
|
|
26
|
+
title = ``,
|
|
27
|
+
fallback = ``,
|
|
28
|
+
fmt = `.2f`,
|
|
29
|
+
as = `section`,
|
|
30
|
+
title_snippet,
|
|
31
|
+
fallback_snippet,
|
|
32
|
+
...rest
|
|
33
|
+
}: Props = $props()
|
|
34
|
+
|
|
35
|
+
let default_fmt = $derived(fmt) // rename fmt to default_fmt for internal use
|
|
4
36
|
</script>
|
|
5
37
|
|
|
6
38
|
<svelte:element this={as} {...rest} class="info-card {rest.class ?? ``}">
|
|
7
39
|
{#if title || title_snippet}
|
|
8
40
|
<h2>
|
|
9
41
|
{#if title_snippet}{@render title_snippet()}{:else}
|
|
10
|
-
{@html title}
|
|
42
|
+
{@html sanitize_html(title)}
|
|
11
43
|
{/if}
|
|
12
44
|
</h2>
|
|
13
45
|
{/if}
|
|
@@ -20,10 +52,10 @@ let default_fmt = $derived(fmt); // rename fmt to default_fmt for internal use
|
|
|
20
52
|
}
|
|
21
53
|
<div>
|
|
22
54
|
<span class="title" {title}>
|
|
23
|
-
{@html title}
|
|
55
|
+
{@html sanitize_html(title)}
|
|
24
56
|
</span>
|
|
25
57
|
<strong title={tooltip ?? null}>
|
|
26
|
-
{@html typeof value == `number` ? format_num(value, fmt) : value}
|
|
58
|
+
{@html sanitize_html(typeof value == `number` ? format_num(value, fmt) : value)}
|
|
27
59
|
{#if unit}
|
|
28
60
|
<small>{unit}</small>
|
|
29
61
|
{/if}
|
|
@@ -1,33 +1,64 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Icon from '../Icon.svelte'
|
|
3
|
+
import { sanitize_html } from '../sanitize'
|
|
4
|
+
import type { Snippet } from 'svelte'
|
|
5
|
+
import { tooltip } from 'svelte-multiselect'
|
|
6
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
7
|
+
import type { InfoTagSize, InfoTagVariant } from './index'
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
label,
|
|
11
|
+
value,
|
|
12
|
+
copy_value,
|
|
13
|
+
title,
|
|
14
|
+
variant = `default`,
|
|
15
|
+
size = `md`,
|
|
16
|
+
removable = false,
|
|
17
|
+
disabled = false,
|
|
18
|
+
onclick,
|
|
19
|
+
onremove,
|
|
20
|
+
children,
|
|
21
|
+
...rest
|
|
22
|
+
}: {
|
|
23
|
+
label: string // Label text (supports HTML)
|
|
24
|
+
value: string | number | undefined // Value to display (supports HTML)
|
|
25
|
+
copy_value?: string | number // Value to copy to clipboard (defaults to value)
|
|
26
|
+
title?: string // Tooltip text
|
|
27
|
+
variant?: InfoTagVariant // Visual variant for semantic meaning
|
|
28
|
+
size?: InfoTagSize // Size variant
|
|
29
|
+
removable?: boolean // Show remove/close button
|
|
30
|
+
disabled?: boolean // Disable interactions
|
|
31
|
+
onclick?: (event: MouseEvent) => void // Custom click handler (overrides copy-to-clipboard default)
|
|
32
|
+
onremove?: () => void // Callback when remove button is clicked
|
|
33
|
+
children?: Snippet<[]> // Additional content to render inside the tag
|
|
34
|
+
} & Omit<HTMLAttributes<HTMLSpanElement>, `onclick` | `onkeydown`> = $props()
|
|
35
|
+
|
|
36
|
+
let just_copied = $state(false)
|
|
37
|
+
|
|
38
|
+
async function copy_to_clipboard(): Promise<void> {
|
|
39
|
+
const to_copy = copy_value ?? value
|
|
40
|
+
if (to_copy === undefined) return
|
|
41
|
+
await navigator.clipboard.writeText(String(to_copy))
|
|
42
|
+
just_copied = true
|
|
43
|
+
setTimeout(() => (just_copied = false), 1000)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function handle_click(event: MouseEvent): void {
|
|
47
|
+
if (disabled) return
|
|
48
|
+
if (onclick) onclick(event)
|
|
49
|
+
else void copy_to_clipboard()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function handle_keydown(event: KeyboardEvent): void {
|
|
53
|
+
if (disabled || (event.key !== `Enter` && event.key !== ` `)) return
|
|
54
|
+
event.preventDefault()
|
|
55
|
+
;(event.currentTarget as HTMLElement)?.click()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function handle_remove(event: MouseEvent): void {
|
|
59
|
+
event.stopPropagation()
|
|
60
|
+
onremove?.()
|
|
61
|
+
}
|
|
31
62
|
</script>
|
|
32
63
|
|
|
33
64
|
<span
|
|
@@ -42,8 +73,8 @@ function handle_remove(event) {
|
|
|
42
73
|
aria-disabled={disabled}
|
|
43
74
|
{...rest}
|
|
44
75
|
>
|
|
45
|
-
{@html label}
|
|
46
|
-
<em>{@html value}</em>
|
|
76
|
+
{@html sanitize_html(label)}
|
|
77
|
+
<em>{@html sanitize_html(value)}</em>
|
|
47
78
|
{#if just_copied}
|
|
48
79
|
<Icon
|
|
49
80
|
icon="Check"
|
|
@@ -1,50 +1,95 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
let
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Icon from '../Icon.svelte'
|
|
3
|
+
import { sanitize_html } from '../sanitize'
|
|
4
|
+
import type { AxisConfig, DataSeries } from '../plot'
|
|
5
|
+
import { Histogram } from '../plot'
|
|
6
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
label,
|
|
10
|
+
min_value = $bindable(),
|
|
11
|
+
max_value = $bindable(),
|
|
12
|
+
placeholders = {},
|
|
13
|
+
title,
|
|
14
|
+
histogram_data,
|
|
15
|
+
histogram_height = 30,
|
|
16
|
+
histogram_color = `rgba(0, 0, 0, 0.2)`,
|
|
17
|
+
histogram_position = `top`,
|
|
18
|
+
log = false,
|
|
19
|
+
disabled = false,
|
|
20
|
+
unit,
|
|
21
|
+
show_clear_button = true,
|
|
22
|
+
onchange,
|
|
23
|
+
onclear,
|
|
24
|
+
...rest
|
|
25
|
+
}: {
|
|
26
|
+
label: string // Label text (supports HTML)
|
|
27
|
+
min_value?: number // Minimum value for filtering (undefined = unbounded)
|
|
28
|
+
max_value?: number // Maximum value for filtering (undefined = unbounded)
|
|
29
|
+
placeholders?: { min?: string; max?: string } // Placeholder text for min/max inputs
|
|
30
|
+
title?: string // Tooltip title for the label
|
|
31
|
+
histogram_data?: number[] // Data array for histogram visualization
|
|
32
|
+
histogram_height?: number // Height of histogram in pixels
|
|
33
|
+
histogram_color?: string // Color for histogram bars (unfilled data)
|
|
34
|
+
histogram_position?: `top` | `bottom` | `none` // Position of histogram relative to inputs, or 'none' to hide
|
|
35
|
+
log?: boolean // Use logarithmic scale for histogram y-axis
|
|
36
|
+
disabled?: boolean // Disable all inputs
|
|
37
|
+
unit?: string // Unit label to display after inputs
|
|
38
|
+
show_clear_button?: boolean // Show clear button when filters are active
|
|
39
|
+
onchange?: (min: number | undefined, max: number | undefined) => void // Callback when filter values change
|
|
40
|
+
onclear?: () => void // Callback when clear button is clicked (fires before onchange)
|
|
41
|
+
} & HTMLAttributes<HTMLDivElement> = $props()
|
|
42
|
+
|
|
43
|
+
let show_histogram = $derived(
|
|
44
|
+
histogram_position !== `none` && histogram_data?.length,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
// Active when either bound is set (undefined = unbounded)
|
|
48
|
+
let active = $derived(min_value !== undefined || max_value !== undefined)
|
|
49
|
+
let plain_label = $derived(label.replace(/<[^>]*>/g, ``))
|
|
50
|
+
|
|
51
|
+
let filtered_data = $derived.by(() => {
|
|
52
|
+
if (!histogram_data) return []
|
|
11
53
|
// undefined means unbounded (-Infinity for min, +Infinity for max)
|
|
12
|
-
const min = min_value ?? -Infinity
|
|
13
|
-
const max = max_value ?? Infinity
|
|
14
|
-
return histogram_data.filter((val) => val >= min && val <= max)
|
|
15
|
-
})
|
|
16
|
-
|
|
54
|
+
const min = min_value ?? -Infinity
|
|
55
|
+
const max = max_value ?? Infinity
|
|
56
|
+
return histogram_data.filter((val) => val >= min && val <= max)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
function onkeydown(event: KeyboardEvent): void {
|
|
17
60
|
if (event.key === `Enter`) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
clear_filter();
|
|
61
|
+
event.preventDefault()
|
|
62
|
+
;(event.target as HTMLInputElement).blur()
|
|
63
|
+
} else if (event.key === `Escape` && active) {
|
|
64
|
+
event.preventDefault()
|
|
65
|
+
clear_filter()
|
|
24
66
|
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function clear_filter(): void {
|
|
70
|
+
min_value = max_value = undefined
|
|
71
|
+
onclear?.()
|
|
72
|
+
onchange?.(undefined, undefined)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const axis_config: AxisConfig = {
|
|
32
76
|
ticks: 0,
|
|
33
77
|
label: ``,
|
|
34
78
|
grid_style: { style: `opacity: 0` },
|
|
35
79
|
tick: { label: { inside: true } },
|
|
36
80
|
color: `color-mix(in srgb, currentColor 60%, transparent)`,
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// x: [] satisfies DataSeries type requirement; Histogram bins on y values only
|
|
84
|
+
const series: DataSeries[] = $derived([
|
|
40
85
|
{ y: histogram_data ?? [], color: histogram_color, label: `All`, x: [] },
|
|
41
86
|
{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
87
|
+
y: filtered_data,
|
|
88
|
+
color: `var(--accent-color, #228be6)`,
|
|
89
|
+
label: `Filtered`,
|
|
90
|
+
x: [],
|
|
46
91
|
},
|
|
47
|
-
])
|
|
92
|
+
])
|
|
48
93
|
</script>
|
|
49
94
|
|
|
50
95
|
{#snippet histogram_snippet()}
|
|
@@ -76,7 +121,7 @@ const series = $derived([
|
|
|
76
121
|
{@render histogram_snippet()}
|
|
77
122
|
{/if}
|
|
78
123
|
<div class="filter-row">
|
|
79
|
-
<span {title} class="filter-label">{@html label}</span>
|
|
124
|
+
<span {title} class="filter-label">{@html sanitize_html(label)}</span>
|
|
80
125
|
<div class="filter-inputs">
|
|
81
126
|
<input
|
|
82
127
|
bind:value={min_value}
|