From 739738c31e6f8b46997706515eb22dd6c034362c Mon Sep 17 00:00:00 2001 From: Adam Dunn Date: Tue, 1 Aug 2023 13:04:19 -0600 Subject: [PATCH 01/14] added mouseover event on row --- package-lock.json | 4 ++-- src/components/DataTable.vue | 13 ++++++++++++- src/hooks/useHoverRow.ts | 20 ++++++++++++++++++++ src/types/internal.d.ts | 2 +- 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 src/hooks/useHoverRow.ts diff --git a/package-lock.json b/package-lock.json index e811890..62deec6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vue3-easy-data-table", - "version": "1.5.44", + "version": "1.5.47", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vue3-easy-data-table", - "version": "1.5.44", + "version": "1.5.47", "license": "MIT", "dependencies": { "vue": "^3.2.45" diff --git a/src/components/DataTable.vue b/src/components/DataTable.vue index e51b2ab..05b9ab6 100644 --- a/src/components/DataTable.vue +++ b/src/components/DataTable.vue @@ -132,6 +132,9 @@ clickRow(item, 'single', $event); clickRowToExpand && updateExpandingItemIndexList(index + prevPageEndIndex, item, $event); }" + @mouseover="($event) => { + hoverRow(item, $event) + }" @dblclick="($event) => {clickRow(item, 'double', $event)}" @contextmenu="($event) => {contextMenuRow(item, $event)}" > @@ -318,10 +321,10 @@ import useTotalItems from '../hooks/useTotalItems'; import type { Header, Item } from '../types/main'; import type { HeaderForRender } from '../types/internal'; - // eslint-disable-next-line import/extensions import { generateColumnContent } from '../utils'; import propsWithDefault from '../propsWithDefault'; +import useHoverRow from '../hooks/useHoverRow'; const props = defineProps({ ...propsWithDefault, @@ -401,6 +404,7 @@ onMounted(() => { const emits = defineEmits([ 'clickRow', + 'hoverRow', 'contextmenuRow', 'selectRow', 'deselectRow', @@ -555,6 +559,13 @@ const { emits, ); +const { + hoverRow, +} = useHoverRow( + showIndex, + emits, +); + const contextMenuRow = (item: Item, $event: MouseEvent) => { if (preventContextMenuRow.value) $event.preventDefault(); emits('contextmenuRow', item, $event); diff --git a/src/hooks/useHoverRow.ts b/src/hooks/useHoverRow.ts new file mode 100644 index 0000000..9b17f65 --- /dev/null +++ b/src/hooks/useHoverRow.ts @@ -0,0 +1,20 @@ +import { Ref, ComputedRef } from 'vue'; +import type { Item } from '../types/main'; +import type { EmitsEventName, ClickEventType } from '../types/internal'; + +export default function useHoverRow( + showIndex: Ref, + emits: (event: EmitsEventName, ...args: any[]) => void, +) { + const hoverRow = (item: Item, $event: Event) => { + const hoverRowArgument = { ...item }; + const { index } = item; + delete hoverRowArgument.index; + hoverRowArgument.indexInCurrentPage = index; + emits('hoverRow', hoverRowArgument, $event); + }; + + return { + hoverRow, + }; +} diff --git a/src/types/internal.d.ts b/src/types/internal.d.ts index f16e893..45bfba6 100644 --- a/src/types/internal.d.ts +++ b/src/types/internal.d.ts @@ -26,4 +26,4 @@ export type ClickEventType = 'single' | 'double' export type MultipleSelectStatus = 'allSelected' | 'noneSelected' | 'partSelected' // eslint-disable-next-line max-len -export type EmitsEventName = 'clickRow' | 'selectRow' | 'deselectRow' | 'expandRow' | 'updateSort' | 'update:itemsSelected' | 'update:serverOptions' | 'updateFilter' | 'updatePageItems' | 'updateTotalItems' | 'selectAll' +export type EmitsEventName = 'clickRow' | 'hoverRow' | 'selectRow' | 'deselectRow' | 'expandRow' | 'updateSort' | 'update:itemsSelected' | 'update:serverOptions' | 'updateFilter' | 'updatePageItems' | 'updateTotalItems' | 'selectAll' From 26035a7b9266134f212282d933ffa1a03b995514 Mon Sep 17 00:00:00 2001 From: Adam Dunn Date: Wed, 30 Aug 2023 16:47:51 -0600 Subject: [PATCH 02/14] we can now hover on a row to see an element appear --- src/components/DataTable.vue | 33 ++++++++++++++++++++++++++++++++- src/hooks/useHoverRowElement.ts | 32 ++++++++++++++++++++++++++++++++ src/modes/Client.vue | 8 +++++++- src/propsWithDefault.ts | 4 ++++ src/types/internal.d.ts | 2 +- 5 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 src/hooks/useHoverRowElement.ts diff --git a/src/components/DataTable.vue b/src/components/DataTable.vue index 05b9ab6..e897ad4 100644 --- a/src/components/DataTable.vue +++ b/src/components/DataTable.vue @@ -133,7 +133,8 @@ clickRowToExpand && updateExpandingItemIndexList(index + prevPageEndIndex, item, $event); }" @mouseover="($event) => { - hoverRow(item, $event) + hoverRow(item, $event); + hoverRowToShowElement && updateHoverRowIndex(index + prevPageEndIndex, item, $event); }" @dblclick="($event) => {clickRow(item, 'double', $event)}" @contextmenu="($event) => {contextMenuRow(item, $event)}" @@ -200,6 +201,21 @@ /> + + + + + !!slots.pagination); const ifHasLoadingSlot = computed(() => !!slots.loading); const ifHasExpandSlot = computed(() => !!slots.expand); +const ifHasHoverSlot = computed(() => !!slots.hover); const ifHasBodySlot = computed(() => !!slots.body); // global dataTable $ref @@ -409,6 +427,7 @@ const emits = defineEmits([ 'selectRow', 'deselectRow', 'expandRow', + 'showHoverElement', 'updateSort', 'updateFilter', 'update:itemsSelected', @@ -542,6 +561,16 @@ const { emits, ); +const { + hoverRowIndex, + updateHoverRowIndex, + clearHoverRowIndex, +} = useHoverRowElement( + pageItems, + prevPageEndIndex, + emits, +); + const { fixedHeaders, lastFixedColumn, @@ -593,6 +622,7 @@ watch(loading, (newVal, oldVal) => { if (newVal === false && oldVal === true) { updateCurrentPaginationNumber(serverOptionsComputed.value.page); clearExpandingItemIndexList(); + clearHoverRowIndex(); } } }); @@ -613,6 +643,7 @@ watch([searchValue, filterOptions], () => { watch([currentPaginationNumber, clientSortOptions, searchField, searchValue, filterOptions], () => { clearExpandingItemIndexList(); + clearHoverRowIndex(); }, { deep: true }); watch(pageItems, (value) => { diff --git a/src/hooks/useHoverRowElement.ts b/src/hooks/useHoverRowElement.ts new file mode 100644 index 0000000..543c9a6 --- /dev/null +++ b/src/hooks/useHoverRowElement.ts @@ -0,0 +1,32 @@ +import { ref, Ref, ComputedRef } from 'vue'; +import type { Item } from '../types/main'; +import type { EmitsEventName } from '../types/internal'; + +export default function useHoverRowElement( + items: Ref, + prevPageEndIndex: ComputedRef, + emits: (event: EmitsEventName, ...args: any[]) => void, +) { + const hoverRowIndex = ref(); + + const updateHoverRowIndex = (index: number, hoverItem: Item, event: Event) => { + event.stopPropagation(); + if (index !== -1) { + hoverRowIndex.value = index; + } else { + const currentPageExpandIndex = items.value.findIndex((item) => JSON.stringify(item) === JSON.stringify(hoverItem)); + emits('showHoverElement', prevPageEndIndex.value + currentPageExpandIndex, hoverItem); + hoverRowIndex.value = prevPageEndIndex.value + currentPageExpandIndex; + } + }; + + const clearHoverRowIndex = () => { + hoverRowIndex.value = undefined; + }; + + return { + hoverRowIndex, + updateHoverRowIndex, + clearHoverRowIndex, + }; +} diff --git a/src/modes/Client.vue b/src/modes/Client.vue index bdbe259..2b39515 100644 --- a/src/modes/Client.vue +++ b/src/modes/Client.vue @@ -12,7 +12,7 @@ + + diff --git a/src/modes/Client.vue b/src/modes/Client.vue index 2b39515..a5b1edc 100644 --- a/src/modes/Client.vue +++ b/src/modes/Client.vue @@ -71,8 +71,8 @@ diff --git a/src/scss/vue3-easy-data-table.scss b/src/scss/vue3-easy-data-table.scss index b537a73..8671ede 100644 --- a/src/scss/vue3-easy-data-table.scss +++ b/src/scss/vue3-easy-data-table.scss @@ -258,6 +258,28 @@ table { cursor: pointer; } +// hover row feature related +.hover-row { + height: 0 !important; + visibility: visible; + + td { + height: 0; + padding: 0; + position: relative; + + div { + position: absolute; + margin-top: calc(var(--easy-table-body-row-height) * -1); + height: var(--easy-table-body-row-height); + background-color: inherit; + left: 0; + width: 100%; + z-index: 10; + } + } +} + .vue3-easy-data-table__footer { background-color: var(--easy-table-footer-background-color); color: var(--easy-table-footer-font-color); From 85d7915c748c7f07491943d2ab4ffa587accf055 Mon Sep 17 00:00:00 2001 From: Adam Dunn Date: Thu, 31 Aug 2023 09:21:11 -0600 Subject: [PATCH 04/14] mouseleave hides the hover element --- src/components/DataTable.vue | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/components/DataTable.vue b/src/components/DataTable.vue index d062008..22bda10 100644 --- a/src/components/DataTable.vue +++ b/src/components/DataTable.vue @@ -105,6 +105,7 @@ v-else-if="headerColumns.length" class="vue3-easy-data-table__body" :class="{'row-alternation': alternating}" + @mouseleave="hoverRowToShowElement && clearHoverRowIndex()" > -
+
- Date: Thu, 31 Aug 2023 10:49:52 -0600 Subject: [PATCH 05/14] getting alternating row color working --- src/components/DataTable.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/DataTable.vue b/src/components/DataTable.vue index 22bda10..e4bc7ae 100644 --- a/src/components/DataTable.vue +++ b/src/components/DataTable.vue @@ -204,12 +204,12 @@ -
+
Date: Thu, 31 Aug 2023 16:16:19 -0600 Subject: [PATCH 06/14] flexibly showing the checkbox --- src/components/DataTable.vue | 29 ++++++++++++++++++++++++----- src/scss/vue3-easy-data-table.scss | 2 +- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/components/DataTable.vue b/src/components/DataTable.vue index e4bc7ae..98d4d02 100644 --- a/src/components/DataTable.vue +++ b/src/components/DataTable.vue @@ -48,7 +48,7 @@ :style="getFixedDistance(header.value)" @click.stop="(header.sortable && header.sortType) ? updateSortField(header.value, header.sortType) : null" > - -
+
{ return undefined; }; -const getFixedDistance = (column: string, type: 'td' | 'th' = 'th') => { +const getHoverStyle = (index:number): string | undefined => { + + let checkBoxTDId = `checkBoxTD_${index}`; + let checkboxTD = document.getElementById(checkBoxTDId); + if(checkboxTD) + { + const width = checkboxTD.clientWidth + 2; + return `width: calc(100% - ${width}px); min-width: calc(100% - ${width}px); margin-left: ${width}px`; + } + + return undefined; +}; + +const getFixedDistance = (column: string, type: 'td' | 'th' = 'th', setMarginLeft: boolean = false) => { if (!fixedHeaders.value.length) return undefined; const columInfo = fixedColumnsInfos.value.find((info) => info.value === column); if (columInfo) { - return `left: ${columInfo.distance}px;z-index: ${type === 'th' ? 3 : 1};position: sticky;`; + if(!setMarginLeft) + { + return `left: ${columInfo.distance}px;z-index: ${type === 'th' ? 3 : 1};position: sticky;`; + } else { + return `margin-left: ${columInfo.distance}px;`; + } } return undefined; }; @@ -670,7 +689,7 @@ defineExpose({ updatePage, rowsPerPageOptions: rowsItemsComputed, rowsPerPageActiveOption: rowsPerPageRef, - updateRowsPerPageActiveOption: updateRowsPerPage, + updateRowsPerPageActiveOption: updateRowsPerPage }); diff --git a/src/scss/vue3-easy-data-table.scss b/src/scss/vue3-easy-data-table.scss index 8671ede..6ff3513 100644 --- a/src/scss/vue3-easy-data-table.scss +++ b/src/scss/vue3-easy-data-table.scss @@ -266,6 +266,7 @@ table { td { height: 0; padding: 0; + margin: 0; position: relative; div { @@ -274,7 +275,6 @@ table { height: var(--easy-table-body-row-height); background-color: inherit; left: 0; - width: 100%; z-index: 10; } } From da96b1d644f2b357078d9679941f3477a0969e3b Mon Sep 17 00:00:00 2001 From: Adam Dunn Date: Thu, 31 Aug 2023 16:28:12 -0600 Subject: [PATCH 07/14] clean up --- src/scss/vue3-easy-data-table.scss | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/scss/vue3-easy-data-table.scss b/src/scss/vue3-easy-data-table.scss index 6ff3513..4f2a7ca 100644 --- a/src/scss/vue3-easy-data-table.scss +++ b/src/scss/vue3-easy-data-table.scss @@ -261,7 +261,7 @@ table { // hover row feature related .hover-row { height: 0 !important; - visibility: visible; + padding: 0; td { height: 0; @@ -274,8 +274,6 @@ table { margin-top: calc(var(--easy-table-body-row-height) * -1); height: var(--easy-table-body-row-height); background-color: inherit; - left: 0; - z-index: 10; } } } From df95aa6a6572e3119f587dc71e20788ca84f1a31 Mon Sep 17 00:00:00 2001 From: Adam Dunn Date: Thu, 31 Aug 2023 16:38:37 -0600 Subject: [PATCH 08/14] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 362620f..2daca79 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "author": "HC200ok", "description": "A customizable and easy-to-use data table component made with Vue.js 3.x.", "private": false, - "version": "1.5.47", + "version": "1.5.48", "types": "./types/main.d.ts", "license": "MIT", "files": [ From 26988af0591a97f3d68646cf59dad234fdf03a23 Mon Sep 17 00:00:00 2001 From: Adam Dunn Date: Fri, 1 Sep 2023 17:02:01 -0600 Subject: [PATCH 09/14] package stuff --- package.json | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 362620f..4b256f6 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "vue3-easy-data-table", + "name": "wl-vue3-easy-data-table", "author": "HC200ok", "description": "A customizable and easy-to-use data table component made with Vue.js 3.x.", "private": false, @@ -10,13 +10,7 @@ "dist", "types" ], - "keywords": [ - "vue3", - "data-table-component", - "data-table", - "vue3-component", - "vue-component" - ], + "keywords": [], "homepage": "https://github.com/HC200ok/vue3-easy-data-table", "main": "./dist/vue3-easy-data-table.umd.js", "module": "./dist/vue3-easy-data-table.es.js", From 2e82d5b140e6f725c94d2dfe0aee2d2048840522 Mon Sep 17 00:00:00 2001 From: Adam Dunn Date: Fri, 1 Sep 2023 17:08:56 -0600 Subject: [PATCH 10/14] sometimes rows are taller do to more content. We handle this now. --- src/components/DataTable.vue | 4 +++- src/scss/vue3-easy-data-table.scss | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/DataTable.vue b/src/components/DataTable.vue index 98d4d02..5432dfa 100644 --- a/src/components/DataTable.vue +++ b/src/components/DataTable.vue @@ -616,8 +616,10 @@ const getHoverStyle = (index:number): string | undefined => { let checkboxTD = document.getElementById(checkBoxTDId); if(checkboxTD) { + console.log(checkboxTD) const width = checkboxTD.clientWidth + 2; - return `width: calc(100% - ${width}px); min-width: calc(100% - ${width}px); margin-left: ${width}px`; + const height = checkboxTD.clientHeight - 1; + return `width: calc(100% - ${width}px); min-width: calc(100% - ${width}px); margin-left: ${width}px; top: ${-height}px; height: ${height}px; min-height: ${height}px`; } return undefined; diff --git a/src/scss/vue3-easy-data-table.scss b/src/scss/vue3-easy-data-table.scss index 4f2a7ca..7ad7516 100644 --- a/src/scss/vue3-easy-data-table.scss +++ b/src/scss/vue3-easy-data-table.scss @@ -271,8 +271,6 @@ table { div { position: absolute; - margin-top: calc(var(--easy-table-body-row-height) * -1); - height: var(--easy-table-body-row-height); background-color: inherit; } } From b3fe5a71a03a309422d56bb3a5d1291266b7fa58 Mon Sep 17 00:00:00 2001 From: Adam Dunn Date: Fri, 1 Sep 2023 17:10:20 -0600 Subject: [PATCH 11/14] clean up --- src/components/DataTable.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/DataTable.vue b/src/components/DataTable.vue index 5432dfa..49a3759 100644 --- a/src/components/DataTable.vue +++ b/src/components/DataTable.vue @@ -616,7 +616,6 @@ const getHoverStyle = (index:number): string | undefined => { let checkboxTD = document.getElementById(checkBoxTDId); if(checkboxTD) { - console.log(checkboxTD) const width = checkboxTD.clientWidth + 2; const height = checkboxTD.clientHeight - 1; return `width: calc(100% - ${width}px); min-width: calc(100% - ${width}px); margin-left: ${width}px; top: ${-height}px; height: ${height}px; min-height: ${height}px`; From e7e6d356bdda0f4c5401798cbf82563f4c9c9499 Mon Sep 17 00:00:00 2001 From: Adam Dunn Date: Fri, 1 Sep 2023 17:12:09 -0600 Subject: [PATCH 12/14] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b256f6..055b835 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "author": "HC200ok", "description": "A customizable and easy-to-use data table component made with Vue.js 3.x.", "private": false, - "version": "1.5.47", + "version": "1.5.48", "types": "./types/main.d.ts", "license": "MIT", "files": [ From 0ebd136724a09fad4420988b663dfd2dc5b6ef1c Mon Sep 17 00:00:00 2001 From: Adam Dunn Date: Wed, 6 Sep 2023 08:41:33 -0600 Subject: [PATCH 13/14] adjusments --- package.json | 2 +- src/components/DataTable.vue | 36 +++++++++++++++++++++--------- src/scss/vue3-easy-data-table.scss | 19 ++++++++++++++++ 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 055b835..03dc1b1 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "author": "HC200ok", "description": "A customizable and easy-to-use data table component made with Vue.js 3.x.", "private": false, - "version": "1.5.48", + "version": "1.5.56", "types": "./types/main.d.ts", "license": "MIT", "files": [ diff --git a/src/components/DataTable.vue b/src/components/DataTable.vue index 49a3759..cccd363 100644 --- a/src/components/DataTable.vue +++ b/src/components/DataTable.vue @@ -210,7 +210,7 @@ -
+
{ return undefined; }; -const getHoverStyle = (index:number): string | undefined => { +// const getHoverStyle = (index:number): string | undefined => { - let checkBoxTDId = `checkBoxTD_${index}`; - let checkboxTD = document.getElementById(checkBoxTDId); - if(checkboxTD) - { - const width = checkboxTD.clientWidth + 2; - const height = checkboxTD.clientHeight - 1; - return `width: calc(100% - ${width}px); min-width: calc(100% - ${width}px); margin-left: ${width}px; top: ${-height}px; height: ${height}px; min-height: ${height}px`; - } +// let checkBoxTDId = `checkBoxTD_${index}`; +// let checkboxTD = document.getElementById(checkBoxTDId); +// if(checkboxTD) +// { +// const width = checkboxTD.clientWidth + 2; +// const height = checkboxTD.clientHeight - 1; +// return `width: calc(100% - ${width}px); min-width: calc(100% - ${width}px); margin-left: ${width}px; top: ${-height}px; height: ${height}px; min-height: ${height}px`; +// } - return undefined; +// return undefined; +// }; + +const getHoverStyle = (index:number): string | undefined => { + +let checkBoxTDId = `checkBoxTD_${index}`; +let checkboxTD = document.getElementById(checkBoxTDId); +if(checkboxTD) +{ + const width = checkboxTD.clientWidth + 2; + const height = checkboxTD.clientHeight; +return `margin-left: ${width}px; top: ${-height}px; height: ${height - 2}px; min-height: ${height - 2}px`; +} + +return undefined; }; const getFixedDistance = (column: string, type: 'td' | 'th' = 'th', setMarginLeft: boolean = false) => { diff --git a/src/scss/vue3-easy-data-table.scss b/src/scss/vue3-easy-data-table.scss index 7ad7516..0ab95a3 100644 --- a/src/scss/vue3-easy-data-table.scss +++ b/src/scss/vue3-easy-data-table.scss @@ -268,10 +268,29 @@ table { padding: 0; margin: 0; position: relative; + border: none; div { position: absolute; + right: 0px; + z-index: 10; background-color: inherit; + + &::before { + content: ""; + position: absolute; + top: 0; + left: -80px; + bottom: 0; + width: 90px; + background: linear-gradient(to right, transparent, var(--easy-table-body-row-background-color)) + } + } + + div.even-row { + &::before { + background: linear-gradient(to right, transparent, var(--easy-table-body-even-row-background-color)) + } } } } From d08c0a3eb69d742b63b0e85f8e3e6e43bff71f88 Mon Sep 17 00:00:00 2001 From: Adam Dunn Date: Wed, 6 Sep 2023 08:42:53 -0600 Subject: [PATCH 14/14] package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 03dc1b1..055b835 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "author": "HC200ok", "description": "A customizable and easy-to-use data table component made with Vue.js 3.x.", "private": false, - "version": "1.5.56", + "version": "1.5.48", "types": "./types/main.d.ts", "license": "MIT", "files": [