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.
Files changed (229) hide show
  1. package/dist/MillerIndexInput.svelte +5 -5
  2. package/dist/api/optimade.js +3 -3
  3. package/dist/brillouin/BrillouinZone.svelte +5 -2
  4. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  5. package/dist/brillouin/BrillouinZoneExportPane.svelte +1 -3
  6. package/dist/brillouin/BrillouinZoneInfoPane.svelte +1 -1
  7. package/dist/brillouin/BrillouinZoneScene.svelte +5 -5
  8. package/dist/brillouin/compute.js +21 -21
  9. package/dist/brillouin/index.d.ts +1 -1
  10. package/dist/brillouin/index.js +0 -1
  11. package/dist/brillouin/types.d.ts +8 -13
  12. package/dist/chempot-diagram/ChemPotDiagram.svelte +3 -3
  13. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +3 -4
  14. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +33 -34
  15. package/dist/chempot-diagram/compute.js +1 -7
  16. package/dist/chempot-diagram/temperature.d.ts +1 -1
  17. package/dist/chempot-diagram/temperature.js +1 -3
  18. package/dist/chempot-diagram/types.d.ts +4 -9
  19. package/dist/colors/index.js +5 -5
  20. package/dist/composition/Composition.svelte +2 -1
  21. package/dist/composition/Formula.svelte +7 -4
  22. package/dist/composition/FormulaFilter.svelte +1 -3
  23. package/dist/composition/format.js +4 -4
  24. package/dist/composition/parse.d.ts +2 -1
  25. package/dist/composition/parse.js +61 -46
  26. package/dist/convex-hull/ConvexHull2D.svelte +62 -51
  27. package/dist/convex-hull/ConvexHull3D.svelte +101 -90
  28. package/dist/convex-hull/ConvexHull4D.svelte +70 -58
  29. package/dist/convex-hull/ConvexHullControls.svelte +24 -35
  30. package/dist/convex-hull/ConvexHullInfoPane.svelte +8 -5
  31. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +2 -0
  32. package/dist/convex-hull/ConvexHullStats.svelte +9 -2
  33. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +2 -0
  34. package/dist/convex-hull/GasPressureControls.svelte +7 -7
  35. package/dist/convex-hull/StructurePopup.svelte +65 -30
  36. package/dist/convex-hull/StructurePopup.svelte.d.ts +6 -6
  37. package/dist/convex-hull/TemperatureSlider.svelte +8 -5
  38. package/dist/convex-hull/barycentric-coords.d.ts +2 -2
  39. package/dist/convex-hull/barycentric-coords.js +2 -2
  40. package/dist/convex-hull/gas-thermodynamics.js +2 -4
  41. package/dist/convex-hull/helpers.d.ts +13 -2
  42. package/dist/convex-hull/helpers.js +37 -16
  43. package/dist/convex-hull/index.d.ts +1 -0
  44. package/dist/convex-hull/index.js +1 -0
  45. package/dist/convex-hull/thermodynamics.d.ts +2 -1
  46. package/dist/convex-hull/thermodynamics.js +7 -7
  47. package/dist/convex-hull/types.d.ts +15 -15
  48. package/dist/effects.svelte.d.ts +12 -0
  49. package/dist/effects.svelte.js +37 -0
  50. package/dist/element/BohrAtom.svelte +4 -4
  51. package/dist/element/data.json.gz.d.ts +3 -1
  52. package/dist/element/index.d.ts +1 -1
  53. package/dist/element/index.js +0 -1
  54. package/dist/fermi-surface/FermiSurface.svelte +4 -4
  55. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  56. package/dist/fermi-surface/FermiSurfaceControls.svelte +15 -19
  57. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  58. package/dist/fermi-surface/FermiSurfaceScene.svelte +8 -6
  59. package/dist/fermi-surface/compute.js +2 -2
  60. package/dist/fermi-surface/export.js +13 -26
  61. package/dist/fermi-surface/parse.js +8 -12
  62. package/dist/fermi-surface/types.d.ts +2 -5
  63. package/dist/heatmap-matrix/HeatmapMatrix.svelte +21 -3
  64. package/dist/heatmap-matrix/index.js +6 -6
  65. package/dist/io/decompress.d.ts +2 -1
  66. package/dist/io/decompress.js +1 -1
  67. package/dist/io/export.js +1 -1
  68. package/dist/io/index.d.ts +1 -1
  69. package/dist/io/index.js +0 -1
  70. package/dist/io/url-drop.js +7 -1
  71. package/dist/isosurface/IsosurfaceControls.svelte +11 -25
  72. package/dist/isosurface/slice.js +1 -1
  73. package/dist/isosurface/types.js +12 -12
  74. package/dist/labels.d.ts +1 -1
  75. package/dist/labels.js +14 -11
  76. package/dist/layout/InfoTag.svelte +6 -4
  77. package/dist/layout/PropertyFilter.svelte +4 -2
  78. package/dist/layout/json-tree/JsonTree.svelte +22 -14
  79. package/dist/layout/json-tree/JsonValue.svelte +2 -2
  80. package/dist/layout/json-tree/types.d.ts +3 -2
  81. package/dist/layout/json-tree/types.js +0 -1
  82. package/dist/layout/json-tree/utils.d.ts +4 -4
  83. package/dist/layout/json-tree/utils.js +12 -20
  84. package/dist/marching-cubes.js +13 -15
  85. package/dist/math.d.ts +11 -1
  86. package/dist/math.js +15 -6
  87. package/dist/overlays/DragControlTab.svelte +98 -0
  88. package/dist/overlays/DragControlTab.svelte.d.ts +8 -0
  89. package/dist/overlays/DraggablePane.svelte +7 -84
  90. package/dist/overlays/index.d.ts +1 -0
  91. package/dist/overlays/index.js +1 -0
  92. package/dist/periodic-table/PeriodicTable.svelte +11 -11
  93. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +4 -2
  94. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  95. package/dist/phase-diagram/PhaseDiagramControls.svelte +4 -9
  96. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  97. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +2 -10
  98. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +2 -3
  99. package/dist/phase-diagram/TdbInfoPanel.svelte +3 -3
  100. package/dist/phase-diagram/build-diagram.js +11 -18
  101. package/dist/phase-diagram/diagram-input.d.ts +5 -9
  102. package/dist/phase-diagram/index.d.ts +2 -2
  103. package/dist/phase-diagram/index.js +0 -2
  104. package/dist/phase-diagram/parse.d.ts +2 -2
  105. package/dist/phase-diagram/parse.js +6 -10
  106. package/dist/phase-diagram/svg-to-diagram.js +15 -15
  107. package/dist/phase-diagram/types.d.ts +5 -11
  108. package/dist/phase-diagram/utils.d.ts +2 -2
  109. package/dist/phase-diagram/utils.js +9 -11
  110. package/dist/plot/BarPlot.svelte +162 -314
  111. package/dist/plot/BarPlot.svelte.d.ts +5 -4
  112. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  113. package/dist/plot/BinnedScatterPlot.svelte +1114 -0
  114. package/dist/plot/BinnedScatterPlot.svelte.d.ts +66 -0
  115. package/dist/plot/ColorBar.svelte +19 -17
  116. package/dist/plot/ColorBar.svelte.d.ts +1 -1
  117. package/dist/plot/FillArea.svelte +2 -4
  118. package/dist/plot/FillArea.svelte.d.ts +1 -1
  119. package/dist/plot/Histogram.svelte +167 -281
  120. package/dist/plot/Histogram.svelte.d.ts +1 -1
  121. package/dist/plot/HistogramControls.svelte.d.ts +1 -1
  122. package/dist/plot/InteractiveAxisLabel.svelte +5 -3
  123. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  124. package/dist/plot/PlotAxis.svelte +169 -0
  125. package/dist/plot/PlotAxis.svelte.d.ts +24 -0
  126. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  127. package/dist/plot/ReferenceLine3D.svelte +53 -51
  128. package/dist/plot/ReferencePlane.svelte +39 -42
  129. package/dist/plot/ScatterPlot.svelte +300 -367
  130. package/dist/plot/ScatterPlot.svelte.d.ts +8 -5
  131. package/dist/plot/ScatterPlot3D.svelte +33 -6
  132. package/dist/plot/ScatterPlot3D.svelte.d.ts +3 -2
  133. package/dist/plot/ScatterPlot3DControls.svelte +9 -9
  134. package/dist/plot/ScatterPlotControls.svelte +3 -4
  135. package/dist/plot/ScatterPoint.svelte +18 -27
  136. package/dist/plot/ScatterPoint.svelte.d.ts +4 -3
  137. package/dist/plot/Surface3D.svelte +4 -7
  138. package/dist/plot/ZeroLines.svelte +2 -1
  139. package/dist/plot/ZeroLines.svelte.d.ts +2 -1
  140. package/dist/plot/ZoomRect.svelte +2 -2
  141. package/dist/plot/ZoomRect.svelte.d.ts +3 -3
  142. package/dist/plot/adaptive-density.d.ts +69 -0
  143. package/dist/plot/adaptive-density.js +191 -0
  144. package/dist/plot/auto-place.d.ts +43 -0
  145. package/dist/plot/auto-place.js +122 -0
  146. package/dist/plot/axis-utils.js +3 -5
  147. package/dist/plot/binned-scatter-types.d.ts +59 -0
  148. package/dist/plot/binned-scatter-types.js +1 -0
  149. package/dist/plot/data-cleaning.js +1 -1
  150. package/dist/plot/data-transform.js +1 -1
  151. package/dist/plot/fill-utils.d.ts +4 -9
  152. package/dist/plot/fill-utils.js +29 -44
  153. package/dist/plot/index.d.ts +4 -0
  154. package/dist/plot/index.js +2 -0
  155. package/dist/plot/interactions.d.ts +4 -4
  156. package/dist/plot/interactions.js +4 -3
  157. package/dist/plot/layout.d.ts +20 -2
  158. package/dist/plot/layout.js +59 -16
  159. package/dist/plot/reference-line.d.ts +1 -1
  160. package/dist/plot/reference-line.js +9 -11
  161. package/dist/plot/scales.d.ts +1 -1
  162. package/dist/plot/scales.js +20 -23
  163. package/dist/plot/types.d.ts +30 -58
  164. package/dist/plot/types.js +2 -6
  165. package/dist/plot/utils/label-placement.d.ts +24 -3
  166. package/dist/plot/utils/label-placement.js +82 -12
  167. package/dist/plot/utils/series-visibility.d.ts +8 -2
  168. package/dist/plot/utils/series-visibility.js +23 -5
  169. package/dist/rdf/RdfPlot.svelte +5 -5
  170. package/dist/rdf/calc-rdf.js +3 -3
  171. package/dist/sanitize.d.ts +2 -0
  172. package/dist/sanitize.js +2 -0
  173. package/dist/spectral/Bands.svelte +1 -1
  174. package/dist/spectral/BandsAndDos.svelte +22 -16
  175. package/dist/spectral/BrillouinBandsDos.svelte +20 -16
  176. package/dist/spectral/Dos.svelte +1 -1
  177. package/dist/spectral/helpers.d.ts +4 -2
  178. package/dist/spectral/helpers.js +44 -35
  179. package/dist/spectral/index.d.ts +1 -1
  180. package/dist/spectral/index.js +0 -1
  181. package/dist/structure/AtomLegend.svelte +23 -6
  182. package/dist/structure/AtomLegend.svelte.d.ts +1 -0
  183. package/dist/structure/CanvasTooltip.svelte +9 -9
  184. package/dist/structure/CanvasTooltip.svelte.d.ts +1 -1
  185. package/dist/structure/CellSelect.svelte +14 -16
  186. package/dist/structure/Structure.svelte +317 -68
  187. package/dist/structure/Structure.svelte.d.ts +4 -2
  188. package/dist/structure/StructureControls.svelte +20 -45
  189. package/dist/structure/StructureExportPane.svelte +2 -1
  190. package/dist/structure/StructureInfoPane.svelte +10 -8
  191. package/dist/structure/StructureScene.svelte +527 -177
  192. package/dist/structure/StructureScene.svelte.d.ts +5 -2
  193. package/dist/structure/atom-properties.js +4 -4
  194. package/dist/structure/bond-order-perception.js +115 -98
  195. package/dist/structure/bonding.d.ts +27 -1
  196. package/dist/structure/bonding.js +187 -16
  197. package/dist/structure/export.js +1 -1
  198. package/dist/structure/index.d.ts +3 -2
  199. package/dist/structure/index.js +0 -2
  200. package/dist/structure/parse.js +88 -59
  201. package/dist/symmetry/WyckoffTable.svelte +7 -0
  202. package/dist/symmetry/index.js +13 -14
  203. package/dist/table/HeatmapTable.svelte +45 -66
  204. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  205. package/dist/table/ToggleMenu.svelte +19 -10
  206. package/dist/theme/themes.mjs +12 -0
  207. package/dist/tooltip/index.d.ts +1 -1
  208. package/dist/tooltip/index.js +0 -1
  209. package/dist/trajectory/Trajectory.svelte +43 -15
  210. package/dist/trajectory/TrajectoryInfoPane.svelte +2 -2
  211. package/dist/trajectory/extract.js +1 -1
  212. package/dist/trajectory/frame-reader.js +4 -4
  213. package/dist/trajectory/helpers.d.ts +5 -4
  214. package/dist/trajectory/helpers.js +9 -17
  215. package/dist/trajectory/index.d.ts +2 -2
  216. package/dist/trajectory/index.js +2 -2
  217. package/dist/trajectory/parse/ase.js +4 -4
  218. package/dist/trajectory/parse/hdf5.js +1 -1
  219. package/dist/trajectory/parse/index.js +2 -3
  220. package/dist/trajectory/parse/lammps.js +1 -1
  221. package/dist/trajectory/parse/vasp.js +1 -1
  222. package/dist/trajectory/plotting.d.ts +1 -1
  223. package/dist/trajectory/plotting.js +38 -38
  224. package/dist/trajectory/types.d.ts +1 -1
  225. package/dist/utils.d.ts +1 -0
  226. package/dist/utils.js +9 -0
  227. package/dist/xrd/calc-xrd.js +3 -4
  228. package/dist/xrd/parse.js +1 -1
  229. package/package.json +42 -22
