Switch.svelte 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. <script lang="ts">
  2. import Loading from '../loading/Loading.svelte';
  3. import type { SwitchProps } from '../../types/index.js';
  4. let {
  5. active = $bindable(false),
  6. radius = 'middle',
  7. inside = null,
  8. injClass = '',
  9. disabled = false,
  10. async = false,
  11. loading = {},
  12. trueChild,
  13. falseChild,
  14. onchange,
  15. onclick
  16. }: SwitchProps = $props();
  17. // 是否处于纵向拉长状态 is in the vertical elongation state
  18. let isLong = $state(false);
  19. const radiusObj = { none: 'rounded-none', middle: 'rounded-sm', full: 'rounded-full' };
  20. const setChangeFun = () => {
  21. if (!disabled) {
  22. if (!async) {
  23. active = !active;
  24. onchange?.(active);
  25. }
  26. onclick?.();
  27. }
  28. };
  29. $effect(() => {
  30. if (!disabled) {
  31. active = active;
  32. isLong = true;
  33. setTimeout(() => {
  34. isLong = false;
  35. }, 150);
  36. }
  37. });
  38. </script>
  39. <button
  40. onclick={setChangeFun}
  41. class="relative flex h-6 w-12 justify-around transition-all duration-500 active:opacity-80 {radiusObj[radius] || radiusObj.middle} {active
  42. ? `bg-primary dark:bg-dark ${injClass}`
  43. : 'bg-black/10 dark:bg-white/20'} {disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}"
  44. >
  45. <div
  46. class="absolute top-0.5 h-5 w-5 bg-white text-center text-xs leading-5 text-black/80 transition-all duration-300 dark:bg-black dark:text-white/90 {radiusObj[
  47. radius
  48. ] || radiusObj.middle}"
  49. style="left:{active ? '1.625rem' : '0.125rem'};transform:{isLong ? 'scaleX(1.3)' : 'scaleX(1)'}"
  50. >
  51. {#if inside === 'state'}
  52. <span class:hidden={!active}><div class="ml-2 mt-1 h-3 w-1 rounded-full bg-black/80 dark:bg-white/90"></div></span>
  53. <span class:hidden={active}><div class="ml-1 mt-1 h-3 w-3 rounded-full border-2 border-black/80 dark:border-white/90"></div></span>
  54. {:else if inside === 'loading'}
  55. <div class="m-0.5">
  56. <Loading width="full" height="full" {...loading} />
  57. </div>
  58. {:else if trueChild && falseChild}
  59. <span class={active ? '' : 'hidden'}>{@render trueChild?.()}</span>
  60. <span class={!active ? '' : 'hidden'}>{@render falseChild?.()}</span>
  61. {:else if Array.isArray(inside) && inside.length === 2}
  62. <span class={active ? '' : 'hidden'}>{inside[1]} </span>
  63. <span class={!active ? '' : 'hidden'}>{inside[0]} </span>
  64. {:else}{/if}
  65. </div>
  66. </button>