UNPKG

@tanstack/angular-virtual

Version:

Headless UI for virtualizing scrollable elements in Angular

91 lines 11.7 kB
import { computed, untracked } from '@angular/core'; export function proxyVirtualizer(virtualizerSignal, lazyInit) { return new Proxy(virtualizerSignal, { apply() { return virtualizerSignal(); }, get(target, property) { const untypedTarget = target; if (untypedTarget[property]) { return untypedTarget[property]; } let virtualizer = untracked(virtualizerSignal); if (virtualizer == null) { virtualizer = lazyInit(); untracked(() => virtualizerSignal.set(virtualizer)); } // Create computed signals for each property that represents a reactive value if (typeof property === 'string' && [ 'getTotalSize', 'getVirtualItems', 'isScrolling', 'options', 'range', 'scrollDirection', 'scrollElement', 'scrollOffset', 'scrollRect', 'measureElementCache', 'measurementsCache', ].includes(property)) { const isFunction = typeof virtualizer[property] === 'function'; Object.defineProperty(untypedTarget, property, { value: isFunction ? computed(() => target()[property]()) : computed(() => target()[property]), configurable: true, enumerable: true, }); } // Create plain signals for functions that accept arguments and return reactive values if (typeof property === 'string' && [ 'getOffsetForAlignment', 'getOffsetForIndex', 'getVirtualItemForOffset', 'indexFromElement', ].includes(property)) { const fn = virtualizer[property]; Object.defineProperty(untypedTarget, property, { value: toComputed(virtualizerSignal, fn), configurable: true, enumerable: true, }); } return untypedTarget[property] || virtualizer[property]; }, has(_, property) { return !!untracked(virtualizerSignal)[property]; }, ownKeys() { return Reflect.ownKeys(untracked(virtualizerSignal)); }, getOwnPropertyDescriptor() { return { enumerable: true, configurable: true, }; }, }); } function toComputed(signal, fn) { const computedCache = {}; return (...args) => { // Cache computeds by their arguments to avoid re-creating the computed on each call const serializedArgs = serializeArgs(...args); if (computedCache.hasOwnProperty(serializedArgs)) { return computedCache[serializedArgs]?.(); } const computedSignal = computed(() => { void signal(); return fn(...args); }); computedCache[serializedArgs] = computedSignal; return computedSignal(); }; } function serializeArgs(...args) { return JSON.stringify(args); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJveHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJveHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFLbkQsTUFBTSxVQUFVLGdCQUFnQixDQUs5QixpQkFBb0MsRUFDcEMsUUFBaUI7SUFFakIsT0FBTyxJQUFJLEtBQUssQ0FBQyxpQkFBaUIsRUFBRTtRQUNsQyxLQUFLO1lBQ0gsT0FBTyxpQkFBaUIsRUFBRSxDQUFBO1FBQzVCLENBQUM7UUFDRCxHQUFHLENBQUMsTUFBTSxFQUFFLFFBQVE7WUFDbEIsTUFBTSxhQUFhLEdBQUcsTUFBYSxDQUFBO1lBQ25DLElBQUksYUFBYSxDQUFDLFFBQVEsQ0FBQyxFQUFFO2dCQUMzQixPQUFPLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQTthQUMvQjtZQUNELElBQUksV0FBVyxHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1lBQzlDLElBQUksV0FBVyxJQUFJLElBQUksRUFBRTtnQkFDdkIsV0FBVyxHQUFHLFFBQVEsRUFBRSxDQUFBO2dCQUN4QixTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUE7YUFDcEQ7WUFFRCw2RUFBNkU7WUFDN0UsSUFDRSxPQUFPLFFBQVEsS0FBSyxRQUFRO2dCQUM1QjtvQkFDRSxjQUFjO29CQUNkLGlCQUFpQjtvQkFDakIsYUFBYTtvQkFDYixTQUFTO29CQUNULE9BQU87b0JBQ1AsaUJBQWlCO29CQUNqQixlQUFlO29CQUNmLGNBQWM7b0JBQ2QsWUFBWTtvQkFDWixxQkFBcUI7b0JBQ3JCLG1CQUFtQjtpQkFDcEIsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQ3BCO2dCQUNBLE1BQU0sVUFBVSxHQUNkLE9BQU8sV0FBVyxDQUFDLFFBQW1CLENBQUMsS0FBSyxVQUFVLENBQUE7Z0JBQ3hELE1BQU0sQ0FBQyxjQUFjLENBQUMsYUFBYSxFQUFFLFFBQVEsRUFBRTtvQkFDN0MsS0FBSyxFQUFFLFVBQVU7d0JBQ2YsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBRSxNQUFNLEVBQUUsQ0FBQyxRQUFtQixDQUFjLEVBQUUsQ0FBQzt3QkFDL0QsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFtQixDQUFDLENBQUM7b0JBQ2pELFlBQVksRUFBRSxJQUFJO29CQUNsQixVQUFVLEVBQUUsSUFBSTtpQkFDakIsQ0FBQyxDQUFBO2FBQ0g7WUFFRCxzRkFBc0Y7WUFDdEYsSUFDRSxPQUFPLFFBQVEsS0FBSyxRQUFRO2dCQUM1QjtvQkFDRSx1QkFBdUI7b0JBQ3ZCLG1CQUFtQjtvQkFDbkIseUJBQXlCO29CQUN6QixrQkFBa0I7aUJBQ25CLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUNwQjtnQkFDQSxNQUFNLEVBQUUsR0FBRyxXQUFXLENBQUMsUUFBbUIsQ0FBYSxDQUFBO2dCQUN2RCxNQUFNLENBQUMsY0FBYyxDQUFDLGFBQWEsRUFBRSxRQUFRLEVBQUU7b0JBQzdDLEtBQUssRUFBRSxVQUFVLENBQUMsaUJBQWlCLEVBQUUsRUFBRSxDQUFDO29CQUN4QyxZQUFZLEVBQUUsSUFBSTtvQkFDbEIsVUFBVSxFQUFFLElBQUk7aUJBQ2pCLENBQUMsQ0FBQTthQUNIO1lBRUQsT0FBTyxhQUFhLENBQUMsUUFBUSxDQUFDLElBQUksV0FBVyxDQUFDLFFBQW1CLENBQUMsQ0FBQTtRQUNwRSxDQUFDO1FBQ0QsR0FBRyxDQUFDLENBQUMsRUFBRSxRQUFnQjtZQUNyQixPQUFPLENBQUMsQ0FBQyxTQUFTLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxRQUFtQixDQUFDLENBQUE7UUFDNUQsQ0FBQztRQUNELE9BQU87WUFDTCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQTtRQUN0RCxDQUFDO1FBQ0Qsd0JBQXdCO1lBQ3RCLE9BQU87Z0JBQ0wsVUFBVSxFQUFFLElBQUk7Z0JBQ2hCLFlBQVksRUFBRSxJQUFJO2FBQ25CLENBQUE7UUFDSCxDQUFDO0tBQ0YsQ0FBd0MsQ0FBQTtBQUMzQyxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQ2pCLE1BQWlCLEVBQ2pCLEVBQVk7SUFFWixNQUFNLGFBQWEsR0FBb0MsRUFBRSxDQUFBO0lBRXpELE9BQU8sQ0FBQyxHQUFHLElBQWdCLEVBQUUsRUFBRTtRQUM3QixvRkFBb0Y7UUFDcEYsTUFBTSxjQUFjLEdBQUcsYUFBYSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUE7UUFDN0MsSUFBSSxhQUFhLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxFQUFFO1lBQ2hELE9BQU8sYUFBYSxDQUFDLGNBQWMsQ0FBQyxFQUFFLEVBQUUsQ0FBQTtTQUN6QztRQUNELE1BQU0sY0FBYyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7WUFDbkMsS0FBSyxNQUFNLEVBQUUsQ0FBQTtZQUNiLE9BQU8sRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUE7UUFDcEIsQ0FBQyxDQUFDLENBQUE7UUFFRixhQUFhLENBQUMsY0FBYyxDQUFDLEdBQUcsY0FBYyxDQUFBO1FBRTlDLE9BQU8sY0FBYyxFQUFFLENBQUE7SUFDekIsQ0FBQyxDQUFBO0FBQ0gsQ0FBQztBQUVELFNBQVMsYUFBYSxDQUFDLEdBQUcsSUFBZ0I7SUFDeEMsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFBO0FBQzdCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjb21wdXRlZCwgdW50cmFja2VkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB0eXBlIHsgU2lnbmFsLCBXcml0YWJsZVNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnXG5pbXBvcnQgdHlwZSB7IFZpcnR1YWxpemVyIH0gZnJvbSAnQHRhbnN0YWNrL3ZpcnR1YWwtY29yZSdcbmltcG9ydCB0eXBlIHsgQW5ndWxhclZpcnR1YWxpemVyIH0gZnJvbSAnLi90eXBlcydcblxuZXhwb3J0IGZ1bmN0aW9uIHByb3h5VmlydHVhbGl6ZXI8XG4gIFYgZXh0ZW5kcyBWaXJ0dWFsaXplcjxhbnksIGFueT4sXG4gIFMgZXh0ZW5kcyBFbGVtZW50IHwgV2luZG93ID0gViBleHRlbmRzIFZpcnR1YWxpemVyPGluZmVyIFUsIGFueT4gPyBVIDogbmV2ZXIsXG4gIEkgZXh0ZW5kcyBFbGVtZW50ID0gViBleHRlbmRzIFZpcnR1YWxpemVyPGFueSwgaW5mZXIgVT4gPyBVIDogbmV2ZXIsXG4+KFxuICB2aXJ0dWFsaXplclNpZ25hbDogV3JpdGFibGVTaWduYWw8Vj4sXG4gIGxhenlJbml0OiAoKSA9PiBWLFxuKTogQW5ndWxhclZpcnR1YWxpemVyPFMsIEk+IHtcbiAgcmV0dXJuIG5ldyBQcm94eSh2aXJ0dWFsaXplclNpZ25hbCwge1xuICAgIGFwcGx5KCkge1xuICAgICAgcmV0dXJuIHZpcnR1YWxpemVyU2lnbmFsKClcbiAgICB9LFxuICAgIGdldCh0YXJnZXQsIHByb3BlcnR5KSB7XG4gICAgICBjb25zdCB1bnR5cGVkVGFyZ2V0ID0gdGFyZ2V0IGFzIGFueVxuICAgICAgaWYgKHVudHlwZWRUYXJnZXRbcHJvcGVydHldKSB7XG4gICAgICAgIHJldHVybiB1bnR5cGVkVGFyZ2V0W3Byb3BlcnR5XVxuICAgICAgfVxuICAgICAgbGV0IHZpcnR1YWxpemVyID0gdW50cmFja2VkKHZpcnR1YWxpemVyU2lnbmFsKVxuICAgICAgaWYgKHZpcnR1YWxpemVyID09IG51bGwpIHtcbiAgICAgICAgdmlydHVhbGl6ZXIgPSBsYXp5SW5pdCgpXG4gICAgICAgIHVudHJhY2tlZCgoKSA9PiB2aXJ0dWFsaXplclNpZ25hbC5zZXQodmlydHVhbGl6ZXIpKVxuICAgICAgfVxuXG4gICAgICAvLyBDcmVhdGUgY29tcHV0ZWQgc2lnbmFscyBmb3IgZWFjaCBwcm9wZXJ0eSB0aGF0IHJlcHJlc2VudHMgYSByZWFjdGl2ZSB2YWx1ZVxuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2YgcHJvcGVydHkgPT09ICdzdHJpbmcnICYmXG4gICAgICAgIFtcbiAgICAgICAgICAnZ2V0VG90YWxTaXplJyxcbiAgICAgICAgICAnZ2V0VmlydHVhbEl0ZW1zJyxcbiAgICAgICAgICAnaXNTY3JvbGxpbmcnLFxuICAgICAgICAgICdvcHRpb25zJyxcbiAgICAgICAgICAncmFuZ2UnLFxuICAgICAgICAgICdzY3JvbGxEaXJlY3Rpb24nLFxuICAgICAgICAgICdzY3JvbGxFbGVtZW50JyxcbiAgICAgICAgICAnc2Nyb2xsT2Zmc2V0JyxcbiAgICAgICAgICAnc2Nyb2xsUmVjdCcsXG4gICAgICAgICAgJ21lYXN1cmVFbGVtZW50Q2FjaGUnLFxuICAgICAgICAgICdtZWFzdXJlbWVudHNDYWNoZScsXG4gICAgICAgIF0uaW5jbHVkZXMocHJvcGVydHkpXG4gICAgICApIHtcbiAgICAgICAgY29uc3QgaXNGdW5jdGlvbiA9XG4gICAgICAgICAgdHlwZW9mIHZpcnR1YWxpemVyW3Byb3BlcnR5IGFzIGtleW9mIFZdID09PSAnZnVuY3Rpb24nXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh1bnR5cGVkVGFyZ2V0LCBwcm9wZXJ0eSwge1xuICAgICAgICAgIHZhbHVlOiBpc0Z1bmN0aW9uXG4gICAgICAgICAgICA/IGNvbXB1dGVkKCgpID0+ICh0YXJnZXQoKVtwcm9wZXJ0eSBhcyBrZXlvZiBWXSBhcyBGdW5jdGlvbikoKSlcbiAgICAgICAgICAgIDogY29tcHV0ZWQoKCkgPT4gdGFyZ2V0KClbcHJvcGVydHkgYXMga2V5b2YgVl0pLFxuICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICB9KVxuICAgICAgfVxuXG4gICAgICAvLyBDcmVhdGUgcGxhaW4gc2lnbmFscyBmb3IgZnVuY3Rpb25zIHRoYXQgYWNjZXB0IGFyZ3VtZW50cyBhbmQgcmV0dXJuIHJlYWN0aXZlIHZhbHVlc1xuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2YgcHJvcGVydHkgPT09ICdzdHJpbmcnICYmXG4gICAgICAgIFtcbiAgICAgICAgICAnZ2V0T2Zmc2V0Rm9yQWxpZ25tZW50JyxcbiAgICAgICAgICAnZ2V0T2Zmc2V0Rm9ySW5kZXgnLFxuICAgICAgICAgICdnZXRWaXJ0dWFsSXRlbUZvck9mZnNldCcsXG4gICAgICAgICAgJ2luZGV4RnJvbUVsZW1lbnQnLFxuICAgICAgICBdLmluY2x1ZGVzKHByb3BlcnR5KVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IGZuID0gdmlydHVhbGl6ZXJbcHJvcGVydHkgYXMga2V5b2YgVl0gYXMgRnVuY3Rpb25cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHVudHlwZWRUYXJnZXQsIHByb3BlcnR5LCB7XG4gICAgICAgICAgdmFsdWU6IHRvQ29tcHV0ZWQodmlydHVhbGl6ZXJTaWduYWwsIGZuKSxcbiAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHVudHlwZWRUYXJnZXRbcHJvcGVydHldIHx8IHZpcnR1YWxpemVyW3Byb3BlcnR5IGFzIGtleW9mIFZdXG4gICAgfSxcbiAgICBoYXMoXywgcHJvcGVydHk6IHN0cmluZykge1xuICAgICAgcmV0dXJuICEhdW50cmFja2VkKHZpcnR1YWxpemVyU2lnbmFsKVtwcm9wZXJ0eSBhcyBrZXlvZiBWXVxuICAgIH0sXG4gICAgb3duS2V5cygpIHtcbiAgICAgIHJldHVybiBSZWZsZWN0Lm93bktleXModW50cmFja2VkKHZpcnR1YWxpemVyU2lnbmFsKSlcbiAgICB9LFxuICAgIGdldE93blByb3BlcnR5RGVzY3JpcHRvcigpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIH1cbiAgICB9LFxuICB9KSBhcyB1bmtub3duIGFzIEFuZ3VsYXJWaXJ0dWFsaXplcjxTLCBJPlxufVxuXG5mdW5jdGlvbiB0b0NvbXB1dGVkPFYgZXh0ZW5kcyBWaXJ0dWFsaXplcjxhbnksIGFueT4+KFxuICBzaWduYWw6IFNpZ25hbDxWPixcbiAgZm46IEZ1bmN0aW9uLFxuKSB7XG4gIGNvbnN0IGNvbXB1dGVkQ2FjaGU6IFJlY29yZDxzdHJpbmcsIFNpZ25hbDx1bmtub3duPj4gPSB7fVxuXG4gIHJldHVybiAoLi4uYXJnczogQXJyYXk8YW55PikgPT4ge1xuICAgIC8vIENhY2hlIGNvbXB1dGVkcyBieSB0aGVpciBhcmd1bWVudHMgdG8gYXZvaWQgcmUtY3JlYXRpbmcgdGhlIGNvbXB1dGVkIG9uIGVhY2ggY2FsbFxuICAgIGNvbnN0IHNlcmlhbGl6ZWRBcmdzID0gc2VyaWFsaXplQXJncyguLi5hcmdzKVxuICAgIGlmIChjb21wdXRlZENhY2hlLmhhc093blByb3BlcnR5KHNlcmlhbGl6ZWRBcmdzKSkge1xuICAgICAgcmV0dXJuIGNvbXB1dGVkQ2FjaGVbc2VyaWFsaXplZEFyZ3NdPy4oKVxuICAgIH1cbiAgICBjb25zdCBjb21wdXRlZFNpZ25hbCA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICAgIHZvaWQgc2lnbmFsKClcbiAgICAgIHJldHVybiBmbiguLi5hcmdzKVxuICAgIH0pXG5cbiAgICBjb21wdXRlZENhY2hlW3NlcmlhbGl6ZWRBcmdzXSA9IGNvbXB1dGVkU2lnbmFsXG5cbiAgICByZXR1cm4gY29tcHV0ZWRTaWduYWwoKVxuICB9XG59XG5cbmZ1bmN0aW9uIHNlcmlhbGl6ZUFyZ3MoLi4uYXJnczogQXJyYXk8YW55Pikge1xuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYXJncylcbn1cbiJdfQ==