{"version":3,"file":"derived.cjs","sources":["../../src/derived.ts"],"sourcesContent":["import { Store } from './store'\nimport { __derivedToStore, __storeToDerived } from './scheduler'\nimport type { Listener } from './types'\n\nexport type UnwrapDerivedOrStore<T> =\n  T extends Derived<infer InnerD>\n    ? InnerD\n    : T extends Store<infer InnerS>\n      ? InnerS\n      : never\n\ntype UnwrapReadonlyDerivedOrStoreArray<\n  TArr extends ReadonlyArray<Derived<any> | Store<any>>,\n> = TArr extends readonly []\n  ? []\n  : TArr extends readonly [infer Head, ...infer Tail]\n    ? Head extends Derived<any> | Store<any>\n      ? Tail extends ReadonlyArray<Derived<any> | Store<any>>\n        ? [\n            UnwrapDerivedOrStore<Head>,\n            ...UnwrapReadonlyDerivedOrStoreArray<Tail>,\n          ]\n        : [UnwrapDerivedOrStore<Head>]\n      : []\n    : TArr extends ReadonlyArray<Derived<any> | Store<any>>\n      ? Array<UnwrapDerivedOrStore<TArr[number]>>\n      : []\n\n// Can't have currVal, as it's being evaluated from the current derived fn\nexport interface DerivedFnProps<\n  TArr extends ReadonlyArray<Derived<any> | Store<any>> = ReadonlyArray<any>,\n  TUnwrappedArr extends\n    UnwrapReadonlyDerivedOrStoreArray<TArr> = UnwrapReadonlyDerivedOrStoreArray<TArr>,\n> {\n  // `undefined` if it's the first run\n  /**\n   * `undefined` if it's the first run\n   * @privateRemarks this also cannot be typed as TState, as it breaks the inferencing of the function's return type when an argument is used - even with `NoInfer` usage\n   */\n  prevVal: unknown | undefined\n  prevDepVals: TUnwrappedArr | undefined\n  currDepVals: TUnwrappedArr\n}\n\nexport interface DerivedOptions<\n  TState,\n  TArr extends ReadonlyArray<Derived<any> | Store<any>> = ReadonlyArray<any>,\n> {\n  onSubscribe?: (\n    listener: Listener<TState>,\n    derived: Derived<TState>,\n  ) => () => void\n  onUpdate?: () => void\n  deps: TArr\n  /**\n   * Values of the `deps` from before and after the current invocation of `fn`\n   */\n  fn: (props: DerivedFnProps<TArr>) => TState\n}\n\nexport class Derived<\n  TState,\n  const TArr extends ReadonlyArray<\n    Derived<any> | Store<any>\n  > = ReadonlyArray<any>,\n> {\n  listeners = new Set<Listener<TState>>()\n  state: TState\n  prevState: TState | undefined\n  options: DerivedOptions<TState, TArr>\n\n  /**\n   * Functions representing the subscriptions. Call a function to cleanup\n   * @private\n   */\n  _subscriptions: Array<() => void> = []\n\n  lastSeenDepValues: Array<unknown> = []\n  getDepVals = () => {\n    const l = this.options.deps.length\n    const prevDepVals = new Array<unknown>(l)\n    const currDepVals = new Array<unknown>(l)\n    for (let i = 0; i < l; i++) {\n      const dep = this.options.deps[i]!\n      prevDepVals[i] = dep.prevState\n      currDepVals[i] = dep.state\n    }\n    this.lastSeenDepValues = currDepVals\n    return {\n      prevDepVals,\n      currDepVals,\n      prevVal: this.prevState ?? undefined,\n    }\n  }\n\n  constructor(options: DerivedOptions<TState, TArr>) {\n    this.options = options\n    this.state = options.fn({\n      prevDepVals: undefined,\n      prevVal: undefined,\n      currDepVals: this.getDepVals().currDepVals as never,\n    })\n  }\n\n  registerOnGraph(\n    deps: ReadonlyArray<Derived<any> | Store<any>> = this.options.deps,\n  ) {\n    for (const dep of deps) {\n      if (dep instanceof Derived) {\n        // First register the intermediate derived value if it's not already registered\n        dep.registerOnGraph()\n        // Then register this derived with the dep's underlying stores\n        this.registerOnGraph(dep.options.deps)\n      } else if (dep instanceof Store) {\n        // Register the derived as related derived to the store\n        let relatedLinkedDerivedVals = __storeToDerived.get(dep)\n        if (!relatedLinkedDerivedVals) {\n          relatedLinkedDerivedVals = new Set()\n          __storeToDerived.set(dep, relatedLinkedDerivedVals)\n        }\n        relatedLinkedDerivedVals.add(this as never)\n\n        // Register the store as a related store to this derived\n        let relatedStores = __derivedToStore.get(this as never)\n        if (!relatedStores) {\n          relatedStores = new Set()\n          __derivedToStore.set(this as never, relatedStores)\n        }\n        relatedStores.add(dep)\n      }\n    }\n  }\n\n  unregisterFromGraph(\n    deps: ReadonlyArray<Derived<any> | Store<any>> = this.options.deps,\n  ) {\n    for (const dep of deps) {\n      if (dep instanceof Derived) {\n        this.unregisterFromGraph(dep.options.deps)\n      } else if (dep instanceof Store) {\n        const relatedLinkedDerivedVals = __storeToDerived.get(dep)\n        if (relatedLinkedDerivedVals) {\n          relatedLinkedDerivedVals.delete(this as never)\n        }\n\n        const relatedStores = __derivedToStore.get(this as never)\n        if (relatedStores) {\n          relatedStores.delete(dep)\n        }\n      }\n    }\n  }\n\n  recompute = () => {\n    this.prevState = this.state\n    const depVals = this.getDepVals()\n    this.state = this.options.fn(depVals as never)\n\n    this.options.onUpdate?.()\n  }\n\n  checkIfRecalculationNeededDeeply = () => {\n    for (const dep of this.options.deps) {\n      if (dep instanceof Derived) {\n        dep.checkIfRecalculationNeededDeeply()\n      }\n    }\n    let shouldRecompute = false\n    const lastSeenDepValues = this.lastSeenDepValues\n    const { currDepVals } = this.getDepVals()\n    for (let i = 0; i < currDepVals.length; i++) {\n      if (currDepVals[i] !== lastSeenDepValues[i]) {\n        shouldRecompute = true\n        break\n      }\n    }\n\n    if (shouldRecompute) {\n      this.recompute()\n    }\n  }\n\n  mount = () => {\n    this.registerOnGraph()\n    this.checkIfRecalculationNeededDeeply()\n\n    return () => {\n      this.unregisterFromGraph()\n      for (const cleanup of this._subscriptions) {\n        cleanup()\n      }\n    }\n  }\n\n  subscribe = (listener: Listener<TState>) => {\n    this.listeners.add(listener)\n    const unsub = this.options.onSubscribe?.(listener, this)\n    return () => {\n      this.listeners.delete(listener)\n      unsub?.()\n    }\n  }\n}\n"],"names":["Store","__storeToDerived","__derivedToStore"],"mappings":";;;;AA4DO,MAAM,QAKX;AAAA,EA8BA,YAAY,SAAuC;AA7BnD,SAAA,gCAAgB,IAAA;AAShB,SAAA,iBAAoC,CAAA;AAEpC,SAAA,oBAAoC,CAAA;AACpC,SAAA,aAAa,MAAM;AACjB,YAAM,IAAI,KAAK,QAAQ,KAAK;AAC5B,YAAM,cAAc,IAAI,MAAe,CAAC;AACxC,YAAM,cAAc,IAAI,MAAe,CAAC;AACxC,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,cAAM,MAAM,KAAK,QAAQ,KAAK,CAAC;AAC/B,oBAAY,CAAC,IAAI,IAAI;AACrB,oBAAY,CAAC,IAAI,IAAI;AAAA,MACvB;AACA,WAAK,oBAAoB;AACzB,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,SAAS,KAAK,aAAa;AAAA,MAAA;AAAA,IAE/B;AA4DA,SAAA,YAAY,MAAM;;AAChB,WAAK,YAAY,KAAK;AACtB,YAAM,UAAU,KAAK,WAAA;AACrB,WAAK,QAAQ,KAAK,QAAQ,GAAG,OAAgB;AAE7C,uBAAK,SAAQ,aAAb;AAAA,IACF;AAEA,SAAA,mCAAmC,MAAM;AACvC,iBAAW,OAAO,KAAK,QAAQ,MAAM;AACnC,YAAI,eAAe,SAAS;AAC1B,cAAI,iCAAA;AAAA,QACN;AAAA,MACF;AACA,UAAI,kBAAkB;AACtB,YAAM,oBAAoB,KAAK;AAC/B,YAAM,EAAE,YAAA,IAAgB,KAAK,WAAA;AAC7B,eAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,YAAI,YAAY,CAAC,MAAM,kBAAkB,CAAC,GAAG;AAC3C,4BAAkB;AAClB;AAAA,QACF;AAAA,MACF;AAEA,UAAI,iBAAiB;AACnB,aAAK,UAAA;AAAA,MACP;AAAA,IACF;AAEA,SAAA,QAAQ,MAAM;AACZ,WAAK,gBAAA;AACL,WAAK,iCAAA;AAEL,aAAO,MAAM;AACX,aAAK,oBAAA;AACL,mBAAW,WAAW,KAAK,gBAAgB;AACzC,kBAAA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,SAAA,YAAY,CAAC,aAA+B;;AAC1C,WAAK,UAAU,IAAI,QAAQ;AAC3B,YAAM,SAAQ,gBAAK,SAAQ,gBAAb,4BAA2B,UAAU;AACnD,aAAO,MAAM;AACX,aAAK,UAAU,OAAO,QAAQ;AAC9B;AAAA,MACF;AAAA,IACF;AAzGE,SAAK,UAAU;AACf,SAAK,QAAQ,QAAQ,GAAG;AAAA,MACtB,aAAa;AAAA,MACb,SAAS;AAAA,MACT,aAAa,KAAK,aAAa;AAAA,IAAA,CAChC;AAAA,EACH;AAAA,EAEA,gBACE,OAAiD,KAAK,QAAQ,MAC9D;AACA,eAAW,OAAO,MAAM;AACtB,UAAI,eAAe,SAAS;AAE1B,YAAI,gBAAA;AAEJ,aAAK,gBAAgB,IAAI,QAAQ,IAAI;AAAA,MACvC,WAAW,eAAeA,aAAO;AAE/B,YAAI,2BAA2BC,UAAAA,iBAAiB,IAAI,GAAG;AACvD,YAAI,CAAC,0BAA0B;AAC7B,yDAA+B,IAAA;AAC/BA,qCAAiB,IAAI,KAAK,wBAAwB;AAAA,QACpD;AACA,iCAAyB,IAAI,IAAa;AAG1C,YAAI,gBAAgBC,UAAAA,iBAAiB,IAAI,IAAa;AACtD,YAAI,CAAC,eAAe;AAClB,8CAAoB,IAAA;AACpBA,qCAAiB,IAAI,MAAe,aAAa;AAAA,QACnD;AACA,sBAAc,IAAI,GAAG;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,oBACE,OAAiD,KAAK,QAAQ,MAC9D;AACA,eAAW,OAAO,MAAM;AACtB,UAAI,eAAe,SAAS;AAC1B,aAAK,oBAAoB,IAAI,QAAQ,IAAI;AAAA,MAC3C,WAAW,eAAeF,aAAO;AAC/B,cAAM,2BAA2BC,UAAAA,iBAAiB,IAAI,GAAG;AACzD,YAAI,0BAA0B;AAC5B,mCAAyB,OAAO,IAAa;AAAA,QAC/C;AAEA,cAAM,gBAAgBC,UAAAA,iBAAiB,IAAI,IAAa;AACxD,YAAI,eAAe;AACjB,wBAAc,OAAO,GAAG;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAmDF;;"}