Skip to content

Commit 42b14f9

Browse files
committed
A ~~working~~ nice-looking functions list as a svelte component
1 parent edbf392 commit 42b14f9

20 files changed

Lines changed: 6455 additions & 4202 deletions

declaration.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
declare module '*.svelte'

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@
1919
"@types/node": "*",
2020
"@typescript-eslint/eslint-plugin": "^5.41.0",
2121
"@typescript-eslint/parser": "^5.41.0",
22+
"css-loader": "^6.7.3",
2223
"eslint": "^8.26.0",
2324
"eslint-config-prettier": "^8.5.0",
2425
"jest": "^29.2.2",
2526
"prettier": "^2.7.1",
2627
"sass": "^1.54.4",
2728
"sass-loader": "^13.0.2",
29+
"style-loader": "^3.3.1",
2830
"svelte": "^3.53.1",
2931
"svelte-loader": "^3.1.4",
32+
"svelte-material-icons": "^2.0.4",
3033
"svelte-preprocess": "^4.10.7",
3134
"ts-jest": "^29.0.3",
3235
"ts-loader": "^9.3.1",
@@ -37,9 +40,7 @@
3740
"yaml": "^2.1.3"
3841
},
3942
"dependencies": {
40-
"css-loader": "^6.7.3",
4143
"function-plot": "^1.23.1",
42-
"obsidian": "0.16.3",
43-
"style-loader": "^3.3.1"
44+
"obsidian": "0.16.3"
4445
}
4546
}

src/app/CreatePlotModal.ts

Lines changed: 41 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,57 @@
1-
import type { FunctionPlotDatum } from "function-plot/dist/types";
21
import { Editor, Modal, Setting } from "obsidian";
32
import {
4-
DEFAULT_FUNCTION_OPTIONS,
53
DEFAULT_PLOT_OPTIONS,
6-
FUNCTION_CASES,
74
} from "../common/defaults";
8-
import type { PlotOptions, rendererType, Line } from "../common/types";
5+
import type { PlotOptions } from "../common/types";
96
import type ObsidianFunctionPlot from "../main";
10-
import { createPlot, renderPlotAsInteractive } from "../common/utils";
11-
import type { Chart } from "function-plot";
7+
import FunctionsList from "../components/CreatePlot/FunctionsList.svelte";
8+
import functionPlot from "function-plot";
129

