Skip to content

Commit

Permalink
feat: implement vue adapter (#3848)
Browse files Browse the repository at this point in the history
* implement vue adapter

* fix package description

Co-authored-by: Tanner Linsley <tannerlinsley@gmail.com>
  • Loading branch information
Mokshit06 and tannerlinsley committed Apr 20, 2022
1 parent 2d88e65 commit 2986a36
Show file tree
Hide file tree
Showing 9 changed files with 377 additions and 2 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"private": true,
"repository": "https://github.com/tanstack/react-table.git",
"scripts": {
"linkAll": "lerna exec 'yarn link' && lerna exec 'yarn link @tanstack/react-table' && lerna exec 'yarn link @tanstack/solid-table'",
"linkAll": "lerna exec 'yarn link' && lerna exec 'yarn link @tanstack/react-table' && lerna exec 'yarn link @tanstack/solid-table' && lerna exec 'yarn link @tanstack/vue-table'",
"unlinkAll": "lerna exec yarn unlink",
"test": "(is-ci && yarn test:ci) || yarn test:dev",
"test:ci": "jest",
Expand All @@ -19,6 +19,7 @@
"./packages/table-core",
"./packages/react-table",
"./packages/solid-table",
"./packages/vue-table",
"./packages/react-table-devtools"
],
"devDependencies": {
Expand Down Expand Up @@ -54,6 +55,7 @@
"solid-js": "^1.3.15",
"stream-to-array": "^2.3.0",
"ts-node": "^10.7.0",
"typescript": "^4.7.0-beta"
"typescript": "^4.7.0-beta",
"vue": "^3.2.33"
}
}
2 changes: 2 additions & 0 deletions packages/table-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
},
"keywords": [
"react",
"vue",
"solid",
"table",
"table-core",
"datagrid"
Expand Down
42 changes: 42 additions & 0 deletions packages/vue-table/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@tanstack/vue-table",
"author": "Tanner Linsley",
"version": "8.0.0-alpha.31",
"description": "Composables for building lightweight, fast and extendable datagrids for Vue",
"license": "MIT",
"homepage": "https://github.com/tanstack/react-table#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/tanstack/react-table.git"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/"
},
"keywords": [
"vue",
"table",
"vue-table",
"datagrid"
],
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"module": "build/esm/index.js",
"main": "build/cjs/index.js",
"browser": "build/umd/index.production.min.js",
"types": "build/types/index.d.ts",
"engines": {
"node": ">=12"
},
"files": [
"build",
"src"
],
"dependencies": {
"@tanstack/table-core": "8.0.0-alpha.30"
},
"peerDependencies": {
"vue": "^3.2.33"
}
}
84 changes: 84 additions & 0 deletions packages/vue-table/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import {
AnyGenerics,
CreateTableFactoryOptions,
Options,
PartialKeys,
Table,
createTableInstance,
init,
TableFeature,
} from '@tanstack/table-core'
import { h, watchEffect, ref } from 'vue'
import { mergeProxy } from './merge-proxy'

export * from '@tanstack/table-core'

function render<TProps extends {}>(Comp: any, props: TProps) {
if (!Comp) return null

if (typeof Comp === 'function') {
return h(Comp, props)
}

return Comp
}

const { createTable, createTableFactory } = init({ render })

export { createTable, createTableFactory }

export function useTableInstance<TGenerics extends AnyGenerics>(
table: Table<TGenerics>,
options: PartialKeys<
Omit<
Options<TGenerics>,
keyof CreateTableFactoryOptions<any, any, any, any>
>,
'state' | 'onStateChange'
>
) {
const resolvedOptions: Options<TGenerics> = mergeProxy(
{
...(table.__options ?? {}),
state: {}, // Dummy state
onStateChange: () => {}, // noop
render,
mergeOptions(defaultOptions: TableFeature, options: Options<TGenerics>) {
return mergeProxy(defaultOptions, options)
},
},
options
)

const instance = createTableInstance<TGenerics>(resolvedOptions)
// can't use `reactive` because update needs to be immutable
const state = ref(instance.initialState)

watchEffect(() => {
instance.setOptions(prev => {
const stateProxy = new Proxy({} as typeof state.value, {
get: (_, prop) => state.value[prop as keyof typeof state.value],
})

return mergeProxy(prev, options, {
// merge the initialState and `options.state`
// create a new proxy on each `setOptions` call
// and get the value from state on each property access
state: mergeProxy(stateProxy, options.state ?? {}),
// Similarly, we'll maintain both our internal state and any user-provided
// state.
onStateChange: (updater: any) => {
if (updater instanceof Function) {
state.value = updater(state.value)
} else {
state.value = updater
}

options.onStateChange?.(updater)
},
})
})
})

return instance
}
81 changes: 81 additions & 0 deletions packages/vue-table/src/merge-proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
function trueFn() {
return true
}

