Skip to content

⬅️ Back to Table of Contents

📄 useManualRefHistory

📊 Analysis Summary

Metric Count
🔧 Functions 12
📦 Imports 8
🟢 Vue Composition API 3
📐 Interfaces 3
📑 Type Aliases 1

📚 Table of Contents

🛠️ File Location:

📂 packages/core/useManualRefHistory/index.ts

📦 Imports

Name Source
ComputedRef vue
Ref vue
CloneFn ../useCloned
timestamp @vueuse/shared
computed vue
deepRef vue
markRaw vue
cloneFnJSON ../useCloned

Vue Composition API

Name Type Reactive Variables Composables
computed computed none none
computed computed none none
computed computed none none

Functions

useManualRefHistory(source: Ref<Raw>, options: UseManualRefHistoryOptions<Raw, Seriali…): UseManualRefHistoryReturn<Raw, Serialized>

Track the change history of a ref, also provides undo and redo functionality.

Parameters:

  • source any: No description
  • options any: No description

See: https://vueuse.org/useManualRefHistory

Raw JSDoc
/**
 * Track the change history of a ref, also provides undo and redo functionality.
 *
 * @see https://vueuse.org/useManualRefHistory
 * @param source
 * @param options
 */

Calls:

  • defaultDump
  • defaultParse
  • markRaw (from vue)
  • dump
  • timestamp (from @vueuse/shared)
  • deepRef (from vue)
  • _createHistoryRecord
  • setSource
  • parse
  • undoStack.value.unshift
  • undoStack.value.splice
  • redoStack.value.splice
  • undoStack.value.shift
  • redoStack.value.unshift
  • _setSource
  • redoStack.value.shift
  • computed (from vue)
Code
export function useManualRefHistory<Raw, Serialized = Raw>(
  source: Ref<Raw>,
  options: UseManualRefHistoryOptions<Raw, Serialized> = {},
): UseManualRefHistoryReturn<Raw, Serialized> {
  const {
    clone = false,
    dump = defaultDump<Raw, Serialized>(clone),
    parse = defaultParse<Raw, Serialized>(clone),
    setSource = fnSetSource,
  } = options

  function _createHistoryRecord(): UseRefHistoryRecord<Serialized> {
    return markRaw({
      snapshot: dump(source.value),
      timestamp: timestamp(),
    })
  }

  const last: Ref<UseRefHistoryRecord<Serialized>> = deepRef(_createHistoryRecord()) as Ref<UseRefHistoryRecord<Serialized>>

  const undoStack: Ref<UseRefHistoryRecord<Serialized>[]> = deepRef([])
  const redoStack: Ref<UseRefHistoryRecord<Serialized>[]> = deepRef([])

  const _setSource = (record: UseRefHistoryRecord<Serialized>) => {
    setSource(source, parse(record.snapshot))
    last.value = record
  }

  const commit = () => {
    undoStack.value.unshift(last.value)
    last.value = _createHistoryRecord()

    if (options.capacity && undoStack.value.length > options.capacity)
      undoStack.value.splice(options.capacity, Number.POSITIVE_INFINITY)
    if (redoStack.value.length)
      redoStack.value.splice(0, redoStack.value.length)
  }

  const clear = () => {
    undoStack.value.splice(0, undoStack.value.length)
    redoStack.value.splice(0, redoStack.value.length)
  }

  const undo = () => {
    const state = undoStack.value.shift()

    if (state) {
      redoStack.value.unshift(last.value)
      _setSource(state)
    }
  }

  const redo = () => {
    const state = redoStack.value.shift()

    if (state) {
      undoStack.value.unshift(last.value)
      _setSource(state)
    }
  }

  const reset = () => {
    _setSource(last.value)
  }

  const history = computed(() => [last.value, ...undoStack.value])

  const canUndo = computed(() => undoStack.value.length > 0)
  const canRedo = computed(() => redoStack.value.length > 0)

  return {
    source,
    undoStack,
    redoStack,
    last,
    history,
    canUndo,
    canRedo,

    clear,
    commit,
    reset,
    undo,
    redo,
  }
}

fnBypass(v: F): T

Parameters:

  • v F

Returns: T

Code
function fnBypass<F, T>(v: F) {
  return v as unknown as T
}

fnSetSource(source: Ref<F>, value: F): F

Parameters:

  • source Ref<F>
  • value F

Returns: F

Code
function fnSetSource<F>(source: Ref<F>, value: F) {
  return source.value = value
}

defaultDump(clone: boolean | CloneFn<R>): FnCloneOrBypass<R, S>

Parameters:

  • clone boolean | CloneFn<R>

Returns: FnCloneOrBypass<R, S>

Code
function defaultDump<R, S>(clone?: boolean | CloneFn<R>) {
  return (clone
    ? typeof clone === 'function'
      ? clone
      : cloneFnJSON
    : fnBypass
  ) as unknown as FnCloneOrBypass<R, S>
}

defaultParse(clone: boolean | CloneFn<R>): FnCloneOrBypass<S, R>

Parameters:

  • clone boolean | CloneFn<R>

Returns: FnCloneOrBypass<S, R>

Code
function defaultParse<R, S>(clone?: boolean | CloneFn<R>) {
  return (clone
    ? typeof clone === 'function'
      ? clone
      : cloneFnJSON
    : fnBypass
  ) as unknown as FnCloneOrBypass<S, R>
}

Internal helpers

Declared inside another function in this file.

