@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,402 @@
1
+ # Transaction Playback System
2
+
3
+ ## Overview
4
+
5
+ The Transaction Playback system provides **index-based access** to transaction views, with smart handling of batch transactions. This gives UI teams maximum flexibility in how they display transactions.
6
+
7
+ ## Index Mapping
8
+
9
+ ### Single Transaction
10
+ ```
11
+ Index 0 → The transaction
12
+ Index 1 → The transaction (same as 0)
13
+ Index 2+ → null (invalid)
14
+ ```
15
+
16
+ ### Batch Transaction (setDataBatch, executeBatch)
17
+ ```
18
+ Index 0 → Summary/expandable view of the batch
19
+ Index 1 → First child transaction
20
+ Index 2 → Second child transaction
21
+ Index N → Nth child transaction
22
+ ```
23
+
24
+ ## Why This Design?
25
+
26
+ This index mapping provides maximum UI flexibility:
27
+
28
+ 1. **Always skip batch summaries**: Request index 1 to always get the "main" transaction
29
+ 2. **Optional batch overview**: Request index 0 to show batch summary when available
30
+ 3. **Navigate children**: Request indices 2, 3, 4... to show specific child transactions
31
+ 4. **Consistent behavior**: Both single and batch transactions work with index 1
32
+
33
+ ## Basic Usage
34
+
35
+ ### Option 1: Headless Composable (Framework Agnostic)
36
+
37
+ ```typescript
38
+ import { useTransactionPlayback } from '@lukso/transaction-view-headless'
39
+
40
+ // Get the view match at index 1 (main transaction)
41
+ const result = useTransactionPlayback(transaction, 1, {
42
+ framework: 'lit',
43
+ fallbackViewId: 'universal-execute'
44
+ })
45
+
46
+ if (result.indexInfo.isValid) {
47
+ console.log('View:', result.match?.view.id)
48
+ console.log('Transaction:', result.transaction)
49
+ console.log('Is batch summary:', result.indexInfo.isBatchSummary)
50
+ console.log('Available indices:', result.batchInfo.availableIndices)
51
+ }
52
+ ```
53
+
54
+ ### Option 2: Playback State (Multiple Indices)
55
+
56
+ ```typescript
57
+ import { createTransactionPlayback } from '@lukso/transaction-view-headless'
58
+
59
+ // Create playback state
60
+ const playback = createTransactionPlayback(transaction, {
61
+ framework: 'lit',
62
+ chain: lukso
63
+ })
64
+
65
+ console.log('Is batch:', playback.isBatch)
66
+ console.log('Available indices:', playback.indexCount)
67
+
68
+ // Get view at specific index
69
+ const view0 = playback.getViewAtIndex(0) // Summary or single transaction
70
+ const view1 = playback.getViewAtIndex(1) // Main transaction (always valid)
71
+
72
+ // Get all views
73
+ const allViews = playback.getAllViews()
74
+ ```
75
+
76
+ ## UI Implementation Patterns
77
+
78
+ ### Pattern 1: Simple List (Always Skip Summaries)
79
+
80
+ ```typescript
81
+ // Always request index 1 - works for both single and batch
82
+ const mainView = useTransactionPlayback(transaction, 1, options)
83
+ // Render mainView.match
84
+ ```
85
+
86
+ ### Pattern 2: Summary + List Toggle
87
+
88
+ ```vue
89
+ <template>
90
+ <div class="transaction-view">
91
+ <!-- Toggle button (only shown for batches) -->
92
+ <button
93
+ v-if="playback.isBatch"
94
+ @click="showSummary = !showSummary"
95
+ >
96
+ {{ showSummary ? 'Show List' : 'Show Summary' }}
97
+ </button>
98
+
99
+ <!-- Render at computed index -->
100
+ <component :is="currentView" />
101
+ </div>
102
+ </template>
103
+
104
+ <script setup lang="ts">
105
+ import { computed, ref } from 'vue'
106
+ import { createTransactionPlayback } from '@lukso/transaction-view-headless'
107
+
108
+ const props = defineProps(['transaction'])
109
+ const showSummary = ref(false)
110
+
111
+ const playback = createTransactionPlayback(props.transaction, {
112
+ framework: 'lit'
113
+ })
114
+
115
+ const currentIndex = computed(() => {
116
+ // For single transactions, index 0 or 1 both work
117
+ // For batches, toggle between summary (0) and main transaction (1)
118
+ return showSummary.value && playback.isBatch ? 0 : 1
119
+ })
120
+
121
+ const result = computed(() =>
122
+ playback.getViewAtIndex(currentIndex.value)
123
+ )
124
+ </script>
125
+ ```
126
+
127
+ ### Pattern 3: Expandable Batch List
128
+
129
+ ```vue
130
+ <template>
131
+ <div class="transaction-view">
132
+ <!-- Main view (index 1) -->
133
+ <div class="main-transaction">
134
+ <component :is="mainView" />
135
+ </div>
136
+
137
+ <!-- Batch children (if expanded) -->
138
+ <div v-if="playback.isBatch && expanded" class="batch-children">
139
+ <div
140
+ v-for="index in childIndices"
141
+ :key="index"
142
+ class="child-transaction"
143
+ >
144
+ <component :is="getChildView(index)" />
145
+ </div>
146
+ </div>
147
+
148
+ <!-- Expand button -->
149
+ <button
150
+ v-if="playback.isBatch"
151
+ @click="expanded = !expanded"
152
+ class="expand-toggle"
153
+ >
154
+ {{ expanded ? 'Collapse' : `Show ${playback.children.length} operations` }}
155
+ </button>
156
+ </div>
157
+ </template>
158
+
159
+ <script setup lang="ts">
160
+ import { computed, ref } from 'vue'
161
+ import { createTransactionPlayback } from '@lukso/transaction-view-headless'
162
+
163
+ const props = defineProps(['transaction'])
164
+ const expanded = ref(false)
165
+
166
+ const playback = createTransactionPlayback(props.transaction, {
167
+ framework: 'lit'
168
+ })
169
+
170
+ // Main view is always at index 1
171
+ const mainView = computed(() =>
172
+ playback.getViewAtIndex(1).match
173
+ )
174
+
175
+ // Child indices start at 2 (index 0 = summary, index 1 = first child)
176
+ const childIndices = computed(() =>
177
+ playback.isBatch
178
+ ? Array.from({ length: playback.children.length - 1 }, (_, i) => i + 2)
179
+ : []
180
+ )
181
+
182
+ function getChildView(index: number) {
183
+ return playback.getViewAtIndex(index).match
184
+ }
185
+ </script>
186
+ ```
187
+
188
+ ### Pattern 4: Pagination Through Batch
189
+
190
+ ```vue
191
+ <template>
192
+ <div class="transaction-view">
193
+ <component :is="currentView" />
194
+
195
+ <!-- Navigation (only for batches) -->
196
+ <div v-if="playback.isBatch" class="pagination">
197
+ <button @click="prevTransaction" :disabled="currentIndex <= 1">
198
+ Previous
199
+ </button>
200
+
201
+ <span>
202
+ {{ currentIndex }} / {{ playback.children.length }}
203
+ </span>
204
+
205
+ <button @click="nextTransaction" :disabled="currentIndex >= playback.children.length">
206
+ Next
207
+ </button>
208
+ </div>
209
+ </div>
210
+ </template>
211
+
212
+ <script setup lang="ts">
213
+ import { computed, ref } from 'vue'
214
+ import { createTransactionPlayback } from '@lukso/transaction-view-headless'
215
+
216
+ const props = defineProps(['transaction'])
217
+ const currentIndex = ref(1) // Start at index 1 (first transaction)
218
+
219
+ const playback = createTransactionPlayback(props.transaction, {
220
+ framework: 'lit'
221
+ })
222
+
223
+ const currentView = computed(() =>
224
+ playback.getViewAtIndex(currentIndex.value).match
225
+ )
226
+
227
+ function nextTransaction() {
228
+ if (currentIndex.value < playback.children.length) {
229
+ currentIndex.value++
230
+ }
231
+ }
232
+
233
+ function prevTransaction() {
234
+ if (currentIndex.value > 1) {
235
+ currentIndex.value--
236
+ }
237
+ }
238
+ </script>
239
+ ```
240
+
241
+ ## Helper Functions
242
+
243
+ ### Check if Index is Valid
244
+
245
+ ```typescript
246
+ import { isValidPlaybackIndex } from '@lukso/transaction-view-headless'
247
+
248
+ const isValid = isValidPlaybackIndex(transaction, 2)
249
+ // Single transaction: false (only 0 and 1 are valid)
250
+ // Batch with 3+ children: true
251
+ ```
252
+
253
+ ### Get All Valid Indices
254
+
255
+ ```typescript
256
+ import { getValidPlaybackIndices } from '@lukso/transaction-view-headless'
257
+
258
+ const validIndices = getValidPlaybackIndices(transaction)
259
+ // Single transaction: [0, 1]
260
+ // Batch with 3 children: [0, 1, 2, 3]
261
+ ```
262
+
263
+ ## Integration with View Loader
264
+
265
+ To actually load and render components, combine playback with the view loader:
266
+
267
+ ```typescript
268
+ import { createTransactionPlayback } from '@lukso/transaction-view-headless'
269
+ import { getGlobalLitLoader } from '@lukso/transaction-view-core'
270
+
271
+ const playback = createTransactionPlayback(transaction, { framework: 'lit' })
272
+ const loader = getGlobalLitLoader()
273
+
274
+ // Get view at index 1
275
+ const result = playback.getViewAtIndex(1)
276
+
277
+ if (result.match) {
278
+ // Load the component
279
+ const componentClass = await loader.loadFromMatch(result.match)
280
+
281
+ // Create instance
282
+ const instance = loader.createInstance(componentClass, {
283
+ transaction: result.transaction,
284
+ // ... other props
285
+ })
286
+
287
+ // Append to DOM
288
+ container.appendChild(instance)
289
+ }
290
+ ```
291
+
292
+ ## API Reference
293
+
294
+ ### `useTransactionPlayback(transaction, index, options)`
295
+
296
+ Returns the view match and transaction data for a specific index.
297
+
298
+ **Parameters:**
299
+ - `transaction: DecoderResult` - The transaction to query
300
+ - `index: number` - The index to retrieve (0, 1, 2, ...)
301
+ - `options: TransactionPlaybackOptions` - Configuration options
302
+
303
+ **Returns:** `PlaybackIndexResult`
304
+ ```typescript
305
+ {
306
+ match: ViewMatch | null, // The matched view
307
+ transaction: DecoderResult | null, // The transaction data
308
+ indexInfo: {
309
+ requested: number, // The requested index
310
+ childIndex: number | null, // Index in children array
311
+ isBatchSummary: boolean, // Whether this is batch summary
312
+ isValid: boolean // Whether the index is valid
313
+ },
314
+ batchInfo: {
315
+ isBatch: boolean, // Whether root is a batch
316
+ childCount: number, // Number of children
317
+ availableIndices: number[] // Valid indices (e.g., [0, 1, 2, 3])
318
+ }
319
+ }
320
+ ```
321
+
322
+ ### `createTransactionPlayback(transaction, options)`
323
+
324
+ Creates a playback state for navigating through a transaction and its children.
325
+
326
+ **Parameters:**
327
+ - `transaction: DecoderResult` - The transaction
328
+ - `options: TransactionPlaybackOptions` - Configuration options
329
+
330
+ **Returns:** `TransactionPlaybackState`
331
+ ```typescript
332
+ {
333
+ rootTransaction: DecoderResult,
334
+ isBatch: boolean,
335
+ children: DecoderResult[],
336
+ indexCount: number,
337
+ getViewAtIndex: (index: number) => PlaybackIndexResult,
338
+ getAllViews: () => PlaybackIndexResult[]
339
+ }
340
+ ```
341
+
342
+ ## Common Scenarios
343
+
344
+ ### Scenario 1: Wallet Approval Flow
345
+ ```typescript
346
+ // Always show index 1 (main transaction) for approval
347
+ const result = useTransactionPlayback(transaction, 1, { framework: 'lit' })
348
+ // User reviews and approves/rejects this single view
349
+ ```
350
+
351
+ ### Scenario 2: Transaction History List
352
+ ```typescript
353
+ // Show summary (index 0) for batches, single transaction (index 1) for singles
354
+ const index = playback.isBatch ? 0 : 1
355
+ const result = playback.getViewAtIndex(index)
356
+ ```
357
+
358
+ ### Scenario 3: Detailed Transaction View
359
+ ```typescript
360
+ // Show expandable list with all children
361
+ const allViews = playback.getAllViews()
362
+ // Render index 0 as expandable header
363
+ // Render indices 1+ as child list items
364
+ ```
365
+
366
+ ## Migration from TransactionViewReplacement
367
+
368
+ If you're using the old `TransactionViewReplacement`, the playback system gives you more control:
369
+
370
+ **Old approach:**
371
+ ```vue
372
+ <TransactionViewReplacement
373
+ :transaction="transaction"
374
+ :handle-subtransactions="true"
375
+ />
376
+ ```
377
+
378
+ **New approach with playback:**
379
+ ```vue
380
+ <TransactionPlayback
381
+ :transaction="transaction"
382
+ :index="1"
383
+ />
384
+ ```
385
+
386
+ This lets you control which index to show, giving the UI team flexibility to choose between summary and detail views.
387
+
388
+ ## Best Practices
389
+
390
+ 1. **Default to index 1** for consistent behavior across single and batch transactions
391
+ 2. **Use index 0** only when you want to show batch summaries
392
+ 3. **Check `indexInfo.isValid`** before rendering
393
+ 4. **Cache playback state** when rendering multiple views from the same transaction
394
+ 5. **Use `batchInfo.availableIndices`** for rendering navigation UI
395
+
396
+ ## Future Enhancements
397
+
398
+ Potential future additions based on UI team feedback:
399
+ - Virtual scrolling for large batches
400
+ - Lazy loading of child views
401
+ - Deep linking to specific child indices
402
+ - Breadcrumb navigation for nested batches
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @lukso/transaction-view-headless
2
+
3
+ Framework-agnostic business logic for transaction views.
4
+
5
+ ## ✨ Key Features
6
+
7
+ - **Framework Priority System** - Native Vue/React Native views automatically preferred over Lit fallbacks
8
+ - **Numeric Custom Matchers** - Fine-grained view selection based on contract metadata
9
+ - **Index-Based Playback** - Flexible batch transaction display (summary, pagination, expansion)
10
+ - **Contract-Level Caching** - Metadata fetched once per contract, shared across batch operations
11
+ - **Extensible Metadata** - `transaction.custom` field for enhancer-populated view-matching data
12
+
13
+ ## 📚 Documentation
14
+
15
+ **Local Guides:**
16
+ - **[REGISTRY_SUMMARY.md](./REGISTRY_SUMMARY.md)** - Complete system overview
17
+ - **[VIEW_REGISTRATION_GUIDE.md](./VIEW_REGISTRATION_GUIDE.md)** - How to register views & create custom packages
18
+ - **[PLAYBACK_GUIDE.md](./PLAYBACK_GUIDE.md)** - Playback system & API reference
19
+ - **[PLAYBACK_EXAMPLES.md](./PLAYBACK_EXAMPLES.md)** - Real-world usage examples
20
+ - **[CONTEXT_VARIANT_GUIDE.md](./CONTEXT_VARIANT_GUIDE.md)** - Context-aware view matching
21
+
22
+ **Main Docs:**
23
+ - **[Architecture Summary](../../docs/ARCHITECTURE_SUMMARY.md)** - Understanding the system
24
+ - **[Vue to Lit Conversion Guide](../../docs/VUE_TO_LIT_CONVERSION_GUIDE.md)** - Component conversion
25
+ - **[Optimization Strategies](../../docs/OPTIMIZATION_STRATEGIES.md)** - Performance patterns
26
+
27
+ ## 🚀 Quick Usage
28
+
29
+ ```typescript
30
+ import { useTransactionView } from '@lukso/transaction-view-headless'
31
+
32
+ const { bestMatch, component, resolvedAddresses } = useTransactionView(transaction, {
33
+ framework: 'lit',
34
+ resolve: true,
35
+ chain: lukso
36
+ })
37
+ ```
38
+
39
+ ## 📁 Package Contents
40
+
41
+ - `src/composables/` - Business logic composables
42
+ - `src/registry/` - View matching and loading
43
+ - `src/types/` - TypeScript interfaces