matterviz 0.3.3 → 0.3.5

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 (126) hide show
  1. package/dist/FilePicker.svelte +1 -1
  2. package/dist/app.css +7 -0
  3. package/dist/brillouin/BrillouinZone.svelte +5 -2
  4. package/dist/brillouin/compute.js +8 -4
  5. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +6 -6
  6. package/dist/chempot-diagram/async-compute.svelte.js +6 -5
  7. package/dist/chempot-diagram/chempot-worker.js +2 -2
  8. package/dist/chempot-diagram/compute.js +16 -16
  9. package/dist/composition/FormulaFilter.svelte +3 -3
  10. package/dist/constants.js +2 -8
  11. package/dist/convex-hull/ConvexHull.svelte +2 -2
  12. package/dist/convex-hull/ConvexHull2D.svelte +11 -10
  13. package/dist/convex-hull/ConvexHull3D.svelte +16 -14
  14. package/dist/convex-hull/ConvexHull4D.svelte +26 -14
  15. package/dist/convex-hull/ConvexHullControls.svelte +1 -1
  16. package/dist/convex-hull/ConvexHullInfoPane.svelte +68 -61
  17. package/dist/convex-hull/ConvexHullStats.svelte +23 -6
  18. package/dist/convex-hull/GasPressureControls.svelte +3 -3
  19. package/dist/convex-hull/TemperatureSlider.svelte +1 -1
  20. package/dist/convex-hull/barycentric-coords.js +2 -2
  21. package/dist/convex-hull/helpers.js +45 -27
  22. package/dist/convex-hull/thermodynamics.js +2 -2
  23. package/dist/element/BohrAtom.svelte +25 -27
  24. package/dist/element/BohrAtom.svelte.d.ts +2 -2
  25. package/dist/element/data.d.ts +2 -3
  26. package/dist/element/data.js +1 -1
  27. package/dist/fermi-surface/FermiSurface.svelte +5 -2
  28. package/dist/fermi-surface/compute.js +3 -3
  29. package/dist/fermi-surface/parse.js +2 -2
  30. package/dist/fermi-surface/symmetry.js +1 -1
  31. package/dist/heatmap-matrix/HeatmapMatrix.svelte +8 -8
  32. package/dist/icons.d.ts +6 -6
  33. package/dist/icons.js +6 -6
  34. package/dist/io/decompress.js +12 -7
  35. package/dist/io/export.js +20 -16
  36. package/dist/io/is-binary.js +19 -4
  37. package/dist/isosurface/parse.js +8 -8
  38. package/dist/isosurface/types.js +9 -9
  39. package/dist/layout/InfoTag.svelte +1 -1
  40. package/dist/layout/json-tree/JsonNode.svelte +1 -0
  41. package/dist/layout/json-tree/utils.js +2 -1
  42. package/dist/marching-cubes.js +1 -1
  43. package/dist/math.js +1 -1
  44. package/dist/overlays/CopyButton.svelte +45 -0
  45. package/dist/overlays/CopyButton.svelte.d.ts +8 -0
  46. package/dist/overlays/InfoPaneCards.svelte +149 -0
  47. package/dist/overlays/InfoPaneCards.svelte.d.ts +22 -0
  48. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +33 -35
  49. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +2 -2
  50. package/dist/phase-diagram/PhaseDiagramControls.svelte +27 -29
  51. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +2 -2
  52. package/dist/phase-diagram/parse.js +3 -3
  53. package/dist/phase-diagram/svg-to-diagram.js +10 -12
  54. package/dist/plot/BarPlot.svelte +24 -15
  55. package/dist/plot/BarPlot.svelte.d.ts +3 -2
  56. package/dist/plot/FillArea.svelte +2 -3
  57. package/dist/plot/FillArea.svelte.d.ts +3 -2
  58. package/dist/plot/Histogram.svelte +37 -19
  59. package/dist/plot/Line.svelte +2 -3
  60. package/dist/plot/Line.svelte.d.ts +2 -2
  61. package/dist/plot/PlotLegend.svelte +79 -8
  62. package/dist/plot/PlotLegend.svelte.d.ts +4 -0
  63. package/dist/plot/PortalSelect.svelte +5 -5
  64. package/dist/plot/ScatterPlot.svelte +47 -33
  65. package/dist/plot/ScatterPlot.svelte.d.ts +5 -4
  66. package/dist/plot/ScatterPlot3D.svelte +6 -3
  67. package/dist/plot/ScatterPoint.svelte +10 -4
  68. package/dist/plot/ScatterPoint.svelte.d.ts +4 -2
  69. package/dist/plot/SpacegroupBarPlot.svelte +5 -4
  70. package/dist/plot/data-cleaning.js +9 -9
  71. package/dist/plot/index.d.ts +0 -6
  72. package/dist/plot/scales.d.ts +3 -3
  73. package/dist/plot/scales.js +29 -29
  74. package/dist/plot/types.d.ts +5 -9
  75. package/dist/rdf/calc-rdf.js +1 -1
  76. package/dist/sanitize.js +22 -15
  77. package/dist/settings.d.ts +2 -0
  78. package/dist/settings.js +12 -3
  79. package/dist/spectral/Bands.svelte +6 -6
  80. package/dist/spectral/BandsAndDos.svelte +4 -4
  81. package/dist/spectral/BrillouinBandsDos.svelte +3 -3
  82. package/dist/spectral/Dos.svelte +2 -2
  83. package/dist/spectral/helpers.js +1 -1
  84. package/dist/structure/AtomLegend.svelte +4 -4
  85. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  86. package/dist/structure/Cylinder.svelte +7 -7
  87. package/dist/structure/Structure.svelte +169 -27
  88. package/dist/structure/Structure.svelte.d.ts +6 -2
  89. package/dist/structure/StructureControls.svelte +130 -16
  90. package/dist/structure/StructureControls.svelte.d.ts +1 -1
  91. package/dist/structure/StructureInfoPane.svelte +519 -218
  92. package/dist/structure/StructureInfoPane.svelte.d.ts +2 -1
  93. package/dist/structure/StructureScene.svelte +399 -68
  94. package/dist/structure/StructureScene.svelte.d.ts +8 -4
  95. package/dist/structure/atom-properties.js +3 -1
  96. package/dist/structure/bond-order-perception.d.ts +13 -0
  97. package/dist/structure/bond-order-perception.js +367 -0
  98. package/dist/structure/bonding.d.ts +10 -1
  99. package/dist/structure/bonding.js +232 -11
  100. package/dist/structure/export.js +6 -4
  101. package/dist/structure/index.d.ts +19 -4
  102. package/dist/structure/index.js +3 -0
  103. package/dist/structure/label-placement.d.ts +14 -0
  104. package/dist/structure/label-placement.js +72 -0
  105. package/dist/structure/parse.d.ts +2 -1
  106. package/dist/structure/parse.js +25 -36
  107. package/dist/structure/supercell.js +35 -2
  108. package/dist/symmetry/SymmetryStats.svelte +1 -1
  109. package/dist/symmetry/cell-transform.js +15 -1
  110. package/dist/symmetry/index.js +3 -3
  111. package/dist/table/HeatmapTable.svelte +3 -3
  112. package/dist/table/ToggleMenu.svelte +1 -1
  113. package/dist/trajectory/Trajectory.svelte +2 -2
  114. package/dist/trajectory/TrajectoryInfoPane.svelte +14 -88
  115. package/dist/trajectory/extract.js +4 -4
  116. package/dist/trajectory/frame-reader.js +2 -2
  117. package/dist/trajectory/parse/ase.js +2 -6
  118. package/dist/trajectory/parse/hdf5.js +1 -3
  119. package/dist/trajectory/plotting.js +1 -1
  120. package/dist/utils.js +1 -1
  121. package/dist/xrd/calc-xrd.js +1 -1
  122. package/package.json +23 -38
  123. package/dist/structure/ferrox-wasm-types.d.ts +0 -46
  124. package/dist/structure/ferrox-wasm-types.js +0 -18
  125. package/dist/structure/ferrox-wasm.d.ts +0 -94
  126. package/dist/structure/ferrox-wasm.js +0 -249
