Skip to content

Commit

Permalink
added ktable to playground
Browse files Browse the repository at this point in the history
  • Loading branch information
BabyElias committed Jun 3, 2024
1 parent b85a6d3 commit 2784a07
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 147 deletions.
27 changes: 23 additions & 4 deletions docs/pages/playground.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
{ text: 'Level 2 ', link: { path: '#' } },
]"
/> -->
<KTable :headers="tableHeaders" :rows="tableRows" caption="User Information Table" />


<!-- Play around with your component here: -->

Expand All @@ -36,12 +38,29 @@
so you can also use `data`, `methods`, etc.
as usual if helpful
*/
import KTable from '../../lib/KTable/KTable.vue';
export default {
name: 'Playground',
data() {
return {};
},
methods: {},
components: {
KTable,
},
data() {
return {
tableHeaders: [
{ label: 'Name', dataType: 'string' },
{ label: 'Age', dataType: 'numeric' },
{ label: 'Birth Date', dataType: 'date' },
{ label: 'City', dataType: 'string' },
{ label: 'Misc', dataType: 'others' },
],
tableRows: [
['Alice', 25, '1999-05-12', 'New York', 'Example'],
['Bob', 30, '1994-02-22', 'San Francisco', 'Example'],
['Charlie', 35, '1989-12-15', 'Chicago', 'Example'],
],
};
},
};
</script>
289 changes: 146 additions & 143 deletions lib/KTable/KTable.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<template>

<div class="k-table">
<table>
<caption v-if="caption">
Expand Down Expand Up @@ -37,159 +38,161 @@
</tbody>
</table>
</div>

</template>

