mirror of https://github.com/buster-so/buster.git
Merge pull request #660 from buster-so/big-nate-bus-1603-finalize-context-menu-options
block context menu updates
This commit is contained in:
commit
efbe35cd39
|
@ -207,7 +207,7 @@ const value: ReportElements = [
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: 'This is a todo list',
|
text: 'This is a todo list',
|
||||||
subscript: true
|
subscript: false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
indent: 1,
|
indent: 1,
|
||||||
|
|
|
@ -203,6 +203,7 @@ export const NodeTypeIcons = {
|
||||||
indent: IndentIncrease,
|
indent: IndentIncrease,
|
||||||
outdent: IndentDecrease,
|
outdent: IndentDecrease,
|
||||||
download: Download,
|
download: Download,
|
||||||
|
turnInto: Pilcrow,
|
||||||
|
|
||||||
// Tools
|
// Tools
|
||||||
equation: Equation,
|
equation: Equation,
|
||||||
|
|
|
@ -124,6 +124,21 @@ export const NodeTypeLabels = {
|
||||||
keyboard: '⌘+⇧+Z',
|
keyboard: '⌘+⇧+Z',
|
||||||
keywords: []
|
keywords: []
|
||||||
},
|
},
|
||||||
|
delete: {
|
||||||
|
label: 'Delete',
|
||||||
|
keyboard: '⌘+⌫',
|
||||||
|
keywords: []
|
||||||
|
},
|
||||||
|
duplicate: {
|
||||||
|
label: 'Duplicate',
|
||||||
|
keyboard: undefined,
|
||||||
|
keywords: []
|
||||||
|
},
|
||||||
|
askAI: {
|
||||||
|
label: 'Ask AI',
|
||||||
|
keyboard: undefined,
|
||||||
|
keywords: []
|
||||||
|
},
|
||||||
link: {
|
link: {
|
||||||
label: 'Link',
|
label: 'Link',
|
||||||
keyboard: '⌘+K',
|
keyboard: '⌘+K',
|
||||||
|
@ -161,13 +176,18 @@ export const NodeTypeLabels = {
|
||||||
keyboard: undefined,
|
keyboard: undefined,
|
||||||
keywords: []
|
keywords: []
|
||||||
},
|
},
|
||||||
insert: {
|
align: {
|
||||||
label: 'Insert',
|
label: 'Align',
|
||||||
keyboard: undefined,
|
keyboard: undefined,
|
||||||
keywords: []
|
keywords: []
|
||||||
},
|
},
|
||||||
align: {
|
indentation: {
|
||||||
label: 'Align',
|
label: 'Indentation',
|
||||||
|
keyboard: undefined,
|
||||||
|
keywords: ['indent', 'outdent']
|
||||||
|
},
|
||||||
|
insert: {
|
||||||
|
label: 'Insert',
|
||||||
keyboard: undefined,
|
keyboard: undefined,
|
||||||
keywords: []
|
keywords: []
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/components/ui/dropdown-menu';
|
||||||
|
|
||||||
import { ToolbarButton } from '@/components/ui/toolbar/Toolbar';
|
import { ToolbarButton } from '@/components/ui/toolbar/Toolbar';
|
||||||
|
import { Tooltip } from '../../tooltip';
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
|
@ -69,13 +70,15 @@ export function AlignToolbarButton(props: DropdownMenuProps) {
|
||||||
tf.textAlign.setNodes(value as Alignment);
|
tf.textAlign.setNodes(value as Alignment);
|
||||||
editor.tf.focus();
|
editor.tf.focus();
|
||||||
}}>
|
}}>
|
||||||
{items.map(({ icon: Icon, value: itemValue }) => (
|
{items.map(({ icon: Icon, label, value: itemValue }) => (
|
||||||
<DropdownMenuRadioItem
|
<Tooltip key={itemValue} title={label} side="left">
|
||||||
key={itemValue}
|
<DropdownMenuRadioItem
|
||||||
className="data-[state=checked]:bg-accent pl-2 *:first:[span]:hidden"
|
key={itemValue}
|
||||||
value={itemValue}>
|
className="data-[state=checked]:bg-accent pl-2 *:first:[span]:hidden"
|
||||||
<Icon />
|
value={itemValue}>
|
||||||
</DropdownMenuRadioItem>
|
<Icon />
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
</Tooltip>
|
||||||
))}
|
))}
|
||||||
</DropdownMenuRadioGroup>
|
</DropdownMenuRadioGroup>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
ContextMenuContent,
|
ContextMenuContent,
|
||||||
ContextMenuGroup,
|
ContextMenuGroup,
|
||||||
ContextMenuItem,
|
ContextMenuItem,
|
||||||
|
ContextMenuShortcut,
|
||||||
ContextMenuSub,
|
ContextMenuSub,
|
||||||
ContextMenuSubContent,
|
ContextMenuSubContent,
|
||||||
ContextMenuSubTrigger,
|
ContextMenuSubTrigger,
|
||||||
|
@ -23,10 +24,33 @@ import {
|
||||||
} from '@/components/ui/context-menu';
|
} from '@/components/ui/context-menu';
|
||||||
import { useIsTouchDevice } from '@/hooks/useIsTouchDevice';
|
import { useIsTouchDevice } from '@/hooks/useIsTouchDevice';
|
||||||
import { THEME_RESET_STYLE } from '@/styles/theme-reset';
|
import { THEME_RESET_STYLE } from '@/styles/theme-reset';
|
||||||
|
import { NodeTypeIcons } from '../config/icons';
|
||||||
|
import { NodeTypeLabels } from '../config/labels';
|
||||||
|
|
||||||
|
// Helper function to render menu item content
|
||||||
|
const MenuItemContent = ({
|
||||||
|
icon,
|
||||||
|
labelKey
|
||||||
|
}: {
|
||||||
|
icon: React.ComponentType;
|
||||||
|
labelKey: keyof typeof NodeTypeLabels;
|
||||||
|
}) => {
|
||||||
|
const label = NodeTypeLabels[labelKey];
|
||||||
|
const Icon = icon;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="text-icon-color text-md size-4">
|
||||||
|
<Icon />
|
||||||
|
</div>
|
||||||
|
{label.label}
|
||||||
|
{label.keyboard && <ContextMenuShortcut>{label.keyboard}</ContextMenuShortcut>}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type Value = 'askAI' | null;
|
type Value = 'askAI' | null;
|
||||||
|
|
||||||
export function BlockContextMenu({ children }: { children: React.ReactNode }) {
|
function BlockContextMenuComponent({ children }: { children: React.ReactNode }) {
|
||||||
const { api, editor } = useEditorPlugin(BlockMenuPlugin);
|
const { api, editor } = useEditorPlugin(BlockMenuPlugin);
|
||||||
const [value, setValue] = React.useState<Value>(null);
|
const [value, setValue] = React.useState<Value>(null);
|
||||||
const isTouch = useIsTouchDevice();
|
const isTouch = useIsTouchDevice();
|
||||||
|
@ -88,7 +112,7 @@ export function BlockContextMenu({ children }: { children: React.ReactNode }) {
|
||||||
y: event.clientY
|
y: event.clientY
|
||||||
});
|
});
|
||||||
}}>
|
}}>
|
||||||
<div className="w-full">{children}</div>
|
<div className="block-context-menu-trigger">{children}</div>
|
||||||
</ContextMenuTrigger>
|
</ContextMenuTrigger>
|
||||||
<ContextMenuContent
|
<ContextMenuContent
|
||||||
className="w-64"
|
className="w-64"
|
||||||
|
@ -104,56 +128,84 @@ export function BlockContextMenu({ children }: { children: React.ReactNode }) {
|
||||||
setValue(null);
|
setValue(null);
|
||||||
}}>
|
}}>
|
||||||
<ContextMenuGroup>
|
<ContextMenuGroup>
|
||||||
<ContextMenuItem
|
{/* <ContextMenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setValue('askAI');
|
setValue('askAI');
|
||||||
}}>
|
}}>
|
||||||
Ask AI
|
<MenuItemContent icon={NodeTypeIcons.ai} labelKey="askAI" />
|
||||||
</ContextMenuItem>
|
</ContextMenuItem> */}
|
||||||
<ContextMenuItem
|
<ContextMenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
editor.getTransforms(BlockSelectionPlugin).blockSelection.removeNodes();
|
editor.getTransforms(BlockSelectionPlugin).blockSelection.removeNodes();
|
||||||
editor.tf.focus();
|
editor.tf.focus();
|
||||||
}}>
|
}}>
|
||||||
Delete
|
<MenuItemContent icon={NodeTypeIcons.trash} labelKey="delete" />
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
<ContextMenuItem
|
<ContextMenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
editor.getTransforms(BlockSelectionPlugin).blockSelection.duplicate();
|
editor.getTransforms(BlockSelectionPlugin).blockSelection.duplicate();
|
||||||
}}>
|
}}>
|
||||||
Duplicate
|
<MenuItemContent icon={NodeTypeIcons.copy} labelKey="duplicate" />
|
||||||
{/* <ContextMenuShortcut>⌘ + D</ContextMenuShortcut> */}
|
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
<ContextMenuSub>
|
<ContextMenuSub>
|
||||||
<ContextMenuSubTrigger>Turn into</ContextMenuSubTrigger>
|
<ContextMenuSubTrigger>
|
||||||
|
<MenuItemContent icon={NodeTypeIcons.turnInto} labelKey="turnInto" />
|
||||||
|
</ContextMenuSubTrigger>
|
||||||
<ContextMenuSubContent className="w-48">
|
<ContextMenuSubContent className="w-48">
|
||||||
<ContextMenuItem onClick={() => handleTurnInto(KEYS.p)}>Paragraph</ContextMenuItem>
|
<ContextMenuItem onClick={() => handleTurnInto(KEYS.p)}>
|
||||||
|
<MenuItemContent icon={NodeTypeIcons.paragraph} labelKey="paragraph" />
|
||||||
|
</ContextMenuItem>
|
||||||
|
|
||||||
<ContextMenuItem onClick={() => handleTurnInto(KEYS.h1)}>Heading 1</ContextMenuItem>
|
<ContextMenuItem onClick={() => handleTurnInto(KEYS.h1)}>
|
||||||
<ContextMenuItem onClick={() => handleTurnInto(KEYS.h2)}>Heading 2</ContextMenuItem>
|
<MenuItemContent icon={NodeTypeIcons.h1} labelKey="h1" />
|
||||||
<ContextMenuItem onClick={() => handleTurnInto(KEYS.h3)}>Heading 3</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
|
<ContextMenuItem onClick={() => handleTurnInto(KEYS.h2)}>
|
||||||
|
<MenuItemContent icon={NodeTypeIcons.h2} labelKey="h2" />
|
||||||
|
</ContextMenuItem>
|
||||||
|
<ContextMenuItem onClick={() => handleTurnInto(KEYS.h3)}>
|
||||||
|
<MenuItemContent icon={NodeTypeIcons.h3} labelKey="h3" />
|
||||||
|
</ContextMenuItem>
|
||||||
<ContextMenuItem onClick={() => handleTurnInto(KEYS.blockquote)}>
|
<ContextMenuItem onClick={() => handleTurnInto(KEYS.blockquote)}>
|
||||||
Blockquote
|
<MenuItemContent icon={NodeTypeIcons.quote} labelKey="blockquote" />
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
</ContextMenuSubContent>
|
</ContextMenuSubContent>
|
||||||
</ContextMenuSub>
|
</ContextMenuSub>
|
||||||
</ContextMenuGroup>
|
</ContextMenuGroup>
|
||||||
|
|
||||||
<ContextMenuGroup>
|
<ContextMenuGroup>
|
||||||
<ContextMenuItem
|
|
||||||
onClick={() => editor.getTransforms(BlockSelectionPlugin).blockSelection.setIndent(1)}>
|
|
||||||
Indent
|
|
||||||
</ContextMenuItem>
|
|
||||||
<ContextMenuItem
|
|
||||||
onClick={() => editor.getTransforms(BlockSelectionPlugin).blockSelection.setIndent(-1)}>
|
|
||||||
Outdent
|
|
||||||
</ContextMenuItem>
|
|
||||||
<ContextMenuSub>
|
<ContextMenuSub>
|
||||||
<ContextMenuSubTrigger>Align</ContextMenuSubTrigger>
|
<ContextMenuSubTrigger>
|
||||||
|
<MenuItemContent icon={NodeTypeIcons.indent} labelKey="indentation" />
|
||||||
|
</ContextMenuSubTrigger>
|
||||||
<ContextMenuSubContent className="w-48">
|
<ContextMenuSubContent className="w-48">
|
||||||
<ContextMenuItem onClick={() => handleAlign('left')}>Left</ContextMenuItem>
|
<ContextMenuItem
|
||||||
<ContextMenuItem onClick={() => handleAlign('center')}>Center</ContextMenuItem>
|
onClick={() =>
|
||||||
<ContextMenuItem onClick={() => handleAlign('right')}>Right</ContextMenuItem>
|
editor.getTransforms(BlockSelectionPlugin).blockSelection.setIndent(1)
|
||||||
|
}>
|
||||||
|
<MenuItemContent icon={NodeTypeIcons.indent} labelKey="indent" />
|
||||||
|
</ContextMenuItem>
|
||||||
|
<ContextMenuItem
|
||||||
|
onClick={() =>
|
||||||
|
editor.getTransforms(BlockSelectionPlugin).blockSelection.setIndent(-1)
|
||||||
|
}>
|
||||||
|
<MenuItemContent icon={NodeTypeIcons.outdent} labelKey="outdent" />
|
||||||
|
</ContextMenuItem>
|
||||||
|
</ContextMenuSubContent>
|
||||||
|
</ContextMenuSub>
|
||||||
|
<ContextMenuSub>
|
||||||
|
<ContextMenuSubTrigger>
|
||||||
|
<MenuItemContent icon={NodeTypeIcons.alignLeft} labelKey="align" />
|
||||||
|
</ContextMenuSubTrigger>
|
||||||
|
<ContextMenuSubContent className="w-48">
|
||||||
|
<ContextMenuItem onClick={() => handleAlign('left')}>
|
||||||
|
<MenuItemContent icon={NodeTypeIcons.alignLeft} labelKey="alignLeft" />
|
||||||
|
</ContextMenuItem>
|
||||||
|
<ContextMenuItem onClick={() => handleAlign('center')}>
|
||||||
|
<MenuItemContent icon={NodeTypeIcons.alignCenter} labelKey="alignCenter" />
|
||||||
|
</ContextMenuItem>
|
||||||
|
<ContextMenuItem onClick={() => handleAlign('right')}>
|
||||||
|
<MenuItemContent icon={NodeTypeIcons.alignRight} labelKey="alignRight" />
|
||||||
|
</ContextMenuItem>
|
||||||
</ContextMenuSubContent>
|
</ContextMenuSubContent>
|
||||||
</ContextMenuSub>
|
</ContextMenuSub>
|
||||||
</ContextMenuGroup>
|
</ContextMenuGroup>
|
||||||
|
@ -161,3 +213,5 @@ export function BlockContextMenu({ children }: { children: React.ReactNode }) {
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const BlockContextMenu = React.memo(BlockContextMenuComponent);
|
||||||
|
|
Loading…
Reference in New Issue