diff --git a/src/components/Table.astro b/src/components/Table.astro index eafaa77..daebd1b 100644 --- a/src/components/Table.astro +++ b/src/components/Table.astro @@ -12,6 +12,8 @@ const { pageSize = 10, fetchData, columnsRendererKey, + classInfos = "", + tableClassNames = "", } = Astro.props as TableProps; const id = `table-${Math.random().toString(36).slice(2, 9)}`; @@ -36,7 +38,13 @@ const id = `table-${Math.random().toString(36).slice(2, 9)}`; class="wr:overflow-x-auto wr:rounded-xl wr:border wr:border-gray-300 wr:dark:border-neutral-700 wr:hidden wr:md:block" > ( `; - columns.forEach((col) => { + let tr = ``; + + columns.forEach((col, colIndex) => { let value = row[col.key] ?? ""; const renderers = columnsRendererKey @@ -183,30 +218,56 @@ const id = `table-${Math.random().toString(36).slice(2, 9)}`; if (col.render) { value = col.render(value, row); } - tr += ``; + + const columnCls = resolveClasses( + classNames?.column, + col, + colIndex, + ); + const cellCls = resolveClasses(classNames?.cell, { + row, + value, + col, + i, + colIndex, + }); + + tr += ``; }); tr += ``; tbody.insertAdjacentHTML("beforeend", tr); // 📱 Mobile let card = `
`; - columns.forEach((col) => { + columns.forEach((col, colIndex) => { let value = row[col.key] ?? ""; const renderers = columnsRendererKey ? window[columnsRendererKey] : {}; - columns.forEach((col) => { - if (renderers[col.key]) col.render = renderers[col.key]; + columns.forEach((c) => { + if (renderers[c.key]) c.render = renderers[c.key]; + }); + + if (col.render) value = col.render(value, row); + + const columnCls = resolveClasses( + classNames?.column, + col, + colIndex, + ); + const cellCls = resolveClasses(classNames?.cell, { + row, + value, + col, + i, + colIndex, }); - if (col.render) { - value = col.render(value, row); - } card += ` -
-
${col.label}
-
${value}
+
+
${col.label}
+
${value}
`; }); card += `
`; diff --git a/src/global.d.ts b/src/global.d.ts index 3904fa8..7ab01b2 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -12,6 +12,7 @@ declare global { myModal_close: any; hls: typeof Hls, flvjs: typeof FlvJs + classNames: any; } } diff --git a/src/pages/table.astro b/src/pages/table.astro index 0382bd9..5339fa8 100644 --- a/src/pages/table.astro +++ b/src/pages/table.astro @@ -239,6 +239,18 @@ const data = [ avatar: "https://i.pravatar.cc/40?img=25", }, ]; + +const studentData = [ + { id: 1, name: "Alice", age: 24, role: "Engineer" }, + { id: 2, name: "Bob", age: 29, role: "Designer" }, + { id: 3, name: "Carol", age: 35, role: "Manager" }, +]; + +const studentColumns = [ + { key: "name", label: "Name", sortable: true }, + { key: "age", label: "Age", sortable: true, align: "right" }, + { key: "role", label: "Role" }, +]; --- @@ -256,6 +268,17 @@ const data = [ fetchData="fetchData" columnsRendererKey="columnsRenderer" /> + +
+ +
const start = () => { @@ -161,6 +172,20 @@ const id = `table-${Math.random().toString(36).slice(2, 9)}`; `; const fetchDataFn = fetchData ? window[fetchData] : null; + const classNames = classInfos ? window[classInfos] : {}; + + const resolveClasses = (input, ...ctx) => { + if (!input) return ""; + const val = typeof input === "function" ? input(...ctx) : input; + if (typeof val === "string") return val; + if (val && typeof val === "object") { + return Object.entries(val) + .filter(([, on]) => !!on) + .map(([cls]) => cls) + .join(" "); + } + return ""; + }; /** 🧱 Render rows */ function renderRows(dataset) { @@ -168,9 +193,19 @@ const id = `table-${Math.random().toString(36).slice(2, 9)}`; mobileBody.innerHTML = ""; dataset.forEach((row, i) => { + const rowCls = resolveClasses(classNames?.row, row, i); + // 🖥️ Desktop - let tr = `
${value}${value}
@@ -396,4 +419,20 @@ const data = [ total, }; }; + + window.classNames = { + row: (_row: any, idx: number) => ({ + "wr:!bg-gray-50 wr:text-black": _row.role === "Engineer", + }), + + column: (col: any) => + col.key === "age" + ? "wr:text-right wr:font-bold wr:bg-yellow-100 wr:text-black" + : "", + + cell: ({ value, col }: { value: any; col: any }) => + typeof value === "number" && col.key === "age" && value > 30 + ? "wr:text-green-600" + : "", + }; diff --git a/src/types/table/types.ts b/src/types/table/types.ts index 9064518..62fe66e 100644 --- a/src/types/table/types.ts +++ b/src/types/table/types.ts @@ -1,3 +1,16 @@ +export type ClassValue = + | string + | Record + | ((...args: any[]) => string | Record); + + +export type ClassNames = { + table?: ClassValue; + row?: ClassValue; + column?: ClassValue; + cell?: ClassValue; +}; + export interface Column { key: keyof T | string; label: string; @@ -18,4 +31,6 @@ export interface TableProps { pagignations?: boolean; pageSize?: number columnsRendererKey?: string + classInfos?: string; + tableClassNames?: string; } \ No newline at end of file