Skip to content

Commit

Permalink
Merge pull request #112 from komarovalexander/dev
Browse files Browse the repository at this point in the history
Add focused property and navigation actions
  • Loading branch information
komarovalexander authored Jan 24, 2021
2 parents e988b70 + aaf9f60 commit b057c29
Show file tree
Hide file tree
Showing 49 changed files with 651 additions and 136 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ka-table",
"version": "6.3.0",
"version": "6.4.0",
"license": "MIT",
"repository": "github:komarovalexander/ka-table",
"homepage": "https://komarovalexander.github.io/ka-table/#/overview",
Expand Down
2 changes: 1 addition & 1 deletion src/Demos/BootstrapDemo/editors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,4 @@ export const DateEditor: React.FC<IFilterRowEditorProps> = ({
/>
</>
);
};
};
2 changes: 1 addition & 1 deletion src/Demos/ColumnSettingsDemo/ColumnSettingsDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,4 @@ const ColumnSettingsDemo: React.FC = () => {
);
};

export default ColumnSettingsDemo;
export default ColumnSettingsDemo;
3 changes: 2 additions & 1 deletion src/Demos/Demos.scss
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ body {
top: -5px;
}
.new-badge, .upd-badge{
margin-left: 20px;
position: relative;
left: 20px;
padding: 0 7px;
background: rgba(118,74,188, 0.64);
color: white;
Expand Down
4 changes: 4 additions & 0 deletions src/Demos/Demos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import GroupingCustomRowDemo from './GroupingCustomRowDemo/GroupingCustomRowDemo
import GroupingDemo from './GroupingDemo/GroupingDemo';
import HoverRowDemo from './HoverRowDemo/HoverRowDemo';
import JsonDemo from './JsonDemo/JsonDemo';
import KeyboardNavigationDemo from './KeyboardNavigationDemo/KeyboardNavigationDemo';
import LoadingDemo from './LoadingDemo/LoadingDemo';
import ManyColumnsDemo from './ManyColumnsDemo/ManyColumnsDemo';
import ManyRowsDemo from './ManyRowsDemo/ManyRowsDemo';
Expand All @@ -53,6 +54,7 @@ import PrintDemo from './PrintDemo/PrintDemo';
import ReduxDemo from './ReduxDemo/ReduxDemo';
import RemoteDataDemo from './RemoteDataDemo/RemoteDataDemo';
import RemoteDataEditingDemo from './RemoteDataEditingDemo/RemoteDataEditingDemo';
import ResponsiveDemo from './ResponsiveDemo/ResponsiveDemo';
import RowReorderingDemo from './RowReorderingDemo/RowReorderingDemo';
import SearchDemo from './SearchDemo/SearchDemo';
import SelectionDemo from './SelectionDemo/SelectionDemo';
Expand Down Expand Up @@ -96,6 +98,7 @@ const demos: Demo[] = [
new Demo(GroupingDemo, '/grouping', 'Grouping', 'GroupingDemo', 'https://stackblitz.com/edit/table-grouping-js', 'https://stackblitz.com/edit/table-grouping-ts', 'Grouping'),
new Demo(HoverRowDemo, '/hover-row', 'Hover Row', 'HoverRowDemo', 'https://stackblitz.com/edit/table-hover-row-js', 'https://stackblitz.com/edit/table-hover-row-ts', 'Rows'),
new Demo(JsonDemo, '/json', 'Json', 'JsonDemo', 'https://stackblitz.com/edit/table-json-js', 'https://stackblitz.com/edit/table-json-ts', 'Remote Data'),
new Demo(KeyboardNavigationDemo, '/keyboard-navigation', 'Keyboard Navigation', 'KeyboardNavigationDemo', 'https://stackblitz.com/edit/table-keyboard-navigation-js', 'https://stackblitz.com/edit/table-keyboard-navigation-ts', 'Miscellaneous'),
new Demo(LoadingDemo, '/loading', 'Loading', 'LoadingDemo', 'https://stackblitz.com/edit/table-loading-js', 'https://stackblitz.com/edit/table-loading-ts', 'Miscellaneous'),
new Demo(ManyColumnsDemo, '/many-columns', 'Many Columns', 'ManyColumnsDemo', 'https://stackblitz.com/edit/table-many-columns-js', 'https://stackblitz.com/edit/table-many-columns-ts', 'Columns'),
new Demo(ManyRowsDemo, '/many-rows', '100K Rows', 'ManyRowsDemo', 'https://stackblitz.com/edit/table-many-rows-js', 'https://stackblitz.com/edit/table-many-rows-ts', 'Virtual Scrolling'),
Expand All @@ -108,6 +111,7 @@ const demos: Demo[] = [
new Demo(ReduxDemo, '/redux', 'Redux', 'ReduxDemo', 'https://stackblitz.com/edit/table-redux-js', 'https://stackblitz.com/edit/table-redux-ts', ''),
new Demo(RemoteDataDemo, '/remote-data', 'Load', 'RemoteDataDemo', 'https://stackblitz.com/edit/table-remote-data-js', 'https://stackblitz.com/edit/table-remote-data-ts', 'Remote Data'),
new Demo(RemoteDataEditingDemo, '/remote-data-editing', 'Editing', 'RemoteDataEditingDemo', 'https://stackblitz.com/edit/table-remote-data-editing-js', 'https://stackblitz.com/edit/table-remote-data-editing-ts', 'Remote Data'),
new Demo(ResponsiveDemo, '/responsive', 'Responsive', 'ResponsiveDemo', 'https://stackblitz.com/edit/table-responsive-js', 'https://stackblitz.com/edit/table-responsive-ts', 'Miscellaneous'),
new Demo(RowReorderingDemo, '/row-reordering', 'Row Reordering', 'RowReorderingDemo', 'https://stackblitz.com/edit/table-row-reordering-js', 'https://stackblitz.com/edit/table-row-reordering-ts', 'Rows'),
new Demo(SearchDemo, '/search', 'Search', 'SearchDemo', 'https://stackblitz.com/edit/table-search-js', 'https://stackblitz.com/edit/table-search-ts', 'Filtering'),
new Demo(SelectionDemo, '/selection', 'Selection - Multiple', 'SelectionDemo', 'https://stackblitz.com/edit/table-selection-js', 'https://stackblitz.com/edit/table-selection-ts', 'Selection'),
Expand Down
9 changes: 5 additions & 4 deletions src/Demos/DemosMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ const synonyms: { [value: string]: any[] } = {
'EditingRowDemo': ['Image', 'Button', 'Btn'],
'EventsDemo': ['Action', 'Click'],
'FilterRowCustomEditorDemo': ['filterRowCell'],
'FixedColumnDemo': ['Sticky'],
'ManyColumnsDemo': ['horizontal'],
'NullableCellDataDemo': ['groupsExpanded'],
'PagingDemo': ['pageSize'],
'ResponsiveDemo': ['Adaptive', 'Mobile'],
'RowReorderingDemo': ['Drag'],
'SearchDemo': ['No Data', 'Empty'],
'FixedColumnDemo': ['Sticky'],
'TabIndexDemo': ['keyboard navigation'],
'SelectionDemo': ['Checkbox']
'SelectionDemo': ['Checkbox'],
'TabIndexDemo': ['keyboard navigation']
};

const DemosMenu: React.FC<IDemosMenuProps> = ({ cases }) => {
Expand Down Expand Up @@ -84,4 +85,4 @@ const DemosMenu: React.FC<IDemosMenuProps> = ({ cases }) => {
);
};

export default DemosMenu;
export default DemosMenu;
3 changes: 3 additions & 0 deletions src/Demos/KeyboardNavigationDemo/KeyboardNavigation.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.ka-row:focus-within {
background: #F7FcFd;
}
10 changes: 10 additions & 0 deletions src/Demos/KeyboardNavigationDemo/KeyboardNavigationDemo.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom';

import KeyboardNavigationDemo from './KeyboardNavigationDemo';

it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<KeyboardNavigationDemo />, div);
ReactDOM.unmountComponentAtNode(div);
});
121 changes: 121 additions & 0 deletions src/Demos/KeyboardNavigationDemo/KeyboardNavigationDemo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import './KeyboardNavigation.scss';

