Drawer.svelte 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. <script lang="ts">
  2. import { onDestroy, onMount, createEventDispatcher } from 'svelte';
  3. import { flyAndScale } from '$lib/utils/transitions';
  4. import { fade, fly, slide } from 'svelte/transition';
  5. const dispatch = createEventDispatcher();
  6. export let show = false;
  7. export let size = 'md';
  8. let modalElement = null;
  9. let mounted = false;
  10. const sizeToWidth = (size) => {
  11. if (size === 'xs') {
  12. return 'w-[16rem]';
  13. } else if (size === 'sm') {
  14. return 'w-[30rem]';
  15. } else if (size === 'md') {
  16. return 'w-[48rem]';
  17. } else {
  18. return 'w-[56rem]';
  19. }
  20. };
  21. const handleKeyDown = (event: KeyboardEvent) => {
  22. if (event.key === 'Escape' && isTopModal()) {
  23. console.log('Escape');
  24. show = false;
  25. }
  26. };
  27. const isTopModal = () => {
  28. const modals = document.getElementsByClassName('modal');
  29. return modals.length && modals[modals.length - 1] === modalElement;
  30. };
  31. onMount(() => {
  32. mounted = true;
  33. });
  34. $: if (show && modalElement) {
  35. document.body.appendChild(modalElement);
  36. window.addEventListener('keydown', handleKeyDown);
  37. document.body.style.overflow = 'hidden';
  38. } else if (modalElement) {
  39. dispatch('close');
  40. window.removeEventListener('keydown', handleKeyDown);
  41. if (document.body.contains(modalElement)) {
  42. document.body.removeChild(modalElement);
  43. document.body.style.overflow = 'unset';
  44. }
  45. }
  46. onDestroy(() => {
  47. show = false;
  48. if (modalElement) {
  49. if (document.body.contains(modalElement)) {
  50. document.body.removeChild(modalElement);
  51. document.body.style.overflow = 'unset';
  52. }
  53. }
  54. });
  55. </script>
  56. <!-- svelte-ignore a11y-click-events-have-key-events -->
  57. <!-- svelte-ignore a11y-no-static-element-interactions -->
  58. <div
  59. bind:this={modalElement}
  60. class="modal fixed right-0 left-0 bottom-0 bg-black/60 w-full h-screen max-h-[100dvh] flex justify-center z-[9999] overflow-hidden overscroll-contain"
  61. in:fly={{ y: 100, duration: 100 }}
  62. on:mousedown={() => {
  63. show = false;
  64. }}
  65. >
  66. <div
  67. class=" mt-auto max-w-full w-full bg-gray-50 dark:bg-gray-900 max-h-[100dvh] overflow-y-auto scrollbar-hidden"
  68. on:mousedown={(e) => {
  69. e.stopPropagation();
  70. }}
  71. >
  72. <slot />
  73. </div>
  74. </div>
  75. <style>
  76. .modal-content {
  77. animation: scaleUp 0.1s ease-out forwards;
  78. }
  79. @keyframes scaleUp {
  80. from {
  81. transform: scale(0.985);
  82. opacity: 0;
  83. }
  84. to {
  85. transform: scale(1);
  86. opacity: 1;
  87. }
  88. }
  89. </style>