matterviz 0.3.2 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/dist/EmptyState.svelte +10 -2
  2. package/dist/FilePicker.svelte +123 -82
  3. package/dist/Icon.svelte +18 -12
  4. package/dist/MillerIndexInput.svelte +27 -21
  5. package/dist/api/optimade.js +6 -6
  6. package/dist/app.css +216 -207
  7. package/dist/brillouin/BrillouinZone.svelte +292 -149
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +69 -42
  11. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte +275 -163
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  15. package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
  16. package/dist/brillouin/compute.js +11 -6
  17. package/dist/chempot-diagram/ChemPotDiagram.svelte +162 -27
  18. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +451 -281
  19. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2148 -1642
  20. package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -5
  21. package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
  22. package/dist/chempot-diagram/async-compute.svelte.js +77 -0
  23. package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
  24. package/dist/chempot-diagram/chempot-worker.js +11 -0
  25. package/dist/chempot-diagram/color.js +1 -2
  26. package/dist/chempot-diagram/compute.d.ts +10 -0
  27. package/dist/chempot-diagram/compute.js +250 -88
  28. package/dist/chempot-diagram/index.d.ts +2 -1
  29. package/dist/chempot-diagram/index.js +2 -1
  30. package/dist/chempot-diagram/temperature.js +8 -9
  31. package/dist/chempot-diagram/types.d.ts +3 -0
  32. package/dist/chempot-diagram/types.js +1 -0
  33. package/dist/colors/index.d.ts +1 -1
  34. package/dist/colors/index.js +5 -3
  35. package/dist/composition/BarChart.svelte +128 -55
  36. package/dist/composition/BubbleChart.svelte +102 -49
  37. package/dist/composition/Composition.svelte +100 -79
  38. package/dist/composition/Formula.svelte +108 -62
  39. package/dist/composition/FormulaFilter.svelte +665 -537
  40. package/dist/composition/PieChart.svelte +183 -108
  41. package/dist/composition/format.d.ts +5 -0
  42. package/dist/composition/format.js +20 -3
  43. package/dist/composition/parse.js +14 -9
  44. package/dist/convex-hull/ConvexHull.svelte +93 -40
  45. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  46. package/dist/convex-hull/ConvexHull2D.svelte +549 -360
  47. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  48. package/dist/convex-hull/ConvexHull3D.svelte +1296 -827
  49. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  50. package/dist/convex-hull/ConvexHull4D.svelte +1004 -688
  51. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  52. package/dist/convex-hull/ConvexHullControls.svelte +115 -28
  53. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +1 -1
  54. package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
  55. package/dist/convex-hull/ConvexHullStats.svelte +425 -328
  56. package/dist/convex-hull/ConvexHullTooltip.svelte +40 -16
  57. package/dist/convex-hull/GasPressureControls.svelte +104 -61
  58. package/dist/convex-hull/StructurePopup.svelte +25 -4
  59. package/dist/convex-hull/TemperatureSlider.svelte +45 -25
  60. package/dist/convex-hull/barycentric-coords.js +13 -7
  61. package/dist/convex-hull/demo-temperature.js +8 -4
  62. package/dist/convex-hull/gas-thermodynamics.js +17 -12
  63. package/dist/convex-hull/helpers.d.ts +9 -0
  64. package/dist/convex-hull/helpers.js +77 -34
  65. package/dist/convex-hull/thermodynamics.js +61 -56
  66. package/dist/convex-hull/types.d.ts +9 -14
  67. package/dist/convex-hull/types.js +0 -17
  68. package/dist/coordination/CoordinationBarPlot.svelte +227 -154
  69. package/dist/element/BohrAtom.svelte +55 -12
  70. package/dist/element/ElementHeading.svelte +7 -2
  71. package/dist/element/ElementPhoto.svelte +15 -9
  72. package/dist/element/ElementStats.svelte +10 -4
  73. package/dist/element/ElementTile.svelte +137 -73
  74. package/dist/element/Nucleus.svelte +39 -11
  75. package/dist/element/data.js +1 -1
  76. package/dist/feedback/ClickFeedback.svelte +16 -5
  77. package/dist/feedback/DragOverlay.svelte +10 -2
  78. package/dist/feedback/Spinner.svelte +4 -2
  79. package/dist/feedback/StatusMessage.svelte +8 -2
  80. package/dist/fermi-surface/FermiSlice.svelte +118 -88
  81. package/dist/fermi-surface/FermiSurface.svelte +328 -187
  82. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  83. package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
  84. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  85. package/dist/fermi-surface/FermiSurfaceScene.svelte +535 -342
  86. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  87. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
  88. package/dist/fermi-surface/compute.js +16 -20
  89. package/dist/fermi-surface/parse.js +24 -14
  90. package/dist/fermi-surface/symmetry.js +2 -7
  91. package/dist/fermi-surface/types.d.ts +3 -5
  92. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1019 -765
  93. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +1 -1
  94. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +76 -22
  95. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +2 -3
  96. package/dist/icons.js +47 -0
  97. package/dist/index.d.ts +2 -1
  98. package/dist/index.js +2 -1
  99. package/dist/io/decompress.js +1 -1
  100. package/dist/io/export.d.ts +3 -0
  101. package/dist/io/export.js +129 -143
  102. package/dist/io/is-binary.js +2 -3
  103. package/dist/io/url-drop.js +1 -2
  104. package/dist/isosurface/Isosurface.svelte +202 -148
  105. package/dist/isosurface/IsosurfaceControls.svelte +46 -28
  106. package/dist/isosurface/parse.js +34 -29
  107. package/dist/isosurface/slice.js +5 -10
  108. package/dist/isosurface/types.d.ts +2 -1
  109. package/dist/isosurface/types.js +61 -12
  110. package/dist/labels.js +11 -8
  111. package/dist/layout/FullscreenToggle.svelte +11 -2
  112. package/dist/layout/InfoCard.svelte +38 -6
  113. package/dist/layout/InfoTag.svelte +63 -32
  114. package/dist/layout/PropertyFilter.svelte +82 -37
  115. package/dist/layout/SettingsSection.svelte +85 -55
  116. package/dist/layout/SubpageGrid.svelte +10 -2
  117. package/dist/layout/json-tree/JsonNode.svelte +183 -138
  118. package/dist/layout/json-tree/JsonTree.svelte +499 -413
  119. package/dist/layout/json-tree/JsonValue.svelte +127 -99
  120. package/dist/layout/json-tree/utils.js +4 -2
  121. package/dist/marching-cubes.js +25 -2
  122. package/dist/math.d.ts +13 -17
  123. package/dist/math.js +133 -67
  124. package/dist/overlays/ContextMenu.svelte +65 -40
  125. package/dist/overlays/DraggablePane.svelte +211 -139
  126. package/dist/periodic-table/PeriodicTable.svelte +278 -145
  127. package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
  128. package/dist/periodic-table/PropertySelect.svelte +25 -7
  129. package/dist/periodic-table/TableInset.svelte +8 -3
  130. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +446 -309
  131. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  132. package/dist/phase-diagram/PhaseDiagramControls.svelte +102 -43
  133. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  134. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +63 -40
  135. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +71 -28
  136. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +1 -1
  137. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +158 -101
  138. package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
  139. package/dist/phase-diagram/build-diagram.js +9 -9
  140. package/dist/phase-diagram/colors.js +1 -3
  141. package/dist/phase-diagram/parse.js +10 -9
  142. package/dist/phase-diagram/svg-to-diagram.js +53 -49
  143. package/dist/phase-diagram/utils.d.ts +1 -0
  144. package/dist/phase-diagram/utils.js +80 -25
  145. package/dist/plot/AxisLabel.svelte +28 -3
  146. package/dist/plot/BarPlot.svelte +1182 -734
  147. package/dist/plot/BarPlot.svelte.d.ts +2 -2
  148. package/dist/plot/BarPlotControls.svelte +31 -5
  149. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  150. package/dist/plot/ColorBar.svelte +479 -329
  151. package/dist/plot/ColorScaleSelect.svelte +27 -6
  152. package/dist/plot/ElementScatter.svelte +36 -15
  153. package/dist/plot/FillArea.svelte +152 -95
  154. package/dist/plot/Histogram.svelte +934 -571
  155. package/dist/plot/Histogram.svelte.d.ts +1 -1
  156. package/dist/plot/HistogramControls.svelte +53 -9
  157. package/dist/plot/HistogramControls.svelte.d.ts +1 -1
  158. package/dist/plot/InteractiveAxisLabel.svelte +34 -11
  159. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  160. package/dist/plot/Line.svelte +63 -28
  161. package/dist/plot/PlotControls.svelte +157 -114
  162. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  163. package/dist/plot/PlotLegend.svelte +174 -91
  164. package/dist/plot/PlotTooltip.svelte +45 -6
  165. package/dist/plot/PortalSelect.svelte +175 -147
  166. package/dist/plot/ReferenceLine.svelte +76 -22
  167. package/dist/plot/ReferenceLine3D.svelte +132 -107
  168. package/dist/plot/ReferencePlane.svelte +146 -121
  169. package/dist/plot/ScatterPlot.svelte +1681 -1091
  170. package/dist/plot/ScatterPlot.svelte.d.ts +2 -2
  171. package/dist/plot/ScatterPlot3D.svelte +256 -131
  172. package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
  173. package/dist/plot/ScatterPlot3DControls.svelte +113 -63
  174. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
  175. package/dist/plot/ScatterPlot3DScene.svelte +608 -403
  176. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
  177. package/dist/plot/ScatterPlotControls.svelte +65 -25
  178. package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
  179. package/dist/plot/ScatterPoint.svelte +98 -26
  180. package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
  181. package/dist/plot/SpacegroupBarPlot.svelte +142 -85
  182. package/dist/plot/Surface3D.svelte +159 -108
  183. package/dist/plot/ZeroLines.svelte +55 -3
  184. package/dist/plot/ZoomRect.svelte +4 -2
  185. package/dist/plot/axis-utils.js +1 -3
  186. package/dist/plot/data-cleaning.js +12 -28
  187. package/dist/plot/data-transform.js +2 -1
  188. package/dist/plot/fill-utils.js +2 -0
  189. package/dist/plot/layout.d.ts +4 -1
  190. package/dist/plot/layout.js +33 -14
  191. package/dist/plot/reference-line.d.ts +2 -2
  192. package/dist/plot/reference-line.js +7 -5
  193. package/dist/plot/scales.js +24 -36
  194. package/dist/plot/types.d.ts +11 -23
  195. package/dist/plot/types.js +6 -11
  196. package/dist/plot/utils/label-placement.d.ts +32 -15
  197. package/dist/plot/utils/label-placement.js +227 -66
  198. package/dist/plot/utils/series-visibility.js +2 -3
  199. package/dist/rdf/RdfPlot.svelte +143 -91
  200. package/dist/rdf/calc-rdf.js +4 -5
  201. package/dist/sanitize.d.ts +4 -0
  202. package/dist/sanitize.js +107 -0
  203. package/dist/settings.d.ts +18 -6
  204. package/dist/settings.js +46 -16
  205. package/dist/spectral/Bands.svelte +632 -453
  206. package/dist/spectral/BandsAndDos.svelte +90 -49
  207. package/dist/spectral/BrillouinBandsDos.svelte +151 -93
  208. package/dist/spectral/Dos.svelte +389 -258
  209. package/dist/spectral/helpers.js +55 -43
  210. package/dist/state.svelte.d.ts +1 -1
  211. package/dist/state.svelte.js +3 -2
  212. package/dist/structure/Arrow.svelte +59 -20
  213. package/dist/structure/AtomLegend.svelte +215 -134
  214. package/dist/structure/Bond.svelte +73 -47
  215. package/dist/structure/CanvasTooltip.svelte +10 -2
  216. package/dist/structure/CellSelect.svelte +72 -45
  217. package/dist/structure/Cylinder.svelte +33 -17
  218. package/dist/structure/Lattice.svelte +88 -33
  219. package/dist/structure/Structure.svelte +1063 -797
  220. package/dist/structure/Structure.svelte.d.ts +1 -1
  221. package/dist/structure/StructureControls.svelte +349 -118
  222. package/dist/structure/StructureExportPane.svelte +124 -89
  223. package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
  224. package/dist/structure/StructureInfoPane.svelte +304 -237
  225. package/dist/structure/StructureScene.svelte +879 -443
  226. package/dist/structure/StructureScene.svelte.d.ts +15 -7
  227. package/dist/structure/atom-properties.js +8 -8
  228. package/dist/structure/bonding.js +6 -7
  229. package/dist/structure/export.js +14 -29
  230. package/dist/structure/ferrox-wasm.js +1 -1
  231. package/dist/structure/index.d.ts +13 -3
  232. package/dist/structure/index.js +83 -23
  233. package/dist/structure/measure.d.ts +2 -2
  234. package/dist/structure/measure.js +4 -44
  235. package/dist/structure/parse.js +113 -141
  236. package/dist/structure/partial-occupancy.js +7 -10
  237. package/dist/structure/pbc.d.ts +1 -0
  238. package/dist/structure/pbc.js +16 -6
  239. package/dist/structure/supercell.d.ts +2 -2
  240. package/dist/structure/supercell.js +12 -22
  241. package/dist/structure/validation.js +1 -2
  242. package/dist/symmetry/SymmetryStats.svelte +84 -41
  243. package/dist/symmetry/WyckoffTable.svelte +26 -6
  244. package/dist/symmetry/cell-transform.js +5 -3
  245. package/dist/symmetry/index.js +8 -7
  246. package/dist/symmetry/spacegroups.js +148 -148
  247. package/dist/table/HeatmapTable.svelte +790 -554
  248. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  249. package/dist/table/ToggleMenu.svelte +125 -92
  250. package/dist/table/index.js +2 -4
  251. package/dist/theme/ThemeControl.svelte +21 -12
  252. package/dist/time.js +4 -1
  253. package/dist/tooltip/TooltipContent.svelte +33 -8
  254. package/dist/trajectory/Trajectory.svelte +758 -558
  255. package/dist/trajectory/TrajectoryError.svelte +14 -3
  256. package/dist/trajectory/TrajectoryExportPane.svelte +137 -83
  257. package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
  258. package/dist/trajectory/extract.js +10 -26
  259. package/dist/trajectory/format-detect.js +5 -5
  260. package/dist/trajectory/frame-reader.d.ts +1 -1
  261. package/dist/trajectory/frame-reader.js +5 -12
  262. package/dist/trajectory/helpers.d.ts +0 -1
  263. package/dist/trajectory/helpers.js +2 -17
  264. package/dist/trajectory/index.js +14 -12
  265. package/dist/trajectory/parse/ase.js +5 -4
  266. package/dist/trajectory/parse/hdf5.js +26 -18
  267. package/dist/trajectory/parse/index.js +13 -18
  268. package/dist/trajectory/parse/lammps.js +17 -7
  269. package/dist/trajectory/parse/vasp.js +5 -2
  270. package/dist/trajectory/parse/xyz.js +8 -7
  271. package/dist/trajectory/plotting.js +13 -8
  272. package/dist/utils.d.ts +1 -0
  273. package/dist/utils.js +13 -0
  274. package/dist/xrd/XrdPlot.svelte +337 -247
  275. package/dist/xrd/broadening.js +14 -9
  276. package/dist/xrd/calc-xrd.js +12 -18
  277. package/dist/xrd/parse.d.ts +1 -1
  278. package/dist/xrd/parse.js +17 -17
  279. package/package.json +99 -103
  280. package/readme.md +1 -1
  281. /package/dist/theme/{themes.js → themes.mjs} +0 -0
