matterviz 0.1.12 → 0.1.13

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 (195) hide show
  1. package/dist/ContextMenu.svelte +1 -1
  2. package/dist/ContextMenu.svelte.d.ts +3 -3
  3. package/dist/DraggablePane.svelte +10 -5
  4. package/dist/DraggablePane.svelte.d.ts +3 -3
  5. package/dist/FilePicker.svelte.d.ts +3 -3
  6. package/dist/Icon.svelte.d.ts +3 -3
  7. package/dist/Nav.svelte +76 -31
  8. package/dist/SettingsSection.svelte.d.ts +3 -3
  9. package/dist/Spinner.svelte +18 -29
  10. package/dist/Spinner.svelte.d.ts +3 -3
  11. package/dist/app.css +4 -0
  12. package/dist/bands/Bands.svelte +216 -0
  13. package/dist/bands/Bands.svelte.d.ts +16 -0
  14. package/dist/bands/BandsAndDos.svelte +26 -0
  15. package/dist/bands/BandsAndDos.svelte.d.ts +16 -0
  16. package/dist/bands/Dos.svelte +124 -0
  17. package/dist/bands/Dos.svelte.d.ts +18 -0
  18. package/dist/bands/helpers.d.ts +11 -0
  19. package/dist/bands/helpers.js +195 -0
  20. package/dist/bands/index.d.ts +5 -0
  21. package/dist/bands/index.js +6 -0
  22. package/dist/bands/types.d.ts +54 -0
  23. package/dist/bands/types.js +2 -0
  24. package/dist/brillouin/BrillouinZone.svelte +373 -0
  25. package/dist/brillouin/BrillouinZone.svelte.d.ts +57 -0
  26. package/dist/brillouin/BrillouinZoneControls.svelte +88 -0
  27. package/dist/brillouin/BrillouinZoneControls.svelte.d.ts +14 -0
  28. package/dist/brillouin/BrillouinZoneExportPane.svelte +129 -0
  29. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +15 -0
  30. package/dist/brillouin/BrillouinZoneInfoPane.svelte +115 -0
  31. package/dist/brillouin/BrillouinZoneInfoPane.svelte.d.ts +13 -0
  32. package/dist/brillouin/BrillouinZoneScene.svelte +180 -0
  33. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +34 -0
  34. package/dist/brillouin/compute.d.ts +7 -0
  35. package/dist/brillouin/compute.js +215 -0
  36. package/dist/brillouin/index.d.ts +7 -0
  37. package/dist/brillouin/index.js +7 -0
  38. package/dist/brillouin/types.d.ts +23 -0
  39. package/dist/brillouin/types.js +1 -0
  40. package/dist/composition/BarChart.svelte.d.ts +3 -3
  41. package/dist/composition/BubbleChart.svelte +7 -6
  42. package/dist/composition/BubbleChart.svelte.d.ts +3 -3
  43. package/dist/composition/Composition.svelte.d.ts +3 -3
  44. package/dist/composition/PieChart.svelte +1 -1
  45. package/dist/composition/PieChart.svelte.d.ts +3 -3
  46. package/dist/composition/parse.d.ts +3 -3
  47. package/dist/coordination/CoordinationBarPlot.svelte +241 -0
  48. package/dist/coordination/CoordinationBarPlot.svelte.d.ts +29 -0
  49. package/dist/coordination/calc-coordination.d.ts +15 -0
  50. package/dist/coordination/calc-coordination.js +66 -0
  51. package/dist/coordination/index.d.ts +8 -0
  52. package/dist/coordination/index.js +7 -0
  53. package/dist/element/BohrAtom.svelte.d.ts +3 -3
  54. package/dist/element/ElementHeading.svelte.d.ts +3 -3
  55. package/dist/element/ElementPhoto.svelte.d.ts +3 -3
  56. package/dist/element/ElementStats.svelte.d.ts +3 -3
  57. package/dist/element/ElementTile.svelte +1 -1
  58. package/dist/element/ElementTile.svelte.d.ts +4 -4
  59. package/dist/element/Nucleus.svelte.d.ts +3 -3
  60. package/dist/icons.d.ts +4 -0
  61. package/dist/icons.js +4 -0
  62. package/dist/index.d.ts +5 -1
  63. package/dist/index.js +5 -1
  64. package/dist/io/export.d.ts +1 -6
  65. package/dist/io/export.js +12 -12
  66. package/dist/labels.d.ts +19 -0
  67. package/dist/labels.js +59 -0
  68. package/dist/math.d.ts +7 -2
  69. package/dist/math.js +24 -12
  70. package/dist/periodic-table/PeriodicTable.svelte.d.ts +3 -3
  71. package/dist/periodic-table/PeriodicTableControls.svelte.d.ts +3 -3
  72. package/dist/periodic-table/PropertySelect.svelte +1 -1
  73. package/dist/periodic-table/PropertySelect.svelte.d.ts +5 -4
  74. package/dist/periodic-table/TableInset.svelte.d.ts +3 -3
  75. package/dist/phase-diagram/PhaseDiagram2D.svelte +44 -107
  76. package/dist/phase-diagram/PhaseDiagram2D.svelte.d.ts +7 -27
  77. package/dist/phase-diagram/PhaseDiagram3D.svelte +67 -170
  78. package/dist/phase-diagram/PhaseDiagram3D.svelte.d.ts +7 -31
  79. package/dist/phase-diagram/PhaseDiagram4D.svelte +87 -145
  80. package/dist/phase-diagram/PhaseDiagram4D.svelte.d.ts +5 -28
  81. package/dist/phase-diagram/PhaseDiagramControls.svelte +9 -9
  82. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +6 -6
  83. package/dist/phase-diagram/PhaseDiagramInfoPane.svelte +4 -4
  84. package/dist/phase-diagram/PhaseDiagramInfoPane.svelte.d.ts +5 -5
  85. package/dist/phase-diagram/PhaseDiagramStats.svelte +9 -16
  86. package/dist/phase-diagram/PhaseDiagramStats.svelte.d.ts +3 -3
  87. package/dist/phase-diagram/StructurePopup.svelte.d.ts +3 -3
  88. package/dist/phase-diagram/barycentric-coords.js +13 -24
  89. package/dist/phase-diagram/helpers.d.ts +12 -14
  90. package/dist/phase-diagram/helpers.js +70 -23
  91. package/dist/phase-diagram/index.d.ts +58 -0
  92. package/dist/phase-diagram/index.js +44 -0
  93. package/dist/phase-diagram/thermodynamics.js +2 -3
  94. package/dist/phase-diagram/types.d.ts +3 -8
  95. package/dist/plot/BarPlot.svelte +474 -240
  96. package/dist/plot/BarPlot.svelte.d.ts +16 -37
  97. package/dist/plot/BarPlotControls.svelte +33 -201
  98. package/dist/plot/BarPlotControls.svelte.d.ts +11 -22
  99. package/dist/plot/ColorBar.svelte.d.ts +3 -3
  100. package/dist/plot/ColorScaleSelect.svelte +1 -1
  101. package/dist/plot/ColorScaleSelect.svelte.d.ts +3 -3
  102. package/dist/plot/ElementScatter.svelte +5 -5
  103. package/dist/plot/ElementScatter.svelte.d.ts +8 -8
  104. package/dist/plot/Histogram.svelte +318 -170
  105. package/dist/plot/Histogram.svelte.d.ts +21 -41
  106. package/dist/plot/HistogramControls.svelte +115 -347
  107. package/dist/plot/HistogramControls.svelte.d.ts +13 -28
  108. package/dist/plot/Line.svelte +1 -1
  109. package/dist/plot/Line.svelte.d.ts +4 -4
  110. package/dist/plot/PlotControls.svelte +280 -0
  111. package/dist/plot/PlotControls.svelte.d.ts +4 -0
  112. package/dist/plot/PlotLegend.svelte +9 -24
  113. package/dist/plot/PlotLegend.svelte.d.ts +3 -3
  114. package/dist/plot/ScatterPlot.svelte +536 -571
  115. package/dist/plot/ScatterPlot.svelte.d.ts +18 -90
  116. package/dist/plot/ScatterPlotControls.svelte +108 -316
  117. package/dist/plot/ScatterPlotControls.svelte.d.ts +11 -38
  118. package/dist/plot/ScatterPoint.svelte +1 -1
  119. package/dist/plot/ScatterPoint.svelte.d.ts +5 -5
  120. package/dist/plot/SpacegroupBarPlot.svelte +235 -0
  121. package/dist/plot/SpacegroupBarPlot.svelte.d.ts +9 -0
  122. package/dist/plot/data-transform.d.ts +2 -2
  123. package/dist/plot/data-transform.js +1 -5
  124. package/dist/plot/index.d.ts +12 -200
  125. package/dist/plot/index.js +14 -6
  126. package/dist/plot/layout.d.ts +10 -16
  127. package/dist/plot/layout.js +40 -25
  128. package/dist/plot/scales.d.ts +7 -8
  129. package/dist/plot/scales.js +22 -7
  130. package/dist/plot/types.d.ts +303 -0
  131. package/dist/plot/types.js +1 -0
  132. package/dist/rdf/RdfPlot.svelte +156 -0
  133. package/dist/rdf/RdfPlot.svelte.d.ts +20 -0
  134. package/dist/rdf/calc-rdf.d.ts +4 -0
  135. package/dist/rdf/calc-rdf.js +107 -0
  136. package/dist/rdf/index.d.ts +22 -0
  137. package/dist/rdf/index.js +2 -0
  138. package/dist/settings.d.ts +86 -75
  139. package/dist/settings.js +257 -155
  140. package/dist/structure/Bond.svelte +126 -110
  141. package/dist/structure/Bond.svelte.d.ts +7 -20
  142. package/dist/structure/CanvasTooltip.svelte.d.ts +4 -4
  143. package/dist/structure/Cylinder.svelte +29 -0
  144. package/dist/structure/Cylinder.svelte.d.ts +10 -0
  145. package/dist/structure/Lattice.svelte +1 -2
  146. package/dist/structure/Lattice.svelte.d.ts +3 -3
  147. package/dist/structure/Structure.svelte +23 -8
  148. package/dist/structure/Structure.svelte.d.ts +10 -7
  149. package/dist/structure/StructureControls.svelte +25 -134
  150. package/dist/structure/StructureControls.svelte.d.ts +4 -9
  151. package/dist/structure/StructureExportPane.svelte +188 -0
  152. package/dist/structure/StructureExportPane.svelte.d.ts +17 -0
  153. package/dist/structure/StructureInfoPane.svelte.d.ts +3 -3
  154. package/dist/structure/StructureLegend.svelte +91 -27
  155. package/dist/structure/StructureLegend.svelte.d.ts +5 -4
  156. package/dist/structure/StructureScene.svelte +93 -100
  157. package/dist/structure/StructureScene.svelte.d.ts +15 -12
  158. package/dist/structure/Vector.svelte +19 -25
  159. package/dist/structure/Vector.svelte.d.ts +3 -3
  160. package/dist/structure/bonding.d.ts +16 -14
  161. package/dist/structure/bonding.js +207 -216
  162. package/dist/structure/export.d.ts +3 -0
  163. package/dist/structure/export.js +120 -0
  164. package/dist/structure/index.d.ts +15 -1
  165. package/dist/structure/index.js +2 -0
  166. package/dist/symmetry/WyckoffTable.svelte.d.ts +3 -3
  167. package/dist/symmetry/index.d.ts +1 -0
  168. package/dist/symmetry/index.js +1 -0
  169. package/dist/symmetry/spacegroups.d.ts +9 -0
  170. package/dist/symmetry/spacegroups.js +397 -0
  171. package/dist/theme/ThemeControl.svelte.d.ts +3 -3
  172. package/dist/theme/themes.js +2 -16
  173. package/dist/trajectory/Trajectory.svelte +52 -78
  174. package/dist/trajectory/Trajectory.svelte.d.ts +5 -5
  175. package/dist/trajectory/TrajectoryError.svelte.d.ts +3 -3
  176. package/dist/trajectory/TrajectoryExportPane.svelte +1 -1
  177. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +5 -5
  178. package/dist/trajectory/TrajectoryInfoPane.svelte +1 -1
  179. package/dist/trajectory/TrajectoryInfoPane.svelte.d.ts +3 -3
  180. package/dist/trajectory/extract.js +2 -1
  181. package/dist/trajectory/index.d.ts +1 -1
  182. package/dist/trajectory/index.js +1 -1
  183. package/dist/trajectory/parse.js +21 -14
  184. package/dist/utils.d.ts +1 -0
  185. package/dist/utils.js +17 -0
  186. package/dist/xrd/XrdPlot.svelte +14 -11
  187. package/dist/xrd/XrdPlot.svelte.d.ts +6 -5
  188. package/package.json +20 -12
  189. package/readme.md +1 -1
  190. package/dist/material/MaterialCard.svelte +0 -123
  191. package/dist/material/MaterialCard.svelte.d.ts +0 -9
  192. package/dist/material/index.d.ts +0 -1
  193. package/dist/material/index.js +0 -1
  194. package/dist/plot/formatting.d.ts +0 -7
  195. package/dist/plot/formatting.js +0 -53