import React, { useState } from 'react';

import { ITableProps, kaReducer, Table } from '../../lib';
import {
clearFocused, moveFocusedDown, moveFocusedLeft, moveFocusedRight, moveFocusedUp, openEditor,
setFocused, updatePageIndex, updateSortDirection,
} from '../../lib/actionCreators';
import { DataType, EditingMode, SortingMode } from '../../lib/enums';
import { DispatchFunc } from '../../lib/types';

const dataArray = Array(100).fill(undefined).map(
(_, index) => ({
column1: `column:1 row:${index}`,
column2: `column:2 row:${index}`,
column3: `column:3 row:${index}`,
column4: `column:4 row:${index}`,
id: index,
}),
);

const tablePropsInit: ITableProps = {
columns: [
{ key: 'column1', title: 'Column 1', dataType: DataType.String },
{ key: 'column2', title: 'Column 2', dataType: DataType.String },
{ key: 'column3', title: 'Column 3', dataType: DataType.String },
{ key: 'column4', title: 'Column 4', dataType: DataType.String },
],
data: dataArray,
rowKeyField: 'id',
sortingMode: SortingMode.Single,
editingMode: EditingMode.Cell,
paging: {
enabled: true,
pageIndex: 0,
pageSize: 10,
},
focused: {
cell: {
columnKey: 'column4',
rowKeyValue: 2
}
}
};

