Skip to content

Commit

Permalink
feat: migrate to svelte 5
Browse files Browse the repository at this point in the history
  • Loading branch information
eye-wave committed Oct 23, 2024
1 parent 437fc73 commit 3cbd731
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 54 deletions.
Binary file modified bun.lockb
Binary file not shown.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "svelte-knobs",
"description": "Svelte component library for building customizable knob controls.",
"version": "0.1.1",
"version": "0.2.0",
"repository": {
"url": "https://github.com/eye-wave/svelte-knobs"
},
Expand Down Expand Up @@ -41,8 +41,8 @@
"devDependencies": {
"@sveltejs/adapter-static": "^3.0.5",
"@sveltejs/kit": "^2.7.2",
"@sveltejs/package": "^2.3.5",
"@sveltejs/vite-plugin-svelte": "^3.1.2",
"@sveltejs/package": "^2.3.6",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@types/eslint": "^9.6.1",
"eslint": "^9.13.0",
"eslint-config-prettier": "^9.1.0",
Expand All @@ -52,11 +52,11 @@
"prettier-plugin-svelte": "^3.2.7",
"publint": "^0.2.11",
"shiki": "^1.22.0",
"svelte": "^4.2.19",
"svelte": "^5.1.0",
"svelte-check": "^4.0.5",
"typescript": "^5.6.3",
"typescript-eslint": "^8.11.0",
"vite": "^5.4.9"
"vite": "^5.4.10"
},
"svelte": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand Down
108 changes: 67 additions & 41 deletions src/lib/Knob.svelte
Original file line number Diff line number Diff line change
@@ -1,40 +1,63 @@
<script lang="ts">
import { normalize, format, unnormalizeToString, unnormalizeToNumber } from './params.js';
import { spring } from 'svelte/motion';
import { createEventDispatcher } from 'svelte';
import type { EnumParam, FloatParam } from './params.js';
import { normalize, format, unnormalizeToString, unnormalizeToNumber } from './params.js';
const size = 80;
export let label = '';
export let unit = '';
export let param: FloatParam | EnumParam<readonly string[]>;
export let value: number | string;
export let stiffness = 0.5;
export let decimalDigits = 0;
export let snapValues: number[] = [];
export let snapThreshold = 0.1;
export let disabled = false;
export let arcColor = '#ae98db';
export let bgColor = '#444';
export let disabledColor = '#777';
$: arcColor2 = disabled ? disabledColor : arcColor;
$: if (param.type === 'enum-param') snapValues = [];
$: center = size / 2;
$: arcRadius = size * 0.4;
$: circleRadius = size * 0.32;
$: lineWidth = size * 0.04;
interface Props {
style?: string;
class?: string;
label?: string;
unit?: string;
size?: number;
onChange?: (value: number | string) => void;
param: FloatParam | EnumParam<readonly string[]>;
value: number | string;
stiffness?: number;
decimalDigits?: number;
snapValues?: Array<number>;
snapThreshold?: number;
disabled?: boolean;
colors?: {
arc?: string;
bg?: string;
disabled?: string;
};
}
let isDragging = false;
let {
style,
class: className,
label = '',
unit = '',
size = 80,
onChange,
value = $bindable(),
param,
stiffness = 0.5,
decimalDigits = 0,
snapValues = [],
snapThreshold = 0.1,
disabled = false,
colors = {}
}: Props = $props();
const {
arc: arcColor = '#ae98db',
bg: bgColor = '#444',
disabled: disabledColor = '#777'
} = colors;
const arcColor2 = $derived(disabled ? disabledColor : arcColor);
const center = $derived(size / 2);
const arcRadius = $derived(size * 0.4);
const circleRadius = $derived(size * 0.32);
const lineWidth = $derived(size * 0.04);
let isDragging = $state(false);
let startY: number;
let startValue: number;
const dispatch = createEventDispatcher();
// This is needed in case some snap value is very close to the min or max range
// preventing the user from selecting that value
function completeFixedSnapValues(snapValues: number[]) {
Expand All @@ -50,14 +73,20 @@
return clone;
}
$: fixedSnapValues = completeFixedSnapValues(snapValues);
const fixedSnapValues = $derived(completeFixedSnapValues(snapValues));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const rotationDegrees = spring(normalize(value as any, param as any) * 270 - 135, { stiffness });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
$: normalizedValue = normalize(value as any, param as any);
$: rotationDegrees.set(normalizedValue * 270 - 135);
const normalizedValue = $derived(normalize(value as any, param as any));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const formatted = $derived(isDragging ? format(value as any, param as any, decimalDigits) : '');
$effect(() => {
rotationDegrees.set(normalizedValue * 270 - 135);
});
function handleMouseDown(event: MouseEvent) {
isDragging = true;
Expand All @@ -83,7 +112,7 @@
if (value !== newValue) {
value = newValue;
dispatch('change', { value });
onChange?.(value);
}
return;
Expand All @@ -109,7 +138,7 @@
if (value !== newValue) {
value = newValue;
dispatch('change', { value });
onChange?.(value);
}
}
Expand Down Expand Up @@ -151,16 +180,13 @@
return paths.join(' ');
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
$: formatted = isDragging ? format(value as any, param as any, decimalDigits) : '';
</script>

