-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Expand file tree
/
Copy pathindex.ts
More file actions
executable file
·140 lines (125 loc) · 3.36 KB
/
index.ts
File metadata and controls
executable file
·140 lines (125 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import {
TableOptions,
createTable,
RowData,
TableOptionsResolved,
} from '@tanstack/table-core'
import {
h,
watchEffect,
ref,
defineComponent,
isRef,
unref,
MaybeRef,
watch,
shallowRef,
} from 'vue'
import { mergeProxy } from './merge-proxy'
export * from '@tanstack/table-core'
export type TableOptionsWithReactiveData<TData extends RowData> = Omit<
TableOptions<TData>,
'data'
> & {
data: MaybeRef<TData[]>
}
export const FlexRender = defineComponent({
props: ['render', 'props'],
setup: (props: { render: any; props: any }) => {
return () => {
if (
typeof props.render === 'function' ||
typeof props.render === 'object'
) {
return h(props.render, props.props)
}
// Return null for empty/nullish values to avoid Vue SSR hydration
// mismatches (e.g. empty string renders a text node on the client
// but nothing on the server)
if (props.render == null || props.render === '') {
return null
}
return props.render
}
},
})
function getOptionsWithReactiveData<TData extends RowData>(
options: TableOptionsWithReactiveData<TData>,
) {
return mergeProxy(options, {
data: unref(options.data),
})
}
export function useVueTable<TData extends RowData>(
initialOptions: TableOptionsWithReactiveData<TData>,
) {
const IS_REACTIVE = isRef(initialOptions.data)
const resolvedOptions = mergeProxy(
{
state: {}, // Dummy state
onStateChange: () => {}, // noop
renderFallbackValue: null,
mergeOptions(
defaultOptions: TableOptions<TData>,
options: TableOptions<TData>,
) {
return IS_REACTIVE
? {
...defaultOptions,
...options,
}
: mergeProxy(defaultOptions, options)
},
},
IS_REACTIVE ? getOptionsWithReactiveData(initialOptions) : initialOptions,
)
const table = createTable<TData>(
resolvedOptions as TableOptionsResolved<TData>,
)
// Add reactivity support
if (IS_REACTIVE) {
const dataRef = shallowRef(initialOptions.data)
watch(
dataRef,
() => {
table.setState((prev) => ({
...prev,
data: dataRef.value,
}))
},
{ immediate: true },
)
}
// can't use `reactive` because update needs to be immutable
const state = ref(table.initialState)
watchEffect(() => {
table.setOptions((prev) => {
const stateProxy = new Proxy({} as typeof state.value, {
get: (_, prop) => state.value[prop as keyof typeof state.value],
})
return mergeProxy(
prev,
IS_REACTIVE
? getOptionsWithReactiveData(initialOptions)
: initialOptions,
{
// 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, initialOptions.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
}
initialOptions.onStateChange?.(updater)
},
},
)
})
})
return table
}