@tanstack/angular-table 9.0.0-alpha.12 → 9.0.0-alpha.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,232 +0,0 @@
1
- import { computed, isSignal } from '@angular/core'
2
- import { $internalMemoFnMeta, getMemoFnMeta } from '@tanstack/table-core'
3
- import type { MemoFnMeta } from '@tanstack/table-core'
4
- import type { Signal } from '@angular/core'
5
-
6
- const $TABLE_REACTIVE = Symbol('reactive')
7
-
8
- function markReactive<T extends object>(obj: T): void {
9
- Object.defineProperty(obj, $TABLE_REACTIVE, { value: true })
10
- }
11
-
12
- function isReactive<T>(obj: T): boolean {
13
- return Reflect.get(obj as {}, $TABLE_REACTIVE) === true
14
- }
15
-
16
- /**
17
- * Defines a lazy computed property on an object. The property is initialized
18
- * with a getter that computes its value only when accessed for the first time.
19
- * After the first access, the computed value is cached, and the getter is
20
- * replaced with a direct property assignment for efficiency.
21
- *
22
- * @internal should be used only internally
23
- */
24
- export function defineLazyComputedProperty<T extends object>(
25
- notifier: Signal<T>,
26
- setObjectOptions: {
27
- originalObject: T
28
- property: keyof T & string
29
- valueFn: (...args: any) => any
30
- overridePrototype?: boolean
31
- },
32
- ) {
33
- const { originalObject, property, overridePrototype, valueFn } =
34
- setObjectOptions
35
-
36
- if (overridePrototype) {
37
- assignReactivePrototypeAPI(notifier, originalObject, property)
38
- } else {
39
- Object.defineProperty(originalObject, property, {
40
- enumerable: true,
41
- configurable: true,
42
- get() {
43
- const computedValue = toComputed(notifier, valueFn, property)
44
- markReactive(computedValue)
45
- // Once the property is set the first time, we don't need a getter anymore
46
- // since we have a computed / cached fn value
47
- Object.defineProperty(originalObject, property, {
48
- value: computedValue,
49
- configurable: true,
50
- enumerable: true,
51
- })
52
- return computedValue
53
- },
54
- })
55
- }
56
- }
57
-
58
- /**
59
- * @internal should be used only internally
60
- */
61
- type ComputedFunction<T> = T extends () => infer TReturn
62
- ? Signal<TReturn>
63
- : // 1+ args
64
- T extends (arg0?: any, ...args: Array<any>) => any
65
- ? T
66
- : never
67
-
68
- /**
69
- * @description Transform a function into a computed that react to given notifier re-computations
70
- *
71
- * Here we'll handle all type of accessors:
72
- * - 0 argument -> e.g. table.getCanNextPage())
73
- * - 0~1 arguments -> e.g. table.getIsSomeRowsPinned(position?)
74
- * - 1 required argument -> e.g. table.getColumn(columnId)
75
- * - 1+ argument -> e.g. table.getRow(id, searchAll?)
76
- *
77
- * Since we are not able to detect automatically the accessors parameters,
78
- * we'll wrap all accessors into a cached function wrapping a computed
79
- * that return it's value based on the given parameters
80
- *
81
- * @internal should be used only internally
82
- */
83
- export function toComputed<
84
- T,
85
- TReturn,
86
- TFunction extends (...args: any) => TReturn,
87
- >(
88
- notifier: Signal<T>,
89
- fn: TFunction,
90
- debugName: string,
91
- ): ComputedFunction<TFunction> {
92
- const hasArgs = getFnArgsLength(fn) > 0
93
- if (!hasArgs) {
94
- const computedFn = computed(
95
- () => {
96
- void notifier()
97
- return fn()
98
- },
99
- { debugName },
100
- )
101
- Object.defineProperty(computedFn, 'name', { value: debugName })
102
- markReactive(computedFn)
103
- return computedFn as ComputedFunction<TFunction>
104
- }
105
-
106
- const computedFn: ((this: unknown, ...argsArray: Array<any>) => unknown) & {
107
- _reactiveCache?: Record<string, Signal<unknown>>
108
- } = function (this: unknown, ...argsArray: Array<any>) {
109
- const cacheable =
110
- argsArray.length === 0 ||
111
- argsArray.every((arg) => {
112
- return (
113
- arg === null ||
114
- arg === undefined ||
115
- typeof arg === 'string' ||
116
- typeof arg === 'number' ||
117
- typeof arg === 'boolean' ||
118
- typeof arg === 'symbol'
119
- )
120
- })
121
- if (!cacheable) {
122
- return fn.apply(this, argsArray)
123
- }
124
- const serializedArgs = serializeArgs(...argsArray)
125
- if ((computedFn._reactiveCache ??= {})[serializedArgs]) {
126
- return computedFn._reactiveCache[serializedArgs]()
127
- }
128
- const computedSignal = computed(
129
- () => {
130
- void notifier()
131
- return fn.apply(this, argsArray)
132
- },
133
- { debugName },
134
- )
135
-
136
- computedFn._reactiveCache[serializedArgs] = computedSignal
137
-
138
- return computedSignal()
139
- }
140
-
141
- Object.defineProperty(computedFn, 'name', { value: debugName })
142
- markReactive(computedFn)
143
-
144
- return computedFn as ComputedFunction<TFunction>
145
- }
146
-
147
- function serializeArgs(...args: Array<any>) {
148
- return JSON.stringify(args)
149
- }
150
-
151
- function getFnArgsLength(
152
- fn: ((...args: any) => any) & { originalArgsLength?: number },
153
- ): number {
154
- return Math.max(0, getMemoFnMeta(fn)?.originalArgsLength ?? fn.length)
155
- }
156
-
157
- function assignReactivePrototypeAPI(
158
- notifier: Signal<unknown>,
159
- prototype: Record<string, any>,
160
- fnName: string,
161
- ) {
162
- if (isReactive(prototype[fnName])) return
163
-
164
- const fn = prototype[fnName]
165
- const originalArgsLength = getFnArgsLength(fn)
166
-
167
- if (originalArgsLength <= 1) {
168
- Object.defineProperty(prototype, fnName, {
169
- enumerable: true,
170
- configurable: true,
171
- get(this) {
172
- const self = this
173
- // Create a cache in the current prototype to allow the signals
174
- // to be garbage collected. Shorthand for a WeakMap implementation
175
- self._reactiveCache ??= {}
176
- const cached = (self._reactiveCache[`${self.id}${fnName}`] ??= computed(
177
- () => {
178
- notifier()
179
- return fn.apply(self)
180
- },
181
- {},
182
- ))
183
- markReactive(cached)
184
- cached[$internalMemoFnMeta] = {
185
- originalArgsLength,
186
- } satisfies MemoFnMeta
187
- return cached
188
- },
189
- })
190
- } else {
191
- prototype[fnName] = function (this: unknown, ...args: Array<any>) {
192
- notifier()
193
- return fn.apply(this, args)
194
- }
195
- markReactive(prototype[fnName])
196
- prototype[fnName][$internalMemoFnMeta] = {
197
- originalArgsLength,
198
- } satisfies MemoFnMeta
199
- }
200
- }
201
-
202
- export function setReactivePropertiesOnObject<T extends object>(
203
- notifier: Signal<T>,
204
- obj: { [key: string]: any },
205
- options: {
206
- overridePrototype?: boolean
207
- skipProperty: (property: string) => boolean
208
- },
209
- ) {
210
- const { skipProperty } = options
211
- if (isReactive(obj)) {
212
- return
213
- }
214
- markReactive(obj)
215
-
216
- for (const property in obj) {
217
- const value = obj[property]
218
- if (
219
- isSignal(value) ||
220
- typeof value !== 'function' ||
221
- skipProperty(property)
222
- ) {
223
- continue
224
- }
225
- defineLazyComputedProperty(notifier, {
226
- valueFn: value,
227
- property,
228
- originalObject: obj,
229
- overridePrototype: options.overridePrototype,
230
- })
231
- }
232
- }