refactor: migrate to svelte 5
This commit is contained in:
parent
f37019c3ef
commit
2d5c5f4130
23 changed files with 3529 additions and 126 deletions
|
@ -31,7 +31,7 @@
|
|||
"prettier": "^3.5.0",
|
||||
"prettier-plugin-svelte": "^3.3.3",
|
||||
"puppeteer": "^22.15.0",
|
||||
"svelte-check": "^3.8.6",
|
||||
"svelte-check": "^4.0.0",
|
||||
"wait-on": "^7.2.0"
|
||||
},
|
||||
"type": "module",
|
||||
|
@ -41,13 +41,13 @@
|
|||
"@sveltejs/adapter-auto": "^3.3.1",
|
||||
"@sveltejs/adapter-static": "^3.0.8",
|
||||
"@sveltejs/kit": "^2.17.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.2",
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
||||
"@tabler/icons-webfont": "^2.47.0",
|
||||
"debug": "^4.4.0",
|
||||
"i18next": "^23.16.8",
|
||||
"lodash": "^4.17.21",
|
||||
"normalize.css": "^8.0.1",
|
||||
"svelte": "^4.2.19",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-i18next": "^2.2.2",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.7.3",
|
||||
|
|
3333
pnpm-lock.yaml
generated
Normal file
3333
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,8 +1,8 @@
|
|||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let heightOdd = false;
|
||||
let widthOdd = false;
|
||||
let heightOdd = $state(false);
|
||||
let widthOdd = $state(false);
|
||||
|
||||
function updateOdd() {
|
||||
heightOdd = window.innerHeight % 2 === 1;
|
||||
|
|
|
@ -7,17 +7,21 @@
|
|||
const MAX_COUNT = 33;
|
||||
const MARGIN_SIZE = 16;
|
||||
|
||||
let horizontalCount = START_COUNT;
|
||||
let verticalCount = START_COUNT;
|
||||
let blockSize = 64;
|
||||
let cornerBlocks = 2;
|
||||
let horizontalCount = $state(START_COUNT);
|
||||
let verticalCount = $state(START_COUNT);
|
||||
let blockSize = $state(64);
|
||||
let cornerBlocks = $state(2);
|
||||
|
||||
let horizontalMargin = MARGIN_SIZE;
|
||||
let verticalMargin = MARGIN_SIZE;
|
||||
let unloaded = true;
|
||||
let horizontalMargin = $state(MARGIN_SIZE);
|
||||
let verticalMargin = $state(MARGIN_SIZE);
|
||||
let unloaded = $state(true);
|
||||
|
||||
export let transparent = false;
|
||||
export let subdued = false;
|
||||
interface Props {
|
||||
transparent?: boolean;
|
||||
subdued?: boolean;
|
||||
}
|
||||
|
||||
let { transparent = false, subdued = false }: Props = $props();
|
||||
|
||||
function updateCounts() {
|
||||
const gridWidth = window.innerWidth - MARGIN_SIZE;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let time = new Date();
|
||||
let time = $state(new Date());
|
||||
|
||||
onMount(() => {
|
||||
setInterval(() => {
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
import { fade } from 'svelte/transition';
|
||||
import { i18n } from '$lib/i18n';
|
||||
|
||||
let screenResolution = '... x ...';
|
||||
let windowResolution = '';
|
||||
let dpr = "1";
|
||||
let screenResolution = $state('... x ...');
|
||||
let windowResolution = $state('');
|
||||
let dpr = $state("1");
|
||||
|
||||
function updateResolution() {
|
||||
const realWidth = Math.round(screen.width) * window.devicePixelRatio;
|
||||
|
|
|
@ -8,25 +8,29 @@
|
|||
import { createEventDispatcher } from 'svelte';
|
||||
const dispatch = createEventDispatcher<{ focus: void }>();
|
||||
|
||||
export let bg = false;
|
||||
interface Props {
|
||||
bg?: boolean;
|
||||
}
|
||||
|
||||
let sizes = {
|
||||
let { bg = false }: Props = $props();
|
||||
|
||||
let sizes = $state({
|
||||
blockSize: 64,
|
||||
horizontalCount: 16,
|
||||
verticalCount: 16,
|
||||
horizontalMargin: 0,
|
||||
verticalMargin: 0
|
||||
};
|
||||
});
|
||||
|
||||
$: columnWidth = sizes.horizontalCount % 2 === 0 ? 3 : 4;
|
||||
$: columnHeight = 2 * Math.floor((sizes.verticalCount * 0.75) / 2) + (sizes.verticalCount % 2);
|
||||
$: leftColumn = sizes.horizontalCount / 4 - columnWidth / 2;
|
||||
$: circleBlocks =
|
||||
2 * Math.floor((Math.min(sizes.horizontalCount, sizes.verticalCount) * 0.66) / 2) +
|
||||
(sizes.horizontalCount % 2);
|
||||
let columnWidth = $derived(sizes.horizontalCount % 2 === 0 ? 3 : 4);
|
||||
let columnHeight = $derived(2 * Math.floor((sizes.verticalCount * 0.75) / 2) + (sizes.verticalCount % 2));
|
||||
let leftColumn = $derived(sizes.horizontalCount / 4 - columnWidth / 2);
|
||||
let circleBlocks =
|
||||
$derived(2 * Math.floor((Math.min(sizes.horizontalCount, sizes.verticalCount) * 0.66) / 2) +
|
||||
(sizes.horizontalCount % 2));
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div
|
||||
class="test-card"
|
||||
class:bg
|
||||
|
@ -37,7 +41,7 @@
|
|||
--column-width: {columnWidth};
|
||||
--column-height: {columnHeight};
|
||||
--left-column: {leftColumn};"
|
||||
on:dblclick={() => dispatch('focus') && document.body.requestFullscreen()}
|
||||
ondblclick={() => dispatch('focus') && document.body.requestFullscreen()}
|
||||
>
|
||||
<BackgroundGrid on:change={(ev) => (sizes = ev.detail)} subdued={bg} />
|
||||
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
<script>
|
||||
<script lang="ts">
|
||||
import { i18n } from '$lib/i18n';
|
||||
interface Props {
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let { children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<a href=".." class="hide-idle"><i class="ti ti-arrow-back"></i> {$i18n.t('Back')}</a>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
|
||||
<style>
|
||||
a {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script lang="ts">
|
||||
import TestCard from '$lib/TestCard.svelte';
|
||||
|
||||
let x = -1;
|
||||
let y = -1;
|
||||
let leftButton = false;
|
||||
let rightButton = false;
|
||||
let x = $state(-1);
|
||||
let y = $state(-1);
|
||||
let leftButton = $state(false);
|
||||
let rightButton = $state(false);
|
||||
|
||||
function onMouseMove(ev: MouseEvent) {
|
||||
x = ev.x;
|
||||
|
@ -31,10 +31,10 @@
|
|||
</script>
|
||||
|
||||
<svelte:body
|
||||
on:mousemove={onMouseMove}
|
||||
on:mousedown={onMouseDown}
|
||||
on:mouseup={onMouseUp}
|
||||
on:contextmenu={(ev) => {
|
||||
onmousemove={onMouseMove}
|
||||
onmousedown={onMouseDown}
|
||||
onmouseup={onMouseUp}
|
||||
oncontextmenu={(ev) => {
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
}}
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
<script lang="ts">
|
||||
import TestCard from '$lib/TestCard.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/state';
|
||||
import { goto } from '$app/navigation';
|
||||
import { i18n } from '$lib/i18n';
|
||||
interface Props {
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let { children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<TestCard bg on:focus={() => goto('/card')} />
|
||||
<main class:sub={!$page.data.root}>
|
||||
<a href=".." class="button button-back"><i class="ti ti-arrow-back" />{$i18n.t('Back')}</a>
|
||||
<slot />
|
||||
<main class:sub={!page.data.root}>
|
||||
<a href=".." class="button button-back"><i class="ti ti-arrow-back"></i>{$i18n.t('Back')}</a>
|
||||
{@render children?.()}
|
||||
</main>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<script lang="ts">
|
||||
import { run } from 'svelte/legacy';
|
||||
|
||||
import { version } from '../../../package.json';
|
||||
import { i18n } from '$lib/i18n';
|
||||
import type { Snapshot } from '@sveltejs/kit';
|
||||
const buildDate = import.meta.env.VITE_BUILD_DATE || "???";
|
||||
|
||||
let search = '';
|
||||
let search = $state('');
|
||||
|
||||
type Entry = {
|
||||
id: string;
|
||||
|
@ -126,8 +128,8 @@
|
|||
}
|
||||
];
|
||||
|
||||
let filteredTests: Test[] = tests;
|
||||
let filteredCategories: Category[] = [];
|
||||
let filteredTests: Test[] = $state(tests);
|
||||
let filteredCategories: Category[] = $state([]);
|
||||
|
||||
function doSearch(search: string) {
|
||||
filteredTests = tests.filter((test) => {
|
||||
|
@ -141,7 +143,9 @@
|
|||
);
|
||||
});
|
||||
}
|
||||
$: doSearch(search);
|
||||
run(() => {
|
||||
doSearch(search);
|
||||
});
|
||||
|
||||
function setFilter(category: Category) {
|
||||
if (filteredCategories.includes(category)) {
|
||||
|
@ -151,13 +155,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
$: nonEmptyCategories = categories.filter((category) => {
|
||||
let nonEmptyCategories = $derived(categories.filter((category) => {
|
||||
const categoryTests = filteredTests.filter((test) => test.categories.includes(category.id));
|
||||
return categoryTests.some(
|
||||
(test) =>
|
||||
!filteredCategories.length || filteredCategories.every((f) => test.categories.includes(f))
|
||||
);
|
||||
});
|
||||
}));
|
||||
|
||||
export const snapshot: Snapshot<string> = {
|
||||
capture: () => JSON.stringify({ filtered: filteredCategories, search }),
|
||||
|
@ -172,13 +176,13 @@
|
|||
<h1>Total Tech Test</h1>
|
||||
|
||||
<nav>
|
||||
<!-- svelte-ignore a11y-autofocus -->
|
||||
<!-- svelte-ignore a11y_autofocus -->
|
||||
<input type="search" placeholder={$i18n.t('Search')} bind:value={search} autofocus />
|
||||
|
||||
<div class="options">
|
||||
{#each superCategories as category}
|
||||
<button
|
||||
on:click={() => setFilter(category.id)}
|
||||
onclick={() => setFilter(category.id)}
|
||||
class:active={!filteredCategories.length || filteredCategories.includes(category.id)}
|
||||
class="super"
|
||||
>
|
||||
|
@ -189,7 +193,7 @@
|
|||
<div class="separator"></div>
|
||||
{#each categories as category}
|
||||
<button
|
||||
on:click={() => setFilter(category.id)}
|
||||
onclick={() => setFilter(category.id)}
|
||||
class:active={!filteredCategories.length || filteredCategories.includes(category.id)}
|
||||
>
|
||||
<i class="ti {category.icon}"></i>
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
<script lang="ts">
|
||||
import CycleButton from './cycle-button.svelte';
|
||||
interface Props {
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let channelsEl: HTMLDivElement;
|
||||
let { children }: Props = $props();
|
||||
|
||||
let channelsEl: HTMLDivElement = $state();
|
||||
</script>
|
||||
|
||||
<div class="channels" bind:this={channelsEl}>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
<div class="controls">
|
||||
<CycleButton element={channelsEl} />
|
||||
|
|
|
@ -2,9 +2,13 @@
|
|||
import { onDestroy } from 'svelte';
|
||||
import { i18n } from '$lib/i18n';
|
||||
|
||||
export let element: HTMLElement;
|
||||
interface Props {
|
||||
element: HTMLElement;
|
||||
}
|
||||
|
||||
let cycling = false;
|
||||
let { element }: Props = $props();
|
||||
|
||||
let cycling = $state(false);
|
||||
let currentChannel: HTMLAudioElement | undefined;
|
||||
async function cycleChannels() {
|
||||
cycling = true;
|
||||
|
@ -44,7 +48,7 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<button on:click={onClick}>
|
||||
<button onclick={onClick}>
|
||||
<i class="ti ti-refresh"></i>
|
||||
{#if cycling}
|
||||
{$i18n.t('Stop Cycling')}
|
||||
|
|
|
@ -1,13 +1,26 @@
|
|||
<script lang="ts">
|
||||
export let src: string;
|
||||
export let left = false;
|
||||
export let center = false;
|
||||
export let right = false;
|
||||
export let lfe = false;
|
||||
export let inline = false;
|
||||
interface Props {
|
||||
src: string;
|
||||
left?: boolean;
|
||||
center?: boolean;
|
||||
right?: boolean;
|
||||
lfe?: boolean;
|
||||
inline?: boolean;
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let currentTime = 0;
|
||||
let paused = true;
|
||||
let {
|
||||
src,
|
||||
left = false,
|
||||
center = false,
|
||||
right = false,
|
||||
lfe = false,
|
||||
inline = false,
|
||||
children
|
||||
}: Props = $props();
|
||||
|
||||
let currentTime = $state(0);
|
||||
let paused = $state(true);
|
||||
function play() {
|
||||
currentTime = 0;
|
||||
paused = false;
|
||||
|
@ -22,14 +35,14 @@
|
|||
class:lfe
|
||||
class:inline
|
||||
class:playing={!paused}
|
||||
on:click={play}
|
||||
onclick={play}
|
||||
>
|
||||
{#if !lfe}
|
||||
<i class="ti ti-volume"></i>
|
||||
{:else}
|
||||
<i class="ti ti-wave-sine"></i>
|
||||
{/if}
|
||||
<span><slot /></span>
|
||||
<span>{@render children?.()}</span>
|
||||
<audio bind:currentTime bind:paused {src}></audio>
|
||||
</button>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import CycleButton from './cycle-button.svelte';
|
||||
import { i18n } from '$lib/i18n';
|
||||
|
||||
let speakersEl: HTMLElement;
|
||||
let speakersEl: HTMLElement = $state();
|
||||
</script>
|
||||
|
||||
<div class="test">
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
<script lang="ts">
|
||||
import { i18n } from '$lib/i18n';
|
||||
interface Props {
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let { children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<h2><i class="ti ti-volume"></i> {$i18n.t('Audio test')}</h2>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
import { onMount } from 'svelte';
|
||||
import { i18n } from '$lib/i18n';
|
||||
|
||||
let frequency = 60;
|
||||
let playing = false;
|
||||
let frequency = $state(60);
|
||||
let playing = $state(false);
|
||||
|
||||
let audioCtx: AudioContext | undefined;
|
||||
let oscillatorL: OscillatorNode | undefined;
|
||||
|
@ -58,9 +58,9 @@
|
|||
<input type="number" bind:value={frequency} min="20" max="20000" disabled={playing} />Hz
|
||||
</label>
|
||||
<div class="controls">
|
||||
<button on:click={() => start('inPhase')}>{$i18n.t('In Phase')}</button>
|
||||
<button on:click={() => start('outOfPhase')}>{$i18n.t('Out of Phase')}</button>
|
||||
<button class="stop" on:click={stop} disabled={!playing}>{$i18n.t('Stop')}</button>
|
||||
<button onclick={() => start('inPhase')}>{$i18n.t('In Phase')}</button>
|
||||
<button onclick={() => start('outOfPhase')}>{$i18n.t('Out of Phase')}</button>
|
||||
<button class="stop" onclick={stop} disabled={!playing}>{$i18n.t('Stop')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<script lang="ts">
|
||||
import videoUrl from '@assets/avsync.webm';
|
||||
import { i18n } from '$lib/i18n';
|
||||
let paused = true;
|
||||
let paused = $state(true);
|
||||
</script>
|
||||
|
||||
<h2><i class="ti ti-time-duration-off"></i> {$i18n.t('Audio/Video Synchronization')}</h2>
|
||||
<!-- svelte-ignore a11y-media-has-caption -->
|
||||
<!-- svelte-ignore a11y_media_has_caption -->
|
||||
<video
|
||||
class:playing={!paused}
|
||||
autoplay
|
||||
loop
|
||||
bind:paused
|
||||
src={videoUrl}
|
||||
on:click={() => (paused = false)}
|
||||
onclick={() => (paused = false)}
|
||||
></video>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,25 +1,31 @@
|
|||
<script lang="ts">
|
||||
import { run } from 'svelte/legacy';
|
||||
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { browser } from '$app/environment';
|
||||
import debug from 'debug';
|
||||
import { i18n } from '$lib/i18n';
|
||||
const dbg = debug('app:camera');
|
||||
|
||||
let video: HTMLVideoElement;
|
||||
let devices: MediaDeviceInfo[] = [];
|
||||
let currentDevice: string | undefined;
|
||||
let video: HTMLVideoElement = $state();
|
||||
let devices: MediaDeviceInfo[] = $state([]);
|
||||
let currentDevice: string | undefined = $state();
|
||||
|
||||
let requestResolution: [number, number] | 'auto' = 'auto';
|
||||
let requestFramerate: number | 'auto' = 'auto';
|
||||
let requestResolution: [number, number] | 'auto' = $state('auto');
|
||||
let requestFramerate: number | 'auto' = $state('auto');
|
||||
let deviceInfo: {
|
||||
resolution?: string;
|
||||
frameRate?: number;
|
||||
} = {};
|
||||
let snapshot: string | undefined;
|
||||
let flipped = false;
|
||||
} = $state({});
|
||||
let snapshot: string | undefined = $state();
|
||||
let flipped = $state(false);
|
||||
|
||||
$: dbg('devices %O', devices);
|
||||
$: dbg('currentDevice %s', currentDevice);
|
||||
run(() => {
|
||||
dbg('devices %O', devices);
|
||||
});
|
||||
run(() => {
|
||||
dbg('currentDevice %s', currentDevice);
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
refreshDevices();
|
||||
|
@ -48,21 +54,23 @@
|
|||
}
|
||||
}
|
||||
|
||||
$: if (currentDevice) {
|
||||
navigator.mediaDevices
|
||||
.getUserMedia({
|
||||
video: {
|
||||
deviceId: currentDevice,
|
||||
width: requestResolution === 'auto' ? undefined : requestResolution[0],
|
||||
height: requestResolution === 'auto' ? undefined : requestResolution[1],
|
||||
frameRate: requestFramerate === 'auto' ? undefined : requestFramerate
|
||||
}
|
||||
})
|
||||
.then((stream) => {
|
||||
video.srcObject = stream;
|
||||
refreshDevices();
|
||||
});
|
||||
}
|
||||
run(() => {
|
||||
if (currentDevice) {
|
||||
navigator.mediaDevices
|
||||
.getUserMedia({
|
||||
video: {
|
||||
deviceId: currentDevice,
|
||||
width: requestResolution === 'auto' ? undefined : requestResolution[0],
|
||||
height: requestResolution === 'auto' ? undefined : requestResolution[1],
|
||||
frameRate: requestFramerate === 'auto' ? undefined : requestFramerate
|
||||
}
|
||||
})
|
||||
.then((stream) => {
|
||||
video.srcObject = stream;
|
||||
refreshDevices();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
async function takeSnapshot() {
|
||||
const canvas = document.createElement('canvas');
|
||||
|
@ -92,7 +100,7 @@
|
|||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
<button on:click={refreshDevices}>
|
||||
<button onclick={refreshDevices}>
|
||||
<i class="ti ti-refresh"></i>
|
||||
{$i18n.t('Refresh')}
|
||||
</button>
|
||||
|
@ -124,13 +132,13 @@
|
|||
</div>
|
||||
|
||||
<div class="display" class:snapshot={Boolean(snapshot)}>
|
||||
<!-- svelte-ignore a11y-media-has-caption -->
|
||||
<!-- svelte-ignore a11y_media_has_caption -->
|
||||
<video class:flipped bind:this={video} autoplay class:unloaded={!currentDevice}></video>
|
||||
{#if snapshot}
|
||||
<!-- svelte-ignore a11y-missing-attribute -->
|
||||
<!-- svelte-ignore a11y_missing_attribute -->
|
||||
<!--suppress HtmlRequiredAltAttribute -->
|
||||
<img src={snapshot} />
|
||||
<button on:click={() => (snapshot = undefined)}><i class="ti ti-x"></i></button>
|
||||
<button onclick={() => (snapshot = undefined)}><i class="ti ti-x"></i></button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
@ -149,11 +157,11 @@
|
|||
{/key}
|
||||
</ul>
|
||||
<div class="controls">
|
||||
<button on:click={takeSnapshot}>
|
||||
<button onclick={takeSnapshot}>
|
||||
<i class="ti ti-camera"></i>
|
||||
{$i18n.t('Take picture')}
|
||||
</button>
|
||||
<button on:click={() => (flipped = !flipped)}>
|
||||
<button onclick={() => (flipped = !flipped)}>
|
||||
<i class="ti ti-flip-vertical"></i>
|
||||
{#if flipped}
|
||||
{$i18n.t('Unflip image')}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { run } from 'svelte/legacy';
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
import { browser } from '$app/environment';
|
||||
import debug from 'debug';
|
||||
|
@ -6,10 +8,10 @@
|
|||
|
||||
const dbg = debug('app:camera');
|
||||
|
||||
let gamepads: Gamepad[] = [];
|
||||
let currentGamepad: Gamepad | undefined;
|
||||
let buttons: GamepadButton[] = [];
|
||||
let axes: number[] = [];
|
||||
let gamepads: Gamepad[] = $state([]);
|
||||
let currentGamepad: Gamepad | undefined = $state();
|
||||
let buttons: GamepadButton[] = $state([]);
|
||||
let axes: number[] = $state([]);
|
||||
|
||||
const axisHistory: number[][] = [];
|
||||
const sizes: [number, number][] = [];
|
||||
|
@ -58,17 +60,23 @@
|
|||
requestAnimationFrame(update);
|
||||
}
|
||||
|
||||
$: {
|
||||
run(() => {
|
||||
if (currentGamepad) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$: dbg('Gamepads %O', gamepads);
|
||||
$: dbg('Current gamepad %s', currentGamepad);
|
||||
run(() => {
|
||||
dbg('Gamepads %O', gamepads);
|
||||
});
|
||||
run(() => {
|
||||
dbg('Current gamepad %s', currentGamepad);
|
||||
});
|
||||
|
||||
$: currentGamepad?.vibrationActuator?.playEffect('dual-rumble', {
|
||||
duration: 1000
|
||||
run(() => {
|
||||
currentGamepad?.vibrationActuator?.playEffect('dual-rumble', {
|
||||
duration: 1000
|
||||
});
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
|
@ -105,7 +113,7 @@
|
|||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
<button on:click={refreshGamepads}>
|
||||
<button onclick={refreshGamepads}>
|
||||
<i class="ti ti-refresh"></i>
|
||||
{$i18n.t('Refresh')}
|
||||
</button>
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
import { onMount } from 'svelte';
|
||||
import { i18n } from '$lib/i18n';
|
||||
|
||||
let key: string;
|
||||
let code: string;
|
||||
let pressedKeys: string[] = [];
|
||||
let key: string = $state();
|
||||
let code: string = $state();
|
||||
let pressedKeys: string[] = $state([]);
|
||||
onMount(() => {
|
||||
document.addEventListener('keydown', (event) => {
|
||||
key = event.key;
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
import { onMount } from 'svelte';
|
||||
import { i18n } from '$lib/i18n';
|
||||
|
||||
let time = 0;
|
||||
let time = $state(0);
|
||||
let fps = 0;
|
||||
let start = 0;
|
||||
let displayFps = '?';
|
||||
let displayFps = $state('?');
|
||||
let fpsInterval: NodeJS.Timeout | undefined;
|
||||
|
||||
const times: number[] = [];
|
||||
|
@ -41,7 +41,7 @@
|
|||
<div class="time">{time}</div>
|
||||
<div class="fps">{displayFps} {$i18n.t('FPS')}</div>
|
||||
</div>
|
||||
<button on:click={restart}>{$i18n.t('Restart')}</button>
|
||||
<button onclick={restart}>{$i18n.t('Restart')}</button>
|
||||
|
||||
<style>
|
||||
div,
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
import '@tabler/icons-webfont/tabler-icons.css';
|
||||
import '../index.css';
|
||||
import { onMount } from 'svelte';
|
||||
interface Props {
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let { children }: Props = $props();
|
||||
|
||||
let idleTimeout: NodeJS.Timeout | undefined;
|
||||
onMount(() => {
|
||||
|
@ -20,7 +25,7 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
|
||||
<style>
|
||||
:global(.hide-idle) {
|
||||
|
|
Loading…
Add table
Reference in a new issue