Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 31 additions & 27 deletions packages/angular-table/src/injectTable.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
Injector,
NgZone,
assertInInjectionContext,
effect,
inject,
Expand Down Expand Up @@ -96,34 +97,37 @@ export function injectTable<
): AngularTable<TFeatures, TData> {
assertInInjectionContext(injectTable)
const injector = inject(Injector)
const ngZone = inject(NgZone)

return lazyInit(() => {
const table = constructTable({
...options(),
_features: {
coreReativityFeature: angularReactivity(injector),
...options()._features,
},
})
return ngZone.runOutsideAngular(() =>
lazyInit(() => {
const table = constructTable({
...options(),
_features: {
coreReativityFeature: angularReactivity(injector),
...options()._features,
},
})

let isMount = true
effect(
() => {
const newOptions = options()
if (isMount) {
isMount = false
return
}
untracked(() =>
table.setOptions((previous) => ({
...previous,
...newOptions,
})),
)
},
{ injector, debugName: 'tableOptionsUpdate' },
)
let isMount = true
effect(
() => {
const newOptions = options()
if (isMount) {
isMount = false
return
}
untracked(() =>
table.setOptions((previous) => ({
...previous,
...newOptions,
})),
)
},
{ injector, debugName: 'tableOptionsUpdate' },
)

return table
})
return table
}),
)
}
4 changes: 3 additions & 1 deletion packages/angular-table/src/reactivity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { computed, signal, untracked } from '@angular/core'
import { NgZone, computed, signal, untracked } from '@angular/core'
import { toObservable } from '@angular/core/rxjs-interop'
import type { Atom, Observer, ReadonlyAtom } from '@tanstack/angular-store'
import type {
Expand Down Expand Up @@ -49,8 +49,10 @@ function signalToWritableAtom<T>(
* and `effect` calls.
*/
export function angularReactivity(injector: Injector): TableReactivityBindings {
const ngZone = injector.get(NgZone)
return {
createOptionsStore: true,
schedule: (fn) => ngZone.runOutsideAngular(() => queueMicrotask(fn)),
createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {
const signal = computed(() => fn(), {
equal: options?.compare,
Expand Down
1 change: 1 addition & 0 deletions packages/lit-table/src/reactivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
export function litReactivity(): TableReactivityBindings {
return {
createOptionsStore: true,
schedule: (fn) => queueMicrotask(() => fn()),
batch,
untrack: (fn) => fn(),
createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {
Expand Down
1 change: 1 addition & 0 deletions packages/preact-table/src/reactivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
export function preactReactivity(): TableReactivityBindings {
return {
createOptionsStore: false,
schedule: (fn) => queueMicrotask(() => fn()),
batch,
untrack: (fn) => fn(),
createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {
Expand Down
1 change: 1 addition & 0 deletions packages/react-table/src/reactivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
export function reactReactivity(): TableReactivityBindings {
return {
createOptionsStore: false,
schedule: (fn) => queueMicrotask(fn),
batch,
untrack: (fn) => fn(),
createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {
Expand Down
1 change: 1 addition & 0 deletions packages/solid-table/src/reactivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function signalToWritableAtom<T>(
export function solidReactivity(owner: Owner): TableReactivityBindings {
return {
createOptionsStore: true,
schedule: (fn) => queueMicrotask(() => fn()),
createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {
const signal = createMemo(() => fn(), {
equals: options?.compare,
Expand Down
1 change: 1 addition & 0 deletions packages/svelte-table/src/reactivity.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ function subscribeToRune<T>(
export function svelteReactivity(): TableReactivityBindings {
return {
createOptionsStore: true,
schedule: (fn) => queueMicrotask(() => fn()),
createReadonlyAtom: <T>(fn: () => T, _options?: TableAtomOptions<T>) => {
const value = $derived.by(fn)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,8 @@ export interface TableReactivityBindings {
* Batches reactive updates to avoid intermediate recomputation.
*/
batch: (fn: () => void) => void
/**
* Schedules a function to run. This is used to defer updates after the current call stack (render, etc.) has finished
*/
schedule: (fn: () => void) => void
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function table_autoResetExpanded<
table.options.autoResetExpanded ??
!table.options.manualExpanding
) {
queueMicrotask(() => table_resetExpanded(table))
table._reactivity.schedule(() => table_resetExpanded(table))
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/table-core/src/store-reactivity-bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function storeReactivityBindings(): TableReactivityBindings {
return {
createOptionsStore: true,
batch,
schedule: (fn) => queueMicrotask(fn),
untrack: (fn) => fn(),
createReadonlyAtom: (fn, options) => {
return createAtom(() => fn(), {
Expand Down
36 changes: 7 additions & 29 deletions packages/table-core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,29 +106,6 @@ export function flattenBy<TNode>(
return flat
}

/**
* Symbol used to attach internal memo metadata to wrapped functions.
*
* This is exported so diagnostics can recognize memoized functions without
* depending on a string property name.
*/
export const $internalMemoFnMeta = Symbol('memoFnMeta')
export type MemoFnMeta = { originalArgsLength?: number }

/**
* @internal
*/
function setMemoFnMeta(fn: Function, meta: MemoFnMeta) {
Object.defineProperty(fn, $internalMemoFnMeta, { value: meta })
}

/**
* @internal
*/
export function getMemoFnMeta(fn: any): MemoFnMeta | null {
return (typeof fn === 'function' && fn[$internalMemoFnMeta]) ?? null
}

interface MemoOptions<TDeps extends ReadonlyArray<any>, TDepArgs, TResult> {
fn: (...args: NoInfer<TDeps>) => TResult
memoDeps?: (depArgs?: TDepArgs) => [...TDeps] | undefined
Expand Down Expand Up @@ -178,8 +155,6 @@ export const memo = <TDeps extends ReadonlyArray<any>, TDepArgs, TResult>({
return result
}

setMemoFnMeta(memoizedFn, { originalArgsLength: fn.length })

return memoizedFn
}

Expand Down Expand Up @@ -283,6 +258,11 @@ export function tableMemo<
console.groupEnd()
}

const onAfterUpdateHandler = () => {
const { schedule, untrack } = table._reactivity
schedule(() => untrack(() => onAfterUpdate?.()))
}

const debugOptions =
process.env.NODE_ENV === 'development'
? {
Expand Down Expand Up @@ -313,12 +293,12 @@ export function tableMemo<
Math.round((endCalcTime - startCalcTime) * 100) / 100
logTime(executionTime, true)
}
queueMicrotask(() => onAfterUpdate?.())
onAfterUpdateHandler()
},
}
: {
onAfterUpdate: () => {
queueMicrotask(() => onAfterUpdate?.())
onAfterUpdateHandler()
},
}

Expand Down Expand Up @@ -440,8 +420,6 @@ export function assignPrototypeAPIs<
return fn(this, ...args)
}
}

setMemoFnMeta(prototype[fnKey], { originalArgsLength: fn.length })
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/vue-table/src/reactivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ function refToWritableAtom<T>(source: ShallowRef<T>): Atom<T> {
export function vueReactivity(): TableReactivityBindings {
return {
createOptionsStore: true,
schedule: (fn) => queueMicrotask(() => fn()),
createReadonlyAtom: <T>(fn: () => T, _options?: TableAtomOptions<T>) => {
return refToReadonlyAtom(computed(fn))
},
Expand Down
Loading