mirror of https://github.com/langgenius/dify.git
feat: modify shortcutsplugin
This commit is contained in:
parent
a9ea8cfd1c
commit
465e978209
|
|
@ -56,7 +56,7 @@ import { VariableValueBlockNode } from './plugins/variable-value-block/node'
|
|||
import { CustomTextNode } from './plugins/custom-text/node'
|
||||
import OnBlurBlock from './plugins/on-blur-or-focus-block'
|
||||
import UpdateBlock from './plugins/update-block'
|
||||
import ShortcutsPopupPlugin from './plugins/shortcuts-popup-plugin'
|
||||
import ShortcutsPopupPlugin, { type Hotkey } from './plugins/shortcuts-popup-plugin'
|
||||
import { textToEditorState } from './utils'
|
||||
import type {
|
||||
ContextBlockType,
|
||||
|
|
@ -97,6 +97,7 @@ export type PromptEditorProps = {
|
|||
workflowVariableBlock?: WorkflowVariableBlockType
|
||||
hitlInputBlock?: HITLInputBlockType
|
||||
isSupportFileVar?: boolean
|
||||
shortcutPopups?: Array<{ hotkey: Hotkey; Popup: React.ComponentType<{ onClose: () => void }> }>
|
||||
}
|
||||
|
||||
const PromptEditor: FC<PromptEditorProps> = ({
|
||||
|
|
@ -121,6 +122,7 @@ const PromptEditor: FC<PromptEditorProps> = ({
|
|||
workflowVariableBlock,
|
||||
hitlInputBlock,
|
||||
isSupportFileVar,
|
||||
shortcutPopups = [],
|
||||
}) => {
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
const initialConfig = {
|
||||
|
|
@ -197,22 +199,11 @@ const PromptEditor: FC<PromptEditorProps> = ({
|
|||
}
|
||||
ErrorBoundary={LexicalErrorBoundary}
|
||||
/>
|
||||
<ShortcutsPopupPlugin>
|
||||
{closePortal => (
|
||||
<div>
|
||||
<div>test content</div>
|
||||
<button
|
||||
className='rounded border border-text-secondary text-xs text-text-primary'
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault() // necessary, otherwise the editor will lose focus
|
||||
closePortal()
|
||||
}}
|
||||
>
|
||||
close
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</ShortcutsPopupPlugin>
|
||||
{shortcutPopups?.map(({ hotkey, Popup }, idx) => (
|
||||
<ShortcutsPopupPlugin key={idx} hotkey={hotkey} >
|
||||
{closePortal => <Popup onClose={closePortal} />}
|
||||
</ShortcutsPopupPlugin>
|
||||
))}
|
||||
<ComponentPickerBlock
|
||||
triggerString='/'
|
||||
contextBlock={contextBlock}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,12 @@ import cn from '@/utils/classnames'
|
|||
|
||||
export const SHORTCUTS_EMPTY_CONTENT = 'shortcuts_empty_content'
|
||||
|
||||
type Hotkey = string | ((e: KeyboardEvent) => boolean)
|
||||
// Hotkey can be:
|
||||
// - string: 'mod+/'
|
||||
// - string[]: ['mod', '/']
|
||||
// - string[][]: [['mod', '/'], ['mod', 'shift', '/']] (any combo matches)
|
||||
// - function: custom matcher
|
||||
export type Hotkey = string | string[] | string[][] | ((e: KeyboardEvent) => boolean)
|
||||
|
||||
type ShortcutPopupPluginProps = {
|
||||
hotkey?: Hotkey
|
||||
|
|
@ -48,58 +53,79 @@ function matchHotkey(event: KeyboardEvent, hotkey?: Hotkey) {
|
|||
if (typeof hotkey === 'function')
|
||||
return hotkey(event)
|
||||
|
||||
const parts = hotkey.toLowerCase().split('+').map(t => t.trim()).filter(Boolean)
|
||||
let expectedKey: string | null = null
|
||||
const matchCombo = (tokens: string[]) => {
|
||||
const parts = tokens.map(t => t.toLowerCase().trim()).filter(Boolean)
|
||||
let expectedKey: string | null = null
|
||||
|
||||
let needMod = false
|
||||
let needCtrl = false
|
||||
let needMeta = false
|
||||
let needAlt = false
|
||||
let needShift = false
|
||||
let needMod = false
|
||||
let needCtrl = false
|
||||
let needMeta = false
|
||||
let needAlt = false
|
||||
let needShift = false
|
||||
|
||||
for (const p of parts) {
|
||||
if (p === 'mod') {
|
||||
needMod = true
|
||||
continue
|
||||
for (const p of parts) {
|
||||
if (p === 'mod') {
|
||||
needMod = true
|
||||
continue
|
||||
}
|
||||
if (CTRL_ALIASES.has(p)) {
|
||||
needCtrl = true
|
||||
continue
|
||||
}
|
||||
if (META_ALIASES.has(p)) {
|
||||
needMeta = true
|
||||
continue
|
||||
}
|
||||
if (ALT_ALIASES.has(p)) {
|
||||
needAlt = true
|
||||
continue
|
||||
}
|
||||
if (SHIFT_ALIASES.has(p)) {
|
||||
needShift = true
|
||||
continue
|
||||
}
|
||||
expectedKey = p
|
||||
}
|
||||
if (CTRL_ALIASES.has(p)) {
|
||||
needCtrl = true
|
||||
continue
|
||||
}
|
||||
if (META_ALIASES.has(p)) {
|
||||
needMeta = true
|
||||
continue
|
||||
}
|
||||
if (ALT_ALIASES.has(p)) {
|
||||
needAlt = true
|
||||
continue
|
||||
}
|
||||
if (SHIFT_ALIASES.has(p)) {
|
||||
needShift = true
|
||||
continue
|
||||
}
|
||||
expectedKey = p
|
||||
}
|
||||
|
||||
if (needMod && !(event.metaKey || event.ctrlKey))
|
||||
return false
|
||||
if (needCtrl && !event.ctrlKey)
|
||||
return false
|
||||
if (needMeta && !event.metaKey)
|
||||
return false
|
||||
if (needAlt && !event.altKey)
|
||||
return false
|
||||
if (needShift && !event.shiftKey)
|
||||
return false
|
||||
|
||||
if (expectedKey) {
|
||||
const k = event.key.toLowerCase()
|
||||
const normalized = k === ' ' ? 'space' : k
|
||||
if (normalized !== expectedKey)
|
||||
if (needMod && !(event.metaKey || event.ctrlKey))
|
||||
return false
|
||||
if (needCtrl && !event.ctrlKey)
|
||||
return false
|
||||
if (needMeta && !event.metaKey)
|
||||
return false
|
||||
if (needAlt && !event.altKey)
|
||||
return false
|
||||
if (needShift && !event.shiftKey)
|
||||
return false
|
||||
|
||||
if (expectedKey) {
|
||||
const k = event.key.toLowerCase()
|
||||
const normalized = k === ' ' ? 'space' : k
|
||||
if (normalized !== expectedKey)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
if (Array.isArray(hotkey)) {
|
||||
const isNested = hotkey.length > 0 && Array.isArray((hotkey as unknown[])[0])
|
||||
if (isNested) {
|
||||
const combos = hotkey as string[][]
|
||||
return combos.some(tokens => matchCombo(tokens))
|
||||
}
|
||||
else {
|
||||
const tokens = hotkey as string[]
|
||||
return matchCombo(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
const tokensFromString = hotkey
|
||||
.toLowerCase()
|
||||
.split('+')
|
||||
.map(t => t.trim())
|
||||
.filter(Boolean)
|
||||
return matchCombo(tokensFromString)
|
||||
}
|
||||
|
||||
export default function ShortcutsPopupPlugin({
|
||||
|
|
|
|||
Loading…
Reference in New Issue