@lukso/transaction-view-headless 0.2.2-dev.a8c9315

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.
Files changed (76) hide show
  1. package/.turbo/turbo-build.log +51 -0
  2. package/CHANGELOG.md +88 -0
  3. package/COMPONENT_ARCHITECTURE.md +190 -0
  4. package/COMPONENT_CONVERSION_ANALYSIS.md +371 -0
  5. package/CONTEXT_VARIANT_GUIDE.md +425 -0
  6. package/LAZY_LOADING_GUIDE.md +534 -0
  7. package/LICENSE +201 -0
  8. package/PLAYBACK_EXAMPLES.md +658 -0
  9. package/PLAYBACK_GUIDE.md +402 -0
  10. package/README.md +43 -0
  11. package/REGISTRY_SUMMARY.md +638 -0
  12. package/SUFFERING_ECONOMICS.md +346 -0
  13. package/SUFFERING_ECONOMICS.zip +0 -0
  14. package/VIEW_REGISTRATION_GUIDE.md +795 -0
  15. package/dist/composables/index.cjs +1321 -0
  16. package/dist/composables/index.cjs.map +1 -0
  17. package/dist/composables/index.d.cts +6 -0
  18. package/dist/composables/index.d.ts +6 -0
  19. package/dist/composables/index.js +1276 -0
  20. package/dist/composables/index.js.map +1 -0
  21. package/dist/index-CMLU1hKL.d.ts +374 -0
  22. package/dist/index-CSDjhiKV.d.cts +374 -0
  23. package/dist/index.cjs +1534 -0
  24. package/dist/index.cjs.map +1 -0
  25. package/dist/index.d.cts +93 -0
  26. package/dist/index.d.ts +93 -0
  27. package/dist/index.js +1463 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/registry/index.cjs +522 -0
  30. package/dist/registry/index.cjs.map +1 -0
  31. package/dist/registry/index.d.cts +46 -0
  32. package/dist/registry/index.d.ts +46 -0
  33. package/dist/registry/index.js +487 -0
  34. package/dist/registry/index.js.map +1 -0
  35. package/dist/types/index.cjs +19 -0
  36. package/dist/types/index.cjs.map +1 -0
  37. package/dist/types/index.d.cts +203 -0
  38. package/dist/types/index.d.ts +203 -0
  39. package/dist/types/index.js +1 -0
  40. package/dist/types/index.js.map +1 -0
  41. package/dist/utils/index.cjs +217 -0
  42. package/dist/utils/index.cjs.map +1 -0
  43. package/dist/utils/index.d.cts +47 -0
  44. package/dist/utils/index.d.ts +47 -0
  45. package/dist/utils/index.js +188 -0
  46. package/dist/utils/index.js.map +1 -0
  47. package/dist/view-loader-dD86QAlQ.d.cts +121 -0
  48. package/dist/view-loader-ii8AxiQR.d.ts +121 -0
  49. package/package.json +64 -0
  50. package/publish.log +0 -0
  51. package/src/composables/index.ts +59 -0
  52. package/src/composables/use-image-loader.ts +315 -0
  53. package/src/composables/use-transaction-playback.ts +396 -0
  54. package/src/composables/use-transaction-view.ts +309 -0
  55. package/src/config/lukso-config.ts +171 -0
  56. package/src/examples/context-aware-views.ts +300 -0
  57. package/src/examples/example-views.ts +197 -0
  58. package/src/examples/lit-plus-rn-strategy.ts +448 -0
  59. package/src/examples/lsp7-custom-matcher-examples.ts +174 -0
  60. package/src/examples/opt-in-context-examples.ts +372 -0
  61. package/src/examples/optimized-view-definitions.ts +408 -0
  62. package/src/examples/vue-to-lit-compilation.ts +358 -0
  63. package/src/hooks/useAddressQuery.ts +135 -0
  64. package/src/hooks/useAddressResolution.ts +437 -0
  65. package/src/index.ts +36 -0
  66. package/src/registry/index.ts +13 -0
  67. package/src/registry/view-loader.ts +305 -0
  68. package/src/registry/view-registry.ts +135 -0
  69. package/src/types/index.ts +16 -0
  70. package/src/types/view-contexts.ts +72 -0
  71. package/src/types/view-matching.ts +173 -0
  72. package/src/utils/context-matcher.ts +165 -0
  73. package/src/utils/index.ts +5 -0
  74. package/src/utils/view-matcher.ts +338 -0
  75. package/tsconfig.json +20 -0
  76. package/tsup.config.ts +34 -0