<script>
import KTableGridItem from './KTableGridItem.vue';
export default {
name: 'KTable',
components: {
KTableGridItem,
},
props: {
headers: {
type: Array,
required: true,
validator: function (value) {
return value.every(
(header) =>
['label', 'dataType'].every((key) => key in header) &&
['string', 'numeric', 'date', 'others'].includes(header.dataType)
);
},
import KTableGridItem from './KTableGridItem.vue';
export default {
name: 'KTable',
components: {
KTableGridItem,
},
rows: {
type: Array,
required: true,
props: {
headers: {
type: Array,
required: true,
validator: function(value) {
return value.every(
header =>
['label', 'dataType'].every(key => key in header) &&
['string', 'numeric', 'date', 'others'].includes(header.dataType)
);
},
},
rows: {
type: Array,
required: true,
},
caption: {

Check warning on line 69 in lib/KTable/KTable.vue

View workflow job for this annotation

GitHub Actions / lint

Prop 'caption' requires default value to be set
type: String,
required: false,
},
},
caption: {
type: String,
required: false,
data() {
return {
sortKey: null,
sortOrder: 'asc',
};
},
},
data() {
return {
sortKey: null,
sortOrder: 'asc',
};
},
computed: {
sortedRows() {
if (this.sortKey === null) return this.rows;
const sortedRows = [...this.rows];
const sortHeader = this.headers[this.sortKey];
if (sortHeader.dataType === 'numeric') {
sortedRows.sort((a, b) => a[this.sortKey] - b[this.sortKey]);
} else if (sortHeader.dataType === 'string' || sortHeader.dataType === 'date') {
sortedRows.sort((a, b) => a[this.sortKey].localeCompare(b[this.sortKey]));
}
if (this.sortOrder === 'desc') {
sortedRows.reverse();
}
return sortedRows;
computed: {
sortedRows() {
if (this.sortKey === null) return this.rows;
const sortedRows = [...this.rows];
const sortHeader = this.headers[this.sortKey];
if (sortHeader.dataType === 'numeric') {
sortedRows.sort((a, b) => a[this.sortKey] - b[this.sortKey]);
} else if (sortHeader.dataType === 'string' || sortHeader.dataType === 'date') {
sortedRows.sort((a, b) => a[this.sortKey].localeCompare(b[this.sortKey]));
}
if (this.sortOrder === 'desc') {
sortedRows.reverse();
}
return sortedRows;
},
},
},
methods: {
handleSort(index) {
const clickedElement = event.target.tagName.toLowerCase();
if (clickedElement !== 'th' || this.headers[index].dataType === 'others') return;
if (this.sortKey === index) {
this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
} else {
this.sortKey = index;
this.sortOrder = 'asc';
}
},
handleKeydown(event, rowIndex, cellIndex) {
const key = event.key;
const totalRows = this.rows.length;
const totalCols = this.headers.length;
let nextRowIndex = rowIndex;
let nextCellIndex = cellIndex;
switch (key) {
case 'ArrowUp':
if (rowIndex === 0) {
this.focusHeader(cellIndex);
return;
} else if (rowIndex > 0) {
nextRowIndex = rowIndex - 1;
} else {
return;
}
break;
case 'ArrowDown':
if (rowIndex === -1) {
nextRowIndex = 0;
} else {
nextRowIndex = (rowIndex + 1) % totalRows;
}
break;
case 'ArrowLeft':
if (rowIndex === -1) {
nextCellIndex = cellIndex > 0 ? cellIndex - 1 : totalCols - 1;
} else if (cellIndex > 0) {
nextCellIndex = cellIndex - 1;
} else {
nextCellIndex = totalCols - 1;
nextRowIndex = rowIndex > 0 ? rowIndex - 1 : -1; // Move to the header row if needed
}
break;
case 'ArrowRight':
if (rowIndex === -1) {
if (cellIndex < totalCols - 1) {
nextCellIndex = cellIndex + 1;
methods: {
handleSort(index) {
const clickedElement = event.target.tagName.toLowerCase();
if (clickedElement !== 'th' || this.headers[index].dataType === 'others') return;
if (this.sortKey === index) {
this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
} else {
nextRowIndex = 0;
nextCellIndex = 0;
this.sortKey = index;
this.sortOrder = 'asc';
}
} else if (cellIndex < totalCols - 1) {
nextCellIndex = cellIndex + 1;
} else {
nextCellIndex = 0;
nextRowIndex = (rowIndex + 1) % totalRows;
}
break;
case 'Enter':
this.handleSort(cellIndex);
break;
default:
return;
}
this.focusCell(nextRowIndex, nextCellIndex);
event.preventDefault();
},
focusHeader(cellIndex) {
const nextHeader = this.$el.querySelector(`thead th:nth-child(${cellIndex + 1})`);
if (nextHeader) {
nextHeader.focus();
}
},
focusCell(rowIndex, cellIndex) {
let nextCell;
if (rowIndex === -1) {
nextCell = this.$el.querySelector(`thead th:nth-child(${cellIndex + 1})`);
} else {
nextCell = this.$el.querySelector(
`tbody tr:nth-child(${rowIndex + 1}) td:nth-child(${cellIndex + 1})`
);
}
if (nextCell) {
nextCell.focus();
}
},
handleKeydown(event, rowIndex, cellIndex) {
const key = event.key;
const totalRows = this.rows.length;
const totalCols = this.headers.length;
let nextRowIndex = rowIndex;
let nextCellIndex = cellIndex;
switch (key) {
case 'ArrowUp':
if (rowIndex === 0) {
this.focusHeader(cellIndex);
return;
} else if (rowIndex > 0) {
nextRowIndex = rowIndex - 1;
} else {
return;
}
break;
case 'ArrowDown':
if (rowIndex === -1) {
nextRowIndex = 0;
} else {
nextRowIndex = (rowIndex + 1) % totalRows;
}
break;
case 'ArrowLeft':
if (rowIndex === -1) {
nextCellIndex = cellIndex > 0 ? cellIndex - 1 : totalCols - 1;
} else if (cellIndex > 0) {
nextCellIndex = cellIndex - 1;
} else {
nextCellIndex = totalCols - 1;
nextRowIndex = rowIndex > 0 ? rowIndex - 1 : -1; // Move to the header row if needed
}
break;
case 'ArrowRight':
if (rowIndex === -1) {
if (cellIndex < totalCols - 1) {
nextCellIndex = cellIndex + 1;
} else {
nextRowIndex = 0;
nextCellIndex = 0;
}
} else if (cellIndex < totalCols - 1) {
nextCellIndex = cellIndex + 1;
} else {
nextCellIndex = 0;
nextRowIndex = (rowIndex + 1) % totalRows;
}
break;
case 'Enter':
this.handleSort(cellIndex);
break;
default:
return;
}
this.focusCell(nextRowIndex, nextCellIndex);
event.preventDefault();
},
focusHeader(cellIndex) {
const nextHeader = this.$el.querySelector(`thead th:nth-child(${cellIndex + 1})`);
if (nextHeader) {
nextHeader.focus();
}
},
focusCell(rowIndex, cellIndex) {
let nextCell;
if (rowIndex === -1) {
nextCell = this.$el.querySelector(`thead th:nth-child(${cellIndex + 1})`);
} else {
nextCell = this.$el.querySelector(
`tbody tr:nth-child(${rowIndex + 1}) td:nth-child(${cellIndex + 1})`
);
}
if (nextCell) {
nextCell.focus();
}
},
},
},
};
};
</script>


Expand Down

0 comments on commit 2784a07

Please sign in to comment.