@livetemplate/client 0.8.37 → 0.8.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range-dom-applier.d.ts","sourceRoot":"","sources":["../../state/range-dom-applier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAShD,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AACjE,eAAO,MAAM,kBAAkB,2BAA2B,CAAC;AAE3D,KAAK,YAAY,GAAG,CAClB,IAAI,EAAE,GAAG,EACT,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACrC,SAAS,CAAC,EAAE,MAAM,KACf,MAAM,CAAC;AAEZ,KAAK,eAAe,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;AAC/D,KAAK,WAAW,GAAG,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC;AACzC,KAAK,YAAY,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,GAAG,CAAC;AAE5D,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,YAAY,CAAC;IACzB,oBAAoB,EAAE,eAAe,CAAC;IACtC;;;;;;;;OAQG;IACH,UAAU,EAAE,YAAY,CAAC;IACzB;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAGd,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,cAAc,CAA8B;gBAEvB,GAAG,EAAE,sBAAsB;IAExD,UAAU,IAAI,IAAI;IAIlB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIvC;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CACX,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,EACjB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,GAAG,IAAI;IAsBjB;;;;OAIG;IACH,gBAAgB,CACd,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,GAAG,EACnB,SAAS,EAAE,MAAM,GAChB,cAAc;IAuDjB;;;;;OAKG;IACH,KAAK,CACH,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,eAAe,EAC3B,eAAe,CAAC,EAAE,GAAG,GACpB,OAAO,GAAG,IAAI;IAsHjB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAqBtC,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,cAAc;IA2DtB,OAAO,CAAC,gBAAgB;IAyBxB,OAAO,CAAC,WAAW;IAiBnB,OAAO,CAAC,YAAY;IAiBpB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAiCzB;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;IA2CpB,OAAO,CAAC,cAAc;IAiBtB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,aAAa;IAwBrB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,0BAA0B;IAyBlC,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,iBAAiB;CAS1B"}
@@ -0,0 +1,510 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RangeDomApplier = exports.TARGETED_SKIP_ATTR = exports.TARGETED_APPLIED_ATTR = void 0;
7
+ const morphdom_1 = __importDefault(require("morphdom"));
8
+ const KEY_ATTRIBUTES = ["data-key", "data-lvt-key"];
9
+ // Pre-compile attribute-presence regexes once at module load — these were
10
+ // previously rebuilt on every staticsContainKeyAttribute call (per static
11
+ // segment, per attribute) which showed up in profiling on initial render.
12
+ const KEY_ATTR_REGEXES = KEY_ATTRIBUTES.map((attr) => new RegExp(`(?:^|[\\s<])${attr}\\s*=`));
13
+ exports.TARGETED_APPLIED_ATTR = "data-lvt-targeted-applied";
14
+ exports.TARGETED_SKIP_ATTR = "data-lvt-targeted-skip";
15
+ /**
16
+ * Applies range diff ops directly to the live DOM, bypassing full HTML
17
+ * reconstruction + morphdom diff. Designed to handle the common case where
18
+ * a 10k-row range receives a single-row mutation; the targeted path turns
19
+ * what would be a 5+ second morphdom walk into a sub-millisecond DOM op.
20
+ *
21
+ * The applier is opt-in per range: `canApplyTargeted` checks that the
22
+ * range has data-key emission, no nested-range items, and a resolvable
23
+ * container element. When any check fails, the caller falls back to the
24
+ * existing applyUpdate → reconstructFromTree → morphdom path.
25
+ */
26
+ class RangeDomApplier {
27
+ constructor(ctx) {
28
+ this.ctx = ctx;
29
+ this.containerCache = new Map();
30
+ }
31
+ invalidate() {
32
+ this.containerCache.clear();
33
+ }
34
+ invalidatePath(rangePath) {
35
+ this.containerCache.delete(rangePath);
36
+ }
37
+ /**
38
+ * Locate the live container element for a range path. The container is
39
+ * the parent element of items rendered with data-key. Cached per path;
40
+ * cache invalidated automatically when a cached element becomes detached.
41
+ *
42
+ * Resolution order:
43
+ * 1. Cached container (if still connected to the wrapper).
44
+ * 2. `wrapper.querySelector('[data-key="anyKnownItemKey"]').parentElement`.
45
+ *
46
+ * The original implementation also fell back to an unscoped
47
+ * `wrapper.querySelector('[data-key]')` walk, but that could return a
48
+ * container belonging to a *different* keyed range when the wrapper has
49
+ * more than one — silently mutating the wrong DOM subtree on subsequent
50
+ * ops. We now prefer to fail closed (return null → caller falls back to
51
+ * full rebuild) over mutating an unrelated container.
52
+ */
53
+ findContainer(wrapper, rangePath, anyKnownItemKey) {
54
+ const cached = this.containerCache.get(rangePath);
55
+ if (cached && cached.isConnected && wrapper.contains(cached)) {
56
+ return cached;
57
+ }
58
+ if (cached) {
59
+ this.containerCache.delete(rangePath);
60
+ }
61
+ if (anyKnownItemKey === undefined) {
62
+ return null;
63
+ }
64
+ const sample = this.findItemByKey(wrapper, anyKnownItemKey);
65
+ if (!sample || !sample.parentElement) {
66
+ return null;
67
+ }
68
+ const container = sample.parentElement;
69
+ this.containerCache.set(rangePath, container);
70
+ return container;
71
+ }
72
+ /**
73
+ * Decide whether a range update can take the targeted-apply path.
74
+ * Returns the resolved container in the success case so the caller
75
+ * can pass it to `apply` without re-resolving.
76
+ */
77
+ canApplyTargeted(wrapper, rangeStructure, rangePath) {
78
+ if (!rangeStructure || typeof rangeStructure !== "object") {
79
+ return { ok: false, reason: "no range structure" };
80
+ }
81
+ if (!Array.isArray(rangeStructure.s) || rangeStructure.s.length === 0) {
82
+ return { ok: false, reason: "no statics" };
83
+ }
84
+ const allStatics = [rangeStructure.s];
85
+ if (rangeStructure.sm && typeof rangeStructure.sm === "object") {
86
+ for (const sm of Object.values(rangeStructure.sm)) {
87
+ if (Array.isArray(sm)) {
88
+ allStatics.push(sm);
89
+ }
90
+ }
91
+ }
92
+ const hasKeyInStatics = allStatics.some((arr) => this.staticsContainKeyAttribute(arr));
93
+ if (!hasKeyInStatics) {
94
+ return { ok: false, reason: "no data-key attribute in statics" };
95
+ }
96
+ const items = rangeStructure.d;
97
+ if (Array.isArray(items)) {
98
+ for (const item of items) {
99
+ if (this.itemHasNestedRange(item)) {
100
+ return { ok: false, reason: "nested-range item" };
101
+ }
102
+ }
103
+ }
104
+ const sampleKey = this.extractItemKey(items?.[0], rangeStructure);
105
+ const container = this.findContainer(wrapper, rangePath, sampleKey);
106
+ if (!container) {
107
+ return { ok: false, reason: "container not found in DOM" };
108
+ }
109
+ // Walk up from container through wrapper (inclusive) — if any element
110
+ // on the path is lvt-ignore'd, the targeted-apply path would mutate
111
+ // DOM inside an ignored subtree while morphdom would have skipped it,
112
+ // violating the lvt-ignore contract.
113
+ let cur = container;
114
+ while (cur) {
115
+ if (cur.hasAttribute("lvt-ignore")) {
116
+ return { ok: false, reason: "lvt-ignore ancestor" };
117
+ }
118
+ if (cur === wrapper)
119
+ break;
120
+ cur = cur.parentElement;
121
+ }
122
+ return { ok: true, container, containerKey: sampleKey };
123
+ }
124
+ /**
125
+ * Apply a single targeted op to the live DOM. Returns the affected
126
+ * container element so the caller can mark it for the morphdom skip
127
+ * mechanism. Returns null if the op could not be applied (caller
128
+ * should fall back to full-rebuild for the next render).
129
+ */
130
+ apply(wrapper, targetedOp, morphdomOptions) {
131
+ const { rangePath, ops, statics, staticsMap } = targetedOp;
132
+ const sampleKey = this.firstKnownKey(ops);
133
+ const container = this.findContainer(wrapper, rangePath, sampleKey);
134
+ if (!container) {
135
+ this.ctx.logger.debug(`[RangeDomApplier] container not found for range ${rangePath}; cannot apply`);
136
+ return null;
137
+ }
138
+ let allOpsSucceeded = true;
139
+ for (const op of ops) {
140
+ if (!Array.isArray(op) || op.length < 1)
141
+ continue;
142
+ const opType = op[0];
143
+ try {
144
+ let opOK = true;
145
+ switch (opType) {
146
+ case "r":
147
+ opOK = this.applyRemove(container, op[1]);
148
+ break;
149
+ case "u":
150
+ opOK = this.applyUpdateRow(container, op[1], statics, staticsMap, rangePath, morphdomOptions);
151
+ break;
152
+ case "i":
153
+ opOK = this.applyInsertAfter(container, op[1], op[2], statics, staticsMap, rangePath);
154
+ break;
155
+ case "a":
156
+ opOK = this.applyAppend(container, op[1], statics, staticsMap, rangePath);
157
+ break;
158
+ case "p":
159
+ opOK = this.applyPrepend(container, op[1], statics, staticsMap, rangePath);
160
+ break;
161
+ case "o":
162
+ opOK = this.applyReorder(container, op[1]);
163
+ break;
164
+ default:
165
+ // Forward-compat: an unrecognised op type means we can't
166
+ // reason about the DOM mutation. Treat as failure so the
167
+ // caller falls back to a full morphdom rebuild from
168
+ // treeState (which the server-emitted unknown op type
169
+ // presumably already mutated correctly).
170
+ this.ctx.logger.warn(`[RangeDomApplier] unknown op type ${opType}; falling back`);
171
+ opOK = false;
172
+ }
173
+ if (!opOK) {
174
+ allOpsSucceeded = false;
175
+ }
176
+ }
177
+ catch (err) {
178
+ this.ctx.logger.error(`[RangeDomApplier] op ${opType} failed for range ${rangePath}`, err);
179
+ return null;
180
+ }
181
+ }
182
+ // If any per-op method silently no-op'd because of stale state
183
+ // (e.g. `u` for a row that's no longer in the DOM, `i` with a
184
+ // missing anchor), we MUST signal failure so the caller falls back
185
+ // to a full rebuild — otherwise the live DOM stays out of sync with
186
+ // treeState and morphdom would skip the subtree (TARGETED_APPLIED
187
+ // marker tells it to).
188
+ //
189
+ // Note: earlier ops in this batch that succeeded are NOT rolled back.
190
+ // No rollback is needed because `treeState` was already mutated to
191
+ // its complete post-op state by `applyDifferentialOpsToRange` BEFORE
192
+ // this method ran. The caller's fallback path re-renders from
193
+ // `treeState.renderState()` and runs morphdom over the full HTML —
194
+ // morphdom reconciles whatever partial DOM mutations we made toward
195
+ // the authoritative end state.
196
+ if (!allOpsSucceeded) {
197
+ return null;
198
+ }
199
+ // Observability hook: increment a global counter so E2E tests can
200
+ // assert the targeted-apply path was actually taken (vs silently
201
+ // hitting the fallback). Opt-in: tests must initialize the property
202
+ // first (e.g. `window.__lvtTargetedHits = 0`); production never sets
203
+ // it so the increment is skipped and we don't pollute the window
204
+ // object outside of test environments.
205
+ if (typeof window !== "undefined" &&
206
+ "__lvtTargetedHits" in window) {
207
+ window.__lvtTargetedHits++;
208
+ }
209
+ return container;
210
+ }
211
+ cleanupMarkers(wrapper) {
212
+ const applied = wrapper.querySelectorAll(`[${exports.TARGETED_APPLIED_ATTR}]`);
213
+ applied.forEach((el) => el.removeAttribute(exports.TARGETED_APPLIED_ATTR));
214
+ if (wrapper.hasAttribute(exports.TARGETED_APPLIED_ATTR)) {
215
+ wrapper.removeAttribute(exports.TARGETED_APPLIED_ATTR);
216
+ }
217
+ const skip = wrapper.querySelectorAll(`[${exports.TARGETED_SKIP_ATTR}]`);
218
+ skip.forEach((el) => el.removeAttribute(exports.TARGETED_SKIP_ATTR));
219
+ if (wrapper.hasAttribute(exports.TARGETED_SKIP_ATTR)) {
220
+ wrapper.removeAttribute(exports.TARGETED_SKIP_ATTR);
221
+ }
222
+ }
223
+ // --- per-op implementations -----------------------------------------------
224
+ //
225
+ // Each per-op method returns `boolean`:
226
+ // true → the live DOM is now consistent with the new treeState
227
+ // false → silent no-op (e.g. row not found, item state unavailable);
228
+ // the caller should invalidate the targeted-apply marker and
229
+ // fall back to a full rebuild
230
+ applyRemove(container, key) {
231
+ const row = this.findItemByKey(container, key);
232
+ if (!row) {
233
+ // r is idempotent: if the row is already gone, treeState's post-op
234
+ // view (also without the row) matches the DOM. No fallback needed.
235
+ this.ctx.logger.debug(`[RangeDomApplier] r: row with key ${key} not found (idempotent no-op)`);
236
+ return true;
237
+ }
238
+ this.fireHookOnSubtree(row, "lvt-destroyed");
239
+ row.remove();
240
+ return true;
241
+ }
242
+ applyUpdateRow(container, key, statics, staticsMap, rangePath, morphdomOptions) {
243
+ const row = this.findItemByKey(container, key);
244
+ if (!row) {
245
+ this.ctx.logger.debug(`[RangeDomApplier] u: row with key ${key} not found in DOM; falling back`);
246
+ return false;
247
+ }
248
+ const itemIdx = this.indexOfChild(container, row);
249
+ const item = this.lookupCurrentItem(rangePath, key);
250
+ if (!item) {
251
+ this.ctx.logger.debug(`[RangeDomApplier] u: item state for key ${key} not available; falling back`);
252
+ return false;
253
+ }
254
+ const newHtml = this.ctx.renderItem(item, itemIdx, statics, staticsMap, rangePath);
255
+ const newRow = this.parseSingleRow(newHtml);
256
+ if (!newRow) {
257
+ this.ctx.logger.warn(`[RangeDomApplier] u: failed to parse rendered row HTML; falling back`);
258
+ return false;
259
+ }
260
+ if (morphdomOptions) {
261
+ // Override childrenOnly: the main morphdom call uses childrenOnly:true
262
+ // because it's diffing the wrapper's children. For a single-row morph
263
+ // we MUST diff the row element itself too (its attributes — class,
264
+ // style, aria, etc. — are produced by statics+dynamics and may have
265
+ // changed). Reuse the same callbacks for behavioral consistency.
266
+ (0, morphdom_1.default)(row, newRow, { ...morphdomOptions, childrenOnly: false });
267
+ }
268
+ else {
269
+ // No morphdom options provided — fall back to wholesale replacement.
270
+ // morphdom's onNodeAdded / onBeforeNodeDiscarded callbacks would
271
+ // normally fire lvt-mounted/lvt-destroyed hooks for us; here we have
272
+ // to fire them manually on both sides AND notify the host so its
273
+ // nodesAddedThisRender counter sees the new subtree (otherwise the
274
+ // post-render directive scans would skip wiring listeners on it).
275
+ this.fireHookOnSubtree(row, "lvt-destroyed");
276
+ row.replaceWith(newRow);
277
+ this.ctx.onNodeAdded?.(newRow);
278
+ this.fireHookOnSubtree(newRow, "lvt-mounted");
279
+ }
280
+ return true;
281
+ }
282
+ applyInsertAfter(container, afterKey, items, statics, staticsMap, rangePath) {
283
+ const anchor = this.findItemByKey(container, afterKey);
284
+ if (!anchor) {
285
+ this.ctx.logger.debug(`[RangeDomApplier] i: anchor key ${afterKey} not found; falling back`);
286
+ return false;
287
+ }
288
+ return this.renderItemsAtomic(items, statics, staticsMap, rangePath, this.indexOfChild(container, anchor) + 1, (frag) => container.insertBefore(frag, anchor.nextSibling));
289
+ }
290
+ applyAppend(container, items, statics, staticsMap, rangePath) {
291
+ return this.renderItemsAtomic(items, statics, staticsMap, rangePath, container.children.length, (frag) => container.appendChild(frag));
292
+ }
293
+ applyPrepend(container, items, statics, staticsMap, rangePath) {
294
+ return this.renderItemsAtomic(items, statics, staticsMap, rangePath, 0, (frag) => container.insertBefore(frag, container.firstChild));
295
+ }
296
+ /**
297
+ * Render N items into a scratch DocumentFragment, splicing them into the
298
+ * live DOM only if ALL renders succeeded. On partial failure no DOM
299
+ * mutation happens and the caller falls back to a full rebuild — this
300
+ * avoids `lvt-mounted` firing on items that morphdom is then about to
301
+ * re-add (which would double-fire the hook).
302
+ */
303
+ renderItemsAtomic(items, statics, staticsMap, rangePath, baseIdx, splice) {
304
+ const list = Array.isArray(items) ? items : [items];
305
+ const scratch = document.createDocumentFragment();
306
+ const newRows = [];
307
+ for (let i = 0; i < list.length; i++) {
308
+ const newRow = this.renderAndParse(list[i], baseIdx + i, statics, staticsMap, rangePath);
309
+ if (!newRow) {
310
+ return false;
311
+ }
312
+ scratch.appendChild(newRow);
313
+ newRows.push(newRow);
314
+ }
315
+ splice(scratch);
316
+ for (const row of newRows) {
317
+ this.ctx.onNodeAdded?.(row);
318
+ this.fireHookOnSubtree(row, "lvt-mounted");
319
+ }
320
+ return true;
321
+ }
322
+ /**
323
+ * Reorder existing children to match `newKeyOrder`. Protocol assumption:
324
+ * the server emits the *full* new key order (mirrors the assumption in
325
+ * `applyDifferentialOpsToRange`'s "o" case in tree-renderer). When the
326
+ * new order is shorter than the current child set, we treat the missing
327
+ * keys as removals and fire `lvt-destroyed` on each dropped subtree
328
+ * (so user teardown — timer cancellation, observer disconnect, etc. —
329
+ * still runs) plus log a warning surfacing the protocol mismatch.
330
+ */
331
+ applyReorder(container, newKeyOrder) {
332
+ if (!Array.isArray(newKeyOrder))
333
+ return false;
334
+ const byKey = new Map();
335
+ Array.from(container.children).forEach((child) => {
336
+ for (const attr of KEY_ATTRIBUTES) {
337
+ const k = child.getAttribute(attr);
338
+ if (k !== null) {
339
+ byKey.set(k, child);
340
+ break;
341
+ }
342
+ }
343
+ });
344
+ const fragment = document.createDocumentFragment();
345
+ const newKeySet = new Set(newKeyOrder);
346
+ for (const key of newKeyOrder) {
347
+ const el = byKey.get(key);
348
+ if (el) {
349
+ fragment.appendChild(el);
350
+ }
351
+ }
352
+ // Fire lvt-destroyed on children that aren't in the new order. The
353
+ // protocol normally sends the FULL key order, but if a partial reorder
354
+ // ever lands here, user-defined teardown (timer cancellation, observer
355
+ // disconnect, etc.) must still run.
356
+ if (newKeySet.size < byKey.size) {
357
+ this.ctx.logger.warn(`[RangeDomApplier] o: newKeyOrder (${newKeySet.size}) shorter than existing children (${byKey.size}); ${byKey.size - newKeySet.size} children will be dropped`);
358
+ for (const [k, el] of byKey) {
359
+ if (!newKeySet.has(k)) {
360
+ this.fireHookOnSubtree(el, "lvt-destroyed");
361
+ }
362
+ }
363
+ }
364
+ container.replaceChildren(fragment);
365
+ return true;
366
+ }
367
+ // --- helpers --------------------------------------------------------------
368
+ renderAndParse(item, itemIdx, statics, staticsMap, rangePath) {
369
+ const html = this.ctx.renderItem(item, itemIdx, statics, staticsMap, rangePath);
370
+ return this.parseSingleRow(html);
371
+ }
372
+ /**
373
+ * Parse a string of HTML containing a single root element and return it.
374
+ * Uses <template> so orphan table-cell content (`<tr>`, `<td>`, etc.)
375
+ * is tolerated by the parser.
376
+ */
377
+ parseSingleRow(html) {
378
+ const template = document.createElement("template");
379
+ template.innerHTML = html.trim();
380
+ const first = template.content.firstElementChild;
381
+ return first ?? null;
382
+ }
383
+ findItemByKey(scope, key) {
384
+ let escaped;
385
+ if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
386
+ escaped = CSS.escape(key);
387
+ }
388
+ else {
389
+ // CSS.escape polyfill is incomplete: only handles `"` and `\`.
390
+ // Keys containing other CSS special chars ([], (), :, ., #, >, ~,
391
+ // whitespace, etc.) would produce a malformed selector and miss the
392
+ // match. Warn so it's visible in test logs rather than silently
393
+ // returning null and looking like the row simply doesn't exist.
394
+ if (/[\[\]():.#>~+*=^$|! \t\n\r]/.test(key)) {
395
+ this.ctx.logger.warn(`[RangeDomApplier] CSS.escape unavailable; key "${key}" contains characters that need escaping. Lookup may miss the row.`);
396
+ }
397
+ escaped = key.replace(/(["\\])/g, "\\$1");
398
+ }
399
+ for (const attr of KEY_ATTRIBUTES) {
400
+ const el = scope.querySelector(`[${attr}="${escaped}"]`);
401
+ if (el)
402
+ return el;
403
+ }
404
+ return null;
405
+ }
406
+ indexOfChild(container, child) {
407
+ let i = 0;
408
+ let cur = container.firstElementChild;
409
+ while (cur) {
410
+ if (cur === child)
411
+ return i;
412
+ i++;
413
+ cur = cur.nextElementSibling;
414
+ }
415
+ return -1;
416
+ }
417
+ firstKnownKey(ops) {
418
+ for (const op of ops) {
419
+ if (!Array.isArray(op) || op.length < 2)
420
+ continue;
421
+ const t = op[0];
422
+ if (t === "r" || t === "u" || t === "i") {
423
+ return typeof op[1] === "string" ? op[1] : undefined;
424
+ }
425
+ if (t === "o" && Array.isArray(op[1]) && op[1].length > 0) {
426
+ return typeof op[1][0] === "string" ? op[1][0] : undefined;
427
+ }
428
+ // For a/p ops there's no DOM-resident key in op[1], but the new
429
+ // items themselves carry `_k`. Sample the first to give
430
+ // findContainer something to walk to (rare cold-cache case;
431
+ // canApplyTargeted normally warms the cache via existing.d[0]
432
+ // before apply runs, so in practice the cache hit covers this).
433
+ if (t === "a" || t === "p") {
434
+ const items = Array.isArray(op[1]) ? op[1] : [op[1]];
435
+ for (const it of items) {
436
+ if (it && typeof it === "object" && it._k !== undefined) {
437
+ return String(it._k);
438
+ }
439
+ }
440
+ }
441
+ }
442
+ return undefined;
443
+ }
444
+ staticsContainKeyAttribute(statics) {
445
+ // Reduces false positives vs. plain `s.includes('data-key=')`:
446
+ // - requires word boundary before the attr name (excludes longer
447
+ // attribute names like `data-keystone=`, `my-data-key=`)
448
+ // - requires `=` to follow optional whitespace (excludes
449
+ // `data-key-something`)
450
+ //
451
+ // Known limitation: cannot distinguish a real attribute from
452
+ // `data-key=` appearing inside a quoted attribute value (e.g.
453
+ // `title='see data-key=foo'`). Such cases would still match. False
454
+ // positives are safe — `findContainer` just fails to locate by key,
455
+ // canApplyTargeted falls back to full rebuild — but they cost a
456
+ // render of wasted work. Real-world templates with `data-key` in
457
+ // attribute values are vanishingly rare.
458
+ for (const s of statics) {
459
+ if (typeof s !== "string")
460
+ continue;
461
+ for (const re of KEY_ATTR_REGEXES) {
462
+ if (re.test(s)) {
463
+ return true;
464
+ }
465
+ }
466
+ }
467
+ return false;
468
+ }
469
+ itemHasNestedRange(item) {
470
+ if (!item || typeof item !== "object")
471
+ return false;
472
+ for (const [key, val] of Object.entries(item)) {
473
+ if (key.startsWith("_"))
474
+ continue;
475
+ if (val && typeof val === "object" && !Array.isArray(val)) {
476
+ const v = val;
477
+ if (Array.isArray(v.d) && Array.isArray(v.s))
478
+ return true;
479
+ if (this.itemHasNestedRange(v))
480
+ return true;
481
+ }
482
+ }
483
+ return false;
484
+ }
485
+ extractItemKey(item, rangeStructure) {
486
+ if (!item || typeof item !== "object")
487
+ return undefined;
488
+ if (item._k !== undefined)
489
+ return String(item._k);
490
+ const idKey = rangeStructure?.m?.idKey;
491
+ if (idKey && item[idKey] !== undefined)
492
+ return String(item[idKey]);
493
+ return undefined;
494
+ }
495
+ lookupCurrentItem(rangePath, key) {
496
+ // O(N) over range.d via the context callback (linear scan in
497
+ // livetemplate-client.ts). Bounded cost per `u` op: one walk per
498
+ // updated row per render. At N=10k that's ~50µs in JS — acceptable.
499
+ return this.ctx.itemLookup(rangePath, key);
500
+ }
501
+ fireHookOnSubtree(root, hookName) {
502
+ if (root.hasAttribute(hookName)) {
503
+ this.ctx.executeLifecycleHook(root, hookName);
504
+ }
505
+ const descendants = root.querySelectorAll(`[${hookName}]`);
506
+ descendants.forEach((el) => this.ctx.executeLifecycleHook(el, hookName));
507
+ }
508
+ }
509
+ exports.RangeDomApplier = RangeDomApplier;
510
+ //# sourceMappingURL=range-dom-applier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range-dom-applier.js","sourceRoot":"","sources":["../../state/range-dom-applier.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,19 @@
1
1
  import type { TreeNode, UpdateResult } from "../types";
2
2
  import type { Logger } from "../utils/logger";
3
+ /**
4
+ * Optional context for `applyUpdate` that opts into per-op targeted DOM
5
+ * mutation. When `canApplyTargeted` returns true for a top-level diff-op
6
+ * key, applyUpdate mutates treeState in place (no deepClone) and emits
7
+ * a `TargetedRangeOp` in the result. The caller is then responsible for
8
+ * applying the op directly to the live DOM (typically via RangeDomApplier).
9
+ *
10
+ * The corresponding range subtree is replaced in `result.html` with a
11
+ * `<!--lvt-targeted-skip:${rangePath}-->` placeholder so that morphdom
12
+ * can be told to short-circuit that subtree.
13
+ */
14
+ export interface ApplyUpdateOptions {
15
+ canApplyTargeted?: (rangeStructure: any, rangePath: string) => boolean;
16
+ }
3
17
  /**
4
18
  * Handles tree state management and HTML reconstruction logic for LiveTemplate.
5
19
  */
@@ -9,10 +23,17 @@ export declare class TreeRenderer {
9
23
  private rangeState;
10
24
  private rangeIdKeys;
11
25
  constructor(logger: Logger);
12
- applyUpdate(update: TreeNode): UpdateResult;
26
+ applyUpdate(update: TreeNode, opts?: ApplyUpdateOptions): UpdateResult;
13
27
  reset(): void;
14
28
  getTreeState(): TreeNode;
15
29
  getStaticStructure(): string[] | null;
30
+ /**
31
+ * Re-render the current treeState as full HTML, with no targeted-apply
32
+ * skip placeholders. Used by `LiveTemplateClient.updateDOM` as a fallback
33
+ * when one or more targeted-apply DOM mutations failed: the treeState is
34
+ * authoritative, so a full rebuild + morphdom pass restores consistency.
35
+ */
36
+ renderState(): string;
16
37
  private deepMergeTreeNodes;
17
38
  /**
18
39
  * Applies differential operations to the provided range structure in-place.
@@ -23,6 +44,16 @@ export declare class TreeRenderer {
23
44
  private reconstructFromTree;
24
45
  private renderValue;
25
46
  private renderRangeStructure;
47
+ /**
48
+ * Renders a single range item to HTML by interleaving its dynamic slots
49
+ * with the range's statics. Honors per-item statics (`_sk` lookup in
50
+ * `staticsMap`) when present.
51
+ *
52
+ * Used by `renderRangeStructure` and `renderItemsWithStatics` for full
53
+ * range rendering, and by `range-dom-applier` to render a single new
54
+ * or updated item for targeted DOM mutations.
55
+ */
56
+ renderRangeItem(item: any, itemIdx: number, statics: string[], staticsMap?: Record<string, string[]>, statePath?: string): string;
26
57
  private applyDifferentialOperations;
27
58
  private getCurrentRangeStructure;
28
59
  private renderItemsWithStatics;
@@ -1 +1 @@
1
- {"version":3,"file":"tree-renderer.d.ts","sourceRoot":"","sources":["../../state/tree-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAoH9C;;GAEG;AACH,qBAAa,YAAY;IAKX,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,UAAU,CAAuC;IACzD,OAAO,CAAC,WAAW,CAA8B;gBAEpB,MAAM,EAAE,MAAM;IAE3C,WAAW,CAAC,MAAM,EAAE,QAAQ,GAAG,YAAY;IA+C3C,KAAK,IAAI,IAAI;IAMb,YAAY,IAAI,QAAQ;IAIxB,kBAAkB,IAAI,MAAM,EAAE,GAAG,IAAI;IAIrC,OAAO,CAAC,kBAAkB;IAmF1B;;;;OAIG;IACH,OAAO,CAAC,2BAA2B;IAoKnC,OAAO,CAAC,mBAAmB;IA8B3B,OAAO,CAAC,WAAW;IAgGnB,OAAO,CAAC,oBAAoB;IAkE5B,OAAO,CAAC,2BAA2B;IAgJnC,OAAO,CAAC,wBAAwB;IAqBhC,OAAO,CAAC,sBAAsB;IAmD9B,OAAO,CAAC,eAAe;IAqBvB,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,kBAAkB;IAW1B;;;;;OAKG;IACH,OAAO,CAAC,cAAc;CAGvB"}
1
+ {"version":3,"file":"tree-renderer.d.ts","sourceRoot":"","sources":["../../state/tree-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,QAAQ,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,gBAAgB,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CACxE;AAoHD;;GAEG;AACH,qBAAa,YAAY;IAKX,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,UAAU,CAAuC;IACzD,OAAO,CAAC,WAAW,CAA8B;gBAEpB,MAAM,EAAE,MAAM;IAE3C,WAAW,CACT,MAAM,EAAE,QAAQ,EAChB,IAAI,CAAC,EAAE,kBAAkB,GACxB,YAAY;IA0Ef,KAAK,IAAI,IAAI;IAMb,YAAY,IAAI,QAAQ;IAIxB,kBAAkB,IAAI,MAAM,EAAE,GAAG,IAAI;IAIrC;;;;;OAKG;IACH,WAAW,IAAI,MAAM;IAIrB,OAAO,CAAC,kBAAkB;IAmF1B;;;;OAIG;IACH,OAAO,CAAC,2BAA2B;IAoKnC,OAAO,CAAC,mBAAmB;IA4C3B,OAAO,CAAC,WAAW;IAgGnB,OAAO,CAAC,oBAAoB;IAqC5B;;;;;;;;OAQG;IACH,eAAe,CACb,IAAI,EAAE,GAAG,EACT,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACrC,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM;IA8BT,OAAO,CAAC,2BAA2B;IAgJnC,OAAO,CAAC,wBAAwB;IAqBhC,OAAO,CAAC,sBAAsB;IAwB9B,OAAO,CAAC,eAAe;IAqBvB,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,kBAAkB;IAW1B;;;;;OAKG;IACH,OAAO,CAAC,cAAc;CAGvB"}