@ndlib/component-library 0.0.65 → 0.0.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,3 +7,4 @@ export declare const Default: Story;
7
7
  export declare const OmitColumn: Story;
8
8
  export declare const ResponsiveColumn: Story;
9
9
  export declare const ColumnGroup: Story;
10
+ export declare const Sortable: Story;
@@ -1,5 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Table, TableColumn } from '.';
3
+ import { SORT_DIRECTION, sortByKey } from '../../../utils/sortByKey';
4
+ import { useState } from 'react';
3
5
  const meta = {
4
6
  title: 'Elements/Table',
5
7
  component: Table,
@@ -71,3 +73,25 @@ export const ColumnGroup = {
71
73
  ]] })));
72
74
  },
73
75
  };
76
+ const SortableStory = () => {
77
+ const [sortConfig, setSortConfig] = useState({
78
+ key: 'name',
79
+ direction: SORT_DIRECTION.ASC,
80
+ });
81
+ console.log(sortConfig);
82
+ const sorted = sortByKey({
83
+ items: data,
84
+ config: sortConfig,
85
+ });
86
+ return (_jsxs(Table, Object.assign({ data: sorted, alternateRowColor: true, sortConfig: sortConfig, updateSort: setSortConfig }, { children: [_jsx(TableColumn, { header: "Name", dataKey: "name", sortable: true, sx: {
87
+ width: '160px',
88
+ } }), [
89
+ _jsx(TableColumn, Object.assign({ header: "Age", sortKey: "age", sortable: true, sx: {
90
+ width: '100px',
91
+ } }, { children: (row) => row.age })),
92
+ _jsx(TableColumn, { header: "Occupation", sortable: true, dataKey: "position" }),
93
+ ]] })));
94
+ };
95
+ export const Sortable = {
96
+ render: SortableStory,
97
+ };
@@ -13,7 +13,7 @@ const data = [
13
13
  col3: 'Cell 2-3',
14
14
  },
15
15
  ];