@@ -110,9 +110,10 @@
110
110
  } = $props()
111
111
 
112
112
  // Focus the multiselect input next to the "Color scale" label
113
- function focus_multiselect(evt: Event): void {
114
- ;(evt.currentTarget as HTMLElement).nextElementSibling
115
- ?.querySelector<HTMLInputElement>(`input`)?.focus()
113
+ function focus_multiselect(
114
+ evt: Event & { currentTarget: HTMLElement },
115
+ ): void {
116
+ evt.currentTarget.nextElementSibling?.querySelector<HTMLInputElement>(`input`)?.focus()
116
117
  }
117
118
  </script>
118
119
 
@@ -145,6 +146,7 @@
145
146
  class="toggle-btn {energy_source_mode === `precomputed` ? `active` : ``}"
146
147
  onclick={() => energy_source_mode = `precomputed`}
147
148
  {@attach tooltip({
149
+ allow_html: true,
148
150
  content: `Use precomputed formation energies (E<sub>form</sub>)`,
149
151
  })}
150
152
  >
@@ -154,6 +156,7 @@
154
156
  class="toggle-btn {energy_source_mode === `on-the-fly` ? `active` : ``}"
155
157
  onclick={() => energy_source_mode = `on-the-fly`}
156
158
  {@attach tooltip({
159
+ allow_html: true,
157
160
  content:
158
161
  `Compute formation energies and hull distances on the fly. Note: Missing pure-element reference entries default to E<sub>form</sub> = 0 eV/atom if not provided explicitly.`,
159
162
  })}
@@ -239,9 +242,7 @@
239
242
  <div class="marker unstable"></div>
240
243
  <span>Above hull{
241
244
  merged_controls.show_counts
242
- ? ` (${
243
- unstable_entries.filter((e) => e.visible).length
244
- }/${unstable_entries.length})`
245
+ ? ` (${show_unstable ? unstable_entries.length : 0}/${unstable_entries.length})`
245
246
  : ``
246
247
  }</span>
247
248
  </div>
@@ -277,9 +278,7 @@
277
278
  <input
278
279
  type="checkbox"
279
280
  checked={show_stable_labels}
280
- oninput={(
281
- evt,
282
- ) => (show_stable_labels = (evt.target as HTMLInputElement).checked)}
281
+ oninput={(evt) => (show_stable_labels = evt.currentTarget.checked)}
283
282
  />
284
283
  <span>Stable</span>
285
284
  </label>
@@ -287,10 +286,7 @@
287
286
  <input
288
287
  type="checkbox"
289
288
  checked={show_unstable_labels}
290
- oninput={(
291
- evt,
292
- ) => (show_unstable_labels =
293
- (evt.target as HTMLInputElement).checked)}
289
+ oninput={(evt) => (show_unstable_labels = evt.currentTarget.checked)}
294
290
  />
295
291
  <span>Unstable</span>
296
292
  </label>
@@ -327,7 +323,7 @@
327
323
  <input
328
324
  type="checkbox"
329
325
  checked={show_hull_faces}
330
- oninput={(e) => on_hull_faces_change?.((e.target as HTMLInputElement).checked)}
326
+ oninput={(event) => on_hull_faces_change?.(event.currentTarget.checked)}
331
327
  />
332
328
  <span>Show</span>
333
329
  </label>
@@ -336,7 +332,7 @@
336
332
  <input
337
333
  type="color"
338
334
  value={hull_face_color}
339
- oninput={(e) => on_hull_face_color_change?.((e.target as HTMLInputElement).value)}
335
+ oninput={(event) => on_hull_face_color_change?.(event.currentTarget.value)}
340
336
  {@attach tooltip({ content: `Set hull face color` })}
341
337
  style="width: 40px; height: 20px"
342
338
  />
@@ -383,20 +379,16 @@
383
379
  <!-- Ternary camera controls (elevation/azimuth) -->
384
380
  <label
385
381
  class="angle-input"
386
- {@attach tooltip({
387
- content:
388
- `Elevation angle (0° = look down z-axis, 90° = side view, 180° = look up z-axis)`,
389
- })}
382
+ {@attach tooltip({ content: `Elevation angle (0° = look down z-axis, 90° = side view, 180° = look up z-axis)` })}
390
383
  >
391
384
  <span>Elev</span>
392
385
  <input
393
386
  type="number"
394
387
  value={camera.elevation.toFixed(0)}
395
388
  step="5"
396
- oninput={(e) =>
397
- camera.elevation = parseFloat(
398
- (e.target as HTMLInputElement).value,
399
- )}
389
+ oninput={(event) => {
390
+ camera.elevation = parseFloat(event.currentTarget.value)
391
+ }}
400
392
  style="width: 3em"
401
393
  />
402
394
  <span>°</span>
@@ -410,10 +402,9 @@
410
402
  type="number"
411
403
  value={camera.azimuth.toFixed(0)}
412
404
  step="15"
413
- oninput={(e) =>
414
- camera.azimuth = parseFloat(
415
- (e.target as HTMLInputElement).value,
416
- )}
405
+ oninput={(event) => {
406
+ camera.azimuth = parseFloat(event.currentTarget.value)
407
+ }}
417
408
  style="width: 3em"
418
409
  />
419
410
  <span>°</span>
@@ -431,10 +422,9 @@
431
422
  step="0.1"
432
423
  min={-Math.PI / 3}
433
424
  max={Math.PI / 3}
434
- oninput={(e) =>
435
- camera.rotation_x = parseFloat(
436
- (e.target as HTMLInputElement).value,
437
- )}
425
+ oninput={(event) => {
426
+ camera.rotation_x = parseFloat(event.currentTarget.value)
427
+ }}
438
428
  style="width: 3em"
439
429
  />
440
430
  </label>
@@ -447,10 +437,9 @@
447
437
  type="number"
448
438
  value={(camera.rotation_y ?? 0).toFixed(2)}
449
439
  step="0.1"
450
- oninput={(e) =>
451
- camera.rotation_y = parseFloat(
452
- (e.target as HTMLInputElement).value,
453
- )}
440
+ oninput={(event) => {
441
+ camera.rotation_y = parseFloat(event.currentTarget.value)
442
+ }}
454
443
  style="width: 3em"
455
444
  />
456
445
  </label>
@@ -23,6 +23,8 @@
23
23
  phase_stats,
24
24
  stable_entries,
25
25
  unstable_entries,
26
+ show_stable = true,
27
+ show_unstable = true,
26
28
  max_hull_dist_show_phases,
27
29
  max_hull_dist_show_labels,
28
30
  label_threshold,
@@ -34,6 +36,8 @@
34
36
  phase_stats: PhaseStats | null
35
37
  stable_entries: ConvexHullEntry[]
36
38
  unstable_entries: ConvexHullEntry[]
39
+ show_stable?: boolean
40
+ show_unstable?: boolean
37
41
  max_hull_dist_show_phases: number
38
42
  max_hull_dist_show_labels: number
39
43
  label_threshold: number
@@ -42,18 +46,15 @@
42
46
  pane_props?: ComponentProps<typeof DraggablePane>[`pane_props`]
43
47
  } = $props()
