Skip to content

Commit

Permalink
Move sound control to header
Browse files Browse the repository at this point in the history
  • Loading branch information
mszula committed Jun 24, 2024
1 parent f27cb6c commit ab9a5e3
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 96 deletions.
16 changes: 3 additions & 13 deletions src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@
} from './lib/sort-algorithms/types';
import { arrayToSort, running } from './states';
import { soundStart, soundStop, type OscillatorType } from './lib/sound';
import SoundControl from './lib/components/SoundControl.svelte';
let selectedTheme = 'dim';
let size = 300;
let delay = 2;
let sound = true;
let bars: SortElement[];
let intervalRef: number;
let algorithm: AlgorithmDefinition & { instance: SortingGenerator };
Expand All @@ -45,7 +43,7 @@
reset();
}
$: {
$running && sound ? soundStart(size, oscillatorType) : soundStop();
$running && oscillatorType ? soundStart(size, oscillatorType) : soundStop();
}
$: {
window.clearInterval(intervalRef);
Expand Down Expand Up @@ -91,7 +89,7 @@
const next = algorithm.instance.next();
if (!next.done) {
sound && soundStart(size, oscillatorType);
oscillatorType && soundStart(size, oscillatorType);
updateBars($arrayToSort, next.value);
soundStop();
}
Expand All @@ -106,7 +104,7 @@
<main>
<div class="flex flex-col min-h-screen">
<div class="flex">
<Header bind:selectedTheme />
<Header bind:selectedTheme bind:oscillatorType />
</div>
<div class="flex-1 flex flex-col m-2 md:m-5">
<div id="bars-container" class="flex flex-grow min-h-80">
Expand Down Expand Up @@ -138,14 +136,6 @@
</div>
</div>
</div>
<div class="hidden md:divider md:divider-horizontal"></div>
<div
class="grid card bg-base-300 rounded-box place-items-center flex-grow w-full lg:max-w-80 p-5"
>
<div class="flex w-full justify-between items-center">
<SoundControl bind:sound bind:oscillatorType />
</div>
</div>
</div>
</div>
<Footer />
Expand Down
10 changes: 5 additions & 5 deletions src/lib/components/AlgorithmSelector.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script lang="ts">
import { onMount } from "svelte";
import { onMount } from 'svelte';
export let selectAlgorithm: (algo: AlgorithmDefinition) => void;
import { algorithms } from "../sort-algorithms/algorithms";
import type { AlgorithmDefinition } from "../sort-algorithms/types";
import { algorithms } from '../sort-algorithms/algorithms';
import type { AlgorithmDefinition } from '../sort-algorithms/types';
let selected = 0;
Expand All @@ -17,11 +17,11 @@
</script>

<div class="flex bg-base-200 rounded-box mb-2 md:mb-0 md:mr-5">
<ul class="menu menu-horizontal md:menu-vertical md:h-40">
<ul class="menu menu-horizontal md:menu-vertical xl:h-40">
{#each algorithms as algo, index}
<li>
<button
class={selected === index ? "active" : ""}
class={selected === index ? 'active' : ''}
on:click={click(index)}>{algo.name}</button
>
</li>
Expand Down
52 changes: 7 additions & 45 deletions src/lib/components/Header.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
<script lang="ts">
import themes from '../../../themes';
import HeaderSoundControl from './HeaderSoundControl.svelte';
import { type OscillatorType } from '../sound';
import HeaderThemeControl from './HeaderThemeControl.svelte';
export let selectedTheme: string;
const selectTheme = (
e: MouseEvent & {
currentTarget: EventTarget & HTMLButtonElement;
}
) => {
selectedTheme = e.currentTarget.dataset.setTheme || 'dim';
document.documentElement.setAttribute('data-theme', selectedTheme);
};
export let oscillatorType: OscillatorType;
</script>

<div class="navbar bg-base-100">
Expand All @@ -24,40 +17,9 @@
</a>
</div>
<div class="flex-none">
<ul class="menu menu-horizontal px-1">
<li>
<details>
<summary
><svg
class="w-[24px] h-[24px]"
aria-hidden="true"
fill="none"
viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.15 5.6h.01m3.337 1.913h.01m-6.979 0h.01M5.541 11h.01M15 15h2.706a1.957 1.957 0 0 0 1.883-1.325A9 9 0 1 0 2.043 11.89 9.1 9.1 0 0 0 7.2 19.1a8.62 8.62 0 0 0 3.769.9A2.013 2.013 0 0 0 13 18v-.857A2.034 2.034 0 0 1 15 15Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
</svg></summary
>
<ul class="p-2 bg-base-100 rounded-t-none z-10">
{#each themes as theme}
<li>
<button
data-act-class="btn-active"
data-set-theme={theme}
on:click={selectTheme}
>{theme.charAt(0).toUpperCase() + theme.slice(1)}</button
>
</li>
{/each}
</ul>
</details>
</li>
<ul class="menu menu-horizontal px-1 items-center">
<HeaderSoundControl bind:oscillatorType />
<HeaderThemeControl bind:selectedTheme />
</ul>

<a
Expand Down
87 changes: 87 additions & 0 deletions src/lib/components/HeaderSoundControl.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<script lang="ts">
import { customOscillatorTypes } from 'web-audio-oscillators';
import { type OscillatorType } from '../sound';
import { handleMenuOutsideClick } from './menu-outside-click-handler';
export let oscillatorType: OscillatorType;
const getOscillatorName = (osc: OscillatorType) => {
if (!osc) {
return 'None';
}
return (osc.charAt(0).toUpperCase() + osc.slice(1)).replace(
/([0-9])/g,
' $1'
);
};
let ref: HTMLDetailsElement;
</script>

<li>
<details bind:this={ref}>
<summary
class="w-40"
on:click|stopPropagation={handleMenuOutsideClick(ref, 'soundSelect')}
>
{#if oscillatorType}
<svg
class="w-[28px] h-[28px]"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15.5 8.43A4.985 4.985 0 0 1 17 12a4.984 4.984 0 0 1-1.43 3.5m2.794 2.864A8.972 8.972 0 0 0 21 12a8.972 8.972 0 0 0-2.636-6.364M12 6.135v11.73a1 1 0 0 1-1.64.768L6 15H4a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h2l4.36-3.633a1 1 0 0 1 1.64.768Z"
/>
</svg>
{:else}
<svg
class="w-[28px] h-[28px]"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15.5 8.43A4.985 4.985 0 0 1 17 12c0 1.126-.5 2.5-1.5 3.5m2.864-9.864A8.972 8.972 0 0 1 21 12c0 2.023-.5 4.5-2.5 6M7.8 7.5l2.56-2.133a1 1 0 0 1 1.64.768V12m0 4.5v1.365a1 1 0 0 1-1.64.768L6 15H4a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1m1-4 14 14"
/>
</svg>
{/if}
{oscillatorType ? getOscillatorName(oscillatorType) : 'None'}
</summary>
<ul class="p-2 bg-base-100 rounded-t-none z-10">
<li>
<button
class={!oscillatorType ? 'btn-active' : ''}
data-sound-select
on:click={() => (oscillatorType = null)}>None</button
>
</li>
{#each customOscillatorTypes as osc}
<li>
<button
class={osc === oscillatorType ? 'btn-active' : ''}
data-sound-select
on:click={() => {
oscillatorType = osc;
}}>{getOscillatorName(osc)}</button
>
</li>
{/each}
</ul>
</details>
</li>
52 changes: 52 additions & 0 deletions src/lib/components/HeaderThemeControl.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<script lang="ts">
import themes from '../../../themes';
import { handleMenuOutsideClick } from './menu-outside-click-handler';
export let selectedTheme: string;
let ref: HTMLDetailsElement;
const selectTheme = (
e: MouseEvent & {
currentTarget: EventTarget & HTMLButtonElement;
}
) => {
selectedTheme = e.currentTarget.dataset.setTheme || 'dim';
document.documentElement.setAttribute('data-theme', selectedTheme);
};
</script>

<li>
<details bind:this={ref}>
<summary on:click|stopPropagation={handleMenuOutsideClick(ref, 'setTheme')}
><svg
class="w-[24px] h-[24px]"
aria-hidden="true"
fill="none"
viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.15 5.6h.01m3.337 1.913h.01m-6.979 0h.01M5.541 11h.01M15 15h2.706a1.957 1.957 0 0 0 1.883-1.325A9 9 0 1 0 2.043 11.89 9.1 9.1 0 0 0 7.2 19.1a8.62 8.62 0 0 0 3.769.9A2.013 2.013 0 0 0 13 18v-.857A2.034 2.034 0 0 1 15 15Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
</svg></summary
>
<ul class="p-2 bg-base-100 rounded-t-none z-10">
{#each themes as theme}
<li>
<button
data-act-class="btn-active"
data-set-theme={theme}
on:click={selectTheme}
>{theme.charAt(0).toUpperCase() + theme.slice(1)}</button
>
</li>
{/each}
</ul>
</details>
</li>
31 changes: 0 additions & 31 deletions src/lib/components/SoundControl.svelte

This file was deleted.

15 changes: 15 additions & 0 deletions src/lib/components/menu-outside-click-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const handleMenuOutsideClick =
(ref: HTMLElement, datasetElement: string) => () => {
const close = (e: Event) => {
if (
e !== null &&
e.target instanceof HTMLElement &&
e.target.dataset &&
e.target.dataset[datasetElement] === undefined
) {
document.body.removeEventListener('click', close);
ref.removeAttribute('open');
}
};
document.body.addEventListener('click', close);
};
7 changes: 5 additions & 2 deletions src/lib/sound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
customOscillatorTypes,
} from 'web-audio-oscillators';

export type OscillatorType = (typeof customOscillatorTypes)[number];
export type OscillatorType = (typeof customOscillatorTypes)[number] | null;

const context = new AudioContext();

Expand All @@ -13,7 +13,10 @@ let freqStepSize = 0;
const maxFrequency = 1500;
const minFrequency = 10;

export const soundStart = (size: number, oscillatorName: OscillatorType) => {
export const soundStart = (
size: number,
oscillatorName: NonNullable<OscillatorType>
) => {
freqStepSize = maxFrequency / size;
if (oscillator) {
soundStop();
Expand Down

0 comments on commit ab9a5e3

Please sign in to comment.