{
  "version": 3,
  "sources": ["../../../../src/specialized-waitables/use-derived-waitable/use-derived-waitable.ts"],
  "sourcesContent": ["import { useMemo } from 'react';\nimport type { EmptyObject, ReadonlyBinding, SingleOrArray } from 'react-bindings';\nimport { isBinding, useCallbackRef, useStableValue } from 'react-bindings';\n\nimport { concatArrays, normalizeAsArray, normalizeAsOptionalArray } from '../../internal-utils/array-like.mjs';\nimport { extractOptionalWaitableDependencyValues } from '../../internal-utils/extract-waitable-dependency-values.mjs';\nimport { getTypedKeys } from '../../internal-utils/get-typed-keys.mjs';\nimport { makeValueThenDo } from '../../internal-utils/make-value-then-do.mjs';\nimport type { UseWaitableArgs } from '../../use-waitable/types/args';\nimport type { WaitablePrimaryFunction } from '../../use-waitable/types/primary-function';\nimport { useWaitable } from '../../use-waitable/use-waitable.mjs';\nimport type {\n  InferOptionalWaitableAndBindingValueTypes,\n  InferRequiredWaitableAndBindingValueTypes\n} from '../../waitable/types/infer-waitable-and-binding-value-types';\nimport type { Waitable } from '../../waitable/types/waitable';\nimport type { WaitableDependencies } from '../../waitable/types/waitable-dependencies';\nimport { isWaitable } from '../../waitable/utils.mjs';\nimport type { UseDerivedWaitableNamedTransformers, UseDerivedWaitableRequiredValuesTransformer } from './types/transformers';\n\nconst emptyDependencies = Object.freeze({} as EmptyObject);\n\nconst emptyHardResetBindings = Object.freeze([]) as unknown as Array<ReadonlyBinding | undefined>;\nconst emptyLockedWhile = Object.freeze([]) as unknown as Array<ReadonlyBinding | undefined>;\n\n/**\n * A derived waitable is a waitable derived from zero or more other waitables and bindings.  The value of a derived waitable is computed\n * using the specified transformers.\n *\n * The general usage pattern is something like:\n *\n * ```\n * const myWaitable = useDerivedWaitable(\n *   { someWaitable, someBinding },\n *   [({ someWaitable, someBinding }) => someWaitable + someBinding, { ifLoading: () => 'loading' }],\n *   { id: 'myWaitable' }\n * );\n * ```\n *\n * An unnamed transformer is the same as `{ ifLoaded: \u2026 }`\n *\n * Named transformer meanings:\n * - `'ifLoaded'` - None of the waitables have undefined values\n * - `'ifError'` - At least one waitable has a defined error\n * - `'ifLoading'` - At least one waitable has an undefined value but no waitables have defined errors\n * - `'ifErrorOrLoading'` - At least one waitable has an undefined value or at least one waitable has a defined error\n * - `'always'` - Always applicable\n *\n * @param dependencies - The waitables and bindings depended upon.  If waitables or bindings are named, their values will be extracted and\n * passed to the first applicable transformer function.\n * @param options - `useWaitable` options.\n * @param transformers - An ordered list of transformers.  The first applicable one is applied.  If multiple named rules are specified in a\n * single object, they are evaluated in the order: `ifLoaded`, `ifError`, `ifLoading`, `ifErrorOrLoading`, `always`\n */\nexport const useDerivedWaitable = <\n  SuccessT,\n  FailureT,\n  DependenciesT extends WaitableDependencies,\n  ExtraFieldsT extends object = EmptyObject\n>(\n  dependencies: DependenciesT | undefined,\n  transformers: SingleOrArray<\n    | UseDerivedWaitableRequiredValuesTransformer<SuccessT, FailureT, DependenciesT>\n    | UseDerivedWaitableNamedTransformers<SuccessT, FailureT, DependenciesT>\n  >,\n  args: UseWaitableArgs<SuccessT, FailureT, ExtraFieldsT>\n) => {\n  const normalizedTransformers = normalizeAsArray(transformers);\n\n  const isNonNamedDependencies = Array.isArray(dependencies) || isWaitable(dependencies) || isBinding(dependencies);\n  const nonNamedDependencies = isNonNamedDependencies ? dependencies : undefined;\n  const namedDependencies = isNonNamedDependencies ? undefined : dependencies;\n  const namedDependencyKeys = namedDependencies !== undefined ? getTypedKeys(namedDependencies) : undefined;\n  const stableAllDependencies = useStableValue(\n    isNonNamedDependencies ? normalizeAsArray(nonNamedDependencies) : Object.values(namedDependencies ?? emptyDependencies)\n  );\n  const stableAllWaitables = useMemo(\n    () => stableAllDependencies.filter((dep) => isWaitable(dep)) as Waitable<any>[],\n    [stableAllDependencies]\n  );\n  const stableAllBindings = useMemo(\n    () => stableAllDependencies.filter((dep) => isBinding(dep)) as ReadonlyBinding<any>[],\n    [stableAllDependencies]\n  );\n\n  const stableWaitableIsCompletes = stableAllWaitables.map((waitable) => waitable?.isComplete);\n  const stableWaitableIsLockedWithoutValueBindings = stableAllWaitables.map((waitable) => waitable?.isLockedWithoutValue);\n\n  /**\n   * Gets the first transformer for the loaded state, where all waitables have defined values.  The first applicable transformer from the\n   * `normalizedTransformers` list is returned.\n   *\n   * Transformers are applicable if:\n   *\n   * - They are unnamed (the default transformed is the same as the `ifLoaded` transformer)\n   * - They are named as either `ifLoaded` or `always`\n   *\n   * In a single object of named transformers, `ifLoaded` takes priority over `always`.\n   */\n  const getLoadedTransformer = useCallbackRef(() => {\n    for (const transformer of normalizedTransformers) {\n      if (typeof transformer === 'function') {\n        return transformer;\n      } else if (transformer.ifLoaded !== undefined) {\n        return transformer.ifLoaded;\n      } else if (transformer.always !== undefined) {\n        return transformer.always;\n      }\n    }\n\n    return undefined;\n  });\n\n  /**\n   * Gets the first transformer for the error state.  The first applicable transformer from the `normalizedTransformers` list is returned.\n   *\n   * Transformers are applicable if they are named as either `ifError`, `ifErrorOrLoading`, or `always`, which is also the preferred order\n   * if multiple named transformers are included in a single object.\n   */\n  const getErrorTransformer = useCallbackRef(() => {\n    for (const transformer of normalizedTransformers) {\n      if (typeof transformer !== 'function') {\n        const t = transformer.ifError ?? transformer.ifErrorOrLoading ?? transformer.always;\n        if (t !== undefined) {\n          return t;\n        }\n      }\n    }\n\n    return undefined;\n  });\n\n  /**\n   * Gets the first transformer for the loading state.  The first applicable transformer from the `normalizedTransformers` list is returned.\n   *\n   * Transformers are applicable if they are named as either `ifLoading`, `ifErrorOrLoading`, or `always`, which is also the preferred order\n   * if multiple named transformers are included in a single object.\n   */\n  const getLoadingTransformer = useCallbackRef(() => {\n    for (const transformer of normalizedTransformers) {\n      if (typeof transformer !== 'function') {\n        const t = transformer.ifLoading ?? transformer.ifErrorOrLoading ?? transformer.always;\n        if (t !== undefined) {\n          return t;\n        }\n      }\n    }\n\n    return undefined;\n  });\n\n  /**\n   * Evaluates the dependencies, extract named dependency values, and runs the most appropriate transformer.\n   *\n   * - If any waitables have defined errors, the overall state is `'error'`\n   * - If any waitables have undefined values, the overall state is `'loading'`\n   * - Otherwise, the overall state is `'loaded'`\n   */\n  const evaluate: WaitablePrimaryFunction<SuccessT, FailureT> = useCallbackRef(({ setSuccess, setFailure, wasReset }) => {\n    const { allWaitablesAreLoaded, anyWaitablesHadErrors, lastError, values } = extractOptionalWaitableDependencyValues<\n      DependenciesT,\n      FailureT\n    >({\n      dependencies,\n      namedDependencyKeys\n    });\n\n    if (allWaitablesAreLoaded) {\n      // Loaded\n      return makeValueThenDo<SuccessT | undefined>(\n        () =>\n          getLoadedTransformer()?.(\n            values as InferRequiredWaitableAndBindingValueTypes<DependenciesT>,\n            dependencies ?? (emptyDependencies as DependenciesT),\n            setFailure,\n            wasReset\n          ),\n        setSuccess\n      );\n    } else if (anyWaitablesHadErrors) {\n      // Error\n      return makeValueThenDo(\n        () =>\n          getErrorTransformer()?.(\n            values as InferOptionalWaitableAndBindingValueTypes<DependenciesT>,\n            dependencies ?? (emptyDependencies as DependenciesT),\n            setFailure,\n            wasReset\n          ),\n        (value) => {\n          if (value !== undefined) {\n            setSuccess?.(value);\n          } else {\n            setFailure?.(lastError!);\n          }\n        }\n      );\n    } else {\n      // Loading\n      return makeValueThenDo<SuccessT | undefined>(\n        () =>\n          getLoadingTransformer()?.(\n            values as InferOptionalWaitableAndBindingValueTypes<DependenciesT>,\n            dependencies ?? (emptyDependencies as DependenciesT),\n            setFailure,\n            wasReset\n          ),\n        setSuccess\n      );\n    }\n  });\n\n  return useWaitable<SuccessT, FailureT, ExtraFieldsT>(evaluate, {\n    defaultValue: 'use-primary-function-if-unlocked',\n    ...args,\n    hardResetBindings: concatArrays(\n      normalizeAsOptionalArray(args.hardResetBindings) ?? emptyHardResetBindings,\n      stableWaitableIsCompletes,\n      stableAllBindings\n    ),\n    lockedWhile: concatArrays(normalizeAsOptionalArray(args.lockedWhile) ?? emptyLockedWhile, stableWaitableIsLockedWithoutValueBindings)\n  });\n};\n"],
  "mappings": "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",
  "names": []
}
