···22 <img src="https://github.com/phlex-ruby/morphlex/assets/246692/128ebe6a-bdf3-4b88-8a40-f29df64b3ac8" alt="Morphlex" width="481">
33</p>
4455-Morphlex is a tiny, optimal DOM morphing library written in TypeScript. DOM morphing is the process of transforming one DOM tree to reflect another, while preserving the state of the original tree and making as few changes as possible.
55+Morphlex is a 2KB DOM morphing library that transforms one DOM tree to match another while preserving element state and making minimal changes.
6677-Morphlex uses ID Sets — a concept pioneered by [Idiomorph](https://github.com/bigskysoftware/idiomorph) — to match nodes with deeply nested identified elements.
88-99-## ID Sets
1010-1111-Each element is tagged with the set of IDs it contains, allowing for more optimal matching.
1212-1313-Failing an ID Set match, Morphlex will search for the next best match by tag name. If no element can be found, the reference element will be deeply cloned instead.
77+## Installation
1481515-## Try it out
99+```bash
1010+npm install morphlex
1111+```
16121717-The easiest way to try out Morphlex is to import it directly from UNPKG.
1313+Or use it directly from a CDN:
18141915```html
2016<script type="module">
2117 import { morph } from "https://www.unpkg.com/morphlex@0.0.16/dist/morphlex.min.js"
2222-2323- morph(currentNode, referenceNode)
2424- morphInner(currentNode, referenceNode)
2518</script>
2619```
27202828-Alternatively, you can install it via npm and import it into your project.
2929-3030-```bash
3131-npm install morphlex --save
3232-```
2121+## Usage
33223423```javascript
3535-import { morph } from "morphlex"
2424+import { morph, morphInner } from "morphlex"
36252626+// Morph the entire element
3727morph(currentNode, referenceNode)
2828+2929+// Morph only the inner content
3030+morphInner(currentNode, referenceNode)
3831```
39324040-The `currentNode` will be morphed into the state of the `referenceNode`. The `referenceNode` will not be mutated in this process.
3333+The `currentNode` is transformed to match the `referenceNode`. The `referenceNode` remains unchanged.
3434+3535+## How it works
3636+3737+Morphlex uses a smart matching algorithm that produces minimal DOM operations for common patterns like inserts, deletes, and reordering.
3838+3939+### Matching strategy
4040+4141+When morphing child nodes, Morphlex tries multiple matching strategies in order of specificity:
4242+4343+1. **Exact match** — Nodes that are completely identical (`isEqualNode`)
4444+2. **ID match** — Elements with the same `id` attribute
4545+3. **ID set match** — Elements containing the same nested IDs (see below)
4646+4. **Tag match** — Elements with the same tag name, or nodes with the same type
41474242-## Contributing
4848+This cascading approach means most updates find optimal matches quickly, while still handling edge cases gracefully.
43494444-If you find a bug or have a feature request, please open an issue. If you want to contribute, please open a pull request.
5050+### ID sets
45514646-> [!TIP]
4747-> Morphlex is written in **[TypeScript](https://www.typescriptlang.org)** because it helps us avoid a whole category of potential bugs. If you’re more comfortable writing JavaScript, you’re very welcome to open a Pull Request modifying the `dist/morphlex.js` file. I’m happy to take care of the TypeScript conversion myself. — Joel
5252+ID sets are inspired by [Idiomorph](https://github.com/bigskysoftware/idiomorph). Each element is tagged with the set of IDs it contains, including deeply nested ones. This helps match elements even when they've moved or been restructured.
5353+5454+For example, if you have a card with `id="card-123"` nested inside a container, the container's ID set includes `"card-123"`. When morphing, Morphlex can match the container based on that nested ID, even if the container itself has no ID.
5555+5656+### Minimal operations
5757+5858+After matching, Morphlex processes nodes in order and makes the minimum number of DOM operations:
5959+6060+- Matched elements are moved into position (if needed) and recursively morphed
6161+- New nodes are inserted at the correct position
6262+- Unmatched nodes are removed
6363+6464+This means operations like sorting a list or inserting items in the middle produce exactly the moves you'd expect, with no unnecessary removals or recreations.
6565+6666+## Contributing
6767+6868+Found a bug or have a feature request? Open an issue. Want to contribute? Open a pull request.