_createHistoryRecord(): UseRefHistoryRecord<Serialized>

Returns: UseRefHistoryRecord<Serialized>

Calls:

  • markRaw (from vue)
  • dump
  • timestamp (from @vueuse/shared)
Code
function _createHistoryRecord(): UseRefHistoryRecord<Serialized> {
    return markRaw({
      snapshot: dump(source.value),
      timestamp: timestamp(),
    })
  }

_setSource(record: UseRefHistoryRecord<Serialized>): void

Parameters:

  • record UseRefHistoryRecord<Serialized>

Returns: void

Calls:

  • setSource
  • parse
Code
(record: UseRefHistoryRecord<Serialized>) => {
    setSource(source, parse(record.snapshot))
    last.value = record
  }

commit(): void

Returns: void

Calls:

  • undoStack.value.unshift
  • _createHistoryRecord
  • undoStack.value.splice
  • redoStack.value.splice
Code
() => {
    undoStack.value.unshift(last.value)
    last.value = _createHistoryRecord()

    if (options.capacity && undoStack.value.length > options.capacity)
      undoStack.value.splice(options.capacity, Number.POSITIVE_INFINITY)
    if (redoStack.value.length)
      redoStack.value.splice(0, redoStack.value.length)
  }

clear(): void

Returns: void

Calls:

  • undoStack.value.splice
  • redoStack.value.splice
Code
() => {
    undoStack.value.splice(0, undoStack.value.length)
    redoStack.value.splice(0, redoStack.value.length)
  }

undo(): void

Returns: void

Calls:

  • undoStack.value.shift
  • redoStack.value.unshift
  • _setSource
Code
() => {
    const state = undoStack.value.shift()

    if (state) {
      redoStack.value.unshift(last.value)
      _setSource(state)
    }
  }

redo(): void

Returns: void

Calls:

  • redoStack.value.shift
  • undoStack.value.unshift
  • _setSource
Code
() => {
    const state = redoStack.value.shift()

    if (state) {
      undoStack.value.unshift(last.value)
      _setSource(state)
    }
  }

reset(): void

Returns: void

Calls:

  • _setSource
Code
() => {
    _setSource(last.value)
  }

Interfaces

UseRefHistoryRecord<T>

Interface Code
export interface UseRefHistoryRecord<T> {
  snapshot: T
  timestamp: number
}

Properties

Name Type Optional Description
snapshot T not shown
timestamp number not shown

UseManualRefHistoryOptions<Raw, Serialized = Raw>

Interface Code
export interface UseManualRefHistoryOptions<Raw, Serialized = Raw> {
  /**
   * Maximum number of history to be kept. Default to unlimited.
   */
  capacity?: number
  /**
   * Clone when taking a snapshot, shortcut for dump: JSON.parse(JSON.stringify(value)).
   * Default to false
   *
   * @default false
   */
  clone?: boolean | CloneFn<Raw>
  /**
   * Serialize data into the history
   */
  dump?: (v: Raw) => Serialized
  /**
   * Deserialize data from the history
   */
  parse?: (v: Serialized) => Raw

  /**
   * set data source
   */
  setSource?: (source: Ref<Raw>, v: Raw) => void
}

Properties

Name Type Optional Description
capacity number not shown
clone boolean \| CloneFn<Raw> not shown
dump (v: Raw) => Serialized not shown
parse (v: Serialized) => Raw not shown
setSource (source: Ref<Raw>, v: Raw) => void not shown

UseManualRefHistoryReturn<Raw, Serialized>

Interface Code
export interface UseManualRefHistoryReturn<Raw, Serialized> {
  /**
   * Bypassed tracking ref from the argument
   */
  source: Ref<Raw>

  /**
   * An array of history records for undo, newest comes to first
   */
  history: ComputedRef<UseRefHistoryRecord<Serialized>[]>

  /**
   * Last history point, source can be different if paused
   */
  last: Ref<UseRefHistoryRecord<Serialized>>

  /**
   * Same as {@link UseManualRefHistoryReturn.history | history}
   */
  undoStack: Ref<UseRefHistoryRecord<Serialized>[]>

  /**
   * Records array for redo
   */
  redoStack: Ref<UseRefHistoryRecord<Serialized>[]>

  /**
   * A ref representing if undo is possible (non empty undoStack)
   */
  canUndo: ComputedRef<boolean>

  /**
   * A ref representing if redo is possible (non empty redoStack)
   */
  canRedo: ComputedRef<boolean>

  /**
   * Undo changes
   */
  undo: () => void

  /**
   * Redo changes
   */
  redo: () => void

  /**
   * Clear all the history
   */
  clear: () => void

  /**
   * Create a new history record
   */
  commit: () => void

  /**
   * Reset ref's value with latest history
   */
  reset: () => void
}

Properties

Name Type Optional Description
source Ref<Raw> not shown
history ComputedRef<UseRefHistoryRecord<Serialized>[]> not shown
last Ref<UseRefHistoryRecord<Serialized>> not shown
undoStack Ref<UseRefHistoryRecord<Serialized>[]> not shown
redoStack Ref<UseRefHistoryRecord<Serialized>[]> not shown
canUndo ComputedRef<boolean> not shown
canRedo ComputedRef<boolean> not shown
undo () => void not shown
redo () => void not shown
clear () => void not shown
commit () => void not shown
reset () => void not shown

Type Aliases

FnCloneOrBypass<F, T>

type FnCloneOrBypass<F, T> = (v: F) => T;

Generated by Syntax Scribe