<svelte:window on:mousemove={handleMouseMove} on:mouseup={handleMouseUp} />
<svelte:window onmousemove={handleMouseMove} onmouseup={handleMouseUp} />

<div class="container" style={$$props.style}>
<div class="container" {style}>
<svg
class={$$props.class}
class={className}
role="slider"
tabindex="0"
aria-valuenow={normalizedValue}
Expand All @@ -170,7 +196,7 @@
stroke-linecap="round"
stroke-linejoin="round"
stroke-width={lineWidth}
on:mousedown={handleMouseDown}
onmousedown={handleMouseDown}
>
<circle cx={center} cy={center} r={circleRadius} fill={bgColor}></circle>
{#if snapValues.length > 0 || param.type === 'enum-param'}
Expand Down
19 changes: 14 additions & 5 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
<div class="example">
<h2>Logarithmic</h2>
<Knob param={freqParam} bind:value={freqValue} label="Frequency" unit="hz" />
<Knob param={gainParam} bind:value={gainValue} label="Gain" unit="dB" />
<Knob param={gainParam} bind:value={gainValue} label="Gain" unit="dB" decimalDigits={1} />
<Knob param={qParam} bind:value={qValue} label="Q" unit="dB" decimalDigits={2} />

<p>A knob with logarithmic scaling (default base is 10).</p>
Expand Down Expand Up @@ -122,16 +122,25 @@
<div class="example">
<h2>Colors</h2>

<Knob param={basicParam} value={24} label="Svelte theme" arcColor="#ff3e00" />
<Knob param={basicParam} value={24} label="Svelte theme" colors={{ arc: '#ff3e00' }} />
<Knob
param={basicParam}
value={48}
label="Light theme"
arcColor="#4292d3"
bgColor="#eef"
colors={{
arc: '#4292d3',
bg: '#eef'
}}
style="color:#000"
/>
<Knob param={basicParam} value={64} label="Disabled color" disabledColor="#aaa" disabled />
<Knob
onChange={console.log}
param={basicParam}
value={64}
label="Disabled color"
colors={{ disabled: '#ccc' }}
disabled
/>

<p>
Of course, <code>{'<Knob />'}</code> colors can be customized to look however you want.
Expand Down
10 changes: 7 additions & 3 deletions src/routes/CopyPaste.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
<script lang="ts">
import type { Snippet } from 'svelte';
let ref: HTMLPreElement;
let copied = false;
let copied = $state(false);
let timeoutId = -1;
let { children }: { children: Snippet } = $props();
function copyToClipboard() {
const code = ref.textContent?.trim();
if (code === undefined) return;
Expand All @@ -18,7 +22,7 @@
</script>

<div class="code-container">
<button on:click={copyToClipboard} class="copy-button" aria-label="Copy code to clipboard">
<button onclick={copyToClipboard} class="copy-button" aria-label="Copy code to clipboard">
{#if copied}
<svg
xmlns="http://www.w3.org/2000/svg"
Expand Down Expand Up @@ -50,7 +54,7 @@
{/if}
</button>
<pre bind:this={ref}>
<slot />
{@render children?.()}
</pre>
</div>

Expand Down

0 comments on commit 3cbd731

Please sign in to comment.