const KeyboardNavigationDemo: React.FC = () => {
const [tableProps, changeTableProps] = useState(tablePropsInit);
const dispatch: DispatchFunc = (action) => {
changeTableProps((prevState: ITableProps) => kaReducer(prevState, action));
};
return (
<>
<p style={{fontSize: 12}}>Use arrow keys to navigate by data cells</p>
<Table
{...tableProps}
childComponents={{
cell: {
elementAttributes: ({column, rowKeyValue, isEditableCell}) => {
if (isEditableCell) return undefined;

const cell = { columnKey: column.key, rowKeyValue }
const isFocused = cell.columnKey === tableProps.focused?.cell?.columnKey
&& cell.rowKeyValue === tableProps.focused?.cell?.rowKeyValue;
return {
tabIndex: 0,
ref: (ref: any) => isFocused && ref?.focus(),
onKeyUp: (e) => {
switch (e.keyCode){
case 39: dispatch(moveFocusedRight({ end: e.ctrlKey })); break;
case 37: dispatch(moveFocusedLeft({ end: e.ctrlKey })); break;
case 38: dispatch(moveFocusedUp({ end: e.ctrlKey })); break;
case 40: dispatch(moveFocusedDown({ end: e.ctrlKey })); break;
case 13:
dispatch(openEditor(cell.rowKeyValue, cell.columnKey));
dispatch(setFocused({ cellEditorInput: cell }));
break;
}
},
onFocus: () => !isFocused && dispatch(setFocused({ cell: { columnKey: column.key, rowKeyValue } })),
onKeyDown: (e) => e.keyCode !== 9 && e.preventDefault(),
onBlur: () => isFocused && dispatch(clearFocused())
}
},
},
cellEditorInput: {
elementAttributes: ({column, rowKeyValue}) => {
const isFocused = column.key === tableProps.focused?.cellEditorInput?.columnKey
&& rowKeyValue === tableProps.focused?.cellEditorInput?.rowKeyValue;
const cell = { columnKey: column.key, rowKeyValue };
return {
ref: (ref: any) => isFocused && ref?.focus(),
onKeyUp: (e) => e.keyCode === 13 && dispatch(setFocused({ cell })),
onBlur: (e, {baseFunc}) => {
baseFunc();
dispatch(clearFocused())
},
onFocus: () => !isFocused && dispatch(setFocused({ cell: { columnKey: column.key, rowKeyValue } })),
}
},
},
pagingIndex: {
elementAttributes: (props) => ({
tabIndex: 0,
onKeyUp: (e) => e.keyCode === 13 && dispatch(updatePageIndex(props.pageIndex))
}),
},
headCell: {
elementAttributes: (props) => ({
tabIndex: 0,
onKeyUp: (e) => e.keyCode === 13 && dispatch(updateSortDirection(props.column.key))
}),
},
}}
dispatch={dispatch}
/>
</>
);
};

export default KeyboardNavigationDemo;
4 changes: 2 additions & 2 deletions src/Demos/MenuItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export class MenuItem {
public isActive?: boolean;
}

