<template>
  <button
    type="button"
    class="vm-toggle-switch"
    :class="{ 'is-on': on, 'is-loading': loading }"
    role="switch"
    :aria-checked="on"
    :disabled="disabled || loading"
    @click="emit('update:modelValue', !on)"
  >
    <span class="vm-toggle-switch__knob" />
  </button>
</template>

<script setup lang="ts">
import { computed } from 'vue'

defineOptions({ name: 'vm-toggle-switch' })

const props = withDefaults(
  defineProps<{
    modelValue?: boolean | number | null
    activeValue?: number | boolean
    loading?: boolean
    disabled?: boolean
  }>(),
  {
    activeValue: 1,
    loading: false,
    disabled: false,
  },
)

const emit = defineEmits<{
  'update:modelValue': [v: boolean]
}>()

const on = computed(() => {
  const v = props.modelValue
  if (typeof props.activeValue === 'boolean') return Boolean(v)
  return Number(v) === Number(props.activeValue)
})
</script>

<style lang="scss" scoped>
.vm-toggle-switch {
  position: relative;
  width: 42px;
  height: 24px;
  flex-shrink: 0;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: color-mix(in srgb, var(--foreground) 18%, transparent);
  cursor: pointer;
  transition: background 0.15s ease;

  &.is-on {
    background: var(--brand);
  }

  &.is-loading,
  &:disabled {
    opacity: 0.6;
    cursor: not-allowed;
  }
}

.vm-toggle-switch__knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgb(0 0 0 / 20%);
  transition: transform 0.15s ease;

  .is-on > & {
    transform: translateX(18px);
  }
}
</style>
