From c9175c175641a69b2fb69d96755136a6f03c45d2 Mon Sep 17 00:00:00 2001 From: curt Date: Tue, 28 Jan 2025 15:24:20 -0600 Subject: [PATCH 1/4] changed amodal to calculate the cell position based on cell and row sizes. Amodal position changed from fixed to absolute --- atable/src/components/ACell.vue | 1 + atable/src/components/ATable.vue | 5 +- atable/src/components/ATableModal.vue | 52 +++++++----- ...able-modal-z-sorting_2025-01-28-21-19.json | 10 +++ examples/atable/list.story.vue | 82 ++++++++++++++++++- 5 files changed, 126 insertions(+), 24 deletions(-) create mode 100644 common/changes/@stonecrop/atable/fix-atable-modal-z-sorting_2025-01-28-21-19.json diff --git a/atable/src/components/ACell.vue b/atable/src/components/ACell.vue index 21f1d5c2..d2a19fea 100644 --- a/atable/src/components/ACell.vue +++ b/atable/src/components/ACell.vue @@ -103,6 +103,7 @@ const showModal = () => { state.modal.bottom = bottom state.modal.width = width state.modal.height = height + state.modal.cell = cellRef.value if (typeof column.modalComponent === 'function') { state.modal.component = column.modalComponent({ table: state.table, row, column }) diff --git a/atable/src/components/ATable.vue b/atable/src/components/ATable.vue index 652ad57d..44bbee52 100644 --- a/atable/src/components/ATable.vue +++ b/atable/src/components/ATable.vue @@ -175,7 +175,7 @@ defineExpose({ store }) .sticky-index { position: sticky; left: 0px; - z-index: 1; + z-index: 10; order: 0; } @@ -185,7 +185,7 @@ td.sticky-column, th.sticky-index, td.sticky-index { position: sticky; - z-index: 1; + z-index: 10; order: 0; background: white; } @@ -209,6 +209,7 @@ td.sticky-index { box-sizing: border-box; table-layout: auto; width: auto; + overflow: clip; /* border-left:4px solid var(--sc-form-border); */ } .atable th { diff --git a/atable/src/components/ATableModal.vue b/atable/src/components/ATableModal.vue index bc4b14bc..c74e87f1 100644 --- a/atable/src/components/ATableModal.vue +++ b/atable/src/components/ATableModal.vue @@ -14,37 +14,47 @@ const { store } = defineProps<{ store: ReturnType }>() const amodalRef = useTemplateRef('amodal') const { width, height } = useElementBounding(amodalRef) -const { y: scrollY } = useWindowScroll() const amodalStyles = computed(() => { if (!(store.modal.height && store.modal.width && store.modal.left && store.modal.bottom)) return - const body = document.body - const html = document.documentElement + const table = getTable(store.modal.cell) + const maxHeight = table.offsetHeight + const maxWidth = table.offsetWidth - const maxHeight = Math.max( - body.scrollHeight, - body.offsetHeight, - html.clientHeight, - html.scrollHeight, - html.offsetHeight - ) - const maxWidth = Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth) + /* Y Positioning */ + const headerHeight = table.querySelector('thead').offsetHeight //height of the header matches row height + const offsetY = store.modal.rowIndex //offset for each table row adding one pixel to its position (probably something to do with border?) + const cellY = (store.modal.rowIndex + 1) * store.modal.height // the y position of the cell clicked + const modalY = cellY + headerHeight + offsetY + const modalPositionY = modalY + height.value < maxHeight ? modalY : modalY - store.modal.height - height.value - const modalY = - store.modal.bottom + height.value + scrollY.value <= maxHeight - ? store.modal.bottom - : store.modal.bottom - height.value - store.modal.height + let modalX = 0 - const modalX = - store.modal.left + width.value <= maxWidth ? store.modal.left : store.modal.left - (width.value - store.modal.width) + //need to get the cumulative width of each cell that comes before this one + const row = store.modal.cell.parentNode + for (let i = 0; i < store.modal.cell.cellIndex; i++) { + modalX += row.children[i].offsetWidth + } + + const modalPositionX = modalX + width.value <= maxWidth ? modalX : modalX - (width.value - store.modal.width) return { - left: `${modalX}px`, - top: `${modalY}px`, + left: `${modalPositionX}px`, + top: `${modalPositionY}px`, } }) +const getTable = htmlElementNode => { + while (htmlElementNode) { + htmlElementNode = htmlElementNode.parentNode + if (htmlElementNode.tagName.toLowerCase() === 'table') { + return htmlElementNode + } + } + return undefined +} + const handleInput = (event: Event) => { event.stopPropagation() } @@ -54,8 +64,8 @@ const handleInput = (event: Event) => { @import url('@stonecrop/themes/default.css'); .amodal { - position: fixed; + position: absolute; background-color: var(--sc-row-color-zebra-dark); - z-index: 1000; + z-index: 5; } diff --git a/common/changes/@stonecrop/atable/fix-atable-modal-z-sorting_2025-01-28-21-19.json b/common/changes/@stonecrop/atable/fix-atable-modal-z-sorting_2025-01-28-21-19.json new file mode 100644 index 00000000..9611cdac --- /dev/null +++ b/common/changes/@stonecrop/atable/fix-atable-modal-z-sorting_2025-01-28-21-19.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@stonecrop/atable", + "comment": "amodal uses cell and row sizes to calculate position", + "type": "none" + } + ], + "packageName": "@stonecrop/atable" +} \ No newline at end of file diff --git a/examples/atable/list.story.vue b/examples/atable/list.story.vue index 0967ed7b..643c1506 100644 --- a/examples/atable/list.story.vue +++ b/examples/atable/list.story.vue @@ -31,7 +31,14 @@ - +
+ +
+
+ +
+ +
@@ -229,6 +236,79 @@ const pinned_logs = ref({ }, ], }) +const pinned_extra_logs = ref({ + rows: http_data, + columns: [ + { + label: 'Home Page', + name: 'home_page', + type: 'Data', + align: 'left', + edit: false, + width: '30ch', + pinned: true, + format: (value: { title?: string; value?: any }) => `${value.title}`, + }, + { + label: 'Report Date', + name: 'report_date', + type: 'component', + align: 'center', + edit: true, + width: '25ch', + pinned: false, + modalComponent: 'DateInput', + format: (value: string | number) => new Date(value).toLocaleDateString('en-US'), + }, + { + label: 'HTTP Method', + name: 'http_method', + type: 'Data', + align: 'left', + edit: true, + width: '20ch', + pinned: false, + }, + { + label: 'HTTP Method', + name: 'http_method', + type: 'Data', + align: 'left', + edit: true, + width: '20ch', + pinned: false, + }, + { + label: 'HTTP Method', + name: 'http_method', + type: 'Data', + align: 'left', + edit: true, + width: '20ch', + pinned: false, + }, + { + label: 'Report Date', + name: 'report_date', + type: 'component', + align: 'center', + edit: true, + width: '25ch', + pinned: false, + modalComponent: 'DateInput', + format: (value: string | number) => new Date(value).toLocaleDateString('en-US'), + }, + { + label: 'HTTP Method', + name: 'http_method', + type: 'Data', + align: 'left', + edit: true, + width: '20ch', + pinned: false, + }, + ], +}) const inbox = ref({ rows: inbox_data, From 25dc1026524e9bdb4a67695ab10e1f8266604a57 Mon Sep 17 00:00:00 2001 From: curt Date: Wed, 29 Jan 2025 12:07:57 -0600 Subject: [PATCH 2/4] amodal row height calculation gets the height of rows instead of assuming they are all the same height --- atable/src/components/ATableModal.vue | 29 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/atable/src/components/ATableModal.vue b/atable/src/components/ATableModal.vue index c74e87f1..369f91d9 100644 --- a/atable/src/components/ATableModal.vue +++ b/atable/src/components/ATableModal.vue @@ -19,33 +19,38 @@ const amodalStyles = computed(() => { if (!(store.modal.height && store.modal.width && store.modal.left && store.modal.bottom)) return const table = getTable(store.modal.cell) - const maxHeight = table.offsetHeight - const maxWidth = table.offsetWidth + const maxHeight = table.offsetHeight || 0 + const maxWidth = table.offsetWidth || 0 - /* Y Positioning */ - const headerHeight = table.querySelector('thead').offsetHeight //height of the header matches row height - const offsetY = store.modal.rowIndex //offset for each table row adding one pixel to its position (probably something to do with border?) - const cellY = (store.modal.rowIndex + 1) * store.modal.height // the y position of the cell clicked - const modalY = cellY + headerHeight + offsetY - const modalPositionY = modalY + height.value < maxHeight ? modalY : modalY - store.modal.height - height.value + /* Get the Y position of the cell clicked by getting the cumulative height of prior rows + the header (if present) */ + + let modalY = 0 + for (let j = 0; j < store.modal.rowIndex; j++) { + modalY += table.rows[j].offsetHeight + } + const headerHeight = table.querySelector('thead').offsetHeight || 0 + modalY += headerHeight + store.modal.height + modalY = modalY + height.value < maxHeight ? modalY : modalY - store.modal.height - height.value + + /* Get the X position of the cell clicked by getting the cumulative width of prior cells within the row */ let modalX = 0 - //need to get the cumulative width of each cell that comes before this one const row = store.modal.cell.parentNode for (let i = 0; i < store.modal.cell.cellIndex; i++) { modalX += row.children[i].offsetWidth } - const modalPositionX = modalX + width.value <= maxWidth ? modalX : modalX - (width.value - store.modal.width) + modalX = modalX + width.value <= maxWidth ? modalX : modalX - (width.value - store.modal.width) return { - left: `${modalPositionX}px`, - top: `${modalPositionY}px`, + left: `${modalX}px`, + top: `${modalY}px`, } }) const getTable = htmlElementNode => { + //return the closest table ancestor to this element while (htmlElementNode) { htmlElementNode = htmlElementNode.parentNode if (htmlElementNode.tagName.toLowerCase() === 'table') { From d7e8f0def1f2f47fa6b61ced91aec9d974239c9a Mon Sep 17 00:00:00 2001 From: Rohan Bansal Date: Thu, 30 Jan 2025 12:56:39 +0530 Subject: [PATCH 3/4] fix: use offsets to determine relative heights/widths --- atable/src/components/ACell.vue | 2 +- atable/src/components/ATable.vue | 1 - atable/src/components/ATableModal.vue | 53 ++++++------------- atable/src/stores/table.ts | 2 +- atable/src/types/index.ts | 1 + ...able-modal-z-sorting_2025-01-28-21-19.json | 2 +- common/reviews/api/atable.api.md | 7 +++ docs/atable/atable.createtablestore.md | 8 ++- docs/atable/atable.tablemodal.md | 1 + examples/atable/list.story.vue | 3 ++ 10 files changed, 37 insertions(+), 43 deletions(-) diff --git a/atable/src/components/ACell.vue b/atable/src/components/ACell.vue index d2a19fea..429787f0 100644 --- a/atable/src/components/ACell.vue +++ b/atable/src/components/ACell.vue @@ -98,7 +98,7 @@ const showModal = () => { state.modal.visible = true state.modal.colIndex = colIndex state.modal.rowIndex = rowIndex - // TODO: typing refs somehow resolves to unref'd value; probably a bug in API Extractor? + // TODO: typing refs somehow resolves to unref'd value; probably a bug in TS? state.modal.left = left state.modal.bottom = bottom state.modal.width = width diff --git a/atable/src/components/ATable.vue b/atable/src/components/ATable.vue index 44bbee52..3a83205b 100644 --- a/atable/src/components/ATable.vue +++ b/atable/src/components/ATable.vue @@ -193,7 +193,6 @@ td.sticky-index { .sticky-column-edge, .atable th.sticky-column-edge { border-right: 1px solid var(--sc-row-border-color); - border-right-width: 1px; } diff --git a/atable/src/components/ATableModal.vue b/atable/src/components/ATableModal.vue index 369f91d9..8039eb30 100644 --- a/atable/src/components/ATableModal.vue +++ b/atable/src/components/ATableModal.vue @@ -1,11 +1,11 @@