Skip to content

(PLAT-4216) MultiSearch + Key bugfix + remove status prop from dataTableEager #174

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export const CheckboxGroup = Object.assign(
cl['bk-checkbox-group'],
{ [cl['bk-checkbox-group--horizontal']]: orientation === 'horizontal' },
{ [cl['bk-checkbox-group--vertical']]: orientation === 'vertical' },
propsRest.className,
)}
contentClassName={cl['bk-checkbox-group__content']}
>
Expand Down
10 changes: 10 additions & 0 deletions src/components/forms/controls/DateTimePicker/DateTimePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ export type DateTimePickerProps = Omit<ComponentProps<'div'>, 'onChange'> & {
/** A Date object to hold the date and time. */
date: null | Date,

/** A Date object limit min selectable date. */
minDate: null | Date,

/** A Date object limit max selectable date. */
maxDate: null | Date,

/** A callback function that is called when either the date or the time picker is changed. */
onChange: ((date: null | Date, event?: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>) => void),

Expand All @@ -32,6 +38,8 @@ export const DateTimePicker = (props: DateTimePickerProps) => {
const {
date,
onChange,
minDate,
maxDate,
dateFormat = 'MM/dd/yyyy',
placeholderText = 'MM/DD/YYYY',
...propsRest
Expand Down Expand Up @@ -65,6 +73,8 @@ export const DateTimePicker = (props: DateTimePickerProps) => {
onChange={onChange}
dateFormat={dateFormat}
placeholderText={placeholderText}
{...(minDate ? { minDate: new Date(minDate) } : {})}
{...(maxDate ? { maxDate: new Date(maxDate) } : {})}
/>
<TimePicker
aria-label="Time input"
Expand Down
64 changes: 60 additions & 4 deletions src/components/overlays/DropdownMenu/DropdownMenuProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,38 @@ export type DropdownMenuProviderProps = Omit<ComponentProps<typeof DropdownMenu>

/** Enable more precise tracking of the anchor, at the cost of performance. */
enablePreciseTracking?: undefined | boolean,

/** For controlled open state. */
open?: boolean,

/** When controlled, callback to set state. */
onOpenChange?: (isOpen: boolean) => void,

/** (optional) Use an existing DOM node as the positioning anchor. */
anchorRef?: React.RefObject<HTMLElement | null>,
};

export type DropdownRef = {
setIsOpen: (open: boolean) => void,
isOpen: boolean,
floatingEl: HTMLElement | null,
};

/**
* Provider for a dropdown menu overlay with its trigger.
*/
export const DropdownMenuProvider = Object.assign(
(props: DropdownMenuProviderProps) => {
React.forwardRef<DropdownRef, DropdownMenuProviderProps>((props, forwardRef) => {
const {
label,
children,
unstyled = false,
items,
placement = 'bottom',
enablePreciseTracking,
open: controlledOpen,
onOpenChange: controlledOnOpenChange,
anchorRef,
...propsRest
} = props;

Expand All @@ -75,6 +94,19 @@ export const DropdownMenuProvider = Object.assign(
fallbackAxisSideDirection: 'none',
fallbackStrategy: 'initialPlacement',
},
floatingUiOptions: {
...(
typeof controlledOpen !== 'undefined' ?
{
open: controlledOpen,
...(
typeof controlledOnOpenChange !== 'undefined' ?
{ onOpenChange: controlledOnOpenChange } : {}
),

} : {}
),
},
floatingUiInteractions: context => [
useListNavigation(context, {
listRef,
Expand All @@ -83,7 +115,31 @@ export const DropdownMenuProvider = Object.assign(
}),
],
});


// keep internal state in sync with the controlled prop
React.useEffect(() => {
if (controlledOpen !== undefined) {
setIsOpen(controlledOpen);
}
}, [controlledOpen, setIsOpen]);

// Use external element as the reference, if provided
React.useLayoutEffect(() => {
if (anchorRef?.current) {
refs.setReference(anchorRef.current);
}
}, [anchorRef?.current, refs.setReference]);

const dropdownRef = React.useMemo<DropdownRef>(() => ({
isOpen,
setIsOpen,
get floatingEl() {
return refs.floating.current;
},
}), [isOpen, setIsOpen, refs.floating]);

React.useImperativeHandle(forwardRef, () => dropdownRef, [dropdownRef]);

const context: DropdownMenuContext = React.useMemo((): DropdownMenuContext => ({
optionProps: () => getItemProps(),
selectedOption: selected?.optionKey ?? null,
Expand Down Expand Up @@ -139,13 +195,13 @@ export const DropdownMenuProvider = Object.assign(
...propsRest,
className: cx(propsRest.className),
})}
ref={mergeRefs<HTMLUListElement>(refs.setFloating, propsRest.ref)}
ref={refs.setFloating}
data-placement={placementEffective}
>
{items}
</DropdownMenu>
</DropdownMenuContext>
);
},
}),
{ Action, Option },
);
76 changes: 67 additions & 9 deletions src/components/tables/DataTable/DataTableEager.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as Filtering from './filtering/Filtering.ts';
import type { Fields, FilterQuery } from '../MultiSearch/filterQuery.ts';

import { Panel } from '../../containers/Panel/Panel.tsx';
import * as MultiSearch from '../MultiSearch/MultiSearch.tsx';
import * as DataTablePlugins from './plugins/useRowSelectColumn.tsx';
import * as DataTableEager from './DataTableEager.tsx';

Expand Down Expand Up @@ -117,7 +118,7 @@ const DataTableEagerTemplate = (props: dataTeableEagerTemplateProps) => {
plugins={[DataTablePlugins.useRowSelectColumn]}
>
<DataTableEager.Search />
<DataTableEager.DataTableEager status={{ error: null, loading: false, ready: true }} />
<DataTableEager.DataTableEager />
</DataTableEager.TableProviderEager>
</Panel>
);
Expand All @@ -139,6 +140,8 @@ const DataTableEagerWithFilterTemplate = (props: dataTeableEagerTemplateProps) =
const filtered = Filtering.filterByQuery(fields, itemsAsRecord, filters);
setFilteredItems(Object.values(filtered) as User[]);
}, [filters, itemsAsRecord]);

