Files
Trilium/apps/client/src/widgets/collections/table/tabulator.tsx
2025-09-06 21:08:32 +03:00

66 lines
2.3 KiB
TypeScript

import { useContext, useEffect, useLayoutEffect, useRef } from "preact/hooks";
import { ColumnDefinition, EventCallBackMethods, Module, Tabulator as VanillaTabulator } from "tabulator-tables";
import "tabulator-tables/dist/css/tabulator.css";
import "../../../../src/stylesheets/table.css";
import { ComponentChildren, RefObject } from "preact";
import { ParentComponent, renderReactWidget } from "../../react/react_utils";
interface TableProps<T> extends Partial<EventCallBackMethods> {
tabulatorRef: RefObject<VanillaTabulator>;
className?: string;
columns: ColumnDefinition[];
data?: T[];
modules?: (new (table: VanillaTabulator) => Module)[];
footerElement?: ComponentChildren;
}
export default function Tabulator<T>({ className, columns, data, modules, tabulatorRef: externalTabulatorRef, footerElement, ...events }: TableProps<T>) {
const parentComponent = useContext(ParentComponent);
const containerRef = useRef<HTMLDivElement>(null);
const tabulatorRef = useRef<VanillaTabulator>(null);
useLayoutEffect(() => {
if (!modules) return;
for (const module of modules) {
VanillaTabulator.registerModule(module);
}
}, [modules]);
useLayoutEffect(() => {
if (!containerRef.current) return;
const tabulator = new VanillaTabulator(containerRef.current, {
columns,
data,
footerElement: (parentComponent && footerElement ? renderReactWidget(parentComponent, footerElement)[0] : undefined)
});
tabulatorRef.current = tabulator;
externalTabulatorRef.current = tabulator;
return () => tabulator.destroy();
}, []);
useEffect(() => {
const tabulator = tabulatorRef.current;
if (!tabulator) return;
for (const [ eventName, handler ] of Object.entries(events)) {
tabulator.on(eventName as keyof EventCallBackMethods, handler);
}
return () => {
for (const [ eventName, handler ] of Object.entries(events)) {
tabulator.off(eventName as keyof EventCallBackMethods, handler);
}
}
}, Object.values(events));
// Change in data.
useEffect(() => { tabulatorRef.current?.setData(data) }, [ data ]);
return (
<div ref={containerRef} className={className} />
);
}