matterviz 0.1.0

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 (131) hide show
  1. package/dist/BohrAtom.svelte +105 -0
  2. package/dist/BohrAtom.svelte.d.ts +21 -0
  3. package/dist/ControlPanel.svelte +158 -0
  4. package/dist/ControlPanel.svelte.d.ts +18 -0
  5. package/dist/Icon.svelte +23 -0
  6. package/dist/Icon.svelte.d.ts +8 -0
  7. package/dist/InfoCard.svelte +79 -0
  8. package/dist/InfoCard.svelte.d.ts +23 -0
  9. package/dist/Nucleus.svelte +64 -0
  10. package/dist/Nucleus.svelte.d.ts +16 -0
  11. package/dist/Spinner.svelte +44 -0
  12. package/dist/Spinner.svelte.d.ts +7 -0
  13. package/dist/api.d.ts +6 -0
  14. package/dist/api.js +30 -0
  15. package/dist/colors/alloy-colors.json +111 -0
  16. package/dist/colors/dark-mode-colors.json +111 -0
  17. package/dist/colors/index.d.ts +26 -0
  18. package/dist/colors/index.js +72 -0
  19. package/dist/colors/jmol-colors.json +111 -0
  20. package/dist/colors/muted-colors.json +111 -0
  21. package/dist/colors/pastel-colors.json +111 -0
  22. package/dist/colors/vesta-colors.json +111 -0
  23. package/dist/composition/BarChart.svelte +260 -0
  24. package/dist/composition/BarChart.svelte.d.ts +33 -0
  25. package/dist/composition/BubbleChart.svelte +166 -0
  26. package/dist/composition/BubbleChart.svelte.d.ts +30 -0
  27. package/dist/composition/Composition.svelte +73 -0
  28. package/dist/composition/Composition.svelte.d.ts +27 -0
  29. package/dist/composition/PieChart.svelte +236 -0
  30. package/dist/composition/PieChart.svelte.d.ts +36 -0
  31. package/dist/composition/index.d.ts +5 -0
  32. package/dist/composition/index.js +5 -0
  33. package/dist/composition/parse.d.ts +14 -0
  34. package/dist/composition/parse.js +307 -0
  35. package/dist/element/ElementHeading.svelte +21 -0
  36. package/dist/element/ElementHeading.svelte.d.ts +8 -0
  37. package/dist/element/ElementPhoto.svelte +56 -0
  38. package/dist/element/ElementPhoto.svelte.d.ts +9 -0
  39. package/dist/element/ElementStats.svelte +73 -0
  40. package/dist/element/ElementStats.svelte.d.ts +8 -0
  41. package/dist/element/ElementTile.svelte +449 -0
  42. package/dist/element/ElementTile.svelte.d.ts +25 -0
  43. package/dist/element/data.d.ts +4958 -0
  44. package/dist/element/data.js +5628 -0
  45. package/dist/element/index.d.ts +4 -0
  46. package/dist/element/index.js +4 -0
  47. package/dist/icons.d.ts +435 -0
  48. package/dist/icons.js +435 -0
  49. package/dist/index.d.ts +82 -0
  50. package/dist/index.js +43 -0
  51. package/dist/io/decompress.d.ts +16 -0
  52. package/dist/io/decompress.js +78 -0
  53. package/dist/io/export.d.ts +9 -0
  54. package/dist/io/export.js +205 -0
  55. package/dist/io/parse.d.ts +53 -0
  56. package/dist/io/parse.js +747 -0
  57. package/dist/labels.d.ts +31 -0
  58. package/dist/labels.js +209 -0
  59. package/dist/material/MaterialCard.svelte +135 -0
  60. package/dist/material/MaterialCard.svelte.d.ts +10 -0
  61. package/dist/material/SymmetryCard.svelte +23 -0
  62. package/dist/material/SymmetryCard.svelte.d.ts +9 -0
  63. package/dist/material/index.d.ts +2 -0
  64. package/dist/material/index.js +2 -0
  65. package/dist/math.d.ts +24 -0
  66. package/dist/math.js +216 -0
  67. package/dist/periodic-table/PeriodicTable.svelte +284 -0
  68. package/dist/periodic-table/PeriodicTable.svelte.d.ts +50 -0
  69. package/dist/periodic-table/PropertySelect.svelte +20 -0
  70. package/dist/periodic-table/PropertySelect.svelte.d.ts +13 -0
  71. package/dist/periodic-table/TableInset.svelte +18 -0
  72. package/dist/periodic-table/TableInset.svelte.d.ts +9 -0
  73. package/dist/periodic-table/index.d.ts +9 -0
  74. package/dist/periodic-table/index.js +3 -0
  75. package/dist/plot/ColorBar.svelte +414 -0
  76. package/dist/plot/ColorBar.svelte.d.ts +22 -0
  77. package/dist/plot/ColorScaleSelect.svelte +31 -0
  78. package/dist/plot/ColorScaleSelect.svelte.d.ts +15 -0
  79. package/dist/plot/ElementScatter.svelte +38 -0
  80. package/dist/plot/ElementScatter.svelte.d.ts +14 -0
  81. package/dist/plot/Line.svelte +42 -0
  82. package/dist/plot/Line.svelte.d.ts +15 -0
  83. package/dist/plot/PlotLegend.svelte +206 -0
  84. package/dist/plot/PlotLegend.svelte.d.ts +18 -0
  85. package/dist/plot/ScatterPlot.svelte +1753 -0
  86. package/dist/plot/ScatterPlot.svelte.d.ts +114 -0
  87. package/dist/plot/ScatterPlotControls.svelte +505 -0
  88. package/dist/plot/ScatterPlotControls.svelte.d.ts +33 -0
  89. package/dist/plot/ScatterPoint.svelte +72 -0
  90. package/dist/plot/ScatterPoint.svelte.d.ts +17 -0
  91. package/dist/plot/index.d.ts +168 -0
  92. package/dist/plot/index.js +46 -0
  93. package/dist/state.svelte.d.ts +12 -0
  94. package/dist/state.svelte.js +11 -0
  95. package/dist/structure/Bond.svelte +68 -0
  96. package/dist/structure/Bond.svelte.d.ts +13 -0
  97. package/dist/structure/Lattice.svelte +115 -0
  98. package/dist/structure/Lattice.svelte.d.ts +15 -0
  99. package/dist/structure/Structure.svelte +298 -0
  100. package/dist/structure/Structure.svelte.d.ts +28 -0
  101. package/dist/structure/StructureCard.svelte +26 -0
  102. package/dist/structure/StructureCard.svelte.d.ts +9 -0
  103. package/dist/structure/StructureControls.svelte +383 -0
  104. package/dist/structure/StructureControls.svelte.d.ts +23 -0
  105. package/dist/structure/StructureLegend.svelte +130 -0
  106. package/dist/structure/StructureLegend.svelte.d.ts +17 -0
  107. package/dist/structure/StructureScene.svelte +331 -0
  108. package/dist/structure/StructureScene.svelte.d.ts +47 -0
  109. package/dist/structure/bonding.d.ts +16 -0
  110. package/dist/structure/bonding.js +150 -0
  111. package/dist/structure/index.d.ts +98 -0
  112. package/dist/structure/index.js +114 -0
  113. package/dist/structure/pbc.d.ts +6 -0
  114. package/dist/structure/pbc.js +72 -0
  115. package/dist/trajectory/Sidebar.svelte +412 -0
  116. package/dist/trajectory/Sidebar.svelte.d.ts +14 -0
  117. package/dist/trajectory/Trajectory.svelte +1084 -0
  118. package/dist/trajectory/Trajectory.svelte.d.ts +49 -0
  119. package/dist/trajectory/TrajectoryError.svelte +120 -0
  120. package/dist/trajectory/TrajectoryError.svelte.d.ts +12 -0
  121. package/dist/trajectory/extract.d.ts +5 -0
  122. package/dist/trajectory/extract.js +157 -0
  123. package/dist/trajectory/index.d.ts +16 -0
  124. package/dist/trajectory/index.js +49 -0
  125. package/dist/trajectory/parse.d.ts +13 -0
  126. package/dist/trajectory/parse.js +1093 -0
  127. package/dist/trajectory/plotting.d.ts +12 -0
  128. package/dist/trajectory/plotting.js +148 -0
  129. package/license +21 -0
  130. package/package.json +131 -0
  131. package/readme.md +95 -0
