vue#readonly TypeScript Examples

The following examples show how to use vue#readonly. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: useHash.ts    From vhook with MIT License 6 votes vote down vote up
export function useHash(): IHashResult {
  const state = ref(window.location.hash)

  const setHash = (hash: string) => {
    if (hash !== state.value) {
      window.location.hash = hash
    }
  }

  const onHashChange = () => {
    state.value = window.location.hash
  }
  useEvent('hashchange', onHashChange)
  return {
    hash: readonly(state),
    setHash
  }
}
Example #2
Source File: usePlocState.ts    From frontend-clean-architecture with MIT License 6 votes vote down vote up
export function usePlocState<S>(ploc: Ploc<S>): DeepReadonly<Ref<S>> {
    const state = ref(ploc.state) as Ref<S>;

    const stateSubscription = (newState: S) => {
        state.value = newState;
    };

    onMounted(() => {
        ploc.subscribe(stateSubscription);
    });

    onUnmounted(() => {
        ploc.unsubscribe(stateSubscription);
    });

    return readonly(state);
}
Example #3
Source File: useWindowScroll.ts    From vhook with MIT License 6 votes vote down vote up
export function useWindowScroll(delay = 200): IWindowScrollState {
  const x = ref(isClient ? window.scrollX : 0)
  const y = ref(isClient ? window.scrollY : 0)
  let cb = () => {
    x.value = window.scrollX
    y.value = window.scrollY
  }
  if (delay) {
    cb = throttle(delay, cb)
  }
  const [, clear] = useEvent('scroll', cb, {
    passive: true,
    capture: false
  })
  return {
    x: readonly(x),
    y: readonly(y),
    clear
  }
}
Example #4
Source File: useToggle.ts    From vhook with MIT License 6 votes vote down vote up
useToggle: IToggle = <
  T extends ToggleParamType = ToggleParamType,
  U extends ToggleParamType = ToggleParamType
