feat(core): add shortcut for multi select docs (#6318)
close TOV-701 In All Doc, `Shift + Click` has been added to activate the multiple selection state.
This commit is contained in:
@@ -106,6 +106,7 @@ export const titleCell = style({
|
|||||||
maxWidth: 'calc(100% - 64px)',
|
maxWidth: 'calc(100% - 64px)',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
|
userSelect: 'none',
|
||||||
});
|
});
|
||||||
export const titleCellMain = style({
|
export const titleCellMain = style({
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import type { PropsWithChildren } from 'react';
|
|||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { selectionStateAtom, useAtom } from '../scoped-atoms';
|
||||||
import type {
|
import type {
|
||||||
CollectionListItemProps,
|
CollectionListItemProps,
|
||||||
DraggableTitleCellData,
|
DraggableTitleCellData,
|
||||||
@@ -172,14 +173,28 @@ function CollectionListItemWrapper({
|
|||||||
children,
|
children,
|
||||||
draggable,
|
draggable,
|
||||||
}: collectionListWrapperProps) {
|
}: collectionListWrapperProps) {
|
||||||
|
const [selectionState, setSelectionActive] = useAtom(selectionStateAtom);
|
||||||
const handleClick = useCallback(
|
const handleClick = useCallback(
|
||||||
(e: React.MouseEvent) => {
|
(e: React.MouseEvent) => {
|
||||||
if (onClick) {
|
if (!selectionState.selectable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.shiftKey) {
|
||||||
stopPropagation(e);
|
stopPropagation(e);
|
||||||
onClick();
|
setSelectionActive(true);
|
||||||
|
onClick?.();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectionState.selectionActive) {
|
||||||
|
return onClick?.();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[onClick]
|
[
|
||||||
|
onClick,
|
||||||
|
selectionState.selectable,
|
||||||
|
selectionState.selectionActive,
|
||||||
|
setSelectionActive,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
const commonProps = useMemo(
|
const commonProps = useMemo(
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ export const titleCell = style({
|
|||||||
maxWidth: 'calc(100% - 64px)',
|
maxWidth: 'calc(100% - 64px)',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
|
userSelect: 'none',
|
||||||
});
|
});
|
||||||
export const titleCellMain = style({
|
export const titleCellMain = style({
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import type { PropsWithChildren } from 'react';
|
|||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { WorkbenchLink } from '../../../modules/workbench/view/workbench-link';
|
import { WorkbenchLink } from '../../../modules/workbench/view/workbench-link';
|
||||||
|
import { selectionStateAtom, useAtom } from '../scoped-atoms';
|
||||||
import type { DraggableTitleCellData, PageListItemProps } from '../types';
|
import type { DraggableTitleCellData, PageListItemProps } from '../types';
|
||||||
import { usePageDisplayProperties } from '../use-page-display-properties';
|
import { usePageDisplayProperties } from '../use-page-display-properties';
|
||||||
import { ColWrapper, formatDate, stopPropagation } from '../utils';
|
import { ColWrapper, formatDate, stopPropagation } from '../utils';
|
||||||
@@ -237,14 +238,22 @@ function PageListItemWrapper({
|
|||||||
children,
|
children,
|
||||||
draggable,
|
draggable,
|
||||||
}: PageListWrapperProps) {
|
}: PageListWrapperProps) {
|
||||||
|
const [selectionState, setSelectionActive] = useAtom(selectionStateAtom);
|
||||||
const handleClick = useCallback(
|
const handleClick = useCallback(
|
||||||
(e: React.MouseEvent) => {
|
(e: React.MouseEvent) => {
|
||||||
if (onClick) {
|
if (!selectionState.selectable) {
|
||||||
stopPropagation(e);
|
return false;
|
||||||
onClick();
|
|
||||||
}
|
}
|
||||||
|
stopPropagation(e);
|
||||||
|
if (e.shiftKey) {
|
||||||
|
setSelectionActive(true);
|
||||||
|
onClick?.();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
onClick?.();
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
[onClick]
|
[onClick, selectionState.selectable, setSelectionActive]
|
||||||
);
|
);
|
||||||
|
|
||||||
const commonProps = useMemo(
|
const commonProps = useMemo(
|
||||||
@@ -255,7 +264,7 @@ function PageListItemWrapper({
|
|||||||
className: styles.root,
|
className: styles.root,
|
||||||
'data-clickable': !!onClick || !!to,
|
'data-clickable': !!onClick || !!to,
|
||||||
'data-dragging': isDragging,
|
'data-dragging': isDragging,
|
||||||
onClick: handleClick,
|
onClick: onClick ? handleClick : undefined,
|
||||||
}),
|
}),
|
||||||
[pageId, draggable, onClick, to, isDragging, handleClick]
|
[pageId, draggable, onClick, to, isDragging, handleClick]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export const pageCount = style({
|
|||||||
fontSize: cssVar('fontBase'),
|
fontSize: cssVar('fontBase'),
|
||||||
lineHeight: '1.6em',
|
lineHeight: '1.6em',
|
||||||
color: cssVar('textSecondaryColor'),
|
color: cssVar('textSecondaryColor'),
|
||||||
|
marginRight: '12px',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const favouritedIcon = style({
|
export const favouritedIcon = style({
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ const useItemSelectionStateEffect = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setSelectionActive(false);
|
setSelectionActive(false);
|
||||||
|
selectionState.onSelectedIdsChange?.([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const escHandler = (e: KeyboardEvent) => {
|
const escHandler = (e: KeyboardEvent) => {
|
||||||
@@ -75,6 +76,7 @@ const useItemSelectionStateEffect = () => {
|
|||||||
}
|
}
|
||||||
if (e.key === 'Escape') {
|
if (e.key === 'Escape') {
|
||||||
setSelectionActive(false);
|
setSelectionActive(false);
|
||||||
|
selectionState.onSelectedIdsChange?.([]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,6 +90,7 @@ const useItemSelectionStateEffect = () => {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}, [
|
}, [
|
||||||
|
selectionState,
|
||||||
selectionState.selectable,
|
selectionState.selectable,
|
||||||
selectionState.selectionActive,
|
selectionState.selectionActive,
|
||||||
setSelectionActive,
|
setSelectionActive,
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ function pageMetaToListItemProp(
|
|||||||
createDate: new Date(item.createDate),
|
createDate: new Date(item.createDate),
|
||||||
updatedDate: item.updatedDate ? new Date(item.updatedDate) : undefined,
|
updatedDate: item.updatedDate ? new Date(item.updatedDate) : undefined,
|
||||||
to: props.rowAsLink && !props.selectable ? `/${item.id}` : undefined,
|
to: props.rowAsLink && !props.selectable ? `/${item.id}` : undefined,
|
||||||
onClick: props.selectable ? toggleSelection : undefined,
|
onClick: toggleSelection,
|
||||||
icon: (
|
icon: (
|
||||||
<UnifiedPageIcon
|
<UnifiedPageIcon
|
||||||
id={item.id}
|
id={item.id}
|
||||||
@@ -378,7 +378,7 @@ function collectionMetaToListItemProp(
|
|||||||
props.rowAsLink && !props.selectable
|
props.rowAsLink && !props.selectable
|
||||||
? `/collection/${item.id}`
|
? `/collection/${item.id}`
|
||||||
: undefined,
|
: undefined,
|
||||||
onClick: props.selectable ? toggleSelection : undefined,
|
onClick: toggleSelection,
|
||||||
icon: <ViewLayersIcon />,
|
icon: <ViewLayersIcon />,
|
||||||
operations: props.operationsRenderer?.(item),
|
operations: props.operationsRenderer?.(item),
|
||||||
selectable: props.selectable,
|
selectable: props.selectable,
|
||||||
@@ -412,7 +412,7 @@ function tagMetaToListItemProp(
|
|||||||
tagId: item.id,
|
tagId: item.id,
|
||||||
title: item.title,
|
title: item.title,
|
||||||
to: props.rowAsLink && !props.selectable ? `/tag/${item.id}` : undefined,
|
to: props.rowAsLink && !props.selectable ? `/tag/${item.id}` : undefined,
|
||||||
onClick: props.selectable ? toggleSelection : undefined,
|
onClick: toggleSelection,
|
||||||
color: item.color,
|
color: item.color,
|
||||||
pageCount: item.pageCount,
|
pageCount: item.pageCount,
|
||||||
operations: props.operationsRenderer?.(item),
|
operations: props.operationsRenderer?.(item),
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ export const titleCell = style({
|
|||||||
maxWidth: 'calc(100% - 64px)',
|
maxWidth: 'calc(100% - 64px)',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
|
userSelect: 'none',
|
||||||
});
|
});
|
||||||
export const titleCellMain = style({
|
export const titleCellMain = style({
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import type { PropsWithChildren } from 'react';
|
|||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { selectionStateAtom, useAtom } from '../scoped-atoms';
|
||||||
import type { DraggableTitleCellData, TagListItemProps } from '../types';
|
import type { DraggableTitleCellData, TagListItemProps } from '../types';
|
||||||
import { ColWrapper, stopPropagation } from '../utils';
|
import { ColWrapper, stopPropagation } from '../utils';
|
||||||
import * as styles from './tag-list-item.css';
|
import * as styles from './tag-list-item.css';
|
||||||
@@ -165,14 +166,28 @@ function TagListItemWrapper({
|
|||||||
children,
|
children,
|
||||||
draggable,
|
draggable,
|
||||||
}: TagListWrapperProps) {
|
}: TagListWrapperProps) {
|
||||||
|
const [selectionState, setSelectionActive] = useAtom(selectionStateAtom);
|
||||||
const handleClick = useCallback(
|
const handleClick = useCallback(
|
||||||
(e: React.MouseEvent) => {
|
(e: React.MouseEvent) => {
|
||||||
if (onClick) {
|
if (!selectionState.selectable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.shiftKey) {
|
||||||
stopPropagation(e);
|
stopPropagation(e);
|
||||||
onClick();
|
setSelectionActive(true);
|
||||||
|
onClick?.();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectionState.selectionActive) {
|
||||||
|
return onClick?.();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[onClick]
|
[
|
||||||
|
onClick,
|
||||||
|
selectionState.selectable,
|
||||||
|
selectionState.selectionActive,
|
||||||
|
setSelectionActive,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
const commonProps = useMemo(
|
const commonProps = useMemo(
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ export const WorkbenchLink = ({
|
|||||||
(event: React.MouseEvent<HTMLAnchorElement>) => {
|
(event: React.MouseEvent<HTMLAnchorElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
if (onClick?.(event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (event.ctrlKey || event.metaKey) {
|
if (event.ctrlKey || event.metaKey) {
|
||||||
if (appSettings.enableMultiView && environment.isDesktop) {
|
if (appSettings.enableMultiView && environment.isDesktop) {
|
||||||
@@ -34,7 +37,6 @@ export const WorkbenchLink = ({
|
|||||||
} else {
|
} else {
|
||||||
workbench.open(to);
|
workbench.open(to);
|
||||||
}
|
}
|
||||||
onClick?.(event);
|
|
||||||
},
|
},
|
||||||
[appSettings.enableMultiView, basename, onClick, to, workbench]
|
[appSettings.enableMultiView, basename, onClick, to, workbench]
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user