-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
114 lines (99 loc) · 2.57 KB
/
app.js
File metadata and controls
114 lines (99 loc) · 2.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import init, { Keisan } from "./libkeisan.js";
const { h, render, Component } = preact;
const html = htm.bind(h);
class App extends Component {
constructor() {
super();
this.state = {
input: "",
results: [],
loading: true,
keisan: null,
};
this.inputRef = preact.createRef();
this.throttleTimeout = null;
}
initWasm = async () => {
await init({
module_or_path: new URL("libkeisan_bg.wasm", import.meta.url),
});
const keisan = new Keisan();
keisan.setLogLevel("debug");
const plugins = [
"./plugins/datetime.js",
"./plugins/unit.js",
"./plugins/percent.js",
"./plugins/currency.js",
];
await Promise.all(
plugins.map(async (p) => {
const res = await fetch(p);
const content = await res.text();
keisan.addPlugin(p, content);
}),
);
this.setState({ keisan });
};
componentDidMount = async () => {
try {
await this.initWasm();
this.setState({ loading: false });
} catch (error) {
console.error("Error initializing:", error);
}
};
componentWillUnmount = () => {
if (this.throttleTimeout) clearTimeout(this.throttleTimeout);
if (this.state.keisan) {
this.state.keisan.free();
}
};
handleInput = (event) => {
const input = event.target.value;
this.setState({ input });
if (this.throttleTimeout) {
clearTimeout(this.throttleTimeout);
}
this.throttleTimeout = setTimeout(() => {
const { keisan } = this.state;
const results = keisan.multiEval(input).map((res) => {
const { output, success } = res;
const ret = { type: success ? "result" : "error", value: output };
res.free();
return ret;
});
this.setState({ results });
}, 100);
};
render() {
if (this.state.loading) {
return html`
<div class="loading">
<span>Loading...</span>
<div class="spinner"></div>
</div>
`;
}
return html`
<div id="input-container">
<textarea
id="input-area"
onInput=${this.handleInput}
value=${this.state.input}
ref=${this.inputRef}
spellcheck="false"
autocorrect="off"
autocapitalize="off"
></textarea>
<div id="results-area">
${this.state.results.map(
(result) => html`
<div class=${result.type}>${result.value || " "}</div>
`,
)}
</div>
</div>
`;
}
}
render(html`<${App} />`, document.getElementById("app"));