From 3ed5d88fdc176e4eea5042b95287a579d3aa6c6f Mon Sep 17 00:00:00 2001 From: Rohan Bansal Date: Fri, 6 Dec 2024 16:48:36 +0530 Subject: [PATCH 1/4] feat: use pinia to track table state --- aform/package.json | 2 +- atable/package.json | 3 +- atable/src/components/ACell.vue | 95 ++---- atable/src/components/AExpansionRow.vue | 19 +- atable/src/components/ARow.vue | 47 +-- atable/src/components/ATable.vue | 91 +++--- atable/src/components/ATableHeader.vue | 29 +- atable/src/components/ATableModal.vue | 13 +- atable/src/components/index.ts | 120 -------- atable/src/index.ts | 8 +- atable/src/stores/table.ts | 209 +++++++++++++ atable/src/types/index.ts | 4 +- beam/package.json | 2 +- code_editor/package.json | 2 +- common/config/rush/pnpm-lock.yaml | 307 ++++++++++---------- common/reviews/api/atable.api.md | 6 +- desktop/package.json | 2 +- examples/atable/list.story.vue | 20 +- examples/docbuilder/components/Listview.vue | 8 +- examples/package.json | 2 +- graphql_client/package.json | 2 +- node_editor/package.json | 2 +- stonecrop/package.json | 4 +- utilities/package.json | 2 +- 24 files changed, 510 insertions(+), 489 deletions(-) delete mode 100644 atable/src/components/index.ts create mode 100644 atable/src/stores/table.ts diff --git a/aform/package.json b/aform/package.json index 73684ec8..8e6abcb2 100644 --- a/aform/package.json +++ b/aform/package.json @@ -45,7 +45,7 @@ "@stonecrop/themes": "workspace:*", "@stonecrop/utilities": "workspace:*", "@vueuse/core": "^11.1.0", - "vue": "^3.5.6" + "vue": "^3.5.11" }, "devDependencies": { "@microsoft/api-documenter": "^7.25.3", diff --git a/atable/package.json b/atable/package.json index 7f566914..b27ae0b8 100644 --- a/atable/package.json +++ b/atable/package.json @@ -49,7 +49,8 @@ "@stonecrop/utilities": "workspace:*", "@vueuse/components": "^10.11.0", "@vueuse/core": "^11.1.0", - "vue": "^3.5.6" + "pinia": "^2.3.0", + "vue": "^3.5.11" }, "devDependencies": { "@microsoft/api-documenter": "^7.25.3", diff --git a/atable/src/components/ACell.vue b/atable/src/components/ACell.vue index c2cc2e77..c264d75a 100644 --- a/atable/src/components/ACell.vue +++ b/atable/src/components/ACell.vue @@ -13,9 +13,9 @@ @blur="updateCellData" @input="updateCellData" @click="showModal" - @mousedown="showModal" class="atable-cell" - :class="pinned ? 'sticky-column' : ''"> + :class="pinned ? 'sticky-column' : ''" + v-on-click-outside="store.closeModal"> import { KeypressHandlers, defaultKeypressHandlers, useKeyboardNav } from '@stonecrop/utilities' +import { vOnClickOutside } from '@vueuse/components' import { useElementBounding } from '@vueuse/core' -import { computed, CSSProperties, inject, ref, useTemplateRef } from 'vue' +import { computed, CSSProperties, ref, useTemplateRef } from 'vue' -import TableDataStore from '.' -import type { CellContext } from '@/types' +import { createTableStore } from '@/stores/table' import { isHtmlString } from '@/utils' const { colIndex, rowIndex, - tableid, + store, addNavigation = true, tabIndex = 0, } = defineProps<{ colIndex: number rowIndex: number - tableid: string + store: ReturnType addNavigation?: boolean | KeypressHandlers tabIndex?: number pinned?: boolean }>() -const tableData = inject(tableid) const cellRef = useTemplateRef('cell') const { bottom, left } = useElementBounding(cellRef) // keep a shallow copy of the original cell value for comparison -const originalData = tableData.cellData(colIndex, rowIndex) +const originalData = store.getCellData(colIndex, rowIndex) +const displayValue = store.getCellDisplayValue(colIndex, rowIndex) const currentData = ref('') const cellModified = ref(false) -const table = tableData.table -const column = tableData.columns[colIndex] -const row = tableData.rows[rowIndex] +const column = store.columns[colIndex] +const row = store.rows[rowIndex] const textAlign = column.align || 'center' const cellWidth = column.width || '40ch' const isHtmlValue = computed(() => { // TODO: check if display value is a native DOM element - return typeof displayValue.value === 'string' ? isHtmlString(displayValue.value) : false + return typeof displayValue === 'string' ? isHtmlString(displayValue) : false }) const cellStyle = computed((): CSSProperties => { @@ -77,34 +76,10 @@ const cellStyle = computed((): CSSProperties => { width: cellWidth, backgroundColor: !cellModified.value ? 'inherit' : 'var(--sc-cell-modified)', fontWeight: !cellModified.value ? 'inherit' : 'bold', - paddingLeft: getIndent(colIndex, tableData.display[rowIndex]?.indent), + paddingLeft: store.getIndent(colIndex, store.display[rowIndex]?.indent), } }) -const displayValue = computed(() => { - const cellData = tableData.cellData(colIndex, rowIndex) - return getFormattedValue(cellData) -}) - -const getFormattedValue = (value: any) => { - const format = column.format - - if (!format) { - return value - } - - if (typeof format === 'function') { - return format(value, { table, row, column }) - } else if (typeof format === 'string') { - // parse format function from string - // eslint-disable-next-line @typescript-eslint/no-implied-eval - const formatFn: (value: any, context?: CellContext) => string = Function(`"use strict";return (${format})`)() - return formatFn(value, { table, row, column }) - } - - return value -} - const showModal = () => { if (column.mask) { // TODO: add masking to cell values @@ -112,21 +87,23 @@ const showModal = () => { } if (column.modalComponent) { - tableData.modal.visible = true - tableData.modal.colIndex = colIndex - tableData.modal.rowIndex = rowIndex - tableData.modal.parent = cellRef.value - tableData.modal.top = bottom.value - tableData.modal.left = left.value - tableData.modal.width = cellWidth - - if (typeof column.modalComponent === 'function') { - tableData.modal.component = column.modalComponent({ table, row, column }) - } else { - tableData.modal.component = column.modalComponent - } + store.$patch(state => { + state.modal.visible = true + state.modal.colIndex = colIndex + state.modal.rowIndex = rowIndex + state.modal.parent = cellRef.value + state.modal.top = bottom.value + state.modal.left = left.value + state.modal.width = cellWidth + + if (typeof column.modalComponent === 'function') { + state.modal.component = column.modalComponent({ table: state.table, row, column }) + } else { + state.modal.component = column.modalComponent + } - tableData.modal.componentProps = column.modalComponentExtraProps + state.modal.componentProps = column.modalComponentExtraProps + }) } } @@ -161,7 +138,7 @@ if (addNavigation) { // if (event) { // // custom components need to handle their own updateData, this is the default // if (!column.component) { -// tableData.setCellData(rowIndex, colIndex, cell.value.innerHTML) +// store.setCellData(rowIndex, colIndex, cell.value.innerHTML) // } // cellModified.value = true // } @@ -177,7 +154,7 @@ const updateCellData = () => { if (cellRef.value) { // only apply changes if the cell value has changed after being mounted if (column.format) { - cellModified.value = cellRef.value.textContent !== getFormattedValue(originalData) + cellModified.value = cellRef.value.textContent !== store.getFormattedValue(colIndex, rowIndex, originalData) } else { cellModified.value = cellRef.value.textContent !== originalData } @@ -187,19 +164,11 @@ const updateCellData = () => { cellRef.value.dispatchEvent(new Event('change')) if (!column.format) { // TODO: need to setup reverse format function - tableData.setCellData(rowIndex, colIndex, currentData.value) + store.setCellData(rowIndex, colIndex, currentData.value) } } } } - -const getIndent = (colIndex: number, indentLevel?: number) => { - if (indentLevel && colIndex === 0 && indentLevel > 0) { - return `${indentLevel}ch` - } else { - return 'inherit' - } -}