@@ -1,5 +1,13 @@
1
- <script lang="ts">let { message, children, ...rest } = $props();
2
- export {};
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte'
3
+ import type { HTMLAttributes } from 'svelte/elements'
4
+
5
+ let { message, children, ...rest }: {
6
+ // Simple text message to display. Ignored if children snippet is provided.
7
+ message?: string
8
+ // Custom content to render. Takes precedence over message prop.
9
+ children?: Snippet
10
+ } & HTMLAttributes<HTMLDivElement> = $props()
3
11
  </script>
4
12
 
5
13
  <div {...rest} class="empty-state {rest.class ?? ``}">
@@ -1,90 +1,131 @@
1
- <script lang="ts">import { tooltip } from 'svelte-multiselect';
2
- // Delay for distinguishing click from double-click (ms)
3
- const CLICK_DELAY = 250;
4
- let { files = [], active_files = [], show_category_filters = false, layout = `wrap`, on_drag_start, on_drag_end, on_click, on_dblclick, type_mapper, file_type_colors = {
5
- cif: `rgba(100, 149, 237, 0.8)`,
6
- xyz: `rgba(50, 205, 50, 0.8)`,
7
- extxyz: `rgba(50, 205, 50, 0.8)`,
8
- poscar: `rgba(255, 140, 0, 0.8)`,
9
- json: `rgba(138, 43, 226, 0.8)`,
10
- traj: `rgba(255, 192, 203, 0.8)`,
11
- hdf5: `rgba(255, 69, 0, 0.8)`,
12
- gz: `rgba(169, 169, 169, 0.8)`,
13
- md: `rgba(255, 215, 0, 0.8)`,
14
- yaml: `rgba(255, 0, 255, 0.8)`,
15
- xdatcar: `rgba(255, 215, 0, 0.8)`,
16
- tdb: `rgba(0, 188, 212, 0.8)`,
17
- chgcar: `rgba(59, 130, 246, 0.8)`,
18
- locpot: `rgba(245, 158, 11, 0.8)`,
19
- elfcar: `rgba(16, 185, 129, 0.8)`,
20
- cube: `rgba(168, 85, 247, 0.8)`,
21
- }, ...rest } = $props();
22
- let active_category_filter = $state(null);
23
- let active_type_filter = $state(null);
24
- // Timer for distinguishing click from double-click (per-component state)
25
- let click_timer = null;
26
- let click_timer_file = null;
27
- const clear_click_timer = () => {
28
- if (click_timer)
29
- clearTimeout(click_timer);
30
- click_timer = null;
31
- click_timer_file = null;
32
- };
33
- // Helper function to get the base file type (removing .gz extension)
34
- const get_base_file_type = (file) => {
35
- if (type_mapper)
36
- return type_mapper(file);
37
- if (file.type)
38
- return file.type.toLowerCase();
39
- let base_name = file.name.toLowerCase();
40
- if (base_name.endsWith(`.gz`))
41
- base_name = base_name.slice(0, -3);
42
- return base_name.split(`.`).pop() || `file`;
43
- };
44
- // Helper function to create normalized category identifier for filtering
45
- const get_category_id = (file) => {
46
- if (!file.category)
47
- return `(uncategorized)`;
48
- return `${file.category_icon ?? ``} ${file.category}`.trim();
49
- };
50
- // Filter files based on active filters
51
- let filtered_files = $derived(files.filter((file) => {
52
- if (active_category_filter) {
53
- return get_category_id(file) === active_category_filter;
54
- }
55
- if (active_type_filter) {
56
- const normalized_type = get_base_file_type(file);
57
- return normalized_type === active_type_filter;
58
- }
59
- return true;
60
- }));
61
- const toggle_filter = (kind, filter) => {
1
+ <script lang="ts">
2
+ import type { FileInfo } from './io'
3
+ import { tooltip } from 'svelte-multiselect'
4
+ import type { HTMLAttributes } from 'svelte/elements'
5
+
6
+ // Delay for distinguishing click from double-click (ms)
7
+ const CLICK_DELAY = 250
8
+
9
+ let {
10
+ files = [],
11
+ active_files = [],
12
+ show_category_filters = false,
13
+ layout = `wrap`,
14
+ on_drag_start,
15
+ on_drag_end,
16
+ on_click,
17
+ on_dblclick,
18
+ type_mapper,
19
+ file_type_colors = {
20
+ cif: `rgba(100, 149, 237, 0.8)`,
21
+ xyz: `rgba(50, 205, 50, 0.8)`,
22
+ extxyz: `rgba(50, 205, 50, 0.8)`,
23
+ poscar: `rgba(255, 140, 0, 0.8)`,
24
+ json: `rgba(138, 43, 226, 0.8)`,
25
+ traj: `rgba(255, 192, 203, 0.8)`,
26
+ hdf5: `rgba(255, 69, 0, 0.8)`,
27
+ gz: `rgba(169, 169, 169, 0.8)`,
28
+ md: `rgba(255, 215, 0, 0.8)`,
29
+ yaml: `rgba(255, 0, 255, 0.8)`,
30
+ xdatcar: `rgba(255, 215, 0, 0.8)`,
31
+ tdb: `rgba(0, 188, 212, 0.8)`,
32
+ chgcar: `rgba(59, 130, 246, 0.8)`,
33
+ parchg: `rgba(99, 102, 241, 0.8)`,
34
+ locpot: `rgba(245, 158, 11, 0.8)`,
35
+ elfcar: `rgba(16, 185, 129, 0.8)`,
36
+ cube: `rgba(168, 85, 247, 0.8)`,
37
+ },
38
+ ...rest
39
+ }: HTMLAttributes<HTMLDivElement> & {
40
+ files?: FileInfo[]
41
+ active_files?: string[]
42
+ show_category_filters?: boolean
43
+ layout?: `wrap` | `vertical`
44
+ on_drag_start?: (file: FileInfo, event: DragEvent) => void
45
+ on_drag_end?: () => void
46
+ on_click?: (file: FileInfo, event: MouseEvent | KeyboardEvent) => void
47
+ on_dblclick?: (file: FileInfo, event: MouseEvent) => void
48
+ type_mapper?: (file: FileInfo) => string
49
+ file_type_colors?: Record<string, string>
50
+ } = $props()
51
+
52
+ let active_category_filter = $state<string | null>(null)
53
+ let active_type_filter = $state<string | null>(null)
54
+ type FilterKind = `category` | `type`
55
+
56
+ // Timer for distinguishing click from double-click (per-component state)
57
+ let click_timer: ReturnType<typeof setTimeout> | null = null
58
+ let click_timer_file: string | null = null
59
+
60
+ const clear_click_timer = () => {
61
+ if (click_timer) clearTimeout(click_timer)
62
+ click_timer = null
63
+ click_timer_file = null
64
+ }
65
+
66
+ // Helper function to get the base file type (removing .gz extension)
67
+ const get_base_file_type = (file: FileInfo): string => {
68
+ if (type_mapper) return type_mapper(file)
69
+ if (file.type) return file.type.toLowerCase()
70
+
71
+ let base_name = file.name.toLowerCase()
72
+ if (base_name.endsWith(`.gz`)) base_name = base_name.slice(0, -3)
73
+ return base_name.split(`.`).pop() || `file`
74
+ }
75
+
76
+ // Helper function to create normalized category identifier for filtering
77
+ const get_category_id = (file: FileInfo): string => {
78
+ if (!file.category) return `(uncategorized)`
79
+ return `${file.category_icon ?? ``} ${file.category}`.trim()
80
+ }
81
+
82
+ // Filter files based on active filters
83
+ let filtered_files = $derived(
84
+ files.filter((file) => {
85
+ if (active_category_filter) {
86
+ return get_category_id(file) === active_category_filter
87
+ }
88
+ if (active_type_filter) {
89
+ const normalized_type = get_base_file_type(file)
90
+ return normalized_type === active_type_filter
91
+ }
92
+ return true
93
+ }),
94
+ )
95
+
96
+ const toggle_filter = (kind: FilterKind, filter: string) => {
62
97
  if (kind === `category`) {
63
- active_category_filter = active_category_filter === filter ? null : filter;
64
- active_type_filter = null;
98
+ active_category_filter = active_category_filter === filter ? null : filter
99
+ active_type_filter = null
100
+ } else {
101
+ active_type_filter = active_type_filter === filter ? null : filter
102
+ active_category_filter = null
65
103
  }
66
- else {
67
- active_type_filter = active_type_filter === filter ? null : filter;
68
- active_category_filter = null;
69
- }
70
- };
71
- const handle_drag_start = (file) => (event) => {
72
- const file_url = file.url || file.name; // Get the URL to drag (falling back to name)
104
+ }
105
+
106
+ const handle_drag_start = (file: FileInfo) => (event: DragEvent) => {
107
+ const file_url = file.url || file.name // Get the URL to drag (falling back to name)
108
+
73
109
  const payload = JSON.stringify({
74
- name: file.name,
75
- url: file_url,
76
- type: file.type || get_base_file_type(file),
77
- category: file.category,
78
- });
110
+ name: file.name,
111
+ url: file_url,
112
+ type: file.type || get_base_file_type(file),
113
+ category: file.category,
114
+ })
79
115
  // Set file data as JSON for applications that can handle it
