matterviz 0.3.5 → 0.3.7
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/MillerIndexInput.svelte +5 -5
- package/dist/api/optimade.js +3 -3
- package/dist/brillouin/BrillouinZone.svelte +5 -2
- package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneExportPane.svelte +1 -3
- package/dist/brillouin/BrillouinZoneInfoPane.svelte +1 -1
- package/dist/brillouin/BrillouinZoneScene.svelte +5 -5
- package/dist/brillouin/compute.js +21 -21
- package/dist/brillouin/index.d.ts +1 -1
- package/dist/brillouin/index.js +0 -1
- package/dist/brillouin/types.d.ts +8 -13
- package/dist/chempot-diagram/ChemPotDiagram.svelte +3 -3
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +3 -4
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +33 -34
- package/dist/chempot-diagram/compute.js +1 -7
- package/dist/chempot-diagram/temperature.d.ts +1 -1
- package/dist/chempot-diagram/temperature.js +1 -3
- package/dist/chempot-diagram/types.d.ts +4 -9
- package/dist/colors/index.js +5 -5
- package/dist/composition/Composition.svelte +2 -1
- package/dist/composition/Formula.svelte +7 -4
- package/dist/composition/FormulaFilter.svelte +1 -3
- package/dist/composition/format.js +4 -4
- package/dist/composition/parse.d.ts +2 -1
- package/dist/composition/parse.js +61 -46
- package/dist/convex-hull/ConvexHull2D.svelte +62 -51
- package/dist/convex-hull/ConvexHull3D.svelte +101 -90
- package/dist/convex-hull/ConvexHull4D.svelte +70 -58
- package/dist/convex-hull/ConvexHullControls.svelte +24 -35
- package/dist/convex-hull/ConvexHullInfoPane.svelte +8 -5
- package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +2 -0
- package/dist/convex-hull/ConvexHullStats.svelte +9 -2
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +2 -0
- package/dist/convex-hull/GasPressureControls.svelte +7 -7
- package/dist/convex-hull/StructurePopup.svelte +65 -30
- package/dist/convex-hull/StructurePopup.svelte.d.ts +6 -6
- package/dist/convex-hull/TemperatureSlider.svelte +8 -5
- package/dist/convex-hull/barycentric-coords.d.ts +2 -2
- package/dist/convex-hull/barycentric-coords.js +2 -2
- package/dist/convex-hull/gas-thermodynamics.js +2 -4
- package/dist/convex-hull/helpers.d.ts +13 -2
- package/dist/convex-hull/helpers.js +37 -16
- package/dist/convex-hull/index.d.ts +1 -0
- package/dist/convex-hull/index.js +1 -0
- package/dist/convex-hull/thermodynamics.d.ts +2 -1
- package/dist/convex-hull/thermodynamics.js +7 -7
- package/dist/convex-hull/types.d.ts +15 -15
- package/dist/effects.svelte.d.ts +12 -0
- package/dist/effects.svelte.js +37 -0
- package/dist/element/BohrAtom.svelte +4 -4
- package/dist/element/data.json.gz.d.ts +3 -1
- package/dist/element/index.d.ts +1 -1
- package/dist/element/index.js +0 -1
- package/dist/fermi-surface/FermiSurface.svelte +4 -4
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte +15 -19
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +8 -6
- package/dist/fermi-surface/compute.js +2 -2
- package/dist/fermi-surface/export.js +13 -26
- package/dist/fermi-surface/parse.js +8 -12
- package/dist/fermi-surface/types.d.ts +2 -5
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +21 -3
- package/dist/heatmap-matrix/index.js +6 -6
- package/dist/io/decompress.d.ts +2 -1
- package/dist/io/decompress.js +1 -1
- package/dist/io/export.js +1 -1
- package/dist/io/index.d.ts +1 -1
- package/dist/io/index.js +0 -1
- package/dist/io/url-drop.js +7 -1
- package/dist/isosurface/IsosurfaceControls.svelte +11 -25
- package/dist/isosurface/slice.js +1 -1
- package/dist/isosurface/types.js +12 -12
- package/dist/labels.d.ts +1 -1
- package/dist/labels.js +14 -11
- package/dist/layout/InfoTag.svelte +6 -4
- package/dist/layout/PropertyFilter.svelte +4 -2
- package/dist/layout/json-tree/JsonTree.svelte +22 -14
- package/dist/layout/json-tree/JsonValue.svelte +2 -2
- package/dist/layout/json-tree/types.d.ts +3 -2
- package/dist/layout/json-tree/types.js +0 -1
- package/dist/layout/json-tree/utils.d.ts +4 -4
- package/dist/layout/json-tree/utils.js +12 -20
- package/dist/marching-cubes.js +13 -15
- package/dist/math.d.ts +11 -1
- package/dist/math.js +15 -6
- package/dist/overlays/DragControlTab.svelte +98 -0
- package/dist/overlays/DragControlTab.svelte.d.ts +8 -0
- package/dist/overlays/DraggablePane.svelte +7 -84
- package/dist/overlays/index.d.ts +1 -0
- package/dist/overlays/index.js +1 -0
- package/dist/periodic-table/PeriodicTable.svelte +11 -11
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +4 -2
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramControls.svelte +4 -9
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +2 -10
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +2 -3
- package/dist/phase-diagram/TdbInfoPanel.svelte +3 -3
- package/dist/phase-diagram/build-diagram.js +11 -18
- package/dist/phase-diagram/diagram-input.d.ts +5 -9
- package/dist/phase-diagram/index.d.ts +2 -2
- package/dist/phase-diagram/index.js +0 -2
- package/dist/phase-diagram/parse.d.ts +2 -2
- package/dist/phase-diagram/parse.js +6 -10
- package/dist/phase-diagram/svg-to-diagram.js +15 -15
- package/dist/phase-diagram/types.d.ts +5 -11
- package/dist/phase-diagram/utils.d.ts +2 -2
- package/dist/phase-diagram/utils.js +9 -11
- package/dist/plot/BarPlot.svelte +162 -314
- package/dist/plot/BarPlot.svelte.d.ts +5 -4
- package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/BinnedScatterPlot.svelte +1114 -0
- package/dist/plot/BinnedScatterPlot.svelte.d.ts +66 -0
- package/dist/plot/ColorBar.svelte +19 -17
- package/dist/plot/ColorBar.svelte.d.ts +1 -1
- package/dist/plot/FillArea.svelte +2 -4
- package/dist/plot/FillArea.svelte.d.ts +1 -1
- package/dist/plot/Histogram.svelte +167 -281
- package/dist/plot/Histogram.svelte.d.ts +1 -1
- package/dist/plot/HistogramControls.svelte.d.ts +1 -1
- package/dist/plot/InteractiveAxisLabel.svelte +5 -3
- package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
- package/dist/plot/PlotAxis.svelte +169 -0
- package/dist/plot/PlotAxis.svelte.d.ts +24 -0
- package/dist/plot/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/ReferenceLine3D.svelte +53 -51
- package/dist/plot/ReferencePlane.svelte +39 -42
- package/dist/plot/ScatterPlot.svelte +300 -367
- package/dist/plot/ScatterPlot.svelte.d.ts +8 -5
- package/dist/plot/ScatterPlot3D.svelte +33 -6
- package/dist/plot/ScatterPlot3D.svelte.d.ts +3 -2
- package/dist/plot/ScatterPlot3DControls.svelte +9 -9
- package/dist/plot/ScatterPlotControls.svelte +3 -4
- package/dist/plot/ScatterPoint.svelte +18 -27
- package/dist/plot/ScatterPoint.svelte.d.ts +4 -3
- package/dist/plot/Surface3D.svelte +4 -7
- package/dist/plot/ZeroLines.svelte +2 -1
- package/dist/plot/ZeroLines.svelte.d.ts +2 -1
- package/dist/plot/ZoomRect.svelte +2 -2
- package/dist/plot/ZoomRect.svelte.d.ts +3 -3
- package/dist/plot/adaptive-density.d.ts +69 -0
- package/dist/plot/adaptive-density.js +191 -0
- package/dist/plot/auto-place.d.ts +43 -0
- package/dist/plot/auto-place.js +122 -0
- package/dist/plot/axis-utils.js +3 -5
- package/dist/plot/binned-scatter-types.d.ts +59 -0
- package/dist/plot/binned-scatter-types.js +1 -0
- package/dist/plot/data-cleaning.js +1 -1
- package/dist/plot/data-transform.js +1 -1
- package/dist/plot/fill-utils.d.ts +4 -9
- package/dist/plot/fill-utils.js +29 -44
- package/dist/plot/index.d.ts +4 -0
- package/dist/plot/index.js +2 -0
- package/dist/plot/interactions.d.ts +4 -4
- package/dist/plot/interactions.js +4 -3
- package/dist/plot/layout.d.ts +20 -2
- package/dist/plot/layout.js +59 -16
- package/dist/plot/reference-line.d.ts +1 -1
- package/dist/plot/reference-line.js +9 -11
- package/dist/plot/scales.d.ts +1 -1
- package/dist/plot/scales.js +20 -23
- package/dist/plot/types.d.ts +30 -58
- package/dist/plot/types.js +2 -6
- package/dist/plot/utils/label-placement.d.ts +24 -3
- package/dist/plot/utils/label-placement.js +82 -12
- package/dist/plot/utils/series-visibility.d.ts +8 -2
- package/dist/plot/utils/series-visibility.js +23 -5
- package/dist/rdf/RdfPlot.svelte +5 -5
- package/dist/rdf/calc-rdf.js +3 -3
- package/dist/sanitize.d.ts +2 -0
- package/dist/sanitize.js +2 -0
- package/dist/spectral/Bands.svelte +1 -1
- package/dist/spectral/BandsAndDos.svelte +22 -16
- package/dist/spectral/BrillouinBandsDos.svelte +20 -16
- package/dist/spectral/Dos.svelte +1 -1
- package/dist/spectral/helpers.d.ts +4 -2
- package/dist/spectral/helpers.js +44 -35
- package/dist/spectral/index.d.ts +1 -1
- package/dist/spectral/index.js +0 -1
- package/dist/structure/AtomLegend.svelte +23 -6
- package/dist/structure/AtomLegend.svelte.d.ts +1 -0
- package/dist/structure/CanvasTooltip.svelte +9 -9
- package/dist/structure/CanvasTooltip.svelte.d.ts +1 -1
- package/dist/structure/CellSelect.svelte +14 -16
- package/dist/structure/Structure.svelte +317 -68
- package/dist/structure/Structure.svelte.d.ts +4 -2
- package/dist/structure/StructureControls.svelte +20 -45
- package/dist/structure/StructureExportPane.svelte +2 -1
- package/dist/structure/StructureInfoPane.svelte +10 -8
- package/dist/structure/StructureScene.svelte +527 -177
- package/dist/structure/StructureScene.svelte.d.ts +5 -2
- package/dist/structure/atom-properties.js +4 -4
- package/dist/structure/bond-order-perception.js +115 -98
- package/dist/structure/bonding.d.ts +27 -1
- package/dist/structure/bonding.js +187 -16
- package/dist/structure/export.js +1 -1
- package/dist/structure/index.d.ts +3 -2
- package/dist/structure/index.js +0 -2
- package/dist/structure/parse.js +88 -59
- package/dist/symmetry/WyckoffTable.svelte +7 -0
- package/dist/symmetry/index.js +13 -14
- package/dist/table/HeatmapTable.svelte +45 -66
- package/dist/table/HeatmapTable.svelte.d.ts +1 -1
- package/dist/table/ToggleMenu.svelte +19 -10
- package/dist/theme/themes.mjs +12 -0
- package/dist/tooltip/index.d.ts +1 -1
- package/dist/tooltip/index.js +0 -1
- package/dist/trajectory/Trajectory.svelte +43 -15
- package/dist/trajectory/TrajectoryInfoPane.svelte +2 -2
- package/dist/trajectory/extract.js +1 -1
- package/dist/trajectory/frame-reader.js +4 -4
- package/dist/trajectory/helpers.d.ts +5 -4
- package/dist/trajectory/helpers.js +9 -17
- package/dist/trajectory/index.d.ts +2 -2
- package/dist/trajectory/index.js +2 -2
- package/dist/trajectory/parse/ase.js +4 -4
- package/dist/trajectory/parse/hdf5.js +1 -1
- package/dist/trajectory/parse/index.js +2 -3
- package/dist/trajectory/parse/lammps.js +1 -1
- package/dist/trajectory/parse/vasp.js +1 -1
- package/dist/trajectory/plotting.d.ts +1 -1
- package/dist/trajectory/plotting.js +38 -38
- package/dist/trajectory/types.d.ts +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +9 -0
- package/dist/xrd/calc-xrd.js +3 -4
- package/dist/xrd/parse.js +1 -1
- package/package.json +42 -22
package/dist/sanitize.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export declare function sanitize_html(html: unknown): string;
|
|
2
|
+
export declare const compact_formula: (formula: string) => string;
|
|
2
3
|
export declare const sanitize_formula: (formula: string, use_subscripts?: boolean) => string;
|
|
4
|
+
export declare const sanitize_compact_formula: (formula: string, use_subscripts?: boolean) => string;
|
|
3
5
|
export declare const sanitize_svg: (html: string) => string;
|
|
4
6
|
export declare const sanitize_icon_svg: (html: string) => string;
|
package/dist/sanitize.js
CHANGED
|
@@ -91,8 +91,10 @@ export function sanitize_html(html) {
|
|
|
91
91
|
] });
|
|
92
92
|
return dp.sanitize(safe, { ALLOWED_TAGS: SAFE_TAGS, ALLOWED_ATTR: SAFE_ATTRS });
|
|
93
93
|
}
|
|
94
|
+
export const compact_formula = (formula) => formula.replaceAll(/\s+/g, ``);
|
|
94
95
|
// Sanitize a chemical formula with optional subscript formatting
|
|
95
96
|
export const sanitize_formula = (formula, use_subscripts = true) => sanitize_html(format_formula_html(formula, use_subscripts));
|
|
97
|
+
export const sanitize_compact_formula = (formula, use_subscripts = true) => sanitize_formula(compact_formula(formula), use_subscripts);
|
|
96
98
|
const SVG_TEXT_TAGS = [`tspan`, `title`];
|
|
97
99
|
// oxfmt-ignore
|
|
98
100
|
const SVG_TEXT_ATTRS = [`dx`, `dy`, `x`, `y`, `fill`, `font-size`, `font-weight`, `baseline-shift`];
|
|
@@ -883,7 +883,7 @@
|
|
|
883
883
|
{/each}
|
|
884
884
|
|
|
885
885
|
<!-- Symmetry point vertical lines (filter NaN from scale) -->
|
|
886
|
-
{#each Object.keys(x_axis_ticks).map(Number).map((
|
|
886
|
+
{#each Object.keys(x_axis_ticks).map(Number).map((tick) => x_scale_fn(tick)).filter(
|
|
887
887
|
Number.isFinite,
|
|
888
888
|
) as
|
|
889
889
|
scaled_x
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import Bands from './Bands.svelte'
|
|
8
8
|
import Dos from './Dos.svelte'
|
|
9
9
|
import {
|
|
10
|
+
axis_with_range,
|
|
10
11
|
compute_frequency_range,
|
|
11
12
|
detect_zoom_change,
|
|
12
13
|
extract_efermi,
|
|
@@ -40,10 +41,26 @@
|
|
|
40
41
|
)
|
|
41
42
|
let fermi_level = $derived(extract_efermi(band_structs) ?? extract_efermi(doses))
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
const bands_default_axis = (range = shared_frequency_range): AxisConfig =>
|
|
45
|
+
shared_y_axis ? axis_with_range(bands_props.y_axis, range) : { ...bands_props.y_axis }
|
|
46
|
+
const dos_default_axis = (range = shared_frequency_range): AxisConfig =>
|
|
47
|
+
shared_y_axis ? axis_with_range(dos_props.y_axis, range, ``) : {
|
|
48
|
+
label: ``,
|
|
49
|
+
...dos_props.y_axis,
|
|
50
|
+
}
|
|
51
|
+
|
|
44
52
|
let synced_zoom_range = $state<Vec2 | null>(null)
|
|
45
|
-
let bands_y_axis = $state<AxisConfig>(
|
|
46
|
-
let dos_y_axis = $state<AxisConfig>(
|
|
53
|
+
let bands_y_axis = $state<AxisConfig>(bands_default_axis())
|
|
54
|
+
let dos_y_axis = $state<AxisConfig>(dos_default_axis())
|
|
55
|
+
let prev_sources: unknown[] | undefined
|
|
56
|
+
$effect(() => {
|
|
57
|
+
const sources = [band_structs, doses, shared_y_axis, bands_props.y_axis, dos_props.y_axis]
|
|
58
|
+
if (prev_sources?.every((source, idx) => source === sources[idx])) return
|
|
59
|
+
prev_sources = sources
|
|
60
|
+
synced_zoom_range = null
|
|
61
|
+
bands_y_axis = bands_default_axis()
|
|
62
|
+
dos_y_axis = dos_default_axis()
|
|
63
|
+
})
|
|
47
64
|
|
|
48
65
|
// Detect zoom changes and sync between components (runs first to capture child updates)
|
|
49
66
|
$effect(() => {
|
|
@@ -67,12 +84,7 @@
|
|
|
67
84
|
return
|
|
68
85
|
}
|
|
69
86
|
// Only include range if it's valid (don't override child's auto-range with undefined)
|
|
70
|
-
bands_y_axis =
|
|
71
|
-
? {
|
|
72
|
-
...bands_props.y_axis,
|
|
73
|
-
...(is_valid_range(base_range) && { range: base_range }),
|
|
74
|
-
}
|
|
75
|
-
: { ...bands_props.y_axis }
|
|
87
|
+
bands_y_axis = bands_default_axis(base_range)
|
|
76
88
|
})
|
|
77
89
|
|
|
78
90
|
// Propagate synced range to DOS y-axis (untrack current to avoid overwriting child zoom)
|
|
@@ -85,13 +97,7 @@
|
|
|
85
97
|
return
|
|
86
98
|
}
|
|
87
99
|
// Only include range if it's valid (don't override child's auto-range with undefined)
|
|
88
|
-
dos_y_axis =
|
|
89
|
-
? {
|
|
90
|
-
label: ``,
|
|
91
|
-
...dos_props.y_axis,
|
|
92
|
-
...(is_valid_range(base_range) && { range: base_range }),
|
|
93
|
-
}
|
|
94
|
-
: { label: ``, ...dos_props.y_axis }
|
|
100
|
+
dos_y_axis = dos_default_axis(base_range)
|
|
95
101
|
})
|
|
96
102
|
|
|
97
103
|
let hovered_frequency = $state<number | null>(null)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { BrillouinZone, reciprocal_lattice } from '../brillouin'
|
|
3
3
|
import type { Vec2, Vec3 } from '../math'
|
|
4
|
-
import type { InternalPoint } from '../plot'
|
|
4
|
+
import type { InternalPoint, ScatterHandlerEvent } from '../plot'
|
|
5
5
|
import type { AxisConfig } from '../plot/types'
|
|
6
6
|
import type { Crystal } from '../structure'
|
|
7
7
|
import type { ComponentProps, Snippet } from 'svelte'
|
|
@@ -101,10 +101,23 @@
|
|
|
101
101
|
: `phone`,
|
|
102
102
|
)
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
const bands_default_axis = (range = shared_frequency_range): AxisConfig =>
|
|
105
|
+
helpers.axis_with_range(bands_props.y_axis, range)
|
|
106
|
+
const dos_default_axis = (range = shared_frequency_range): AxisConfig =>
|
|
107
|
+
is_desktop ? helpers.axis_with_range(dos_props.y_axis, range, ``) : { ...dos_props.y_axis }
|
|
108
|
+
|
|
105
109
|
let synced_zoom_range = $state<Vec2 | null>(null)
|
|
106
|
-
let bands_y_axis = $state<AxisConfig>(
|
|
107
|
-
let dos_y_axis = $state<AxisConfig>(
|
|
110
|
+
let bands_y_axis = $state<AxisConfig>(bands_default_axis())
|
|
111
|
+
let dos_y_axis = $state<AxisConfig>(dos_default_axis())
|
|
112
|
+
let prev_sources: unknown[] | undefined
|
|
113
|
+
$effect(() => {
|
|
114
|
+
const sources = [band_structs, doses, is_desktop, bands_props.y_axis, dos_props.y_axis]
|
|
115
|
+
if (prev_sources?.every((source, idx) => source === sources[idx])) return
|
|
116
|
+
prev_sources = sources
|
|
117
|
+
synced_zoom_range = null
|
|
118
|
+
bands_y_axis = bands_default_axis()
|
|
119
|
+
dos_y_axis = dos_default_axis()
|
|
120
|
+
})
|
|
108
121
|
|
|
109
122
|
// Detect zoom changes and sync between components (runs first to capture child updates)
|
|
110
123
|
$effect(() => {
|
|
@@ -130,10 +143,7 @@
|
|
|
130
143
|
!helpers.ranges_equal(current_range, base_range)
|
|
131
144
|
) return
|
|
132
145
|
// Only include range if it's valid (don't override child's auto-range with undefined)
|
|
133
|
-
bands_y_axis =
|
|
134
|
-
...bands_props.y_axis,
|
|
135
|
-
...(helpers.is_valid_range(base_range) && { range: base_range }),
|
|
136
|
-
}
|
|
146
|
+
bands_y_axis = bands_default_axis(base_range)
|
|
137
147
|
})
|
|
138
148
|
|
|
139
149
|
// Propagate synced range to DOS y-axis (untrack current to avoid overwriting child zoom)
|
|
@@ -147,13 +157,7 @@
|
|
|
147
157
|
!helpers.ranges_equal(current_range, base_range)
|
|
148
158
|
) return
|
|
149
159
|
// Only include range if it's valid (don't override child's auto-range with undefined)
|
|
150
|
-
dos_y_axis =
|
|
151
|
-
? {
|
|
152
|
-
label: ``,
|
|
153
|
-
...dos_props.y_axis,
|
|
154
|
-
...(helpers.is_valid_range(base_range) && { range: base_range }),
|
|
155
|
-
}
|
|
156
|
-
: { ...dos_props.y_axis }
|
|
160
|
+
dos_y_axis = dos_default_axis(base_range)
|
|
157
161
|
})
|
|
158
162
|
|
|
159
163
|
let hovered_frequency = $state<number | null>(null)
|
|
@@ -174,7 +178,7 @@
|
|
|
174
178
|
bind:y_axis={bands_y_axis}
|
|
175
179
|
bind:x_positions={bands_x_positions}
|
|
176
180
|
reference_frequency={hovered_frequency}
|
|
177
|
-
on_point_hover={(event) => {
|
|
181
|
+
on_point_hover={(event: ScatterHandlerEvent | null) => {
|
|
178
182
|
hovered_band_point = event?.point ?? null
|
|
179
183
|
bands_props.on_point_hover?.(event)
|
|
180
184
|
}}
|
package/dist/spectral/Dos.svelte
CHANGED
|
@@ -239,7 +239,7 @@
|
|
|
239
239
|
|
|
240
240
|
// For mirror mode, negate the densities
|
|
241
241
|
if (effective_spin_mode === `mirror`) {
|
|
242
|
-
densities_down = densities_down.map((
|
|
242
|
+
densities_down = densities_down.map((density) => -density)
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
// For stacked plots with overlay mode, use separate spin-down cumulative
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Matrix3x3, Vec2, Vec3 } from '../math';
|
|
2
|
+
import type { AxisConfig } from '../plot/types';
|
|
2
3
|
import type * as types from './types';
|
|
3
4
|
import type { RibbonConfig } from './types';
|
|
4
5
|
export declare const is_valid_range: (range: unknown) => range is Vec2;
|
|
5
6
|
export declare const ranges_equal: (a: Vec2 | undefined | null, b: Vec2 | undefined | null, tol?: number) => boolean;
|
|
7
|
+
export declare const axis_with_range: (axis: AxisConfig | undefined, range: Vec2 | undefined, label?: string) => AxisConfig;
|
|
6
8
|
export declare function detect_zoom_change(bands_range: unknown, dos_range: unknown, shared_range: Vec2, current_synced: Vec2 | null, dos_enabled?: boolean): Vec2 | null | undefined;
|
|
7
9
|
export declare const IMAGINARY_MODE_NOISE_THRESHOLD = 0.005;
|
|
8
10
|
export declare function pretty_sym_point(symbol: string): string;
|
|
@@ -89,7 +91,7 @@ export declare const DEFAULT_SIGMA = 0;
|
|
|
89
91
|
export declare const DEFAULT_NORMALIZE: types.NormalizationMode;
|
|
90
92
|
export declare const DEFAULT_UNITS: types.FrequencyUnit;
|
|
91
93
|
export declare function format_sigma(val: number): string;
|
|
92
|
-
export declare
|
|
94
|
+
export declare const validate_sigma_range: ([min, max]: [number, number]) => [number, number];
|
|
93
95
|
export declare function calculate_sigma_step(range: [number, number]): number;
|
|
94
96
|
export interface BandPointMeta extends Record<string, unknown> {
|
|
95
97
|
band_idx: number;
|
package/dist/spectral/helpers.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Helper utilities for band structure and DOS data processing
|
|
2
2
|
import { SUBSCRIPT_MAP } from '../labels';
|
|
3
3
|
import { centered_frac, euclidean_dist } from '../math';
|
|
4
|
+
const is_subscript_key = (key) => key in SUBSCRIPT_MAP;
|
|
4
5
|
// Check if range is a valid [min, max] tuple (strict 2-element array of finite numbers)
|
|
5
6
|
export const is_valid_range = (range) => Array.isArray(range) &&
|
|
6
7
|
range.length === 2 &&
|
|
@@ -16,6 +17,11 @@ export const ranges_equal = (a, b, tol = 0.001) => {
|
|
|
16
17
|
Math.abs(a[0] - b[0]) <= safe_tol &&
|
|
17
18
|
Math.abs(a[1] - b[1]) <= safe_tol);
|
|
18
19
|
};
|
|
20
|
+
export const axis_with_range = (axis, range, label) => ({
|
|
21
|
+
...axis,
|
|
22
|
+
...(label !== undefined && { label }),
|
|
23
|
+
...(is_valid_range(range) && { range }),
|
|
24
|
+
});
|
|
19
25
|
// Detect which plot triggered a zoom change and return the new synced range.
|
|
20
26
|
// Returns null to reset to shared range, undefined for no change, or Vec2 for new zoom.
|
|
21
27
|
export function detect_zoom_change(bands_range, dos_range, shared_range, current_synced, dos_enabled = true) {
|
|
@@ -72,7 +78,7 @@ export function pretty_sym_point(symbol) {
|
|
|
72
78
|
.replace(/(\p{L})(\d+)/gu, (_, letter, num) => letter +
|
|
73
79
|
num
|
|
74
80
|
.split(``)
|
|
75
|
-
.map((digit) => SUBSCRIPT_MAP[digit]
|
|
81
|
+
.map((digit) => (is_subscript_key(digit) ? SUBSCRIPT_MAP[digit] : digit))
|
|
76
82
|
.join(``));
|
|
77
83
|
}
|
|
78
84
|
// Create segment key from start and end labels
|
|
@@ -81,7 +87,7 @@ export const get_segment_key = (start_label, end_label) => `${start_label ?? `nu
|
|
|
81
87
|
export const get_ordered_segments = (band_struct, segments) => {
|
|
82
88
|
if (!band_struct)
|
|
83
89
|
return Array.from(segments);
|
|
84
|
-
const ordered = band_struct.branches.map((
|
|
90
|
+
const ordered = band_struct.branches.map((branch) => get_segment_key(band_struct.qpoints[branch.start_index]?.label ?? undefined, band_struct.qpoints[branch.end_index]?.label ?? undefined));
|
|
85
91
|
const remaining = Array.from(segments).filter((seg) => !ordered.includes(seg));
|
|
86
92
|
return [...ordered, ...remaining];
|
|
87
93
|
};
|
|
@@ -105,17 +111,23 @@ export function scale_segment_distances(segment_distances, x_start, x_end) {
|
|
|
105
111
|
// primitive-typed keys (opacity, max_width, scale, color) exist at the top level.
|
|
106
112
|
export function get_ribbon_config(ribbon_config, label) {
|
|
107
113
|
const defaults = { opacity: 0.3, max_width: 6, scale: 1 };
|
|
114
|
+
const config_record = ribbon_config;
|
|
108
115
|
// Check for primitive config values (not objects) to distinguish single vs per-structure config
|
|
109
|
-
const
|
|
110
|
-
|
|
116
|
+
const has_primitive = [`opacity`, `max_width`, `scale`, `color`].some((key) => {
|
|
117
|
+
const value = config_record[key];
|
|
118
|
+
return value !== undefined && typeof value !== `object`;
|
|
119
|
+
});
|
|
111
120
|
if (has_primitive) {
|
|
112
121
|
// Single global config with primitive values - apply to all structures
|
|
113
122
|
return { ...defaults, ...ribbon_config };
|
|
114
123
|
}
|
|
115
124
|
// Otherwise, treat as Record<string, RibbonConfig> and look up by label
|
|
116
125
|
// Empty label skips lookup and uses defaults only
|
|
117
|
-
const
|
|
118
|
-
return {
|
|
126
|
+
const label_config = label ? config_record[label] : undefined;
|
|
127
|
+
return {
|
|
128
|
+
...defaults,
|
|
129
|
+
...(label_config && typeof label_config === `object` ? label_config : {}),
|
|
130
|
+
};
|
|
119
131
|
}
|
|
120
132
|
// Extract tick positions and labels for a band structure plot.
|
|
121
133
|
export function get_band_xaxis_ticks(band_struct, branches = []) {
|
|
@@ -132,7 +144,7 @@ export function get_band_xaxis_ticks(band_struct, branches = []) {
|
|
|
132
144
|
// Find which branch this point belongs to
|
|
133
145
|
const branch_names = band_struct.branches
|
|
134
146
|
.filter((branch) => branch.start_index <= idx && idx <= branch.end_index)
|
|
135
|
-
.map((
|
|
147
|
+
.map((branch) => branch.name);
|
|
136
148
|
const this_branch = branch_names[0] || null;
|
|
137
149
|
if (point.label !== prev_label && prev_branch !== this_branch) {
|
|
138
150
|
// Branch transition - combine labels
|
|
@@ -279,10 +291,7 @@ export function clear_smearing_cache() {
|
|
|
279
291
|
}
|
|
280
292
|
// Type guards for pymatgen qpoint formats
|
|
281
293
|
const is_vec3 = (val) => Array.isArray(val) && val.length >= 3 && val.slice(0, 3).every(Number.isFinite);
|
|
282
|
-
const is_kpoint = (val) => !!val &&
|
|
283
|
-
typeof val === `object` &&
|
|
284
|
-
`frac_coords` in val &&
|
|
285
|
-
is_vec3(val.frac_coords);
|
|
294
|
+
const is_kpoint = (val) => !!val && typeof val === `object` && `frac_coords` in val && is_vec3(val.frac_coords);
|
|
286
295
|
const is_pymatgen_format = (obj) => {
|
|
287
296
|
// Check for explicit pymatgen markers
|
|
288
297
|
if (typeof obj[`@class`] === `string` || typeof obj[`@module`] === `string`) {
|
|
@@ -381,17 +390,19 @@ function convert_pymatgen_band_structure(pmg) {
|
|
|
381
390
|
!raw_bands.length)
|
|
382
391
|
return null;
|
|
383
392
|
const qpoints = raw_qpts
|
|
384
|
-
.map((
|
|
385
|
-
.filter((
|
|
393
|
+
.map((qpoint) => parse_qpoint(qpoint, labels_dict))
|
|
394
|
+
.filter((qpoint) => qpoint !== null);
|
|
386
395
|
if (!qpoints.length)
|
|
387
396
|
return null;
|
|
388
397
|
// Step distances and discontinuity detection (5x median threshold)
|
|
389
398
|
const steps = qpoints
|
|
390
399
|
.slice(1)
|
|
391
|
-
.map((
|
|
400
|
+
.map((qpoint, idx) => euclidean_dist(qpoints[idx].frac_coords, qpoint.frac_coords));
|
|
392
401
|
const sorted = steps.slice().sort((a, b) => a - b);
|
|
393
402
|
const threshold = (sorted[Math.floor(sorted.length / 2)] ?? 0) * 5;
|
|
394
|
-
const disc_set = new Set(steps
|
|
403
|
+
const disc_set = new Set(steps
|
|
404
|
+
.map((step, idx) => (step > threshold ? idx + 1 : -1))
|
|
405
|
+
.filter((disc_idx) => disc_idx >= 0));
|
|
395
406
|
// Cumulative distance (skip discontinuities)
|
|
396
407
|
const distance = steps.reduce((acc, step, idx) => [...acc, disc_set.has(idx + 1) ? acc[idx] : acc[idx] + step], [0]);
|
|
397
408
|
// Use pymatgen's branches if available - they correctly handle discontinuities
|
|
@@ -400,11 +411,11 @@ function convert_pymatgen_band_structure(pmg) {
|
|
|
400
411
|
let branches = [];
|
|
401
412
|
if (Array.isArray(pmg_branches) && pmg_branches.length > 0) {
|
|
402
413
|
// Validate and use pymatgen branches directly
|
|
403
|
-
branches = pmg_branches.filter((
|
|
404
|
-
typeof
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
414
|
+
branches = pmg_branches.filter((branch) => typeof branch.start_index === `number` &&
|
|
415
|
+
typeof branch.end_index === `number` &&
|
|
416
|
+
branch.start_index >= 0 &&
|
|
417
|
+
branch.end_index < qpoints.length &&
|
|
418
|
+
branch.start_index <= branch.end_index);
|
|
408
419
|
}
|
|
409
420
|
// Fallback: infer branches from discontinuities when none provided or all invalid
|
|
410
421
|
if (branches.length === 0) {
|
|
@@ -426,7 +437,7 @@ function convert_pymatgen_band_structure(pmg) {
|
|
|
426
437
|
name: `${start_label}-${end_label}`,
|
|
427
438
|
};
|
|
428
439
|
})
|
|
429
|
-
.filter((
|
|
440
|
+
.filter((branch) => branch.start_index <= branch.end_index);
|
|
430
441
|
}
|
|
431
442
|
if (!branches.length) {
|
|
432
443
|
branches.push({ start_index: 0, end_index: qpoints.length - 1, name: `path` });
|
|
@@ -482,11 +493,11 @@ export function normalize_band_structure(bs) {
|
|
|
482
493
|
const n_qpts = qpoints.length;
|
|
483
494
|
if (distance.length !== n_qpts ||
|
|
484
495
|
bands.some((band) => !Array.isArray(band) || band.length !== n_qpts) ||
|
|
485
|
-
branches.some((
|
|
486
|
-
typeof
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
496
|
+
branches.some((branch) => typeof branch.start_index !== `number` ||
|
|
497
|
+
typeof branch.end_index !== `number` ||
|
|
498
|
+
branch.start_index < 0 ||
|
|
499
|
+
branch.end_index >= n_qpts ||
|
|
500
|
+
branch.start_index > branch.end_index))
|
|
490
501
|
return null;
|
|
491
502
|
return band_struct;
|
|
492
503
|
}
|
|
@@ -522,7 +533,7 @@ export function normalize_dos(dos, options = {}) {
|
|
|
522
533
|
let final_frequencies = frequencies;
|
|
523
534
|
if (auto_convert_units && max_freq > 100) {
|
|
524
535
|
// Likely in cm⁻¹, convert to THz
|
|
525
|
-
final_frequencies = frequencies.map((
|
|
536
|
+
final_frequencies = frequencies.map((frequency) => frequency * CM_TO_THZ);
|
|
526
537
|
console.warn(`Phonon DOS frequencies appear to be in cm⁻¹ (max: ${max_freq.toFixed(1)}). ` +
|
|
527
538
|
`Converting to THz (max: ${(max_freq * CM_TO_THZ).toFixed(1)} THz).`);
|
|
528
539
|
}
|
|
@@ -912,6 +923,7 @@ function parse_axis_label(label) {
|
|
|
912
923
|
const match = /^(.+?)\s*\(([^)]+)\)$/.exec(label);
|
|
913
924
|
return match ? { name: match[1], unit: match[2] } : { name: label };
|
|
914
925
|
}
|
|
926
|
+
const format_tooltip_line = (name, value, unit) => `${name}: ${value}${unit ? ` ${unit}` : ``}`;
|
|
915
927
|
// Format DOS tooltip content from axis labels and values
|
|
916
928
|
export function format_dos_tooltip(x_formatted, y_formatted, label, is_horizontal, is_phonon, units, x_axis_label, y_axis_label, num_series) {
|
|
917
929
|
const x_parsed = parse_axis_label(x_axis_label);
|
|
@@ -920,15 +932,14 @@ export function format_dos_tooltip(x_formatted, y_formatted, label, is_horizonta
|
|
|
920
932
|
name: is_phonon ? `Frequency` : `Energy`,
|
|
921
933
|
unit: is_phonon ? units : `eV`,
|
|
922
934
|
};
|
|
923
|
-
const format_line = (name, value, unit) => `${name}: ${value}${unit ? ` ${unit}` : ``}`;
|
|
924
935
|
const lines = is_horizontal
|
|
925
936
|
? [
|
|
926
|
-
|
|
927
|
-
|
|
937
|
+
format_tooltip_line(y_parsed.name || freq_defaults.name, y_formatted, y_parsed.unit || freq_defaults.unit),
|
|
938
|
+
format_tooltip_line(x_parsed.name || `Density`, x_formatted),
|
|
928
939
|
]
|
|
929
940
|
: [
|
|
930
|
-
|
|
931
|
-
|
|
941
|
+
format_tooltip_line(y_parsed.name || `Density`, y_formatted),
|
|
942
|
+
format_tooltip_line(x_parsed.name || freq_defaults.name, x_formatted, x_parsed.unit || freq_defaults.unit),
|
|
932
943
|
];
|
|
933
944
|
return { title: num_series > 1 && label ? label : undefined, lines };
|
|
934
945
|
}
|
|
@@ -962,9 +973,7 @@ export function format_sigma(val) {
|
|
|
962
973
|
return val.toFixed(val < 1 ? 3 : 2);
|
|
963
974
|
}
|
|
964
975
|
// Validate sigma_range: ensures min < max, returns [0, 1] if invalid
|
|
965
|
-
export
|
|
966
|
-
return Number.isFinite(min) && Number.isFinite(max) && min < max ? [min, max] : [0, 1];
|
|
967
|
-
}
|
|
976
|
+
export const validate_sigma_range = ([min, max]) => Number.isFinite(min) && Number.isFinite(max) && min < max ? [min, max] : [0, 1];
|
|
968
977
|
// Calculate slider step: 1/100th of range, or 0.01 fallback
|
|
969
978
|
export function calculate_sigma_step(range) {
|
|
970
979
|
const [min, max] = validate_sigma_range(range);
|
package/dist/spectral/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export { default as BandsAndDos } from './BandsAndDos.svelte';
|
|
|
3
3
|
export { default as BrillouinBandsDos } from './BrillouinBandsDos.svelte';
|
|
4
4
|
export { default as Dos } from './Dos.svelte';
|
|
5
5
|
export * from './helpers';
|
|
6
|
-
export * from './types';
|
|
6
|
+
export type * from './types';
|
package/dist/spectral/index.js
CHANGED
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
title = ``,
|
|
45
45
|
sym_data = null,
|
|
46
46
|
structure = undefined,
|
|
47
|
+
show_mode_toggle = true,
|
|
47
48
|
children,
|
|
48
49
|
...rest
|
|
49
50
|
}: Omit<HTMLAttributes<HTMLDivElement>, `children`> & {
|
|
@@ -66,6 +67,7 @@
|
|
|
66
67
|
title?: string
|
|
67
68
|
sym_data?: MoyoDataset | null
|
|
68
69
|
structure?: AnyStructure | null
|
|
70
|
+
show_mode_toggle?: boolean
|
|
69
71
|
children?: Snippet<[{ mode_menu_open: boolean; structure?: AnyStructure | null }]>
|
|
70
72
|
} = $props()
|
|
71
73
|
|
|
@@ -87,13 +89,14 @@
|
|
|
87
89
|
|
|
88
90
|
// Dropdown state
|
|
89
91
|
let mode_menu_open = $state(false)
|
|
92
|
+
let mode_toggle_visible = $derived(show_mode_toggle || mode_menu_open)
|
|
90
93
|
|
|
91
94
|
// Clear hidden property values when switching modes (since they may not be valid)
|
|
92
|
-
let
|
|
95
|
+
let prev_mode = $state(atom_color_config.mode)
|
|
93
96
|
$effect(() => {
|
|
94
|
-
if (atom_color_config.mode !==
|
|
97
|
+
if (atom_color_config.mode !== prev_mode) {
|
|
95
98
|
hidden_prop_vals.clear()
|
|
96
|
-
|
|
99
|
+
prev_mode = atom_color_config.mode
|
|
97
100
|
}
|
|
98
101
|
})
|
|
99
102
|
|
|
@@ -111,7 +114,9 @@
|
|
|
111
114
|
if (typeof val === `string` && val.includes(`|`)) { // Format Wyckoff orbit IDs
|
|
112
115
|
const [wyckoff, element] = val.split(`|`, 2)
|
|
113
116
|
// Count how many sites have this wyckoff+element combination
|
|
114
|
-
const count = property_colors?.values.filter((
|
|
117
|
+
const count = property_colors?.values.filter((property_value) =>
|
|
118
|
+
property_value === val
|
|
119
|
+
).length ?? 0
|
|
115
120
|
return `${element}:${count}${wyckoff}`
|
|
116
121
|
}
|
|
117
122
|
return String(val)
|
|
@@ -237,9 +242,12 @@
|
|
|
237
242
|
>
|
|
238
243
|
<button
|
|
239
244
|
class="mode-toggle"
|
|
245
|
+
class:visible={mode_toggle_visible}
|
|
240
246
|
onclick={() => (mode_menu_open = !mode_menu_open)}
|
|
241
247
|
title="Change atom coloring mode"
|
|
242
248
|
aria-expanded={mode_menu_open}
|
|
249
|
+
aria-hidden={mode_toggle_visible ? undefined : true}
|
|
250
|
+
tabindex={mode_toggle_visible ? undefined : -1}
|
|
243
251
|
{@attach tooltip()}
|
|
244
252
|
>
|
|
245
253
|
<Icon icon={mode_menu_open ? `Collapse` : `Expand`} />
|
|
@@ -715,6 +723,7 @@
|
|
|
715
723
|
position: relative;
|
|
716
724
|
display: flex;
|
|
717
725
|
align-items: center;
|
|
726
|
+
margin-left: calc(-0.5 * var(--struct-legend-gap, clamp(3pt, 2cqmin, 7pt)));
|
|
718
727
|
}
|
|
719
728
|
.mode-toggle {
|
|
720
729
|
background: transparent;
|
|
@@ -724,10 +733,18 @@
|
|
|
724
733
|
display: flex;
|
|
725
734
|
align-items: center;
|
|
726
735
|
font-size: 0.9em;
|
|
727
|
-
opacity: 0
|
|
736
|
+
opacity: 0;
|
|
737
|
+
pointer-events: none;
|
|
728
738
|
transition: opacity 0.2s ease;
|
|
729
739
|
}
|
|
730
|
-
.mode-toggle:
|
|
740
|
+
.mode-toggle :global(svg) {
|
|
741
|
+
font-size: 1.15em;
|
|
742
|
+
}
|
|
743
|
+
.mode-toggle.visible {
|
|
744
|
+
opacity: 0.7;
|
|
745
|
+
pointer-events: auto;
|
|
746
|
+
}
|
|
747
|
+
.mode-toggle.visible:hover {
|
|
731
748
|
opacity: 1;
|
|
732
749
|
}
|
|
733
750
|
.mode-dropdown {
|
|
@@ -24,6 +24,7 @@ type $$ComponentProps = Omit<HTMLAttributes<HTMLDivElement>, `children`> & {
|
|
|
24
24
|
title?: string;
|
|
25
25
|
sym_data?: MoyoDataset | null;
|
|
26
26
|
structure?: AnyStructure | null;
|
|
27
|
+
show_mode_toggle?: boolean;
|
|
27
28
|
children?: Snippet<[{
|
|
28
29
|
mode_menu_open: boolean;
|
|
29
30
|
structure?: AnyStructure | null;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { HTML } from '@threlte/extras'
|
|
3
|
+
import type { Snippet } from 'svelte'
|
|
4
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
2
5
|
import type { Vec3 } from '../math'
|
|
3
|
-
import { HTML } from '@threlte/extras'
|
|
4
|
-
import type { Snippet } from 'svelte'
|
|
5
|
-
import type { HTMLAttributes } from 'svelte/elements'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
let { position, children, ...rest }: HTMLAttributes<HTMLDivElement> & {
|
|
8
|
+
position: Vec3
|
|
9
|
+
children: Snippet<[{ position: Vec3 }]>
|
|
10
|
+
} = $props()
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
13
|
<HTML {position} pointerEvents="none">
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
box-sizing: border-box;
|
|
23
23
|
text-align: var(--canvas-tooltip-text-align, left);
|
|
24
24
|
border-radius: var(--canvas-tooltip-border-radius, var(--border-radius, 3pt));
|
|
25
|
-
background: var(--canvas-tooltip-bg,
|
|
25
|
+
background: var(--canvas-tooltip-bg, light-dark(rgba(226, 232, 240, 0.96), rgba(15, 23, 42, 0.96)));
|
|
26
26
|
padding: var(--canvas-tooltip-padding, 1pt 5pt);
|
|
27
|
-
color: var(--canvas-tooltip-text-color);
|
|
27
|
+
color: var(--canvas-tooltip-text-color, light-dark(#0f172a, #f8fafc));
|
|
28
28
|
font-family: var(--canvas-tooltip-font-family);
|
|
29
29
|
font-size: var(--canvas-tooltip-font-size, clamp(8pt, 3cqmin, 18pt));
|
|
30
30
|
line-height: var(--canvas-tooltip-line-height);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Vec3 } from '../math';
|
|
2
1
|
import type { Snippet } from 'svelte';
|
|
3
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import type { Vec3 } from '../math';
|
|
4
4
|
type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
5
5
|
position: Vec3;
|
|
6
6
|
children: Snippet<[{
|
|
@@ -118,7 +118,6 @@
|
|
|
118
118
|
class:align-left={align === `left`}
|
|
119
119
|
transition:fade={{ duration: 100 }}
|
|
120
120
|
>
|
|
121
|
-
<!-- Cell type selector -->
|
|
122
121
|
<div class="cell-type-row">
|
|
123
122
|
{#each cell_types as type (type)}
|
|
124
123
|
{@const disabled = type !== `original` && !sym_data}
|
|
@@ -140,7 +139,6 @@
|
|
|
140
139
|
{/each}
|
|
141
140
|
</div>
|
|
142
141
|
|
|
143
|
-
<!-- Supercell presets -->
|
|
144
142
|
<div class="supercell-grid">
|
|
145
143
|
{#each supercell_presets as preset (preset)}
|
|
146
144
|
<button
|
|
@@ -153,7 +151,6 @@
|
|
|
153
151
|
{/each}
|
|
154
152
|
</div>
|
|
155
153
|
|
|
156
|
-
<!-- Custom input -->
|
|
157
154
|
<div class="custom-input-row">
|
|
158
155
|
<input
|
|
159
156
|
type="text"
|
|
@@ -188,10 +185,11 @@
|
|
|
188
185
|
);
|
|
189
186
|
}
|
|
190
187
|
.toggle-btn {
|
|
188
|
+
font: inherit;
|
|
191
189
|
padding: var(--struct-legend-padding, 0 4pt);
|
|
192
190
|
line-height: var(--struct-legend-line-height, 1.3);
|
|
193
191
|
vertical-align: middle;
|
|
194
|
-
color:
|
|
192
|
+
color: inherit;
|
|
195
193
|
background: var(--btn-bg, light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.1)));
|
|
196
194
|
border: 1px solid var(--border-color);
|
|
197
195
|
border-radius: var(--border-radius, 3pt);
|
|
@@ -211,15 +209,22 @@
|
|
|
211
209
|
right: 0;
|
|
212
210
|
margin-top: 2px;
|
|
213
211
|
background: var(--surface-bg, light-dark(rgba(255, 255, 255, 0.96), #222));
|
|
214
|
-
padding:
|
|
212
|
+
padding: 4px;
|
|
215
213
|
border-radius: var(--struct-border-radius, var(--border-radius, 3pt));
|
|
216
214
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
217
215
|
display: flex;
|
|
218
216
|
flex-direction: column;
|
|
219
217
|
gap: 5px;
|
|
220
218
|
z-index: 100;
|
|
219
|
+
font-size: var(--struct-cell-select-dropdown-font, max(10px, 1em));
|
|
221
220
|
min-width: 118px;
|
|
222
221
|
}
|
|
222
|
+
.dropdown button,
|
|
223
|
+
.custom-input-row input {
|
|
224
|
+
color: inherit;
|
|
225
|
+
font-family: inherit;
|
|
226
|
+
font-size: inherit;
|
|
227
|
+
}
|
|
223
228
|
/* Invisible bridge to prevent menu closing when moving mouse from toggle to dropdown */
|
|
224
229
|
.dropdown::before {
|
|
225
230
|
content: '';
|
|
@@ -244,7 +249,6 @@
|
|
|
244
249
|
left: 0;
|
|
245
250
|
}
|
|
246
251
|
|
|
247
|
-
/* Cell type row - compact buttons with minimal padding */
|
|
248
252
|
.cell-type-row {
|
|
249
253
|
display: flex;
|
|
250
254
|
gap: 3px;
|
|
@@ -253,9 +257,7 @@
|
|
|
253
257
|
}
|
|
254
258
|
.cell-type-btn {
|
|
255
259
|
flex: 1;
|
|
256
|
-
padding:
|
|
257
|
-
font-size: 0.9em;
|
|
258
|
-
color: var(--text-color);
|
|
260
|
+
padding: 1px 3px;
|
|
259
261
|
background: var(--btn-bg, light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.1)));
|
|
260
262
|
border: 1px solid var(--border-color);
|
|
261
263
|
border-radius: var(--border-radius, 3pt);
|
|
@@ -288,16 +290,14 @@
|
|
|
288
290
|
cursor: not-allowed;
|
|
289
291
|
}
|
|
290
292
|
|
|
291
|
-
/* Supercell grid */
|
|
292
293
|
.supercell-grid {
|
|
293
294
|
display: grid;
|
|
294
295
|
grid-template-columns: 1fr 1fr;
|
|
295
|
-
gap:
|
|
296
|
+
gap: 3px;
|
|
296
297
|
}
|
|
297
298
|
.preset-btn {
|
|
298
|
-
padding:
|
|
299
|
-
|
|
300
|
-
color: var(--text-color);
|
|
299
|
+
padding: 0 1px;
|
|
300
|
+
line-height: 1;
|
|
301
301
|
background: var(--btn-bg, light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.1)));
|
|
302
302
|
border: 1px solid var(--border-color);
|
|
303
303
|
border-radius: var(--border-radius, 3pt);
|
|
@@ -324,7 +324,6 @@
|
|
|
324
324
|
);
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
-
/* Custom input row */
|
|
328
327
|
.custom-input-row {
|
|
329
328
|
display: flex;
|
|
330
329
|
align-items: center;
|
|
@@ -334,7 +333,6 @@
|
|
|
334
333
|
max-width: 60px;
|
|
335
334
|
min-height: 0;
|
|
336
335
|
padding: 1px 4px;
|
|
337
|
-
font-size: 0.85em;
|
|
338
336
|
}
|
|
339
337
|
.custom-input-row input.invalid {
|
|
340
338
|
border-color: rgba(255, 100, 100, 0.6);
|