> (
    defaultValue: T = false as T,
    reverseValue?: U
  ) => {
  const state = ref(defaultValue) as Ref<T | U>
  const reverseTo = (reverseValue === undefined ? !defaultValue : reverseValue) as T | U

  const toggle = (next?: T | U) => {
    if (next !== undefined) {
      state.value = next
    } else {
      state.value = state.value === defaultValue ? reverseTo : defaultValue
    }
  }
  const setDefault = () => {
    state.value = defaultValue
  }
  const setRight = () => {
    state.value = reverseTo
  }
  return {
    state: readonly(state),
    setDefault,
    setRight,
    toggle
  }
}
Example #5
Source File: useTimeout.ts    From vhook with MIT License 6 votes vote down vote up
export function useTimeout(delay = 1000, immediate = true): ITimeoutResult {
  const ready = ref(false)
  let timer: any
  const stop = () => {
    if (timer) {
      clearTimeout(timer)
      timer = null
    }
  }
  const initTimeout = () => {
    ready.value = false
    stop()
    timer = window.setTimeout(() => {
      ready.value = true
      timer = null
    }, delay)
  }
  immediate && initTimeout()

  tryOnUnmounted(() => {
    stop()
  })

  return {
    ready: readonly(ready),
    start: () => initTimeout(),
    stop
  }
}
Example #6
Source File: useStorage.ts    From vhook with MIT License 6 votes vote down vote up
export function useStorage<T>(key: string, val: T, storage: Storage = localStorage): IStorage<T> {
  const value = getDefaultValue(storage, key, val)
  const state: Ref<T | null> = ref(null)
  const setState = (val?: T) => {
    if (val === undefined) {
      storage.removeItem(key)
      state.value = null
    } else {
      storage.setItem(key, JSON.stringify(val))
      state.value = val
    }
  }
  setState(value)
  return [readonly(state), setState]
}
Example #7
Source File: useScroll.ts    From vhook with MIT License 6 votes vote down vote up
export function useScroll(target: string | Element | Ref<Element | null>, delay = 200): IScrollResult {
  const x = ref(0)
  const y = ref(0)
  let cb = () => {
    if (eventTarget.value) {
      x.value = ((eventTarget.value as unknown) as Element).scrollLeft
      y.value = ((eventTarget.value as unknown) as Element).scrollTop
    }
  }
  if (delay) {
    cb = throttle(delay, cb)
  }
  const [eventTarget, clear] = useEvent('scroll', cb, { capture: false, passive: true }, target)
  return [readonly(x), readonly(y), clear]
}
Example #8
Source File: useResize.ts    From vhook with MIT License 6 votes vote down vote up
export function useResize(handler: ResizeHandler | null = null, delay = 200): IResizeState {
  const width = ref(window.innerWidth)
  const height = ref(window.innerHeight)
  let cb: ResizeHandler = function (this: Window, e: WindowEventMap['resize']) {
    handler && handler.call(this, e)
    width.value = window.innerWidth
    height.value = window.innerHeight
  }
  if (delay) {
    cb = useDebounceFn(cb, delay)
  }
  useEvent('resize', cb)
  return {
    width: readonly(width),
    height: readonly(height)
  }
}
Example #9
Source File: use-os-theme.ts    From vooks with MIT License 6 votes vote down vote up
export default function useOsTheme (): Readonly<Ref<Theme | null>> {
  /* istanbul ignore next */
  if (process.env.NODE_ENV !== 'test' && !supportMatchMedia) {
    return readonly(osTheme)
  }
  if (process.env.NODE_ENV === 'test' && window.matchMedia === undefined) {
    return readonly(osTheme)
  }
  if (usedCount === 0) init()
  if (managable && (managable = hasInstance())) {
    onBeforeMount(() => {
      usedCount += 1
    })
    onBeforeUnmount(() => {
      usedCount -= 1
      if (usedCount === 0) clean()
    })
  }
  return readonly(osTheme)
}
Example #10
Source File: use-false-until-truthy.ts    From vooks with MIT License 6 votes vote down vote up
export default function useFalseUntilTruthy (originalRef: Ref<any>): Readonly<Ref<boolean>> {
  const currentRef = ref(!!(originalRef.value as boolean))
  if (currentRef.value) return readonly(currentRef)
  const stop = watch(originalRef, (value: any) => {
    if (value as boolean) {
      currentRef.value = true
      stop()
    }
  })
  return readonly(currentRef)
}
Example #11
Source File: use-clicked.ts    From vooks with MIT License 6 votes vote down vote up
export default function useClicked (timeout: number): Readonly<Ref<boolean>> {
  if (!isBrowser) return readonly(ref(false))
  const clickedRef = ref(false)
  let timerId: number | null = null
  function clearTimer (): void {
    if (timerId !== null) window.clearTimeout(timerId)
  }
  function clickedHandler (): void {
    clearTimer()
    clickedRef.value = true
    timerId = window.setTimeout(() => {
      clickedRef.value = false
    }, timeout)
  }
  if (usedCount === 0) {
    on('click', window, handleClick, true)
  }
  const setup = (): void => {
    usedCount += 1
    on('click', window, clickedHandler, true)
  }
  if (managable && (managable = hasInstance())) {
    onBeforeMount(setup)
    onBeforeUnmount(() => {
      usedCount -= 1
      if (usedCount === 0) {
        off('click', window, handleClick, true)
      }
      off('click', window, clickedHandler, true)
      clearTimer()
    })
  } else {
    setup()
  }
  return readonly(clickedRef)
}
Example #12
Source File: use-click-position.ts    From vooks with MIT License 6 votes vote down vote up
export default function useClickPosition (): Readonly<
Ref<MousePosition | null>
> {
  if (!isBrowser) return readonly(ref(null))
  if (usedCount === 0) on('click', document, clickHandler as any, true)
  const setup = (): void => {
    usedCount += 1
  }
  if (managable && (managable = hasInstance())) {
    onBeforeMount(setup)
    onBeforeUnmount(() => {
      usedCount -= 1
      if (usedCount === 0) off('click', document, clickHandler as any, true)
    })
  } else {
    setup()
  }
  return readonly(mousePositionRef)
}
Example #13
Source File: useResize.ts    From jz-gantt with MIT License 5 votes vote down vote up
/**
 * 悬停按钮的定位方法
 */
