{"version":3,"file":"ListLoaderState.mjs","names":[],"sources":["../../../../../../../../components-base/src/list/loading/ListLoaderState.ts"],"sourcesContent":["import type { BatchLoadingState, ListData } from \"./types\";\nimport { action, computed, makeObservable, observable } from \"mobx\";\nimport { uniqueBy } from \"remeda\";\n\nexport interface ListLoaderStateOptions<T> {\n  /**\n   * Identifies an item, so the same one loaded in two batches appears once.\n   * Without it the batches are concatenated as they arrive.\n   */\n  getItemId?: (item: T) => string;\n}\n\n/**\n * What a list has loaded so far, and how far each batch has got.\n *\n * MobX, and nothing else — no hook, no framework. A binding reads it through\n * its own reactivity: React with `useSelector`, Vue with `watchMobxValue`. That\n * split is the point: the batching, the deduplication and the \"still loading\"\n * rules are one implementation, and only the subscription is written twice.\n *\n * What is _not_ here is the loading itself. Fetching a batch is\n * `usePromise`/Suspense in React and something else in Vue, so it stays with\n * the binding, and only its outcome is reported here.\n */\nexport class ListLoaderState<T> {\n  public dataBatches: ListData<T>[] = [];\n  public batchLoadingStates: BatchLoadingState[] = [\"void\"];\n  public metadata?: unknown = undefined;\n  public isInitiallyLoading = true;\n\n  /**\n   * The last non-empty result, kept outside MobX on purpose: it exists so a\n   * reset can keep rendering the previous data instead of flashing empty, and\n   * observing it would make that very reset re-render.\n   */\n  public prevDataBatches: ListData<T>[] = [];\n\n  private readonly getItemId?: (item: T) => string;\n\n  public constructor(options: ListLoaderStateOptions<T> = {}) {\n    this.getItemId = options.getItemId;\n\n    makeObservable(this, {\n      prevDataBatches: false,\n      dataBatches: observable.shallow,\n      batchLoadingStates: observable.shallow,\n      metadata: observable,\n      mergedData: computed,\n      isLoading: computed,\n      isLoadingMore: computed,\n      isInitiallyLoading: observable,\n      setIsInitiallyLoading: action.bound,\n      reset: action.bound,\n      setDataBatch: action.bound,\n      setBatchLoadingState: action.bound,\n      setMetadata: action.bound,\n    });\n  }\n\n  public reset(): void {\n    this.batchLoadingStates = [];\n    this.dataBatches = [];\n  }\n\n  public setDataBatch(index: number, data: ListData<T>): void {\n    if (this.dataBatches.length === 0) {\n      this.prevDataBatches = [];\n    }\n\n    if (this.dataBatches[index] !== data) {\n      this.dataBatches[index] = data;\n      this.prevDataBatches[index] = data;\n    }\n  }\n\n  public setBatchLoadingState(index: number, state: BatchLoadingState): void {\n    if (state === \"error\" || state === \"loaded\") {\n      this.setIsInitiallyLoading(false);\n    }\n    if (this.batchLoadingStates[index] !== state) {\n      this.batchLoadingStates[index] = state;\n    }\n  }\n\n  public setMetadata(metadata?: unknown): void {\n    this.metadata = metadata;\n  }\n\n  public setIsInitiallyLoading(isInitiallyLoading: boolean): void {\n    this.isInitiallyLoading = isInitiallyLoading;\n  }\n\n  public get mergedData(): T[] {\n    const dataBatches =\n      this.dataBatches.length === 0 ? this.prevDataBatches : this.dataBatches;\n\n    const merged = dataBatches.flatMap((d) => d);\n    return this.getItemId ? uniqueBy(merged, this.getItemId) : merged;\n  }\n\n  public get isLoading(): boolean {\n    return this.batchLoadingStates.some((s) => s === \"loading\" || s === \"void\");\n  }\n\n  public get isLoadingMore(): boolean {\n    return this.isLoading && this.dataBatches.length > 0;\n  }\n\n  public isBatchLoaded(batchIndex: number): boolean {\n    return batchIndex in this.dataBatches;\n  }\n}\n\nexport default ListLoaderState;\n"],"mappings":";;;;;;;;;;;;;;;;;AAwBA,IAAa,kBAAb,MAAgC;CAC9B,cAAoC,CAAC;CACrC,qBAAiD,CAAC,MAAM;CACxD,WAA4B,KAAA;CAC5B,qBAA4B;;;;;;CAO5B,kBAAwC,CAAC;CAEzC;CAEA,YAAmB,UAAqC,CAAC,GAAG;EAC1D,KAAK,YAAY,QAAQ;EAEzB,eAAe,MAAM;GACnB,iBAAiB;GACjB,aAAa,WAAW;GACxB,oBAAoB,WAAW;GAC/B,UAAU;GACV,YAAY;GACZ,WAAW;GACX,eAAe;GACf,oBAAoB;GACpB,uBAAuB,OAAO;GAC9B,OAAO,OAAO;GACd,cAAc,OAAO;GACrB,sBAAsB,OAAO;GAC7B,aAAa,OAAO;EACtB,CAAC;CACH;CAEA,QAAqB;EACnB,KAAK,qBAAqB,CAAC;EAC3B,KAAK,cAAc,CAAC;CACtB;CAEA,aAAoB,OAAe,MAAyB;EAC1D,IAAI,KAAK,YAAY,WAAW,GAC9B,KAAK,kBAAkB,CAAC;EAG1B,IAAI,KAAK,YAAY,WAAW,MAAM;GACpC,KAAK,YAAY,SAAS;GAC1B,KAAK,gBAAgB,SAAS;EAChC;CACF;CAEA,qBAA4B,OAAe,OAAgC;EACzE,IAAI,UAAU,WAAW,UAAU,UACjC,KAAK,sBAAsB,KAAK;EAElC,IAAI,KAAK,mBAAmB,WAAW,OACrC,KAAK,mBAAmB,SAAS;CAErC;CAEA,YAAmB,UAA0B;EAC3C,KAAK,WAAW;CAClB;CAEA,sBAA6B,oBAAmC;EAC9D,KAAK,qBAAqB;CAC5B;CAEA,IAAW,aAAkB;EAI3B,MAAM,UAFJ,KAAK,YAAY,WAAW,IAAI,KAAK,kBAAkB,KAAK,YAAA,CAEnC,SAAS,MAAM,CAAC;EAC3C,OAAO,KAAK,YAAY,SAAS,QAAQ,KAAK,SAAS,IAAI;CAC7D;CAEA,IAAW,YAAqB;EAC9B,OAAO,KAAK,mBAAmB,MAAM,MAAM,MAAM,aAAa,MAAM,MAAM;CAC5E;CAEA,IAAW,gBAAyB;EAClC,OAAO,KAAK,aAAa,KAAK,YAAY,SAAS;CACrD;CAEA,cAAqB,YAA6B;EAChD,OAAO,cAAc,KAAK;CAC5B;AACF"}