63 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
			
		
		
	
	
			63 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
| import raf from '../../_util/raf';
 | |
| import type { Ref, UnwrapRef } from 'vue';
 | |
| import { onBeforeUnmount, ref, shallowRef } from 'vue';
 | |
| 
 | |
| export type Updater<State> = (prev: State) => State;
 | |
| 
 | |
| export function useLayoutState<State>(
 | |
|   defaultState: State,
 | |
| ): [Ref<State>, (updater: Updater<State>) => void] {
 | |
|   const stateRef = shallowRef<State>(defaultState);
 | |
|   let rafId: number;
 | |
|   const updateBatchRef = shallowRef<Updater<State>[]>([]);
 | |
|   function setFrameState(updater: Updater<State>) {
 | |
|     updateBatchRef.value.push(updater);
 | |
|     raf.cancel(rafId);
 | |
|     rafId = raf(() => {
 | |
|       const prevBatch = updateBatchRef.value;
 | |
|       // const prevState = stateRef.value;
 | |
|       updateBatchRef.value = [];
 | |
|       prevBatch.forEach(batchUpdater => {
 | |
|         stateRef.value = batchUpdater(stateRef.value as State);
 | |
|       });
 | |
|     });
 | |
|   }
 | |
|   onBeforeUnmount(() => {
 | |
|     raf.cancel(rafId);
 | |
|   });
 | |
| 
 | |
|   return [stateRef as Ref<State>, setFrameState];
 | |
| }
 | |
| 
 | |
| /** Lock frame, when frame pass reset the lock. */
 | |
| export function useTimeoutLock<State>(
 | |
|   defaultState?: State,
 | |
| ): [(state: UnwrapRef<State>) => void, () => UnwrapRef<State> | null] {
 | |
|   const frameRef = ref<State | null>(defaultState || null);
 | |
|   const timeoutRef = ref<any>();
 | |
| 
 | |
|   function cleanUp() {
 | |
|     clearTimeout(timeoutRef.value);
 | |
|   }
 | |
| 
 | |
|   function setState(newState: UnwrapRef<State>) {
 | |
|     frameRef.value = newState;
 | |
|     cleanUp();
 | |
| 
 | |
|     timeoutRef.value = setTimeout(() => {
 | |
|       frameRef.value = null;
 | |
|       timeoutRef.value = undefined;
 | |
|     }, 100);
 | |
|   }
 | |
| 
 | |
|   function getState() {
 | |
|     return frameRef.value;
 | |
|   }
 | |
| 
 | |
|   onBeforeUnmount(() => {
 | |
|     cleanUp();
 | |
|   });
 | |
| 
 | |
|   return [setState, getState];
 | |
| }
 |