@@ -1,81 +1,31 @@
1
- import { DraggablePane } from '..';
2
1
  import type { D3ColorSchemeName, D3InterpolateName } from '../colors';
3
- import type { DataSeries, HoverConfig, InternalPoint, LabelPlacementConfig, LegendConfig, Markers, PlotPoint, Point, ScaleType, ScatterTooltipProps, Sides, UserContentProps, XyObj } from './';
2
+ import type { AxisConfig, ControlsConfig, DataSeries, DisplayConfig, HoverConfig, InternalPoint, LabelPlacementConfig, LegendConfig, PlotPoint, Point, ScaleType, ScatterTooltipProps, Sides, StyleOverrides, TweenedOptions, UserContentProps, XyObj } from './';
4
3
  import { ColorBar } from './';
5
4
  import type { ComponentProps, Snippet } from 'svelte';
6
5
  import type { HTMLAttributes } from 'svelte/elements';
7
- import { type TicksOption } from './scales';
8
- type LocalTweenedOptions<T> = {
9
- duration?: number;
10
- delay?: number;
11
- easing?: (t: number) => number;
12
- interpolate?: (a: T, b: T) => (t: number) => T;
13
- };
14
- interface Props extends HTMLAttributes<HTMLDivElement> {
6
+ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
15
7
  series?: DataSeries[];
16
- x_lim?: [number | null, number | null];
17
- y_lim?: [number | null, number | null];
18
- x_range?: [number | null, number | null];
19
- y_range?: [number | null, number | null];
20
- current_x_value?: number | null;
21
- y2_lim?: [number | null, number | null];
22
- y2_range?: [number | null, number | null];
23
- y2_label?: string;
24
- y2_label_shift?: {
25
- x?: number;
26
- y?: number;
27
- };
28
- y2_tick_label_shift?: {
29
- x?: number;
30
- y?: number;
31
- };
32
- y2_unit?: string;
33
- y2_format?: string;
34
- y2_ticks?: TicksOption;
35
- y2_scale_type?: ScaleType;
36
- y2_grid?: boolean | Record<string, unknown>;
8
+ x_axis?: AxisConfig;
9
+ y_axis?: AxisConfig;
10
+ y2_axis?: AxisConfig;
11
+ display?: DisplayConfig;
12
+ styles?: StyleOverrides;
13
+ controls?: ControlsConfig;
37
14
  padding?: Sides;
38
- x_label?: string;
39
- x_label_shift?: {
40
- x?: number;
41
- y?: number;
42
- };
43
- x_tick_label_shift?: {
44
- x?: number;
45
- y?: number;
46
- };
47
- y_label?: string;
48
- y_label_shift?: {
49
- x?: number;
50
- y?: number;
51
- };
52
- y_tick_label_shift?: {
53
- x?: number;
54
- y?: number;
55
- };
56
- y_unit?: string;
15
+ range_padding?: number;
16
+ current_x_value?: number | null;
57
17
  tooltip_point?: InternalPoint | null;
58
18
  hovered?: boolean;
59
- markers?: Markers;
60
- x_format?: string;
61
- y_format?: string;
62
19
  tooltip?: Snippet<[PlotPoint & ScatterTooltipProps]>;
63
20
  user_content?: Snippet<[UserContentProps]>;
64
21
  change?: (data: (Point & {
65
22
  series: DataSeries;
66
23
  }) | null) => void;
67
- x_ticks?: TicksOption;
68
- y_ticks?: TicksOption;
69
- x_scale_type?: ScaleType;
70
- y_scale_type?: ScaleType;
71
- show_zero_lines?: boolean;
72
- x_grid?: boolean | Record<string, unknown>;
73
- y_grid?: boolean | Record<string, unknown>;
74
24
  color_scale?: {
75
25
  type?: ScaleType;
76
26
  scheme?: D3ColorSchemeName | D3InterpolateName;
77
27
  value_range?: [number, number];
78
- };
28
+ } | D3InterpolateName;
79
29
  size_scale?: {
80
30
  type?: ScaleType;
81
31
  radius_range?: [number, number];
@@ -83,49 +33,27 @@ interface Props extends HTMLAttributes<HTMLDivElement> {
83
33
  };
84
34
  color_bar?: (ComponentProps<typeof ColorBar> & {
85
35
  margin?: number | Sides;
86
- tween?: LocalTweenedOptions<XyObj>;
36
+ tween?: TweenedOptions<XyObj>;
87
37
  }) | null;
88
38
  label_placement_config?: Partial<LabelPlacementConfig>;
89
39
  hover_config?: Partial<HoverConfig>;
90
40
  legend?: LegendConfig | null;
91
- point_tween?: LocalTweenedOptions<XyObj>;
92
- line_tween?: LocalTweenedOptions<string>;
93
- range_padding?: number;
41
+ point_tween?: TweenedOptions<XyObj>;
42
+ line_tween?: TweenedOptions<string>;
94
43
  point_events?: Record<string, (payload: {
95
44
  point: InternalPoint;
96
45
  event: Event;
97
46
  }) => void>;
98
- on_point_click?: (payload: {
47
+ on_point_click?: (data: {
99
48
  point: InternalPoint;
100
49
  event: MouseEvent;
101
50
  }) => void;
102
- on_point_hover?: (payload: {
51
+ on_point_hover?: (data: {
103
52
  point: InternalPoint | null;
104
53
  event?: MouseEvent;
105
54
  }) => void;
106
- show_controls?: boolean;
107
- controls_open?: boolean;
108
- plot_controls?: Snippet<[]>;
109
- point_size?: number;
110
- point_color?: string;
111
- point_opacity?: number;
112
- point_stroke_width?: number;
113
- point_stroke_color?: string;
114
- point_stroke_opacity?: number;
115
- line_width?: number;
116
- line_color?: string;
117
- line_opacity?: number;
118
- line_dash?: string;
119
- show_points?: boolean;
120
- show_lines?: boolean;
121
55
  selected_series_idx?: number;
122
- color_axis_labels?: boolean | {
123
- y1?: string | null;
124
- y2?: string | null;
125
- };
126
- controls_toggle_props?: ComponentProps<typeof DraggablePane>[`toggle_props`];
127
- children?: Snippet<[]>;
128
- }
129
- declare const ScatterPlot: import("svelte").Component<Props, {}, "x_format" | "y_format" | "y2_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" | "controls_open" | "hovered" | "tooltip_point" | "selected_series_idx">;
56
+ };
57
+ declare const ScatterPlot: import("svelte").Component<$$ComponentProps, {}, "display" | "controls" | "y_axis" | "y2_axis" | "x_axis" | "hovered" | "styles" | "tooltip_point" | "selected_series_idx">;
130
58
  type ScatterPlot = ReturnType<typeof ScatterPlot>;
131
59
  export default ScatterPlot;
@@ -1,291 +1,71 @@
1
- <script lang="ts">import { DraggablePane, SettingsSection } from '..';
2
- import { DEFAULTS, SETTINGS_CONFIG } from '../settings';
3
- import { format } from 'd3-format';
4
- import { timeFormat } from 'd3-time-format';
1
+ <script lang="ts">import { SettingsSection } from '..';
2
+ import { PlotControls } from './';
3
+ import { DEFAULTS } from '../settings';
5
4
  import { tooltip } from 'svelte-multiselect/attachments';
6
- let { show_controls = $bindable(false), controls_open = $bindable(false), plot_controls, series = [], markers = $bindable(DEFAULTS.scatter.markers), show_zero_lines = $bindable(DEFAULTS.plot.show_zero_lines), x_grid = $bindable(DEFAULTS.plot.x_grid), y_grid = $bindable(DEFAULTS.plot.y_grid), y2_grid = $bindable(DEFAULTS.plot.y2_grid), has_y2_points = false,
7
- // Range controls
8
- x_range = $bindable(undefined), y_range = $bindable(undefined), y2_range = $bindable(undefined),
9
- // Auto-detected ranges for fallback when only one value is set
10
- auto_x_range = [0, 1], auto_y_range = [0, 1], auto_y2_range = [0, 1],
11
- // Format controls
12
- x_format = $bindable(DEFAULTS.plot.x_format), y_format = $bindable(DEFAULTS.plot.y_format), y2_format = $bindable(DEFAULTS.plot.y2_format),
13
- // Style controls
14
- point_size = $bindable(DEFAULTS.scatter.point_size), point_color = $bindable(DEFAULTS.scatter.point_color), point_opacity = $bindable(DEFAULTS.scatter.point_opacity), point_stroke_width = $bindable(DEFAULTS.scatter.point_stroke_width), point_stroke_color = $bindable(DEFAULTS.scatter.point_stroke_color), point_stroke_opacity = $bindable(DEFAULTS.scatter.point_stroke_opacity), line_width = $bindable(DEFAULTS.scatter.line_width), line_color = $bindable(DEFAULTS.scatter.line_color), line_opacity = $bindable(DEFAULTS.scatter.line_opacity), line_dash = $bindable(DEFAULTS.scatter.line_dash), show_points = $bindable(DEFAULTS.scatter.show_points), show_lines = $bindable(DEFAULTS.scatter.show_lines), selected_series_idx = $bindable(0), toggle_props = {}, pane_props = {}, } = $props();
5
+ let { series = [], x_axis = $bindable({}), y_axis = $bindable({}), y2_axis = $bindable({}), display = $bindable({}), styles = $bindable({}), controls = $bindable({}), selected_series_idx = $bindable(0), ...rest } = $props();
15
6
  // Derived state
16
7
  let has_multiple_series = $derived(series.filter(Boolean).length > 1);
17
- // Generic helpers to eliminate ALL repetition
18
- const validate_format = (str) => {
19
- if (!str)
20
- return true;
21
- try {
22
- return str.startsWith(`%`)
23
- ? timeFormat(str)(new Date()) || true
24
- : format(str)(123.456) || true;
25
- }
26
- catch {
27
- return false;
28
- }
29
- };
30
- const format_input_handler = (type) => (event) => {
31
- const input = event.target;
32
- // Update local state
33
- if (type === `x`)
34
- x_format_input = input.value;
35
- else if (type === `y`)
36
- y_format_input = input.value;
37
- else
38
- y2_format_input = input.value;
39
- // Validate and update prop
40
- const is_valid = validate_format(input.value);
41
- input.classList.toggle(`invalid`, !is_valid);
42
- if (is_valid) {
43
- if (type === `x`)
44
- x_format = input.value;
45
- else if (type === `y`)
46
- y_format = input.value;
47
- else
48
- y2_format = input.value;
49
- }
50
- };
51
- const range_complete = (axis) => {
52
- const [min_el, max_el] = [`min`, `max`].map((b) => document.getElementById(`${axis}-range-${b}`));
53
- if (!min_el || !max_el)
54
- return;
55
- const [min, max] = [min_el, max_el].map((el) => (el.classList.remove(`invalid`), el.value === `` ? null : +el.value));
56
- const auto = { x: auto_x_range, y: auto_y_range, y2: auto_y2_range }[axis];
57
- if (min !== null && max !== null && min >= max) {
58
- ;
59
- [min_el, max_el].forEach((el) => el.classList.add(`invalid`));
60
- return;
61
- }
62
- const ranges = {
63
- x: (r) => x_range = r,
64
- y: (r) => y_range = r,
65
- y2: (r) => y2_range = r,
66
- };
67
- ranges[axis](min === null && max === null ? undefined : [min ?? auto[0], max ?? auto[1]]);
68
- };
69
- const input_props = (axis, bound, range) => ({
70
- id: `${axis}-range-${bound}`,
71
- type: `number`,
72
- value: range?.[bound === `min` ? 0 : 1] ?? ``,
73
- placeholder: `auto`,
74
- class: `range-input`,
75
- onblur: () => range_complete(axis),
76
- onkeydown: (e) => e.key === `Enter` && e.target.blur(),
77
- });
78
- // Ultra-minimal effects
79
- $effect(() => [[x_range, `x`], [y_range, `y`], [y2_range, `y2`]].forEach(([range, axis]) => {
80
- if (!range) {
81
- for (const bound of [`min`, `max`]) {
82
- const el = document.getElementById(`${axis}-range-${bound}`);
83
- if (el)
84
- el.value = ``;
85
- }
86
- }
87
- }));
88
- $effect(() => {
89
- show_points = markers?.includes(`points`) ?? false;
90
- show_lines = markers?.includes(`line`) ?? false;
91
- if (has_multiple_series && series[selected_series_idx]) {
92
- const s = series[selected_series_idx];
93
- const ps = Array.isArray(s.point_style) ? s.point_style[0] : s.point_style;
94
- if (ps) {
95
- point_size = ps.radius ?? 4;
96
- point_color = ps.fill ?? `#4682b4`;
97
- point_stroke_width = ps.stroke_width ?? 1;
98
- point_stroke_color = ps.stroke ?? `#000`;
99
- point_opacity = ps.fill_opacity ?? 1;
100
- }
101
- if (s.line_style) {
102
- line_width = s.line_style.stroke_width ?? 2;
103
- line_color = s.line_style.stroke ?? `#4682b4`;
104
- line_dash = s.line_style.line_dash ?? DEFAULTS.scatter.line_dash;
105
- }
106
- }
107
- });
8
+ // Initialize show_points/show_lines from defaults
108
9
  $effect(() => {
109
- markers = show_points && show_lines
110
- ? `line+points`
111
- : show_points
112
- ? `points`
113
- : `line`;
10
+ styles.show_points ??= DEFAULTS.scatter.show_points;
11
+ styles.show_lines ??= DEFAULTS.scatter.show_lines;
114
12
  });
115
- // Local format state
116
- let x_format_input = $state(x_format);
117
- let y_format_input = $state(y_format);
118
- let y2_format_input = $state(y2_format);
119
13
  </script>
120
14
 
121
- {#if show_controls}
122
- <DraggablePane
123
- bind:show={controls_open}
124
- closed_icon="Settings"
125
- open_icon="Cross"
126
- toggle_props={{
127
- ...toggle_props,
128
- class: `scatter-controls-toggle ${toggle_props?.class ?? ``}`,
129
- title: `${controls_open ? `Close` : `Open`} scatter plot controls`,
130
- style:
131
- `position: absolute; top: var(--ctrl-btn-top, 1ex); right: var(--ctrl-btn-right, 1ex); background-color: transparent; ${
132
- toggle_props?.style ?? ``
133
- }`,
134
- }}
135
- pane_props={{
136
- ...pane_props,
137
- class: `scatter-controls-pane ${pane_props?.class ?? ``}`,
15
+ <PlotControls bind:x_axis bind:y_axis bind:y2_axis bind:display {...rest}>
16
+ <!-- Add show_points and show_lines checkboxes to Display section by extending it -->
17
+ <!-- This is done via the Display section in PlotControls, but we need custom controls -->
18
+ <!-- For now, we'll add a separate section for markers -->
19
+ <SettingsSection
20
+ title="Markers"
21
+ current_values={{ show_points: styles.show_points, show_lines: styles.show_lines }}
22
+ on_reset={() => {
23
+ styles.show_points = DEFAULTS.scatter.show_points
24
+ styles.show_lines = DEFAULTS.scatter.show_lines
138
25
  }}
26
+ style="display: flex; flex-wrap: wrap; gap: 1ex"
139
27
  >
140
- {#if plot_controls}
141
- {@render plot_controls()}
142
- {:else}
143
- <SettingsSection
144
- title="Display"
145
- current_values={{ show_zero_lines, show_points, show_lines, x_grid, y_grid, y2_grid }}
146
- on_reset={() => {
147
- show_zero_lines = DEFAULTS.plot.show_zero_lines
148
- show_points = DEFAULTS.scatter.show_points
149
- show_lines = DEFAULTS.scatter.show_lines
150
- x_grid = DEFAULTS.plot.x_grid
151
- y_grid = DEFAULTS.plot.y_grid
152
- y2_grid = DEFAULTS.plot.y2_grid
153
- }}
154
- style="display: flex; flex-wrap: wrap; gap: 1ex"
155
- >
156
- <label>
157
- <input type="checkbox" bind:checked={show_zero_lines} /> Show zero lines
158
- </label>
159
- <label
160
- {@attach tooltip({ content: `Toggle visibility of data points in the scatter plot` })}
161
- >
162
- <input type="checkbox" bind:checked={show_points} /> Show points
163
- </label>
164
- <label
165
- {@attach tooltip({
166
- content: `Toggle visibility of connecting lines between data points`,
167
- })}
168
- >
169
- <input type="checkbox" bind:checked={show_lines} /> Show lines
170
- </label>
171
- <label
172
- {@attach tooltip({ content: SETTINGS_CONFIG.plot.grid_lines.description })}
173
- >
174
- <input type="checkbox" bind:checked={x_grid as boolean} /> X-axis grid
175
- </label>
176
- <label
177
- {@attach tooltip({ content: SETTINGS_CONFIG.plot.grid_lines.description })}
178
- >
179
- <input type="checkbox" bind:checked={y_grid as boolean} /> Y-axis grid
180
- </label>
181
- {#if has_y2_points}
182
- <label>
183
- <input type="checkbox" bind:checked={y2_grid as boolean} /> Y2-axis grid
184
- </label>
185
- {/if}
186
- </SettingsSection>
28
+ <label
29
+ {@attach tooltip({ content: `Toggle visibility of data points in the scatter plot` })}
30
+ >
31
+ <input type="checkbox" bind:checked={styles.show_points} /> Show points
32
+ </label>
33
+ <label
34
+ {@attach tooltip({
35
+ content: `Toggle visibility of connecting lines between data points`,
36
+ })}
37
+ >
38
+ <input type="checkbox" bind:checked={styles.show_lines} /> Show lines
39
+ </label>
40
+ </SettingsSection>
187
41
 
188
- <SettingsSection
189
- title="Axis Range"
190
- current_values={{ x_range, y_range, y2_range }}
191
- on_reset={() => {
192
- x_range = undefined
193
- y_range = undefined
194
- y2_range = undefined
195
- }}
196
- class="pane-grid"
197
- style="grid-template-columns: repeat(4, max-content)"
198
- >
199
- <label for="x-range-min">X-axis:</label>
200
- <input {...input_props(`x`, `min`, x_range)} />
201
- &nbsp;to
202
- <input {...input_props(`x`, `max`, x_range)} />
203
- <label for="y-range-min">Y-axis:</label>
204
- <input {...input_props(`y`, `min`, y_range)} />
205
- &nbsp;to
206
- <input {...input_props(`y`, `max`, y_range)} />
207
- {#if has_y2_points}
208
- <label for="y2-range-min">Y2-axis:</label>
209
- <input {...input_props(`y2`, `min`, y2_range)} />
210
- &nbsp;to
211
- <input {...input_props(`y2`, `max`, y2_range)} />
212
- {/if}
213
- </SettingsSection>
42
+ {#snippet post_children()}
43
+ <!-- Series Selection (for multi-series style controls) -->
44
+ {#if has_multiple_series}
45
+ <div class="pane-row">
46
+ <label for="series-select">Series</label>
47
+ <select bind:value={selected_series_idx} id="series-select">
48
+ {#each series as srs, idx (idx)}
49
+ {#if srs}
50
+ <option value={idx}>
51
+ {srs.label ?? `Series ${idx + 1}`}
52
+ </option>
53
+ {/if}
54
+ {/each}
55
+ </select>
56
+ </div>
57
+ {/if}
214
58
 
59
+ <!-- Point Style Controls -->
60
+ {#if styles.show_points}
215
61
  <SettingsSection
216
- title="Tick Format"
217
- current_values={{ x_format, y_format, y2_format }}
62
+ title="Point Style"
63
+ current_values={styles.point ?? {}}
218
64
  on_reset={() => {
219
- x_format = DEFAULTS.plot.x_format
220
- y_format = DEFAULTS.plot.y_format
221
- y2_format = DEFAULTS.plot.y2_format
65
+ styles.point = { ...DEFAULTS.scatter.point }
222
66
  }}
223
- class="pane-grid"
224
- style="grid-template-columns: auto 1fr"
225
67
  >
226
- <label for="x-format">X-axis:</label>
227
- <input
228
- id="x-format"
229
- type="text"
230
- bind:value={x_format_input}
231
- placeholder=".2f / .0% / %Y-%m-%d"
232
- oninput={format_input_handler(`x`)}
233
- />
234
- <label for="y-format">Y-axis:</label>
235
- <input
236
- id="y-format"
237
- type="text"
238
- bind:value={y_format_input}
239
- placeholder=".2f / .1e / .0%"
240
- oninput={format_input_handler(`y`)}
241
- />
242
- {#if has_y2_points}
243
- <label for="y2-format">Y2-axis:</label>
244
- <input
245
- id="y2-format"
246
- type="text"
247
- bind:value={y2_format_input}
248
- placeholder=".2f / .1e / .0%"
249
- oninput={format_input_handler(`y2`)}
250
- />
251
- {/if}
252
- </SettingsSection>
253
-
254
- <!-- Series Selection (for multi-series style controls) -->
255
- {#if has_multiple_series}
256
- <div class="pane-row">
257
- <label for="series-select">Series</label>
258
- <select bind:value={selected_series_idx} id="series-select">
259
- {#each series.filter(Boolean) as series_data, idx (series_data.label ?? idx)}
260
- <option value={idx}>
261
- {series_data.label ?? `Series ${idx + 1}`}
262
- </option>
263
- {/each}
264
- </select>
265
- </div>
266
- {/if}
267
-
268
- <!-- Point Style Controls -->
269
- {#if show_points}
270
- <SettingsSection
271
- title="Point Style"
272
- current_values={{
273
- point_size,
274
- point_color,
275
- point_opacity,
276
- point_stroke_width,
277
- point_stroke_color,
278
- point_stroke_opacity,
279
- }}
280
- on_reset={() => {
281
- point_size = DEFAULTS.scatter.point_size
282
- point_color = DEFAULTS.scatter.point_color
283
- point_opacity = DEFAULTS.scatter.point_opacity
284
- point_stroke_width = DEFAULTS.scatter.point_stroke_width
285
- point_stroke_color = DEFAULTS.scatter.point_stroke_color
286
- point_stroke_opacity = DEFAULTS.scatter.point_stroke_opacity
287
- }}
288
- >
68
+ {#if styles.point}
289
69
  <div class="pane-row">
290
70
  <label for="point-size-range">Size:</label>
291
71
  <input
@@ -294,22 +74,34 @@ let y2_format_input = $state(y2_format);
294
74
  min="1"
295
75
  max="20"
296
76
  step="0.5"
297
- bind:value={point_size}
77
+ bind:value={styles.point.size}
78
+ />
79
+ <input
80
+ type="number"
81
+ min="1"
82
+ max="20"
83
+ step="0.5"
84
+ bind:value={styles.point.size}
298
85
  />
299
- <input type="number" min="1" max="20" step="0.5" bind:value={point_size} />
300
86
  </div>
301
87
  <div class="pane-row">
302
88
  <label for="point-color">Color:</label>
303
- <input id="point-color" type="color" bind:value={point_color} />
89
+ <input id="point-color" type="color" bind:value={styles.point.color} />
304
90
  <input
305
91
  type="range"
306
92
  min="0"
307
93
  max="1"
308
94
  step="0.05"
309
- bind:value={point_opacity}
95
+ bind:value={styles.point.opacity}
310
96
  title="Color opacity"
311
97
  />
312
- <input type="number" min="0" max="1" step="0.05" bind:value={point_opacity} />
98
+ <input
99
+ type="number"
100
+ min="0"
101
+ max="1"
102
+ step="0.05"
103
+ bind:value={styles.point.opacity}
104
+ />
313
105
  </div>
314
106
  <div class="pane-row">
315
107
  <label for="point-stroke-width-range">Stroke Width:</label>
@@ -319,25 +111,29 @@ let y2_format_input = $state(y2_format);
319
111
  min="0"
320
112
  max="5"
321
113
  step="0.1"
322
- bind:value={point_stroke_width}
114
+ bind:value={styles.point.stroke_width}
323
115
  />
324
116
  <input
325
117
  type="number"
326
118
  min="0"
327
119
  max="5"
328
120
  step="0.1"
329
- bind:value={point_stroke_width}
121
+ bind:value={styles.point.stroke_width}
330
122
  />
331
123
  </div>
332
124
  <div class="pane-row">
333
125
  <label for="point-stroke-color">Stroke Color:</label>
334
- <input id="point-stroke-color" type="color" bind:value={point_stroke_color} />
126
+ <input
127
+ id="point-stroke-color"
128
+ type="color"
129
+ bind:value={styles.point.stroke_color}
130
+ />
335
131
  <input
336
132
  type="range"
337
133
  min="0"
338
134
  max="1"
339
135
  step="0.05"
340
- bind:value={point_stroke_opacity}
136
+ bind:value={styles.point.stroke_opacity}
341
137
  title="Stroke opacity"
342
138
  />
343
139
  <input
@@ -345,24 +141,23 @@ let y2_format_input = $state(y2_format);
345
141
  min="0"
346
142
  max="1"
347
143
  step="0.05"
348
- bind:value={point_stroke_opacity}
144
+ bind:value={styles.point.stroke_opacity}
349
145
  />
350
146
  </div>
351
- </SettingsSection>
352
- {/if}
147
+ {/if}
148
+ </SettingsSection>
149
+ {/if}
353
150
 
354
- <!-- Line Style Controls -->
355
- {#if show_lines}
356
- <SettingsSection
357
- title="Line Style"
358
- current_values={{ line_width, line_color, line_opacity, line_dash }}
359
- on_reset={() => {
360
- line_width = DEFAULTS.scatter.line_width
361
- line_color = DEFAULTS.scatter.line_color
362
- line_opacity = DEFAULTS.scatter.line_opacity
363
- line_dash = DEFAULTS.scatter.line_dash
364
- }}
365
- >
151
+ <!-- Line Style Controls -->
152
+ {#if styles.show_lines}
153
+ <SettingsSection
154
+ title="Line Style"
155
+ current_values={styles.line ?? {}}
156
+ on_reset={() => {
157
+ styles.line = { ...DEFAULTS.scatter.line }
158
+ }}
159
+ >
160
+ {#if styles.line}
366
161
  <div class="pane-row">
367
162
  <label for="line-width-range">Line Width:</label>
368
163
  <input
@@ -371,19 +166,25 @@ let y2_format_input = $state(y2_format);
371
166
  min="0.5"
372
167
  max="10"
373
168
  step="0.5"
374
- bind:value={line_width}
169
+ bind:value={styles.line.width}
170
+ />
171
+ <input
172
+ type="number"
173
+ min="0.5"
174
+ max="10"
175
+ step="0.5"
176
+ bind:value={styles.line.width}
375
177
  />
376
- <input type="number" min="0.5" max="10" step="0.5" bind:value={line_width} />
377
178
  </div>
378
179
  <div class="pane-row">
379
180
  <label for="line-color">Line Color:</label>
380
- <input id="line-color" type="color" bind:value={line_color} />
181
+ <input id="line-color" type="color" bind:value={styles.line.color} />
381
182
  <input
382
183
  type="range"
383
184
  min="0"
384
185
  max="1"
385
186
  step="0.05"
386
- bind:value={line_opacity}
187
+ bind:value={styles.line.opacity}
387
188
  title="Line opacity"
388
189
  />
389
190
  <input
@@ -391,29 +192,20 @@ let y2_format_input = $state(y2_format);
391
192
  min="0"
392
193
  max="1"
393
194
  step="0.05"
394
- bind:value={line_opacity}
195
+ bind:value={styles.line.opacity}
395
196
  />
396
197
  </div>
397
198
  <div class="pane-row">
398
199
  <label for="line-style-select">Line Style:</label>
399
- <select
400
- id="line-style-select"
401
- value={line_dash ?? `solid`}
402
- onchange={(event) => {
403
- const target = event.currentTarget as HTMLSelectElement
404
- line_dash = target.value === `solid`
405
- ? DEFAULTS.scatter.line_dash
406
- : target.value
407
- }}
408
- >
200
+ <select id="line-style-select" bind:value={styles.line.dash}>
409
201
  <option value="solid">Solid</option>
410
202
  <option value="4,4">Dashed</option>
411
203
  <option value="2,2">Dotted</option>
412
204
  <option value="8,4,2,4">Dash-dot</option>
413
205
  </select>
414
206
  </div>
415
- </SettingsSection>
416
- {/if}
207
+ {/if}
208
+ </SettingsSection>
417
209
  {/if}
418
- </DraggablePane>
419
- {/if}
210
+ {/snippet}
211
+ </PlotControls>