-
-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
I wanted to share a practical example of using reddojs in vue. The useHistory vue composable pacakge is a valid example but is not practical for a non-trivial app. I was going to put it in a PR but wasn't sure if it should just be docs or another vue helper import.
// my-app-history.ts
import type { History } from '@reddojs/core'
import { computed, ref } from 'vue'
// global history instance
let HISTORY: History | undefined
// global unsubscribe
let historyUnsub: (() => void) | undefined
const canUndoRef = ref(false)
const canRedoRef = ref(false)
// readonly
const canUndo = computed(() => canUndoRef.value)
const canRedo = computed(() => canRedoRef.value)
// can be used to call history.execute outside vue component context
export function getGlobalHistory(): History {
if (!HISTORY) {
throw new Error('Global History not set. Call setGlobalHistory()')
}
return HISTORY
}
export function setGlobalHistory(history: History) {
if (HISTORY) {
throw new Error('history already set')
}
HISTORY = history
canUndoRef.value = HISTORY.canUndo
canRedoRef.value = HISTORY.canRedo
historyUnsub = HISTORY.subscribe(() => {
canUndoRef.value = HISTORY!.canUndo
canRedoRef.value = HISTORY!.canRedo
})
return historyUnsub
}
// vue component context history helper
let VUE_HISTORY: VueHistory | undefined
export interface VueHistoryOptions {
undo?: (history: History) => void
redo?: (history: History) => void
}
export type VueHistory = ReturnType<typeof makeVueHistory>
function makeVueHistory(history: History, opts?: VueHistoryOptions) {
function dispose() {
historyUnsub?.()
history.clear()
HISTORY = undefined
VUE_HISTORY = undefined
canUndoRef.value = false
canRedoRef.value = false
}
const undo = opts?.undo ? () => opts.undo!(history) : () => history.undo()
const redo = opts?.redo ? () => opts.redo!(history) : () => history.redo()
return {
size: history.size,
subscribe: history.subscribe,
canUndo,
canRedo,
execute: history.execute,
undo,
redo,
clear: history.clear,
dispose,
}
}
export function useVueHistory(): VueHistory {
if (!VUE_HISTORY) {
throw new Error('VueHistory not booted. Call bootVueHistory()')
}
return VUE_HISTORY
}
export function bootVueHistory(opts?: VueHistoryOptions): VueHistory {
if (!VUE_HISTORY) {
VUE_HISTORY = makeVueHistory(getGlobalHistory(), opts)
}
return VUE_HISTORY
}Usage
// main.ts
import { createHistory } from '@reddojs/core/src'
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { setGlobalHistory } from './my-history.ts'
setGlobalHistory(createHistory({ size: 100, coalesce: true }))
createApp(App).mount('#app')
``
```vue
<script setup lang="ts">
// App.vue
import { bootVueHistory } from './my-history.ts'
const { execute, canRedo, canUndo, undo, redo } = bootVueHistory({
undo(history: History) {
if (!history.canUndo) {
// @TODO notify user in UI using in component context behavior
console.log('no undos left')
return
}
history.undo()
},
redo(history: History) {
if (!history.canRedo) {
// @TODO notify user in UI using in component context behavior
console.log('no redos left')
return
}
history.redo()
},
})
</script>
<template> ... </template><script setup lang="ts">
// OtherComponent.vue
// incase you need to access this stuff again
const { execute, canRedo, canUndo, undo, redo } = useVueHistory()
// anywhere in your code (in or out of component)
const { execute } = getGlobalHistory()Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels