From 424301cb35cef47c2586d855b1c06d7855f1ae16 Mon Sep 17 00:00:00 2001 From: Kevin Van Cott Date: Sat, 4 Jan 2025 22:27:43 -0600 Subject: [PATCH] update the qwik adapter a little bit --- examples/qwik/filters/src/main.tsx | 38 ++++++----- examples/qwik/row-selection/src/main.tsx | 18 +++-- packages/qwik-table/src/createTableHelper.ts | 63 +++++++++++++++++ packages/qwik-table/src/flexRender.tsx | 20 ++++++ packages/qwik-table/src/index.tsx | 72 +------------------- packages/qwik-table/src/useTable.ts | 46 +++++++++++++ 6 files changed, 166 insertions(+), 91 deletions(-) create mode 100644 packages/qwik-table/src/createTableHelper.ts create mode 100644 packages/qwik-table/src/flexRender.tsx create mode 100644 packages/qwik-table/src/useTable.ts diff --git a/examples/qwik/filters/src/main.tsx b/examples/qwik/filters/src/main.tsx index 229b1f0435..3cf0cf3faa 100644 --- a/examples/qwik/filters/src/main.tsx +++ b/examples/qwik/filters/src/main.tsx @@ -13,6 +13,7 @@ import { createSortedRowModel, filterFns, flexRender, + globalFilteringFeature, rowPaginationFeature, rowSortingFeature, sortFns, @@ -115,6 +116,7 @@ const _features = tableFeatures({ columnFilteringFeature, rowPaginationFeature, rowSortingFeature, + globalFilteringFeature, }) const columnHelper = createColumnHelper() @@ -123,7 +125,7 @@ const columns = columnHelper.columns([ columnHelper.group({ header: 'Name', footer: (props) => props.column.id, - columns: [ + columns: columnHelper.columns([ columnHelper.accessor('firstName', { cell: (info) => info.getValue(), footer: (props) => props.column.id, @@ -142,19 +144,19 @@ const columns = columnHelper.columns([ footer: (props) => props.column.id, sortFn: fuzzySort, }), - ], + ]), }), columnHelper.group({ header: 'Info', footer: (props) => props.column.id, - columns: [ + columns: columnHelper.columns([ columnHelper.accessor('age', { header: () => 'Age', footer: (props) => props.column.id, }), columnHelper.group({ header: 'More Info', - columns: [ + columns: columnHelper.columns([ columnHelper.accessor('visits', { header: () => Visits, footer: (props) => props.column.id, @@ -167,9 +169,9 @@ const columns = columnHelper.columns([ header: 'Profile Progress', footer: (props) => props.column.id, }), - ], + ]), }), - ], + ]), }), ]) @@ -190,12 +192,9 @@ const App = component$(() => { paginatedRowModel: createPaginatedRowModel(), sortedRowModel: createSortedRowModel(sortFns), }, - data: defaultData, columns, + data: defaultData, enableSorting: true, - filterFns: { - fuzzy: fuzzyFilter, - }, state: { columnFilters: columnFilters.value, globalFilter: globalFilter.value, @@ -242,16 +241,19 @@ const App = component$(() => { ? 'cursor-pointer select-none' : '' } - onClick={header.column.getToggleSortingHandler()} + onClick$={$(() => { + header.column.getToggleSortingHandler() + })} > {flexRender( header.column.columnDef.header, header.getContext(), )} - {{ - asc: ' 🔼', - desc: ' 🔽', - }[header.column.getIsSorted() as string] ?? null} + {header.column.getIsSorted() + ? header.column.getIsSorted() === 'asc' + ? ' 🔼' + : ' 🔽' + : null} {header.column.getCanFilter() ? (
@@ -270,7 +272,7 @@ const App = component$(() => { {table.getRowModel().rows.map((row) => { return ( - {row.getVisibleCells().map((cell) => ( + {row.getAllCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} @@ -290,8 +292,8 @@ function Filter({ column, table, }: { - column: Column - table: Table + column: Column + table: Table }) { const { id } = column const firstValue = table diff --git a/examples/qwik/row-selection/src/main.tsx b/examples/qwik/row-selection/src/main.tsx index ad1b77163c..af6f5692b6 100644 --- a/examples/qwik/row-selection/src/main.tsx +++ b/examples/qwik/row-selection/src/main.tsx @@ -14,6 +14,7 @@ import { tableFeatures, useTable, } from '@tanstack/qwik-table' +import type { JSX } from '@builder.io/qwik' import type { ColumnDef } from '@tanstack/qwik-table' type Person = { @@ -226,12 +227,21 @@ const App = component$(() => { ) }) -const IndeterminateCheckbox = component$<{ - indeterminate?: boolean -}>(({ indeterminate, ...rest }) => { +const IndeterminateCheckbox = component$< + Omit & { + indeterminate?: boolean + } +>(({ indeterminate, ...rest }) => { const inputSig = useSignal() - return + return ( + + ) }) render(document.getElementById('app') as HTMLElement, ) diff --git a/packages/qwik-table/src/createTableHelper.ts b/packages/qwik-table/src/createTableHelper.ts new file mode 100644 index 0000000000..9c3b865278 --- /dev/null +++ b/packages/qwik-table/src/createTableHelper.ts @@ -0,0 +1,63 @@ +import { constructTableHelper } from '@tanstack/table-core' +import { useTable } from './useTable' +import type { NoSerialize } from '@builder.io/qwik' +import type { + RowData, + Table, + TableFeatures, + TableHelperOptions, + TableHelper_Core, + TableOptions, +} from '@tanstack/table-core' + +export type TableHelper< + TFeatures extends TableFeatures, + TData extends RowData = any, +> = Omit, 'tableCreator'> & { + useTable: ( + tableOptions: Omit< + TableOptions, + '_features' | '_rowModels' + >, + ) => NoSerialize> +} + +export function createTableHelper< + TFeatures extends TableFeatures, + TDataList extends Array = Array, +>( + tableHelperOptions: TableHelperOptions, +): TableHelper { + const tableHelper = constructTableHelper(useTable as any, tableHelperOptions) + return { + ...tableHelper, + useTable: tableHelper.tableCreator, + } as unknown as TableHelper +} + +// test + +// type Person = { +// firstName: string +// lastName: string +// age: number +// } + +// const tableHelper = createTableHelper({ +// _features: { rowSelectionFeature: {} }, +// TData: {} as Person, +// }) + +// const columns = [ +// tableHelper.columnHelper.accessor('firstName', { header: 'First Name' }), +// tableHelper.columnHelper.accessor('lastName', { header: 'Last Name' }), +// tableHelper.columnHelper.accessor('age', { header: 'Age' }), +// tableHelper.columnHelper.display({ header: 'Actions', id: 'actions' }), +// ] as Array> + +// const data: Array = [] + +// tableHelper.useTable({ +// columns, +// data, +// }) diff --git a/packages/qwik-table/src/flexRender.tsx b/packages/qwik-table/src/flexRender.tsx new file mode 100644 index 0000000000..93787d291e --- /dev/null +++ b/packages/qwik-table/src/flexRender.tsx @@ -0,0 +1,20 @@ +import { isFunction } from '@tanstack/table-core' +import type { Component, FunctionComponent } from '@builder.io/qwik' + +type QwikComps = Component | FunctionComponent + +const isQwikComponent = (comp: unknown): comp is QwikComps => + isFunction(comp) && comp.name === 'QwikComponent' + +export function flexRender( + Comp: any, // TODO: add renderable type + props: TProps, +) { + return !Comp ? null : isQwikComponent(Comp) ? ( + + ) : isFunction(Comp) ? ( + Comp(props) + ) : ( + Comp + ) +} diff --git a/packages/qwik-table/src/index.tsx b/packages/qwik-table/src/index.tsx index 39557e868f..6686a5d12d 100644 --- a/packages/qwik-table/src/index.tsx +++ b/packages/qwik-table/src/index.tsx @@ -1,70 +1,4 @@ -import * as Qwik from '@builder.io/qwik' -import { constructTable, isFunction } from '@tanstack/table-core' -import type { - RowData, - Table, - TableFeatures, - TableOptions, -} from '@tanstack/table-core' - +export * from './createTableHelper' +export * from './flexRender' +export * from './useTable' export * from '@tanstack/table-core' - -type QwikComps = Qwik.Component | Qwik.FunctionComponent - -const isQwikComponent = (comp: unknown): comp is QwikComps => - isFunction(comp) && comp.name === 'QwikComponent' - -export function flexRender( - Comp: any, // TODO: add renderable type - props: TProps, -) { - return !Comp ? null : isQwikComponent(Comp) ? ( - - ) : isFunction(Comp) ? ( - Comp(props) - ) : ( - Comp - ) -} - -export function useTable< - TFeatures extends TableFeatures, - TData extends RowData, ->(options: TableOptions) { - // Compose in the generic options to the user options - const resolvedOptions: TableOptions = { - state: {}, - onStateChange: () => {}, - renderFallbackValue: null, - ...options, - } - - // Create a new table instance and store it in a Qwik store - const table = Qwik.useStore<{ - instance: Qwik.NoSerialize> - }>({ - instance: Qwik.noSerialize(constructTable(resolvedOptions)), - }) - - // By default, manage table state here using the table's initial state - const state = Qwik.useSignal(table.instance!.initialState) - - // Compose the default state above with any user state. This will allow the user - // to only control a subset of the state if desired. - table.instance!.setOptions((prev) => ({ - ...prev, - ...options, - state: { - ...state.value, - ...options.state, - }, - // Similarly, we'll maintain both our internal state and any user-provided - // state. - onStateChange: (updater) => { - state.value = isFunction(updater) ? updater(state.value) : updater - options.onStateChange?.(updater) - }, - })) - - return table.instance! as Table -} diff --git a/packages/qwik-table/src/useTable.ts b/packages/qwik-table/src/useTable.ts new file mode 100644 index 0000000000..d0d40f8d3f --- /dev/null +++ b/packages/qwik-table/src/useTable.ts @@ -0,0 +1,46 @@ +import { noSerialize, useSignal, useStore } from '@builder.io/qwik' +import { + constructTable, + coreFeatures, + getInitialTableState, + isFunction, +} from '@tanstack/table-core' +import type { NoSerialize } from '@builder.io/qwik' +import type { + RowData, + Table, + TableFeatures, + TableOptions, +} from '@tanstack/table-core' + +export function useTable< + TFeatures extends TableFeatures, + TData extends RowData, +>(tableOptions: TableOptions): Table { + const _features = { ...coreFeatures, ...tableOptions._features } + + const state = useSignal( + getInitialTableState(_features, tableOptions.initialState), + ) + + const statefulOptions: TableOptions = { + ...tableOptions, + _features, + state: { + ...state.value, + ...tableOptions.state, + }, + onStateChange: (updater) => { + state.value = isFunction(updater) ? updater(state.value) : updater + tableOptions.onStateChange?.(updater) + }, + } + + const table = useStore<{ + instance: NoSerialize> + }>({ + instance: noSerialize(constructTable(statefulOptions)), + }) + + return table.instance! +}