const newItems: string[] = ['RemoteDataDemo', 'JsonDemo'];
const updateItems: string[] = ['RemoteData', 'RemoteDataEditingDemo'];
const newItems: string[] = ['ResponsiveDemo', 'KeyboardNavigationDemo'];
const updateItems: string[] = ['Miscellaneous'];

const MenuItems: React.FC<{ items: MenuItem[] }> = ({ items }) => {

Expand Down
2 changes: 1 addition & 1 deletion src/Demos/RemoteDataEditingDemo/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ export const DeleteRow: React.FC<ICellTextProps> = ({
alt=''
/>
);
};
};
52 changes: 52 additions & 0 deletions src/Demos/ResponsiveDemo/ResponsiveDemo.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.responsive-demo{
.ka{
width: 400px;
table {
border-collapse: collapse;
}

/* Force table to not be like tables anymore */
table, thead, tbody, th, td, tr {
display: block;
}

/* Hide table headers (but not display: none;, for accessibility) */
thead {
position: absolute;
top: -9999px;
left: -9999px;
}
tr:nth-of-type(even) {
background: #f6f6f6;
td{
border-bottom: 1px solid white;
}
}

tr { border: 1px solid #ccc; }

td.ka-cell {
/* Behave like a "row" */
border: none;
border-bottom: 1px solid #eee;
position: relative;
padding-left: 50%;
}

td.ka-cell:before {
/* Now like a table header */
position: absolute;
/* Top/left values mimic padding */
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
/* Label the data */
content: attr(data-column);

color: #000;
font-weight: bold;
}
}
}
10 changes: 10 additions & 0 deletions src/Demos/ResponsiveDemo/ResponsiveDemo.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom';

import ResponsiveDemo from './ResponsiveDemo';

it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<ResponsiveDemo />, div);
ReactDOM.unmountComponentAtNode(div);
});
59 changes: 59 additions & 0 deletions src/Demos/ResponsiveDemo/ResponsiveDemo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// open TS Example or JS Example to see how to override styles
import './ResponsiveDemo.scss';

import React, { useState } from 'react';

import { ITableProps, kaReducer, Table } from '../../lib';
import { DataType, EditingMode } from '../../lib/enums';
import { DispatchFunc } from '../../lib/types';

const dataArray = Array(10).fill(undefined).map(
(_, index) => ({
column1: `value:1 row:${index}`,
column2: `value:2 row:${index}`,
column3: `value:3 row:${index}`,
column4: `value:4 row:${index}`,
id: index,
}),
);

const tablePropsInit: ITableProps = {
columns: [
{ key: 'column1', title: 'Column 1', dataType: DataType.String },
{ key: 'column2', title: 'Column 2', dataType: DataType.String },
{ key: 'column3', title: 'Column 3', dataType: DataType.String },
{ key: 'column4', title: 'Column 4', dataType: DataType.String },
],
data: dataArray,
editingMode: EditingMode.Cell,
rowKeyField: 'id',
};

const ResponsiveDemo: React.FC = () => {
const [tableProps, changeTableProps] = useState(tablePropsInit);
const dispatch: DispatchFunc = (action) => {
changeTableProps((prevState: ITableProps) => kaReducer(prevState, action));
};

return (
<div className='responsive-demo'>
<Table
{...tableProps}
dispatch={dispatch}
childComponents={{
cell: {
elementAttributes: ({ column }) => ({
'data-column': column.title
} as any)
}
}}
/>
<br />
<div>
Based on the <a href='https://codepen.io/andornagy/pen/EVXpbR' target='_blank' rel='noopener noreferrer'>example</a>.
But notice that ka-table can be used with any adaptive approach of HTML tables.</div>
</div>
);
};

export default ResponsiveDemo;
2 changes: 1 addition & 1 deletion src/Demos/TabIndexDemo/hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ const useKaFocusRef = (focusedData: any) => {
}
};

export default useKaFocusRef;
export default useKaFocusRef;
8 changes: 2 additions & 6 deletions src/lib/Components/CellComponent/CellComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,11 @@ const CellComponent: React.FunctionComponent<ICellProps> = (props) => {
(
isEditableCell ?
(
<CellEditor
{...props}
/>
<CellEditor {...props} />
)
:
(
<CellText
{...props}
/>
<CellText {...props} />
)
)
}
Expand Down
Loading

0 comments on commit b057c29

Please sign in to comment.