{"version":3,"file":"until.js","sources":["../../../src/directives/until.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {Part, noChange} from '../lit-html.js';\nimport {isPrimitive} from '../directive-helpers.js';\nimport {\n  directive,\n  AsyncDirective,\n  DirectiveResult,\n} from '../async-directive.js';\nimport {Pauser, PseudoWeakRef} from './private-async-helpers.js';\n\nconst isPromise = (x: unknown): x is Promise<unknown> => {\n  return !isPrimitive(x) && typeof (x as {then?: unknown}).then === 'function';\n};\n// Effectively infinity, but a SMI.\nconst _infinity = 0x3fffffff;\n\ntype UnwrapPromise<T> = T extends Promise<infer U> ? U : T;\n\nexport class UntilDirective<T> extends AsyncDirective {\n  private __lastRenderedIndex: number = _infinity;\n  private __values: unknown[] = [];\n  private __weakThis = new PseudoWeakRef(this);\n  private __pauser = new Pauser();\n\n  render(...args: Array<T>): UnwrapPromise<T> {\n    return (args.find((x) => !isPromise(x)) ?? noChange) as UnwrapPromise<T>;\n  }\n\n  override update(_part: Part, args: Array<unknown>) {\n    const previousValues = this.__values;\n    let previousLength = previousValues.length;\n    this.__values = args;\n\n    const weakThis = this.__weakThis;\n    const pauser = this.__pauser;\n\n    // If our initial render occurs while disconnected, ensure that the pauser\n    // and weakThis are in the disconnected state\n    if (!this.isConnected) {\n      this.disconnected();\n    }\n\n    for (let i = 0; i < args.length; i++) {\n      // If we've rendered a higher-priority value already, stop.\n      if (i > this.__lastRenderedIndex) {\n        break;\n      }\n\n      const value = args[i];\n\n      // Render non-Promise values immediately\n      if (!isPromise(value)) {\n        this.__lastRenderedIndex = i;\n        // Since a lower-priority value will never overwrite a higher-priority\n        // synchronous value, we can stop processing now.\n        return value;\n      }\n\n      // If this is a Promise we've already handled, skip it.\n      if (i < previousLength && value === previousValues[i]) {\n        continue;\n      }\n\n      // We have a Promise that we haven't seen before, so priorities may have\n      // changed. Forget what we rendered before.\n      this.__lastRenderedIndex = _infinity;\n      previousLength = 0;\n\n      // Note, the callback avoids closing over `this` so that the directive\n      // can be gc'ed before the promise resolves; instead `this` is retrieved\n      // from `weakThis`, which can break the hard reference in the closure when\n      // the directive disconnects\n      Promise.resolve(value).then(async (result: unknown) => {\n        // If we're disconnected, wait until we're (maybe) reconnected\n        // The while loop here handles the case that the connection state\n        // thrashes, causing the pauser to resume and then get re-paused\n        while (pauser.get()) {\n          await pauser.get();\n        }\n        // If the callback gets here and there is no `this`, it means that the\n        // directive has been disconnected and garbage collected and we don't\n        // need to do anything else\n        const _this = weakThis.deref();\n        if (_this !== undefined) {\n          const index = _this.__values.indexOf(value);\n          // If state.values doesn't contain the value, we've re-rendered without\n          // the value, so don't render it. Then, only render if the value is\n          // higher-priority than what's already been rendered.\n          if (index > -1 && index < _this.__lastRenderedIndex) {\n            _this.__lastRenderedIndex = index;\n            _this.setValue(result);\n          }\n        }\n      });\n    }\n\n    return noChange;\n  }\n\n  override disconnected() {\n    this.__weakThis.disconnect();\n    this.__pauser.pause();\n  }\n\n  override reconnected() {\n    this.__weakThis.reconnect(this);\n    this.__pauser.resume();\n  }\n}\n\ninterface Until {\n  <T extends Array<unknown>>(\n    ...args: T\n  ): DirectiveResult<typeof UntilDirective<T[number]>>;\n}\n\n/**\n * Renders one of a series of values, including Promises, to a Part.\n *\n * Values are rendered in priority order, with the first argument having the\n * highest priority and the last argument having the lowest priority. If a\n * value is a Promise, low-priority values will be rendered until it resolves.\n *\n * The priority of values can be used to create placeholder content for async\n * data. For example, a Promise with pending content can be the first,\n * highest-priority, argument, and a non_promise loading indicator template can\n * be used as the second, lower-priority, argument. The loading indicator will\n * render immediately, and the primary content will render when the Promise\n * resolves.\n *\n * Example:\n *\n * ```js\n * const content = fetch('./content.txt').then(r => r.text());\n * html`${until(content, html`<span>Loading...</span>`)}`\n * ```\n */\nexport const until: Until = directive(UntilDirective);\n\n/**\n * The type of the class that powers this directive. Necessary for naming the\n * directive's return type.\n */\n// export type {UntilDirective};\n"],"names":[],"mappings":"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"}