Skip to content

Commit

Permalink
update the qwik adapter a little bit
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinVandy committed Jan 5, 2025
1 parent 9a6f472 commit 424301c
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 91 deletions.
38 changes: 20 additions & 18 deletions examples/qwik/filters/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
createSortedRowModel,
filterFns,
flexRender,
globalFilteringFeature,
rowPaginationFeature,
rowSortingFeature,
sortFns,
Expand Down Expand Up @@ -115,6 +116,7 @@ const _features = tableFeatures({
columnFilteringFeature,
rowPaginationFeature,
rowSortingFeature,
globalFilteringFeature,
})

const columnHelper = createColumnHelper<typeof _features, Person>()
Expand All @@ -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,
Expand All @@ -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: () => <span>Visits</span>,
footer: (props) => props.column.id,
Expand All @@ -167,9 +169,9 @@ const columns = columnHelper.columns([
header: 'Profile Progress',
footer: (props) => props.column.id,
}),
],
]),
}),
],
]),
}),
])

Expand All @@ -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,
Expand Down Expand Up @@ -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}
</div>
{header.column.getCanFilter() ? (
<div>
Expand All @@ -270,7 +272,7 @@ const App = component$(() => {
{table.getRowModel().rows.map((row) => {
return (
<tr key={row.id}>
{row.getVisibleCells().map((cell) => (
{row.getAllCells().map((cell) => (
<td key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
Expand All @@ -290,8 +292,8 @@ function Filter({
column,
table,
}: {
column: Column<any, unknown>
table: Table<any>
column: Column<typeof _features, Person>
table: Table<typeof _features, Person>
}) {
const { id } = column
const firstValue = table
Expand Down
18 changes: 14 additions & 4 deletions examples/qwik/row-selection/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -226,12 +227,21 @@ const App = component$(() => {
)
})

const IndeterminateCheckbox = component$<{
indeterminate?: boolean
}>(({ indeterminate, ...rest }) => {
const IndeterminateCheckbox = component$<
Omit<JSX.IntrinsicElements['input'], 'type'> & {
indeterminate?: boolean
}
>(({ indeterminate, ...rest }) => {
const inputSig = useSignal<Element | undefined>()

return <input type="checkbox" ref={inputSig} {...rest} />
return (
<input
type="checkbox"
ref={inputSig}
indeterminate={indeterminate}
{...rest}
/>
)
})

render(document.getElementById('app') as HTMLElement, <App />)
63 changes: 63 additions & 0 deletions packages/qwik-table/src/createTableHelper.ts
Original file line number Diff line number Diff line change
@@ -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<TableHelper_Core<TFeatures, TData>, 'tableCreator'> & {
useTable: (
tableOptions: Omit<
TableOptions<TFeatures, TData>,
'_features' | '_rowModels'
>,
) => NoSerialize<Table<TFeatures, TData>>
}

export function createTableHelper<
TFeatures extends TableFeatures,
TDataList extends Array<RowData> = Array<any>,
>(
tableHelperOptions: TableHelperOptions<TFeatures, TDataList>,
): TableHelper<TFeatures, TDataList[number]> {
const tableHelper = constructTableHelper(useTable as any, tableHelperOptions)
return {
...tableHelper,
useTable: tableHelper.tableCreator,
} as unknown as TableHelper<TFeatures, TDataList[number]>
}

// 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<ColumnDef<typeof tableHelper.features, Person, unknown>>

// const data: Array<Person> = []

// tableHelper.useTable({
// columns,
// data,
// })
20 changes: 20 additions & 0 deletions packages/qwik-table/src/flexRender.tsx
Original file line number Diff line number Diff line change
@@ -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<TProps extends object>(
Comp: any, // TODO: add renderable type
props: TProps,
) {
return !Comp ? null : isQwikComponent(Comp) ? (
<Comp {...props} />
) : isFunction(Comp) ? (
Comp(props)
) : (
Comp
)
}
72 changes: 3 additions & 69 deletions packages/qwik-table/src/index.tsx
Original file line number Diff line number Diff line change
@@ -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<TProps extends object>(
Comp: any, // TODO: add renderable type
props: TProps,
) {
return !Comp ? null : isQwikComponent(Comp) ? (
<Comp {...props} />
) : isFunction(Comp) ? (
Comp(props)
) : (
Comp
)
}

export function useTable<
TFeatures extends TableFeatures,
TData extends RowData,
>(options: TableOptions<TFeatures, TData>) {
// Compose in the generic options to the user options
const resolvedOptions: TableOptions<TFeatures, TData> = {
state: {},
onStateChange: () => {},
renderFallbackValue: null,
...options,
}

// Create a new table instance and store it in a Qwik store
const table = Qwik.useStore<{
instance: Qwik.NoSerialize<Table<TFeatures, TData>>
}>({
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<TFeatures, TData>
}
46 changes: 46 additions & 0 deletions packages/qwik-table/src/useTable.ts
Original file line number Diff line number Diff line change
@@ -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<TFeatures, TData>): Table<TFeatures, TData> {
const _features = { ...coreFeatures, ...tableOptions._features }

const state = useSignal(
getInitialTableState(_features, tableOptions.initialState),
)

const statefulOptions: TableOptions<TFeatures, TData> = {
...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<Table<TFeatures, TData>>
}>({
instance: noSerialize(constructTable(statefulOptions)),
})

return table.instance!
}

0 comments on commit 424301c

Please sign in to comment.