matterviz 0.4.2 → 0.4.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/FilePicker.svelte +40 -50
- package/dist/api/optimade.js +10 -7
- package/dist/app.css +15 -0
- package/dist/brillouin/BrillouinZone.svelte +18 -9
- package/dist/brillouin/BrillouinZoneScene.svelte +20 -29
- package/dist/brillouin/compute.js +10 -16
- package/dist/brillouin/geometry.js +2 -2
- package/dist/chempot-diagram/ChemPotDiagram.svelte +18 -15
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +17 -113
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +104 -264
- package/dist/chempot-diagram/async-compute.svelte.js +12 -13
- package/dist/chempot-diagram/color.d.ts +21 -1
- package/dist/chempot-diagram/color.js +70 -1
- package/dist/chempot-diagram/compute.d.ts +7 -0
- package/dist/chempot-diagram/compute.js +85 -26
- package/dist/chempot-diagram/export.js +1 -6
- package/dist/chempot-diagram/temperature.js +9 -10
- package/dist/composition/BarChart.svelte +7 -9
- package/dist/composition/Composition.svelte +3 -8
- package/dist/composition/Formula.svelte +2 -2
- package/dist/composition/FormulaFilter.svelte +27 -93
- package/dist/composition/format.js +6 -8
- package/dist/composition/parse.js +50 -105
- package/dist/constants.d.ts +0 -1
- package/dist/constants.js +6 -17
- package/dist/convex-hull/ConvexHull2D.svelte +0 -2
- package/dist/convex-hull/ConvexHull3D.svelte +19 -47
- package/dist/convex-hull/ConvexHull4D.svelte +65 -95
- package/dist/convex-hull/StructurePopup.svelte +1 -1
- package/dist/convex-hull/gas-thermodynamics.js +21 -53
- package/dist/convex-hull/helpers.js +1 -7
- package/dist/convex-hull/thermodynamics.js +19 -27
- package/dist/coordination/CoordinationBarPlot.svelte +12 -21
- package/dist/element/BohrAtom.svelte +0 -1
- package/dist/element/ElementTile.svelte +26 -44
- package/dist/element/data.d.ts +2 -0
- package/dist/element/data.js +5 -1
- package/dist/element/index.d.ts +1 -1
- package/dist/element/index.js +1 -1
- package/dist/fermi-surface/FermiSurface.svelte +22 -23
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +2 -6
- package/dist/fermi-surface/FermiSurfaceScene.svelte +32 -77
- package/dist/fermi-surface/compute.js +22 -55
- package/dist/fermi-surface/parse.js +38 -70
- package/dist/file-viewer/JsonBrowser.svelte +1043 -0
- package/dist/file-viewer/JsonBrowser.svelte.d.ts +9 -0
- package/dist/file-viewer/PlotPanel.svelte +350 -0
- package/dist/file-viewer/PlotPanel.svelte.d.ts +9 -0
- package/dist/file-viewer/TrajectoryWithDos.svelte +30 -0
- package/dist/file-viewer/TrajectoryWithDos.svelte.d.ts +10 -0
- package/dist/file-viewer/detect.d.ts +11 -0
- package/dist/file-viewer/detect.js +381 -0
- package/dist/file-viewer/eligibility.d.ts +4 -0
- package/dist/file-viewer/eligibility.js +53 -0
- package/dist/file-viewer/host-protocol.d.ts +50 -0
- package/dist/file-viewer/host-transfer.d.ts +25 -0
- package/dist/file-viewer/host-transfer.js +42 -0
- package/dist/file-viewer/index.d.ts +5 -0
- package/dist/file-viewer/index.js +5 -0
- package/dist/file-viewer/main.d.ts +44 -0
- package/dist/file-viewer/main.js +535 -0
- package/dist/file-viewer/parse.d.ts +9 -0
- package/dist/file-viewer/parse.js +170 -0
- package/dist/file-viewer/plot-utils.d.ts +24 -0
- package/dist/file-viewer/plot-utils.js +191 -0
- package/dist/file-viewer/types.d.ts +4 -0
- package/dist/file-viewer/types.js +5 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +57 -84
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/io/ExportPane.svelte +1 -1
- package/dist/io/decompress.d.ts +2 -0
- package/dist/io/decompress.js +3 -2
- package/dist/io/export.d.ts +7 -4
- package/dist/io/export.js +70 -18
- package/dist/io/file-drop.js +60 -35
- package/dist/io/url-drop.d.ts +2 -0
- package/dist/io/url-drop.js +28 -16
- package/dist/isosurface/Isosurface.svelte +687 -196
- package/dist/isosurface/Isosurface.svelte.d.ts +7 -1
- package/dist/isosurface/IsosurfaceControls.svelte +564 -85
- package/dist/isosurface/IsosurfaceControls.svelte.d.ts +1 -1
- package/dist/isosurface/VolumeSlice.svelte +224 -0
- package/dist/isosurface/VolumeSlice.svelte.d.ts +28 -0
- package/dist/isosurface/coloring.d.ts +20 -0
- package/dist/isosurface/coloring.js +118 -0
- package/dist/isosurface/geometry-worker-types.d.ts +38 -0
- package/dist/isosurface/geometry.worker.d.ts +1 -0
- package/dist/isosurface/geometry.worker.js +59 -0
- package/dist/isosurface/grid.d.ts +10 -0
- package/dist/isosurface/grid.js +31 -0
- package/dist/isosurface/index.d.ts +4 -0
- package/dist/isosurface/index.js +4 -0
- package/dist/isosurface/profile.d.ts +12 -0
- package/dist/isosurface/profile.js +19 -0
- package/dist/isosurface/sampling.d.ts +34 -0
- package/dist/isosurface/sampling.js +408 -0
- package/dist/isosurface/slice-rendering.d.ts +13 -0
- package/dist/isosurface/slice-rendering.js +79 -0
- package/dist/isosurface/slice.d.ts +22 -2
- package/dist/isosurface/slice.js +200 -116
- package/dist/isosurface/types.d.ts +24 -1
- package/dist/isosurface/types.js +120 -8
- package/dist/json-path.d.ts +4 -0
- package/dist/json-path.js +89 -0
- package/dist/labels.js +1 -1
- package/dist/layout/InfoCard.svelte +1 -3
- package/dist/layout/SettingsSection.svelte +52 -61
- package/dist/layout/SettingsSection.svelte.d.ts +6 -7
- package/dist/layout/ViewerChrome.svelte +7 -1
- package/dist/layout/json-tree/JsonNode.svelte +14 -48
- package/dist/layout/json-tree/JsonTree.svelte +48 -95
- package/dist/layout/json-tree/JsonValue.svelte +3 -18
- package/dist/layout/json-tree/utils.d.ts +0 -3
- package/dist/layout/json-tree/utils.js +50 -179
- package/dist/marching-cubes.d.ts +8 -1
- package/dist/marching-cubes.js +115 -48
- package/dist/math.d.ts +3 -2
- package/dist/math.js +29 -38
- package/dist/overlays/ContextMenu.svelte +15 -32
- package/dist/overlays/DraggablePane.svelte +39 -58
- package/dist/overlays/DraggablePane.svelte.d.ts +1 -1
- package/dist/overlays/GlassChip.svelte +3 -1
- package/dist/periodic-table/PeriodicTableControls.svelte +26 -52
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +18 -34
- package/dist/phase-diagram/build-diagram.js +1 -6
- package/dist/phase-diagram/svg-to-diagram.js +9 -14
- package/dist/plot/bar/BarPlot.svelte +38 -42
- package/dist/plot/bar/SpacegroupBarPlot.svelte +18 -42
- package/dist/plot/box/BoxPlot.svelte +27 -23
- package/dist/plot/core/auto-place.d.ts +1 -1
- package/dist/plot/core/auto-place.js +1 -1
- package/dist/plot/core/data-transform.d.ts +1 -2
- package/dist/plot/core/data-transform.js +0 -10
- package/dist/plot/core/layout.d.ts +12 -5
- package/dist/plot/core/layout.js +37 -27
- package/dist/plot/core/pan-zoom.svelte.d.ts +2 -4
- package/dist/plot/core/pan-zoom.svelte.js +34 -17
- package/dist/plot/core/placed-tween.svelte.d.ts +3 -0
- package/dist/plot/core/placed-tween.svelte.js +68 -21
- package/dist/plot/core/svg.js +0 -1
- package/dist/plot/core/utils/hierarchy-chart.d.ts +1 -0
- package/dist/plot/core/utils/hierarchy-chart.js +12 -0
- package/dist/plot/core/utils/hierarchy-labels.js +3 -2
- package/dist/plot/histogram/Histogram.svelte +21 -26
- package/dist/plot/sankey/sankey.js +13 -9
- package/dist/plot/scatter/BinnedScatterPlot.svelte +59 -43
- package/dist/plot/scatter/ScatterPlot.svelte +67 -52
- package/dist/plot/scatter/adaptive-density.d.ts +1 -1
- package/dist/plot/scatter/adaptive-density.js +36 -20
- package/dist/plot/sunburst/Sunburst.svelte +20 -20
- package/dist/plot/treemap/Treemap.svelte +175 -60
- package/dist/plot/treemap/Treemap.svelte.d.ts +6 -0
- package/dist/plot/treemap/index.d.ts +1 -0
- package/dist/plot/treemap/labels.d.ts +38 -0
- package/dist/plot/treemap/labels.js +80 -0
- package/dist/plot/treemap/treemap.d.ts +4 -2
- package/dist/plot/treemap/treemap.js +5 -2
- package/dist/rdf/RdfPlot.svelte +17 -35
- package/dist/rdf/calc-rdf.js +59 -44
- package/dist/rdf/index.d.ts +0 -1
- package/dist/sanitize.js +84 -26
- package/dist/scene/SceneCamera.svelte +1 -1
- package/dist/scene/SceneCamera.svelte.d.ts +1 -1
- package/dist/scene/index.d.ts +1 -2
- package/dist/scene/index.js +1 -1
- package/dist/scene/{props.js → props.svelte.js} +15 -1
- package/dist/settings.js +159 -482
- package/dist/spectral/Bands.svelte +151 -158
- package/dist/spectral/BrillouinBandsDos.svelte +4 -19
- package/dist/spectral/Dos.svelte +26 -24
- package/dist/spectral/helpers.js +40 -105
- package/dist/structure/AtomLegend.svelte +8 -13
- package/dist/structure/AtomLegend.svelte.d.ts +2 -3
- package/dist/structure/CellSelect.svelte +35 -10
- package/dist/structure/Structure.svelte +177 -99
- package/dist/structure/Structure.svelte.d.ts +1 -1
- package/dist/structure/StructureCarousel.svelte +10 -3
- package/dist/structure/StructureControls.svelte +8 -26
- package/dist/structure/StructureControls.svelte.d.ts +1 -1
- package/dist/structure/StructureInfoPane.svelte +65 -76
- package/dist/structure/StructureScene.svelte +75 -109
- package/dist/structure/StructureScene.svelte.d.ts +3 -1
- package/dist/structure/StructureViewport.svelte +120 -55
- package/dist/structure/StructureViewport.svelte.d.ts +3 -1
- package/dist/structure/atom-properties.d.ts +1 -1
- package/dist/structure/atom-properties.js +4 -3
- package/dist/structure/bond-order-perception.js +3 -8
- package/dist/structure/bonding.d.ts +0 -1
- package/dist/structure/bonding.js +16 -23
- package/dist/structure/export.js +50 -74
- package/dist/structure/format-detect.js +5 -7
- package/dist/structure/index.js +6 -12
- package/dist/structure/parse.js +38 -100
- package/dist/structure/partial-occupancy.js +7 -4
- package/dist/structure/pbc.js +8 -10
- package/dist/structure/polyhedra.js +5 -4
- package/dist/structure/prop-groups.d.ts +85 -0
- package/dist/structure/prop-groups.js +18 -0
- package/dist/symmetry/SymmetryStats.svelte +0 -4
- package/dist/symmetry/WyckoffTable.svelte +5 -4
- package/dist/symmetry/cell-transform.js +5 -14
- package/dist/symmetry/index.js +6 -9
- package/dist/table/HeatmapTable.svelte +61 -103
- package/dist/table/ToggleMenu.svelte +166 -44
- package/dist/table/ToggleMenu.svelte.d.ts +1 -1
- package/dist/theme/embedded.d.ts +18 -0
- package/dist/theme/embedded.js +206 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/index.js +1 -2
- package/dist/theme/themes.mjs +31 -60
- package/dist/tooltip/TooltipContent.svelte +1 -1
- package/dist/tooltip/TooltipContent.svelte.d.ts +1 -1
- package/dist/tooltip/index.d.ts +8 -1
- package/dist/trajectory/Trajectory.svelte +140 -120
- package/dist/trajectory/TrajectoryError.svelte +1 -66
- package/dist/trajectory/TrajectoryExportPane.svelte +0 -1
- package/dist/trajectory/TrajectoryInfoPane.svelte +55 -80
- package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +2 -1
- package/dist/trajectory/extract.js +19 -29
- package/dist/trajectory/format-detect.d.ts +2 -0
- package/dist/trajectory/format-detect.js +7 -5
- package/dist/trajectory/frame-reader.js +3 -4
- package/dist/trajectory/helpers.js +16 -49
- package/dist/trajectory/index.js +2 -8
- package/dist/trajectory/parse/ase.js +1 -1
- package/dist/trajectory/parse/index.d.ts +4 -3
- package/dist/trajectory/parse/index.js +12 -17
- package/dist/trajectory/parse/vaspout-h5.d.ts +0 -1
- package/dist/trajectory/parse/vaspout-h5.js +1 -4
- package/dist/trajectory/parse/xyz.js +48 -2
- package/dist/trajectory/plotting.js +14 -37
- package/dist/xrd/XrdPlot.svelte +43 -68
- package/dist/xrd/calc-xrd.js +22 -58
- package/dist/xrd/parse.js +13 -22
- package/package.json +40 -8
- package/readme.md +6 -5
- package/dist/scene/types.d.ts +0 -26
- package/dist/tooltip/types.d.ts +0 -8
- package/dist/trajectory/constants.d.ts +0 -6
- package/dist/trajectory/constants.js +0 -11
- /package/dist/{scene/types.js → file-viewer/host-protocol.js} +0 -0
- /package/dist/{tooltip/types.js → isosurface/geometry-worker-types.js} +0 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { PaneProps, PaneToggleProps } from '../overlays'
|
|
3
3
|
import { get_electro_neg_formula } from '../composition'
|
|
4
|
-
import {
|
|
4
|
+
import { element_by_symbol, type ElementSymbol } from '../element'
|
|
5
5
|
import Icon from '../Icon.svelte'
|
|
6
6
|
import { format_num } from '../labels'
|
|
7
7
|
import type { InfoItem } from '../layout'
|
|
8
8
|
import type { Vec2 } from '../math'
|
|
9
|
-
import CopyButton from '../overlays/CopyButton.svelte'
|
|
10
9
|
import DraggablePane from '../overlays/DraggablePane.svelte'
|
|
11
10
|
import { sanitize_html } from '../sanitize'
|
|
12
11
|
import { colors } from '../state.svelte'
|
|
@@ -93,11 +92,6 @@
|
|
|
93
92
|
const copy_to_clipboard = (label: string, value: string, key: string): Promise<void> =>
|
|
94
93
|
copy(`${label}: ${value}`, key)
|
|
95
94
|
|
|
96
|
-
function copy_event(event: MouseEvent, label: string, value: string, key: string) {
|
|
97
|
-
event.stopPropagation()
|
|
98
|
-
copy_to_clipboard(label, value, key)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
95
|
function copy_info_item(item: InfoItem) {
|
|
102
96
|
copy_to_clipboard(item.label, String(item.value), item.key ?? item.label)
|
|
103
97
|
}
|
|
@@ -153,19 +147,22 @@
|
|
|
153
147
|
sibling_cards[next_idx]?.focus()
|
|
154
148
|
}
|
|
155
149
|
|
|
156
|
-
const get_element_name = (element: string): string =>
|
|
157
|
-
element_data?.find((element_record) => element_record.symbol === element)?.name || element
|
|
158
|
-
|
|
159
150
|
const site_summary = (card: SiteCard): string =>
|
|
160
151
|
[card.element_name, ...card.details.map(({ label, value }) => `${label}: ${value}`)].join(
|
|
161
152
|
`; `,
|
|
162
153
|
)
|
|
163
154
|
|
|
155
|
+
function compact_site_detail_label(detail: SiteDetail): string {
|
|
156
|
+
if (detail.key === `fractional`) return `Frac.`
|
|
157
|
+
if (detail.key === `cartesian`) return `Cart.`
|
|
158
|
+
return detail.label
|
|
159
|
+
}
|
|
160
|
+
|
|
164
161
|
function format_site_property(prop_key: string, prop_value: unknown): SiteDetail | null {
|
|
165
162
|
if (prop_value == null) return null
|
|
166
|
-
const format_numeric_value = (value: unknown
|
|
163
|
+
const format_numeric_value = (value: unknown): string | null => {
|
|
167
164
|
const numeric_value = Number(value)
|
|
168
|
-
return Number.isNaN(numeric_value) ? null : format_num(numeric_value,
|
|
165
|
+
return Number.isNaN(numeric_value) ? null : format_num(numeric_value, `.3~f`)
|
|
169
166
|
}
|
|
170
167
|
const format_value_list = (values: unknown[]): string =>
|
|
171
168
|
`(${values.map((value) => format_numeric_value(value) ?? String(value)).join(`, `)})`
|
|
@@ -241,7 +238,7 @@
|
|
|
241
238
|
},
|
|
242
239
|
{
|
|
243
240
|
label: `a, b, c`,
|
|
244
|
-
value: `${format_num(a, `.
|
|
241
|
+
value: `${format_num(a, `.3~f`)}, ${format_num(b, `.3~f`)}, ${format_num(c, `.3~f`)} Å`,
|
|
245
242
|
key: `cell-abc`,
|
|
246
243
|
},
|
|
247
244
|
{
|
|
@@ -319,7 +316,7 @@
|
|
|
319
316
|
if (!structure || !site_cards_visible) return []
|
|
320
317
|
return structure.sites.map((site: Site, idx: number) => {
|
|
321
318
|
const element = site.species?.[0]?.element || `Unknown`
|
|
322
|
-
const element_name =
|
|
319
|
+
const element_name = element_by_symbol.get(element as ElementSymbol)?.name ?? element
|
|
323
320
|
const details: SiteDetail[] = []
|
|
324
321
|
for (const [label, key, coords, unit] of [
|
|
325
322
|
[`Fractional`, `fractional`, site.abc, ``],
|
|
@@ -329,7 +326,7 @@
|
|
|
329
326
|
details.push({
|
|
330
327
|
label,
|
|
331
328
|
key,
|
|
332
|
-
value: `(${coords.map((coord) => format_num(coord, `.
|
|
329
|
+
value: `(${coords.map((coord) => format_num(coord, `.3~f`)).join(`, `)})${unit}`,
|
|
333
330
|
})
|
|
334
331
|
}
|
|
335
332
|
if (site.properties) {
|
|
@@ -404,7 +401,12 @@
|
|
|
404
401
|
}}
|
|
405
402
|
open_icon="Cross"
|
|
406
403
|
closed_icon="Info"
|
|
407
|
-
|
|
404
|
+
icon_style="transform: scale(1.15)"
|
|
405
|
+
pane_props={{
|
|
406
|
+
...pane_props,
|
|
407
|
+
class: `structure-info-pane ${pane_props?.class ?? ``}`,
|
|
408
|
+
style: `--pane-padding: 4pt; --pane-gap: 2pt; ${pane_props?.style ?? ``}`,
|
|
409
|
+
}}
|
|
408
410
|
{...rest}
|
|
409
411
|
>
|
|
410
412
|
<h4 id="structure-info" style="margin-top: 0">Structure Info</h4>
|
|
@@ -446,7 +448,7 @@
|
|
|
446
448
|
{wyckoff_positions}
|
|
447
449
|
on_hover={(site_indices) => (highlighted_sites = site_indices ?? [])}
|
|
448
450
|
on_click={(site_indices) => (selected_sites = site_indices ?? [])}
|
|
449
|
-
style="width: 100%; margin-top:
|
|
451
|
+
style="width: 100%; margin-top: 2pt; font-size: 0.8em"
|
|
450
452
|
/>
|
|
451
453
|
{/if}
|
|
452
454
|
</section>
|
|
@@ -531,42 +533,18 @@
|
|
|
531
533
|
onclick={(event) => select_site(card.idx, event)}
|
|
532
534
|
onkeydown={(event) => handle_site_keydown(event, card)}
|
|
533
535
|
>
|
|
534
|
-
<
|
|
535
|
-
<span class="site-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
</span>
|
|
540
|
-
<CopyButton
|
|
541
|
-
label="Copy {card.title}"
|
|
542
|
-
title="Copy {card.title}"
|
|
543
|
-
copied={copied.has(`site-${card.idx}-summary`)}
|
|
544
|
-
onclick={(event) =>
|
|
545
|
-
copy_event(
|
|
546
|
-
event,
|
|
547
|
-
card.title,
|
|
548
|
-
site_summary(card),
|
|
549
|
-
`site-${card.idx}-summary`,
|
|
550
|
-
)}
|
|
551
|
-
/>
|
|
552
|
-
</div>
|
|
536
|
+
<span class="site-title">
|
|
537
|
+
<span class="site-color" aria-hidden="true"></span>
|
|
538
|
+
<strong>{card.title}</strong>
|
|
539
|
+
<span>{card.element_name}</span>
|
|
540
|
+
</span>
|
|
553
541
|
<div class="site-card-details">
|
|
554
542
|
{#each card.details as detail (`site-${card.idx}-${detail.key}`)}
|
|
555
543
|
<div class="site-detail">
|
|
556
|
-
<span
|
|
544
|
+
<span title={detail.label}
|
|
545
|
+
>{@html sanitize_html(compact_site_detail_label(detail))}</span
|
|
546
|
+
>
|
|
557
547
|
<span title={detail.tooltip}>{@html sanitize_html(detail.value)}</span>
|
|
558
|
-
<CopyButton
|
|
559
|
-
label="Copy {card.title} {detail.label}"
|
|
560
|
-
title="Copy {detail.label}"
|
|
561
|
-
copied={copied.has(`site-${card.idx}-${detail.key}`)}
|
|
562
|
-
onclick={(event) =>
|
|
563
|
-
copy_event(
|
|
564
|
-
event,
|
|
565
|
-
`${card.title} ${detail.label}`,
|
|
566
|
-
detail.value,
|
|
567
|
-
`site-${card.idx}-${detail.key}`,
|
|
568
|
-
)}
|
|
569
|
-
/>
|
|
570
548
|
</div>
|
|
571
549
|
{/each}
|
|
572
550
|
</div>
|
|
@@ -591,13 +569,20 @@
|
|
|
591
569
|
</DraggablePane>
|
|
592
570
|
|
|
593
571
|
<style>
|
|
594
|
-
|
|
595
|
-
|
|
572
|
+
h4 {
|
|
573
|
+
margin: 2pt 0;
|
|
574
|
+
font-size: 0.95em;
|
|
575
|
+
}
|
|
576
|
+
hr {
|
|
577
|
+
margin: 2pt 0;
|
|
578
|
+
}
|
|
579
|
+
.info-row {
|
|
596
580
|
display: flex;
|
|
597
581
|
justify-content: space-between;
|
|
598
|
-
gap:
|
|
599
|
-
padding: 1pt;
|
|
600
|
-
|
|
582
|
+
gap: 4pt;
|
|
583
|
+
padding: 0 1pt;
|
|
584
|
+
font-size: 0.9em;
|
|
585
|
+
line-height: 1.3;
|
|
601
586
|
}
|
|
602
587
|
.info-row.clickable {
|
|
603
588
|
cursor: pointer;
|
|
@@ -610,10 +595,7 @@
|
|
|
610
595
|
display: flex;
|
|
611
596
|
align-items: center;
|
|
612
597
|
justify-content: space-between;
|
|
613
|
-
gap:
|
|
614
|
-
h4 {
|
|
615
|
-
margin: 0.5em 0;
|
|
616
|
-
}
|
|
598
|
+
gap: 4pt;
|
|
617
599
|
}
|
|
618
600
|
.sites-toggle,
|
|
619
601
|
.site-window-controls button {
|
|
@@ -630,8 +612,8 @@
|
|
|
630
612
|
.site-filter {
|
|
631
613
|
box-sizing: border-box;
|
|
632
614
|
width: 100%;
|
|
633
|
-
margin-bottom:
|
|
634
|
-
padding:
|
|
615
|
+
margin-bottom: 3pt;
|
|
616
|
+
padding: 3pt 5pt;
|
|
635
617
|
border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
|
|
636
618
|
border-radius: var(--border-radius, 3pt);
|
|
637
619
|
background: color-mix(in srgb, var(--pane-bg, Canvas) 88%, currentColor);
|
|
@@ -646,8 +628,8 @@
|
|
|
646
628
|
display: flex;
|
|
647
629
|
align-items: center;
|
|
648
630
|
justify-content: space-between;
|
|
649
|
-
gap:
|
|
650
|
-
margin-bottom:
|
|
631
|
+
gap: 4pt;
|
|
632
|
+
margin-bottom: 3pt;
|
|
651
633
|
font-size: 0.8em;
|
|
652
634
|
button {
|
|
653
635
|
padding: 2pt 5pt;
|
|
@@ -659,13 +641,12 @@
|
|
|
659
641
|
}
|
|
660
642
|
.site-cards {
|
|
661
643
|
display: grid;
|
|
662
|
-
gap:
|
|
644
|
+
gap: 6pt;
|
|
663
645
|
}
|
|
664
646
|
.site-card {
|
|
665
647
|
border-left: 3px solid var(--site-color, #888);
|
|
666
|
-
border-radius: var(--border-radius, 3pt);
|
|
667
648
|
background: color-mix(in srgb, currentColor 4%, transparent);
|
|
668
|
-
padding:
|
|
649
|
+
padding: 4pt 8pt;
|
|
669
650
|
cursor: pointer;
|
|
670
651
|
outline: none;
|
|
671
652
|
&:is(:hover, :focus-visible, .highlighted) {
|
|
@@ -676,16 +657,12 @@
|
|
|
676
657
|
background: color-mix(in srgb, var(--site-color, currentColor) 25%, transparent);
|
|
677
658
|
}
|
|
678
659
|
}
|
|
679
|
-
.site-card-header,
|
|
680
660
|
.site-title,
|
|
681
661
|
.site-detail {
|
|
682
662
|
display: flex;
|
|
683
663
|
align-items: center;
|
|
684
664
|
gap: 5pt;
|
|
685
665
|
}
|
|
686
|
-
.site-card-header {
|
|
687
|
-
justify-content: space-between;
|
|
688
|
-
}
|
|
689
666
|
.site-title {
|
|
690
667
|
min-width: 0;
|
|
691
668
|
span:last-child {
|
|
@@ -700,13 +677,17 @@
|
|
|
700
677
|
background: var(--site-color, #888);
|
|
701
678
|
}
|
|
702
679
|
.site-card-details {
|
|
703
|
-
display:
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
680
|
+
display: flex;
|
|
681
|
+
flex-wrap: wrap;
|
|
682
|
+
gap: 1pt 4pt;
|
|
683
|
+
margin-top: 2pt;
|
|
684
|
+
font-size: 0.73em;
|
|
685
|
+
line-height: 1.3;
|
|
707
686
|
}
|
|
708
687
|
.site-detail {
|
|
709
|
-
|
|
688
|
+
gap: 2pt;
|
|
689
|
+
min-width: 0;
|
|
690
|
+
max-width: 100%;
|
|
710
691
|
span:first-child {
|
|
711
692
|
opacity: 0.75;
|
|
712
693
|
}
|
|
@@ -735,8 +716,16 @@
|
|
|
735
716
|
}
|
|
736
717
|
}
|
|
737
718
|
.tips-item {
|
|
738
|
-
|
|
739
|
-
|
|
719
|
+
display: grid;
|
|
720
|
+
grid-template-columns: max-content minmax(0, 1fr);
|
|
721
|
+
gap: 4pt;
|
|
722
|
+
padding: 1pt 0;
|
|
723
|
+
font-size: 0.8em;
|
|
724
|
+
line-height: 1.25;
|
|
725
|
+
span:first-child {
|
|
726
|
+
font-weight: 600;
|
|
727
|
+
text-align: right;
|
|
728
|
+
}
|
|
740
729
|
span:last-child {
|
|
741
730
|
opacity: 0.8;
|
|
742
731
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { D3InterpolateName } from '../colors'
|
|
3
|
-
import { get_d3_interpolator } from '../colors'
|
|
3
|
+
import { get_d3_interpolator, is_dark_mode, watch_dark_mode } from '../colors'
|
|
4
4
|
import type { ElementSymbol } from '../element'
|
|
5
|
-
import {
|
|
5
|
+
import { element_by_symbol } from '../element'
|
|
6
6
|
import Isosurface from '../isosurface/Isosurface.svelte'
|
|
7
7
|
import type { IsosurfaceSettings, VolumetricData } from '../isosurface/types'
|
|
8
8
|
import { DEFAULT_ISOSURFACE_SETTINGS } from '../isosurface/types'
|
|
@@ -211,13 +211,14 @@
|
|
|
211
211
|
dragging_atoms = $bindable(false),
|
|
212
212
|
volumetric_data = undefined,
|
|
213
213
|
isosurface_settings = DEFAULT_ISOSURFACE_SETTINGS,
|
|
214
|
+
active_volume_idx = 0,
|
|
215
|
+
volume_scaling = [1, 1, 1],
|
|
214
216
|
interactive = true,
|
|
215
217
|
}: SceneControlProps & {
|
|
216
218
|
structure?: AnyStructure
|
|
217
219
|
base_structure?: AnyStructure // The original structure without image atoms, used for property color calculation
|
|
218
220
|
atom_radius?: number // scale factor for atomic radii
|
|
219
|
-
same_size_atoms?: boolean //
|
|
220
|
-
// determined by the atomic radius of the element
|
|
221
|
+
same_size_atoms?: boolean // uniform radius for all atoms (else per-element atomic radii)
|
|
221
222
|
camera_position?: [x: number, y: number, z: number] // initial camera position from which to render the scene
|
|
222
223
|
camera_target?: Vec3 // external orbit-controls target for pan synchronization
|
|
223
224
|
// When set (and camera_position is unset/zero), auto-place the camera along this
|
|
@@ -316,8 +317,12 @@
|
|
|
316
317
|
add_element?: ElementSymbol // element to add when clicking in add-atom mode
|
|
317
318
|
cursor?: string // cursor style for the 3D canvas
|
|
318
319
|
dragging_atoms?: boolean // true while TransformControls drag is active (skips expensive recalculations)
|
|
319
|
-
|
|
320
|
+
// Loaded volumetric datasets for isosurface rendering (single volume accepted
|
|
321
|
+
// for backwards compatibility)
|
|
322
|
+
volumetric_data?: VolumetricData | VolumetricData[]
|
|
320
323
|
isosurface_settings?: IsosurfaceSettings // Isosurface rendering settings
|
|
324
|
+
active_volume_idx?: number // Volume implicit single-isovalue settings apply to
|
|
325
|
+
volume_scaling?: Vec3 // Supercell tiling applied to isosurface geometry
|
|
321
326
|
// When false, render the scene without hover/edit raycast helpers. Used by multi-side
|
|
322
327
|
// view so inactive panes skip interaction-only work while the active pane stays editable.
|
|
323
328
|
interactive?: boolean
|
|
@@ -328,6 +333,8 @@
|
|
|
328
333
|
{ step: 0.015, frequency: 5 },
|
|
329
334
|
)
|
|
330
335
|
let pulse_opacity = $derived(0.15 + 0.25 * pulse.unit)
|
|
336
|
+
let dark_mode = $state(is_dark_mode())
|
|
337
|
+
$effect(() => watch_dark_mode((dark) => (dark_mode = dark)))
|
|
331
338
|
|
|
332
339
|
bind_renderer((threlte_scene, threlte_camera) => {
|
|
333
340
|
scene = threlte_scene
|
|
@@ -431,6 +438,22 @@
|
|
|
431
438
|
bond_context_target = null
|
|
432
439
|
}
|
|
433
440
|
|
|
441
|
+
// Shared handlers for bond context-menu buttons: act on pointerdown (a click would
|
|
442
|
+
// arrive after orbit-controls' start handler already closed the menu) or Enter/Space
|
|
443
|
+
const menu_action_props = (action: () => void) => {
|
|
444
|
+
const run = (event: Event) => {
|
|
445
|
+
event.preventDefault()
|
|
446
|
+
event.stopPropagation()
|
|
447
|
+
action()
|
|
448
|
+
}
|
|
449
|
+
return {
|
|
450
|
+
onpointerdown: run,
|
|
451
|
+
onkeydown: (event: KeyboardEvent) => {
|
|
452
|
+
if (event.key === `Enter` || event.key === ` `) run(event)
|
|
453
|
+
},
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
434
457
|
const canonical_bond_target = (bond: BondKeyTarget): BondKeyTarget =>
|
|
435
458
|
canonicalize_bond_target(bond, structure?.sites)
|
|
436
459
|
|
|
@@ -500,20 +523,14 @@
|
|
|
500
523
|
const BOND_ENDPOINT_HIT_FRACTION = 0.3
|
|
501
524
|
const BOND_ENDPOINT_SITE_MATCH_TOLERANCE = 1e-6
|
|
502
525
|
const EDITABLE_ATOM_HIT_RADIUS_SCALE = 1.15
|
|
503
|
-
const skip_raycast = (): void => undefined
|
|
504
526
|
|
|
505
527
|
function apply_bond_transform(mesh: Mesh, bond: BondPair): void {
|
|
506
528
|
mesh.matrix.fromArray(bond.transform_matrix)
|
|
507
529
|
mesh.matrixWorldNeedsUpdate = true
|
|
508
530
|
}
|
|
509
531
|
|
|
510
|
-
function apply_non_raycastable_bond_hit_transform(mesh: Mesh, bond: BondPair): void {
|
|
511
|
-
apply_bond_transform(mesh, bond)
|
|
512
|
-
disable_raycast(mesh)
|
|
513
|
-
}
|
|
514
|
-
|
|
515
532
|
function disable_raycast(mesh: Mesh): void {
|
|
516
|
-
mesh.raycast =
|
|
533
|
+
mesh.raycast = () => undefined
|
|
517
534
|
}
|
|
518
535
|
|
|
519
536
|
function site_world_position(parent: Object3D, site: Site): Vector3 {
|
|
@@ -1464,7 +1481,7 @@
|
|
|
1464
1481
|
: get_site_radius(site, site_idx)
|
|
1465
1482
|
targets.push({ kind, site, site_idx, color, radius })
|
|
1466
1483
|
}
|
|
1467
|
-
add(`hover`, hovered_site, hovered_idx, `white`)
|
|
1484
|
+
add(`hover`, hovered_site, hovered_idx, dark_mode ? `white` : `#333`)
|
|
1468
1485
|
for (const idx of selected_sites ?? []) {
|
|
1469
1486
|
add(`selected`, structure?.sites?.[idx] ?? null, idx, selection_highlight_color)
|
|
1470
1487
|
}
|
|
@@ -1689,12 +1706,6 @@
|
|
|
1689
1706
|
})
|
|
1690
1707
|
</script>
|
|
1691
1708
|
|
|
1692
|
-
{#snippet bond_instanced_mesh_snippet(group: ComponentProps<typeof Bond>[`group`])}
|
|
1693
|
-
{#key group.instances.length}
|
|
1694
|
-
<Bond {group} />
|
|
1695
|
-
{/key}
|
|
1696
|
-
{/snippet}
|
|
1697
|
-
|
|
1698
1709
|
{#snippet site_label_snippet(site_idx: number)}
|
|
1699
1710
|
{@const site = structure!.sites[site_idx]}
|
|
1700
1711
|
{#if site}
|
|
@@ -1800,42 +1811,27 @@
|
|
|
1800
1811
|
/>
|
|
1801
1812
|
</T.Mesh>
|
|
1802
1813
|
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
args={[
|
|
1825
|
-
0.5,
|
|
1826
|
-
sphere_segments,
|
|
1827
|
-
PARTIAL_OCCUPANCY_CAP_ARC.end_cap_arc_start,
|
|
1828
|
-
PARTIAL_OCCUPANCY_CAP_ARC.arc_length,
|
|
1829
|
-
]}
|
|
1830
|
-
/>
|
|
1831
|
-
<T.MeshStandardMaterial
|
|
1832
|
-
color={partial_color}
|
|
1833
|
-
side={2}
|
|
1834
|
-
opacity={ghost_opacity}
|
|
1835
|
-
transparent={partial_edit_image}
|
|
1836
|
-
/>
|
|
1837
|
-
</T.Mesh>
|
|
1838
|
-
{/if}
|
|
1814
|
+
<!-- Flat caps closing the wedge at its start/end azimuthal angles -->
|
|
1815
|
+
{#each [[atom.render_start_cap, atom.start_phi, PARTIAL_OCCUPANCY_CAP_ARC.start_cap_arc_start], [atom.render_end_cap, atom.end_phi, PARTIAL_OCCUPANCY_CAP_ARC.end_cap_arc_start]] as const as [render_cap, phi, arc_start], cap_idx (cap_idx)}
|
|
1816
|
+
{#if render_cap}
|
|
1817
|
+
<T.Mesh rotation={[0, phi, 0]}>
|
|
1818
|
+
<T.CircleGeometry
|
|
1819
|
+
args={[
|
|
1820
|
+
0.5,
|
|
1821
|
+
sphere_segments,
|
|
1822
|
+
arc_start,
|
|
1823
|
+
PARTIAL_OCCUPANCY_CAP_ARC.arc_length,
|
|
1824
|
+
]}
|
|
1825
|
+
/>
|
|
1826
|
+
<T.MeshStandardMaterial
|
|
1827
|
+
color={partial_color}
|
|
1828
|
+
side={2}
|
|
1829
|
+
opacity={ghost_opacity}
|
|
1830
|
+
transparent={partial_edit_image}
|
|
1831
|
+
/>
|
|
1832
|
+
</T.Mesh>
|
|
1833
|
+
{/if}
|
|
1834
|
+
{/each}
|
|
1839
1835
|
</T.Group>
|
|
1840
1836
|
{/each}
|
|
1841
1837
|
|
|
@@ -1881,11 +1877,11 @@
|
|
|
1881
1877
|
{/each}
|
|
1882
1878
|
|
|
1883
1879
|
<!-- Instanced bond rendering with gradient colors -->
|
|
1884
|
-
{#
|
|
1885
|
-
{#
|
|
1886
|
-
{
|
|
1887
|
-
{/
|
|
1888
|
-
{/
|
|
1880
|
+
{#each instanced_bond_groups as group (group.thickness + group.instances.length)}
|
|
1881
|
+
{#key group.instances.length}
|
|
1882
|
+
<Bond {group} />
|
|
1883
|
+
{/key}
|
|
1884
|
+
{/each}
|
|
1889
1885
|
|
|
1890
1886
|
<!-- Coordination polyhedra: all faces in one merged mesh, edges in one
|
|
1891
1887
|
LineSegments (1-2 draw calls regardless of supercell size) -->
|
|
@@ -1954,7 +1950,10 @@
|
|
|
1954
1950
|
{#if is_hovered}
|
|
1955
1951
|
<T.Mesh
|
|
1956
1952
|
matrixAutoUpdate={false}
|
|
1957
|
-
oncreate={(ref) =>
|
|
1953
|
+
oncreate={(ref) => {
|
|
1954
|
+
apply_bond_transform(ref, bond)
|
|
1955
|
+
disable_raycast(ref)
|
|
1956
|
+
}}
|
|
1958
1957
|
>
|
|
1959
1958
|
<T.CylinderGeometry args={[bond_hover_radius, bond_hover_radius, 1, 6]} />
|
|
1960
1959
|
<T.MeshBasicMaterial
|
|
@@ -1996,52 +1995,15 @@
|
|
|
1996
1995
|
{#each BOND_ORDER_OPTIONS as { order, label } (label)}
|
|
1997
1996
|
<button
|
|
1998
1997
|
type="button"
|
|
1999
|
-
|
|
2000
|
-
event.preventDefault()
|
|
2001
|
-
event.stopPropagation()
|
|
2002
|
-
set_context_bond_order(order)
|
|
2003
|
-
}}
|
|
2004
|
-
onkeydown={(event: KeyboardEvent) => {
|
|
2005
|
-
if (event.key !== `Enter` && event.key !== ` `) return
|
|
2006
|
-
event.preventDefault()
|
|
2007
|
-
event.stopPropagation()
|
|
2008
|
-
set_context_bond_order(order)
|
|
2009
|
-
}}
|
|
1998
|
+
{...menu_action_props(() => set_context_bond_order(order))}
|
|
2010
1999
|
>
|
|
2011
2000
|
{label}
|
|
2012
2001
|
</button>
|
|
2013
2002
|
{/each}
|
|
2014
|
-
<button
|
|
2015
|
-
type="button"
|
|
2016
|
-
class="remove"
|
|
2017
|
-
onpointerdown={(event: PointerEvent) => {
|
|
2018
|
-
event.preventDefault()
|
|
2019
|
-
event.stopPropagation()
|
|
2020
|
-
remove_context_bond()
|
|
2021
|
-
}}
|
|
2022
|
-
onkeydown={(event: KeyboardEvent) => {
|
|
2023
|
-
if (event.key !== `Enter` && event.key !== ` `) return
|
|
2024
|
-
event.preventDefault()
|
|
2025
|
-
event.stopPropagation()
|
|
2026
|
-
remove_context_bond()
|
|
2027
|
-
}}
|
|
2028
|
-
>
|
|
2003
|
+
<button type="button" class="remove" {...menu_action_props(remove_context_bond)}>
|
|
2029
2004
|
Remove
|
|
2030
2005
|
</button>
|
|
2031
|
-
<button
|
|
2032
|
-
type="button"
|
|
2033
|
-
onpointerdown={(event: PointerEvent) => {
|
|
2034
|
-
event.preventDefault()
|
|
2035
|
-
event.stopPropagation()
|
|
2036
|
-
close_bond_context_menu()
|
|
2037
|
-
}}
|
|
2038
|
-
onkeydown={(event: KeyboardEvent) => {
|
|
2039
|
-
if (event.key !== `Enter` && event.key !== ` `) return
|
|
2040
|
-
event.preventDefault()
|
|
2041
|
-
event.stopPropagation()
|
|
2042
|
-
close_bond_context_menu()
|
|
2043
|
-
}}
|
|
2044
|
-
>
|
|
2006
|
+
<button type="button" {...menu_action_props(close_bond_context_menu)}>
|
|
2045
2007
|
Close
|
|
2046
2008
|
</button>
|
|
2047
2009
|
</div>
|
|
@@ -2122,7 +2084,7 @@
|
|
|
2122
2084
|
<div class="elements">
|
|
2123
2085
|
{#each tooltip_species as { element, occu, oxidation_state: oxi_state }, idx (`${element ?? ``}-${occu ?? ``}-${oxi_state ?? ``}-${idx}`)}
|
|
2124
2086
|
{@const element_name =
|
|
2125
|
-
|
|
2087
|
+
element_by_symbol.get(element as ElementSymbol)?.name ?? ``}
|
|
2126
2088
|
<span class="species">
|
|
2127
2089
|
{#if occu !== 1}<span class="occupancy">{format_num(occu, `.3~f`)}</span>{/if}
|
|
2128
2090
|
<strong>
|
|
@@ -2228,7 +2190,15 @@
|
|
|
2228
2190
|
|
|
2229
2191
|
<!-- Isosurface rendering from volumetric data (CHGCAR, .cube files) -->
|
|
2230
2192
|
{#if volumetric_data && isosurface_settings}
|
|
2231
|
-
|
|
2193
|
+
{@const volume_list = Array.isArray(volumetric_data)
|
|
2194
|
+
? volumetric_data
|
|
2195
|
+
: [volumetric_data]}
|
|
2196
|
+
<Isosurface
|
|
2197
|
+
volumes={volume_list}
|
|
2198
|
+
settings={isosurface_settings}
|
|
2199
|
+
{active_volume_idx}
|
|
2200
|
+
tiling={volume_scaling}
|
|
2201
|
+
/>
|
|
2232
2202
|
{/if}
|
|
2233
2203
|
|
|
2234
2204
|
<!-- Measurement overlays for measured sites -->
|
|
@@ -2241,17 +2211,13 @@
|
|
|
2241
2211
|
{@const pos_i = site_i.xyz}
|
|
2242
2212
|
{@const pos_j = site_j.xyz}
|
|
2243
2213
|
<Cylinder from={pos_i} to={pos_j} thickness={0.12} color={measure_line_color} />
|
|
2244
|
-
{@const
|
|
2245
|
-
(pos_i[0] + pos_j[0]) / 2,
|
|
2246
|
-
(pos_i[1] + pos_j[1]) / 2,
|
|
2247
|
-
(pos_i[2] + pos_j[2]) / 2,
|
|
2248
|
-
] as Vec3}
|
|
2214
|
+
{@const mid_pos = midpoint(pos_i, pos_j)}
|
|
2249
2215
|
{@const direct = math.euclidean_dist(pos_i, pos_j)}
|
|
2250
2216
|
{@const pbc = lattice
|
|
2251
2217
|
? measure.distance_pbc(pos_i, pos_j, lattice.matrix, undefined, lattice.pbc)
|
|
2252
2218
|
: direct}
|
|
2253
2219
|
{@const differ = lattice ? Math.abs(pbc - direct) > 1e-6 : false}
|
|
2254
|
-
<extras.HTML center position={
|
|
2220
|
+
<extras.HTML center position={mid_pos}>
|
|
2255
2221
|
<span class="measure-label">
|
|
2256
2222
|
{#if differ}
|
|
2257
2223
|
PBC: {format_num(pbc, float_fmt)} Å<br /><small>
|
|
@@ -106,8 +106,10 @@ type $$ComponentProps = SceneControlProps & {
|
|
|
106
106
|
add_element?: ElementSymbol;
|
|
107
107
|
cursor?: string;
|
|
108
108
|
dragging_atoms?: boolean;
|
|
109
|
-
volumetric_data?: VolumetricData;
|
|
109
|
+
volumetric_data?: VolumetricData | VolumetricData[];
|
|
110
110
|
isosurface_settings?: IsosurfaceSettings;
|
|
111
|
+
active_volume_idx?: number;
|
|
112
|
+
volume_scaling?: Vec3;
|
|
111
113
|
interactive?: boolean;
|
|
112
114
|
};
|
|
113
115
|
declare const StructureScene: import("svelte").Component<$$ComponentProps, {}, "cursor" | "camera" | "site_label_offset" | "vector_configs" | "orbit_controls" | "hovered_idx" | "hovered_site" | "polyhedra_rendered_elements" | "camera_is_moving" | "selected_sites" | "measured_sites" | "added_bonds" | "removed_bonds" | "bond_order_overrides" | "bond_edit_mode" | "active_sites" | "scene" | "rotation_target_ref" | "initial_computed_zoom" | "hidden_elements" | "hidden_prop_vals" | "element_radius_overrides" | "site_radius_overrides" | "add_atom_mode" | "add_element" | "dragging_atoms">;
|