refactor: revamp picker block (#4227)
Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com>pull/6078/head
parent
68b1d063f7
commit
0046ef7707
@ -1,85 +0,0 @@
|
||||
import { memo } from 'react'
|
||||
import { MenuOption } from '@lexical/react/LexicalTypeaheadMenuPlugin'
|
||||
|
||||
export class VariableOption extends MenuOption {
|
||||
title: string
|
||||
icon?: JSX.Element
|
||||
extraElement?: JSX.Element
|
||||
keywords: Array<string>
|
||||
keyboardShortcut?: string
|
||||
onSelect: (queryString: string) => void
|
||||
|
||||
constructor(
|
||||
title: string,
|
||||
options: {
|
||||
icon?: JSX.Element
|
||||
extraElement?: JSX.Element
|
||||
keywords?: Array<string>
|
||||
keyboardShortcut?: string
|
||||
onSelect: (queryString: string) => void
|
||||
},
|
||||
) {
|
||||
super(title)
|
||||
this.title = title
|
||||
this.keywords = options.keywords || []
|
||||
this.icon = options.icon
|
||||
this.extraElement = options.extraElement
|
||||
this.keyboardShortcut = options.keyboardShortcut
|
||||
this.onSelect = options.onSelect.bind(this)
|
||||
}
|
||||
}
|
||||
|
||||
type VariableMenuItemProps = {
|
||||
isSelected: boolean
|
||||
onClick: () => void
|
||||
onMouseEnter: () => void
|
||||
option: VariableOption
|
||||
queryString: string | null
|
||||
}
|
||||
export const VariableMenuItem = memo(({
|
||||
isSelected,
|
||||
onClick,
|
||||
onMouseEnter,
|
||||
option,
|
||||
queryString,
|
||||
}: VariableMenuItemProps) => {
|
||||
const title = option.title
|
||||
let before = title
|
||||
let middle = ''
|
||||
let after = ''
|
||||
|
||||
if (queryString) {
|
||||
const regex = new RegExp(queryString, 'i')
|
||||
const match = regex.exec(option.title)
|
||||
|
||||
if (match) {
|
||||
before = title.substring(0, match.index)
|
||||
middle = match[0]
|
||||
after = title.substring(match.index + match[0].length)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={option.key}
|
||||
className={`
|
||||
flex items-center px-3 h-6 rounded-md hover:bg-primary-50 cursor-pointer
|
||||
${isSelected && 'bg-primary-50'}
|
||||
`}
|
||||
tabIndex={-1}
|
||||
ref={option.setRefElement}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onClick={onClick}>
|
||||
<div className='mr-2'>
|
||||
{option.icon}
|
||||
</div>
|
||||
<div className='grow text-[13px] text-gray-900 truncate' title={option.title}>
|
||||
{before}
|
||||
<span className='text-[#2970FF]'>{middle}</span>
|
||||
{after}
|
||||
</div>
|
||||
{option.extraElement}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
VariableMenuItem.displayName = 'VariableMenuItem'
|
||||
@ -0,0 +1,31 @@
|
||||
import { MenuOption } from '@lexical/react/LexicalTypeaheadMenuPlugin'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
/**
|
||||
* Corresponds to the `MenuRenderFn` type from `@lexical/react/LexicalTypeaheadMenuPlugin`.
|
||||
*/
|
||||
type MenuOptionRenderProps = {
|
||||
isSelected: boolean
|
||||
onSelect: () => void
|
||||
onSetHighlight: () => void
|
||||
queryString: string | null
|
||||
}
|
||||
|
||||
export class PickerBlockMenuOption extends MenuOption {
|
||||
public group?: string
|
||||
|
||||
constructor(
|
||||
private data: {
|
||||
key: string
|
||||
group?: string
|
||||
onSelect?: () => void
|
||||
render: (menuRenderProps: MenuOptionRenderProps) => JSX.Element
|
||||
},
|
||||
) {
|
||||
super(data.key)
|
||||
this.group = data.group
|
||||
}
|
||||
|
||||
public onSelectMenuOption = () => this.data.onSelect?.()
|
||||
public renderMenuOption = (menuRenderProps: MenuOptionRenderProps) => <Fragment key={this.data.key}>{this.data.render(menuRenderProps)}</Fragment>
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
import { memo } from 'react'
|
||||
import { PromptMenuItem } from './prompt-option'
|
||||
|
||||
type PromptMenuProps = {
|
||||
startIndex: number
|
||||
selectedIndex: number | null
|
||||
options: any[]
|
||||
onClick: (index: number, option: any) => void
|
||||
onMouseEnter: (index: number, option: any) => void
|
||||
}
|
||||
const PromptMenu = ({
|
||||
startIndex,
|
||||
selectedIndex,
|
||||
options,
|
||||
onClick,
|
||||
onMouseEnter,
|
||||
}: PromptMenuProps) => {
|
||||
return (
|
||||
<div className='p-1'>
|
||||
{
|
||||
options.map((option, index: number) => (
|
||||
<PromptMenuItem
|
||||
startIndex={startIndex}
|
||||
index={index}
|
||||
isSelected={selectedIndex === index + startIndex}
|
||||
onClick={onClick}
|
||||
onMouseEnter={onMouseEnter}
|
||||
key={option.key}
|
||||
option={option}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(PromptMenu)
|
||||
@ -1,40 +0,0 @@
|
||||
import { memo } from 'react'
|
||||
import { VariableMenuItem } from './variable-option'
|
||||
|
||||
type VariableMenuProps = {
|
||||
startIndex: number
|
||||
selectedIndex: number | null
|
||||
options: any[]
|
||||
onClick: (index: number, option: any) => void
|
||||
onMouseEnter: (index: number, option: any) => void
|
||||
queryString: string | null
|
||||
}
|
||||
const VariableMenu = ({
|
||||
startIndex,
|
||||
selectedIndex,
|
||||
options,
|
||||
onClick,
|
||||
onMouseEnter,
|
||||
queryString,
|
||||
}: VariableMenuProps) => {
|
||||
return (
|
||||
<div className='p-1'>
|
||||
{
|
||||
options.map((option, index: number) => (
|
||||
<VariableMenuItem
|
||||
startIndex={startIndex}
|
||||
index={index}
|
||||
isSelected={selectedIndex === index + startIndex}
|
||||
onClick={onClick}
|
||||
onMouseEnter={onMouseEnter}
|
||||
key={option.key}
|
||||
option={option}
|
||||
queryString={queryString}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(VariableMenu)
|
||||
Loading…
Reference in New Issue