@@ -0,0 +1,114 @@
1
+ import type { D3ColorSchemeName, D3InterpolateName } from '../colors';
2
+ import type { DataSeries, HoverConfig, InternalPoint, LabelPlacementConfig, LegendConfig, PlotPoint, Point, ScaleType, Sides, TimeInterval, TooltipProps, XyObj } from './';
3
+ import { ColorBar } from './';
4
+ import type { ComponentProps, Snippet } from 'svelte';
5
+ type LocalTweenedOptions<T> = {
6
+ duration?: number;
7
+ delay?: number;
8
+ easing?: (t: number) => number;
9
+ interpolate?: (a: T, b: T) => (t: number) => T;
10
+ };
11
+ interface Props {
12
+ series?: DataSeries[];
13
+ style?: string;
14
+ x_lim?: [number | null, number | null];
15
+ y_lim?: [number | null, number | null];
16
+ x_range?: [number, number];
17
+ y_range?: [number, number];
18
+ current_x_value?: number | null;
19
+ y2_lim?: [number | null, number | null];
20
+ y2_range?: [number, number];
21
+ y2_label?: string;
22
+ y2_label_shift?: {
23
+ x?: number;
24
+ y?: number;
25
+ };
26
+ y2_tick_label_shift?: {
27
+ x?: number;
28
+ y?: number;
29
+ };
30
+ y2_unit?: string;
31
+ y2_format?: string;
32
+ y2_ticks?: number;
33
+ y2_scale_type?: ScaleType;
34
+ y2_grid?: boolean | Record<string, unknown>;
35
+ padding?: Sides;
36
+ x_label?: string;
37
+ x_label_shift?: {
38
+ x?: number;
39
+ y?: number;
40
+ };
41
+ x_tick_label_shift?: {
42
+ x?: number;
43
+ y?: number;
44
+ };
45
+ y_label?: string;
46
+ y_label_shift?: {
47
+ x?: number;
48
+ y?: number;
49
+ };
50
+ y_tick_label_shift?: {
51
+ x?: number;
52
+ y?: number;
53
+ };
54
+ y_unit?: string;
55
+ tooltip_point?: InternalPoint | null;
56
+ hovered?: boolean;
57
+ markers?: `line` | `points` | `line+points`;
58
+ x_format?: string;
59
+ y_format?: string;
60
+ tooltip?: Snippet<[PlotPoint & TooltipProps]>;
61
+ change?: (data: (Point & {
62
+ series: DataSeries;
63
+ }) | null) => void;
64
+ x_ticks?: number | TimeInterval | number[];
65
+ y_ticks?: number | number[];
66
+ x_scale_type?: ScaleType;
67
+ y_scale_type?: ScaleType;
68
+ show_zero_lines?: boolean;
69
+ x_grid?: boolean | Record<string, unknown>;
70
+ y_grid?: boolean | Record<string, unknown>;
71
+ color_scale?: {
72
+ type?: ScaleType;
73
+ scheme?: D3ColorSchemeName | D3InterpolateName;
74
+ value_range?: [number, number];
75
+ };
76
+ size_scale?: {
77
+ type?: ScaleType;
78
+ radius_range?: [number, number];
79
+ value_range?: [number, number];
80
+ };
81
+ color_bar?: (ComponentProps<typeof ColorBar> & {
82
+ margin?: number | Sides;
83
+ tween?: LocalTweenedOptions<XyObj>;
84
+ }) | null;
85
+ label_placement_config?: Partial<LabelPlacementConfig>;
86
+ hover_config?: Partial<HoverConfig>;
87
+ legend?: LegendConfig | null;
88
+ point_tween?: LocalTweenedOptions<XyObj>;
89
+ line_tween?: LocalTweenedOptions<string>;
90
+ range_padding?: number;
91
+ point_events?: Record<string, (payload: {
92
+ point: InternalPoint;
93
+ event: Event;
94
+ }) => void>;
95
+ show_controls?: boolean;
96
+ controls_open?: boolean;
97
+ plot_controls?: Snippet<[]>;
98
+ point_size?: number;
99
+ point_color?: string;
100
+ point_opacity?: number;
101
+ point_stroke_width?: number;
102
+ point_stroke_color?: string;
103
+ point_stroke_opacity?: number;
104
+ line_width?: number;
105
+ line_color?: string;
106
+ line_opacity?: number;
107
+ line_dash?: string | undefined;
108
+ show_points?: boolean;
109
+ show_lines?: boolean;
110
+ selected_series_idx?: number;
111
+ }
112
+ declare const ScatterPlot: import("svelte").Component<Props, {}, "controls_open" | "hovered" | "tooltip_point" | "y_format" | "y2_format" | "x_format" | "point_size" | "point_color" | "point_opacity" | "point_stroke_width" | "point_stroke_color" | "point_stroke_opacity" | "line_width" | "line_color" | "line_opacity" | "line_dash" | "show_points" | "show_lines" | "selected_series_idx">;
113
+ type ScatterPlot = ReturnType<typeof ScatterPlot>;
114
+ export default ScatterPlot;
@@ -0,0 +1,505 @@
1
+ <script lang="ts">import { ControlPanel } from '..';
2
+ import { format } from 'd3-format';
3
+ import { timeFormat } from 'd3-time-format';
4
+ let { show_controls = $bindable(false), controls_open = $bindable(false), plot_controls, series = [], markers = $bindable(`line+points`), show_zero_lines = $bindable(true), x_grid = $bindable(true), y_grid = $bindable(true), y2_grid = $bindable(true), has_y2_points = false,
5
+ // Format controls
6
+ x_format = $bindable(``), y_format = $bindable(``), y2_format = $bindable(``),
7
+ // Style controls
8
+ point_size = $bindable(4), point_color = $bindable(`#4682b4`), point_opacity = $bindable(1), point_stroke_width = $bindable(1), point_stroke_color = $bindable(`#000000`), point_stroke_opacity = $bindable(1), line_width = $bindable(2), line_color = $bindable(`#4682b4`), line_opacity = $bindable(1), line_dash = $bindable(undefined), show_points = $bindable(true), show_lines = $bindable(true), selected_series_idx = $bindable(0), } = $props();
9
+ // Local variables for format inputs to prevent invalid values from reaching props
10
+ let x_format_input = $state(x_format);
11
+ let y_format_input = $state(y_format);
12
+ let y2_format_input = $state(y2_format);
13
+ // Derived state
14
+ let has_multiple_series = $derived(series.filter(Boolean).length > 1);
15
+ // Validation function for format specifiers
16
+ function is_valid_format(format_string) {
17
+ if (!format_string)
18
+ return true; // Empty string is valid (uses default formatting)
19
+ try {
20
+ if (format_string.startsWith(`%`)) { // Time format validation
21
+ timeFormat(format_string)(new Date());
22
+ return true;
23
+ }
24
+ else { // Number format validation
25
+ format(format_string)(123.456);
26
+ return true;
27
+ }
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }
33
+ // Handle format input changes - only update prop if valid
34
+ function handle_format_input(event, format_type) {
35
+ const input = event.target;
36
+ // Update local variable
37
+ if (format_type === `x`)
38
+ x_format_input = input.value;
39
+ else if (format_type === `y`)
40
+ y_format_input = input.value;
41
+ else if (format_type === `y2`)
42
+ y2_format_input = input.value;
43
+ // Only update prop if valid
44
+ if (is_valid_format(input.value)) {
45
+ input.classList.remove(`invalid`);
46
+ if (format_type === `x`)
47
+ x_format = input.value;
48
+ else if (format_type === `y`)
49
+ y_format = input.value;
50
+ else if (format_type === `y2`)
51
+ y2_format = input.value;
52
+ }
53
+ else
54
+ input.classList.add(`invalid`);
55
+ }
56
+ // Handle click outside control panel to close it
57
+ function handle_click_outside_controls(event) {
58
+ if (!controls_open)
59
+ return;
60
+ const target = event.target;
61
+ const control_panel = target.closest(`.plot-controls`);
62
+ // Don't close if clicking inside the control panel
63
+ if (!control_panel)
64
+ controls_open = false;
65
+ }
66
+ // Sync control states with props
67
+ $effect(() => {
68
+ // Sync with markers prop
69
+ show_points = markers?.includes(`points`) ?? false;
70
+ show_lines = markers?.includes(`line`) ?? false;
71
+ // Sync with first series style properties
72
+ if (series.length > 0 && series[0]) {
73
+ const first_series = series[0];
74
+ // Point style
75
+ const first_point_style = Array.isArray(first_series.point_style)
76
+ ? first_series.point_style[0]
77
+ : first_series.point_style;
78
+ if (first_point_style) {
79
+ point_size = first_point_style.radius ?? 4;
80
+ point_color = first_point_style.fill ?? `#4682b4`;
81
+ point_stroke_width = first_point_style.stroke_width ?? 1;
82
+ point_stroke_color = first_point_style.stroke ?? `#000000`;
83
+ point_opacity = first_point_style.fill_opacity ?? 1;
84
+ }
85
+ // Line style
86
+ if (first_series.line_style) {
87
+ line_width = first_series.line_style.stroke_width ?? 2;
88
+ line_color = first_series.line_style.stroke ?? `#4682b4`;
89
+ line_dash = first_series.line_style.line_dash;
90
+ }
91
+ }
92
+ });
93
+ // Apply control states back to props
94
+ $effect(() => {
95
+ // Update markers
96
+ const new_markers = show_points && show_lines
97
+ ? `line+points`
98
+ : show_points
99
+ ? `points`
100
+ : show_lines
101
+ ? `line`
102
+ : `points`;
103
+ if (new_markers !== markers)
104
+ markers = new_markers;
105
+ });
106
+ </script>
107
+
108
+ <svelte:document onclick={handle_click_outside_controls} />
109
+
110
+ {#if show_controls}
111
+ <div class="plot-controls">
112
+ <ControlPanel
113
+ bind:controls_open
114
+ show_toggle_button
115
+ toggle_button={{ class: `plot-controls-toggle` }}
116
+ panel_props={{ class: `plot-controls-panel`, style: `top: 30px; right: 6px;` }}
117
+ closed_icon="Settings"
118
+ open_icon="Cross"
119
+ >
120
+ {#snippet controls_content()}
121
+ {#if plot_controls}
122
+ {@render plot_controls()}
123
+ {:else}
124
+ <div class="plot-controls-content">
125
+ <!-- Display Controls -->
126
+ <h4 class="section-heading">Display</h4>
127
+ <div class="controls-group">
128
+ <label class="checkbox-label">
129
+ <input type="checkbox" bind:checked={show_zero_lines} />
130
+ Show zero lines
131
+ </label>
132
+ <label class="checkbox-label">
133
+ <input type="checkbox" bind:checked={show_points} />
134
+ Show points
135
+ </label>
136
+ <label class="checkbox-label">
137
+ <input type="checkbox" bind:checked={show_lines} />
138
+ Show lines
139
+ </label>
140
+ <label class="checkbox-label">
141
+ <input type="checkbox" bind:checked={x_grid as boolean} />
142
+ X-axis grid
143
+ </label>
144
+ <label class="checkbox-label">
145
+ <input type="checkbox" bind:checked={y_grid as boolean} />
146
+ Y-axis grid
147
+ </label>
148
+ {#if has_y2_points}
149
+ <label class="checkbox-label">
150
+ <input type="checkbox" bind:checked={y2_grid as boolean} />
151
+ Y2-axis grid
152
+ </label>
153
+ {/if}
154
+ </div>
155
+
156
+ <!-- Format Controls -->
157
+ <h4 class="section-heading">Tick Format</h4>
158
+ <div class="controls-group">
159
+ <div class="control-row">
160
+ <label for="x-format">X-axis:</label>
161
+ <input
162
+ id="x-format"
163
+ type="text"
164
+ bind:value={x_format_input}
165
+ placeholder="e.g., .2f, .0%, %Y-%m-%d"
166
+ class="format-input"
167
+ oninput={(event) => handle_format_input(event, `x`)}
168
+ />
169
+ </div>
170
+ <div class="control-row">
171
+ <label for="y-format">Y-axis:</label>
172
+ <input
173
+ id="y-format"
174
+ type="text"
175
+ bind:value={y_format_input}
176
+ placeholder="e.g., .2f, .1e, .0%"
177
+ class="format-input"
178
+ oninput={(event) => handle_format_input(event, `y`)}
179
+ />
180
+ </div>
181
+ {#if has_y2_points}
182
+ <div class="control-row">
183
+ <label for="y2-format">Y2-axis:</label>
184
+ <input
185
+ id="y2-format"
186
+ type="text"
187
+ bind:value={y2_format_input}
188
+ placeholder="e.g., .2f, .1e, .0%"
189
+ class="format-input"
190
+ oninput={(event) => handle_format_input(event, `y2`)}
191
+ />
192
+ </div>
193
+ {/if}
194
+ </div>
195
+
196
+ <!-- Series Selection (for multi-series style controls) -->
197
+ {#if has_multiple_series}
198
+ <div class="controls-group">
199
+ <div class="control-row">
200
+ <label for="series-select">Series</label>
201
+ <select bind:value={selected_series_idx} id="series-select">
202
+ {#each series.filter(Boolean) as
203
+ series_data,
204
+ idx
205
+ (series_data.label ?? idx)
206
+ }
207
+ <option value={idx}>
208
+ {series_data.label ?? `Series ${idx + 1}`}
209
+ </option>
210
+ {/each}
211
+ </select>
212
+ </div>
213
+ </div>
214
+ {/if}
215
+
216
+ <!-- Point Style Controls -->
217
+ {#if show_points}
218
+ <h4 class="section-heading">Point Style</h4>
219
+ <div class="controls-group">
220
+ <div class="control-row">
221
+ <label for="point-size-range">Size:</label>
222
+ <input
223
+ id="point-size-range"
224
+ type="range"
225
+ min="1"
226
+ max="20"
227
+ step="0.5"
228
+ bind:value={point_size}
229
+ />
230
+ <input
231
+ type="number"
232
+ min="1"
233
+ max="20"
234
+ step="0.5"
235
+ bind:value={point_size}
236
+ class="number-input"
237
+ />
238
+ </div>
239
+ <div class="control-row">
240
+ <label for="point-color">Color:</label>
241
+ <input
242
+ id="point-color"
243
+ type="color"
244
+ bind:value={point_color}
245
+ class="color-input"
246
+ />
247
+ <input
248
+ type="range"
249
+ min="0"
250
+ max="1"
251
+ step="0.05"
252
+ bind:value={point_opacity}
253
+ class="opacity-slider"
254
+ title="Color opacity"
255
+ />
256
+ <input
257
+ type="number"
258
+ min="0"
259
+ max="1"
260
+ step="0.05"
261
+ bind:value={point_opacity}
262
+ class="number-input opacity-number"
263
+ />
264
+ </div>
265
+ <div class="control-row">
266
+ <label for="point-stroke-width-range">Stroke Width:</label>
267
+ <input
268
+ id="point-stroke-width-range"
269
+ type="range"
270
+ min="0"
271
+ max="5"
272
+ step="0.1"
273
+ bind:value={point_stroke_width}
274
+ />
275
+ <input
276
+ type="number"
277
+ min="0"
278
+ max="5"
279
+ step="0.1"
280
+ bind:value={point_stroke_width}
281
+ class="number-input"
282
+ />
283
+ </div>
284
+ <div class="control-row">
285
+ <label for="point-stroke-color">Stroke Color:</label>
286
+ <input
287
+ id="point-stroke-color"
288
+ type="color"
289
+ bind:value={point_stroke_color}
290
+ />
291
+ <input
292
+ type="range"
293
+ min="0"
294
+ max="1"
295
+ step="0.05"
296
+ bind:value={point_stroke_opacity}
297
+ class="opacity-slider"
298
+ title="Stroke opacity"
299
+ />
300
+ <input
301
+ type="number"
302
+ min="0"
303
+ max="1"
304
+ step="0.05"
305
+ bind:value={point_stroke_opacity}
306
+ class="number-input opacity-number"
307
+ />
308
+ </div>
309
+ </div>
310
+ {/if}
311
+
312
+ <!-- Line Style Controls -->
313
+ {#if show_lines}
314
+ <h4 class="section-heading">Line Style</h4>
315
+ <div class="controls-group">
316
+ <div class="control-row">
317
+ <label for="line-width-range">Line Width:</label>
318
+ <input
319
+ id="line-width-range"
320
+ type="range"
321
+ min="0.5"
322
+ max="10"
323
+ step="0.5"
324
+ bind:value={line_width}
325
+ />
326
+ <input
327
+ type="number"
328
+ min="0.5"
329
+ max="10"
330
+ step="0.5"
331
+ bind:value={line_width}
332
+ class="number-input"
333
+ />
334
+ </div>
335
+ <div class="control-row">
336
+ <label for="line-color">Line Color:</label>
337
+ <input
338
+ id="line-color"
339
+ type="color"
340
+ bind:value={line_color}
341
+ />
342
+ <input
343
+ type="range"
344
+ min="0"
345
+ max="1"
346
+ step="0.05"
347
+ bind:value={line_opacity}
348
+ class="opacity-slider"
349
+ title="Line opacity"
350
+ />
351
+ <input
352
+ type="number"
353
+ min="0"
354
+ max="1"
355
+ step="0.05"
356
+ bind:value={line_opacity}
357
+ class="number-input opacity-number"
358
+ />
359
+ </div>
360
+ <div class="control-row">
361
+ <label for="line-style-select">Line Style:</label>
362
+ <select
363
+ id="line-style-select"
364
+ value={line_dash ?? `solid`}
365
+ onchange={(event) => {
366
+ line_dash = event.currentTarget.value === `solid`
367
+ ? undefined
368
+ : event.currentTarget.value
369
+ }}
370
+ >
371
+ <option value="solid">Solid</option>
372
+ <option value="4,4">Dashed</option>
373
+ <option value="2,2">Dotted</option>
374
+ <option value="8,4,2,4">Dash-dot</option>
375
+ </select>
376
+ </div>
377
+ </div>
378
+ {/if}
379
+ </div>
380
+ {/if}
381
+ {/snippet}
382
+ </ControlPanel>
383
+ </div>
384
+ {/if}
385
+
386
+ <style>
387
+ .plot-controls {
388
+ position: absolute;
389
+ top: 8px;
390
+ right: 8px;
391
+ z-index: 10;
392
+ }
393
+ .plot-controls :global(.plot-controls-toggle) {
394
+ background: transparent;
395
+ color: var(--esp-controls-icon-color, currentColor);
396
+ border: none;
397
+ border-radius: 4px;
398
+ padding: 6px;
399
+ }
400
+ .plot-controls :global(.plot-controls-toggle):hover {
401
+ background: var(--esp-controls-hover-bg, rgba(0, 0, 0, 0.2)) !important;
402
+ border-color: var(--esp-controls-hover-border, rgba(255, 255, 255, 0.3)) !important;
403
+ }
404
+ .plot-controls :global(.plot-controls-panel) {
405
+ --controls-bg: rgba(0, 0, 0, 0.9);
406
+ --controls-text-color: white;
407
+ --controls-width: 16em;
408
+ }
409
+ .plot-controls :global(.section-heading) {
410
+ margin: 0 0 8px 0;
411
+ font-size: 0.9em;
412
+ color: #ccc;
413
+ font-weight: 600;
414
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
415
+ padding-bottom: 4px;
416
+ }
417
+ .plot-controls :global(.plot-controls-content) {
418
+ max-height: 400px;
419
+ overflow-y: auto;
420
+ padding-right: 4px;
421
+ }
422
+ .plot-controls :global(.controls-group) {
423
+ display: flex;
424
+ flex-direction: column;
425
+ gap: 6px;
426
+ margin-bottom: 16px;
427
+ }
428
+ .plot-controls :global(.checkbox-label) {
429
+ display: flex;
430
+ align-items: center;
431
+ gap: 6px;
432
+ font-size: 0.85em;
433
+ }
434
+ .plot-controls :global(.control-row) {
435
+ display: flex;
436
+ align-items: center;
437
+ gap: 8px;
438
+ font-size: 0.85em;
439
+ }
440
+ .plot-controls :global(.control-row label) {
441
+ min-width: 80px;
442
+ font-size: 0.85em;
443
+ }
444
+ .plot-controls :global(.control-row input[type='range']) {
445
+ flex: 1;
446
+ min-width: 60px;
447
+ }
448
+ .plot-controls :global(.number-input) {
449
+ width: 50px;
450
+ text-align: center;
451
+ background: rgba(255, 255, 255, 0.1);
452
+ border: 1px solid rgba(255, 255, 255, 0.2);
453
+ border-radius: 3px;
454
+ color: white;
455
+ padding: 2px 4px;
456
+ font-size: 0.8em;
457
+ }
458
+ .plot-controls :global(.control-row input[type='color']) {
459
+ width: 40px;
460
+ height: 24px;
461
+ border: 1px solid rgba(255, 255, 255, 0.1);
462
+ border-radius: 3px;
463
+ cursor: pointer;
464
+ }
465
+ .plot-controls :global(.control-row select) {
466
+ flex: 1;
467
+ background: rgba(255, 255, 255, 0.1);
468
+ border: 1px solid rgba(255, 255, 255, 0.2);
469
+ border-radius: 3px;
470
+ color: white;
471
+ padding: 2px 4px;
472
+ font-size: 0.8em;
473
+ }
474
+ .plot-controls :global(.opacity-slider) {
475
+ flex: 1;
476
+ min-width: 50px;
477
+ margin-left: 4px;
478
+ }
479
+ .plot-controls :global(.opacity-number) {
480
+ width: 40px;
481
+ margin-left: 4px;
482
+ }
483
+ .plot-controls :global(.format-input) {
484
+ flex: 1;
485
+ background: rgba(255, 255, 255, 0.1);
486
+ border: 1px solid rgba(255, 255, 255, 0.2);
487
+ border-radius: 3px;
488
+ color: white;
489
+ padding: 4px 6px;
490
+ font-size: 0.8em;
491
+ font-family: monospace;
492
+ }
493
+ .plot-controls :global(.format-input::placeholder) {
494
+ color: rgba(255, 255, 255, 0.5);
495
+ font-style: italic;
496
+ }
497
+ .plot-controls :global(.format-input.invalid) {
498
+ border-color: #ff6b6b;
499
+ background: rgba(255, 107, 107, 0.1);
500
+ }
501
+ .plot-controls :global(.format-input.invalid:focus) {
502
+ outline-color: #ff6b6b;
503
+ box-shadow: 0 0 0 2px rgba(255, 107, 107, 0.2);
504
+ }
505
+ </style>
@@ -0,0 +1,33 @@
1
+ import type { DataSeries } from './';
2
+ import type { Snippet } from 'svelte';
3
+ interface Props {
4
+ show_controls?: boolean;
5
+ controls_open?: boolean;
6
+ plot_controls?: Snippet<[]>;
7
+ series?: readonly DataSeries[];
8
+ markers?: `line` | `points` | `line+points`;
9
+ show_zero_lines?: boolean;
10
+ x_grid?: boolean | Record<string, unknown>;
11
+ y_grid?: boolean | Record<string, unknown>;
12
+ y2_grid?: boolean | Record<string, unknown>;
13
+ has_y2_points?: boolean;
14
+ x_format?: string;
15
+ y_format?: string;
16
+ y2_format?: string;
17
+ point_size?: number;
18
+ point_color?: string;
19
+ point_opacity?: number;
20
+ point_stroke_width?: number;
21
+ point_stroke_color?: string;
22
+ point_stroke_opacity?: number;
23
+ line_width?: number;
24
+ line_color?: string;
25
+ line_opacity?: number;
26
+ line_dash?: string | undefined;
27
+ show_points?: boolean;
28
+ show_lines?: boolean;
29
+ selected_series_idx?: number;
30
+ }
31
+ declare const ScatterPlotControls: import("svelte").Component<Props, {}, "controls_open" | "y_format" | "y2_format" | "x_format" | "point_size" | "point_color" | "point_opacity" | "point_stroke_width" | "point_stroke_color" | "point_stroke_opacity" | "line_width" | "line_color" | "line_opacity" | "line_dash" | "show_points" | "show_lines" | "selected_series_idx" | "y2_grid" | "markers" | "show_zero_lines" | "x_grid" | "y_grid" | "show_controls">;
32
+ type ScatterPlotControls = ReturnType<typeof ScatterPlotControls>;
33
+ export default ScatterPlotControls;