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,64 +1,94 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Icon from '../Icon.svelte'
|
|
3
|
+
import type { Snippet } from 'svelte'
|
|
4
|
+
import { untrack } from 'svelte'
|
|
5
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
title,
|
|
9
|
+
current_values,
|
|
10
|
+
children,
|
|
11
|
+
on_reset = () => {},
|
|
12
|
+
...rest
|
|
13
|
+
}: HTMLAttributes<HTMLElementTagNameMap[`section`]> & {
|
|
14
|
+
title: string
|
|
15
|
+
current_values: Record<string, unknown>
|
|
16
|
+
children: Snippet<
|
|
17
|
+
[{
|
|
18
|
+
current_values: Record<string, unknown>
|
|
19
|
+
has_changes: boolean
|
|
20
|
+
reference_values: Record<string, unknown>
|
|
21
|
+
}]
|
|
22
|
+
>
|
|
23
|
+
on_reset?: () => void
|
|
24
|
+
} = $props()
|
|
25
|
+
|
|
26
|
+
// Create a deep copy of current_values on mount to use as reference values
|
|
27
|
+
function deep_copy(obj: unknown): unknown {
|
|
28
|
+
if (obj === null || typeof obj !== `object`) return obj
|
|
29
|
+
if (obj instanceof Date) return new Date(obj.getTime())
|
|
30
|
+
if (obj instanceof RegExp) return new RegExp(obj)
|
|
12
31
|
if (Array.isArray(obj)) {
|
|
13
|
-
|
|
32
|
+
return obj.map((item) =>
|
|
33
|
+
typeof item === `object` && item !== null ? deep_copy(item) : item
|
|
34
|
+
)
|
|
14
35
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
36
|
+
|
|
37
|
+
const copy: Record<string, unknown> = {}
|
|
38
|
+
for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {
|
|
39
|
+
copy[key] = typeof value === `object` && value !== null
|
|
40
|
+
? deep_copy(value)
|
|
41
|
+
: value
|
|
20
42
|
}
|
|
21
|
-
return copy
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
43
|
+
return copy
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Capture initial values once at mount - must NOT be $derived or it tracks changes
|
|
47
|
+
const reference_values = untrack(() =>
|
|
48
|
+
deep_copy(current_values) as Record<string, unknown>
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
// Check if any values have changed from reference values
|
|
52
|
+
let has_changes = $derived.by(() => {
|
|
27
53
|
for (const [key, reference_value] of Object.entries(reference_values)) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// Handle undefined/null comparisons properly
|
|
46
|
-
if (reference_value === undefined && current_value === undefined)
|
|
47
|
-
continue;
|
|
48
|
-
if (reference_value === null && current_value === null)
|
|
49
|
-
continue;
|
|
50
|
-
// Basic comparison for primitives
|
|
51
|
-
if (current_value !== reference_value) {
|
|
52
|
-
return true;
|
|
54
|
+
const current_value = current_values[key]
|
|
55
|
+
|
|
56
|
+
// Deep comparison for arrays
|
|
57
|
+
if (Array.isArray(reference_value) && Array.isArray(current_value)) {
|
|
58
|
+
if (reference_value.length !== current_value.length) return true
|
|
59
|
+
if (
|
|
60
|
+
reference_value.some((val, idx) => {
|
|
61
|
+
const curr_val = current_value[idx]
|
|
62
|
+
// Handle nested objects/arrays in arrays
|
|
63
|
+
if (
|
|
64
|
+
typeof val === `object` && val !== null &&
|
|
65
|
+
typeof curr_val === `object` && curr_val !== null
|
|
66
|
+
) return JSON.stringify(val) !== JSON.stringify(curr_val) // Quick deep comparison fallback
|
|
67
|
+
return val !== curr_val
|
|
68
|
+
})
|
|
69
|
+
) {
|
|
70
|
+
return true
|
|
53
71
|
}
|
|
72
|
+
continue
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Handle undefined/null comparisons properly
|
|
76
|
+
if (reference_value === undefined && current_value === undefined) continue
|
|
77
|
+
if (reference_value === null && current_value === null) continue
|
|
78
|
+
|
|
79
|
+
// Basic comparison for primitives
|
|
80
|
+
if (current_value !== reference_value) {
|
|
81
|
+
return true
|
|
82
|
+
}
|
|
54
83
|
}
|
|
55
|
-
return false
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
event.
|
|
60
|
-
|
|
61
|
-
|
|
84
|
+
return false
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
function handle_reset(event: MouseEvent) {
|
|
88
|
+
event.stopPropagation()
|
|
89
|
+
event.preventDefault()
|
|
90
|
+
on_reset()
|
|
91
|
+
}
|
|
62
92
|
</script>
|
|
63
93
|
|
|
64
94
|
<h4 id="settings-section-title">
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Icon from '../Icon.svelte'
|
|
3
|
+
import type { IconName } from '../icons'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
title: string
|
|
7
|
+
subtitle: string
|
|
8
|
+
subpages: { href: string; title: string; description: string; icon: IconName }[]
|
|
9
|
+
}
|
|
10
|
+
const { title, subtitle, subpages }: Props = $props()
|
|
3
11
|
</script>
|
|
4
12
|
|
|
5
13
|
<h1>{title}</h1>
|
|
@@ -1,169 +1,214 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Icon from '../../Icon.svelte'
|
|
3
|
+
import { getContext, onMount } from 'svelte'
|
|
4
|
+
import JsonNode from './JsonNode.svelte'
|
|
5
|
+
import JsonValue from './JsonValue.svelte'
|
|
6
|
+
import type { JsonTreeContext } from './types'
|
|
7
|
+
import { JSON_TREE_CONTEXT_KEY } from './types'
|
|
8
|
+
import {
|
|
9
|
+
build_path,
|
|
10
|
+
estimate_byte_size,
|
|
11
|
+
format_byte_size,
|
|
12
|
+
format_preview,
|
|
13
|
+
get_child_count,
|
|
14
|
+
get_value_type,
|
|
15
|
+
is_expandable,
|
|
16
|
+
} from './utils'
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
node_key = null,
|
|
20
|
+
value,
|
|
21
|
+
path,
|
|
22
|
+
depth,
|
|
23
|
+
is_last = true,
|
|
24
|
+
}: {
|
|
25
|
+
node_key?: string | number | null
|
|
26
|
+
value: unknown
|
|
27
|
+
path: string
|
|
28
|
+
depth: number
|
|
29
|
+
is_last?: boolean
|
|
30
|
+
} = $props()
|
|
31
|
+
|
|
32
|
+
const ctx = getContext<JsonTreeContext>(JSON_TREE_CONTEXT_KEY)
|
|
33
|
+
|
|
34
|
+
onMount(() => {
|
|
10
35
|
// Register this path with context for keyboard navigation
|
|
11
36
|
if (ctx && path) {
|
|
12
|
-
|
|
13
|
-
|
|
37
|
+
ctx.register_path(path)
|
|
38
|
+
return () => ctx.unregister_path(path)
|
|
14
39
|
}
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
//
|
|
21
|
-
let
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Determine value type
|
|
43
|
+
let value_type = $derived(get_value_type(value))
|
|
44
|
+
|
|
45
|
+
// Check if this node is expandable
|
|
46
|
+
let expandable = $derived(is_expandable(value))
|
|
47
|
+
|
|
48
|
+
// Get child count for preview
|
|
49
|
+
let child_count = $derived(expandable ? get_child_count(value) : 0)
|
|
50
|
+
|
|
51
|
+
// Determine if this node should be collapsed
|
|
52
|
+
let is_collapsed = $derived.by(() => {
|
|
53
|
+
if (!expandable) return false
|
|
54
|
+
|
|
26
55
|
// Check if explicitly collapsed
|
|
27
|
-
if (ctx?.collapsed.has(path))
|
|
28
|
-
|
|
56
|
+
if (ctx?.collapsed.has(path)) return true
|
|
57
|
+
|
|
29
58
|
// Check if explicitly force-expanded (overrides auto-fold)
|
|
30
|
-
if (ctx?.force_expanded.has(path))
|
|
31
|
-
|
|
59
|
+
if (ctx?.force_expanded.has(path)) return false
|
|
60
|
+
|
|
32
61
|
// If depth >= default_fold_level, default to collapsed
|
|
33
|
-
const fold_level = ctx?.settings.default_fold_level ?? 2
|
|
34
|
-
if (depth >= fold_level)
|
|
35
|
-
|
|
62
|
+
const fold_level = ctx?.settings.default_fold_level ?? 2
|
|
63
|
+
if (depth >= fold_level) return true
|
|
64
|
+
|
|
36
65
|
// Check auto-fold thresholds
|
|
37
66
|
if (value_type === `array`) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return true;
|
|
67
|
+
const threshold = ctx?.settings.auto_fold_arrays ?? 10
|
|
68
|
+
if (child_count > threshold) return true
|
|
41
69
|
}
|
|
42
70
|
if (value_type === `object`) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return true;
|
|
71
|
+
const threshold = ctx?.settings.auto_fold_objects ?? 20
|
|
72
|
+
if (child_count > threshold) return true
|
|
46
73
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
let
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
|
|
75
|
+
return false
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// Note: Search highlighting is handled by CSS Highlight API in JsonTree.svelte
|
|
79
|
+
|
|
80
|
+
// Check if this node is focused
|
|
81
|
+
let is_focused = $derived(ctx?.focused_path === path)
|
|
82
|
+
|
|
83
|
+
// Check if this is the current search match being navigated
|
|
84
|
+
let is_current_match = $derived(ctx?.current_match_path === path)
|
|
85
|
+
|
|
86
|
+
// Check if this node is selected
|
|
87
|
+
let is_selected = $derived(ctx?.selected_paths.has(path) ?? false)
|
|
88
|
+
|
|
89
|
+
// Diff status for this node (null if no diff or unchanged)
|
|
90
|
+
let diff_status = $derived(ctx?.diff_map?.get(path)?.status ?? null)
|
|
91
|
+
|
|
92
|
+
// Estimated byte size for collapsed preview (only compute when collapsed)
|
|
93
|
+
let byte_size = $derived(
|
|
94
|
+
expandable && is_collapsed ? format_byte_size(estimate_byte_size(value)) : ``,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
// Toggle collapse state
|
|
98
|
+
function toggle_collapse(event?: MouseEvent) {
|
|
99
|
+
event?.stopPropagation()
|
|
63
100
|
if (ctx && expandable) {
|
|
64
|
-
|
|
101
|
+
ctx.toggle_collapse(path, is_collapsed)
|
|
65
102
|
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Toggle collapse recursively on double-click
|
|
106
|
+
function toggle_collapse_recursive(event: MouseEvent) {
|
|
107
|
+
event.stopPropagation()
|
|
70
108
|
if (ctx && expandable) {
|
|
71
|
-
|
|
72
|
-
|
|
109
|
+
// If collapsed, expand all; if expanded, collapse all
|
|
110
|
+
ctx.toggle_collapse_recursive(path, !is_collapsed)
|
|
73
111
|
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Focus this node
|
|
115
|
+
function focus_node() {
|
|
116
|
+
ctx?.set_focused(path)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Get children based on value type
|
|
120
|
+
function get_children(): Array<{ key: string | number; value: unknown }> {
|
|
121
|
+
if (!expandable) return []
|
|
122
|
+
|
|
83
123
|
if (value_type === `array`) {
|
|
84
|
-
|
|
124
|
+
return (value as unknown[]).map((val, idx) => ({ key: idx, value: val }))
|
|
85
125
|
}
|
|
126
|
+
|
|
86
127
|
if (value_type === `object`) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
128
|
+
let keys = Object.keys(value as Record<string, unknown>)
|
|
129
|
+
if (ctx?.settings.sort_keys) {
|
|
130
|
+
keys = keys.sort()
|
|
131
|
+
}
|
|
132
|
+
return keys.map((key) => ({
|
|
133
|
+
key,
|
|
134
|
+
value: (value as Record<string, unknown>)[key],
|
|
135
|
+
}))
|
|
95
136
|
}
|
|
137
|
+
|
|
96
138
|
if (value_type === `map`) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
139
|
+
const map = value as Map<unknown, unknown>
|
|
140
|
+
return Array.from(map.entries()).map(([key, val], idx) => ({
|
|
141
|
+
key: idx,
|
|
142
|
+
value: { key, value: val },
|
|
143
|
+
}))
|
|
102
144
|
}
|
|
145
|
+
|
|
103
146
|
if (value_type === `set`) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
147
|
+
return Array.from(value as Set<unknown>).map((val, idx) => ({
|
|
148
|
+
key: idx,
|
|
149
|
+
value: val,
|
|
150
|
+
}))
|
|
108
151
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
let
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
|
|
152
|
+
|
|
153
|
+
return []
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
let children = $derived(get_children())
|
|
157
|
+
|
|
158
|
+
// Ghost children: removed entries from diff (pre-computed in JsonTree for O(1) lookup)
|
|
159
|
+
let ghost_children = $derived.by(() => {
|
|
160
|
+
if (!expandable || is_collapsed) return []
|
|
161
|
+
const all_ghosts = ctx?.ghost_map.get(path) ?? []
|
|
162
|
+
if (all_ghosts.length === 0) return []
|
|
119
163
|
// Filter out ghosts whose keys already exist in current children
|
|
120
|
-
const existing_keys = new Set(children.map((child) => String(child.key)))
|
|
121
|
-
return all_ghosts.filter((ghost) => !existing_keys.has(String(ghost.key)))
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
let
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
164
|
+
const existing_keys = new Set(children.map((child) => String(child.key)))
|
|
165
|
+
return all_ghosts.filter((ghost) => !existing_keys.has(String(ghost.key)))
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
// Get bracket characters based on type
|
|
169
|
+
let open_bracket = $derived(value_type === `array` ? `[` : `{`)
|
|
170
|
+
let close_bracket = $derived(value_type === `array` ? `]` : `}`)
|
|
171
|
+
|
|
172
|
+
// Handle keyboard navigation
|
|
173
|
+
function handle_keydown(event: KeyboardEvent) {
|
|
174
|
+
if (!is_focused) return
|
|
175
|
+
|
|
130
176
|
if (event.key === `Enter` || event.key === ` `) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
event.preventDefault();
|
|
156
|
-
event.stopPropagation();
|
|
157
|
-
ctx?.copy_value(path, value);
|
|
177
|
+
event.preventDefault()
|
|
178
|
+
if (expandable) {
|
|
179
|
+
toggle_collapse()
|
|
180
|
+
} else {
|
|
181
|
+
ctx?.copy_value(path, value)
|
|
182
|
+
}
|
|
183
|
+
} else if (event.key === `ArrowRight`) {
|
|
184
|
+
event.preventDefault()
|
|
185
|
+
if (expandable && is_collapsed) {
|
|
186
|
+
toggle_collapse()
|
|
187
|
+
}
|
|
188
|
+
} else if (event.key === `ArrowLeft`) {
|
|
189
|
+
event.preventDefault()
|
|
190
|
+
if (expandable && !is_collapsed) {
|
|
191
|
+
toggle_collapse()
|
|
192
|
+
}
|
|
193
|
+
} else if (
|
|
194
|
+
(event.key === `c` || event.key === `C`) && (event.ctrlKey || event.metaKey)
|
|
195
|
+
) {
|
|
196
|
+
// When nodes are selected, let the tree-level handler do bulk copy
|
|
197
|
+
if (ctx?.selected_paths.size) return
|
|
198
|
+
event.preventDefault()
|
|
199
|
+
event.stopPropagation()
|
|
200
|
+
ctx?.copy_value(path, value)
|
|
158
201
|
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
$
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Element reference for focus management
|
|
205
|
+
let node_element: HTMLDivElement | undefined = $state()
|
|
206
|
+
|
|
207
|
+
$effect(() => {
|
|
163
208
|
if (is_focused && node_element) {
|
|
164
|
-
|
|
209
|
+
node_element.focus()
|
|
165
210
|
}
|
|
166
|
-
})
|
|
211
|
+
})
|
|
167
212
|
</script>
|
|
168
213
|
|
|
169
214
|
<div
|