80
- event.dataTransfer?.setData(`application/json`, payload);
116
+ event.dataTransfer?.setData(`application/json`, payload)
117
+
81
118
  // Also set plain text as fallback for external applications
82
- event.dataTransfer?.setData(`text/plain`, file_url);
83
- on_drag_start?.(file, event);
84
- };
85
- // Get unique file types/categories for format/category filters
86
- let uniq_formats = $derived([...new Set(files.map(get_base_file_type))].sort());
87
- let uniq_categories = $derived([...new Set(files.map(get_category_id))].filter(Boolean).sort());
119
+ event.dataTransfer?.setData(`text/plain`, file_url)
120
+
121
+ on_drag_start?.(file, event)
122
+ }
123
+
124
+ // Get unique file types/categories for format/category filters
125
+ let uniq_formats = $derived([...new Set(files.map(get_base_file_type))].sort())
126
+ let uniq_categories = $derived(
127
+ [...new Set(files.map(get_category_id))].filter(Boolean).sort(),
128
+ )
88
129
  </script>
89
130
 
90
131
  <div class="file-picker" class:vertical={layout === `vertical`} {...rest}>
package/dist/Icon.svelte CHANGED
@@ -1,14 +1,20 @@
1
- <script lang="ts">import { ICON_DATA } from './icons';
2
- let { icon, path, viewBox = `0 0 24 24`, stroke, ...rest } = $props();
3
- const data = $derived.by(() => {
4
- if (path)
5
- return { path, viewBox: viewBox ?? `0 0 24 24`, stroke };
6
- if (icon && icon in ICON_DATA)
7
- return ICON_DATA[icon];
8
- if (icon)
9
- console.error(`Icon '${icon}' not found`);
10
- return ICON_DATA.Alert;
11
- });
1
+ <script lang="ts">
2
+ import type { SVGAttributes } from 'svelte/elements'
3
+ import { ICON_DATA, type IconName } from './icons'
4
+ import { sanitize_icon_svg } from './sanitize'
5
+
6
+ type IconData = { path: string; viewBox: string; stroke?: string }
7
+ let { icon, path, viewBox = `0 0 24 24`, stroke, ...rest }:
8
+ & { icon?: IconName }
9
+ & Partial<IconData>
10
+ & SVGAttributes<SVGSVGElement> = $props()
11
+
12
+ const data: IconData = $derived.by(() => {
13
+ if (path) return { path, viewBox: viewBox ?? `0 0 24 24`, stroke }
14
+ if (icon && icon in ICON_DATA) return ICON_DATA[icon]
15
+ if (icon) console.error(`Icon '${icon}' not found`)
16
+ return ICON_DATA.Alert
17
+ })
12
18
  </script>