@@ -0,0 +1,658 @@
1
+ # Transaction Playback - Complete Examples
2
+
3
+ This guide shows real-world examples of using the Transaction Playback system in Lit and Vue applications.
4
+
5
+ ## Quick Reference
6
+
7
+ ### Index Mapping
8
+
9
+ **Single Transaction:**
10
+ - Index 0 → The transaction
11
+ - Index 1 → The transaction (same)
12
+ - Index 2+ → null
13
+
14
+ **Batch Transaction:**
15
+ - Index 0 → Batch summary/expandable view
16
+ - Index 1 → First child
17
+ - Index 2 → Second child
18
+ - Index N → Nth child
19
+
20
+ ### Default Behavior
21
+
22
+ Use **index 1** as default for consistent behavior that always shows the main transaction and skips batch summaries.
23
+
24
+ ## Lit Web Component Examples
25
+
26
+ ### 1. Simple Usage (Lit in Any Framework)
27
+
28
+ ```html
29
+ <!DOCTYPE html>
30
+ <html>
31
+ <head>
32
+ <script type="module">
33
+ // Import and initialize the transaction view system
34
+ import { initializeTransactionViews } from '@lukso/transaction-view-core'
35
+ initializeTransactionViews()
36
+ </script>
37
+ </head>
38
+ <body>
39
+ <!-- Always show main transaction (index 1) -->
40
+ <transaction-playback
41
+ id="tx-view"
42
+ index="1"
43
+ ></transaction-playback>
44
+
45
+ <script type="module">
46
+ // Set transaction data
47
+ const txView = document.getElementById('tx-view')
48
+ txView.transaction = {
49
+ resultType: 'transfer',
50
+ standard: 'LSP7',
51
+ // ... other transaction data
52
+ }
53
+ </script>
54
+ </body>
55
+ </html>
56
+ ```
57
+
58
+ ### 2. Vue 3 with Lit Component
59
+
60
+ ```vue
61
+ <template>
62
+ <div class="transaction-container">
63
+ <transaction-playback
64
+ :transaction="transaction"
65
+ :index="currentIndex"
66
+ :debug="true"
67
+ />
68
+ </div>
69
+ </template>
70
+
71
+ <script setup lang="ts">
72
+ import { ref } from 'vue'
73
+ import { initializeTransactionViews } from '@lukso/transaction-view-core'
74
+ import type { DecoderResult } from '@lukso/transaction-decoder'
75
+
76
+ // Initialize on app startup (do this once in main.ts)
77
+ initializeTransactionViews()
78
+
79
+ const props = defineProps<{
80
+ transaction: DecoderResult
81
+ }>()
82
+
83
+ // Default to index 1 (skip batch summaries)
84
+ const currentIndex = ref(1)
85
+ </script>
86
+ ```
87
+
88
+ ### 3. Batch Navigation with Lit
89
+
90
+ ```vue
91
+ <template>
92
+ <div class="batch-viewer">
93
+ <!-- Navigation controls -->
94
+ <div v-if="isBatch" class="batch-controls">
95
+ <button @click="showSummary" :disabled="currentIndex === 0">
96
+ Summary
97
+ </button>
98
+ <button @click="prevChild" :disabled="currentIndex <= 1">
99
+ ← Previous
100
+ </button>
101
+ <span class="index-display">
102
+ {{ currentIndex }} / {{ maxIndex }}
103
+ </span>
104
+ <button @click="nextChild" :disabled="currentIndex >= maxIndex">
105
+ Next →
106
+ </button>
107
+ </div>
108
+
109
+ <!-- Transaction view -->
110
+ <transaction-playback
111
+ :transaction="transaction"
112
+ :index="currentIndex"
113
+ />
114
+ </div>
115
+ </template>
116
+
117
+ <script setup lang="ts">
118
+ import { computed, ref } from 'vue'
119
+ import { getValidPlaybackIndices } from '@lukso/transaction-view-headless'
120
+ import type { DecoderResult } from '@lukso/transaction-decoder'
121
+
122
+ const props = defineProps<{
123
+ transaction: DecoderResult
124
+ }>()
125
+
126
+ const currentIndex = ref(1) // Start at first transaction
127
+
128
+ const validIndices = computed(() =>
129
+ getValidPlaybackIndices(props.transaction)
130
+ )
131
+
132
+ const isBatch = computed(() =>
133
+ props.transaction.resultType === 'executeBatch' ||
134
+ props.transaction.resultType === 'setDataBatch'
135
+ )
136
+
137
+ const maxIndex = computed(() =>
138
+ Math.max(...validIndices.value)
139
+ )
140
+
141
+ function showSummary() {
142
+ currentIndex.value = 0
143
+ }
144
+
145
+ function nextChild() {
146
+ if (currentIndex.value < maxIndex.value) {
147
+ currentIndex.value++
148
+ }
149
+ }
150
+
151
+ function prevChild() {
152
+ if (currentIndex.value > 1) {
153
+ currentIndex.value--
154
+ }
155
+ }
156
+ </script>
157
+
158
+ <style scoped>
159
+ .batch-controls {
160
+ display: flex;
161
+ gap: 12px;
162
+ align-items: center;
163
+ margin-bottom: 16px;
164
+ padding: 12px;
165
+ background: #f9fafb;
166
+ border-radius: 8px;
167
+ }
168
+
169
+ .batch-controls button {
170
+ padding: 8px 16px;
171
+ background: white;
172
+ border: 1px solid #e5e7eb;
173
+ border-radius: 6px;
174
+ cursor: pointer;
175
+ }
176
+
177
+ .batch-controls button:hover:not(:disabled) {
178
+ background: #f3f4f6;
179
+ }
180
+
181
+ .batch-controls button:disabled {
182
+ opacity: 0.5;
183
+ cursor: not-allowed;
184
+ }
185
+
186
+ .index-display {
187
+ font-weight: 500;
188
+ color: #374151;
189
+ }
190
+ </style>
191
+ ```
192
+
193
+ ## Vue Component Examples
194
+
195
+ ### 1. Simple Vue Playback
196
+
197
+ ```vue
198
+ <template>
199
+ <TransactionPlayback
200
+ :transaction="transaction"
201
+ :index="1"
202
+ framework="lit"
203
+ />
204
+ </template>
205
+
206
+ <script setup lang="ts">
207
+ import { TransactionPlayback } from '@lukso/transaction-view-core-vue'
208
+ import type { DecoderResult } from '@lukso/transaction-decoder'
209
+
210
+ const props = defineProps<{
211
+ transaction: DecoderResult
212
+ }>()
213
+ </script>
214
+ ```
215
+
216
+ ### 2. Expandable Batch List (Vue)
217
+
218
+ ```vue
219
+ <template>
220
+ <div class="transaction-playback-container">
221
+ <!-- Main transaction (always index 1) -->
222
+ <TransactionPlayback
223
+ :transaction="transaction"
224
+ :index="1"
225
+ framework="lit"
226
+ class="main-transaction"
227
+ />
228
+
229
+ <!-- Batch expansion -->
230
+ <div v-if="playback.isBatch" class="batch-section">
231
+ <!-- Expand/collapse button -->
232
+ <button @click="expanded = !expanded" class="expand-button">
233
+ <span class="expand-icon">{{ expanded ? '▼' : '▶' }}</span>
234
+ {{ expanded ? 'Hide' : 'Show' }} {{ childCount }}
235
+ {{ childCount === 1 ? 'operation' : 'operations' }}
236
+ </button>
237
+
238
+ <!-- Child transactions (when expanded) -->
239
+ <div v-if="expanded" class="child-transactions">
240
+ <TransactionPlayback
241
+ v-for="index in childIndices"
242
+ :key="index"
243
+ :transaction="transaction"
244
+ :index="index"
245
+ framework="lit"
246
+ class="child-transaction"
247
+ />
248
+ </div>
249
+ </div>
250
+ </div>
251
+ </template>
252
+
253
+ <script setup lang="ts">
254
+ import { computed, ref } from 'vue'
255
+ import { TransactionPlayback } from '@lukso/transaction-view-core-vue'
256
+ import { createTransactionPlayback } from '@lukso/transaction-view-headless'
257
+ import type { DecoderResult } from '@lukso/transaction-decoder'
258
+
259
+ const props = defineProps<{
260
+ transaction: DecoderResult
261
+ }>()
262
+
263
+ const expanded = ref(false)
264
+
265
+ const playback = computed(() =>
266
+ createTransactionPlayback(props.transaction, { framework: 'lit' })
267
+ )
268
+
269
+ const childCount = computed(() => playback.value.children.length)
270
+
271
+ // Child indices: 2, 3, 4... (1 is the main transaction, already shown)
272
+ const childIndices = computed(() =>
273
+ Array.from({ length: childCount.value - 1 }, (_, i) => i + 2)
274
+ )
275
+ </script>
276
+
277
+ <style scoped>
278
+ .transaction-playback-container {
279
+ display: flex;
280
+ flex-direction: column;
281
+ gap: 16px;
282
+ }
283
+
284
+ .batch-section {
285
+ border-top: 1px solid #e5e7eb;
286
+ padding-top: 16px;
287
+ }
288
+
289
+ .expand-button {
290
+ display: flex;
291
+ align-items: center;
292
+ gap: 8px;
293
+ padding: 10px 16px;
294
+ width: 100%;
295
+ background: #f9fafb;
296
+ border: 1px solid #e5e7eb;
297
+ border-radius: 8px;
298
+ cursor: pointer;
299
+ font-size: 14px;
300
+ font-weight: 500;
301
+ color: #374151;
302
+ transition: all 0.2s;
303
+ }
304
+
305
+ .expand-button:hover {
306
+ background: #f3f4f6;
307
+ border-color: #d1d5db;
308
+ }
309
+
310
+ .expand-icon {
311
+ font-size: 12px;
312
+ transition: transform 0.2s;
313
+ }
314
+
315
+ .child-transactions {
316
+ margin-top: 12px;
317
+ display: flex;
318
+ flex-direction: column;
319
+ gap: 12px;
320
+ }
321
+
322
+ .child-transaction {
323
+ padding: 12px;
324
+ background: #fafafa;
325
+ border: 1px solid #e5e7eb;
326
+ border-radius: 8px;
327
+ }
328
+ </style>
329
+ ```
330
+
331
+ ### 3. Smart Index Selection (Vue)
332
+
333
+ ```vue
334
+ <template>
335
+ <div class="smart-transaction-view">
336
+ <!-- Show different indices based on context -->
337
+ <TransactionPlayback
338
+ :transaction="transaction"
339
+ :index="smartIndex"
340
+ framework="lit"
341
+ :debug="isDevelopment"
342
+ />
343
+
344
+ <!-- Context switcher (for demo) -->
345
+ <div v-if="isDevelopment" class="context-switcher">
346
+ <button
347
+ v-for="ctx in contexts"
348
+ :key="ctx.value"
349
+ @click="context = ctx.value"
350
+ :class="{ active: context === ctx.value }"
351
+ >
352
+ {{ ctx.label }}
353
+ </button>
354
+ </div>
355
+ </div>
356
+ </template>
357
+
358
+ <script setup lang="ts">
359
+ import { computed, ref } from 'vue'
360
+ import { TransactionPlayback } from '@lukso/transaction-view-core-vue'
361
+ import { createTransactionPlayback } from '@lukso/transaction-view-headless'
362
+ import type { DecoderResult } from '@lukso/transaction-decoder'
363
+
364
+ const props = defineProps<{
365
+ transaction: DecoderResult
366
+ context?: 'approval' | 'feed' | 'detail' | 'list'
367
+ }>()
368
+
369
+ const isDevelopment = import.meta.env.DEV
370
+ const context = ref(props.context || 'detail')
371
+
372
+ const playback = computed(() =>
373
+ createTransactionPlayback(props.transaction, { framework: 'lit' })
374
+ )
375
+
376
+ // Smart index selection based on context
377
+ const smartIndex = computed(() => {
378
+ const ctx = context.value
379
+
380
+ // Approval flow: always show main transaction (no summaries)
381
+ if (ctx === 'approval') {
382
+ return 1
383
+ }
384
+
385
+ // Detail view: show batch summary if batch, otherwise main transaction
386
+ if (ctx === 'detail') {
387
+ return playback.value.isBatch ? 0 : 1
388
+ }
389
+
390
+ // Feed/List: always show main transaction for compact display
391
+ if (ctx === 'feed' || ctx === 'list') {
392
+ return 1
393
+ }
394
+
395
+ return 1
396
+ })
397
+
398
+ const contexts = [
399
+ { value: 'approval', label: 'Approval' },
400
+ { value: 'detail', label: 'Detail' },
401
+ { value: 'feed', label: 'Feed' },
402
+ { value: 'list', label: 'List' },
403
+ ]
404
+ </script>
405
+
406
+ <style scoped>
407
+ .context-switcher {
408
+ margin-top: 16px;
409
+ display: flex;
410
+ gap: 8px;
411
+ padding: 12px;
412
+ background: #f9fafb;
413
+ border-radius: 8px;
414
+ }
415
+
416
+ .context-switcher button {
417
+ padding: 6px 12px;
418
+ background: white;
419
+ border: 1px solid #e5e7eb;
420
+ border-radius: 6px;
421
+ font-size: 13px;
422
+ cursor: pointer;
423
+ }
424
+
425
+ .context-switcher button.active {
426
+ background: #3b82f6;
427
+ color: white;
428
+ border-color: #3b82f6;
429
+ }
430
+ </style>
431
+ ```
432
+
433
+ ## Headless Usage (Framework Agnostic)
434
+
435
+ ### Custom Rendering Logic
436
+
437
+ ```typescript
438
+ import {
439
+ createTransactionPlayback,
440
+ useTransactionPlayback,
441
+ } from '@lukso/transaction-view-headless'
442
+ import type { DecoderResult } from '@lukso/transaction-decoder'
443
+
444
+ function renderTransaction(transaction: DecoderResult, container: HTMLElement) {
445
+ // Create playback state
446
+ const playback = createTransactionPlayback(transaction, {
447
+ framework: 'lit',
448
+ fallbackViewId: 'universal-execute',
449
+ })
450
+
451
+ console.log('Is batch:', playback.isBatch)
452
+ console.log('Child count:', playback.children.length)
453
+ console.log('Available indices:', playback.batchInfo.availableIndices)
454
+
455
+ // Get view at index 1 (main transaction)
456
+ const result = playback.getViewAtIndex(1)
457
+
458
+ if (result.indexInfo.isValid && result.match) {
459
+ console.log('View ID:', result.match.view.id)
460
+ console.log('Transaction:', result.transaction)
461
+
462
+ // Load and render component (pseudo-code)
463
+ // const component = await loadComponent(result.match)
464
+ // container.appendChild(component)
465
+ } else {
466
+ console.error('Invalid index or no matching view')
467
+ }
468
+ }
469
+
470
+ // Alternative: Use the composable directly
471
+ function quickRender(transaction: DecoderResult, index: number) {
472
+ const result = useTransactionPlayback(transaction, index, {
473
+ framework: 'lit',
474
+ })
475
+
476
+ return {
477
+ isValid: result.indexInfo.isValid,
478
+ viewId: result.match?.view.id,
479
+ transaction: result.transaction,
480
+ }
481
+ }
482
+ ```
483
+
484
+ ## Common Patterns
485
+
486
+ ### Pattern 1: Always Skip Batch Summaries
487
+
488
+ ```vue
489
+ <!-- Always use index 1 -->
490
+ <TransactionPlayback :transaction="tx" :index="1" />
491
+ ```
492
+
493
+ ### Pattern 2: Show Summary for Batches Only
494
+
495
+ ```vue
496
+ <!-- Use index 0 for batches, index 1 for singles -->
497
+ <TransactionPlayback
498
+ :transaction="tx"
499
+ :index="isBatch(tx) ? 0 : 1"
500
+ />
501
+ ```
502
+
503
+ ### Pattern 3: Paginate Through Batch
504
+
505
+ ```vue
506
+ <template>
507
+ <div>
508
+ <TransactionPlayback :transaction="tx" :index="currentPage" />
509
+ <Pagination v-model="currentPage" :max="maxPages" />
510
+ </div>
511
+ </template>
512
+ ```
513
+
514
+ ### Pattern 4: Conditional Rendering
515
+
516
+ ```typescript
517
+ import { isValidPlaybackIndex } from '@lukso/transaction-view-headless'
518
+
519
+ // Check before rendering
520
+ if (isValidPlaybackIndex(transaction, desiredIndex)) {
521
+ // Render at desiredIndex
522
+ } else {
523
+ // Fall back to index 1
524
+ }
525
+ ```
526
+
527
+ ## Debug Mode
528
+
529
+ Enable debug mode to see detailed playback information:
530
+
531
+ ```vue
532
+ <TransactionPlayback
533
+ :transaction="transaction"
534
+ :index="1"
535
+ :debug="true"
536
+ />
537
+ ```
538
+
539
+ This shows:
540
+ - Requested index
541
+ - Validity status
542
+ - Batch information
543
+ - Matched view ID
544
+ - Available indices
545
+
546
+ ## Integration with Existing Code
547
+
548
+ ### Replacing TransactionIframe
549
+
550
+ **Before:**
551
+ ```vue
552
+ <TransactionIframe
553
+ :transaction="transaction"
554
+ :handle-subtransactions="true"
555
+ />
556
+ ```
557
+
558
+ **After:**
559
+ ```vue
560
+ <TransactionPlayback
561
+ :transaction="transaction"
562
+ :index="1"
563
+ framework="lit"
564
+ />
565
+ ```
566
+
567
+ ### Adding to Existing Components
568
+
569
+ ```vue
570
+ <template>
571
+ <div class="transaction-card">
572
+ <!-- Existing header, metadata, etc. -->
573
+ <div class="transaction-header">...</div>
574
+
575
+ <!-- Add playback component -->
576
+ <TransactionPlayback
577
+ :transaction="transaction"
578
+ :index="viewIndex"
579
+ framework="lit"
580
+ />
581
+
582
+ <!-- Existing footer, actions, etc. -->
583
+ <div class="transaction-actions">...</div>
584
+ </div>
585
+ </template>
586
+ ```
587
+
588
+ ## Performance Tips
589
+
590
+ 1. **Memoize playback state** when rendering multiple views:
591
+ ```typescript
592
+ const playback = computed(() =>
593
+ createTransactionPlayback(transaction, options)
594
+ )
595
+ ```
596
+
597
+ 2. **Use index 1 by default** to avoid unnecessary batch processing
598
+
599
+ 3. **Lazy load children** in expandable lists:
600
+ ```vue
601
+ <div v-if="expanded">
602
+ <TransactionPlayback
603
+ v-for="index in childIndices"
604
+ :key="index"
605
+ :transaction="transaction"
606
+ :index="index"
607
+ />
608
+ </div>
609
+ ```
610
+
611
+ 4. **Cache valid indices** to avoid recalculation:
612
+ ```typescript
613
+ const validIndices = computed(() =>
614
+ getValidPlaybackIndices(transaction)
615
+ )
616
+ ```
617
+
618
+ ## Troubleshooting
619
+
620
+ ### Issue: Component not rendering
621
+
622
+ **Solution:** Ensure the transaction view system is initialized:
623
+ ```typescript
624
+ import { initializeTransactionViews } from '@lukso/transaction-view-core'
625
+ initializeTransactionViews()
626
+ ```
627
+
628
+ ### Issue: Invalid index error
629
+
630
+ **Solution:** Check valid indices before rendering:
631
+ ```typescript
632
+ import { getValidPlaybackIndices } from '@lukso/transaction-view-headless'
633
+
634
+ const validIndices = getValidPlaybackIndices(transaction)
635
+ console.log('Valid indices:', validIndices) // [0, 1] or [0, 1, 2, 3]
636
+ ```
637
+
638
+ ### Issue: Batch summary shows instead of transaction
639
+
640
+ **Solution:** Use index 1 instead of index 0:
641
+ ```vue
642
+ <TransactionPlayback :index="1" />
643
+ ```
644
+
645
+ ### Issue: Children not showing
646
+
647
+ **Solution:** Check if transaction is actually a batch:
648
+ ```typescript
649
+ const playback = createTransactionPlayback(transaction, options)
650
+ console.log('Is batch:', playback.isBatch)
651
+ console.log('Children:', playback.children)
652
+ ```
653
+
654
+ ## Next Steps
655
+
656
+ - See [PLAYBACK_GUIDE.md](./PLAYBACK_GUIDE.md) for conceptual overview
657
+ - See [COMPONENT_ARCHITECTURE.md](../../docs/COMPONENT_ARCHITECTURE.md) for system architecture
658
+ - See [VIEW_SETUP.md](../../docs/architecture/VIEW_SETUP.md) for view registry details