mirror of
				https://github.com/crater-invoice/crater.git
				synced 2025-11-04 06:23:17 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			144 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
<template>
 | 
						|
  <Teleport to="body">
 | 
						|
    <TransitionRoot appear as="template" :show="show">
 | 
						|
      <Dialog
 | 
						|
        as="div"
 | 
						|
        static
 | 
						|
        class="fixed inset-0 z-20 overflow-y-auto"
 | 
						|
        :open="show"
 | 
						|
        @close="$emit('close')"
 | 
						|
      >
 | 
						|
        <div
 | 
						|
          class="
 | 
						|
            flex
 | 
						|
            items-end
 | 
						|
            justify-center
 | 
						|
            min-h-screen min-h-screen-ios
 | 
						|
            px-4
 | 
						|
            text-center
 | 
						|
            sm:block sm:px-2
 | 
						|
          "
 | 
						|
        >
 | 
						|
          <TransitionChild
 | 
						|
            as="template"
 | 
						|
            enter="ease-out duration-300"
 | 
						|
            enter-from="opacity-0"
 | 
						|
            enter-to="opacity-100"
 | 
						|
            leave="ease-in duration-200"
 | 
						|
            leave-from="opacity-100"
 | 
						|
            leave-to="opacity-0"
 | 
						|
          >
 | 
						|
            <DialogOverlay
 | 
						|
              class="fixed inset-0 transition-opacity bg-gray-700 bg-opacity-25"
 | 
						|
            />
 | 
						|
          </TransitionChild>
 | 
						|
 | 
						|
          <!-- This element is to trick the browser into centering the modal contents. -->
 | 
						|
          <span
 | 
						|
            class="
 | 
						|
              hidden
 | 
						|
              sm:inline-block sm:align-middle sm:h-screen sm:h-screen-ios
 | 
						|
            "
 | 
						|
            aria-hidden="true"
 | 
						|
            >​</span
 | 
						|
          >
 | 
						|
          <TransitionChild
 | 
						|
            as="template"
 | 
						|
            enter="ease-out duration-300"
 | 
						|
            enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
 | 
						|
            enter-to="opacity-100 translate-y-0 sm:scale-100"
 | 
						|
            leave="ease-in duration-200"
 | 
						|
            leave-from="opacity-100 translate-y-0 sm:scale-100"
 | 
						|
            leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
 | 
						|
          >
 | 
						|
            <div
 | 
						|
              :class="`inline-block
 | 
						|
              align-middle
 | 
						|
              bg-white
 | 
						|
              rounded-lg
 | 
						|
              text-left
 | 
						|
              overflow-hidden
 | 
						|
              shadow-xl
 | 
						|
              transform
 | 
						|
              transition-all
 | 
						|
              my-4
 | 
						|
              ${modalSize}
 | 
						|
              sm:w-full
 | 
						|
              border-t-8 border-solid rounded shadow-xl  border-primary-500`"
 | 
						|
            >
 | 
						|
              <div
 | 
						|
                v-if="hasHeaderSlot"
 | 
						|
                class="
 | 
						|
                  flex
 | 
						|
                  items-center
 | 
						|
                  justify-between
 | 
						|
                  px-6
 | 
						|
                  py-4
 | 
						|
                  text-lg
 | 
						|
                  font-medium
 | 
						|
                  text-black
 | 
						|
                  border-b border-gray-200 border-solid
 | 
						|
                "
 | 
						|
              >
 | 
						|
                <slot name="header" />
 | 
						|
              </div>
 | 
						|
 | 
						|
              <slot />
 | 
						|
 | 
						|
              <slot name="footer" />
 | 
						|
            </div>
 | 
						|
          </TransitionChild>
 | 
						|
        </div>
 | 
						|
      </Dialog>
 | 
						|
    </TransitionRoot>
 | 
						|
  </Teleport>
 | 
						|
</template>
 | 
						|
 | 
						|
<script setup>
 | 
						|
import { useModalStore } from '@/scripts/stores/modal'
 | 
						|
import { computed, watchEffect, useSlots } from 'vue'
 | 
						|
import {
 | 
						|
  Dialog,
 | 
						|
  DialogOverlay,
 | 
						|
  TransitionChild,
 | 
						|
  TransitionRoot,
 | 
						|
} from '@headlessui/vue'
 | 
						|
 | 
						|
const props = defineProps({
 | 
						|
  show: {
 | 
						|
    type: Boolean,
 | 
						|
    default: false,
 | 
						|
  },
 | 
						|
})
 | 
						|
const slots = useSlots()
 | 
						|
 | 
						|
const emit = defineEmits(['close', 'open'])
 | 
						|
 | 
						|
const modalStore = useModalStore()
 | 
						|
 | 
						|
watchEffect(() => {
 | 
						|
  if (props.show) {
 | 
						|
    emit('open', props.show)
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
const modalSize = computed(() => {
 | 
						|
  const size = modalStore.size
 | 
						|
  switch (size) {
 | 
						|
    case 'sm':
 | 
						|
      return 'sm:max-w-2xl w-full'
 | 
						|
    case 'md':
 | 
						|
      return 'sm:max-w-4xl w-full'
 | 
						|
    case 'lg':
 | 
						|
      return 'sm:max-w-6xl w-full'
 | 
						|
 | 
						|
    default:
 | 
						|
      return 'sm:max-w-2xl w-full'
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
const hasHeaderSlot = computed(() => {
 | 
						|
  return !!slots.header
 | 
						|
})
 | 
						|
</script>
 |