{"version":3,"file":"repeat.js","sourceRoot":"","sources":["../../src/directives/repeat.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {ChildPart, noChange} from '../lit-html.js';\nimport {directive, Directive, PartInfo, PartType} from '../directive.js';\nimport {\n  insertPart,\n  getCommittedValue,\n  removePart,\n  setCommittedValue,\n  setChildPartValue,\n} from '../directive-helpers.js';\n\nexport type KeyFn<T> = (item: T, index: number) => unknown;\nexport type ItemTemplate<T> = (item: T, index: number) => unknown;\n\n// Helper for generating a map of array item to its index over a subset\n// of an array (used to lazily generate `newKeyToIndexMap` and\n// `oldKeyToIndexMap`)\nconst generateMap = (list: unknown[], start: number, end: number) => {\n  const map = new Map<unknown, number>();\n  for (let i = start; i <= end; i++) {\n    map.set(list[i], i);\n  }\n  return map;\n};\n\nclass RepeatDirective extends Directive {\n  private _itemKeys?: unknown[];\n\n  constructor(partInfo: PartInfo) {\n    super(partInfo);\n    if (partInfo.type !== PartType.CHILD) {\n      throw new Error('repeat() can only be used in text expressions');\n    }\n  }\n\n  private _getValuesAndKeys<T>(\n    items: Iterable<T>,\n    keyFnOrTemplate: KeyFn<T> | ItemTemplate<T>,\n    template?: ItemTemplate<T>\n  ) {\n    let keyFn: KeyFn<T> | undefined;\n    if (template === undefined) {\n      template = keyFnOrTemplate;\n    } else if (keyFnOrTemplate !== undefined) {\n      keyFn = keyFnOrTemplate as KeyFn<T>;\n    }\n    const keys = [];\n    const values = [];\n    let index = 0;\n    for (const item of items) {\n      keys[index] = keyFn ? keyFn(item, index) : index;\n      values[index] = template!(item, index);\n      index++;\n    }\n    return {\n      values,\n      keys,\n    };\n  }\n\n  render<T>(items: Iterable<T>, template: ItemTemplate<T>): Array<unknown>;\n  render<T>(\n    items: Iterable<T>,\n    keyFn: KeyFn<T> | ItemTemplate<T>,\n    template: ItemTemplate<T>\n  ): Array<unknown>;\n  render<T>(\n    items: Iterable<T>,\n    keyFnOrTemplate: KeyFn<T> | ItemTemplate<T>,\n    template?: ItemTemplate<T>\n  ) {\n    return this._getValuesAndKeys(items, keyFnOrTemplate, template).values;\n  }\n\n  override update<T>(\n    containerPart: ChildPart,\n    [items, keyFnOrTemplate, template]: [\n      Iterable<T>,\n      KeyFn<T> | ItemTemplate<T>,\n      ItemTemplate<T>,\n    ]\n  ) {\n    // Old part & key lists are retrieved from the last update (which may\n    // be primed by hydration)\n    const oldParts = getCommittedValue(\n      containerPart\n    ) as Array<ChildPart | null>;\n    const {values: newValues, keys: newKeys} = this._getValuesAndKeys(\n      items,\n      keyFnOrTemplate,\n      template\n    );\n\n    // We check that oldParts, the committed value, is an Array as an\n    // indicator that the previous value came from a repeat() call. If\n    // oldParts is not an Array then this is the first render and we return\n    // an array for lit-html's array handling to render, and remember the\n    // keys.\n    if (!Array.isArray(oldParts)) {\n      this._itemKeys = newKeys;\n      return newValues;\n    }\n\n    // In SSR hydration it's possible for oldParts to be an array but for us\n    // to not have item keys because the update() hasn't run yet. We set the\n    // keys to an empty array. This will cause all oldKey/newKey comparisons\n    // to fail and execution to fall to the last nested brach below which\n    // reuses the oldPart.\n    const oldKeys = (this._itemKeys ??= []);\n\n    // New part list will be built up as we go (either reused from\n    // old parts or created for new keys in this update). This is\n    // saved in the above cache at the end of the update.\n    const newParts: ChildPart[] = [];\n\n    // Maps from key to index for current and previous update; these\n    // are generated lazily only when needed as a performance\n    // optimization, since they are only required for multiple\n    // non-contiguous changes in the list, which are less common.\n    let newKeyToIndexMap!: Map<unknown, number>;\n    let oldKeyToIndexMap!: Map<unknown, number>;\n\n    // Head and tail pointers to old parts and new values\n    let oldHead = 0;\n    let oldTail = oldParts.length - 1;\n    let newHead = 0;\n    let newTail = newValues.length - 1;\n\n    // Overview of O(n) reconciliation algorithm (general approach\n    // based on ideas found in ivi, vue, snabbdom, etc.):\n    //\n    // * We start with the list of old parts and new values (and\n    //   arrays of their respective keys), head/tail pointers into\n    //   each, and we build up the new list of parts by updating\n    //   (and when needed, moving) old parts or creating new ones.\n    //   The initial scenario might look like this (for brevity of\n    //   the diagrams, the numbers in the array reflect keys\n    //   associated with the old parts or new values, although keys\n    //   and parts/values are actually stored in parallel arrays\n    //   indexed using the same head/tail pointers):\n    //\n    //      oldHead v                 v oldTail\n    //   oldKeys:  [0, 1, 2, 3, 4, 5, 6]\n    //   newParts: [ ,  ,  ,  ,  ,  ,  ]\n    //   newKeys:  [0, 2, 1, 4, 3, 7, 6] <- reflects the user's new\n    //                                      item order\n    //      newHead ^                 ^ newTail\n    //\n    // * Iterate old & new lists from both sides, updating,\n    //   swapping, or removing parts at the head/tail locations\n    //   until neither head nor tail can move.\n    //\n    // * Example below: keys at head pointers match, so update old\n    //   part 0 in-place (no need to move it) and record part 0 in\n    //   the `newParts` list. The last thing we do is advance the\n    //   `oldHead` and `newHead` pointers (will be reflected in the\n    //   next diagram).\n    //\n    //      oldHead v                 v oldTail\n    //   oldKeys:  [0, 1, 2, 3, 4, 5, 6]\n    //   newParts: [0,  ,  ,  ,  ,  ,  ] <- heads matched: update 0\n    //   newKeys:  [0, 2, 1, 4, 3, 7, 6]    and advance both oldHead\n    //                                      & newHead\n    //      newHead ^                 ^ newTail\n    //\n    // * Example below: head pointers don't match, but tail\n    //   pointers do, so update part 6 in place (no need to move\n    //   it), and record part 6 in the `newParts` list. Last,\n    //   advance the `oldTail` and `oldHead` pointers.\n    //\n    //         oldHead v              v oldTail\n    //   oldKeys:  [0, 1, 2, 3, 4, 5, 6]\n    //   newParts: [0,  ,  ,  ,  ,  , 6] <- tails matched: update 6\n    //   newKeys:  [0, 2, 1, 4, 3, 7, 6]    and advance both oldTail\n    //                                      & newTail\n    //         newHead ^              ^ newTail\n    //\n    // * If neither head nor tail match; next check if one of the\n    //   old head/tail items was removed. We first need to generate\n    //   the reverse map of new keys to index (`newKeyToIndexMap`),\n    //   which is done once lazily as a performance optimization,\n    //   since we only hit this case if multiple non-contiguous\n    //   changes were made. Note that for contiguous removal\n    //   anywhere in the list, the head and tails would advance\n    //   from either end and pass each other before we get to this\n    //   case and removals would be handled in the final while loop\n    //   without needing to generate the map.\n    //\n    // * Example below: The key at `oldTail` was removed (no longer\n    //   in the `newKeyToIndexMap`), so remove that part from the\n    //   DOM and advance just the `oldTail` pointer.\n    //\n    //         oldHead v           v oldTail\n    //   oldKeys:  [0, 1, 2, 3, 4, 5, 6]\n    //   newParts: [0,  ,  ,  ,  ,  , 6] <- 5 not in new map: remove\n    //   newKeys:  [0, 2, 1, 4, 3, 7, 6]    5 and advance oldTail\n    //         newHead ^           ^ newTail\n    //\n    // * Once head and tail cannot move, any mismatches are due to\n    //   either new or moved items; if a new key is in the previous\n    //   \"old key to old index\" map, move the old part to the new\n    //   location, otherwise create and insert a new part. Note\n    //   that when moving an old part we null its position in the\n    //   oldParts array if it lies between the head and tail so we\n    //   know to skip it when the pointers get there.\n    //\n    // * Example below: neither head nor tail match, and neither\n    //   were removed; so find the `newHead` key in the\n    //   `oldKeyToIndexMap`, and move that old part's DOM into the\n    //   next head position (before `oldParts[oldHead]`). Last,\n    //   null the part in the `oldPart` array since it was\n    //   somewhere in the remaining oldParts still to be scanned\n    //   (between the head and tail pointers) so that we know to\n    //   skip that old part on future iterations.\n    //\n    //         oldHead v        v oldTail\n    //   oldKeys:  [0, 1, -, 3, 4, 5, 6]\n    //   newParts: [0, 2,  ,  ,  ,  , 6] <- stuck: update & move 2\n    //   newKeys:  [0, 2, 1, 4, 3, 7, 6]    into place and advance\n    //                                      newHead\n    //         newHead ^           ^ newTail\n    //\n    // * Note that for moves/insertions like the one above, a part\n    //   inserted at the head pointer is inserted before the\n    //   current `oldParts[oldHead]`, and a part inserted at the\n    //   tail pointer is inserted before `newParts[newTail+1]`. The\n    //   seeming asymmetry lies in the fact that new parts are\n    //   moved into place outside in, so to the right of the head\n    //   pointer are old parts, and to the right of the tail\n    //   pointer are new parts.\n    //\n    // * We always restart back from the top of the algorithm,\n    //   allowing matching and simple updates in place to\n    //   continue...\n    //\n    // * Example below: the head pointers once again match, so\n    //   simply update part 1 and record it in the `newParts`\n    //   array.  Last, advance both head pointers.\n    //\n    //         oldHead v        v oldTail\n    //   oldKeys:  [0, 1, -, 3, 4, 5, 6]\n    //   newParts: [0, 2, 1,  ,  ,  , 6] <- heads matched: update 1\n    //   newKeys:  [0, 2, 1, 4, 3, 7, 6]    and advance both oldHead\n    //                                      & newHead\n    //            newHead ^        ^ newTail\n    //\n    // * As mentioned above, items that were moved as a result of\n    //   being stuck (the final else clause in the code below) are\n    //   marked with null, so we always advance old pointers over\n    //   these so we're comparing the next actual old value on\n    //   either end.\n    //\n    // * Example below: `oldHead` is null (already placed in\n    //   newParts), so advance `oldHead`.\n    //\n    //            oldHead v     v oldTail\n    //   oldKeys:  [0, 1, -, 3, 4, 5, 6] <- old head already used:\n    //   newParts: [0, 2, 1,  ,  ,  , 6]    advance oldHead\n    //   newKeys:  [0, 2, 1, 4, 3, 7, 6]\n    //               newHead ^     ^ newTail\n    //\n    // * Note it's not critical to mark old parts as null when they\n    //   are moved from head to tail or tail to head, since they\n    //   will be outside the pointer range and never visited again.\n    //\n    // * Example below: Here the old tail key matches the new head\n    //   key, so the part at the `oldTail` position and move its\n    //   DOM to the new head position (before `oldParts[oldHead]`).\n    //   Last, advance `oldTail` and `newHead` pointers.\n    //\n    //               oldHead v  v oldTail\n    //   oldKeys:  [0, 1, -, 3, 4, 5, 6]\n    //   newParts: [0, 2, 1, 4,  ,  , 6] <- old tail matches new\n    //   newKeys:  [0, 2, 1, 4, 3, 7, 6]   head: update & move 4,\n    //                                     advance oldTail & newHead\n    //               newHead ^     ^ newTail\n    //\n    // * Example below: Old and new head keys match, so update the\n    //   old head part in place, and advance the `oldHead` and\n    //   `newHead` pointers.\n    //\n    //               oldHead v oldTail\n    //   oldKeys:  [0, 1, -, 3, 4, 5, 6]\n    //   newParts: [0, 2, 1, 4, 3,   ,6] <- heads match: update 3\n    //   newKeys:  [0, 2, 1, 4, 3, 7, 6]    and advance oldHead &\n    //                                      newHead\n    //                  newHead ^  ^ newTail\n    //\n    // * Once the new or old pointers move past each other then all\n    //   we have left is additions (if old list exhausted) or\n    //   removals (if new list exhausted). Those are handled in the\n    //   final while loops at the end.\n    //\n    // * Example below: `oldHead` exceeded `oldTail`, so we're done\n    //   with the main loop.  Create the remaining part and insert\n    //   it at the new head position, and the update is complete.\n    //\n    //                   (oldHead > oldTail)\n    //   oldKeys:  [0, 1, -, 3, 4, 5, 6]\n    //   newParts: [0, 2, 1, 4, 3, 7 ,6] <- create and insert 7\n    //   newKeys:  [0, 2, 1, 4, 3, 7, 6]\n    //                     newHead ^ newTail\n    //\n    // * Note that the order of the if/else clauses is not\n    //   important to the algorithm, as long as the null checks\n    //   come first (to ensure we're always working on valid old\n    //   parts) and that the final else clause comes last (since\n    //   that's where the expensive moves occur). The order of\n    //   remaining clauses is just a simple guess at which cases\n    //   will be most common.\n    //\n    // * Note, we could calculate the longest\n    //   increasing subsequence (LIS) of old items in new position,\n    //   and only move those not in the LIS set. However that costs\n    //   O(nlogn) time and adds a bit more code, and only helps\n    //   make rare types of mutations require fewer moves. The\n    //   above handles removes, adds, reversal, swaps, and single\n    //   moves of contiguous items in linear time, in the minimum\n    //   number of moves. As the number of multiple moves where LIS\n    //   might help approaches a random shuffle, the LIS\n    //   optimization becomes less helpful, so it seems not worth\n    //   the code at this point. Could reconsider if a compelling\n    //   case arises.\n\n    while (oldHead <= oldTail && newHead <= newTail) {\n      if (oldParts[oldHead] === null) {\n        // `null` means old part at head has already been used\n        // below; skip\n        oldHead++;\n      } else if (oldParts[oldTail] === null) {\n        // `null` means old part at tail has already been used\n        // below; skip\n        oldTail--;\n      } else if (oldKeys[oldHead] === newKeys[newHead]) {\n        // Old head matches new head; update in place\n        newParts[newHead] = setChildPartValue(\n          oldParts[oldHead]!,\n          newValues[newHead]\n        );\n        oldHead++;\n        newHead++;\n      } else if (oldKeys[oldTail] === newKeys[newTail]) {\n        // Old tail matches new tail; update in place\n        newParts[newTail] = setChildPartValue(\n          oldParts[oldTail]!,\n          newValues[newTail]\n        );\n        oldTail--;\n        newTail--;\n      } else if (oldKeys[oldHead] === newKeys[newTail]) {\n        // Old head matches new tail; update and move to new tail\n        newParts[newTail] = setChildPartValue(\n          oldParts[oldHead]!,\n          newValues[newTail]\n        );\n        insertPart(containerPart, newParts[newTail + 1], oldParts[oldHead]!);\n        oldHead++;\n        newTail--;\n      } else if (oldKeys[oldTail] === newKeys[newHead]) {\n        // Old tail matches new head; update and move to new head\n        newParts[newHead] = setChildPartValue(\n          oldParts[oldTail]!,\n          newValues[newHead]\n        );\n        insertPart(containerPart, oldParts[oldHead]!, oldParts[oldTail]!);\n        oldTail--;\n        newHead++;\n      } else {\n        if (newKeyToIndexMap === undefined) {\n          // Lazily generate key-to-index maps, used for removals &\n          // moves below\n          newKeyToIndexMap = generateMap(newKeys, newHead, newTail);\n          oldKeyToIndexMap = generateMap(oldKeys, oldHead, oldTail);\n        }\n        if (!newKeyToIndexMap.has(oldKeys[oldHead])) {\n          // Old head is no longer in new list; remove\n          removePart(oldParts[oldHead]!);\n          oldHead++;\n        } else if (!newKeyToIndexMap.has(oldKeys[oldTail])) {\n          // Old tail is no longer in new list; remove\n          removePart(oldParts[oldTail]!);\n          oldTail--;\n        } else {\n          // Any mismatches at this point are due to additions or\n          // moves; see if we have an old part we can reuse and move\n          // into place\n          const oldIndex = oldKeyToIndexMap.get(newKeys[newHead]);\n          const oldPart = oldIndex !== undefined ? oldParts[oldIndex] : null;\n          if (oldPart === null) {\n            // No old part for this value; create a new one and\n            // insert it\n            const newPart = insertPart(containerPart, oldParts[oldHead]!);\n            setChildPartValue(newPart, newValues[newHead]);\n            newParts[newHead] = newPart;\n          } else {\n            // Reuse old part\n            newParts[newHead] = setChildPartValue(oldPart, newValues[newHead]);\n            insertPart(containerPart, oldParts[oldHead]!, oldPart);\n            // This marks the old part as having been used, so that\n            // it will be skipped in the first two checks above\n            oldParts[oldIndex as number] = null;\n          }\n          newHead++;\n        }\n      }\n    }\n    // Add parts for any remaining new values\n    while (newHead <= newTail) {\n      // For all remaining additions, we insert before last new\n      // tail, since old pointers are no longer valid\n      const newPart = insertPart(containerPart, newParts[newTail + 1]);\n      setChildPartValue(newPart, newValues[newHead]);\n      newParts[newHead++] = newPart;\n    }\n    // Remove any remaining unused old parts\n    while (oldHead <= oldTail) {\n      const oldPart = oldParts[oldHead++];\n      if (oldPart !== null) {\n        removePart(oldPart);\n      }\n    }\n\n    // Save order of new parts for next round\n    this._itemKeys = newKeys;\n    // Directly set part value, bypassing it's dirty-checking\n    setCommittedValue(containerPart, newParts);\n    return noChange;\n  }\n}\n\nexport interface RepeatDirectiveFn {\n  <T>(\n    items: Iterable<T>,\n    keyFnOrTemplate: KeyFn<T> | ItemTemplate<T>,\n    template?: ItemTemplate<T>\n  ): unknown;\n  <T>(items: Iterable<T>, template: ItemTemplate<T>): unknown;\n  <T>(\n    items: Iterable<T>,\n    keyFn: KeyFn<T> | ItemTemplate<T>,\n    template: ItemTemplate<T>\n  ): unknown;\n}\n\n/**\n * A directive that repeats a series of values (usually `TemplateResults`)\n * generated from an iterable, and updates those items efficiently when the\n * iterable changes based on user-provided `keys` associated with each item.\n *\n * Note that if a `keyFn` is provided, strict key-to-DOM mapping is maintained,\n * meaning previous DOM for a given key is moved into the new position if\n * needed, and DOM will never be reused with values for different keys (new DOM\n * will always be created for new keys). This is generally the most efficient\n * way to use `repeat` since it performs minimum unnecessary work for insertions\n * and removals.\n *\n * The `keyFn` takes two parameters, the item and its index, and returns a unique key value.\n *\n * ```js\n * html`\n *   <ol>\n *     ${repeat(this.items, (item) => item.id, (item, index) => {\n *       return html`<li>${index}: ${item.name}</li>`;\n *     })}\n *   </ol>\n * `\n * ```\n *\n * **Important**: If providing a `keyFn`, keys *must* be unique for all items in a\n * given call to `repeat`. The behavior when two or more items have the same key\n * is undefined.\n *\n * If no `keyFn` is provided, this directive will perform similar to mapping\n * items to values, and DOM will be reused against potentially different items.\n */\nexport const repeat = directive(RepeatDirective) as RepeatDirectiveFn;\n\n/**\n * The type of the class that powers this directive. Necessary for naming the\n * directive's return type.\n */\nexport type {RepeatDirective};\n"]}