⚡ (editor) Add Ctrl + z shortcut to undo changes in editor (#255)
Closes #217
This commit is contained in:
@@ -17,7 +17,7 @@ import {
|
|||||||
import { RightPanel, useEditor } from '../../providers/EditorProvider'
|
import { RightPanel, useEditor } from '../../providers/EditorProvider'
|
||||||
import { useTypebot } from '../../providers/TypebotProvider'
|
import { useTypebot } from '../../providers/TypebotProvider'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import React from 'react'
|
import React, { useState } from 'react'
|
||||||
import { isNotDefined } from 'utils'
|
import { isNotDefined } from 'utils'
|
||||||
import { EditableTypebotName } from './EditableTypebotName'
|
import { EditableTypebotName } from './EditableTypebotName'
|
||||||
import { getBubbleActions } from 'typebot-js'
|
import { getBubbleActions } from 'typebot-js'
|
||||||
@@ -27,6 +27,8 @@ import { headerHeight } from '../../constants'
|
|||||||
import { EditableEmojiOrImageIcon } from '@/components/EditableEmojiOrImageIcon'
|
import { EditableEmojiOrImageIcon } from '@/components/EditableEmojiOrImageIcon'
|
||||||
import { PublishButton } from '@/features/publish'
|
import { PublishButton } from '@/features/publish'
|
||||||
import { CollaborationMenuButton } from '@/features/collaboration'
|
import { CollaborationMenuButton } from '@/features/collaboration'
|
||||||
|
import { useUndoShortcut } from '@/hooks/useUndoShortcut'
|
||||||
|
import { useDebouncedCallback } from 'use-debounce'
|
||||||
|
|
||||||
export const TypebotHeader = () => {
|
export const TypebotHeader = () => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -41,6 +43,11 @@ export const TypebotHeader = () => {
|
|||||||
isSavingLoading,
|
isSavingLoading,
|
||||||
} = useTypebot()
|
} = useTypebot()
|
||||||
const { setRightPanel, rightPanel, setStartPreviewAtGroup } = useEditor()
|
const { setRightPanel, rightPanel, setStartPreviewAtGroup } = useEditor()
|
||||||
|
const [isUndoShortcutTooltipOpen, setUndoShortcutTooltipOpen] =
|
||||||
|
useState(false)
|
||||||
|
const hideUndoShortcutTooltipLater = useDebouncedCallback(() => {
|
||||||
|
setUndoShortcutTooltipOpen(false)
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
const handleNameSubmit = (name: string) => updateTypebot({ name })
|
const handleNameSubmit = (name: string) => updateTypebot({ name })
|
||||||
|
|
||||||
@@ -52,6 +59,14 @@ export const TypebotHeader = () => {
|
|||||||
setRightPanel(RightPanel.PREVIEW)
|
setRightPanel(RightPanel.PREVIEW)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useUndoShortcut(() => {
|
||||||
|
if (!canUndo) return
|
||||||
|
hideUndoShortcutTooltipLater.flush()
|
||||||
|
setUndoShortcutTooltipOpen(true)
|
||||||
|
hideUndoShortcutTooltipLater()
|
||||||
|
undo()
|
||||||
|
})
|
||||||
|
|
||||||
const handleHelpClick = () => {
|
const handleHelpClick = () => {
|
||||||
isCloudProdInstance
|
isCloudProdInstance
|
||||||
? getBubbleActions().open()
|
? getBubbleActions().open()
|
||||||
@@ -162,7 +177,11 @@ export const TypebotHeader = () => {
|
|||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
<HStack>
|
<HStack>
|
||||||
<Tooltip label="Undo">
|
<Tooltip
|
||||||
|
label={isUndoShortcutTooltipOpen ? 'Changes reverted!' : 'Undo'}
|
||||||
|
isOpen={isUndoShortcutTooltipOpen ? true : undefined}
|
||||||
|
hasArrow={isUndoShortcutTooltipOpen}
|
||||||
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
display={['none', 'flex']}
|
display={['none', 'flex']}
|
||||||
icon={<UndoIcon />}
|
icon={<UndoIcon />}
|
||||||
|
|||||||
18
apps/builder/src/hooks/useUndoShortcut.ts
Normal file
18
apps/builder/src/hooks/useUndoShortcut.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { useEventListener } from '@chakra-ui/react'
|
||||||
|
|
||||||
|
export const useUndoShortcut = (undo: () => void) => {
|
||||||
|
const isUndoShortcut = (event: KeyboardEvent) =>
|
||||||
|
(event.metaKey || event.ctrlKey) && event.key === 'z'
|
||||||
|
|
||||||
|
useEventListener('keydown', (event: KeyboardEvent) => {
|
||||||
|
const target = event.target as HTMLElement | null
|
||||||
|
const isTyping =
|
||||||
|
target?.role === 'textbox' ||
|
||||||
|
target instanceof HTMLTextAreaElement ||
|
||||||
|
target instanceof HTMLInputElement
|
||||||
|
if (isTyping) return
|
||||||
|
if (isUndoShortcut(event)) {
|
||||||
|
undo()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user