Skip to content

Commit

Permalink
Update Svelte and add snippetFormatter utility; enhance Slider compon…
Browse files Browse the repository at this point in the history
…ent with label formatting
  • Loading branch information
yustarandomname committed Dec 2, 2024
1 parent 1e105ce commit 225b564
Show file tree
Hide file tree
Showing 17 changed files with 302 additions and 136 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"prettier-plugin-svelte": "^3.2.6",
"prettier-plugin-tailwindcss": "^0.6.9",
"storybook": "^8.4.2",
"svelte": "^5.0.0",
"svelte": "^5.3.1",
"svelte-check": "^4.0.0",
"tailwind-merge": "^2.5.4",
"tailwind-variants": "^0.3.0",
Expand All @@ -56,6 +56,7 @@
"vite": "^5.0.3"
},
"dependencies": {
"@number-flow/svelte": "^0.2.1",
"@sveltejs/adapter-netlify": "^4.3.6",
"@sveltejs/adapter-node": "^5.2.9",
"@threlte/core": "8.0.0-next.30",
Expand Down
238 changes: 136 additions & 102 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions src/lib/components/controls/Slider.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,12 @@
class="relative flex w-fit items-center gap-1 pr-1 text-xs text-slate-700"
for="range-{uuid}"
>{slider.label}:
<p class="absolute left-full text-sm" style="color:{slider.color};">
{label}
<p class="absolute left-full flex text-sm" style="color:{slider.color};">
{#if slider.labelFormat}
{@render slider.labelFormat(value)}
{:else}
{label}
{/if}
</p>
</Label>
{/if}
Expand Down
5 changes: 5 additions & 0 deletions src/lib/controls/Controls.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type Matrix2 from '$lib/utils/Matrix2.svelte';
import { PrimeColor, type ColorString } from '$lib/utils/PrimeColors';
import type { Snippet } from 'svelte';
import { Button } from './Button.svelte';
import { Dropdown } from './Dropdown.svelte';
import { Matrix } from './Matrix.svelte';
Expand Down Expand Up @@ -95,6 +96,7 @@ export class Controls<
label?: string;
loop?: boolean;
valueFn?: (v: number) => string;
labelFormat?: Snippet<[number]>;
onRelease?: (v: number) => void;
}
) {
Expand All @@ -110,6 +112,7 @@ export class Controls<
options?.label,
options?.loop,
options?.valueFn,
options?.labelFormat,
options?.onRelease
);

Expand Down Expand Up @@ -140,6 +143,7 @@ export class Controls<
label?: string;
loop?: boolean;
valueFn?: (v: number) => string;
labelFormat?: Snippet<[number]>;
onRelease?: (v: number) => void;
}
) {
Expand All @@ -152,6 +156,7 @@ export class Controls<
options?.label,
options?.loop,
options?.valueFn,
options?.labelFormat,
options?.onRelease
);
return new Controls([newSlider] as const, newSlider.width);
Expand Down
4 changes: 4 additions & 0 deletions src/lib/controls/Slider.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Controller } from './Controls';
import { PrimeColor } from '$lib/utils/PrimeColors';
import type { Snippet } from 'svelte';

/**
* The Slider class is used to create a slider with a default value and a range of values.
Expand All @@ -25,6 +26,7 @@ export class Slider implements Controller<number> {
label = '';
loop = false;
valueFn: (v: number) => string;
labelFormat?: (v: number) => ReturnType<Snippet>;
onRelease: (v: number) => void;

constructor(
Expand All @@ -36,6 +38,7 @@ export class Slider implements Controller<number> {
label: string = '',
loop: boolean = false,
valueFn: (v: number) => string = (v) => v.toString(),
valueFormat: ((v: number) => ReturnType<Snippet>) | undefined = undefined,
onRelease: (v: number) => void = () => {}
) {
this.defaultValue = defaultValue;
Expand All @@ -48,6 +51,7 @@ export class Slider implements Controller<number> {
this.loop = loop;
this.valueFn = valueFn;
this.onRelease = onRelease;
this.labelFormat = valueFormat;
}

static Default = new Slider(0);
Expand Down
37 changes: 37 additions & 0 deletions src/lib/utils/SnippetFormatter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { Snippet } from 'svelte';

type Convert<A extends unknown[]> = {
[K in keyof A]: A[K] extends A[K] ? (() => A[K]) | undefined : never;
};

// type FillArgs<A extends unknown[], B extends unknown[]> = {
// [K in keyof A]: A[K] extends undefined ? B[K] : A[K];
// };

export function snippetFormatter<Args extends unknown[] = []>(
snippet: Snippet<Args>,
args: Convert<Args>
) {
function fillArgs(arg1: Args[], arg2: Args[]): Args[] {
for (let index = 0; index < arg1.length; index++) {
if (arg1[index] === undefined) {
arg1[index] = arg2.shift();
}
}
if (arg2.length > 0) {
arg1.push(...arg2);
}
return arg1;
}

if (snippet.length - 1 === args.length) {
return function ($$anchor: any) {
return snippet($$anchor, ...args);
};
}

return function ($$anchor: any, ...arg: Partial<Args>) {
const fullArguments = fillArgs(args, arg);
return snippet($$anchor, ...fullArguments);
};
}
4 changes: 2 additions & 2 deletions src/routes/[...catchall]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{ name: 'Christophe Smet', title: 'Teacher/Reviewer' },
{ name: 'Fokko van de Bult', title: 'Teacher/Reviewer' },
{ name: 'Teun Janssen', title: 'Teacher/Reviewer' },
{ name: 'Beryl van Gelderen', title: 'Cooridinator' }
{ name: 'Beryl van Gelderen', title: 'Coordinator' }
];
const fileUrls = Object.keys(modules).map((rawUrl) =>
Expand Down Expand Up @@ -48,7 +48,7 @@
class="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100"
>
<span class="text-xs">⌘/Ctrl</span>K
</kbd> to search in through all applets.
</kbd> to search through all applets.
</blockquote>
</div>

Expand Down
12 changes: 9 additions & 3 deletions src/routes/applet/dot_product/inner_product_length/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@
import { Formula } from '$lib/utils/Formulas';
import { round } from '$lib/utils/MathLib';
import { PrimeColor } from '$lib/utils/PrimeColors';
import { snippetFormatter } from '$lib/utils/SnippetFormatter';
import NumberFlow from '@number-flow/svelte';
import { Vector3 } from 'three';
const slider_step = 0.5;
let controls = Controls.addSlider(-3, -5, 5, slider_step, PrimeColor.yellow, {
label: 'x',
valueFn: (v) => round(v, 1).toString()
labelFormat: snippetFormatter<[number]>(labelFormat, [undefined])
})
.addSlider(3, -5, 5, slider_step, PrimeColor.yellow, {
label: 'y',
valueFn: (v) => round(v, 1).toString()
labelFormat: snippetFormatter<[number]>(labelFormat, [undefined])
})
.addSlider(6, -5, 6, slider_step, PrimeColor.yellow, {
label: 'z',
valueFn: (v) => round(v, 1).toString()
labelFormat: snippetFormatter<[number]>(labelFormat, [undefined])
});
const A = $derived(new Vector3(controls[1], controls[2], controls[0]));
Expand All @@ -47,6 +49,10 @@
});
</script>

{#snippet labelFormat(value: number)}
<NumberFlow {value} />
{/snippet}

<Canvas3D {controls} {formulas} cameraPosition={new Vector3(2.73, 13.56, 10.42)}>
<!-- Vector q [raspberry] -->
<Vector3D direction={Q} color={PrimeColor.raspberry} length={Q.length()} />
Expand Down
11 changes: 9 additions & 2 deletions src/routes/applet/geom_lin_trans/rotisdoublerefl/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@
import { VECTOR_WIDTH } from '$lib/utils/AttributeDimensions';
import { Formula, Formulas } from '$lib/utils/Formulas';
import { PrimeColor } from '$lib/utils/PrimeColors';
import { snippetFormatter } from '$lib/utils/SnippetFormatter';
import { Vector2 } from 'three';
import NumberFlow from '@number-flow/svelte';
const controls = Controls.addSlider(0.5, 0, Math.PI, 0.1, PrimeColor.cyan, {
label: 'ϕ/2',
valueFn: (v) => (v / Math.PI).toFixed(2) + 'π'
labelFormat: snippetFormatter<[number]>(labelFormat, [undefined])
}).addSlider(0.4, 0, Math.PI * 0.75, 0.1, PrimeColor.blue, {
label: 'θ/2',
valueFn: (v) => (v / Math.PI).toFixed(2) + 'π'
labelFormat: snippetFormatter<[number]>(labelFormat, [undefined])
});
const draggables = [
Expand Down Expand Up @@ -53,6 +55,11 @@
});
</script>

{#snippet labelFormat(value: number)}
<NumberFlow value={value / Math.PI} />
<p>π</p>
{/snippet}

<Canvas2D {draggables} {formulas} {controls} showFormulasDefault>
<!-- L1 -->
<InfiniteLine2D direction={dir_L1} color={PrimeColor.cyan} />
Expand Down
13 changes: 11 additions & 2 deletions src/routes/applet/linear_combinations/span_one/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
<script>
<script lang="ts">
import { Controls } from '$lib/controls/Controls';
import Axis3D from '$lib/threlte/Axis3D.svelte';
import Canvas3D from '$lib/threlte/Canvas3D.svelte';
import Latex3D from '$lib/threlte/Latex3D.svelte';
import Line3D from '$lib/threlte/Line3D.svelte';
import Vector3D from '$lib/threlte/Vector3D.svelte';
import { PrimeColor } from '$lib/utils/PrimeColors';
import { snippetFormatter } from '$lib/utils/SnippetFormatter';
import NumberFlow from '@number-flow/svelte';
import { Vector3 } from 'three';
const vDir = new Vector3(3, 2, -3);
const lineDir = vDir.clone().normalize().multiplyScalar(10);
const controls = Controls.addSlider(vDir.length(), -9, 9, 0.5, PrimeColor.raspberry);
const controls = Controls.addSlider(vDir.length(), -9, 9, 0.5, PrimeColor.raspberry, {
label: 'length',
labelFormat: snippetFormatter<[number]>(labelFormat, [undefined])
});
// Do not allow the vector to be zero, otherwise the direction is not defined
const vLength = $derived(Math.abs(controls[0]) <= 0.0001 ? 0.5 : controls[0]);
const v = $derived(vDir.clone().normalize().multiplyScalar(vLength)); // Direction of vector v
</script>

{#snippet labelFormat(value: number)}
<NumberFlow {value} />
{/snippet}

<Canvas3D {controls} title="Span of a vector">
<Vector3D alwaysOnTop direction={v} length={v.length()} color={PrimeColor.raspberry}>
{#snippet children(endPoint)}
Expand Down
22 changes: 14 additions & 8 deletions src/routes/applet/linear_combinations/span_two_line/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
<script>
<script lang="ts">
import { Controls } from '$lib/controls/Controls';
import Axis3D from '$lib/threlte/Axis3D.svelte';
import Canvas3D from '$lib/threlte/Canvas3D.svelte';
import Latex3D from '$lib/threlte/Latex3D.svelte';
import Line3D from '$lib/threlte/Line3D.svelte';
import Vector3D from '$lib/threlte/Vector3D.svelte';
import { PrimeColor } from '$lib/utils/PrimeColors';
import { snippetFormatter } from '$lib/utils/SnippetFormatter';
import NumberFlow from '@number-flow/svelte';
import { Vector3 } from 'three';
let controls = Controls.addSlider(3, -5, 5, 0.5, PrimeColor.raspberry).addSlider(
5,
-5,
5,
0.5,
PrimeColor.blue
);
let controls = Controls.addSlider(3, -5, 5, 0.5, PrimeColor.raspberry, {
label: 'v',
labelFormat: snippetFormatter<[number]>(labelFormat, [undefined])
}).addSlider(5, -5, 5, 0.5, PrimeColor.blue, {
label: 'u',
labelFormat: snippetFormatter<[number]>(labelFormat, [undefined])
});
const v = $derived(new Vector3(3, 2, -3).normalize().multiplyScalar(3)); // Vector v;
const u = $derived(v.clone().multiplyScalar(2)); // Vector u = 2 * v;
Expand All @@ -24,6 +26,10 @@
const uLen = $derived(Math.abs(controls[1]) < 1 ? (controls[1] < 0 ? -1 : 1) : controls[1]);
</script>

{#snippet labelFormat(value: number)}
<NumberFlow {value} />
{/snippet}

<Canvas3D title="Span of two parallel vectors" {controls}>
<!-- If u & v are on the same quadrant and v is SMALLER OR EQUAL TO than u -> u on top -->
{#if controls[0] * controls[1] >= 0 && Math.abs(controls[0]) <= Math.abs(controls[1])}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
<script>
<script lang="ts">
import { Controls } from '$lib/controls/Controls';
import Axis3D from '$lib/threlte/Axis3D.svelte';
import Canvas3D from '$lib/threlte/Canvas3D.svelte';
import Latex3D from '$lib/threlte/Latex3D.svelte';
import Vector3D from '$lib/threlte/Vector3D.svelte';
import { Formula } from '$lib/utils/Formulas';
import { PrimeColor } from '$lib/utils/PrimeColors';
import { snippetFormatter } from '$lib/utils/SnippetFormatter';
import NumberFlow from '@number-flow/svelte';
import { Vector3 } from 'three';
const v_0 = new Vector3(-2, 3, 2);
const u = new Vector3(2, 1, -1);
let controls = Controls.addSlider(2, -1.5, 3, 0.1, PrimeColor.darkGreen);
let controls = Controls.addSlider(2, -1.5, 3, 0.1, PrimeColor.darkGreen, {
label: 'r',
labelFormat: snippetFormatter<[number]>(labelFormat, [undefined])
});
const ru_len = $derived(controls[0] * u.length());
const formula = $derived(new Formula('r = \\$', controls[0], PrimeColor.darkGreen));
</script>

{#snippet labelFormat(value: number)}
<NumberFlow {value} />
{/snippet}

<Canvas3D
formulas={[formula]}
cameraPosition={new Vector3(3.31, 6.55, 15.68)}
cameraZoom={38}
{controls}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import { Formula, Formulas } from '$lib/utils/Formulas';
import { round } from '$lib/utils/MathLib';
import { PrimeColor } from '$lib/utils/PrimeColors';
import { snippetFormatter } from '$lib/utils/SnippetFormatter';
import NumberFlow from '@number-flow/svelte';
import { Vector2 } from 'three';
const controls = Controls.addSlider(1, -5, 5, 0.5, PrimeColor.darkGreen, {
label: 'r',
valueFn: (x) => round(x).toString()
labelFormat: snippetFormatter<[number]>(labelFormat, [undefined])
});
const u = new Vector2(-2, 1);
Expand All @@ -37,6 +39,10 @@
});
</script>

{#snippet labelFormat(value: number)}
<NumberFlow {value} />
{/snippet}

<Canvas2D {controls} {formulas} showFormulasDefault title="A parametric vector of a line">
<!-- Line L -->
<InfiniteLine2D origin={v0} direction={u} color={PrimeColor.cyan} />
Expand Down
Loading

0 comments on commit 225b564

Please sign in to comment.