feat: Upgrade template based on projects made with it
Some checks failed
Build, check & Test / run (push) Failing after 42s
Some checks failed
Build, check & Test / run (push) Failing after 42s
Signed-off-by: Florian Bouillon <f.bouillon@aptatio.com>
This commit is contained in:
47
src/components/global/Table/Table.astro
Normal file
47
src/components/global/Table/Table.astro
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
import { objectClone } from '@dzeio/object-util'
|
||||
import type TableProps from './TableProps'
|
||||
export interface Props extends TableProps {}
|
||||
|
||||
const props = objectClone(Astro.props)
|
||||
delete props.header
|
||||
delete props.data
|
||||
---
|
||||
<table {...props}>
|
||||
<thead>
|
||||
<tr data-row="0">
|
||||
{Astro.props.header?.map((it, idx) => <th data-cell={idx}>{it}</th>)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Astro.props.data?.map((row, rowIdx) => <tr data-row={rowIdx}>{row.map((it, cellIdx) => <td data-cell={cellIdx}>{it}</td>)}</tr>)}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<style>
|
||||
table {
|
||||
@apply flex w-full flex-col border-1 rounded-lg overflow-clip
|
||||
}
|
||||
table :global(th) {
|
||||
@apply font-medium
|
||||
}
|
||||
table :global(thead),
|
||||
table :global(tbody),
|
||||
table :global(tr) {
|
||||
@apply flex justify-between
|
||||
}
|
||||
table :global(thead),
|
||||
table :global(tbody) {
|
||||
@apply flex-col
|
||||
}
|
||||
table :global(th),
|
||||
table :global(td) {
|
||||
@apply block w-full py-2 px-4 text-right
|
||||
}
|
||||
table :global(tr) {
|
||||
@apply border-gray-200
|
||||
}
|
||||
table :global(thead) {
|
||||
@apply bg-gray-100 border-b-1 border-gray-200
|
||||
}
|
||||
</style>
|
4
src/components/global/Table/TableProps.ts
Normal file
4
src/components/global/Table/TableProps.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default interface TableProps extends astroHTML.JSX.TableHTMLAttributes {
|
||||
header?: Array<string | number> | null | undefined
|
||||
data?: Array<Array<string | number>> | null | undefined
|
||||
}
|
95
src/components/global/Table/TableUtil.ts
Normal file
95
src/components/global/Table/TableUtil.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import type Props from './TableProps'
|
||||
|
||||
export function updateTable(comp: HTMLTableElement, data: Props, options?: {
|
||||
keepHeaders?: boolean
|
||||
keepData?: boolean
|
||||
}) {
|
||||
const head = comp.querySelector('thead > tr')
|
||||
const body = comp.querySelector('tbody')
|
||||
|
||||
if (!head || !body) {
|
||||
console.error('could not update table')
|
||||
return
|
||||
}
|
||||
|
||||
const curHeaders = head.querySelectorAll('th')
|
||||
const newHeaders = data.header ?? []
|
||||
const headersLength = Math.max(newHeaders.length, curHeaders?.length ?? 0)
|
||||
|
||||
for (let headerIdx = 0; headerIdx < headersLength; headerIdx++) {
|
||||
const headerHTML = curHeaders[headerIdx]
|
||||
const headerContent = newHeaders[headerIdx]
|
||||
// new el, add it
|
||||
if (!headerHTML) {
|
||||
const el = document.createElement('th')
|
||||
el.innerText = headerContent as string
|
||||
el.dataset.idx = headerIdx.toString()
|
||||
head.appendChild(el)
|
||||
// header too large, remove
|
||||
} else if (!headerContent && !options?.keepHeaders) {
|
||||
head.removeChild(headerHTML)
|
||||
// replace content
|
||||
} else if(!options?.keepHeaders) {
|
||||
headerHTML.innerText = (headerContent ?? '').toString()
|
||||
}
|
||||
}
|
||||
|
||||
const curBody = body.querySelectorAll('tr')
|
||||
const newBody = data.data ?? []
|
||||
const bodyLength = Math.max(newBody.length, curBody.length ?? 0)
|
||||
|
||||
for (let bodyRowIdx = 0; bodyRowIdx < bodyLength; bodyRowIdx++) {
|
||||
const bodyRowHTML = curBody[bodyRowIdx]
|
||||
const bodyRowContent = newBody[bodyRowIdx]
|
||||
// new el, add it
|
||||
if (!bodyRowHTML) {
|
||||
const row = document.createElement('tr')
|
||||
row.dataset.row = bodyRowIdx.toString()
|
||||
for (let cellIdx = 0; cellIdx < (bodyRowContent as Array<string>).length; cellIdx++) {
|
||||
const cellContent = (bodyRowContent as Array<string>)[cellIdx] as string
|
||||
const cell = document.createElement('td')
|
||||
cell.dataset.cell = cellIdx.toString()
|
||||
cell.innerText = cellContent
|
||||
row.appendChild(cell)
|
||||
}
|
||||
body.appendChild(row)
|
||||
// body too large, remove row
|
||||
} else if (!bodyRowContent) {
|
||||
body.removeChild(bodyRowHTML)
|
||||
// replace row
|
||||
} else {
|
||||
const bodyRowHTML = curBody[bodyRowIdx] as HTMLTableRowElement
|
||||
const cells = bodyRowHTML!.querySelectorAll('td')
|
||||
const cellLength = Math.max(cells.length, bodyRowContent.length)
|
||||
for (let cellIdx = 0; cellIdx < cellLength; cellIdx++) {
|
||||
const currCell = cells[cellIdx];
|
||||
const newCell = bodyRowContent[cellIdx];
|
||||
// new el, add it
|
||||
if (!currCell) {
|
||||
const el = document.createElement('td')
|
||||
el.dataset.cell = cellIdx.toString()
|
||||
el.innerText = newCell as string
|
||||
bodyRowHTML.appendChild(el)
|
||||
// header too large, remove
|
||||
} else if (!newCell && !options?.keepData) {
|
||||
bodyRowHTML.removeChild(currCell)
|
||||
// replace content
|
||||
} else if(!options?.keepData) {
|
||||
currCell.innerText = (newCell ?? '').toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function setOnTableClick(table: HTMLTableElement, fn: (row: number, cell: number) => void | Promise<void>) {
|
||||
table.querySelector('tbody')?.classList?.add('hover:cursor-pointer')
|
||||
table.querySelectorAll<HTMLTableCellElement>('td').forEach((it) => {
|
||||
it.addEventListener('click', () => {
|
||||
const row = it.parentElement as HTMLTableRowElement
|
||||
const rowIdx = parseInt(row.dataset.row as string)
|
||||
const cellIdx = parseInt(it.dataset.cell as string)
|
||||
fn(rowIdx, cellIdx)
|
||||
})
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user