blob: 8d8410c8a6123408b96804209c4d0acdaf62728f [file] [log] [blame]
<script lang="ts">
import { createBubbler, handlers } from 'svelte/legacy';
const bubble = createBubbler();
import { twMerge } from 'tailwind-merge';
let isMouseDown = $state(false);
interface Props {
checked?: boolean | undefined;
value: string;
id?: string;
name?: string | undefined;
bindGroup?: string[] | undefined;
disabled?: boolean;
onclick?: (e: Event) => void;
}
let {
checked = $bindable(undefined),
value,
id = '',
name = undefined,
bindGroup = $bindable(undefined),
disabled = false,
onclick
}: Props = $props();
function onChange(e: Event) {
const { value: checkboxValue, checked: checkboxChecked } = e.target as HTMLInputElement;
if (bindGroup) {
if (checkboxChecked) {
bindGroup = [...bindGroup, checkboxValue];
} else {
bindGroup = bindGroup.filter((item) => item !== value);
checked = checkboxChecked;
}
} else {
checked = checkboxChecked;
}
}
</script>
<div class="relative w-8 h-8">
<input
type="checkbox"
checked={bindGroup?.includes(value) || checked}
{name}
{value}
{id}
{disabled}
onchange={handlers(onChange, bubble('change'))}
onclick={onclick}
onmousedown={() => (isMouseDown = true)}
onmouseup={() => (isMouseDown = false)}
onmouseleave={() => (isMouseDown = false)}
onmouseout={() => (isMouseDown = false)}
onblur={() => (isMouseDown = false)}
/>
<div
role="checkbox"
tabindex="0"
aria-checked={checked}
class={twMerge(
'w-[18px] h-[18px] absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 border-neutral-300 border-2 rounded transition-all pointer-events-none',
isMouseDown && 'scale-90'
)}
></div>
<svg
class="w-[18px] h-[18px] pointer-events-none transition-all scale-75 opacity-0 absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
id="Vector"
d="M6 12L10.2426 16.2426L18.727 7.75732"
stroke-width="2.4"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</div>
<style lang="postcss">
input[type='checkbox'] {
@apply cursor-pointer appearance-none m-0 absolute inset-0;
}
input[type='checkbox'] + div {
@apply bg-shadeL100;
}
input[type='checkbox']:hover:not(:checked):not(:disabled) + div {
@apply border-neutral-400;
}
input[type='checkbox']:checked + div {
@apply bg-[#32AD84];
}
input[type='checkbox']:checked + div + svg {
@apply opacity-100 stroke-white;
}
input[type='checkbox']:checked:disabled + div {
@apply opacity-50;
}
input[type='checkbox']:disabled {
@apply cursor-not-allowed;
}
</style>