13
19
 
14
20
  <svg
@@ -19,7 +25,7 @@ const data = $derived.by(() => {
19
25
  {...rest}
20
26
  >
21
27
  {#if data.path.trim().startsWith(`<`)}
22
- {@html data.path}
28
+ {@html sanitize_icon_svg(data.path)}
23
29
  {:else}
24
30
  <path d={data.path} />
25
31
  {/if}
@@ -1,28 +1,34 @@
1
- <script lang="ts">let { value = $bindable([0, 0, 1]) } = $props();
2
- // Format: compact "001" for single-digit, spaced "10 0 1" for multi-digit
3
- let hkl_text = $derived(value.every((v) => Math.abs(v) < 10) ? value.join(``) : value.join(` `));
4
- // Parse hkl string: supports compact "001"/"-101" and spaced/comma "10, 0, 1"
5
- function parse_hkl(input) {
1
+ <script lang="ts">
2
+ // Compact single-field input for Miller indices (hkl).
3
+ // Accepts "001", "111", "-101", "1 0 1", "10, 0, 1" and emits a Vec3 tuple.
4
+ import type { Vec3 } from './math'
5
+
6
+ let { value = $bindable([0, 0, 1]) }: { value?: Vec3 } = $props()
7
+
8
+ // Format: compact "001" for single-digit, spaced "10 0 1" for multi-digit
9
+ let hkl_text = $derived(
10
+ value.every((v) => Math.abs(v) < 10) ? value.join(``) : value.join(` `),
11
+ )
12
+
13
+ // Parse hkl string: supports compact "001"/"-101" and spaced/comma "10, 0, 1"
14
+ function parse_hkl(input: string): Vec3 | null {
6
15
  // Try spaced/comma format first (handles multi-digit)
7
- const spaced = input.trim().split(/[,\s]+/);
16
+ const spaced = input.trim().split(/[,\s]+/)
8
17
  if (spaced.length === 3) {
9
- const nums = spaced.map(Number);
10
- if (nums.every((n) => !isNaN(n)))
11
- return nums;
18
+ const nums = spaced.map(Number)
19
+ if (nums.every((n) => !isNaN(n))) return nums as Vec3
12
20
  }
13
21
  // Fall back to compact single-digit format: "001", "-101"
14
- const compact = input.replace(/\s+/g, ``);
15
- const match = compact.match(/^(-?\d)(-?\d)(-?\d)$/);
16
- if (match)
17
- return [Number(match[1]), Number(match[2]), Number(match[3])];
18
- return null;
19
- }
20
- function handle_input(event) {
21
- const parsed = parse_hkl(event.target.value);
22
- if (parsed)
23
- value = parsed;
24
- }
25
- export {};
22
+ const compact = input.replace(/\s+/g, ``)
23
+ const match = compact.match(/^(-?\d)(-?\d)(-?\d)$/)
24
+ if (match) return [Number(match[1]), Number(match[2]), Number(match[3])] as Vec3
25
+ return null
26
+ }
27
+
28
+ function handle_input(event: Event) {
29
+ const parsed = parse_hkl((event.target as HTMLInputElement).value)
30
+ if (parsed) value = parsed
31
+ }
26
32
  </script>
27
33
 
28
34
  <label class="miller-input">
@@ -1,4 +1,3 @@
1
- // deno-lint-ignore-file no-await-in-loop
2
1
  // OPTIMADE API utilities for fetching structure data
3
2
  // Based on OPTIMADE 1.2.0 specification
4
3
  // Multiple CORS proxies for fallback reliability
@@ -18,7 +17,7 @@ const RESOLVED_URLS_CACHE_DURATION = 10 * 60 * 1000;
18
17
  async function fetch_with_cors_proxy(url) {
19
18
  try {
20
19
  const direct_response = await fetch(url, {
21
- headers: { 'Accept': `application/vnd.api+json`, 'User-Agent': `MatterViz/1.0` },
20
+ headers: { Accept: `application/vnd.api+json`, 'User-Agent': `MatterViz/1.0` },
22
21
  });
23
22
  if (direct_response.ok)
24
23
  return direct_response;
@@ -29,7 +28,7 @@ async function fetch_with_cors_proxy(url) {
29
28
  for (const proxy of CORS_PROXIES) {
30
29
  try {
31
30
  const response = await fetch(`${proxy}${encodeURIComponent(url)}`, {
32
- headers: { 'Accept': `application/vnd.api+json`, 'User-Agent': `MatterViz/1.0` },
31
+ headers: { Accept: `application/vnd.api+json`, 'User-Agent': `MatterViz/1.0` },
33
32
  });
34
33
  if (response.ok)
35
34
  return response;
@@ -43,14 +42,15 @@ async function fetch_with_cors_proxy(url) {
43
42
  async function resolve_provider_url(provider_base_url) {
44
43
  const now = Date.now();
45
44
  if (resolved_provider_urls[provider_base_url] &&
46
- (now - resolved_urls_cache_time) < RESOLVED_URLS_CACHE_DURATION) {
45
+ now - resolved_urls_cache_time < RESOLVED_URLS_CACHE_DURATION) {
47
46
  return resolved_provider_urls[provider_base_url];
48
47
  }
49
48
  for (const endpoint of [`/links`, `/v1/links`]) {
50
49
  try {
51
50
  const response = await fetch_with_cors_proxy(`${provider_base_url}${endpoint}`);
52
51
  const data = await response.json();
53
- const self_link = data.data?.find((link) => link.type === `links` && link.attributes?.base_url &&
52
+ const self_link = data.data?.find((link) => link.type === `links` &&
53
+ link.attributes?.base_url &&
54
54
  link.attributes.link_type === `child`);
55
55
  if (self_link?.attributes.base_url) {
56
56
  resolved_provider_urls[provider_base_url] = self_link.attributes.base_url;
@@ -68,7 +68,7 @@ async function resolve_provider_url(provider_base_url) {
68
68
  }
69
69
  export async function fetch_optimade_providers() {
70
70
  const now = Date.now();
71
- if (cached_providers && (now - providers_cache_time) < CACHE_DURATION) {
71
+ if (cached_providers && now - providers_cache_time < CACHE_DURATION) {
72
72
  return cached_providers;
73
73
  }
74
74
  try {