|
26 | 26 | </template> |
27 | 27 |
|
28 | 28 | <script setup lang="ts"> |
29 | | - import { onClickOutside, useDraggable, useEventListener } from '@vueuse/core'; |
| 29 | + import { |
| 30 | + onClickOutside, |
| 31 | + type Position, |
| 32 | + useDraggable, |
| 33 | + useEventListener, |
| 34 | + useLocalStorage, |
| 35 | + } from '@vueuse/core'; |
30 | 36 | import { computed, type CSSProperties, ref } from 'vue'; |
31 | 37 |
|
32 | 38 | const handles = ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'] as const; |
|
38 | 44 | const headerRef = ref<HTMLDivElement>(); |
39 | 45 | const isActive = ref(false); |
40 | 46 | const isResizing = ref(false); |
41 | | - const width = ref(400); |
42 | | - const height = ref(300); |
| 47 | + const width = useLocalStorage('chat_windowWidth', 400); |
| 48 | + const height = useLocalStorage('chat_windowHeight', 300); |
| 49 | + const initialPosition = useLocalStorage<Position>( |
| 50 | + 'chat_windowPosition', |
| 51 | + { x: 0, y: 0 }, |
| 52 | + { mergeDefaults: true }, |
| 53 | + ); |
43 | 54 |
|
44 | 55 | onClickOutside(containerRef, () => { |
45 | 56 | isActive.value = false; |
46 | 57 | }); |
47 | 58 |
|
48 | 59 | const { x, y } = useDraggable(containerRef, { |
49 | | - initialValue: { x: 100, y: 100 }, |
| 60 | + initialValue: initialPosition, |
50 | 61 | handle: headerRef, |
| 62 | + onEnd(endPosition) { |
| 63 | + // Save position to localStorage |
| 64 | + Object.assign(initialPosition.value, endPosition); |
| 65 | + }, |
51 | 66 | }); |
52 | 67 |
|
53 | 68 | let currentHandle: Handle | null = null; |
|
116 | 131 | isResizing.value = false; |
117 | 132 | currentHandle = null; |
118 | 133 | positionStart = null; |
| 134 | + // Save position to localStorage |
| 135 | + initialPosition.value.x = x.value; |
| 136 | + initialPosition.value.y = y.value; |
119 | 137 | cleanupMove?.(); |
120 | 138 | cleanupEnd?.(); |
121 | 139 | } |
|
0 commit comments