import { isString, IPlatform, type IDisposable, emptyArray, resolve } from '@aurelia/kernel'; import { type Scope } from '@aurelia/runtime'; import { type BindingBehaviorInstance, BindingBehaviorStaticAuDefinition, behaviorTypeName } from '../binding-behavior'; import { type IBinding, type IRateLimitOptions } from '../../binding/interfaces-bindings'; const bindingHandlerMap: WeakMap = new WeakMap(); const defaultDelay = 200; export class ThrottleBindingBehavior implements BindingBehaviorInstance { public static readonly $au: BindingBehaviorStaticAuDefinition = { type: behaviorTypeName, name: 'throttle', }; /** @internal */ private readonly _now: () => number; public constructor() { ({ performanceNow: this._now } = resolve(IPlatform)); } public bind(scope: Scope, binding: IBinding, delay?: number, signals?: string | string[]) { const opts: IRateLimitOptions = { type: 'throttle', delay: delay ?? defaultDelay, now: this._now, signals: isString(signals) ? [signals] : (signals ?? emptyArray), }; const handler = binding.limit?.(opts); if (handler == null) { /* istanbul ignore next */ if (__DEV__) { // eslint-disable-next-line no-console console.warn(`[DEV:aurelia] Binding ${binding.constructor.name} does not support throttle rate limiting`); } } else { bindingHandlerMap.set(binding, handler); } } public unbind(scope: Scope, binding: IBinding) { bindingHandlerMap.get(binding)?.dispose(); bindingHandlerMap.delete(binding); } }