Skip to content

Commit

Permalink
#638 Fix select cell mouse input not working
Browse files Browse the repository at this point in the history
  • Loading branch information
Polleps committed Nov 7, 2023
1 parent 6b51c8a commit 69ec1b0
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 61 deletions.
4 changes: 3 additions & 1 deletion browser/data-browser/src/components/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface PopoverProps {
onOpenChange: (open: boolean) => void;
className?: string;
noArrow?: boolean;
noLock?: boolean;
}

export function Popover({
Expand All @@ -20,6 +21,7 @@ export function Popover({
open,
defaultOpen,
noArrow,
noLock,
onOpenChange,
Trigger,
}: React.PropsWithChildren<PopoverProps>): JSX.Element {
Expand All @@ -28,7 +30,7 @@ export function Popover({

const container = containerRef.current ?? undefined;

useControlLock(!!open);
useControlLock(!noLock && !!open);

const handleOpenChange = useCallback(
(changedToOpen: boolean) => {
Expand Down
8 changes: 7 additions & 1 deletion browser/data-browser/src/components/TableEditor/Cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from './TableEditorContext';
import { FaExpandAlt } from 'react-icons/fa';
import { IconButton } from '../IconButton/IconButton';
import { KeyboardInteraction } from './helpers/keyboardHandlers';

export enum CellAlign {
Start = 'flex-start',
Expand Down Expand Up @@ -53,6 +54,7 @@ export function Cell({
multiSelectCornerCellRef,
setCursorMode,
registerEventListener,
disabledKeyboardInteractions,
} = useTableEditorContext();

const isActive = rowIndex === selectedRow && columnIndex === selectedColumn;
Expand Down Expand Up @@ -89,10 +91,14 @@ export function Cell({
return setCursorMode(CursorMode.Edit);
}

if (disabledKeyboardInteractions.has(KeyboardInteraction.ExitEditMode)) {
return;
}

setCursorMode(CursorMode.Visual);
setActiveCell(rowIndex, columnIndex);
},
[setActiveCell, isActive, columnIndex],
[setActiveCell, isActive, columnIndex, disabledKeyboardInteractions],
);

useLayoutEffect(() => {
Expand Down
11 changes: 8 additions & 3 deletions browser/data-browser/src/components/TableEditor/TableEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { usePasteCommand } from './hooks/usePasteCommand';
import { DndWrapper } from './DndWrapper';
import { VisuallyHidden } from '../VisuallyHidden';
import { useClickAwayListener } from '../../hooks/useClickAwayListener';
import { KeyboardInteraction } from './helpers/keyboardHandlers';

const ARIA_TABLE_USAGE =
'Use the arrow keys to navigate the table. Press enter to edit a cell. Press escape to exit edit mode.';
Expand Down Expand Up @@ -99,8 +100,8 @@ function FancyTableInner<T>({
const scrollerRef = useRef<HTMLDivElement>(null);
const headerRef = useRef<HTMLDivElement>(null);

const { listRef, tableRef, setCursorMode } = useTableEditorContext();

const { listRef, tableRef, setCursorMode, disabledKeyboardInteractions } =
useTableEditorContext();
const [onScroll, setOnScroll] = useState<OnScroll>(() => undefined);

const { templateColumns, contentRowWidth, resizeCell } = useCellSizes(
Expand All @@ -110,8 +111,12 @@ function FancyTableInner<T>({
);

const handleClickOutside = useCallback(() => {
if (disabledKeyboardInteractions.has(KeyboardInteraction.ExitEditMode)) {
return;
}

setCursorMode(CursorMode.Visual);
}, []);
}, [disabledKeyboardInteractions]);

useClickAwayListener([tableRef], handleClickOutside, true);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {
core,
JSONValue,
properties,
Store,
useArray,
useResource,
useStore,
} from '@tomic/react';
import React, { useCallback, useEffect, useMemo } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { FaPlus, FaTimes } from 'react-icons/fa';
import * as RadixPopover from '@radix-ui/react-popover';
import { styled } from 'styled-components';
Expand All @@ -27,6 +27,7 @@ import {
useCellOptions,
} from '../../../components/TableEditor';
import { useTableEditorContext } from '../../../components/TableEditor/TableEditorContext';
import { CellOptions } from '../../../components/TableEditor/hooks/useCellOptions';

const TAG_SPACING = '0.5rem';

Expand All @@ -35,67 +36,67 @@ const emptyArray: string[] = [];
function buildListWithTitles(
store: Store,
subjects: string[],
ignore: string[],
): { subject: string; title: string }[] {
return subjects.map(subject => {
const resource = store.getResourceLoading(subject);
const title = resource?.get(properties.shortname) ?? subject;

return { subject, title: title as string };
});
return subjects
.filter(v => !ignore.includes(v))
.map(subject => {
const resource = store.getResourceLoading(subject);
const title = resource?.get(core.properties.shortname) ?? subject;

return { subject, title: title as string };
});
}

function ResourceArrayCellEdit({
value,
property,
onChange,
}: EditCellProps<JSONValue>): JSX.Element {
const val = (value as string[]) ?? emptyArray;

const store = useStore();
const propertyResource = useResource(property);
const [allowsOnly] = useArray(propertyResource, properties.allowsOnly);
const [filteredTags, setFilteredTags] = React.useState<string[]>(allowsOnly);
const [open, setOpen] = React.useState(true);
const [selectedIndex, setSelectedIndex] = React.useState(0);
const [focusIndex, setFocusIndex] = React.useState(0);
const [allowsOnly] = useArray(propertyResource, core.properties.allowsOnly);
const [query, setQuery] = useState('');
const filteredTags = useMemo(() => {
const listWithTitles = buildListWithTitles(store, allowsOnly, val);

return listWithTitles
.filter(v => v.title.includes(query))
.map(ft => ft.subject);
}, [store, allowsOnly, val, query]);
const [open, setOpen] = useState(true);
const [selectedIndex, setSelectedIndex] = useState(0);

const { activeCellRef } = useTableEditorContext();

const val = (value as string[]) ?? emptyArray;

const cellOptions = useMemo(() => {
const cellOptions = useMemo((): CellOptions => {
const disabledKeyboardInteractions = new Set<KeyboardInteraction>([
KeyboardInteraction.EditNextRow,
]);

if (focusIndex !== 0) {
disabledKeyboardInteractions.add(KeyboardInteraction.EditPreviousCell);
}

if (focusIndex !== val.length) {
disabledKeyboardInteractions.add(KeyboardInteraction.EditNextCell);
if (open) {
disabledKeyboardInteractions.add(KeyboardInteraction.ExitEditMode);
}

return {
disabledKeyboardInteractions,
hideActiveIndicator: true,
};
}, [focusIndex, val]);
}, [val, open]);

useCellOptions(cellOptions);

const listWithTitles = useMemo(
() => buildListWithTitles(store, allowsOnly),
[allowsOnly],
);
// const listWithTitles = useMemo(
// () => buildListWithTitles(store, allowsOnly, val),
// [allowsOnly, val],
// );

const handleSearch = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const query = stringToSlug(e.target.value);
const filtered = listWithTitles.filter(v => v.title.includes(query));
setFilteredTags(filtered.map(v => v.subject));
setSelectedIndex(0);
},
[listWithTitles],
);
const handleSearch = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
setQuery(stringToSlug(e.target.value));
setSelectedIndex(0);
}, []);

const handleAddTag = useCallback(
(subject: string) => {
Expand Down Expand Up @@ -152,13 +153,10 @@ function ResourceArrayCellEdit({
return (
<AbsoluteCell>
<Row gap={TAG_SPACING} center wrapItems>
{val.map((v, i) => (
{val.map(v => (
<Tag subject={v} key={v}>
<TagIconButton
title='remove tag'
onFocus={() => {
setFocusIndex(i);
}}
onClick={() => handleRemoveTag(v)}
>
<FaTimes />
Expand All @@ -167,16 +165,11 @@ function ResourceArrayCellEdit({
))}
<Popover
defaultOpen
noLock
open={open}
onOpenChange={setOpen}
Trigger={
<IconButton
title='Add tag'
as={RadixPopover.Trigger}
onFocus={() => {
setFocusIndex(val.length);
}}
>
<IconButton title='Add tag' as={RadixPopover.Trigger}>
<StyledIcon />
</IconButton>
}
Expand Down
22 changes: 13 additions & 9 deletions browser/data-browser/src/views/TablePage/PropertyForm/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,10 @@ interface TagWrapperProps {
color: string;
}

const TagWrapper = styled.span`
--tag-dark-color: ${(props: TagWrapperProps) =>
setLightness(0.11, props.color)};
--tag-mid-color: ${(props: TagWrapperProps) =>
setLightness(0.4, props.color)};
--tag-light-color: ${(props: TagWrapperProps) =>
const TagWrapper = styled.span<TagWrapperProps>`
--tag-dark-color: ${props => setLightness(0.11, props.color)};
--tag-mid-color: ${props => setLightness(0.4, props.color)};
--tag-light-color: ${props =>
setSaturation(0.5, setLightness(0.9, props.color))};
display: inline-flex;
gap: 0.5rem;
Expand Down Expand Up @@ -99,9 +97,14 @@ export function SelectableTag({
}: SelectableTagProps): JSX.Element {
const { color, text } = useTagData(subject);

const handleClick = useCallback(() => {
onClick(subject);
}, [onClick]);
const handleClick: React.MouseEventHandler = useCallback(
e => {
e.preventDefault();
e.stopPropagation();
onClick(subject);
},
[onClick],
);

const className = selected ? 'selected-tag' : '';

Expand All @@ -111,6 +114,7 @@ export function SelectableTag({
as='button'
onClick={handleClick}
className={className}
tabIndex={-1}
>
{text}
</TagWrapperButton>
Expand Down

0 comments on commit 69ec1b0

Please sign in to comment.