@portel/photon-core 1.5.0 → 2.1.0

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 (163) hide show
  1. package/dist/auto-ui.js +1 -1
  2. package/dist/auto-ui.js.map +1 -1
  3. package/dist/base.d.ts +1 -1
  4. package/dist/base.d.ts.map +1 -1
  5. package/dist/base.js +2 -2
  6. package/dist/base.js.map +1 -1
  7. package/dist/cli-ui-renderer.js +1 -1
  8. package/dist/cli-ui-renderer.js.map +1 -1
  9. package/dist/design-system/index.d.ts +21 -0
  10. package/dist/design-system/index.d.ts.map +1 -0
  11. package/dist/design-system/index.js +27 -0
  12. package/dist/design-system/index.js.map +1 -0
  13. package/dist/design-system/tokens.d.ts +149 -0
  14. package/dist/design-system/tokens.d.ts.map +1 -0
  15. package/dist/design-system/tokens.js +413 -0
  16. package/dist/design-system/tokens.js.map +1 -0
  17. package/dist/design-system/transaction-ui.d.ts +70 -0
  18. package/dist/design-system/transaction-ui.d.ts.map +1 -0
  19. package/dist/design-system/transaction-ui.js +982 -0
  20. package/dist/design-system/transaction-ui.js.map +1 -0
  21. package/dist/generator.d.ts +56 -6
  22. package/dist/generator.d.ts.map +1 -1
  23. package/dist/generator.js.map +1 -1
  24. package/dist/index.d.ts +6 -7
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +46 -56
  27. package/dist/index.js.map +1 -1
  28. package/dist/io.d.ts +103 -2
  29. package/dist/io.d.ts.map +1 -1
  30. package/dist/io.js +37 -1
  31. package/dist/io.js.map +1 -1
  32. package/dist/rendering/components.d.ts +29 -0
  33. package/dist/rendering/components.d.ts.map +1 -0
  34. package/dist/rendering/components.js +773 -0
  35. package/dist/rendering/components.js.map +1 -0
  36. package/dist/rendering/field-analyzer.d.ts +48 -0
  37. package/dist/rendering/field-analyzer.d.ts.map +1 -0
  38. package/dist/rendering/field-analyzer.js +270 -0
  39. package/dist/rendering/field-analyzer.js.map +1 -0
  40. package/dist/rendering/field-renderers.d.ts +64 -0
  41. package/dist/rendering/field-renderers.d.ts.map +1 -0
  42. package/dist/rendering/field-renderers.js +317 -0
  43. package/dist/rendering/field-renderers.js.map +1 -0
  44. package/dist/rendering/index.d.ts +28 -0
  45. package/dist/rendering/index.d.ts.map +1 -0
  46. package/dist/rendering/index.js +60 -0
  47. package/dist/rendering/index.js.map +1 -0
  48. package/dist/rendering/layout-selector.d.ts +48 -0
  49. package/dist/rendering/layout-selector.d.ts.map +1 -0
  50. package/dist/rendering/layout-selector.js +347 -0
  51. package/dist/rendering/layout-selector.js.map +1 -0
  52. package/dist/rendering/template-engine.d.ts +41 -0
  53. package/dist/rendering/template-engine.d.ts.map +1 -0
  54. package/dist/rendering/template-engine.js +236 -0
  55. package/dist/rendering/template-engine.js.map +1 -0
  56. package/dist/schema-extractor.d.ts +30 -0
  57. package/dist/schema-extractor.d.ts.map +1 -1
  58. package/dist/schema-extractor.js +205 -12
  59. package/dist/schema-extractor.js.map +1 -1
  60. package/dist/stateful.js +1 -1
  61. package/dist/stateful.js.map +1 -1
  62. package/dist/types.d.ts +9 -1
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/types.js.map +1 -1
  65. package/dist/ucp/ap2/handlers.d.ts +242 -0
  66. package/dist/ucp/ap2/handlers.d.ts.map +1 -0
  67. package/dist/ucp/ap2/handlers.js +482 -0
  68. package/dist/ucp/ap2/handlers.js.map +1 -0
  69. package/dist/ucp/ap2/mandates.d.ts +95 -0
  70. package/dist/ucp/ap2/mandates.d.ts.map +1 -0
  71. package/dist/ucp/ap2/mandates.js +234 -0
  72. package/dist/ucp/ap2/mandates.js.map +1 -0
  73. package/dist/ucp/ap2/types.d.ts +305 -0
  74. package/dist/ucp/ap2/types.d.ts.map +1 -0
  75. package/dist/ucp/ap2/types.js +8 -0
  76. package/dist/ucp/ap2/types.js.map +1 -0
  77. package/dist/ucp/capabilities/checkout.d.ts +118 -0
  78. package/dist/ucp/capabilities/checkout.d.ts.map +1 -0
  79. package/dist/ucp/capabilities/checkout.js +344 -0
  80. package/dist/ucp/capabilities/checkout.js.map +1 -0
  81. package/dist/ucp/capabilities/identity.d.ts +130 -0
  82. package/dist/ucp/capabilities/identity.d.ts.map +1 -0
  83. package/dist/ucp/capabilities/identity.js +290 -0
  84. package/dist/ucp/capabilities/identity.js.map +1 -0
  85. package/dist/ucp/capabilities/order.d.ts +142 -0
  86. package/dist/ucp/capabilities/order.d.ts.map +1 -0
  87. package/dist/ucp/capabilities/order.js +383 -0
  88. package/dist/ucp/capabilities/order.js.map +1 -0
  89. package/dist/ucp/index.d.ts +18 -0
  90. package/dist/ucp/index.d.ts.map +1 -0
  91. package/dist/ucp/index.js +19 -0
  92. package/dist/ucp/index.js.map +1 -0
  93. package/dist/ucp/manifest.d.ts +62 -0
  94. package/dist/ucp/manifest.d.ts.map +1 -0
  95. package/dist/ucp/manifest.js +180 -0
  96. package/dist/ucp/manifest.js.map +1 -0
  97. package/dist/ucp/types.d.ts +327 -0
  98. package/dist/ucp/types.d.ts.map +1 -0
  99. package/dist/ucp/types.js +8 -0
  100. package/dist/ucp/types.js.map +1 -0
  101. package/package.json +3 -4
  102. package/src/auto-ui.ts +1 -1
  103. package/src/base.ts +2 -2
  104. package/src/cli-ui-renderer.ts +1 -1
  105. package/src/design-system/index.ts +30 -0
  106. package/src/design-system/tokens.ts +451 -0
  107. package/src/design-system/transaction-ui.ts +1038 -0
  108. package/src/generator.ts +58 -2
  109. package/src/index.ts +135 -124
  110. package/src/io.ts +108 -3
  111. package/src/rendering/components.ts +785 -0
  112. package/src/rendering/field-analyzer.ts +299 -0
  113. package/src/rendering/field-renderers.ts +356 -0
  114. package/src/rendering/index.ts +63 -0
  115. package/src/rendering/layout-selector.ts +390 -0
  116. package/src/rendering/template-engine.ts +254 -0
  117. package/src/schema-extractor.ts +225 -12
  118. package/src/stateful.ts +1 -1
  119. package/src/types.ts +10 -1
  120. package/src/ucp/ap2/handlers.ts +779 -0
  121. package/src/ucp/ap2/mandates.ts +354 -0
  122. package/src/ucp/ap2/types.ts +441 -0
  123. package/src/ucp/capabilities/checkout.ts +497 -0
  124. package/src/ucp/capabilities/identity.ts +425 -0
  125. package/src/ucp/capabilities/order.ts +549 -0
  126. package/src/ucp/index.ts +27 -0
  127. package/src/ucp/manifest.ts +257 -0
  128. package/src/ucp/types.ts +454 -0
  129. package/dist/cli-formatter.d.ts +0 -92
  130. package/dist/cli-formatter.d.ts.map +0 -1
  131. package/dist/cli-formatter.js +0 -486
  132. package/dist/cli-formatter.js.map +0 -1
  133. package/dist/context.d.ts +0 -6
  134. package/dist/context.d.ts.map +0 -1
  135. package/dist/context.js +0 -3
  136. package/dist/context.js.map +0 -1
  137. package/dist/elicit.d.ts +0 -93
  138. package/dist/elicit.d.ts.map +0 -1
  139. package/dist/elicit.js +0 -373
  140. package/dist/elicit.js.map +0 -1
  141. package/dist/mcp-client.d.ts +0 -218
  142. package/dist/mcp-client.d.ts.map +0 -1
  143. package/dist/mcp-client.js +0 -424
  144. package/dist/mcp-client.js.map +0 -1
  145. package/dist/mcp-sdk-transport.d.ts +0 -88
  146. package/dist/mcp-sdk-transport.d.ts.map +0 -1
  147. package/dist/mcp-sdk-transport.js +0 -360
  148. package/dist/mcp-sdk-transport.js.map +0 -1
  149. package/dist/photon-config.d.ts +0 -86
  150. package/dist/photon-config.d.ts.map +0 -1
  151. package/dist/photon-config.js +0 -156
  152. package/dist/photon-config.js.map +0 -1
  153. package/dist/progress.d.ts +0 -93
  154. package/dist/progress.d.ts.map +0 -1
  155. package/dist/progress.js +0 -195
  156. package/dist/progress.js.map +0 -1
  157. package/src/cli-formatter.ts +0 -579
  158. package/src/context.ts +0 -7
  159. package/src/elicit.ts +0 -438
  160. package/src/mcp-client.ts +0 -561
  161. package/src/mcp-sdk-transport.ts +0 -449
  162. package/src/photon-config.ts +0 -201
  163. package/src/progress.ts +0 -224
