{"version":3,"file":"repeat.js","sources":["../../../src/directives/repeat.ts"],"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 = (item: T, index: number) => unknown;\nexport type ItemTemplate = (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();\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(\n items: Iterable,\n keyFnOrTemplate: KeyFn | ItemTemplate,\n template?: ItemTemplate\n ) {\n let keyFn: KeyFn | undefined;\n if (template === undefined) {\n template = keyFnOrTemplate;\n } else if (keyFnOrTemplate !== undefined) {\n keyFn = keyFnOrTemplate as KeyFn;\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(items: Iterable, template: ItemTemplate): Array;\n render(\n items: Iterable,\n keyFn: KeyFn | ItemTemplate,\n template: ItemTemplate\n ): Array;\n render(\n items: Iterable,\n keyFnOrTemplate: KeyFn | ItemTemplate,\n template?: ItemTemplate\n ) {\n return this._getValuesAndKeys(items, keyFnOrTemplate, template).values;\n }\n\n override update(\n containerPart: ChildPart,\n [items, keyFnOrTemplate, template]: [\n Iterable,\n KeyFn | ItemTemplate,\n ItemTemplate\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;\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;\n let oldKeyToIndexMap!: Map;\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 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 (\n items: Iterable,\n keyFnOrTemplate: KeyFn | ItemTemplate,\n template?: ItemTemplate\n ): unknown;\n (items: Iterable, template: ItemTemplate): unknown;\n (\n items: Iterable,\n keyFn: KeyFn | ItemTemplate,\n template: ItemTemplate\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 *
    \n * ${repeat(this.items, (item) => item.id, (item, index) => {\n * return html`
  1. ${index}: ${item.name}
  2. `;\n * })}\n *
\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"],"names":[],"mappings":"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"}