@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.
- package/.turbo/turbo-build.log +51 -0
- package/CHANGELOG.md +88 -0
- package/COMPONENT_ARCHITECTURE.md +190 -0
- package/COMPONENT_CONVERSION_ANALYSIS.md +371 -0
- package/CONTEXT_VARIANT_GUIDE.md +425 -0
- package/LAZY_LOADING_GUIDE.md +534 -0
- package/LICENSE +201 -0
- package/PLAYBACK_EXAMPLES.md +658 -0
- package/PLAYBACK_GUIDE.md +402 -0
- package/README.md +43 -0
- package/REGISTRY_SUMMARY.md +638 -0
- package/SUFFERING_ECONOMICS.md +346 -0
- package/SUFFERING_ECONOMICS.zip +0 -0
- package/VIEW_REGISTRATION_GUIDE.md +795 -0
- package/dist/composables/index.cjs +1321 -0
- package/dist/composables/index.cjs.map +1 -0
- package/dist/composables/index.d.cts +6 -0
- package/dist/composables/index.d.ts +6 -0
- package/dist/composables/index.js +1276 -0
- package/dist/composables/index.js.map +1 -0
- package/dist/index-CMLU1hKL.d.ts +374 -0
- package/dist/index-CSDjhiKV.d.cts +374 -0
- package/dist/index.cjs +1534 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +93 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.js +1463 -0
- package/dist/index.js.map +1 -0
- package/dist/registry/index.cjs +522 -0
- package/dist/registry/index.cjs.map +1 -0
- package/dist/registry/index.d.cts +46 -0
- package/dist/registry/index.d.ts +46 -0
- package/dist/registry/index.js +487 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/types/index.cjs +19 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +203 -0
- package/dist/types/index.d.ts +203 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.cjs +217 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +47 -0
- package/dist/utils/index.d.ts +47 -0
- package/dist/utils/index.js +188 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/view-loader-dD86QAlQ.d.cts +121 -0
- package/dist/view-loader-ii8AxiQR.d.ts +121 -0
- package/package.json +64 -0
- package/publish.log +0 -0
- package/src/composables/index.ts +59 -0
- package/src/composables/use-image-loader.ts +315 -0
- package/src/composables/use-transaction-playback.ts +396 -0
- package/src/composables/use-transaction-view.ts +309 -0
- package/src/config/lukso-config.ts +171 -0
- package/src/examples/context-aware-views.ts +300 -0
- package/src/examples/example-views.ts +197 -0
- package/src/examples/lit-plus-rn-strategy.ts +448 -0
- package/src/examples/lsp7-custom-matcher-examples.ts +174 -0
- package/src/examples/opt-in-context-examples.ts +372 -0
- package/src/examples/optimized-view-definitions.ts +408 -0
- package/src/examples/vue-to-lit-compilation.ts +358 -0
- package/src/hooks/useAddressQuery.ts +135 -0
- package/src/hooks/useAddressResolution.ts +437 -0
- package/src/index.ts +36 -0
- package/src/registry/index.ts +13 -0
- package/src/registry/view-loader.ts +305 -0
- package/src/registry/view-registry.ts +135 -0
- package/src/types/index.ts +16 -0
- package/src/types/view-contexts.ts +72 -0
- package/src/types/view-matching.ts +173 -0
- package/src/utils/context-matcher.ts +165 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/view-matcher.ts +338 -0
- package/tsconfig.json +20 -0
- 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
|