export const $PROXY = Symbol('merge-proxy')

// https://github.com/solidjs/solid/blob/c20ca4fd8c36bc0522fedb2c7f38a110b7ee2663/packages/solid/src/render/component.ts#L51-L118
const propTraps: ProxyHandler<{
get: (k: string | number | symbol) => any
has: (k: string | number | symbol) => boolean
keys: () => string[]
}> = {
get(_, property, receiver) {
if (property === $PROXY) return receiver
return _.get(property)
},
has(_, property) {
return _.has(property)
},
set: trueFn,
deleteProperty: trueFn,
getOwnPropertyDescriptor(_, property) {
return {
configurable: true,
enumerable: true,
get() {
return _.get(property)
},
set: trueFn,
deleteProperty: trueFn,
}
},
ownKeys(_) {
return _.keys()
},
}

type UnboxLazy<T> = T extends () => infer U ? U : T
type BoxedTupleTypes<T extends any[]> = {
[P in keyof T]: [UnboxLazy<T[P]>]
}[Exclude<keyof T, keyof any[]>]
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never
type UnboxIntersection<T> = T extends { 0: infer U } ? U : never
type MergeProxy<T extends any[]> = UnboxIntersection<
UnionToIntersection<BoxedTupleTypes<T>>
>

function resolveSource(s: any) {
return 'value' in s ? s.value : s
}

export function mergeProxy<T extends any[]>(...sources: T): MergeProxy<T>
export function mergeProxy(...sources: any): any {
return new Proxy(
{
get(property: string | number | symbol) {
for (let i = sources.length - 1; i >= 0; i--) {
const v = resolveSource(sources[i])[property]
if (v !== undefined) return v
}
},
has(property: string | number | symbol) {
for (let i = sources.length - 1; i >= 0; i--) {
if (property in resolveSource(sources[i])) return true
}
return false
},
keys() {
const keys = []
for (let i = 0; i < sources.length; i++)
keys.push(...Object.keys(resolveSource(sources[i])))
return [...new Set(keys)]
},
},
propTraps
)
}
12 changes: 12 additions & 0 deletions packages/vue-table/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"composite": true,
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./build/types"
},
"files": ["src/index.tsx"],
"include": [
"src"
// "__tests__/**/*.test.*"
]
}
8 changes: 8 additions & 0 deletions packages/vue-table/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@tanstack/table-core@8.0.0-alpha.30":
version "8.0.0-alpha.30"
resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.0.0-alpha.30.tgz#cec207bc869af82cfcbe314ed840a2756a17e900"
integrity sha512-oz15xICZ7zwQvt/KUUCrvpKt569c5/f83p19CDKvFCcyXC1Yls/WfdSgodqYAuHEgQER0HCn8UDXZyMIcnrTkg==
9 changes: 9 additions & 0 deletions rollup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ type Options = {

const globals = {
react: 'React',
vue: 'Vue',
'solid-js': 'Solid',
'solid-js/store': 'SolidStore',
'react-dom': 'ReactDOM',
'@tanstack/table-core': 'TableCore',
'@tanstack/vue-table': 'VueTable',
'@tanstack/solid-table': 'SolidTable',
'@tanstack/react-table': 'ReactTable',
'@tanstack/react-table-devtools': 'ReactTableDevtools',
Expand Down Expand Up @@ -65,6 +67,13 @@ export default function rollup(options: RollupOptions): RollupOptions[] {
outputFile: 'solid-table',
entryFile: 'src/index.tsx',
}),
...buildConfigs({
name: 'vue-table',
packageDir: 'packages/vue-table',
jsName: 'VueTable',
outputFile: 'vue-table',
entryFile: 'src/index.ts',
}),
...buildConfigs({
name: 'react-table-devtools',
packageDir: 'packages/react-table-devtools',
Expand Down

1 comment on commit 2986a36

@vercel
Copy link

@vercel vercel bot commented on 2986a36 Apr 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

react-table – ./

react-table-tanstack.vercel.app
react-table-v8.tanstack.com
react-table-git-alpha-tanstack.vercel.app

Please sign in to comment.