@@ -0,0 +1,773 @@
1
+ /**
2
+ * Component Renderers - iOS-inspired UI components
3
+ *
4
+ * Provides render functions for:
5
+ * - List (iOS UITableView style)
6
+ * - Card (single item display)
7
+ * - Grid (visual grid layout)
8
+ * - Tree (nested/hierarchical data)
9
+ * - Chips (string array as tags)
10
+ */
11
+ /**
12
+ * Generate CSS for all components
13
+ * Uses Photon Design System tokens (Material Design 3 + Apple HIG)
14
+ */
15
+ export function generateComponentCSS() {
16
+ return `
17
+ /* ==========================================================================
18
+ Smart Rendering Components (using Photon Design Tokens)
19
+ ========================================================================== */
20
+
21
+ /* List Component (iOS-style) */
22
+ .smart-list {
23
+ display: flex;
24
+ flex-direction: column;
25
+ gap: 1px;
26
+ background: var(--color-outline-variant);
27
+ border-radius: var(--radius-md);
28
+ overflow: hidden;
29
+ }
30
+
31
+ .smart-list.style-plain {
32
+ background: transparent;
33
+ gap: 0;
34
+ border-radius: 0;
35
+ }
36
+
37
+ .smart-list.style-inset {
38
+ margin: 0 var(--space-4);
39
+ border-radius: var(--radius-md);
40
+ }
41
+
42
+ .smart-list.style-grouped {
43
+ background: transparent;
44
+ gap: var(--space-4);
45
+ }
46
+
47
+ /* List Item */
48
+ .list-item {
49
+ display: flex;
50
+ align-items: center;
51
+ gap: var(--space-3);
52
+ padding: var(--space-3) var(--space-4);
53
+ background: var(--color-surface-container);
54
+ cursor: pointer;
55
+ transition: background var(--duration-fast) var(--ease-standard);
56
+ }
57
+
58
+ .list-item:hover {
59
+ background: var(--color-surface-container-high);
60
+ }
61
+
62
+ .list-item:active {
63
+ background: var(--color-surface-container-highest);
64
+ }
65
+
66
+ .style-plain .list-item {
67
+ border-bottom: 1px solid var(--color-outline-variant);
68
+ }
69
+
70
+ .style-plain .list-item:last-child {
71
+ border-bottom: none;
72
+ }
73
+
74
+ /* List Item: Leading (icon/avatar) */
75
+ .list-item-leading {
76
+ flex-shrink: 0;
77
+ width: 40px;
78
+ height: 40px;
79
+ display: flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ font-size: var(--text-title-lg);
83
+ border-radius: var(--radius-sm);
84
+ background: var(--color-surface-container-highest);
85
+ }
86
+
87
+ .list-item-leading img {
88
+ width: 100%;
89
+ height: 100%;
90
+ object-fit: cover;
91
+ border-radius: var(--radius-sm);
92
+ }
93
+
94
+ .list-item-leading.emoji {
95
+ background: transparent;
96
+ }
97
+
98
+ /* List Item: Content (title + subtitle) */
99
+ .list-item-content {
100
+ flex: 1;
101
+ min-width: 0;
102
+ display: flex;
103
+ flex-direction: column;
104
+ gap: 2px;
105
+ }
106
+
107
+ .list-item-title {
108
+ font-size: var(--text-body-lg);
109
+ font-weight: var(--weight-medium);
110
+ color: var(--color-on-surface);
111
+ white-space: nowrap;
112
+ overflow: hidden;
113
+ text-overflow: ellipsis;
114
+ }
115
+
116
+ .list-item-subtitle {
117
+ font-size: var(--text-body-sm);
118
+ color: var(--color-on-surface-variant);
119
+ white-space: nowrap;
120
+ overflow: hidden;
121
+ text-overflow: ellipsis;
122
+ }
123
+
124
+ /* List Item: Trailing (detail + badge) */
125
+ .list-item-trailing {
126
+ flex-shrink: 0;
127
+ display: flex;
128
+ align-items: center;
129
+ gap: var(--space-2);
130
+ color: var(--color-on-surface-variant);
131
+ font-size: var(--text-body-sm);
132
+ }
133
+
134
+ .list-item-badge {
135
+ padding: var(--space-1) var(--space-2);
136
+ border-radius: var(--radius-full);
137
+ font-size: var(--text-label-sm);
138
+ font-weight: var(--weight-medium);
139
+ background: var(--color-primary-container);
140
+ color: var(--color-on-primary-container);
141
+ }
142
+
143
+ .list-item-badge.status-active,
144
+ .list-item-badge.status-success {
145
+ background: var(--color-success-container);
146
+ color: var(--color-on-success-container);
147
+ }
148
+
149
+ .list-item-badge.status-inactive,
150
+ .list-item-badge.status-error {
151
+ background: var(--color-error-container);
152
+ color: var(--color-on-error-container);
153
+ }
154
+
155
+ .list-item-badge.status-pending,
156
+ .list-item-badge.status-warning {
157
+ background: var(--color-warning-container);
158
+ color: var(--color-on-warning-container);
159
+ }
160
+
161
+ /* List Item: Accessory */
162
+ .list-item-accessory {
163
+ flex-shrink: 0;
164
+ color: var(--color-on-surface-muted);
165
+ font-size: var(--text-title-md);
166
+ }
167
+
168
+ .list-item-accessory.chevron::after {
169
+ content: '›';
170
+ }
171
+
172
+ .list-item-accessory.disclosure::after {
173
+ content: '▼';
174
+ font-size: var(--text-label-sm);
175
+ }
176
+
177
+ /* Card Component */
178
+ .smart-card {
179
+ background: var(--color-surface-container);
180
+ border-radius: var(--radius-lg);
181
+ overflow: hidden;
182
+ border: 1px solid var(--color-outline-variant);
183
+ }
184
+
185
+ .smart-card-header {
186
+ display: flex;
187
+ align-items: center;
188
+ gap: var(--space-3);
189
+ padding: var(--space-4);
190
+ border-bottom: 1px solid var(--color-outline-variant);
191
+ }
192
+
193
+ .smart-card-icon {
194
+ width: 48px;
195
+ height: 48px;
196
+ display: flex;
197
+ align-items: center;
198
+ justify-content: center;
199
+ font-size: var(--text-headline-md);
200
+ border-radius: var(--radius-md);
201
+ background: var(--color-surface-container-highest);
202
+ }
203
+
204
+ .smart-card-icon img {
205
+ width: 100%;
206
+ height: 100%;
207
+ object-fit: cover;
208
+ border-radius: var(--radius-md);
209
+ }
210
+
211
+ .smart-card-header-content {
212
+ flex: 1;
213
+ min-width: 0;
214
+ }
215
+
216
+ .smart-card-title {
217
+ font-size: var(--text-title-lg);
218
+ font-weight: var(--weight-semibold);
219
+ color: var(--color-on-surface);
220
+ }
221
+
222
+ .smart-card-subtitle {
223
+ font-size: var(--text-body-sm);
224
+ color: var(--color-on-surface-variant);
225
+ margin-top: 2px;
226
+ }
227
+
228
+ .smart-card-body {
229
+ padding: 0;
230
+ }
231
+
232
+ .smart-card-row {
233
+ display: flex;
234
+ justify-content: space-between;
235
+ padding: var(--space-3) var(--space-4);
236
+ border-bottom: 1px solid var(--color-outline-variant);
237
+ }
238
+
239
+ .smart-card-row:last-child {
240
+ border-bottom: none;
241
+ }
242
+
243
+ .smart-card-label {
244
+ color: var(--color-on-surface-variant);
245
+ font-size: var(--text-body-sm);
246
+ }
247
+
248
+ .smart-card-value {
249
+ color: var(--color-on-surface);
250
+ font-weight: var(--weight-medium);
251
+ text-align: right;
252
+ }
253
+
254
+ /* Grid Component */
255
+ .smart-grid {
256
+ display: grid;
257
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
258
+ gap: var(--space-4);
259
+ }
260
+
261
+ .smart-grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
262
+ .smart-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
263
+ .smart-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
264
+
265
+ .grid-item {
266
+ background: var(--color-surface-container);
267
+ border-radius: var(--radius-md);
268
+ overflow: hidden;
269
+ border: 1px solid var(--color-outline-variant);
270
+ cursor: pointer;
271
+ transition: transform var(--duration-fast) var(--ease-standard),
272
+ box-shadow var(--duration-fast) var(--ease-standard);
273
+ }
274
+
275
+ .grid-item:hover {
276
+ transform: translateY(-2px);
277
+ box-shadow: var(--elevation-2);
278
+ }
279
+
280
+ .grid-item-image {
281
+ width: 100%;
282
+ aspect-ratio: 1;
283
+ object-fit: cover;
284
+ background: var(--color-surface-container-highest);
285
+ }
286
+
287
+ .grid-item-content {
288
+ padding: var(--space-3);
289
+ }
290
+
291
+ .grid-item-title {
292
+ font-weight: var(--weight-medium);
293
+ color: var(--color-on-surface);
294
+ white-space: nowrap;
295
+ overflow: hidden;
296
+ text-overflow: ellipsis;
297
+ }
298
+
299
+ .grid-item-detail {
300
+ font-size: var(--text-body-sm);
301
+ color: var(--color-on-surface-variant);
302
+ margin-top: var(--space-1);
303
+ }
304
+
305
+ /* Tree Component */
306
+ .smart-tree {
307
+ font-family: var(--font-mono);
308
+ font-size: var(--text-body-sm);
309
+ line-height: 1.6;
310
+ }
311
+
312
+ .tree-node {
313
+ margin-left: 0;
314
+ }
315
+
316
+ .tree-node-inner {
317
+ margin-left: var(--space-5);
318
+ }
319
+
320
+ .tree-key {
321
+ color: var(--color-on-surface-variant);
322
+ }
323
+
324
+ .tree-value {
325
+ color: var(--color-on-surface);
326
+ }
327
+
328
+ .tree-value.string { color: var(--color-success); }
329
+ .tree-value.number { color: var(--color-primary); }
330
+ .tree-value.boolean { color: var(--color-error); }
331
+ .tree-value.null { color: var(--color-on-surface-muted); }
332
+
333
+ .tree-toggle {
334
+ cursor: pointer;
335
+ user-select: none;
336
+ }
337
+
338
+ .tree-toggle::before {
339
+ content: '▼ ';
340
+ font-size: var(--text-label-sm);
341
+ }
342
+
343
+ .tree-toggle.collapsed::before {
344
+ content: '▶ ';
345
+ }
346
+
347
+ /* Chips Component */
348
+ .smart-chips {
349
+ display: flex;
350
+ flex-wrap: wrap;
351
+ gap: var(--space-2);
352
+ }
353
+
354
+ .chip {
355
+ display: inline-flex;
356
+ align-items: center;
357
+ padding: var(--space-1) var(--space-3);
358
+ border-radius: var(--radius-full);
359
+ background: var(--color-surface-container-highest);
360
+ color: var(--color-on-surface);
361
+ font-size: var(--text-body-sm);
362
+ }
363
+
364
+ .chip.clickable {
365
+ cursor: pointer;
366
+ transition: background var(--duration-fast) var(--ease-standard);
367
+ }
368
+
369
+ .chip.clickable:hover {
370
+ background: var(--color-surface-container-high);
371
+ }
372
+
373
+ /* Text Component */
374
+ .smart-text {
375
+ color: var(--color-on-surface);
376
+ line-height: 1.6;
377
+ }
378
+
379
+ .smart-text.large {
380
+ font-size: var(--text-display-sm);
381
+ font-weight: var(--weight-semibold);
382
+ }
383
+
384
+ .smart-text.muted {
385
+ color: var(--color-on-surface-variant);
386
+ }
387
+
388
+ /* JSON Syntax Highlighting */
389
+ .json-highlighted {
390
+ margin: 0;
391
+ font-family: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
392
+ font-size: 13px;
393
+ line-height: 1.5;
394
+ }
395
+
396
+ .json-key {
397
+ color: #9cdcfe;
398
+ }
399
+
400
+ .json-string {
401
+ color: #ce9178;
402
+ }
403
+
404
+ .json-number {
405
+ color: #b5cea8;
406
+ }
407
+
408
+ .json-boolean {
409
+ color: #569cd6;
410
+ }
411
+
412
+ .json-null {
413
+ color: #808080;
414
+ }
415
+ `;
416
+ }
417
+ /**
418
+ * Generate JavaScript for component renderers (to embed in HTML)
419
+ */
420
+ export function generateComponentsJS() {
421
+ return `
422
+ // Component Renderers
423
+
424
+ // JSON Syntax Highlighting
425
+ function syntaxHighlightJson(json) {
426
+ if (typeof json !== 'string') {
427
+ json = JSON.stringify(json, null, 2);
428
+ }
429
+ var result = '';
430
+ var i = 0;
431
+ while (i < json.length) {
432
+ var ch = json[i];
433
+ if (ch === '"') {
434
+ var start = i;
435
+ i++;
436
+ while (i < json.length && !(json[i] === '"' && json[i-1] !== String.fromCharCode(92))) i++;
437
+ i++;
438
+ var str = json.substring(start, i);
439
+ var rest = json.substring(i).trimStart();
440
+ if (rest[0] === ':') {
441
+ result += '<span class="json-key">' + escapeHtml(str) + '</span>';
442
+ } else {
443
+ result += '<span class="json-string">' + escapeHtml(str) + '</span>';
444
+ }
445
+ } else if (/[0-9-]/.test(ch)) {
446
+ var start = i;
447
+ while (i < json.length && /[0-9.eE+-]/.test(json[i])) i++;
448
+ result += '<span class="json-number">' + json.substring(start, i) + '</span>';
449
+ } else if (json.substring(i, i+4) === 'true') {
450
+ result += '<span class="json-boolean">true</span>';
451
+ i += 4;
452
+ } else if (json.substring(i, i+5) === 'false') {
453
+ result += '<span class="json-boolean">false</span>';
454
+ i += 5;
455
+ } else if (json.substring(i, i+4) === 'null') {
456
+ result += '<span class="json-null">null</span>';
457
+ i += 4;
458
+ } else {
459
+ result += ch;
460
+ i++;
461
+ }
462
+ }
463
+ return result;
464
+ }
465
+
466
+ function renderSmartResult(data, format, layoutHints) {
467
+ // Get layout type
468
+ const layout = selectLayout(data, format, layoutHints);
469
+
470
+ // Get field analysis
471
+ const mapping = analyzeFields(data);
472
+ const typeHints = detectFieldTypes(data);
473
+
474
+ // Merge with explicit hints
475
+ const finalMapping = { ...mapping, ...layoutHints };
476
+
477
+ // Render based on layout
478
+ switch (layout) {
479
+ case 'list':
480
+ return renderList(data, finalMapping, typeHints, layoutHints?.style, layoutHints?.accessory);
481
+ case 'card':
482
+ return renderCard(data, finalMapping, typeHints);
483
+ case 'grid':
484
+ return renderGrid(data, finalMapping, typeHints, layoutHints?.columns);
485
+ case 'tree':
486
+ return renderTree(data);
487
+ case 'chips':
488
+ return renderChips(data);
489
+ case 'kv':
490
+ return renderKeyValueTable(data);
491
+ case 'text':
492
+ return renderText(data);
493
+ case 'markdown':
494
+ return renderMarkdown(data);
495
+ case 'mermaid':
496
+ // Handle in parent (needs async)
497
+ return null;
498
+ case 'html':
499
+ // Raw HTML - return as-is (assumes data is HTML string)
500
+ return typeof data === 'string' ? data : (data?.html || String(data));
501
+ case 'code':
502
+ return '<pre class="code-block">' + escapeHtml(String(data)) + '</pre>';
503
+ case 'json':
504
+ default:
505
+ return '<pre class="json-highlighted">' + syntaxHighlightJson(data) + '</pre>';
506
+ }
507
+ }
508
+
509
+ function renderList(data, mapping, typeHints, style, accessory) {
510
+ if (!Array.isArray(data) || data.length === 0) {
511
+ return '<div class="smart-text muted">No items</div>';
512
+ }
513
+
514
+ const styleClass = style ? 'style-' + style : '';
515
+ const items = data.map(item => renderListItem(item, mapping, typeHints, accessory)).join('');
516
+
517
+ return '<div class="smart-list ' + styleClass + '">' + items + '</div>';
518
+ }
519
+
520
+ function renderListItem(item, mapping, typeHints, accessory) {
521
+ let html = '<div class="list-item">';
522
+
523
+ // Handle primitive items (strings, numbers, booleans)
524
+ if (typeof item !== 'object' || item === null) {
525
+ html += '<div class="list-item-content">';
526
+ html += '<div class="list-item-title">' + escapeHtml(String(item)) + '</div>';
527
+ html += '</div>';
528
+ if (accessory && accessory !== 'none') {
529
+ html += '<div class="list-item-accessory ' + accessory + '"></div>';
530
+ }
531
+ html += '</div>';
532
+ return html;
533
+ }
534
+
535
+ // Leading (icon/avatar)
536
+ if (mapping.icon && item[mapping.icon] !== undefined) {
537
+ const iconValue = item[mapping.icon];
538
+ const isEmoji = typeof iconValue === 'string' && iconValue.length <= 2;
539
+ const isImage = typeof iconValue === 'string' && /\\.(jpg|jpeg|png|gif|webp|svg)/i.test(iconValue);
540
+
541
+ if (isImage) {
542
+ html += '<div class="list-item-leading"><img src="' + escapeHtml(iconValue) + '" alt=""></div>';
543
+ } else {
544
+ html += '<div class="list-item-leading' + (isEmoji ? ' emoji' : '') + '">' + escapeHtml(String(iconValue)) + '</div>';
545
+ }
546
+ }
547
+
548
+ // Content (title + subtitle)
549
+ html += '<div class="list-item-content">';
550
+ if (mapping.title && item[mapping.title] !== undefined) {
551
+ html += '<div class="list-item-title">' + escapeHtml(String(item[mapping.title])) + '</div>';
552
+ }
553
+ if (mapping.subtitle && item[mapping.subtitle] !== undefined) {
554
+ const subtitleValue = item[mapping.subtitle];
555
+ const isEmail = typeHints.find(h => h.field === mapping.subtitle && h.type === 'email');
556
+ if (isEmail) {
557
+ html += '<div class="list-item-subtitle"><a href="mailto:' + escapeHtml(subtitleValue) + '">' + escapeHtml(subtitleValue) + '</a></div>';
558
+ } else {
559
+ html += '<div class="list-item-subtitle">' + escapeHtml(String(subtitleValue)) + '</div>';
560
+ }
561
+ }
562
+ html += '</div>';
563
+
564
+ // Trailing (detail + badge)
565
+ html += '<div class="list-item-trailing">';
566
+ if (mapping.detail && item[mapping.detail] !== undefined) {
567
+ html += '<span>' + renderFieldValue(item[mapping.detail], mapping.detail, typeHints) + '</span>';
568
+ }
569
+ if (mapping.badge && item[mapping.badge] !== undefined) {
570
+ const badgeValue = String(item[mapping.badge]).toLowerCase();
571
+ const statusClass = getStatusClass(badgeValue);
572
+ html += '<span class="list-item-badge ' + statusClass + '">' + escapeHtml(String(item[mapping.badge])) + '</span>';
573
+ }
574
+ html += '</div>';
575
+
576
+ // Accessory
577
+ if (accessory && accessory !== 'none') {
578
+ html += '<div class="list-item-accessory ' + accessory + '"></div>';
579
+ }
580
+
581
+ html += '</div>';
582
+ return html;
583
+ }
584
+
585
+ function renderCard(data, mapping, typeHints) {
586
+ if (!data || typeof data !== 'object') {
587
+ return renderText(data);
588
+ }
589
+
590
+ let html = '<div class="smart-card">';
591
+
592
+ // Header (icon + title + subtitle)
593
+ const hasHeader = mapping.icon || mapping.title || mapping.subtitle;
594
+ if (hasHeader) {
595
+ html += '<div class="smart-card-header">';
596
+
597
+ if (mapping.icon && data[mapping.icon] !== undefined) {
598
+ const iconValue = data[mapping.icon];
599
+ const isImage = typeof iconValue === 'string' && /\\.(jpg|jpeg|png|gif|webp|svg)/i.test(iconValue);
600
+ if (isImage) {
601
+ html += '<div class="smart-card-icon"><img src="' + escapeHtml(iconValue) + '" alt=""></div>';
602
+ } else {
603
+ html += '<div class="smart-card-icon">' + escapeHtml(String(iconValue)) + '</div>';
604
+ }
605
+ }
606
+
607
+ html += '<div class="smart-card-header-content">';
608
+ if (mapping.title && data[mapping.title] !== undefined) {
609
+ html += '<div class="smart-card-title">' + escapeHtml(String(data[mapping.title])) + '</div>';
610
+ }
611
+ if (mapping.subtitle && data[mapping.subtitle] !== undefined) {
612
+ html += '<div class="smart-card-subtitle">' + escapeHtml(String(data[mapping.subtitle])) + '</div>';
613
+ }
614
+ html += '</div></div>';
615
+ }
616
+
617
+ // Body (remaining fields as key-value rows)
618
+ const excludeFields = new Set([mapping.icon, mapping.title, mapping.subtitle, mapping.id].filter(Boolean));
619
+ const bodyFields = Object.keys(data).filter(k => !excludeFields.has(k));
620
+
621
+ if (bodyFields.length > 0) {
622
+ html += '<div class="smart-card-body">';
623
+ for (const field of bodyFields) {
624
+ html += '<div class="smart-card-row">';
625
+ html += '<span class="smart-card-label">' + formatFieldLabel(field) + '</span>';
626
+ html += '<span class="smart-card-value">' + renderFieldValue(data[field], field, typeHints) + '</span>';
627
+ html += '</div>';
628
+ }
629
+ html += '</div>';
630
+ }
631
+
632
+ html += '</div>';
633
+ return html;
634
+ }
635
+
636
+ function renderGrid(data, mapping, typeHints, columns) {
637
+ if (!Array.isArray(data) || data.length === 0) {
638
+ return '<div class="smart-text muted">No items</div>';
639
+ }
640
+
641
+ const colsClass = columns ? 'cols-' + columns : '';
642
+ let html = '<div class="smart-grid ' + colsClass + '">';
643
+
644
+ for (const item of data) {
645
+ html += '<div class="grid-item">';
646
+
647
+ // Image
648
+ const imageField = mapping.image || Object.keys(item).find(k => /image|photo|thumbnail/i.test(k));
649
+ if (imageField && item[imageField]) {
650
+ html += '<img class="grid-item-image" src="' + escapeHtml(item[imageField]) + '" alt="">';
651
+ } else {
652
+ html += '<div class="grid-item-image"></div>';
653
+ }
654
+
655
+ // Content
656
+ html += '<div class="grid-item-content">';
657
+ if (mapping.title && item[mapping.title] !== undefined) {
658
+ html += '<div class="grid-item-title">' + escapeHtml(String(item[mapping.title])) + '</div>';
659
+ }
660
+ if (mapping.detail && item[mapping.detail] !== undefined) {
661
+ html += '<div class="grid-item-detail">' + renderFieldValue(item[mapping.detail], mapping.detail, typeHints) + '</div>';
662
+ }
663
+ html += '</div></div>';
664
+ }
665
+
666
+ html += '</div>';
667
+ return html;
668
+ }
669
+
670
+ function renderTree(data, depth = 0) {
671
+ if (data === null) return '<span class="tree-value null">null</span>';
672
+ if (data === undefined) return '<span class="tree-value null">undefined</span>';
673
+
674
+ if (typeof data !== 'object') {
675
+ const typeClass = typeof data;
676
+ if (typeof data === 'string') {
677
+ return '<span class="tree-value string">"' + escapeHtml(data) + '"</span>';
678
+ }
679
+ return '<span class="tree-value ' + typeClass + '">' + escapeHtml(String(data)) + '</span>';
680
+ }
681
+
682
+ if (Array.isArray(data)) {
683
+ if (data.length === 0) return '<span class="tree-value">[]</span>';
684
+ let html = '<div class="tree-node">[';
685
+ html += '<div class="tree-node-inner">';
686
+ data.forEach((item, i) => {
687
+ html += '<div>' + renderTree(item, depth + 1);
688
+ if (i < data.length - 1) html += ',';
689
+ html += '</div>';
690
+ });
691
+ html += '</div>]</div>';
692
+ return html;
693
+ }
694
+
695
+ const keys = Object.keys(data);
696
+ if (keys.length === 0) return '<span class="tree-value">{}</span>';
697
+
698
+ let html = '<div class="tree-node">{';
699
+ html += '<div class="tree-node-inner">';
700
+ keys.forEach((key, i) => {
701
+ html += '<div><span class="tree-key">' + escapeHtml(key) + '</span>: ' + renderTree(data[key], depth + 1);
702
+ if (i < keys.length - 1) html += ',';
703
+ html += '</div>';
704
+ });
705
+ html += '</div>}</div>';
706
+ return html;
707
+ }
708
+
709
+ function renderChips(data) {
710
+ if (!Array.isArray(data) || data.length === 0) {
711
+ return '<div class="smart-text muted">No items</div>';
712
+ }
713
+
714
+ const chips = data.map(item => '<span class="chip">' + escapeHtml(String(item)) + '</span>').join('');
715
+ return '<div class="smart-chips">' + chips + '</div>';
716
+ }
717
+
718
+ function renderText(data) {
719
+ if (data === null || data === undefined) {
720
+ return '<div class="smart-text muted">—</div>';
721
+ }
722
+
723
+ const text = String(data);
724
+
725
+ // Large display for short text/numbers
726
+ if (text.length < 20 && !text.includes('\\n')) {
727
+ return '<div class="smart-text large">' + escapeHtml(text) + '</div>';
728
+ }
729
+
730
+ return '<div class="smart-text">' + escapeHtml(text) + '</div>';
731
+ }
732
+
733
+ function renderFieldValue(value, field, typeHints) {
734
+ if (value === null || value === undefined) return '—';
735
+ if (typeof value === 'boolean') return value ? '✓' : '✗';
736
+
737
+ const hint = typeHints.find(h => h.field === field);
738
+
739
+ if (hint) {
740
+ switch (hint.type) {
741
+ case 'email':
742
+ return '<a href="mailto:' + escapeHtml(value) + '">' + escapeHtml(value) + '</a>';
743
+ case 'url':
744
+ return '<a href="' + escapeHtml(value) + '" target="_blank">' + escapeHtml(value) + '</a>';
745
+ case 'date':
746
+ try {
747
+ return new Date(value).toLocaleDateString();
748
+ } catch {
749
+ return escapeHtml(String(value));
750
+ }
751
+ case 'currency':
752
+ if (typeof value === 'number') return '$' + value.toFixed(2);
753
+ return escapeHtml(String(value));
754
+ }
755
+ }
756
+
757
+ if (typeof value === 'object') {
758
+ return escapeHtml(JSON.stringify(value));
759
+ }
760
+
761
+ return escapeHtml(String(value));
762
+ }
763
+
764
+ function getStatusClass(value) {
765
+ const lower = value.toLowerCase();
766
+ if (/active|success|complete|done|enabled|yes|true/.test(lower)) return 'status-active';
767
+ if (/inactive|error|failed|disabled|no|false/.test(lower)) return 'status-inactive';
768
+ if (/pending|warning|waiting|processing/.test(lower)) return 'status-pending';
769
+ return '';
770
+ }
771
+ `;
772
+ }
773
+ //# sourceMappingURL=components.js.map