feat(SW-441): Added table block component
This commit is contained in:
committed by
Pontus Dreij
parent
ef411b4cf9
commit
dfd40aa7aa
97
components/Blocks/Table/index.tsx
Normal file
97
components/Blocks/Table/index.tsx
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import {
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table"
|
||||||
|
import { useState } from "react"
|
||||||
|
|
||||||
|
import ScrollWrapper from "@/components/TempDesignSystem/ScrollWrapper"
|
||||||
|
import ShowMoreButton from "@/components/TempDesignSystem/ShowMoreButton"
|
||||||
|
import Table from "@/components/TempDesignSystem/Table"
|
||||||
|
|
||||||
|
import styles from "./table.module.css"
|
||||||
|
|
||||||
|
import type { TableProps } from "@/types/components/blocks/table"
|
||||||
|
|
||||||
|
export default function TableBlock({ data }: TableProps) {
|
||||||
|
const { columns, rows, totalWidth } = data
|
||||||
|
const initialPageSize = 5
|
||||||
|
const [pageSize, setPageSize] = useState(initialPageSize)
|
||||||
|
const showMoreVisible = rows.length > initialPageSize
|
||||||
|
const showLessVisible = pageSize >= rows.length
|
||||||
|
const columnDefs = columns.map((col) => ({
|
||||||
|
accessorKey: col.id,
|
||||||
|
header: col.header,
|
||||||
|
size: col.width,
|
||||||
|
}))
|
||||||
|
|
||||||
|
const table = useReactTable({
|
||||||
|
columns: columnDefs,
|
||||||
|
data: rows,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
state: {
|
||||||
|
pagination: {
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
function handleShowMore() {
|
||||||
|
setPageSize(showLessVisible ? initialPageSize : rows.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.tableWrapper}>
|
||||||
|
<ScrollWrapper>
|
||||||
|
<Table
|
||||||
|
width={`${totalWidth}%`}
|
||||||
|
variant="content"
|
||||||
|
intent="striped"
|
||||||
|
layout="fixed"
|
||||||
|
borderRadius="none"
|
||||||
|
>
|
||||||
|
<Table.THead>
|
||||||
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
|
<Table.TR key={headerGroup.id}>
|
||||||
|
{headerGroup.headers.map((header) => (
|
||||||
|
<Table.TH
|
||||||
|
key={header.id}
|
||||||
|
width={`${header.column.columnDef.size}%`}
|
||||||
|
>
|
||||||
|
{flexRender(
|
||||||
|
header.column.columnDef.header,
|
||||||
|
header.getContext()
|
||||||
|
)}
|
||||||
|
</Table.TH>
|
||||||
|
))}
|
||||||
|
</Table.TR>
|
||||||
|
))}
|
||||||
|
</Table.THead>
|
||||||
|
<Table.TBody>
|
||||||
|
{table.getRowModel().rows.map((row) => (
|
||||||
|
<Table.TR key={row.id}>
|
||||||
|
{row.getVisibleCells().map((cell) => (
|
||||||
|
<Table.TD key={cell.id}>
|
||||||
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||||
|
</Table.TD>
|
||||||
|
))}
|
||||||
|
</Table.TR>
|
||||||
|
))}
|
||||||
|
</Table.TBody>
|
||||||
|
</Table>
|
||||||
|
</ScrollWrapper>
|
||||||
|
{showMoreVisible ? (
|
||||||
|
<ShowMoreButton
|
||||||
|
loadMoreData={handleShowMore}
|
||||||
|
showLess={showLessVisible}
|
||||||
|
intent="table"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
6
components/Blocks/Table/table.module.css
Normal file
6
components/Blocks/Table/table.module.css
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
.tableWrapper {
|
||||||
|
display: grid;
|
||||||
|
border: 1px solid var(--Base-Border-Subtle);
|
||||||
|
border-radius: var(--Corner-radius-Small);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import TextCols from "@/components/Blocks/TextCols"
|
|||||||
import UspGrid from "@/components/Blocks/UspGrid"
|
import UspGrid from "@/components/Blocks/UspGrid"
|
||||||
import JsonToHtml from "@/components/JsonToHtml"
|
import JsonToHtml from "@/components/JsonToHtml"
|
||||||
|
|
||||||
import Table from "../Table"
|
import Table from "./Table"
|
||||||
|
|
||||||
import type { BlocksProps } from "@/types/components/blocks"
|
import type { BlocksProps } from "@/types/components/blocks"
|
||||||
import { BlocksEnums } from "@/types/enums/blocks"
|
import { BlocksEnums } from "@/types/enums/blocks"
|
||||||
@@ -50,7 +50,7 @@ export default function Blocks({ blocks }: BlocksProps) {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
case BlocksEnums.block.Table:
|
case BlocksEnums.block.Table:
|
||||||
return <Table columns={block.table.columns} rows={block.table.rows} />
|
return <Table data={block.table} />
|
||||||
case BlocksEnums.block.TextCols:
|
case BlocksEnums.block.TextCols:
|
||||||
return <TextCols text_cols={block.text_cols} />
|
return <TextCols text_cols={block.text_cols} />
|
||||||
case BlocksEnums.block.TextContent:
|
case BlocksEnums.block.TextContent:
|
||||||
|
|||||||
@@ -40,6 +40,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mainContent {
|
.mainContent {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--Spacing-x4);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
35
components/TempDesignSystem/ScrollWrapper/index.tsx
Normal file
35
components/TempDesignSystem/ScrollWrapper/index.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { useMemo } from "react"
|
||||||
|
|
||||||
|
import useScrollShadows from "@/hooks/useScrollShadows"
|
||||||
|
|
||||||
|
import { ScrollWrapperProps } from "./scrollWrapper"
|
||||||
|
|
||||||
|
import styles from "./scrollWrapper.module.css"
|
||||||
|
|
||||||
|
export default function ScrollWrapper({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
}: ScrollWrapperProps) {
|
||||||
|
const { containerRef, showLeftShadow, showRightShadow } = useScrollShadows()
|
||||||
|
|
||||||
|
const classNames = useMemo(() => {
|
||||||
|
const cls = [styles.scrollWrapper, className]
|
||||||
|
if (showLeftShadow) {
|
||||||
|
cls.push(styles.leftShadow)
|
||||||
|
}
|
||||||
|
if (showRightShadow) {
|
||||||
|
cls.push(styles.rightShadow)
|
||||||
|
}
|
||||||
|
return cls.join(" ")
|
||||||
|
}, [showLeftShadow, showRightShadow, className])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classNames}>
|
||||||
|
<div className={styles.content} ref={containerRef}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
.scrollWrapper {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollWrapper::before,
|
||||||
|
.scrollWrapper::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 1;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
opacity: 0;
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollWrapper.leftShadow::before {
|
||||||
|
left: 0;
|
||||||
|
background: linear-gradient(to right, rgba(0, 0, 0, 0.3), transparent);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollWrapper.rightShadow::after {
|
||||||
|
right: 0;
|
||||||
|
background: linear-gradient(to left, rgba(0, 0, 0, 0.3), transparent);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export interface ScrollWrapperProps
|
||||||
|
extends React.PropsWithChildren<React.HTMLAttributes<HTMLDivElement>> {}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
@@ -5,18 +5,29 @@ import { useIntl } from "react-intl"
|
|||||||
import { ChevronDownIcon } from "@/components/Icons"
|
import { ChevronDownIcon } from "@/components/Icons"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
|
|
||||||
import styles from "./button.module.css"
|
import { showMoreButtonVariants } from "./variants"
|
||||||
|
|
||||||
import type { ShowMoreButtonParams } from "@/types/components/myPages/stays/button"
|
import styles from "./showMoreButton.module.css"
|
||||||
|
|
||||||
|
import type { ShowMoreButtonProps } from "./showMoreButton"
|
||||||
|
|
||||||
export default function ShowMoreButton({
|
export default function ShowMoreButton({
|
||||||
|
className,
|
||||||
|
intent,
|
||||||
disabled,
|
disabled,
|
||||||
|
showLess,
|
||||||
loadMoreData,
|
loadMoreData,
|
||||||
}: ShowMoreButtonParams) {
|
}: ShowMoreButtonProps) {
|
||||||
const { formatMessage } = useIntl()
|
const intl = useIntl()
|
||||||
|
const classNames = showMoreButtonVariants({
|
||||||
|
className,
|
||||||
|
intent,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={`${classNames} ${showLess ? styles.showLess : ""}`}>
|
||||||
<Button
|
<Button
|
||||||
|
className={styles.button}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={loadMoreData}
|
onClick={loadMoreData}
|
||||||
variant="icon"
|
variant="icon"
|
||||||
@@ -24,8 +35,8 @@ export default function ShowMoreButton({
|
|||||||
theme="base"
|
theme="base"
|
||||||
intent="text"
|
intent="text"
|
||||||
>
|
>
|
||||||
<ChevronDownIcon />
|
<ChevronDownIcon className={styles.icon} />
|
||||||
{formatMessage({ id: "Show more" })}
|
{intl.formatMessage({ id: showLess ? "Show less" : "Show more" })}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
display: grid;
|
||||||
|
justify-content: stretch;
|
||||||
|
border-top: 1px solid var(--Base-Border-Subtle);
|
||||||
|
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table .button {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.showLess .icon {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
11
components/TempDesignSystem/ShowMoreButton/showMoreButton.ts
Normal file
11
components/TempDesignSystem/ShowMoreButton/showMoreButton.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { showMoreButtonVariants } from "./variants"
|
||||||
|
|
||||||
|
import type { VariantProps } from "class-variance-authority"
|
||||||
|
|
||||||
|
export interface ShowMoreButtonProps
|
||||||
|
extends React.PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>,
|
||||||
|
VariantProps<typeof showMoreButtonVariants> {
|
||||||
|
disabled?: boolean
|
||||||
|
showLess?: boolean
|
||||||
|
loadMoreData: () => void
|
||||||
|
}
|
||||||
11
components/TempDesignSystem/ShowMoreButton/variants.ts
Normal file
11
components/TempDesignSystem/ShowMoreButton/variants.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { cva } from "class-variance-authority"
|
||||||
|
|
||||||
|
import styles from "./showMoreButton.module.css"
|
||||||
|
|
||||||
|
export const showMoreButtonVariants = cva(styles.container, {
|
||||||
|
variants: {
|
||||||
|
intent: {
|
||||||
|
table: styles.table,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
import styles from "./table.module.css"
|
import styles from "./table.module.css"
|
||||||
|
|
||||||
function TH({ children }: React.PropsWithChildren) {
|
import type { THeadProps } from "./table"
|
||||||
return <th className={styles.th}>{children}</th>
|
|
||||||
|
function TH({ children, width = "auto", ...props }: THeadProps) {
|
||||||
|
return (
|
||||||
|
<th className={styles.th} style={{ width }} {...props}>
|
||||||
|
{children}
|
||||||
|
</th>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TH
|
export default TH
|
||||||
|
|||||||
@@ -1,13 +1,34 @@
|
|||||||
|
import { TableProps } from "./table"
|
||||||
import TBody from "./TBody"
|
import TBody from "./TBody"
|
||||||
import TD from "./TD"
|
import TD from "./TD"
|
||||||
import TH from "./TH"
|
import TH from "./TH"
|
||||||
import THead from "./THead"
|
import THead from "./THead"
|
||||||
import TR from "./TR"
|
import TR from "./TR"
|
||||||
|
import { tableVariants } from "./variants"
|
||||||
|
|
||||||
import styles from "./table.module.css"
|
function Table({
|
||||||
|
className,
|
||||||
|
intent,
|
||||||
|
borderRadius,
|
||||||
|
variant,
|
||||||
|
layout,
|
||||||
|
width = "100%",
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: TableProps) {
|
||||||
|
const classNames = tableVariants({
|
||||||
|
className,
|
||||||
|
borderRadius,
|
||||||
|
intent,
|
||||||
|
layout,
|
||||||
|
variant,
|
||||||
|
})
|
||||||
|
|
||||||
function Table({ children }: React.PropsWithChildren) {
|
return (
|
||||||
return <table className={styles.table}>{children}</table>
|
<table className={classNames} style={{ width }} {...props}>
|
||||||
|
{children}
|
||||||
|
</table>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Table.THead = THead
|
Table.THead = THead
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
.table {
|
.table {
|
||||||
border-radius: var(--Corner-radius-Medium);
|
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
min-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thead {
|
.thead {
|
||||||
background-color: var(--Base-Background-Secondary-Normal, #f7e1d5);
|
color: var(--Base-Text-High-contrast);
|
||||||
|
background-color: var(--Base-Surface-Primary-dark-Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tbody {
|
.tbody {
|
||||||
background-color: var(--Base-Surface-Primary-light-Normal, #fff);
|
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tr:not(:last-of-type) {
|
.tr:not(:last-of-type) {
|
||||||
border-bottom: 1px solid var(--Primary-Light-On-Surface-Divider, #f0c1b6);
|
border-bottom: 1px solid var(--Base-Border-Subtle);
|
||||||
}
|
}
|
||||||
|
|
||||||
.th {
|
.th {
|
||||||
@@ -28,6 +28,35 @@
|
|||||||
padding: var(--Spacing-x2);
|
padding: var(--Spacing-x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fixed {
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smallRadius {
|
||||||
|
border-radius: var(--Corner-radius-Small);
|
||||||
|
}
|
||||||
|
.mediumRadius {
|
||||||
|
border-radius: var(--Corner-radius-Medium);
|
||||||
|
}
|
||||||
|
.largeRadius {
|
||||||
|
border-radius: var(--Corner-radius-Large);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .thead {
|
||||||
|
background-color: var(--Base-Surface-Subtle-Hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .tbody {
|
||||||
|
background-color: var(--Base-Background-Primary-Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content.striped .tbody .tr:nth-child(odd) {
|
||||||
|
background-color: var(--Base-Surface-Subtle-Normal);
|
||||||
|
}
|
||||||
|
.content.striped .tbody .tr:nth-child(even) {
|
||||||
|
background-color: var(--Base-Background-Primary-Normal);
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
.th {
|
.th {
|
||||||
padding: var(--Spacing-x2) var(--Spacing-x3);
|
padding: var(--Spacing-x2) var(--Spacing-x3);
|
||||||
|
|||||||
14
components/TempDesignSystem/Table/table.ts
Normal file
14
components/TempDesignSystem/Table/table.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { tableVariants } from "./variants"
|
||||||
|
|
||||||
|
import type { VariantProps } from "class-variance-authority"
|
||||||
|
|
||||||
|
export interface TableProps
|
||||||
|
extends React.PropsWithChildren<React.HTMLAttributes<HTMLTableElement>>,
|
||||||
|
VariantProps<typeof tableVariants> {
|
||||||
|
width?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface THeadProps
|
||||||
|
extends React.PropsWithChildren<React.HTMLAttributes<HTMLTableCellElement>> {
|
||||||
|
width?: string
|
||||||
|
}
|
||||||
27
components/TempDesignSystem/Table/variants.ts
Normal file
27
components/TempDesignSystem/Table/variants.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { cva } from "class-variance-authority"
|
||||||
|
|
||||||
|
import styles from "./table.module.css"
|
||||||
|
|
||||||
|
export const tableVariants = cva(styles.table, {
|
||||||
|
variants: {
|
||||||
|
intent: {
|
||||||
|
light: styles.light,
|
||||||
|
striped: styles.striped,
|
||||||
|
},
|
||||||
|
variant: {
|
||||||
|
content: styles.content,
|
||||||
|
},
|
||||||
|
borderRadius: {
|
||||||
|
none: "",
|
||||||
|
small: styles.smallRadius,
|
||||||
|
medium: styles.mediumRadius,
|
||||||
|
large: styles.largeRadius,
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
fixed: styles.fixed,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
borderRadius: "medium",
|
||||||
|
},
|
||||||
|
})
|
||||||
36
hooks/useScrollShadows.ts
Normal file
36
hooks/useScrollShadows.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { useEffect, useRef, useState } from "react"
|
||||||
|
|
||||||
|
const useScrollShadows = () => {
|
||||||
|
const containerRef = useRef<HTMLDivElement | null>(null)
|
||||||
|
const [showLeftShadow, setShowLeftShadow] = useState<boolean>(false)
|
||||||
|
const [showRightShadow, setShowRightShadow] = useState<boolean>(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleScroll = () => {
|
||||||
|
const container = containerRef.current
|
||||||
|
if (!container) return
|
||||||
|
|
||||||
|
setShowLeftShadow(container.scrollLeft > 0)
|
||||||
|
setShowRightShadow(
|
||||||
|
container.scrollLeft < container.scrollWidth - container.clientWidth
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const container = containerRef.current
|
||||||
|
if (container) {
|
||||||
|
container.addEventListener("scroll", handleScroll)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleScroll()
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (container) {
|
||||||
|
container.removeEventListener("scroll", handleScroll)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return { containerRef, showLeftShadow, showRightShadow }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useScrollShadows
|
||||||
32
package-lock.json
generated
32
package-lock.json
generated
@@ -23,6 +23,7 @@
|
|||||||
"@scandic-hotels/design-system": "git+https://x-token-auth:$DESIGN_SYSTEM_ACCESS_TOKEN@bitbucket.org/scandic-swap/design-system.git#v0.1.0-rc.9",
|
"@scandic-hotels/design-system": "git+https://x-token-auth:$DESIGN_SYSTEM_ACCESS_TOKEN@bitbucket.org/scandic-swap/design-system.git#v0.1.0-rc.9",
|
||||||
"@t3-oss/env-nextjs": "^0.9.2",
|
"@t3-oss/env-nextjs": "^0.9.2",
|
||||||
"@tanstack/react-query": "^5.28.6",
|
"@tanstack/react-query": "^5.28.6",
|
||||||
|
"@tanstack/react-table": "^8.20.5",
|
||||||
"@trpc/client": "^11.0.0-rc.467",
|
"@trpc/client": "^11.0.0-rc.467",
|
||||||
"@trpc/react-query": "^11.0.0-rc.467",
|
"@trpc/react-query": "^11.0.0-rc.467",
|
||||||
"@trpc/server": "^11.0.0-rc.467",
|
"@trpc/server": "^11.0.0-rc.467",
|
||||||
@@ -5971,6 +5972,37 @@
|
|||||||
"react": "^18.0.0"
|
"react": "^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tanstack/react-table": {
|
||||||
|
"version": "8.20.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.20.5.tgz",
|
||||||
|
"integrity": "sha512-WEHopKw3znbUZ61s9i0+i9g8drmDo6asTWbrQh8Us63DAk/M0FkmIqERew6P71HI75ksZ2Pxyuf4vvKh9rAkiA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/table-core": "8.20.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8",
|
||||||
|
"react-dom": ">=16.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tanstack/table-core": {
|
||||||
|
"version": "8.20.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.20.5.tgz",
|
||||||
|
"integrity": "sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@testing-library/dom": {
|
"node_modules/@testing-library/dom": {
|
||||||
"version": "10.1.0",
|
"version": "10.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz",
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
"@scandic-hotels/design-system": "git+https://x-token-auth:$DESIGN_SYSTEM_ACCESS_TOKEN@bitbucket.org/scandic-swap/design-system.git#v0.1.0-rc.9",
|
"@scandic-hotels/design-system": "git+https://x-token-auth:$DESIGN_SYSTEM_ACCESS_TOKEN@bitbucket.org/scandic-swap/design-system.git#v0.1.0-rc.9",
|
||||||
"@t3-oss/env-nextjs": "^0.9.2",
|
"@t3-oss/env-nextjs": "^0.9.2",
|
||||||
"@tanstack/react-query": "^5.28.6",
|
"@tanstack/react-query": "^5.28.6",
|
||||||
|
"@tanstack/react-table": "^8.20.5",
|
||||||
"@trpc/client": "^11.0.0-rc.467",
|
"@trpc/client": "^11.0.0-rc.467",
|
||||||
"@trpc/react-query": "^11.0.0-rc.467",
|
"@trpc/react-query": "^11.0.0-rc.467",
|
||||||
"@trpc/server": "^11.0.0-rc.467",
|
"@trpc/server": "^11.0.0-rc.467",
|
||||||
|
|||||||
@@ -28,17 +28,20 @@ export const tableSchema = z.object({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.transform((data) => {
|
.transform((data) => {
|
||||||
|
const totalWidth = data.column_widths.reduce(
|
||||||
|
(acc, width) => acc + width,
|
||||||
|
0
|
||||||
|
)
|
||||||
const columns = data.table.tableState.columns.map((col, idx) => ({
|
const columns = data.table.tableState.columns.map((col, idx) => ({
|
||||||
id: col.id,
|
id: col.id,
|
||||||
Header: col.label || "",
|
header: col.label || "",
|
||||||
accessor: col.accessor,
|
width: data.column_widths[idx] || 0,
|
||||||
columnWidth: data.column_widths[idx] || 0,
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const rows = data.table.tableState.data.map((rowData) => {
|
const rows = data.table.tableState.data.map((rowData) => {
|
||||||
const transformedRow: Record<string, string> = {}
|
const transformedRow: Record<string, string> = {}
|
||||||
columns.forEach((col) => {
|
columns.forEach((header) => {
|
||||||
transformedRow[col.accessor] = rowData[col.accessor] || ""
|
transformedRow[header.id] = rowData[header.id] || ""
|
||||||
})
|
})
|
||||||
return transformedRow
|
return transformedRow
|
||||||
})
|
})
|
||||||
@@ -46,6 +49,7 @@ export const tableSchema = z.object({
|
|||||||
return {
|
return {
|
||||||
columns,
|
columns,
|
||||||
rows,
|
rows,
|
||||||
|
totalWidth,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
5
types/components/blocks/table.ts
Normal file
5
types/components/blocks/table.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import type { TableData } from "@/types/trpc/routers/contentstack/blocks"
|
||||||
|
|
||||||
|
export interface TableProps {
|
||||||
|
data: TableData
|
||||||
|
}
|
||||||
@@ -14,6 +14,6 @@ export interface DynamicContent extends z.output<typeof dynamicContentSchema> {}
|
|||||||
export interface Shortcuts extends z.output<typeof shortcutsSchema> {}
|
export interface Shortcuts extends z.output<typeof shortcutsSchema> {}
|
||||||
export type Shortcut = Shortcuts["shortcuts"]
|
export type Shortcut = Shortcuts["shortcuts"]
|
||||||
export interface TableBlock extends z.output<typeof tableSchema> {}
|
export interface TableBlock extends z.output<typeof tableSchema> {}
|
||||||
export type Table = TableBlock["table"]
|
export type TableData = TableBlock["table"]
|
||||||
export interface TextCols extends z.output<typeof textColsSchema> {}
|
export interface TextCols extends z.output<typeof textColsSchema> {}
|
||||||
export interface UspGrid extends z.output<typeof uspGridSchema> {}
|
export interface UspGrid extends z.output<typeof uspGridSchema> {}
|
||||||
|
|||||||
Reference in New Issue
Block a user