44
48
 
45
- const count_visible = (entries: ConvexHullEntry[]): number =>
46
- entries.reduce((count, entry) => count + Number(entry.visible), 0)
47
-
48
49
  let settings_rows = $derived([
49
50
  {
50
51
  label: `Visible stable`,
51
- value: `${count_visible(stable_entries)} / ${stable_entries.length}`,
52
+ value: `${show_stable ? stable_entries.length : 0} / ${stable_entries.length}`,
52
53
  key: `hull-visible-stable`,
53
54
  },
54
55
  {
55
56
  label: `Visible unstable`,
56
- value: `${count_visible(unstable_entries)} / ${unstable_entries.length}`,
57
+ value: `${show_unstable ? unstable_entries.length : 0} / ${unstable_entries.length}`,
57
58
  key: `hull-visible-unstable`,
58
59
  },
59
60
  {
@@ -108,6 +109,8 @@
108
109
  {phase_stats}
109
110
  {stable_entries}
110
111
  {unstable_entries}
112
+ {show_stable}
113
+ {show_unstable}
111
114
  style="padding: 3pt; background: var(--pane-bg); --hull-stats-table-height: 30rem"
112
115
  />
113
116
 
@@ -6,6 +6,8 @@ type $$ComponentProps = Omit<HTMLAttributes<HTMLDivElement>, `onclose`> & {
6
6
  phase_stats: PhaseStats | null;
7
7
  stable_entries: ConvexHullEntry[];
8
8
  unstable_entries: ConvexHullEntry[];
9
+ show_stable?: boolean;
10
+ show_unstable?: boolean;
9
11
  max_hull_dist_show_phases: number;
10
12
  max_hull_dist_show_labels: number;
11
13
  label_threshold: number;
@@ -19,6 +19,8 @@
19
19
  phase_stats,
20
20
  stable_entries,
21
21
  unstable_entries,
22
+ show_stable = true,
23
+ show_unstable = true,
22
24
  layout = `toggle`,
23
25
  on_entry_click,
24
26
  highlighted_entry_id,
@@ -31,6 +33,8 @@
31
33
  phase_stats: PhaseStats | null
32
34
  stable_entries: ConvexHullEntry[]
33
35
  unstable_entries: ConvexHullEntry[]
36
+ show_stable?: boolean
37
+ show_unstable?: boolean
34
38
  // 'toggle' shows stats/table with toggle buttons (default)
35
39
  // 'side-by-side' shows both stats and table next to each other without toggle
36
40
  layout?: `toggle` | `side-by-side`
@@ -82,6 +86,10 @@
82
86
 
83
87
  // Shared concatenation of stable + unstable for histograms
84
88
  let all_entries = $derived([...stable_entries, ...unstable_entries])
89
+ let shown_entries = $derived([
90
+ ...(show_stable ? stable_entries : []),
91
+ ...(show_unstable ? unstable_entries : []),
92
+ ])
85
93
 
86
94
  // Static arity labels for phase breakdown display
87
95
  const arity_types: [string, PhaseArityField, number][] = [
@@ -222,8 +230,7 @@
222
230
 
223
231
  // Table view: visible entries filtered by min element count and formula
224
232
  let visible_entries = $derived(
225
- all_entries.filter((entry) => {
226
- if (!entry.visible) return false
233
+ shown_entries.filter((entry) => {
227
234
  if (min_n_elements > 1 && get_arity(entry) < min_n_elements) return false
228
235
  if (
229
236
  active_formula_filter &&
@@ -4,6 +4,8 @@ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
4
4
  phase_stats: PhaseStats | null;
5
5
  stable_entries: ConvexHullEntry[];
6
6
  unstable_entries: ConvexHullEntry[];
7
+ show_stable?: boolean;
8
+ show_unstable?: boolean;
7
9
  layout?: `toggle` | `side-by-side`;
8
10
  on_entry_click?: (entry: ConvexHullEntry) => void;
9
11
  highlighted_entry_id?: string;
@@ -90,8 +90,11 @@
90
90
  }
91
91
  }
92
92
 
93
- function handle_slider_end(gas: GasSpecies, event: Event): void {
94
- const P = slider_to_pressure(+(event.currentTarget as HTMLInputElement).value)
93
+ function handle_slider_end(
94
+ gas: GasSpecies,
95
+ event: Event & { currentTarget: HTMLInputElement },
96
+ ): void {
97
+ const P = slider_to_pressure(+event.currentTarget.value)
95
98
  pressures = { ...pressures, [gas]: P }
96
99
  // Clear only this gas's preview (don't reset other sliders being dragged simultaneously)
97
100
  const { [gas]: _removed_preview, ...remaining_previews } = preview_pressures
@@ -112,13 +115,10 @@
112
115
  {#each enabled_gases as gas (gas)}
113
116
  {@const P = get_pressure(gas)}
114
117
  {@const mu = get_mu(gas)}
118
+ {@const tooltip_content = `${gas} partial pressure for μ(T,P)\nμ = ${format_chemical_potential(mu, 3)}`}
115
119
  <div
116
120
  class="pressure-slider"
117
- {@attach tooltip({
118
- content: `${gas} partial pressure for μ(T,P)\nμ = ${
119
- format_chemical_potential(mu, 3)
120
- }`,
121
- })}
121
+ {@attach tooltip({ content: tooltip_content })}
122
122
  >
123
123
  <label class="pressure-label">
124
124
  <input
@@ -1,9 +1,15 @@
1
1
  <script lang="ts">
2
2
  import type { AnyStructure } from '../structure'
3
+ import { get_electro_neg_formula } from '../composition'
3
4
  import Icon from '../Icon.svelte'
4
5
  import { format_num } from '../labels'
6
+ import { DragControlTab } from '../overlays'
7
+ import { sanitize_formula } from '../sanitize'
5
8
  import { Structure } from '../structure'
9
+ import type { StructurePopupContext, StructurePopupStats } from './types'
10
+ import type { Snippet } from 'svelte'
6
11
  import type { HTMLAttributes } from 'svelte/elements'
12
+ import { draggable } from 'svelte-multiselect/attachments'
7
13
 
8
14
  let {
9
15
  structure,
@@ -12,17 +18,25 @@
12
18
  height = 400,
13
19
  onclose,
14
20
  stats,
21
+ top_left,
22
+ children,
15
23
  popup_div = $bindable(),
16
24
  ...rest
17
- }: HTMLAttributes<HTMLDivElement> & {
25
+ }: Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
18
26
  structure: AnyStructure
19
27
  place_right?: boolean
20
28
  width?: number
21
29
  height?: number
22
30
  onclose?: () => void
23
- stats?: { id?: string; e_above_hull?: number; e_form?: number }
31
+ stats?: StructurePopupStats
32
+ top_left?: Snippet<[StructurePopupContext]>
33
+ children?: Snippet<[StructurePopupContext]>
24
34
  popup_div?: HTMLDivElement
25
35
  } = $props()
36
+
37
+ const formula_html = $derived.by(() =>
38
+ sanitize_formula(get_electro_neg_formula(stats?.formula ?? structure, true)))
39
+ const context = $derived({ structure, stats, formula_html })
26
40
  </script>
27
41
 
28
42
  {#snippet close_button()}
@@ -40,6 +54,9 @@
40
54
  />
41
55
 
42
56
  <div
57
+ {@attach draggable({
58
+ handle_selector: `.drag-handle`,
59
+ })}
43
60
  {...rest}
44
61
  class="structure-popup {place_right ? `right` : `left`} {rest.class ?? ``}"
45
62
  role="dialog"
@@ -47,49 +64,66 @@
47
64
  tabindex="-1"
48
65
  bind:this={popup_div}
49
66
  >
50
- {#if stats}
51
- <div class="structure-stats">
52
- {#if stats.id}
53
- ID = {stats.id}<br>
54
- {/if}
55
- {#if stats.e_above_hull != null}
56
- E<sub>above hull</sub> = {format_num(stats.e_above_hull ?? 0, `.3~`)} eV/atom<br>
57
- {/if}
58
- {#if stats.e_form != null}
59
- E<sub>form</sub> = {format_num(stats.e_form || 0, `.3~`)}
60
- eV/atom
61
- {/if}
62
- </div>
63
- {/if}
67
+ <DragControlTab />
68
+ <div class="structure-popup-content">
69
+ {#if top_left || stats}
70
+ <div class="structure-stats">
71
+ {#if top_left}
72
+ {@render top_left(context)}
73
+ {:else if stats}
74
+ {#if stats.id}
75
+ ID = {stats.id}<br>
76
+ {/if}
77
+ {#if formula_html}
78
+ {@html formula_html}<br>
79
+ {/if}
80
+ {#if stats.e_above_hull != null}
81
+ E<sub>above hull</sub> = {format_num(stats.e_above_hull, `.3~`)} eV/atom<br>
82
+ {/if}
83
+ {#if stats.e_form != null}
84
+ E<sub>form</sub> = {format_num(stats.e_form, `.3~`)}
85
+ eV/atom
86
+ {/if}
87
+ {/if}
88
+ </div>
89
+ {/if}
64
90
 
65
- <Structure
66
- {structure}
67
- {width}
68
- {height}
69
- top_right_controls={close_button}
70
- show_controls
71
- />
91
+ <Structure
92
+ {structure}
93
+ {width}
94
+ {height}
95
+ top_right_controls={close_button}
96
+ show_controls="hover"
97
+ style="--struct-width: {width}px; --struct-height: {height}px; --struct-min-width: 0"
98
+ />
99
+ {@render children?.(context)}
100
+ </div>
72
101
  </div>
73
102
 
74
103
  <style>
75
104
  .structure-popup {
76
105
  position: absolute;
77
106
  box-sizing: border-box;
78
- width: 500px;
107
+ width: max-content;
108
+ z-index: 10000;
109
+ overflow: visible;
110
+ top: 50%;
111
+ transform: translateY(-50%);
112
+ }
113
+ .structure-popup-content {
114
+ display: flex;
115
+ gap: 8px;
79
116
  background: var(--surface-bg);
80
117
  border: 1px solid var(--border-color);
81
118
  border-radius: 8px;
82
119
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.15);
83
- z-index: 10000;
84
120
  overflow: hidden;
85
- top: 50%;
86
- transform: translateY(-50%);
87
121
  }
88
122
  .structure-popup.right {
89
- left: calc(100% + 1em);
123
+ left: calc(100% + var(--structure-popup-gap, 1em));
90
124
  }
91
125
  .structure-popup.left {
92
- right: calc(100% + 1em);
126
+ right: calc(100% + var(--structure-popup-gap, 1em));
93
127
  }
94
128
  .close-btn {
95
129
  background: transparent;
@@ -106,7 +140,8 @@
106
140
  position: absolute;
107
141
  top: 10px;
108
142
  left: 10px;
109
- background: var(--surface-bg);
143
+ background: transparent;
144
+ backdrop-filter: blur(8px);
110
145
  color: var(--text-color);
111
146
  padding: 4px 8px;
112
147
  border-radius: 6px;
@@ -1,16 +1,16 @@
1
1
  import type { AnyStructure } from '../structure';
2
+ import type { StructurePopupContext, StructurePopupStats } from './types';
3
+ import type { Snippet } from 'svelte';
2
4
  import type { HTMLAttributes } from 'svelte/elements';
3
- type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
5
+ type $$ComponentProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
4
6
  structure: AnyStructure;
5
7
  place_right?: boolean;
6
8
  width?: number;
7
9
  height?: number;
8
10
  onclose?: () => void;
9
- stats?: {
10
- id?: string;
11
- e_above_hull?: number;
12
- e_form?: number;
13
- };
11
+ stats?: StructurePopupStats;
12
+ top_left?: Snippet<[StructurePopupContext]>;
13
+ children?: Snippet<[StructurePopupContext]>;
14
14
  popup_div?: HTMLDivElement;
15
15
  };
16
16
  declare const StructurePopup: import("svelte").Component<$$ComponentProps, {}, "popup_div">;
@@ -22,8 +22,10 @@
22
22
  const display_index = $derived(preview_index ?? temp_index)
23
23
  const display_temp = $derived(available_temperatures[display_index] ?? temperature)
24
24
 
25
- function handle_slider_input(event: Event): void {
26
- const new_index = +(event.currentTarget as HTMLInputElement).value
25
+ function handle_slider_input(
26
+ event: Event & { currentTarget: HTMLInputElement },
27
+ ): void {
28
+ const new_index = +event.currentTarget.value
27
29
  preview_index = new_index
28
30
  // Throttle parent updates during drag to prevent scene flashing
29
31
  const now = Date.now()
@@ -33,9 +35,10 @@
33
35
  }
34
36
  }
35
37
 
36
- function handle_slider_end(event: Event): void {
37
- const new_temp =
38
- available_temperatures[+(event.currentTarget as HTMLInputElement).value]
38
+ function handle_slider_end(
39
+ event: Event & { currentTarget: HTMLInputElement },
40
+ ): void {
41
+ const new_temp = available_temperatures[+event.currentTarget.value]
39
42
  if (new_temp !== undefined) temperature = new_temp
40
43
  preview_index = null
41
44
  }
@@ -1,6 +1,6 @@
1
1
  import type { ElementSymbol } from '../element';
2
- import type { Vec3 } from '../math';
3
- import type { ConvexHullEntry, PhaseData, Point3D } from './types';
2
+ import type { Point3D, Vec3 } from '../math';
3
+ import type { ConvexHullEntry, PhaseData } from './types';
4
4
  export declare const TRIANGLE_VERTICES: readonly [readonly [1, 0], readonly [0.5, number], readonly [0, 0]];
5
5
  export declare function composition_to_barycentric_3d(composition: Record<string, number>, elements: ElementSymbol[]): Vec3;
6
6
  export declare function barycentric_to_ternary_xy(barycentric: Vec3): [number, number];
@@ -86,7 +86,7 @@ export function get_ternary_3d_coordinates(entries, elements, el_refs) {
86
86
  : (compute_e_form_per_atom(entry, refs) ?? NaN);
87
87
  const xyz = barycentric_to_ternary_xyz(barycentric, e_form_per_atom);
88
88
  const is_element = is_unary_entry(entry);
89
- return { ...entry, ...xyz, is_element, visible: true };
89
+ return { ...entry, ...xyz, is_element };
90
90
  });
91
91
  return result;
92
92
  }
@@ -177,6 +177,6 @@ export function compute_4d_coords(entries, elements) {
177
177
  const barycentric_4d = composition_to_barycentric_4d(entry.composition, elements);
178
178
  const tetrahedral = barycentric_to_tetrahedral(barycentric_4d);
179
179
  const is_element = is_unary_entry(entry);
180
- return { ...entry, ...tetrahedral, is_element, visible: true };
180
+ return { ...entry, ...tetrahedral, is_element };
181
181
  });
182
182
  }
@@ -121,9 +121,7 @@ export function create_default_gas_provider() {
121
121
  let default_provider = null;
122
122
  // Get the default gas thermodynamics provider (lazy initialization)
123
123
  export function get_default_gas_provider() {
124
- if (!default_provider) {
125
- default_provider = create_default_gas_provider();
126
- }
124
+ default_provider ??= create_default_gas_provider();
127
125
  return default_provider;
128
126
  }
129
127
  // Gas Chemical Potential Calculations
@@ -275,7 +273,7 @@ export function compute_gas_correction(entry, config, T, pressures) {
275
273
  // By only correcting unary references, we effectively replace the standard
276
274
  // elemental reference with the gas chemical potential at (T, P).
277
275
  export function apply_gas_corrections(entries, config, T) {
278
- if (!config || !config.enabled_gases?.length)
276
+ if (!config?.enabled_gases?.length)
279
277
  return entries;
280
278
  const analysis = analyze_gas_data(entries, config);
281
279
  // No gas-dependent elements, return entries unchanged
@@ -9,9 +9,17 @@ export declare function compute_hull_stability(raw_distance: number, exclude_fro
9
9
  e_above_hull: number;
10
10
  is_stable: boolean;
11
11
  };
12
+ type StabilityEntry = {
13
+ is_stable?: boolean;
14
+ e_above_hull?: number;
15
+ };
16
+ export declare const entry_is_stable: (entry: StabilityEntry, tol?: number) => boolean;
12
17
  export declare const is_on_hull: (entry: PhaseData, tol?: number) => boolean;
13
18
  export declare const get_arity: (entry: PhaseData) => number;
14
19
  export declare const is_unary_entry: (entry: PhaseData) => boolean;
20
+ export declare const entry_is_unstable: (entry: StabilityEntry) => boolean;
21
+ export declare const entry_is_visible: (entry: StabilityEntry, show_stable: boolean, show_unstable: boolean) => boolean;
22
+ export declare const visible_entries: <Entry extends StabilityEntry>(entries: readonly Entry[], show_stable: boolean, show_unstable: boolean) => Entry[];
15
23
  export declare function get_energy_color_scale(color_mode: `stability` | `energy`, color_scale: D3InterpolateName, plot_entries: {
16
24
  e_above_hull?: number;
17
25
  }[]): ((value: number) => string) | null;
@@ -22,12 +30,15 @@ export declare function get_point_color_for_entry(entry: {
22
30
  export declare function parse_hull_entries_from_drop(event: DragEvent): Promise<PhaseData[] | null>;
23
31
  export declare function calc_max_hull_dist_in_data(processed_entries: PhaseData[]): number;
24
32
  export declare function compute_auto_hull_dist_threshold(n_entries: number, max_hull_dist_in_data: number, static_default: number): number;
33
+ export declare function auto_threshold_reset(default_threshold: number): (next_source: unknown, current_threshold: number, next_auto_threshold: number) => number | undefined;
34
+ export declare function current_entry<Entry extends {
35
+ entry_id?: string;
36
+ }>(entry: Entry | null | undefined, entries: readonly Entry[]): Entry | null;
25
37
  export declare function build_entry_tooltip_text(entry: PhaseData): string;
26
38
  export declare function find_hull_entry_at_mouse<T extends {
27
39
  x: number;
28
40
  y: number;
29
41
  z: number;
30
- visible?: boolean;
31
42
  size?: number;
32
43
  is_stable?: boolean;
33
44
  e_above_hull?: number;
@@ -80,7 +91,7 @@ export interface TemperatureAnalysis {
80
91
  available_temperatures: number[];
81
92
  }
82
93
  export declare function analyze_temperature_data(entries: PhaseData[]): TemperatureAnalysis;
83
- export declare function entry_has_temperature(entry: PhaseData, T: number): boolean;
94
+ export declare const entry_has_temperature: (entry: PhaseData, T: number) => boolean;
84
95
  export declare function get_energy_at_temperature(entry: PhaseData, T: number): number;
85
96
  export declare function can_interpolate_at_temperature(entry: PhaseData, T: number, max_gap: number): boolean;
86
97
  export declare function interpolate_energy_at_temperature(entry: PhaseData, T: number, max_gap: number): number | null;