summaryrefslogtreecommitdiff
path: root/ui/lib
diff options
context:
space:
mode:
Diffstat (limited to 'ui/lib')
-rw-r--r--ui/lib/components/swatch/EventLog.svelte37
-rw-r--r--ui/lib/swatch/derive.js20
-rw-r--r--ui/lib/swatch/event-capture.svelte.js22
3 files changed, 79 insertions, 0 deletions
diff --git a/ui/lib/components/swatch/EventLog.svelte b/ui/lib/components/swatch/EventLog.svelte
new file mode 100644
index 0000000..2d8c5c0
--- /dev/null
+++ b/ui/lib/components/swatch/EventLog.svelte
@@ -0,0 +1,37 @@
+<script>
+ /*
+ * The interface exposed by this component is designed to be compatible with the interface
+ * exposed by the `EventCapture` class, so that you can do this:
+ *
+ * let capture = $state(new EventCapture());
+ * const someEvent = capture.on('someEvent');
+ *
+ * // …
+ *
+ * <EventLog events={capture.events} clear={capture.clear.bind(capture)} />
+ */
+
+ let { events, clear = () => {} } = $props();
+
+ function onclick() {
+ clear();
+ }
+</script>
+
+<button {onclick}>clear</button>
+<table>
+ <thead>
+ <tr>
+ <th>event</th>
+ <th>arguments</th>
+ </tr>
+ </thead>
+ <tbody>
+ {#each events as { event, args }}
+ <tr>
+ <td>{event}</td>
+ <td><code>{JSON.stringify(args)}</code></td>
+ </tr>
+ {/each}
+ </tbody>
+</table>
diff --git a/ui/lib/swatch/derive.js b/ui/lib/swatch/derive.js
new file mode 100644
index 0000000..85547e8
--- /dev/null
+++ b/ui/lib/swatch/derive.js
@@ -0,0 +1,20 @@
+// A fun fact about $derive: if the deriving expression throws an error, then Svelte (at least as of
+// 5.20.2) _permanently_ stops evaluating it, even if the inputs change. To prevent this, you need
+// to ensure that derive expressions never raise an exception.
+function tryDerive(args, func, fallback) {
+ try {
+ return func(...args);
+ } catch (e) {
+ console.debug('deriver threw exception', e, func, args);
+ return fallback;
+ }
+}
+
+// A "deriver" is a function that never raises; if the underlying function would raise, the
+// corresponding deriver instead returns a fallback value (or `undefined`).
+export function makeDeriver(func, fallback) {
+ return (...args) => tryDerive(args, func, fallback);
+}
+
+// Some widely-used derivers, for convenience.
+export const json = makeDeriver(JSON.parse);
diff --git a/ui/lib/swatch/event-capture.svelte.js b/ui/lib/swatch/event-capture.svelte.js
new file mode 100644
index 0000000..32c0f39
--- /dev/null
+++ b/ui/lib/swatch/event-capture.svelte.js
@@ -0,0 +1,22 @@
+/*
+ * The interface exposed by this class is designed to closely match the interface expected by
+ * the `EventLog` component, so that you can do this:
+ *
+ * let capture = $state(new EventCapture());
+ * const someEvent = capture.on('someEvent');
+ *
+ * // …
+ *
+ * <EventLog events={capture.events} clear={capture.clear.bind(capture)} />
+ */
+export default class EventCapture {
+ events = $state([]);
+
+ on(event) {
+ return (...args) => this.events.push({ event, args });
+ }
+
+ clear() {
+ this.events = [];
+ }
+}