cathode/src/components/bar.svelte

127 lines
2.8 KiB
Svelte

<script lang="ts">
import { draggable } from "@neodrag/svelte";
import { onMount } from "svelte";
import { tweened } from "svelte/motion";
import { sineIn, sineOut } from "svelte/easing";
// import { invoke } from "@tauri-apps/api";
export let progress = 0;
export let withSetpoint = false;
export let setpoint = 0;
export let onSetpointChange = (_: number) => {};
let bar: HTMLDivElement;
let point: HTMLDivElement;
let pos = { x: 0, y: 0 };
const tweenedProgress = tweened(0, { duration: 100, easing: sineOut });
onMount(async () => {
let rect = bar.getBoundingClientRect();
let prect = point.getBoundingClientRect();
pos.y = -(setpoint / 100) * rect.height + prect.height;
});
$: if (bar) {
let pxProgress = (progress / 100) * bar.getBoundingClientRect().height;
if (pxProgress > $tweenedProgress) {
tweenedProgress
.set(pxProgress, {
duration: 30,
easing: sineOut,
})
.then();
} else {
$tweenedProgress = pxProgress;
}
}
</script>
<svelte:window
on:resize={async () => {
// await invoke("log", {
// msg: `Resized`,
// });
pos = { x: 0, y: 0 };
let rect = bar.getBoundingClientRect();
let prect = point.getBoundingClientRect();
pos.y = -(setpoint / 100) * rect.height + prect.height;
}}
/>
<div class="box">
<div bind:this={bar} class="bar-container">
{#if withSetpoint}
<div
bind:this={point}
class="setpoint"
use:draggable={{
onDragStart: () => (pos = undefined),
handle: ".handle",
position: pos,
axis: "y",
bounds: "parent",
onDragEnd: (e) => {
let rect = bar.getBoundingClientRect();
let y = (e.domRect.y - rect.y + e.domRect.height / 2) / rect.height;
onSetpointChange(1.0 - y);
},
}}
>
<div class="handle" />
</div>
{/if}
<div class="bar" style="height: {$tweenedProgress}px;" />
</div>
<slot class="icon" />
</div>
<style lang="scss">
.box {
display: flex;
flex-direction: column;
align-items: center;
gap: 1vh;
:global(img) {
width: var(--bar-width, 5vh);
}
}
.setpoint {
position: absolute;
background-color: black;
width: var(--bar-width, 5vh);
height: 0.5vh;
.handle {
position: absolute;
border-top: 2vh solid transparent;
border-bottom: 2vh solid transparent;
border-left: 2vh solid var(--handle-color, forestgreen);
left: -2.2vh;
top: 50%;
transform: translateY(-50%);
}
}
.bar-container {
border-radius: var(--bar-radius, 0px);
display: flex;
flex-direction: column;
justify-content: flex-end;
background-color: white;
border: 2px solid black;
height: 80vh;
width: var(--bar-width, 5vh);
}
.bar {
border-radius: inherit;
user-select: none;
width: 100%;
border: 0;
margin: 0;
background-color: var(--bar-color, blue);
transition: background-color 0.1s;
}
</style>