import { type RowData, type TableOptions, type TableOptionsResolved, type TableState, createTable, } from "@tanstack/table-core"; /** * Creates a reactive TanStack table object for Svelte. * @param options Table options to create the table with. * @returns A reactive table object. * @example * ```svelte * * * * * {#each table.getHeaderGroups() as headerGroup} * * {#each headerGroup.headers as header} * * {/each} * * {/each} * * *
* *
* ``` */ export function createSvelteTable(options: TableOptions) { const resolvedOptions: TableOptionsResolved = mergeObjects( { state: {}, onStateChange() {}, renderFallbackValue: null, mergeOptions: ( defaultOptions: TableOptions, options: Partial> ) => { return mergeObjects(defaultOptions, options); }, }, options ); const table = createTable(resolvedOptions); let state = $state>(table.initialState); function updateOptions() { table.setOptions((prev) => { return mergeObjects(prev, options, { state: mergeObjects(state, options.state || {}), // eslint-disable-next-line @typescript-eslint/no-explicit-any onStateChange: (updater: any) => { if (updater instanceof Function) state = updater(state); else state = mergeObjects(state, updater); options.onStateChange?.(updater); }, }); }); } updateOptions(); $effect.pre(() => { updateOptions(); }); return table; } type MaybeThunk = T | (() => T | null | undefined); type Intersection = (T extends [infer H, ...infer R] ? H & Intersection : unknown) & {}; /** * Lazily merges several objects (or thunks) while preserving * getter semantics from every source. * * Proxy-based to avoid known WebKit recursion issue. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function mergeObjects[]>( ...sources: Sources ): Intersection<{ [K in keyof Sources]: Sources[K] }> { const resolve = (src: MaybeThunk): T | undefined => typeof src === "function" ? (src() ?? undefined) : src; const findSourceWithKey = (key: PropertyKey) => { for (let i = sources.length - 1; i >= 0; i--) { const obj = resolve(sources[i]); if (obj && key in obj) return obj; } return undefined; }; return new Proxy(Object.create(null), { get(_, key) { const src = findSourceWithKey(key); return src?.[key as never]; }, has(_, key) { return !!findSourceWithKey(key); }, ownKeys(): (string | symbol)[] { const all = new Set(); for (const s of sources) { const obj = resolve(s); if (obj) { for (const k of Reflect.ownKeys(obj) as (string | symbol)[]) { all.add(k); } } } return [...all]; }, getOwnPropertyDescriptor(_, key) { const src = findSourceWithKey(key); if (!src) return undefined; return { configurable: true, enumerable: true, // eslint-disable-next-line @typescript-eslint/no-explicit-any value: (src as any)[key], writable: true, }; }, }) as Intersection<{ [K in keyof Sources]: Sources[K] }>; }