feat(richtext-lexical)!: dropdown menu disabled status (#8177)
**Breaking change**: ToolbarDropdown no longer receives
`groupKey={group.key}` and `items={group.items}` as props, but instead
`group={group}`
___
Similar to #8159, but in this case it allows you to disable an entire
dropdown menu, not just individual items in the dropdown.
This adds a new property to `ToolbarGroup` when used with `type:
'dropdown'`.
For example, if you add `isEnabled: () => false,` inside
`packages/richtext-lexical/src/features/shared/toolbar/textDropdownGroup.ts`
and run `pnpm dev fields`, this is what you'll see in the Lexical
editor:

This commit is contained in:
@@ -110,9 +110,8 @@ function ToolbarGroupComponent({
|
||||
<ToolbarDropdown
|
||||
anchorElem={anchorElem}
|
||||
editor={editor}
|
||||
groupKey={group.key}
|
||||
group={group}
|
||||
Icon={DropdownIcon}
|
||||
items={group.items}
|
||||
itemsContainerClassNames={['fixed-toolbar__dropdown-items']}
|
||||
label={dropdownLabel}
|
||||
maxActiveItems={1}
|
||||
@@ -122,8 +121,7 @@ function ToolbarGroupComponent({
|
||||
<ToolbarDropdown
|
||||
anchorElem={anchorElem}
|
||||
editor={editor}
|
||||
groupKey={group.key}
|
||||
items={group.items}
|
||||
group={group}
|
||||
itemsContainerClassNames={['fixed-toolbar__dropdown-items']}
|
||||
label={dropdownLabel}
|
||||
maxActiveItems={1}
|
||||
|
||||
@@ -101,9 +101,8 @@ function ToolbarGroupComponent({
|
||||
<ToolbarDropdown
|
||||
anchorElem={anchorElem}
|
||||
editor={editor}
|
||||
groupKey={group.key}
|
||||
group={group}
|
||||
Icon={DropdownIcon}
|
||||
items={group.items}
|
||||
maxActiveItems={1}
|
||||
onActiveChange={onActiveChange}
|
||||
/>
|
||||
@@ -111,8 +110,7 @@ function ToolbarGroupComponent({
|
||||
<ToolbarDropdown
|
||||
anchorElem={anchorElem}
|
||||
editor={editor}
|
||||
groupKey={group.key}
|
||||
items={group.items}
|
||||
group={group}
|
||||
maxActiveItems={1}
|
||||
onActiveChange={onActiveChange}
|
||||
/>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
&:hover:not([disabled]) {
|
||||
&:hover:not(.disabled) {
|
||||
background-color: var(--theme-elevation-100);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,8 @@
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
|
||||
.icon {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover:not([disabled]) {
|
||||
background-color: var(--theme-elevation-100);
|
||||
|
||||
@@ -9,7 +9,7 @@ import { mergeRegister } from '@lexical/utils'
|
||||
import { useTranslation } from '@payloadcms/ui'
|
||||
import { $getSelection } from 'lexical'
|
||||
|
||||
import type { ToolbarGroupItem } from '../../types.js'
|
||||
import type { ToolbarDropdownGroup, ToolbarGroupItem } from '../../types.js'
|
||||
|
||||
import { useEditorConfigContext } from '../../../../lexical/config/client/EditorConfigProvider.js'
|
||||
import { DropDown, DropDownItem } from './DropDown.js'
|
||||
@@ -70,9 +70,8 @@ export const ToolbarDropdown = ({
|
||||
anchorElem,
|
||||
classNames,
|
||||
editor,
|
||||
groupKey,
|
||||
group,
|
||||
Icon,
|
||||
items,
|
||||
itemsContainerClassNames,
|
||||
label,
|
||||
maxActiveItems,
|
||||
@@ -81,9 +80,8 @@ export const ToolbarDropdown = ({
|
||||
anchorElem: HTMLElement
|
||||
classNames?: string[]
|
||||
editor: LexicalEditor
|
||||
groupKey: string
|
||||
group: ToolbarDropdownGroup
|
||||
Icon?: React.FC
|
||||
items: ToolbarGroupItem[]
|
||||
itemsContainerClassNames?: string[]
|
||||
label?: string
|
||||
/**
|
||||
@@ -95,7 +93,9 @@ export const ToolbarDropdown = ({
|
||||
}) => {
|
||||
const [activeItemKeys, setActiveItemKeys] = React.useState<string[]>([])
|
||||
const [enabledItemKeys, setEnabledItemKeys] = React.useState<string[]>([])
|
||||
const [enabledGroup, setEnabledGroup] = React.useState<boolean>(true)
|
||||
const editorConfigContext = useEditorConfigContext()
|
||||
const { items, key: groupKey } = group
|
||||
|
||||
const updateStates = useCallback(() => {
|
||||
editor.getEditorState().read(() => {
|
||||
@@ -125,6 +125,9 @@ export const ToolbarDropdown = ({
|
||||
_enabledItemKeys.push(item.key)
|
||||
}
|
||||
}
|
||||
if (group.isEnabled) {
|
||||
setEnabledGroup(group.isEnabled({ editor, editorConfigContext, selection }))
|
||||
}
|
||||
setActiveItemKeys(_activeItemKeys)
|
||||
setEnabledItemKeys(_enabledItemKeys)
|
||||
|
||||
@@ -132,7 +135,7 @@ export const ToolbarDropdown = ({
|
||||
onActiveChange({ activeItems: _activeItems })
|
||||
}
|
||||
})
|
||||
}, [editor, editorConfigContext, items, maxActiveItems, onActiveChange])
|
||||
}, [editor, editorConfigContext, group, items, maxActiveItems, onActiveChange])
|
||||
|
||||
useEffect(() => {
|
||||
updateStates()
|
||||
@@ -152,6 +155,7 @@ export const ToolbarDropdown = ({
|
||||
buttonClassName={[baseClass, `${baseClass}-${groupKey}`, ...(classNames || [])]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
disabled={!enabledGroup}
|
||||
Icon={Icon}
|
||||
itemsContainerClassNames={[`${baseClass}-items`, ...(itemsContainerClassNames || [])]}
|
||||
key={groupKey}
|
||||
|
||||
@@ -4,30 +4,25 @@ import type React from 'react'
|
||||
|
||||
import type { EditorConfigContextType } from '../../lexical/config/client/EditorConfigProvider.js'
|
||||
|
||||
export type ToolbarGroup =
|
||||
| {
|
||||
/**
|
||||
* All toolbar items part of this toolbar group need to be added here.
|
||||
*/
|
||||
items: Array<ToolbarGroupItem>
|
||||
/**
|
||||
* Each toolbar group needs to have a unique key. Groups with the same keys will have their items merged together.
|
||||
*/
|
||||
key: string
|
||||
/**
|
||||
* Determines where the toolbar group will be.
|
||||
*/
|
||||
order?: number
|
||||
/**
|
||||
* Controls the toolbar group type. Set to `buttons` to create a buttons toolbar group, which displays toolbar items horizontally using only their icons.
|
||||
*/
|
||||
type: 'buttons'
|
||||
}
|
||||
| {
|
||||
export type ToolbarGroup = ToolbarButtonsGroup | ToolbarDropdownGroup
|
||||
|
||||
export type ToolbarDropdownGroup = {
|
||||
/**
|
||||
* The dropdown toolbar ChildComponent allows you to pass in a React Component which will be displayed within the dropdown button.
|
||||
*/
|
||||
ChildComponent?: React.FC
|
||||
/**
|
||||
* This is optional and controls if the toolbar group is highlighted or not.
|
||||
*/
|
||||
isEnabled?: ({
|
||||
editor,
|
||||
editorConfigContext,
|
||||
selection,
|
||||
}: {
|
||||
editor: LexicalEditor
|
||||
editorConfigContext: EditorConfigContextType
|
||||
selection: BaseSelection
|
||||
}) => boolean
|
||||
/**
|
||||
* All toolbar items part of this toolbar group need to be added here.
|
||||
*/
|
||||
@@ -46,6 +41,25 @@ export type ToolbarGroup =
|
||||
type: 'dropdown'
|
||||
}
|
||||
|
||||
export type ToolbarButtonsGroup = {
|
||||
/**
|
||||
* All toolbar items part of this toolbar group need to be added here.
|
||||
*/
|
||||
items: Array<ToolbarGroupItem>
|
||||
/**
|
||||
* Each toolbar group needs to have a unique key. Groups with the same keys will have their items merged together.
|
||||
*/
|
||||
key: string
|
||||
/**
|
||||
* Determines where the toolbar group will be.
|
||||
*/
|
||||
order?: number
|
||||
/**
|
||||
* Controls the toolbar group type. Set to `buttons` to create a buttons toolbar group, which displays toolbar items horizontally using only their icons.
|
||||
*/
|
||||
type: 'buttons'
|
||||
}
|
||||
|
||||
export type ToolbarGroupItem = {
|
||||
/** A React component which is rendered within your toolbar item's default button component. Usually, you want this to be an icon. */
|
||||
ChildComponent?: React.FC
|
||||
|
||||
Reference in New Issue
Block a user