export function useBtnPosition() {
  const size = ref(30);
  const top = ref(size.value * 2);
  const right = ref(-size.value / 2);

  const opBtnStyle = computed(() => {
    return {
      position: ' absolute',
      right: `${right.value}px`,
      top: `${top.value}px`,
      zIndex: 99
    };
  });

  const originPosition = ref<null | number>(null);
  function onOpBtnMouseLeave() {
    if (isNumber(originPosition.value)) {
      right.value = originPosition.value;
    }
  }

  function onOpBtnMouseEnter() {
    if (right.value >= 0) {
      originPosition.value = null;
      return;
    }

    originPosition.value = right.value;
    right.value = 0;
  }

  return {
    btnSize: readonly(size),
    opBtnStyle,
    onOpBtnMouseLeave,
    onOpBtnMouseEnter
  };
}
Example #14
Source File: use-is-mounted.ts    From vooks with MIT License 5 votes vote down vote up
export default function isMounted (): Readonly<Ref<boolean>> {
  const isMounted = ref(false)
  onMounted(() => { isMounted.value = true })
  return readonly(isMounted)
}
Example #15
Source File: use-state.ts    From fect with MIT License 5 votes vote down vote up
useState = <T>(initial?: T) => {
  const state = ref<T | undefined>(initial)
  const dispatch = (next: SetStateAction<T>) => {
    const draft = typeof next === 'function' ? (next as (prevState: T) => T)(state.value as T) : next
    state.value = draft as UnwrapRef<T>
  }
  return [readonly(state), dispatch] as [DeepReadonly<Ref<T>>, Dispatch<T>]
}
Example #16
Source File: use-theme.ts    From fect with MIT License 5 votes vote down vote up
useTheme = () => {
  const themes = [THEMES.LIGHT, THEMES.DARK]

  const getClientTheme = () => {
    const storageTheme = localStorage.getItem(THEME_STORAGE_KEY)
    if (storageTheme) return storageTheme === THEMES.DARK ? THEMES.DARK : THEMES.LIGHT
    if (window.matchMedia(DARK_THEME_QUERY).matches) return THEMES.DARK
    if (window.matchMedia(LIGHT_THEME_QUERY).matches) return THEMES.LIGHT
    return THEMES.LIGHT
  }

  const set = (newTheme: Theme) => {
    if (themes.includes(newTheme) && newTheme !== theme.value) {
      theme.value = newTheme
    }
  }

  const themeChange = () => {
    const nextTheme = theme.value === THEMES.DARK ? THEMES.LIGHT : THEMES.DARK
    set(nextTheme)
  }

  onMounted(() => {
    if (typeof window === 'undefined' || !window.localStorage) return
    const theme = getClientTheme()
    set(theme)
  })

  watch(theme, (cur) => {
    if (typeof window === 'undefined' || !window.localStorage) return
    if (!cur) return
    localStorage.setItem('theme', cur)
    const root = document.querySelector('html') as HTMLElement
    root.setAttribute('class', cur)
  })

  return {
    themeChange,
    theme: readonly(theme)
  }
}
Example #17
Source File: use-keyboard.ts    From vooks with MIT License 4 votes vote down vote up
export default function useKeyboard (
  options: useKeyboardOptions = {},
  enabledRef?: Ref<boolean>
): Readonly<UseKeyboardState> {
  const state = reactive<UseKeyboardState>({
    ctrl: false,
    command: false,
    win: false,
    shift: false,
    tab: false
  })
  const {
    keydown,
    keyup
  } = options
  const keydownHandler = (e: KeyboardEvent): void => {
    switch (e.key) {
      case 'Control':
        state.ctrl = true
        break
      case 'Meta':
        state.command = true
        state.win = true
        break
      case 'Shift':
        state.shift = true
        break
      case 'Tab':
        state.tab = true
        break
    }
    if (keydown !== undefined) {
      Object.keys(keydown).forEach(key => {
        if (key !== e.key) return
        const handler = keydown[key]
        if (typeof handler === 'function') {
          handler(e)
        } else {
          const { stop = false, prevent = false } = handler
          if (stop) e.stopPropagation()
          if (prevent) e.preventDefault()
          handler.handler(e)
        }
      })
    }
  }
  const keyupHandler = (e: KeyboardEvent): void => {
    switch (e.key) {
      case 'Control':
        state.ctrl = false
        break
      case 'Meta':
        state.command = false
        state.win = false
        break
      case 'Shift':
        state.shift = false
        break
      case 'Tab':
        state.tab = false
        break
    }
    if (keyup !== undefined) {
      Object.keys(keyup).forEach(key => {
        if (key !== e.key) return
        const handler = keyup[key]
        if (typeof handler === 'function') {
          handler(e)
        } else {
          const { stop = false, prevent = false } = handler
          if (stop) e.stopPropagation()
          if (prevent) e.preventDefault()
          handler.handler(e)
        }
      })
    }
  }
  const setup = (): void => {
    if (enabledRef === undefined || enabledRef.value) {
      on('keydown', document, keydownHandler)
      on('keyup', document, keyupHandler)
    }
    if (enabledRef !== undefined) {
      watch(enabledRef, value => {
        if (value) {
          on('keydown', document, keydownHandler)
          on('keyup', document, keyupHandler)
        } else {
          off('keydown', document, keydownHandler)
          off('keyup', document, keyupHandler)
        }
      })
    }
  }
  if (hasInstance()) {
    onBeforeMount(setup)
    onBeforeUnmount(() => {
      if (enabledRef === undefined || enabledRef.value) {
        off('keydown', document, keydownHandler)
        off('keyup', document, keyupHandler)
      }
    })
  } else {
    setup()
  }
  return readonly(state)
}
Example #18
Source File: document.ts    From quantum-sheet with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Create a document
 * @param elementTypes Element types in the document
 */