@@ -0,0 +1,149 @@
1
+ <script lang="ts">
2
+ import { sanitize_html } from '../sanitize'
3
+ import type { HTMLAttributes } from 'svelte/elements'
4
+ import { SvelteSet } from 'svelte/reactivity'
5
+ import CopyButton from './CopyButton.svelte'
6
+
7
+ type InfoPaneRow = {
8
+ label: string
9
+ value: string | number
10
+ key?: string
11
+ tooltip?: string
12
+ }
13
+ type InfoPaneCard = {
14
+ title: string
15
+ rows: InfoPaneRow[]
16
+ }
17
+
18
+ let {
19
+ cards,
20
+ filter_placeholder,
21
+ empty_label,
22
+ show_filter = true,
23
+ heading_level = 4,
24
+ row_label_min = `5em`,
25
+ ...rest
26
+ }: HTMLAttributes<HTMLDivElement> & {
27
+ cards: InfoPaneCard[]
28
+ filter_placeholder: string
29
+ empty_label: string
30
+ show_filter?: boolean
31
+ heading_level?: 4 | 5
32
+ row_label_min?: string
33
+ } = $props()
34
+
35
+ let info_filter = $state(``)
36
+ const copied_items = new SvelteSet<string>()
37
+ const row_key = (card_title: string, row: InfoPaneRow, row_idx: number): string =>
38
+ row.key ?? `${card_title}:${row.label}:${row.value}:${row_idx}`
39
+
40
+ let filtered_cards = $derived.by(() => {
41
+ const filter = info_filter.trim().toLowerCase()
42
+ if (!filter) return cards
43
+ return cards
44
+ .map((card) => ({
45
+ ...card,
46
+ rows: card.rows.filter(({ label, value }) =>
47
+ `${card.title} ${label} ${value}`.toLowerCase().includes(filter)
48
+ ),
49
+ }))
50
+ .filter(({ rows }) => rows.length > 0)
51
+ })
52
+
53
+ async function copy_row(
54
+ card_title: string,
55
+ row: InfoPaneRow,
56
+ row_idx: number,
57
+ ): Promise<void> {
58
+ const key = row_key(card_title, row, row_idx)
59
+ try {
60
+ await navigator.clipboard.writeText(`${row.label}: ${row.value}`)
61
+ copied_items.add(key)
62
+ setTimeout(() => copied_items.delete(key), 1000)
63
+ } catch (error) {
64
+ console.error(`Failed to copy to clipboard:`, error)
65
+ }
66
+ }
67
+ </script>
68
+ {#if show_filter}
69
+ <input
70
+ class="info-filter"
71
+ type="search"
72
+ bind:value={info_filter}
73
+ placeholder={filter_placeholder}
74
+ aria-label={filter_placeholder}
75
+ />
76
+ {/if}
77
+
78
+ {#if filtered_cards.length === 0}
79
+ <p class="empty-filter">No {empty_label} matches "{info_filter}".</p>
80
+ {:else}
81
+ <div {...rest} class="info-cards {rest.class ?? ``}" style:--row-label-min={row_label_min}>
82
+ {#each filtered_cards as card (card.title)}
83
+ <section class="info-card">
84
+ <svelte:element this={`h${heading_level}`}>{card.title}</svelte:element>
85
+ {#each card.rows as row, row_idx (row_key(card.title, row, row_idx))}
86
+ <div class="info-row" data-testid={row.key}>
87
+ <span>{@html sanitize_html(row.label)}</span>
88
+ <span title={row.tooltip}>{@html sanitize_html(row.value)}</span>
89
+ <CopyButton
90
+ label="Copy {row.label}: {row.value}"
91
+ title="Copy {row.label}"
92
+ copied={copied_items.has(row_key(card.title, row, row_idx))}
93
+ onclick={() => copy_row(card.title, row, row_idx)}
94
+ />
95
+ </div>
96
+ {/each}
97
+ </section>
98
+ {/each}
99
+ </div>
100
+ {/if}
101
+
102
+ <style>
103
+ .info-filter {
104
+ box-sizing: border-box;
105
+ width: 100%;
106
+ margin-bottom: 5pt;
107
+ padding: 4pt 6pt;
108
+ border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
109
+ border-radius: var(--border-radius, 3pt);
110
+ background: color-mix(in srgb, var(--pane-bg, Canvas) 88%, currentColor);
111
+ color: inherit;
112
+ }
113
+ .empty-filter {
114
+ margin: 0.25em 0;
115
+ opacity: 0.75;
116
+ }
117
+ .info-cards {
118
+ display: grid;
119
+ gap: 5pt;
120
+ }
121
+ .info-card {
122
+ padding: var(--info-card-padding, 5pt);
123
+ border-left: 3px solid var(--accent-color, currentColor);
124
+ border-radius: var(--border-radius, 3pt);
125
+ background: var(--info-card-bg, color-mix(in srgb, currentColor 4%, transparent));
126
+ :is(h4, h5) {
127
+ margin: 0 0 var(--info-card-heading-gap, 3pt);
128
+ }
129
+ }
130
+ .info-row {
131
+ display: grid;
132
+ grid-template-columns: minmax(var(--row-label-min), var(--row-label-max, 0.8fr)) minmax(
133
+ 0,
134
+ 1fr
135
+ ) auto;
136
+ align-items: center;
137
+ gap: 5pt;
138
+ padding: var(--info-row-padding, 1pt 0);
139
+ line-height: 1.5;
140
+ span:first-child {
141
+ color: var(--info-row-label-color);
142
+ }
143
+ span:nth-child(2) {
144
+ overflow: hidden;
145
+ text-overflow: ellipsis;
146
+ white-space: nowrap;
147
+ }
148
+ }
149
+ </style>
@@ -0,0 +1,22 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ type InfoPaneRow = {
3
+ label: string;
4
+ value: string | number;
5
+ key?: string;
6
+ tooltip?: string;
7
+ };
8
+ type InfoPaneCard = {
9
+ title: string;
10
+ rows: InfoPaneRow[];
11
+ };
12
+ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
13
+ cards: InfoPaneCard[];
14
+ filter_placeholder: string;
15
+ empty_label: string;
16
+ show_filter?: boolean;
17
+ heading_level?: 4 | 5;
18
+ row_label_min?: string;
19
+ };
20
+ declare const InfoPaneCards: import("svelte").Component<$$ComponentProps, {}, "">;
21
+ type InfoPaneCards = ReturnType<typeof InfoPaneCards>;
22
+ export default InfoPaneCards;
@@ -48,7 +48,36 @@
48
48
  transform_vertices,
49
49
  } from './utils'
50
50
 
51
- type Props = HTMLAttributes<HTMLDivElement> & {
51
+ let {
52
+ data,
53
+ config = $bindable({}),
54
+ on_phase_hover,
55
+ fullscreen = $bindable(false),
56
+ wrapper = $bindable(),
57
+ hovered_region = $bindable(null),
58
+ show_boundaries = $bindable(true),
59
+ show_labels = $bindable(true),
60
+ show_special_points = $bindable(true),
61
+ show_grid = $bindable(true),
62
+ show_component_labels = $bindable(true),
63
+ fullscreen_toggle = true,
64
+ enable_export = true,
65
+ show_controls = true,
66
+ display_temp_unit = $bindable(),
67
+ controls_open = $bindable(false),
68
+ controls_props = {},
69
+ export_pane_open = $bindable(false),
70
+ png_dpi = $bindable(150),
71
+ export_filename = `phase-diagram`,
72
+ lever_rule_mode = $bindable(`horizontal`),
73
+ diagram_input = $bindable<DiagramInput | null>(null),
74
+ editor_open = $bindable(false),
75
+ x_axis = $bindable({}),
76
+ y_axis = $bindable({}),
77
+ tooltip,
78
+ children,
79
+ ...rest
80
+ }: HTMLAttributes<HTMLDivElement> & {
52
81
  data: PhaseDiagramData
53
82
  config?: Partial<PhaseDiagramConfig>
54
83
  // Hover callback
@@ -89,38 +118,7 @@
89
118
  children?: Snippet<
90
119
  [{ width: number; height: number; fullscreen: boolean }]
91
120
  >
92
- }
93
-
94
- let {
95
- data,
96
- config = $bindable({}),
97
- on_phase_hover,
98
- fullscreen = $bindable(false),
99
- wrapper = $bindable(),
100
- hovered_region = $bindable(null),
101
- show_boundaries = $bindable(true),
102
- show_labels = $bindable(true),
103
- show_special_points = $bindable(true),
104
- show_grid = $bindable(true),
105
- show_component_labels = $bindable(true),
106
- fullscreen_toggle = true,
107
- enable_export = true,
108
- show_controls = true,
109
- display_temp_unit = $bindable(),
110
- controls_open = $bindable(false),
111
- controls_props = {},
112
- export_pane_open = $bindable(false),
113
- png_dpi = $bindable(150),
114
- export_filename = `phase-diagram`,
115
- lever_rule_mode = $bindable(`horizontal`),
116
- diagram_input = $bindable<DiagramInput | null>(null),
117
- editor_open = $bindable(false),
118
- x_axis = $bindable({}),
119
- y_axis = $bindable({}),
120
- tooltip,
121
- children,
122
- ...rest
123
- }: Props = $props()
121
+ } = $props()
124
122
 
125
123
  // Shared icon/toggle styling for controls and export panes
126
124
  const pane_icon_style = `width: 14px; height: 14px`
@@ -229,10 +227,10 @@
229
227
  const transformed_regions = $derived(
230
228
  (effective_data?.regions ?? []).map((region) => {
231
229
  const svg_vertices = transform_vertices(region.vertices, x_scale, y_scale)
232
- const { width, height } = compute_bounding_box_2d(svg_vertices)
230
+ const { width: box_width, height: box_height } = compute_bounding_box_2d(svg_vertices)
233
231
  const label_props = compute_label_properties(
234
232
  region.name,
235
- { width, height },
233
+ { width: box_width, height: box_height },
236
234
  merged_config.font_size,
237
235
  )
238
236
  // Get gradient stops for multi-phase regions (2+, supports 3+ phases)
@@ -4,7 +4,7 @@ import type { HTMLAttributes } from 'svelte/elements';
4
4
  import type { DiagramInput } from './diagram-input';
5
5
  import PhaseDiagramControls from './PhaseDiagramControls.svelte';
6
6
  import type { LeverRuleMode, PhaseDiagramConfig, PhaseDiagramData, PhaseDiagramTooltipConfig, PhaseHoverInfo, PhaseRegion } from './types';
7
- type Props = HTMLAttributes<HTMLDivElement> & {
7
+ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
8
8
  data: PhaseDiagramData;
9
9
  config?: Partial<PhaseDiagramConfig>;
10
10
  on_phase_hover?: (info: PhaseHoverInfo | null) => void;
@@ -39,6 +39,6 @@ type Props = HTMLAttributes<HTMLDivElement> & {
39
39
  }
40
40
  ]>;
41
41
  };
42
- declare const IsobaricBinaryPhaseDiagram: import("svelte").Component<Props, {}, "fullscreen" | "controls_open" | "x_axis" | "y_axis" | "show_grid" | "wrapper" | "hovered_region" | "config" | "show_boundaries" | "show_labels" | "show_special_points" | "show_component_labels" | "png_dpi" | "export_pane_open" | "lever_rule_mode" | "editor_open" | "diagram_input" | "display_temp_unit">;
42
+ declare const IsobaricBinaryPhaseDiagram: import("svelte").Component<$$ComponentProps, {}, "fullscreen" | "controls_open" | "x_axis" | "y_axis" | "show_grid" | "wrapper" | "hovered_region" | "config" | "show_boundaries" | "show_labels" | "show_special_points" | "show_component_labels" | "png_dpi" | "export_pane_open" | "lever_rule_mode" | "editor_open" | "diagram_input" | "display_temp_unit">;
43
43
  type IsobaricBinaryPhaseDiagram = ReturnType<typeof IsobaricBinaryPhaseDiagram>;
44
44
  export default IsobaricBinaryPhaseDiagram;
@@ -10,34 +10,6 @@
10
10
  import type { LeverRuleMode, PhaseDiagramConfig, PhaseDiagramData } from './types'
11
11
  import { merge_phase_diagram_config, PHASE_DIAGRAM_DEFAULTS } from './utils'
12
12
 
13
- type Props = Omit<ComponentProps<typeof DraggablePane>, `children`> & {
14
- controls_open?: boolean
15
- // Visibility toggles
16
- show_boundaries?: boolean
17
- show_labels?: boolean
18
- show_special_points?: boolean
19
- show_grid?: boolean
20
- show_component_labels?: boolean
21
- // Configuration
22
- config?: Partial<PhaseDiagramConfig>
23
- // Lever rule mode
24
- lever_rule_mode?: LeverRuleMode
25
- // Axis configuration
26
- x_axis?: AxisConfig
27
- y_axis?: AxisConfig
28
- // Data for context (components, units, etc.)
29
- data?: PhaseDiagramData
30
- // Export settings
31
- enable_export?: boolean
32
- png_dpi?: number
33
- // Pane customization
34
- pane_props?: ComponentProps<typeof DraggablePane>[`pane_props`]
35
- toggle_props?: ComponentProps<typeof DraggablePane>[`toggle_props`]
36
- // Custom content snippets
37
- children?: Snippet<[{ controls_open: boolean }]>
38
- post_children?: Snippet<[{ controls_open: boolean }]>
39
- }
40
-
41
13
  let {
42
14
  controls_open = $bindable(false),
43
15
  // Visibility toggles
@@ -65,7 +37,33 @@
65
37
  children,
66
38
  post_children,
67
39
  ...rest
68
- }: Props = $props()
40
+ }: Omit<ComponentProps<typeof DraggablePane>, `children`> & {
41
+ controls_open?: boolean
42
+ // Visibility toggles
43
+ show_boundaries?: boolean
44
+ show_labels?: boolean
45
+ show_special_points?: boolean
46
+ show_grid?: boolean
47
+ show_component_labels?: boolean
48
+ // Configuration
49
+ config?: Partial<PhaseDiagramConfig>
50
+ // Lever rule mode
51
+ lever_rule_mode?: LeverRuleMode
52
+ // Axis configuration
53
+ x_axis?: AxisConfig
54
+ y_axis?: AxisConfig
55
+ // Data for context (components, units, etc.)
56
+ data?: PhaseDiagramData
57
+ // Export settings
58
+ enable_export?: boolean
59
+ png_dpi?: number
60
+ // Pane customization
61
+ pane_props?: ComponentProps<typeof DraggablePane>[`pane_props`]
62
+ toggle_props?: ComponentProps<typeof DraggablePane>[`toggle_props`]
63
+ // Custom content snippets
64
+ children?: Snippet<[{ controls_open: boolean }]>
65
+ post_children?: Snippet<[{ controls_open: boolean }]>
66
+ } = $props()
69
67
 
70
68
  // Merged config using shared helper
71
69
  const merged_config = $derived(merge_phase_diagram_config(config))
@@ -2,7 +2,7 @@ import DraggablePane from '../overlays/DraggablePane.svelte';
2
2
  import type { AxisConfig } from '../plot';
3
3
  import type { ComponentProps, Snippet } from 'svelte';
4
4
  import type { LeverRuleMode, PhaseDiagramConfig, PhaseDiagramData } from './types';
5
- type Props = Omit<ComponentProps<typeof DraggablePane>, `children`> & {
5
+ type $$ComponentProps = Omit<ComponentProps<typeof DraggablePane>, `children`> & {
6
6
  controls_open?: boolean;
7
7
  show_boundaries?: boolean;
8
8
  show_labels?: boolean;
@@ -25,6 +25,6 @@ type Props = Omit<ComponentProps<typeof DraggablePane>, `children`> & {
25
25
  controls_open: boolean;
26
26
  }]>;
27
27
  };
28
- declare const PhaseDiagramControls: import("svelte").Component<Props, {}, "controls_open" | "x_axis" | "y_axis" | "show_grid" | "config" | "show_boundaries" | "show_labels" | "show_special_points" | "show_component_labels" | "png_dpi" | "lever_rule_mode">;
28
+ declare const PhaseDiagramControls: import("svelte").Component<$$ComponentProps, {}, "controls_open" | "x_axis" | "y_axis" | "show_grid" | "config" | "show_boundaries" | "show_labels" | "show_special_points" | "show_component_labels" | "png_dpi" | "lever_rule_mode">;
29
29
  type PhaseDiagramControls = ReturnType<typeof PhaseDiagramControls>;
30
30
  export default PhaseDiagramControls;
@@ -124,9 +124,9 @@ const LINE_PARSERS = [
124
124
  .split(`,`)
125
125
  .map((name) => name.trim())
126
126
  .filter((name) => name.length > 0));
127
- const phase = data.phases.find((phase) => phase.name.toUpperCase() === phase_name.toUpperCase());
128
- if (phase)
129
- phase.constituents = constituents;
127
+ const matched_phase = data.phases.find((candidate_phase) => candidate_phase.name.toUpperCase() === phase_name.toUpperCase());
128
+ if (matched_phase)
129
+ matched_phase.constituents = constituents;
130
130
  },
131
131
  },
132
132
  {
@@ -475,10 +475,10 @@ function infer_regions(boundaries, labels, x_scale, y_scale) {
475
475
  // Build cell grid: cells[col][row]
476
476
  const n_cols = x_coords.length - 1;
477
477
  const n_rows = y_coords.length - 1;
478
- const cell_ids = Array.from({ length: n_cols }, () => new Array(n_rows).fill(-1));
478
+ const cell_ids = Array.from({ length: n_cols }, () => Array(n_rows).fill(-1));
479
479
  // Check which cell edges have boundaries
480
- const h_walls = Array.from({ length: n_cols }, () => new Array(n_rows + 1).fill(false));
481
- const v_walls = Array.from({ length: n_cols + 1 }, () => new Array(n_rows).fill(false));
480
+ const h_walls = Array.from({ length: n_cols }, () => Array(n_rows + 1).fill(false));
481
+ const v_walls = Array.from({ length: n_cols + 1 }, () => Array(n_rows).fill(false));
482
482
  // Mark horizontal walls (bottom/top of cells)
483
483
  for (const hb of horizontals) {
484
484
  const row = find_coord_index(y_coords, hb.y1);
@@ -720,14 +720,12 @@ function find_comment_text(group) {
720
720
  return null;
721
721
  }
722
722
  // Clean LaTeX subscript notation: "La$_2$NiO$_4$" -> "La2NiO4"
723
- function clean_latex(text) {
724
- return text
725
- .replaceAll(/\$_\{([^}]*)\}\$/g, `$1`) // $_{10}$ -> 10
726
- .replaceAll(/\$_(\d)\$/g, `$1`) // $_2$ -> 2
727
- .replaceAll(`$`, ``) // remove any remaining $
728
- .replaceAll(/\s+/g, ` `)
729
- .trim();
730
- }
723
+ const clean_latex = (text) => text
724
+ .replaceAll(/\$_\{([^}]*)\}\$/g, `$1`) // $_{10}$ -> 10
725
+ .replaceAll(/\$_(\d)\$/g, `$1`) // $_2$ -> 2
726
+ .replaceAll(`$`, ``) // remove any remaining $
727
+ .replaceAll(/\s+/g, ` `)
728
+ .trim();
731
729
  // Parse SVG path data into absolute line segments [x1,y1,x2,y2]
732
730
  // Handles all SVG path commands (M/L/H/V/C/S/Q/T/A/Z, both absolute and relative)
733
731
  // Curves (C/S/Q/T/A) are approximated as straight lines from start to endpoint
@@ -798,7 +796,7 @@ function parse_path_segments(path_str) {
798
796
  const upper = cmd.toUpperCase();
799
797
  const skip = curve_skip[upper];
800
798
  if (skip !== undefined) {
801
- for (let _skip = 0; _skip < skip; _skip++)
799
+ for (let skip_idx = 0; skip_idx < skip; skip_idx++)
802
800
  next_num();
803
801
  const end_x = next_num();
804
802
  const end_y = next_num();
@@ -25,7 +25,6 @@
25
25
  RefLine,
26
26
  RefLineEvent,
27
27
  ScaleType,
28
- TweenedOptions,
29
28
  UserContentProps,
30
29
  XyObj,
31
30
  } from './'
@@ -70,7 +69,7 @@
70
69
  import type { Snippet } from 'svelte'
71
70
  import { untrack } from 'svelte'
72
71
  import type { HTMLAttributes } from 'svelte/elements'
73
- import { Tween } from 'svelte/motion'
72
+ import { Tween, type TweenOptions } from 'svelte/motion'
74
73
  import { SvelteMap } from 'svelte/reactivity'
75
74
  import type { Vec2 } from '../math'
76
75
  import {
@@ -193,7 +192,7 @@
193
192
  radius_range?: [number, number]
194
193
  value_range?: [number, number]
195
194
  }
196
- point_tween?: TweenedOptions<XyObj>
195
+ point_tween?: TweenOptions<XyObj>
197
196
  on_point_click?: (
198
197
  data: LineMarkerHandlerProps & { event: MouseEvent | KeyboardEvent },
199
198
  ) => void
@@ -366,7 +365,7 @@
366
365
 
367
366
  if (!points.length) return [0, 1]
368
367
 
369
- let y_range = get_nice_data_range(
368
+ let computed_y_range = get_nice_data_range(
370
369
  points,
371
370
  (pt) => pt.y,
372
371
  y_limit,
@@ -384,12 +383,12 @@
384
383
 
385
384
  // Only adjust if no explicit y_range is set
386
385
  if (y_limit?.[0] == null && y_limit?.[1] == null) {
387
- if (has_positive && !has_negative) y_range = [0, y_range[1]]
388
- else if (has_negative && !has_positive) y_range = [y_range[0], 0]
386
+ if (has_positive && !has_negative) computed_y_range = [0, computed_y_range[1]]
387
+ else if (has_negative && !has_positive) computed_y_range = [computed_y_range[0], 0]
389
388
  }
390
389
  }
391
390
 
392
- return y_range
391
+ return computed_y_range
393
392
  }
394
393
 
395
394
  // Get x values split by axis for range calculation
@@ -1070,6 +1069,7 @@
1070
1069
 
1071
1070
  // Legend placement stability state
1072
1071
  let legend_element = $state<HTMLDivElement | undefined>()
1072
+ let hovered_legend_series_idx = $state<number | null>(null)
1073
1073
  const legend_hover = create_hover_lock()
1074
1074
  const dim_tracker = create_dimension_tracker()
1075
1075
  let has_initial_legend_placement = $state(false)
@@ -1102,7 +1102,7 @@
1102
1102
  // untrack() explicitly captures initial tween config (intentional - config set once at mount)
1103
1103
  const tweened_legend_coords = new Tween(
1104
1104
  { x: 0, y: 0 },
1105
- untrack(() => ({ duration: 400, ...(legend?.tween ?? {}) })),
1105
+ untrack(() => ({ duration: 400, ...legend?.tween })),
1106
1106
  )
1107
1107
 
1108
1108
  // Update legend position with stability checks
@@ -1450,7 +1450,7 @@
1450
1450
  y1={-(height - pad.b - pad.t)}
1451
1451
  y2="0"
1452
1452
  {...DEFAULT_GRID_STYLE}
1453
- {...(x_axis.grid_style ?? {})}
1453
+ {...x_axis.grid_style}
1454
1454
  />
1455
1455
  {/if}
1456
1456
  <line
@@ -1525,7 +1525,7 @@
1525
1525
  y1="0"
1526
1526
  y2={height - pad.b - pad.t}
1527
1527
  {...DEFAULT_GRID_STYLE}
1528
- {...(x2_axis.grid_style ?? {})}
1528
+ {...x2_axis.grid_style}
1529
1529
  />
1530
1530
  {/if}
1531
1531
  <line
@@ -1595,7 +1595,7 @@
1595
1595
  x1="0"
1596
1596
  x2={width - pad.l - pad.r}
1597
1597
  {...DEFAULT_GRID_STYLE}
1598
- {...(y_axis.grid_style ?? {})}
1598
+ {...y_axis.grid_style}
1599
1599
  />
1600
1600
  {/if}
1601
1601
  <line
@@ -1674,7 +1674,7 @@
1674
1674
  x1={-(width - pad.l - pad.r)}
1675
1675
  x2="0"
1676
1676
  {...DEFAULT_GRID_STYLE}
1677
- {...(y2_axis.grid_style ?? {})}
1677
+ {...y2_axis.grid_style}
1678
1678
  />
1679
1679
  {/if}
1680
1680
  <line
@@ -1766,6 +1766,10 @@
1766
1766
  <g
1767
1767
  class={is_line ? `line-series` : `bar-series`}
1768
1768
  data-series-idx={series_idx}
1769
+ opacity={hovered_legend_series_idx !== null &&
1770
+ hovered_legend_series_idx !== series_idx
1771
+ ? 0.25
1772
+ : 1}
1769
1773
  >
1770
1774
  {#if is_line}
1771
1775
  <!-- Render as line -->
@@ -2079,7 +2083,7 @@
2079
2083
  </svg>
2080
2084
 
2081
2085
  <!-- Legend -->
2082
- {#if legend && series.length > 1}
2086
+ {#if legend && (show_legend !== undefined ? show_legend : series.length > 1)}
2083
2087
  <PlotLegend
2084
2088
  bind:root_element={legend_element}
2085
2089
  {...legend}
@@ -2087,6 +2091,11 @@
2087
2091
  on_toggle={legend?.on_toggle || toggle_series_visibility}
2088
2092
  on_group_toggle={legend?.on_group_toggle || toggle_group_visibility}
2089
2093
  on_hover_change={legend_hover.set_locked}
2094
+ on_item_hover={(series_idx) =>
2095
+ (hovered_legend_series_idx = series_idx != null && series_idx >= 0
2096
+ ? series_idx
2097
+ : null)}
2098
+ active_series_idx={hover_info?.series_idx ?? hovered_legend_series_idx}
2090
2099
  style={`
2091
2100
  position: absolute;
2092
2101
  left: ${legend_placement ? tweened_legend_coords.current.x : pad.l + 10}px;
@@ -2196,8 +2205,8 @@
2196
2205
  left: 0;
2197
2206
  width: 100vw !important;
2198
2207
  height: 100vh !important;
2199
- /* Must be higher than Structure.svelte's --struct-buttons-z-index (100000000) */
2200
- z-index: var(--barplot-fullscreen-z-index, 100000001);
2208
+ /* Must be higher than Structure.svelte's --struct-buttons-z-index. */
2209
+ z-index: var(--barplot-fullscreen-z-index, var(--z-index-overlay-nav, 100000001));
2201
2210
  margin: 0;
2202
2211
  border-radius: 0;
2203
2212
  background: var(--barplot-fullscreen-bg, var(--barplot-bg, var(--plot-bg)));
@@ -1,7 +1,8 @@
1
1
  import type { D3ColorSchemeName, D3InterpolateName } from '../colors';
2
- import type { AxisLoadError, BarHandlerProps, BarMode, BarSeries, BarStyle, BasePlotProps, DataLoaderFn, InternalPoint, LegendConfig, LineStyle, Orientation, PanConfig, PlotConfig, RefLine, RefLineEvent, ScaleType, TweenedOptions, UserContentProps, XyObj } from './';
2
+ import type { AxisLoadError, BarHandlerProps, BarMode, BarSeries, BarStyle, BasePlotProps, DataLoaderFn, InternalPoint, LegendConfig, LineStyle, Orientation, PanConfig, PlotConfig, RefLine, RefLineEvent, ScaleType, UserContentProps, XyObj } from './';
3
3
  import type { Snippet } from 'svelte';
4
4
  import type { HTMLAttributes } from 'svelte/elements';
5
+ import { type TweenOptions } from 'svelte/motion';
5
6
  declare function $$render<Metadata extends Record<string, unknown> = Record<string, unknown>>(): {
6
7
  props: HTMLAttributes<HTMLDivElement> & BasePlotProps & PlotConfig & {
7
8
  series?: BarSeries<Metadata>[];
@@ -39,7 +40,7 @@ declare function $$render<Metadata extends Record<string, unknown> = Record<stri
39
40
  radius_range?: [number, number];
40
41
  value_range?: [number, number];
41
42
  };
42
- point_tween?: TweenedOptions<XyObj>;
43
+ point_tween?: TweenOptions<XyObj>;
43
44
  on_point_click?: (data: (BarHandlerProps<Metadata> & {
44
45
  point: InternalPoint<Metadata>;
45
46
  }) & {
@@ -3,12 +3,11 @@
3
3
  // Supports gradients, hover/click interactions, and animated path transitions
4
4
  import { interpolatePath } from 'd3-interpolate-path'
5
5
  import { untrack } from 'svelte'
6
- import { Tween } from 'svelte/motion'
6
+ import { Tween, type TweenOptions } from 'svelte/motion'
7
7
  import type {
8
8
  FillGradient,
9
9
  FillHandlerEvent,
10
10
  FillRegion,
11
- TweenedOptions,
12
11
  } from './types'
13
12
 
14
13
  let {
@@ -32,7 +31,7 @@
32
31
  hovered_region?: number | null
33
32
  on_click?: (event: FillHandlerEvent) => void
34
33
  on_hover?: (event: FillHandlerEvent | null) => void
35
- tween_options?: TweenedOptions<string>
34
+ tween_options?: TweenOptions<string>
36
35
  } = $props()
37
36
 
38
37
  // Stable instance ID for gradient uniqueness (generated once per component instance)
@@ -1,4 +1,5 @@
1
- import type { FillHandlerEvent, FillRegion, TweenedOptions } from './types';
1
+ import { type TweenOptions } from 'svelte/motion';
2
+ import type { FillHandlerEvent, FillRegion } from './types';
2
3
  type $$ComponentProps = {
3
4
  region: FillRegion;
4
5
  region_idx: number;
@@ -13,7 +14,7 @@ type $$ComponentProps = {
13
14
  hovered_region?: number | null;
14
15
  on_click?: (event: FillHandlerEvent) => void;
15
16
  on_hover?: (event: FillHandlerEvent | null) => void;
16
- tween_options?: TweenedOptions<string>;
17
+ tween_options?: TweenOptions<string>;
17
18
  };
18
19
  declare const FillArea: import("svelte").Component<$$ComponentProps, {}, "">;
19
20
  type FillArea = ReturnType<typeof FillArea>;