Skip to content

Commit

Permalink
feat: add useSortingOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
sgratzl committed May 24, 2021
1 parent 5c19bdf commit c206920
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 8 deletions.
24 changes: 24 additions & 0 deletions packages/_playground/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,30 @@ function MyFilterAction(props: { col: ColumnInstance<Row>; icons: ActionIcons })
);
}


function MyGroupingOptionAction(props: { col: ColumnInstance<Row>; icons: ActionIcons }) {
const col = props.col as unknown as ColumnInstance<Row> & UseFiltersColumnProps<Row>;

const [visible, setVisible] = useState(false);
const showGroupingDialog = useCallback(() => {
setVisible(!visible);
}, [visible, setVisible]);

return (
<>
<LineUpLiteFilterAction {...col} iconFilter={props.icons.filterColumn} toggleFilterColumn={showGroupingDialog} />
{visible && (
<div className="filter-dialog">
{col.render('Summary')}
<button onClick={showGroupingDialog} type="button">
Close
</button>
</div>
)}
</>
);
}

function Table({ isDarkTheme }: { isDarkTheme: boolean }) {
const columns: LineUpLiteColumn<Row>[] = useMemo(
() => [
Expand Down
1 change: 1 addition & 0 deletions packages/hooks/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ export * from './useRowSelectColumn';
export * from './useRowExpandColumn';
export * from './useRowRankColumn';
export * from './useGroupingOptions';
export * from './useSortingOptions';
export { default as IndeterminateCheckbox } from './IndeterminateCheckbox';
12 changes: 4 additions & 8 deletions packages/hooks/src/hooks/useGroupingOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,10 @@ import {
} from 'react-table';
import type { AnyObject, UnknownObject } from '../types';

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface UseGroupingOptionsOptions {}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type GroupingOptionsValue = any;
export type GroupingOptions<D extends AnyObject> = Array<{ id: IdType<D>; value: GroupingOptionsValue }>;

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface UseGroupingOptionsState<D extends AnyObject> {
groupingOptions: GroupingOptions<D>;
}
Expand All @@ -49,12 +45,12 @@ export interface UseGroupingOptionGroupingFunction<D extends AnyObject = Unknown
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface UseGroupingOptionsInstanceProps {}
export interface UseGroupingOptionsInstanceProps {
setGroupingOptions: (columnId: string, value: GroupingOptionsValue) => void;
}

export interface UseGroupingOptionsColumnProps {
setGroupingOptions: (
updater: ((groupingOption: GroupingOptionsValue) => GroupingOptionsValue) | GroupingOptionsValue
) => void;
setGroupingOptions: (value: GroupingOptionsValue) => void;
groupingOptions: GroupingOptionsValue;
}

Expand Down
127 changes: 127 additions & 0 deletions packages/hooks/src/hooks/useSortingOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/**
* @lineup-lite/hooks
* https://github.com/sgratzl/lineup-lite
*
* Copyright (c) 2021 Samuel Gratzl <[email protected]>
*/

import React from 'react';
import { actions, ActionType, CellProps, HeaderProps, Hooks, IdType, TableInstance, TableState } from 'react-table';
import type { AnyObject, UnknownObject } from '../types';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type SortingOptionsValue = any;
export type SortingOptions<D extends AnyObject> = Array<{ id: IdType<D>; value: SortingOptionsValue }>;

export interface UseSortingOptionsState<D extends AnyObject> {
sortingOptions: SortingOptions<D>;
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface UseSortingOptionsInstanceProps {
setSortingOptions: (columnId: string, value: SortingOptionsValue) => void;
}

export interface UseSortingOptionsColumnProps {
setSortingOptions: (value: SortingOptionsValue) => void;
sortingOptions: SortingOptionsValue;
}

export type SortingOptionsProps<D extends AnyObject = UnknownObject> = HeaderProps<D> & {
column: UseSortingOptionsColumnProps;
};
export type SortingOptionsCellProps<D extends AnyObject = UnknownObject> = CellProps<D> & {
column: UseSortingOptionsColumnProps;
};

export function useSortingOptions<D extends AnyObject = UnknownObject>(hooks: Hooks<D>): void {
hooks.stateReducers.push(reducer);
hooks.useInstance.push(useInstance);
}
useSortingOptions.pluginName = 'useSortingOptions';

// Actions
actions.setSortingOptions = 'setSortingOptions';

function reducer<D extends AnyObject = UnknownObject>(
state: TableState<D> & Partial<UseSortingOptionsState<D>>,
action: ActionType,
_previousState?: TableState<D>,
instance?: TableInstance<D>
): (TableState<D> & UseSortingOptionsState<D>) | undefined {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const { allColumns } = instance!;

if (action.type === actions.init) {
return {
sortingOptions: [],
...state,
};
}

if (action.type === actions.setRowState) {
const { columnId, sortingOptions } = action as unknown as {
columnId: string;
sortingOptions: Record<string, unknown>;
};

const column = allColumns.find((d) => d.id === columnId);

if (!column) {
throw new Error(`React-Table: Could not find a column with id: ${columnId}`);
}
const previousFilter = state.sortingOptions?.find((d) => d.id === columnId);
//
if (sortingOptions == null) {
return {
...state,
sortingOptions: state.sortingOptions?.filter((d) => d.id !== columnId) ?? [],
};
}

if (previousFilter) {
return {
...state,
sortingOptions:
state.sortingOptions?.map((d) => {
if (d.id === columnId) {
return { id: columnId, value: sortingOptions };
}
return d;
}) ?? [],
};
}

return {
...state,
sortingOptions: [...(state.sortingOptions ?? []), { id: columnId, value: sortingOptions }],
};
}

return undefined;
}

function useInstance<D extends AnyObject = UnknownObject>(instance: TableInstance<D>) {
const { dispatch, allColumns, state } = instance;
const { sortingOptions = [] } = state as Partial<UseSortingOptionsState<D>>;

const setSortingOptions = React.useCallback(
(columnId: string, value: Record<string, unknown>) => {
dispatch({ type: actions.setSortingOptions, columnId, sortingOptions: value });
},
[dispatch]
);
allColumns.forEach((column) => {
const cc = column as Partial<UseSortingOptionsColumnProps>;
// Provide the column a way of updating the filter value
cc.setSortingOptions = (val: Record<string, unknown>) => setSortingOptions(column.id, val);
// Provide the current filter value to the column for
// convenience
const found = sortingOptions.find((d) => d.id === column.id);
cc.sortingOptions = found && found.value;
});

Object.assign(instance, {
setSortingOptions,
});
}

0 comments on commit c206920

Please sign in to comment.