1310
export default class CreatePlotModal extends Modal {
1411
options: PlotOptions;
1512
plugin: ObsidianFunctionPlot;
1613
editor: Editor;
17-
plot: Chart;
18-
renderer: rendererType;
14+
rendertarget: HTMLElement;
1915

2016
constructor(plugin: ObsidianFunctionPlot, editor: Editor) {
2117
super(plugin.app);
2218
this.plugin = plugin;
2319
this.editor = editor;
24-
this.renderer = this.plugin.settings.defaultRenderer;
2520
}
2621

27-
/**
28-
* Reload the preview using internal functions. Zooming doesn't work here.
29-
* @returns A Promise
30-
*/
3122
reloadPreview() {
32-
if (!this.plot) return;
33-
// update values
34-
this.plot.options.title = this.options.title;
35-
this.plot.options.xAxis.label = this.options.xLabel;
36-
this.plot.options.yAxis.label = this.options.yLabel;
37-
this.plot.options.xAxis.domain = this.options.bounds.slice(0, 2);
38-
this.plot.options.yAxis.domain = this.options.bounds.slice(2, 4);
39-
this.plot.options.grid = this.options.grid;
40-
this.plot.options.data = this.options.functions.map(
41-
(line): FunctionPlotDatum => {
42-
// use polyline by default
43-
const lineProperties: Line = { graphType: "polyline" };
44-
45-
line.split("@").forEach((property) => {
46-
const tup = property.split("=");
47-
const value = tup[1].trim();
48-
lineProperties[tup[0].trim()] = value.startsWith("[")
49-
? JSON.parse(value)
50-
: value;
51-
});
52-
53-
return lineProperties;
54-
}
55-
);
56-
// redirect errors within function-plot to debug
57-
try {
58-
this.plot.build();
59-
} catch (e) {
60-
console.debug(e);
61-
}
62-
}
63-
64-
computeStates(cases, options) {
65-
const states = [];
66-
for (const [test] of cases) {
67-
states.push(test(options));
68-
}
69-
return states;
23+
if (!this.rendertarget) return;
24+
console.log(this.options)
25+
functionPlot(
26+
Object.assign({}, this.options, {target: this.rendertarget})
27+
)
7028
}
7129

7230
async onOpen() {
31+
// fix modal size
32+
document
33+
.getElementsByClassName("modal")[0]
34+
.setAttribute(
35+
"style",
36+
"width: var(--max-modal-width); height: var(--max-modal-height);"
37+
);
38+
7339
this.options = JSON.parse(JSON.stringify(DEFAULT_PLOT_OPTIONS)); // deepcopy to avoid side effects
7440

7541
const { contentEl } = this;
7642
contentEl.empty();
7743

7844
// Header
79-
contentEl.createEl("h1", { text: "Plot a function" });
45+
contentEl.createEl("h1", { text: "Create a plot" });
8046

8147
const flex = contentEl.createDiv({
8248
attr: { style: "display: flex; align-items: center" },
8349
});
8450

8551
const settings = flex.createDiv();
8652
const preview = flex.createDiv({ attr: { style: "padding: 1em" } });
87-
this.plot = await createPlot(
88-
Object.assign({}, this.options, { disableZoom: true }),
89-
preview.createDiv(),
90-
this.plugin
91-
);
53+
this.rendertarget = preview.createDiv()
54+
9255
preview.createEl("p", {
9356
text: "Preview - Zoom is disabled while in preview",
9457
attr: {
@@ -105,18 +68,18 @@ export default class CreatePlotModal extends Modal {
10568

10669
new Setting(settings).setName("Label X").addText((text) => {
10770
text.onChange(async (value) => {
108-
this.options.xLabel = value;
71+
this.options.xAxis.label = value;
10972
this.reloadPreview();
11073
});
11174
});
11275
new Setting(settings).setName("Label Y").addText((text) => {
11376
text.onChange(async (value) => {
114-
this.options.yLabel = value;
77+
this.options.yAxis.label = value;
11578
this.reloadPreview();
11679
});
11780
});
11881

119-
const placeholders = ["X min", "X max", "Y min", "Y max"];
82+
/*const placeholders = ["X min", "X max", "Y min", "Y max"];
12083
12184
const bounds = new Setting(settings).setName("Bounds");
12285
@@ -129,16 +92,13 @@ export default class CreatePlotModal extends Modal {
12992
this.options.bounds[i] = +value;
13093
this.reloadPreview();
13194
} else {
132-
console.log(
133-
`resetting ${i} to default ${DEFAULT_PLOT_OPTIONS.bounds[i]}`
134-
);
13595
this.options.bounds[i] = DEFAULT_PLOT_OPTIONS.bounds[i];
13696
this.reloadPreview();
13797
}
13898
})
139-
.inputEl.classList.add("function-plot-numberinput");
99+
.inputEl.setAttribute("style", "width: 4em");
140100
});
141-
});
101+
});*/
142102

143103
new Setting(settings).setName("Disable Zoom").addToggle((com) => {
144104
com.setValue(this.options.disableZoom);
@@ -156,48 +116,17 @@ export default class CreatePlotModal extends Modal {
156116
});
157117
});
158118

159-
const functionsSetting = new Setting(settings)
160-
.setName("Functions")
161-
.setDesc("Functions to plot.");
162-
functionsSetting.settingEl.setAttribute("style", "display: block");
163-
const functionsControlEl = functionsSetting.controlEl;
164-
functionsControlEl.classList.value = "function-plot-functions-container";
165-
const functionsList = functionsControlEl.createDiv({
166-
attr: { class: "function-plot-functions-list" },
167-
});
168-
169-
functionsControlEl.createDiv(
170-
{ attr: { class: "function-plot-functions-add" } },
171-
(el) => {
172-
new Setting(el).addButton((btn) => {
173-
btn
174-
.setButtonText("Add function")
175-
.setIcon("plus")
176-
.onClick(async () => {
177-
const id = Math.random().toString(36).substring(2, 9);
178-
const options = Object.assign(
179-
JSON.parse(JSON.stringify(DEFAULT_FUNCTION_OPTIONS)),
180-
{ id }
181-
);
182-
const prevStates = this.computeStates(FUNCTION_CASES, options);
183-
184-
new Setting(functionsList).addDropdown((com) => {
185-
com
186-
.addOptions({
187-
linear: "linear",
188-
vector: "vector",
189-
polar: "polar",
190-
points: "points",
191-
})
192-
.setValue(options.fnType)
193-
.onChange((value) => {
194-
options.fnType = value;
195-
});
196-
});
197-
});
198-
});
119+
const dataSetting = new Setting(settings)
120+
.setName("Data")
121+
dataSetting.settingEl.setAttribute("style", "display: block");
122+
123+
new FunctionsList({
124+
target: dataSetting.controlEl,
125+
props: {
126+
options: this.options,
127+
reloadPreview: this.reloadPreview.bind(this),
199128
}
200-
);
129+
})
201130

202131
new Setting(contentEl)
203132
/*.addDropdown((com) => {
@@ -213,29 +142,29 @@ export default class CreatePlotModal extends Modal {
213142
.setButtonText("Plot")
214143
.setCta()
215144
.onClick(async () => {
216-
await this.handleFinalPlotCreate(this.options);
145+
// await this.handleFinalPlotCreate(this.options);
217146
});
218147
});
219148
}
220149

150+
/*
221151
async handleFinalPlotCreate(options: PlotOptions) {
222152
// render and insert chosen plot using renderer
223-
switch (this.renderer) {
153+
switch ("interactive") {
224154
case "interactive":
225155
renderPlotAsInteractive(this.plugin, this.editor, options);
226156
break;
227157
/*
228158
case "image":
229159
await renderPlotAsImage(this.plugin, this.editor, options);
230-
break; */
160+
break; *//*
231161
}
232162
233163
this.close();
234164
}
165+
*/
235166

236167
onClose() {
237-
const { contentEl } = this;
238-
contentEl.empty();
239-
this.plot = null;
168+
this.contentEl.empty();
240169
}
241170
}

src/app/SettingsTab.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ export default class SettingsTab extends PluginSettingTab {
197197
.onClick(() => {
198198
Object.assign(this.plugin.settings, DEFAULT_PLUGIN_SETTINGS);
199199
for (const [key, input] of this.settingsInputs) {
200-
if (key === "telemetry") continue; // don't reset telemetry
201200
input.setValue(this.plugin.settings[key]);
202201
}
203202
this.plugin.saveSettings();

src/common/defaults.ts

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,45 @@
1-
import type { rendererType, PlotOptions, PluginSettings } from "./types";
1+
import type { FunctionOptions, PlotOptions, PluginSettings } from "./types";
22

3-
export const DEFAULT_FUNCTION_OPTIONS = {
4-
fnType: 'linear',
5-
fn: '',
6-
vector: ['',''],
7-
r: '',
8-
points: '',
9-
color: null,
10-
offset: ['', ''],
3+
export const DEFAULT_FUNCTION_OPTIONS: FunctionOptions = {
4+
id: null,
5+
fnType: "linear",
6+
fn: "",
7+
vector: [undefined, undefined],
8+
r: "",
9+
color: '#000',
10+
offset: [undefined, undefined],
1111
closed: false,
12-
graphType: 'interval',
13-
range: ['', ''],
14-
nSamples: '',
15-
skipTip: false
16-
}
12+
graphType: "interval",
13+
range: [undefined, undefined],
14+
nSamples: undefined,
15+
skipTip: false,
16+
};
1717

18-
export const FUNCTION_CASES = [
19-
[options => options.fnType == 'vector', () => {/*set fn field to two values*/ }, () => {/*revert to one field*/}]
20-
]
2118
/**
2219
* The options displayed for renderers
23-
*/
20+
*
2421
// eslint-disable-next-line no-unused-vars
2522
export const rendererOptions: { [_ in rendererType]: string } = {
2623
interactive: "Interactive (zoomable)",
2724
//image: "Image (exportable)",
28-
};
25+
};*/
2926

3027
/**
3128
* The default options for a plot.
3229
*/
3330
export const DEFAULT_PLOT_OPTIONS: PlotOptions = {
3431
title: "",
35-
xLabel: "",
36-
yLabel: "",
37-
bounds: [-10, 10, -10, 10],
38-
disableZoom: false,
32+
xAxis: {
33+
label: "",
34+
domain: [-10, 10],
35+
},
36+
yAxis: {
37+
label: "",
38+
domain: [-10, 10],
39+
},
3940
grid: true,
40-
functions: [],
41+
disableZoom: false,
42+
data: []
4143
};
4244

4345
/**
@@ -56,6 +58,4 @@ export const DEFAULT_PLUGIN_SETTINGS: PluginSettings = {
5658
// annotationColor: '#000',
5759
lineColor: "gray",
5860
gridColor: "var(--interactive-hover)",
59-
60-
defaultRenderer: "interactive",
6161
};

0 commit comments

Comments
 (0)