const query = React.useCallback((filters: FilterQuery) => { setFilters(filters); }, []);

return (
<Panel>
Expand All @@ -149,7 +152,8 @@ const DataTableEagerWithFilterTemplate = (props: dataTeableEagerTemplateProps) =
getRowId={(item: User) => item.id}
plugins={[DataTablePlugins.useRowSelectColumn]}
>
<DataTableEager.DataTableEager status={{ error: null, loading: false, ready: true }} />
<MultiSearch.MultiSearch query={query} fields={fields} filters={filters}/>
<DataTableEager.DataTableEager />
</DataTableEager.TableProviderEager>
</Panel>
);
Expand Down Expand Up @@ -206,13 +210,13 @@ export const AsyncInitialization = {
render: (args: dataTeableEagerTemplateProps) => <DataTableEagerTemplate {...args} />,
};

// export const WithFilter = {
// args: {
// columns,
// items: generateData({ numItems: 45 }),
// },
// render: (args: dataTeableEagerTemplateProps) => <DataTableEagerWithFilterTemplate {...args} />,
// };
export const WithFilter = {
args: {
columns,
items: generateData({ numItems: 45 }),
},
render: (args: dataTeableEagerTemplateProps) => <DataTableEagerWithFilterTemplate {...args} />,
};

const moreColumns = [
...columns,
Expand All @@ -223,35 +227,89 @@ const moreColumns = [
Cell: ({ value }: { value: string }) => value,
disableSortBy: false,
disableGlobalFilter: true,
className: 'user-table__column',
},
{
id: 'dummy_2',
accessor: (user: User) => user.email,
Header: 'Email',
disableSortBy: false,
disableGlobalFilter: true,
className: 'user-table__column',
},
{
id: 'dummy_3',
accessor: (user: User) => user.company,
Header: 'Company',
disableSortBy: false,
disableGlobalFilter: true,
className: 'user-table__column',
},
{
id: 'dummy_4',
accessor: (user: User) => user.company,
Header: 'Company',
disableSortBy: false,
disableGlobalFilter: true,
className: 'user-table__column',
},
{
id: 'dummy_5',
accessor: (user: User) => user.company,
Header: 'Company',
disableSortBy: false,
disableGlobalFilter: true,
className: 'user-table__column',
},
{
id: 'dummy_6',
accessor: (user: User) => user.company,
Header: 'Company',
disableSortBy: false,
disableGlobalFilter: true,
className: 'user-table__column',
},
{
id: 'dummy_7',
accessor: (user: User) => user.company,
Header: 'Company',
disableSortBy: false,
disableGlobalFilter: true,
className: 'user-table__column',
},
{
id: 'dummy_8',
accessor: (user: User) => user.company,
Header: 'Company',
disableSortBy: false,
disableGlobalFilter: true,
className: 'user-table__column',
},
{
id: 'dummy_9',
accessor: (user: User) => user.company,
Header: 'Company',
disableSortBy: false,
disableGlobalFilter: true,
className: 'user-table__column',
},
{
id: 'dummy_10',
accessor: (user: User) => user.company,
Header: 'Company',
disableSortBy: false,
disableGlobalFilter: true,
className: 'user-table__column',
},
{
id: 'dummy_11',
accessor: (user: User) => user.company,
Header: 'Company',
disableSortBy: false,
disableGlobalFilter: true,
className: 'user-table__column',
},

];
// FIXME: example with horizontal scroll
// export const WithScroll = {
Expand Down
2 changes: 1 addition & 1 deletion src/components/tables/DataTable/DataTableEager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export const MultiSearch = (props: React.ComponentPropsWithoutRef<typeof MultiSe
};
MultiSearch.displayName = 'MultiSearch';

export type DataTableEagerProps = Omit<React.ComponentProps<typeof DataTableSync>, 'table'> & {
export type DataTableEagerProps = Omit<React.ComponentProps<typeof DataTableSync>, 'table' | 'status'> & {
children?: React.ReactNode,
className?: ClassNameArgument,
footer?: React.ReactNode,
Expand Down
4 changes: 3 additions & 1 deletion src/components/tables/DataTable/table/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export const DataTable = <D extends object>(props: DataTableProps<D>) => {
const headerGroup: undefined | ReactTable.HeaderGroup<D> = table.headerGroups[0];
if (!headerGroup) { return null; }

const { key, ...HeaderGroupPropsRest } = headerGroup.getHeaderGroupProps();

return (
<table
{...table.getTableProps()}
Expand All @@ -52,7 +54,7 @@ export const DataTable = <D extends object>(props: DataTableProps<D>) => {
{columnGroups}

<thead>
<tr {...headerGroup.getHeaderGroupProps()}>
<tr key={key} {...HeaderGroupPropsRest}>
{/*<th/> {/ * Empty header for the selection checkbox column */}

{headerGroup.headers.map((column: ReactTable.HeaderGroup<D>) => {
Expand Down
Loading