|
<script lang="ts"> |
|
import { onMount } from "svelte"; |
|
|
|
export let position = 0.5; |
|
export let disabled = false; |
|
export let show_nav = true; |
|
|
|
let active = false; |
|
let hidden = true; |
|
let el: HTMLDivElement; |
|
let inner: HTMLDivElement; |
|
let box: DOMRect; |
|
let px = 0; |
|
let offset = 0; |
|
|
|
function handle_mousedown(e: MouseEvent) { |
|
if (disabled) return; |
|
active = true; |
|
box = el.getBoundingClientRect(); |
|
const innerbox = inner.getBoundingClientRect(); |
|
offset = e.clientX - innerbox.left; |
|
} |
|
|
|
function handle_mouseup(e: MouseEvent) { |
|
active = false; |
|
} |
|
|
|
function handle_mousemove(e: MouseEvent) { |
|
if (!active) return; |
|
px = clamp(e.clientX - offset - box.left, 100, box.width - 240); |
|
position = round((px + 10) / box.width, 5); |
|
} |
|
|
|
function clamp(n: number, min: number, max: number) { |
|
return n < min ? min : n > max ? max : n; |
|
} |
|
|
|
function round(n: number, points: number) { |
|
const mod = Math.pow(10, points); |
|
return Math.round((n + Number.EPSILON) * mod) / mod; |
|
} |
|
|
|
function set_position() { |
|
box = el.getBoundingClientRect(); |
|
px = box.width * position - 10; |
|
hidden = false; |
|
} |
|
|
|
onMount(set_position); |
|
|
|
$: if (!hidden && show_nav) { |
|
box = el.getBoundingClientRect(); |
|
px = box.width * position - 10; |
|
} else if (!hidden && !show_nav) { |
|
box = el.getBoundingClientRect(); |
|
px = box.width * position - 10; |
|
} |
|
</script> |
|
|
|
<svelte:window |
|
on:resize={set_position} |
|
on:mousemove={handle_mousemove} |
|
on:mouseup={handle_mouseup} |
|
/> |
|
|
|
<div class="wrap" bind:this={el}> |
|
<slot /> |
|
<div |
|
class="outer hidden sm:block" |
|
class:disabled |
|
on:mousedown={handle_mousedown} |
|
on:mouseup={handle_mouseup} |
|
bind:this={inner} |
|
role="none" |
|
style="transform: translateX({px}px)" |
|
> |
|
<div {hidden} class="inner"> |
|
<div class="notches text-gray-400 select-none">||</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<style> |
|
.wrap { |
|
position: relative; |
|
width: 100%; |
|
height: 100%; |
|
} |
|
|
|
.outer { |
|
width: 20px; |
|
height: 100%; |
|
position: absolute; |
|
cursor: grab; |
|
position: absolute; |
|
top: 0; |
|
left: 0; |
|
cursor: ew-resize; |
|
} |
|
|
|
.inner { |
|
width: 15px; |
|
height: 100%; |
|
background: #fbfcfc; |
|
position: absolute; |
|
left: calc((100% - 2px) / 2); |
|
border-right: 1px solid rgb(229, 231, 235); |
|
border-left: 1px solid rgb(229, 231, 235); |
|
} |
|
|
|
.disabled { |
|
cursor: auto; |
|
} |
|
|
|
.disabled .inner { |
|
box-shadow: none; |
|
} |
|
|
|
.notches { |
|
margin: 0; |
|
position: absolute; |
|
top: 50%; |
|
left: 50%; |
|
transform: translate(-50%, -50%) scale(1, 2.5); |
|
font-weight: bold; |
|
} |
|
</style> |
|
|