16
- export const testExample = (_jsxs(Table, Object.assign({ data: data }, { children: [_jsx(TableColumn, { header: "Column 1", dataKey: "col1" }), _jsx(TableColumn, Object.assign({ header: "Column 2" }, { children: (row) => row.col2 })), _jsx(TableColumn, { dataKey: "col3", header: _jsx("div", { children: "Column 3" }) })] })));
16
+ export const testExample = (_jsxs(Table, Object.assign({ data: data }, { children: [_jsx(TableColumn, { header: "Column 1", dataKey: "col1" }), _jsx(TableColumn, Object.assign({ header: "Column 2" }, { children: (row) => row.col2 })), _jsx(TableColumn, { dataKey: "col3", header: "Column 3" })] })));
17
17
  describe('Table', () => {
18
18
  it('renders all headers and cells', () => {
19
19
  const { getByText } = render(testExample);
@@ -1,8 +1,11 @@
1
1
  /// <reference types="react" />
2
2
  import { StyledElementProps, StylesProp } from '../../../theme';
3
+ import { SortConfig } from '../../../utils/sortByKey';
3
4
  type ColumnRenderFn<RowData> = (data: RowData) => React.ReactNode;
4
5
  type ColumnProps<RowData extends object> = {
5
- header: string | React.ReactNode;
6
+ header: string;
7
+ sortable?: boolean;
8
+ sortKey?: keyof RowData;
6
9
  dataKey?: keyof RowData;
7
10
  headerStyles?: StylesProp;
8
11
  align?: 'left' | 'center' | 'right';
@@ -14,6 +17,8 @@ type ColumnProps<RowData extends object> = {
14
17
  type ChildList = ChildList[] | JSX.Element | null | undefined;
15
18
  type TableProps<RowData> = StyledElementProps<HTMLTableElement, {
16
19
  data: RowData[];
20
+ sortConfig?: SortConfig<RowData>;
21
+ updateSort?: (sortConfig: SortConfig<RowData>) => void;
17
22
  children: ChildList[];
18
23
  cellStyles?: StylesProp;
19
24
  alternateRowColor?: boolean;
@@ -1,9 +1,17 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "theme-ui/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "theme-ui/jsx-runtime";
2
2
  import { useMemo } from 'react';
3
3
  import { COLOR } from '../../../theme/colors';
4
4
  import { useEnvironment } from '../../providers/env';
5
- import { TYPOGRAPHY_TYPE, typographyStyleMap } from '../../../theme/typography';
5
+ import { FONT_SIZE, TYPOGRAPHY_TYPE, typographyStyleMap, } from '../../../theme/typography';
6
6
  import { useMediaQuery } from '../../providers/media';
7
+ import { Row } from '../layout/Row';
8
+ import _ArrowDropDown from '@mui/icons-material/ArrowDropDown';
9
+ import _ArrowDropUp from '@mui/icons-material/ArrowDropUp';
10
+ import { importedDefaultComponentShim } from '../../../utils/misc';
11
+ import { Icon } from '../Icon';
12
+ import { SORT_DIRECTION } from '../../../utils/sortByKey';
13
+ const ArrowDropDown = importedDefaultComponentShim(_ArrowDropDown);
14
+ const ArrowDropUp = importedDefaultComponentShim(_ArrowDropUp);
7
15
  const useColumnSpec = (children) => {
8
16
  const headerList = [];
9
17
  const parseHeaders = (children) => {
@@ -41,7 +49,7 @@ export function TableColumn(props) {
41
49
  return null;
42
50
  }
43
51
  export function Table(props) {
44
- const { role, data, alternateRowColor = true, cellStyles, sx, children, showRowDividers = true, showColumnDividers = false, } = props;
52
+ const { role, data, alternateRowColor = true, cellStyles, sx, children, showRowDividers = true, showColumnDividers = false, sortConfig, updateSort, } = props;
45
53
  const cellTypographyStyles = typographyStyleMap[TYPOGRAPHY_TYPE.CONDENSED_TEXT_MEDIUM];
46
54
  const headerTypographyStyles = typographyStyleMap[TYPOGRAPHY_TYPE.CONTROL_MEDIUM];
47
55
  const { breakpoint } = useMediaQuery();
@@ -61,7 +69,20 @@ export function Table(props) {
61
69
  if (column.breakpoint && breakpoint < column.breakpoint) {
62
70
  return null;
63
71
  }
64
- return (_jsx("th", Object.assign({ role: "columnheader", sx: Object.assign(Object.assign({ textAlign: column.alignHeader || column.align || 'left', borderBottom: '1px solid', borderRight: showColumnDividers && !isLastColumn ? '1px solid' : 'none', borderColor: COLOR.LIGHT_GRAY, px: 3, pb: 1 }, headerTypographyStyles), column.headerStyles) }, { children: column.header }), i));
72
+ const canSort = sortConfig && column.sortable;
73
+ const sortKey = column.sortKey || column.dataKey;
74
+ const onSort = () => {
75
+ if (canSort) {
76
+ const direction = sortConfig.direction === SORT_DIRECTION.ASC
77
+ ? SORT_DIRECTION.DESC
78
+ : SORT_DIRECTION.ASC;
79
+ updateSort &&
80
+ updateSort({ key: sortKey, direction });
81
+ }
82
+ };
83
+ return (_jsx("th", Object.assign({ role: "columnheader", sx: Object.assign(Object.assign({ textAlign: column.alignHeader || column.align || 'left', borderBottom: '1px solid', borderRight: showColumnDividers && !isLastColumn ? '1px solid' : 'none', borderColor: COLOR.LIGHT_GRAY, px: 3, pb: 1 }, headerTypographyStyles), column.headerStyles) }, { children: _jsxs(Row, Object.assign({ onClick: onSort, tabIndex: canSort ? 0 : undefined, sx: { cursor: canSort ? 'pointer' : 'default' } }, { children: [column.header, canSort &&
84
+ sortConfig.key === sortKey &&
85
+ (sortConfig.direction === SORT_DIRECTION.ASC ? (_jsx(Icon, { icon: ArrowDropUp, sx: { ml: 1 }, size: FONT_SIZE.MD })) : (_jsx(Icon, { icon: ArrowDropDown, sx: { ml: 1 }, size: FONT_SIZE.MD })))] })) }), i));
65
86
  }) }) })), _jsx("tbody", Object.assign({ role: "rowgroup" }, { children: data.map((rowData, rowIndex) => {
66
87
  return (_jsx("tr", Object.assign({ role: "row" }, { children: columnSpec.map((column, columnIndex) => {
67
88
  if (column.breakpoint && breakpoint < column.breakpoint) {
package/dist/index.d.ts CHANGED
@@ -48,4 +48,6 @@ export { useAlerts, AlertsProvider, ALERT_TYPE, ALERT_DOMAIN, } from './componen
48
48
  export { MediaSizeProvider, useMediaQuery } from './components/providers/media';
49
49
  export { DialogsProvider, useDialog } from './components/providers/dialogs';
50
50
  export { useUniqueId } from './components/providers/uniqueIds';
51
+ export { sortByKey, SORT_DIRECTION } from './utils/sortByKey';
52
+ export type { SortConfig } from './utils/sortByKey';
51
53
  export { useHover } from './utils/hooks/useHover';
package/dist/index.js CHANGED
@@ -47,4 +47,5 @@ export { useAlerts, AlertsProvider, ALERT_TYPE, ALERT_DOMAIN, } from './componen
47
47
  export { MediaSizeProvider, useMediaQuery } from './components/providers/media';
48
48
  export { DialogsProvider, useDialog } from './components/providers/dialogs';
49
49
  export { useUniqueId } from './components/providers/uniqueIds';
50
+ export { sortByKey, SORT_DIRECTION } from './utils/sortByKey';
50
51
  export { useHover } from './utils/hooks/useHover';
@@ -0,0 +1,12 @@
1
+ export declare enum SORT_DIRECTION {
2
+ ASC = "ASC",
3
+ DESC = "DESC"
4
+ }
5
+ export type SortConfig<RowData> = {
6
+ key: keyof RowData;
7
+ direction: SORT_DIRECTION;
8
+ };
9
+ export declare function sortByKey<Item = any>(params: {
10
+ items: Item[];
11
+ config: SortConfig<Item>;
12
+ }): Item[];
@@ -0,0 +1,20 @@
1
+ export var SORT_DIRECTION;
2
+ (function (SORT_DIRECTION) {
3
+ SORT_DIRECTION["ASC"] = "ASC";
4
+ SORT_DIRECTION["DESC"] = "DESC";
5
+ })(SORT_DIRECTION || (SORT_DIRECTION = {}));
6
+ export function sortByKey(params) {
7
+ const { items, config: { key, direction }, } = params;
8
+ const newItems = [...items];
9
+ return newItems.sort((a, b) => {
10
+ if (a[key] < b[key] && direction === SORT_DIRECTION.ASC) {
11
+ return -1;
12
+ }
13
+ else if (b[key] < a[key] && direction === SORT_DIRECTION.DESC) {
14
+ return -1;
15
+ }
16
+ else {
17
+ return 1;
18
+ }
19
+ });
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndlib/component-library",
3
- "version": "0.0.65",
3
+ "version": "0.0.66",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "files": [