export function useDocument<TElements extends QuantumDocumentElementTypes<readonly QuantumElementType[]>>(
  elementTypes: TElements
): UseQuantumDocument<TElements> {
  const options = reactive<DocumentOptions>({
    gridCellSize: readonly(new Vector2(20, 20)),
    paperStyle: 'standard',
    paperSize: 'A4',
  })

  const elementRemoveCallbacks = new Map<string, () => void>()
  const elementList = useElementList()
  const elementSelection = useElementSelection()
  const elementFocus = useElementFocus()

  // TODO: Prevent this from being moved
  const rootScope = createElement(ScopeElementType.typeName, {
    position: Vector2.zero,
    size: Vector2.zero,
  })

  function addElement<T extends QuantumElement>(element: T): T {
    // TODO: I think we can use the effectScope API here https://github.com/vuejs/rfcs/blob/master/active-rfcs/0041-reactivity-effect-scope.md
    // (Replacing the stopHandles)

    let stopHandles = [elementList.watchElement(element), elementSelection.watchElement(element), elementFocus.watchElement(element)]
    elementRemoveCallbacks.set(element.id, () => {
      stopHandles.forEach((stopHandle) => stopHandle())
    })

    return element
  }

  function createElement<T extends keyof TElements>(typeName: T, options: QuantumElementCreationOptions): GetQuantumElement<TElements[T]> {
    let elementType = elementTypes[typeName]
    if (!elementType) throw new Error(`Unknown element type ${typeName}`)

    const element = new elementType.elementType(options)
    //elementType.useElement(useQuantumElement('' + typeName, options)) as ReturnType<TElements[T]['useElement']>
    addElement(element)

    return element as any
  }

  function deleteElement(element: QuantumElement) {
    let removeCallback = elementRemoveCallbacks.get(element.id)
    if (removeCallback) {
      removeCallback()
      elementRemoveCallbacks.delete(element.id)
    }
  }

  function getElementById<T extends keyof TElements>(id: string, typeName?: T): GetQuantumElement<TElements[T]> | undefined {
    let element = elementList.elements.find((e: QuantumElement) => e.id == id)
    if (element && typeName && element.typeName != typeName) {
      throw new Error(`Wrong type, passed ${typeName} but element has ${element.typeName}`)
    }

    // Yeah, Typescript really does dislike this XD
    return element as any
  }

  function getElementsByType<T extends keyof TElements>(typeName: T): GetQuantumElement<TElements[T]>[] | undefined {
    let elements = elementList.elements.filter((e: QuantumElement) => e.typeName == typeName)

    // Yeah, Typescript really does dislike this XD
    return elements as any[]
  }

  function serializeDocument() {
    let serializedData: SerializedDocument = {
      version: pkg.version,
      options: serializeOptions(options),
      elements: [],
    }
    elementList.elements.forEach((element: QuantumElement) => {
      let elementType = elementTypes[element.typeName]
      serializedData.elements.push(elementType.serializeElement(element))
    })
    return serializedData
  }

  function deserializeDocument(serializedData: SerializedDocument) {
    if (serializedData?.options) {
      const deserializedOptions = deserializeOptions(serializedData?.options)
      options.gridCellSize = deserializedOptions.gridCellSize ?? options.gridCellSize
      options.paperStyle = deserializedOptions.paperStyle ?? options.paperStyle
      options.paperSize = deserializedOptions.paperSize ?? options.paperSize
    }
    serializedData?.elements?.forEach((elementData: JsonType) => {
      let elementType = elementTypes[(elementData as any).typeName]
      if (!elementType) {
        console.warn('Element is missing its type', elementData)
      }
      const { element, onAddedCallback } = elementType.deserializeElement(elementData)
      addElement(element)
      onAddedCallback()
    })
  }

  function moveElements(elements: QuantumElement[], delta: Vector2, limit?: Vector2) {
    // TODO: dont let it move outside sheet (thus no longer needing 'interact.modifiers.restrict'?)
    let limited = false
    elements.forEach((element: QuantumElement) => {
      let newPos = element?.position.value.add(delta)
      if (limit) {
        if (
          newPos.x < 0 ||
          newPos.y < 0 ||
          limit.subtract(newPos.add(element.size.value)).x < 0 ||
          limit.subtract(newPos.add(element.size.value)).y < 0
        ) {
          limited = true
        }
      }
    })
    if (limited) return
    elements.forEach((element: QuantumElement) => {
      let newPos = element?.position.value.add(delta)
      if (newPos) element?.setPosition(newPos)
    })
  }

  function moveSelectedElements(delta: Vector2, limit?: Vector2) {
    moveElements(elementSelection.selectedElements, delta, limit)
  }

  return {
    options,
    elementTypes: elementTypes,
    elements: elementList.elements,
    createElement,
    deleteElement,
    getElementAt: elementList.getElementAt,
    getElementById,
    getSelection: () => [...elementSelection.selectedElements],
    setSelection: elementSelection.setSelection,
    setFocus: elementFocus.setFocus,
    moveElements,
    moveSelectedElements,

    serializeDocument,
    deserializeDocument,
  }
}