mirror of https://github.com/docusealco/docuseal
				
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							140 lines
						
					
					
						
							3.5 KiB
						
					
					
				
			
		
		
	
	
							140 lines
						
					
					
						
							3.5 KiB
						
					
					
				| <template>
 | |
|   <div
 | |
|     class="absolute overflow-visible group"
 | |
|     :style="positionStyle"
 | |
|     @pointerdown.stop
 | |
|     @mousedown.stop="startDrag"
 | |
|   >
 | |
|     <div
 | |
|       v-if="field"
 | |
|       class="absolute bg-white rounded-t border overflow-visible whitespace-nowrap hidden group-hover:block group-hover:z-10"
 | |
|       style="top: -25px; height: 25px"
 | |
|       @mousedown.stop
 | |
|       @pointerdown.stop
 | |
|     >
 | |
|       <button
 | |
|         v-for="(component, type, index) in iconComponents"
 | |
|         :key="type"
 | |
|         class="px-0.5 hover:text-base-100 hover:bg-base-content transition-colors"
 | |
|         :class="{ 'bg-base-content text-base-100': field.type === type, 'rounded-tl': index === 0, 'rounded-tr': index === 4 }"
 | |
|         @click="changeTypeTo(type)"
 | |
|       >
 | |
|         <component
 | |
|           :is="component"
 | |
|           :width="20"
 | |
|           stroke-width="1.5"
 | |
|         />
 | |
|       </button>
 | |
|     </div>
 | |
|     <div
 | |
|       class="bg-red-100 opacity-70 flex items-center justify-center h-full w-full"
 | |
|     >
 | |
|       {{ field?.name || field?.type }}
 | |
|     </div>
 | |
|     <span
 | |
|       class="h-2 w-2 right-0 bottom-0 bg-red-900 absolute cursor-nwse-resize"
 | |
|       @mousedown.stop="startResize"
 | |
|     />
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import { IconTextSize, IconWriting, IconCalendarEvent, IconPhoto, IconCheckbox } from '@tabler/icons-vue'
 | |
| 
 | |
| export default {
 | |
|   name: 'FieldArea',
 | |
|   props: {
 | |
|     bounds: {
 | |
|       type: Object,
 | |
|       required: false,
 | |
|       default () {
 | |
|         return {
 | |
|           x: 0,
 | |
|           y: 0,
 | |
|           w: 0,
 | |
|           h: 0
 | |
|         }
 | |
|       }
 | |
|     },
 | |
|     field: {
 | |
|       type: Object,
 | |
|       required: false,
 | |
|       default: null
 | |
|     }
 | |
|   },
 | |
|   emits: ['start-resize', 'stop-resize', 'start-drag', 'stop-drag'],
 | |
|   data () {
 | |
|     return {
 | |
|       isResize: false,
 | |
|       dragFrom: { x: 0, y: 0 }
 | |
|     }
 | |
|   },
 | |
|   computed: {
 | |
|     iconComponents () {
 | |
|       return {
 | |
|         text: IconTextSize,
 | |
|         signature: IconWriting,
 | |
|         date: IconCalendarEvent,
 | |
|         image: IconPhoto,
 | |
|         checkbox: IconCheckbox
 | |
|       }
 | |
|     },
 | |
|     positionStyle () {
 | |
|       const { x, y, w, h } = this.bounds
 | |
| 
 | |
|       return {
 | |
|         top: y * 100 + '%',
 | |
|         left: x * 100 + '%',
 | |
|         width: w * 100 + '%',
 | |
|         height: h * 100 + '%'
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   methods: {
 | |
|     changeTypeTo (type) {
 | |
|       this.field.type = type
 | |
|     },
 | |
|     resize (e) {
 | |
|       if (e.toElement.id === 'mask') {
 | |
|         this.bounds.w = e.layerX / e.toElement.clientWidth - this.bounds.x
 | |
|         this.bounds.h = e.layerY / e.toElement.clientHeight - this.bounds.y
 | |
|       }
 | |
|     },
 | |
|     drag (e) {
 | |
|       if (e.toElement.id === 'mask') {
 | |
|         this.bounds.x = (e.layerX - this.dragFrom.x) / e.toElement.clientWidth
 | |
|         this.bounds.y = (e.layerY - this.dragFrom.y) / e.toElement.clientHeight
 | |
|       }
 | |
|     },
 | |
|     startDrag (e) {
 | |
|       const rect = e.target.getBoundingClientRect()
 | |
| 
 | |
|       this.dragFrom = { x: e.clientX - rect.left, y: e.clientY - rect.top }
 | |
| 
 | |
|       document.addEventListener('mousemove', this.drag)
 | |
|       document.addEventListener('mouseup', this.stopDrag)
 | |
| 
 | |
|       this.$emit('start-drag')
 | |
|     },
 | |
|     stopDrag () {
 | |
|       document.removeEventListener('mousemove', this.drag)
 | |
|       document.removeEventListener('mouseup', this.stopDrag)
 | |
| 
 | |
|       this.$emit('stop-drag')
 | |
|     },
 | |
|     startResize () {
 | |
|       document.addEventListener('mousemove', this.resize)
 | |
|       document.addEventListener('mouseup', this.stopResize)
 | |
| 
 | |
|       this.$emit('start-resize')
 | |
|     },
 | |
|     stopResize () {
 | |
|       document.removeEventListener('mousemove', this.resize)
 | |
|       document.removeEventListener('mouseup', this.stopResize)
 | |
| 
 | |
|       this.$emit('stop-resize')
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </script>
 |