@portel/photon 1.18.0 → 1.20.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 (238) hide show
  1. package/dist/auto-ui/beam/routes/api-browse.d.ts.map +1 -1
  2. package/dist/auto-ui/beam/routes/api-browse.js +16 -4
  3. package/dist/auto-ui/beam/routes/api-browse.js.map +1 -1
  4. package/dist/auto-ui/beam/routes/api-config.js +4 -4
  5. package/dist/auto-ui/beam/routes/api-config.js.map +1 -1
  6. package/dist/auto-ui/beam/routes/api-marketplace.d.ts.map +1 -1
  7. package/dist/auto-ui/beam/routes/api-marketplace.js +14 -1
  8. package/dist/auto-ui/beam/routes/api-marketplace.js.map +1 -1
  9. package/dist/auto-ui/beam.d.ts.map +1 -1
  10. package/dist/auto-ui/beam.js +196 -77
  11. package/dist/auto-ui/beam.js.map +1 -1
  12. package/dist/auto-ui/bridge/index.d.ts.map +1 -1
  13. package/dist/auto-ui/bridge/index.js +17 -0
  14. package/dist/auto-ui/bridge/index.js.map +1 -1
  15. package/dist/auto-ui/streamable-http-transport.d.ts +1 -0
  16. package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
  17. package/dist/auto-ui/streamable-http-transport.js +64 -16
  18. package/dist/auto-ui/streamable-http-transport.js.map +1 -1
  19. package/dist/auto-ui/types.d.ts +12 -0
  20. package/dist/auto-ui/types.d.ts.map +1 -1
  21. package/dist/auto-ui/types.js.map +1 -1
  22. package/dist/beam-form.bundle.js +49 -6
  23. package/dist/beam-form.bundle.js.map +2 -2
  24. package/dist/beam.bundle.js +2090 -512
  25. package/dist/beam.bundle.js.map +4 -4
  26. package/dist/capability-negotiator.d.ts +67 -0
  27. package/dist/capability-negotiator.d.ts.map +1 -0
  28. package/dist/capability-negotiator.js +104 -0
  29. package/dist/capability-negotiator.js.map +1 -0
  30. package/dist/channel-manager.d.ts +122 -0
  31. package/dist/channel-manager.d.ts.map +1 -0
  32. package/dist/channel-manager.js +266 -0
  33. package/dist/channel-manager.js.map +1 -0
  34. package/dist/claude-code-plugin.js +1 -1
  35. package/dist/cli/commands/beam.d.ts.map +1 -1
  36. package/dist/cli/commands/beam.js +8 -2
  37. package/dist/cli/commands/beam.js.map +1 -1
  38. package/dist/cli/commands/changelog.d.ts +9 -0
  39. package/dist/cli/commands/changelog.d.ts.map +1 -0
  40. package/dist/cli/commands/changelog.js +133 -0
  41. package/dist/cli/commands/changelog.js.map +1 -0
  42. package/dist/cli/commands/maker.d.ts.map +1 -1
  43. package/dist/cli/commands/maker.js +23 -2
  44. package/dist/cli/commands/maker.js.map +1 -1
  45. package/dist/cli/commands/mcp.d.ts.map +1 -1
  46. package/dist/cli/commands/mcp.js +53 -0
  47. package/dist/cli/commands/mcp.js.map +1 -1
  48. package/dist/cli/commands/package.d.ts.map +1 -1
  49. package/dist/cli/commands/package.js +43 -9
  50. package/dist/cli/commands/package.js.map +1 -1
  51. package/dist/cli/commands/run.d.ts.map +1 -1
  52. package/dist/cli/commands/run.js +1 -0
  53. package/dist/cli/commands/run.js.map +1 -1
  54. package/dist/cli/commands/update.d.ts +3 -2
  55. package/dist/cli/commands/update.d.ts.map +1 -1
  56. package/dist/cli/commands/update.js +50 -43
  57. package/dist/cli/commands/update.js.map +1 -1
  58. package/dist/cli/index.d.ts.map +1 -1
  59. package/dist/cli/index.js +16 -2
  60. package/dist/cli/index.js.map +1 -1
  61. package/dist/cli-alias.js +1 -1
  62. package/dist/cli-alias.js.map +1 -1
  63. package/dist/context-store.d.ts +23 -33
  64. package/dist/context-store.d.ts.map +1 -1
  65. package/dist/context-store.js +147 -97
  66. package/dist/context-store.js.map +1 -1
  67. package/dist/context.d.ts +15 -10
  68. package/dist/context.d.ts.map +1 -1
  69. package/dist/context.js +37 -13
  70. package/dist/context.js.map +1 -1
  71. package/dist/daemon/client.d.ts.map +1 -1
  72. package/dist/daemon/client.js +12 -0
  73. package/dist/daemon/client.js.map +1 -1
  74. package/dist/daemon/server.js +34 -51
  75. package/dist/daemon/server.js.map +1 -1
  76. package/dist/daemon/worker-manager.d.ts.map +1 -1
  77. package/dist/daemon/worker-manager.js +21 -7
  78. package/dist/daemon/worker-manager.js.map +1 -1
  79. package/dist/data-migration.d.ts +27 -0
  80. package/dist/data-migration.d.ts.map +1 -0
  81. package/dist/data-migration.js +307 -0
  82. package/dist/data-migration.js.map +1 -0
  83. package/dist/editor-support/docblock-tag-catalog.d.ts.map +1 -1
  84. package/dist/editor-support/docblock-tag-catalog.js +6 -0
  85. package/dist/editor-support/docblock-tag-catalog.js.map +1 -1
  86. package/dist/loader.d.ts +13 -0
  87. package/dist/loader.d.ts.map +1 -1
  88. package/dist/loader.js +169 -22
  89. package/dist/loader.js.map +1 -1
  90. package/dist/marketplace-manager.d.ts +6 -0
  91. package/dist/marketplace-manager.d.ts.map +1 -1
  92. package/dist/marketplace-manager.js +185 -62
  93. package/dist/marketplace-manager.js.map +1 -1
  94. package/dist/namespace-migration.d.ts +1 -0
  95. package/dist/namespace-migration.d.ts.map +1 -1
  96. package/dist/namespace-migration.js +86 -0
  97. package/dist/namespace-migration.js.map +1 -1
  98. package/dist/photon-cli-runner.d.ts.map +1 -1
  99. package/dist/photon-cli-runner.js +47 -21
  100. package/dist/photon-cli-runner.js.map +1 -1
  101. package/dist/photon-doc-extractor.d.ts +1 -0
  102. package/dist/photon-doc-extractor.d.ts.map +1 -1
  103. package/dist/photon-doc-extractor.js +6 -0
  104. package/dist/photon-doc-extractor.js.map +1 -1
  105. package/dist/readme-syncer.d.ts.map +1 -1
  106. package/dist/readme-syncer.js +6 -1
  107. package/dist/readme-syncer.js.map +1 -1
  108. package/dist/resource-server.d.ts +105 -0
  109. package/dist/resource-server.d.ts.map +1 -0
  110. package/dist/resource-server.js +723 -0
  111. package/dist/resource-server.js.map +1 -0
  112. package/dist/serv/auth/jwt.d.ts +2 -0
  113. package/dist/serv/auth/jwt.d.ts.map +1 -1
  114. package/dist/serv/auth/jwt.js +11 -5
  115. package/dist/serv/auth/jwt.js.map +1 -1
  116. package/dist/serv/vault/token-vault.d.ts +2 -0
  117. package/dist/serv/vault/token-vault.d.ts.map +1 -1
  118. package/dist/serv/vault/token-vault.js +6 -0
  119. package/dist/serv/vault/token-vault.js.map +1 -1
  120. package/dist/server.d.ts +30 -119
  121. package/dist/server.d.ts.map +1 -1
  122. package/dist/server.js +252 -1122
  123. package/dist/server.js.map +1 -1
  124. package/dist/shared/audit.d.ts.map +1 -1
  125. package/dist/shared/audit.js +11 -4
  126. package/dist/shared/audit.js.map +1 -1
  127. package/dist/shared/security.d.ts +10 -0
  128. package/dist/shared/security.d.ts.map +1 -1
  129. package/dist/shared/security.js +27 -0
  130. package/dist/shared/security.js.map +1 -1
  131. package/dist/task-executor.d.ts +69 -0
  132. package/dist/task-executor.d.ts.map +1 -0
  133. package/dist/task-executor.js +182 -0
  134. package/dist/task-executor.js.map +1 -0
  135. package/dist/tasks/store.d.ts.map +1 -1
  136. package/dist/tasks/store.js +6 -2
  137. package/dist/tasks/store.js.map +1 -1
  138. package/dist/types/photon-instance.d.ts +50 -0
  139. package/dist/types/photon-instance.d.ts.map +1 -0
  140. package/dist/types/photon-instance.js +9 -0
  141. package/dist/types/photon-instance.js.map +1 -0
  142. package/dist/types/server-types.d.ts +61 -0
  143. package/dist/types/server-types.d.ts.map +1 -0
  144. package/dist/types/server-types.js +8 -0
  145. package/dist/types/server-types.js.map +1 -0
  146. package/dist/version-notify.d.ts +27 -0
  147. package/dist/version-notify.d.ts.map +1 -0
  148. package/dist/version-notify.js +142 -0
  149. package/dist/version-notify.js.map +1 -0
  150. package/package.json +3 -3
  151. package/dist/auto-ui/bridge/openai-shim.d.ts +0 -20
  152. package/dist/auto-ui/bridge/openai-shim.d.ts.map +0 -1
  153. package/dist/auto-ui/bridge/openai-shim.js +0 -231
  154. package/dist/auto-ui/bridge/openai-shim.js.map +0 -1
  155. package/dist/auto-ui/bridge/photon-app.d.ts +0 -162
  156. package/dist/auto-ui/bridge/photon-app.d.ts.map +0 -1
  157. package/dist/auto-ui/bridge/photon-app.js +0 -460
  158. package/dist/auto-ui/bridge/photon-app.js.map +0 -1
  159. package/dist/auto-ui/daemon-tools.d.ts +0 -45
  160. package/dist/auto-ui/daemon-tools.d.ts.map +0 -1
  161. package/dist/auto-ui/daemon-tools.js +0 -581
  162. package/dist/auto-ui/daemon-tools.js.map +0 -1
  163. package/dist/auto-ui/design-system/index.d.ts +0 -21
  164. package/dist/auto-ui/design-system/index.d.ts.map +0 -1
  165. package/dist/auto-ui/design-system/index.js +0 -27
  166. package/dist/auto-ui/design-system/index.js.map +0 -1
  167. package/dist/auto-ui/design-system/transaction-ui.d.ts +0 -70
  168. package/dist/auto-ui/design-system/transaction-ui.d.ts.map +0 -1
  169. package/dist/auto-ui/design-system/transaction-ui.js +0 -982
  170. package/dist/auto-ui/design-system/transaction-ui.js.map +0 -1
  171. package/dist/auto-ui/playground-server.d.ts +0 -7
  172. package/dist/auto-ui/playground-server.d.ts.map +0 -1
  173. package/dist/auto-ui/playground-server.js +0 -840
  174. package/dist/auto-ui/playground-server.js.map +0 -1
  175. package/dist/auto-ui/rendering/components.d.ts +0 -29
  176. package/dist/auto-ui/rendering/components.d.ts.map +0 -1
  177. package/dist/auto-ui/rendering/components.js +0 -1341
  178. package/dist/auto-ui/rendering/components.js.map +0 -1
  179. package/dist/auto-ui/rendering/field-analyzer.d.ts +0 -104
  180. package/dist/auto-ui/rendering/field-analyzer.d.ts.map +0 -1
  181. package/dist/auto-ui/rendering/field-analyzer.js +0 -447
  182. package/dist/auto-ui/rendering/field-analyzer.js.map +0 -1
  183. package/dist/auto-ui/rendering/field-renderers.d.ts +0 -64
  184. package/dist/auto-ui/rendering/field-renderers.d.ts.map +0 -1
  185. package/dist/auto-ui/rendering/field-renderers.js +0 -317
  186. package/dist/auto-ui/rendering/field-renderers.js.map +0 -1
  187. package/dist/auto-ui/rendering/index.d.ts +0 -28
  188. package/dist/auto-ui/rendering/index.d.ts.map +0 -1
  189. package/dist/auto-ui/rendering/index.js +0 -60
  190. package/dist/auto-ui/rendering/index.js.map +0 -1
  191. package/dist/auto-ui/rendering/layout-selector.d.ts +0 -60
  192. package/dist/auto-ui/rendering/layout-selector.d.ts.map +0 -1
  193. package/dist/auto-ui/rendering/layout-selector.js +0 -476
  194. package/dist/auto-ui/rendering/layout-selector.js.map +0 -1
  195. package/dist/markdown-utils.d.ts +0 -8
  196. package/dist/markdown-utils.d.ts.map +0 -1
  197. package/dist/markdown-utils.js +0 -64
  198. package/dist/markdown-utils.js.map +0 -1
  199. package/dist/mcp-client.d.ts +0 -9
  200. package/dist/mcp-client.d.ts.map +0 -1
  201. package/dist/mcp-client.js +0 -11
  202. package/dist/mcp-client.js.map +0 -1
  203. package/dist/mcp-elicitation.d.ts +0 -32
  204. package/dist/mcp-elicitation.d.ts.map +0 -1
  205. package/dist/mcp-elicitation.js +0 -26
  206. package/dist/mcp-elicitation.js.map +0 -1
  207. package/dist/photons/builder-compass.photon.d.ts +0 -167
  208. package/dist/photons/builder-compass.photon.d.ts.map +0 -1
  209. package/dist/photons/builder-compass.photon.js +0 -816
  210. package/dist/photons/builder-compass.photon.js.map +0 -1
  211. package/dist/photons/builder-compass.photon.ts +0 -1129
  212. package/dist/photons/docs/ui/docs.html +0 -441
  213. package/dist/photons/docs.photon.d.ts +0 -237
  214. package/dist/photons/docs.photon.d.ts.map +0 -1
  215. package/dist/photons/docs.photon.js +0 -483
  216. package/dist/photons/docs.photon.js.map +0 -1
  217. package/dist/photons/docs.photon.ts +0 -536
  218. package/dist/photons/slides.photon.d.ts +0 -212
  219. package/dist/photons/slides.photon.d.ts.map +0 -1
  220. package/dist/photons/slides.photon.js +0 -355
  221. package/dist/photons/slides.photon.js.map +0 -1
  222. package/dist/photons/slides.photon.ts +0 -370
  223. package/dist/photons/spreadsheet/ui/spreadsheet.html +0 -779
  224. package/dist/photons/spreadsheet.photon.d.ts +0 -554
  225. package/dist/photons/spreadsheet.photon.d.ts.map +0 -1
  226. package/dist/photons/spreadsheet.photon.js +0 -1050
  227. package/dist/photons/spreadsheet.photon.js.map +0 -1
  228. package/dist/photons/spreadsheet.photon.ts +0 -1239
  229. package/dist/photons/ui/builder-compass.html +0 -1199
  230. package/dist/photons/ui/builder-compass.photon.html +0 -380
  231. package/dist/security-scanner.d.ts +0 -52
  232. package/dist/security-scanner.d.ts.map +0 -1
  233. package/dist/security-scanner.js +0 -181
  234. package/dist/security-scanner.js.map +0 -1
  235. package/dist/shared/performance.d.ts +0 -65
  236. package/dist/shared/performance.d.ts.map +0 -1
  237. package/dist/shared/performance.js +0 -136
  238. package/dist/shared/performance.js.map +0 -1
@@ -1,1341 +0,0 @@
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
- /* Metric Component */
389
- .smart-metric {
390
- text-align: center;
391
- padding: var(--space-5) var(--space-4);
392
- }
393
-
394
- .smart-metric-value {
395
- font-size: 3rem;
396
- font-weight: 700;
397
- color: var(--color-on-surface);
398
- line-height: 1.1;
399
- font-variant-numeric: tabular-nums;
400
- }
401
-
402
- .smart-metric-label {
403
- font-size: var(--text-body-sm);
404
- color: var(--color-on-surface-variant);
405
- text-transform: uppercase;
406
- letter-spacing: 0.08em;
407
- margin-top: var(--space-1);
408
- }
409
-
410
- .smart-metric-delta {
411
- display: inline-block;
412
- padding: var(--space-1) var(--space-3);
413
- border-radius: var(--radius-full);
414
- font-weight: 600;
415
- margin-top: var(--space-2);
416
- }
417
-
418
- .smart-metric-delta.up { color: var(--color-success); }
419
- .smart-metric-delta.down { color: var(--color-error); }
420
-
421
- /* Gauge Component */
422
- .smart-gauge {
423
- text-align: center;
424
- padding: var(--space-4);
425
- }
426
-
427
- /* Timeline Component */
428
- .smart-timeline {
429
- position: relative;
430
- padding-left: var(--space-6);
431
- }
432
-
433
- .smart-timeline::before {
434
- content: '';
435
- position: absolute;
436
- left: calc(var(--space-2) + 4px);
437
- top: 0;
438
- bottom: 0;
439
- width: 2px;
440
- background: var(--color-outline-variant);
441
- }
442
-
443
- .timeline-item {
444
- position: relative;
445
- padding: var(--space-2) 0 var(--space-2) var(--space-4);
446
- }
447
-
448
- .timeline-item::before {
449
- content: '';
450
- position: absolute;
451
- left: calc(-1 * var(--space-4));
452
- top: calc(var(--space-2) + 6px);
453
- width: 10px;
454
- height: 10px;
455
- border-radius: 50%;
456
- background: var(--color-primary);
457
- border: 2px solid var(--color-surface);
458
- }
459
-
460
- .timeline-item-title {
461
- font-weight: var(--weight-semibold);
462
- color: var(--color-on-surface);
463
- }
464
-
465
- .timeline-item-time {
466
- font-size: var(--text-label-sm);
467
- color: var(--color-on-surface-variant);
468
- }
469
-
470
- .timeline-item-description {
471
- font-size: var(--text-body-sm);
472
- color: var(--color-on-surface-variant);
473
- margin-top: var(--space-1);
474
- }
475
-
476
- /* Dashboard Component */
477
- .smart-dashboard {
478
- display: grid;
479
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
480
- gap: var(--space-4);
481
- }
482
-
483
- .dashboard-panel {
484
- background: var(--color-surface-container);
485
- border: 1px solid var(--color-outline-variant);
486
- border-radius: var(--radius-md);
487
- overflow: hidden;
488
- }
489
-
490
- .dashboard-panel-header {
491
- padding: var(--space-2) var(--space-3);
492
- font-size: var(--text-label-sm);
493
- font-weight: var(--weight-semibold);
494
- color: var(--color-on-surface-variant);
495
- text-transform: uppercase;
496
- letter-spacing: 0.06em;
497
- border-bottom: 1px solid var(--color-outline-variant);
498
- }
499
-
500
- .dashboard-panel-content {
501
- padding: var(--space-2);
502
- }
503
-
504
- /* Cart Component */
505
- .smart-cart-item {
506
- display: flex;
507
- align-items: center;
508
- gap: 12px;
509
- padding: 8px 12px;
510
- border-bottom: 1px solid var(--color-outline-variant, #334155);
511
- }
512
-
513
- .smart-cart-item:last-of-type {
514
- border-bottom: none;
515
- }
516
-
517
- .smart-cart-item-image {
518
- width: 40px;
519
- height: 40px;
520
- border-radius: 4px;
521
- object-fit: cover;
522
- flex-shrink: 0;
523
- }
524
-
525
- .smart-cart-item-info {
526
- flex: 1;
527
- min-width: 0;
528
- }
529
-
530
- .smart-cart-item-name {
531
- font-weight: 500;
532
- }
533
-
534
- .smart-cart-qty {
535
- padding: 2px 8px;
536
- background: rgba(255,255,255,0.05);
537
- border-radius: 4px;
538
- font-size: 0.8rem;
539
- color: #94a3b8;
540
- }
541
-
542
- .smart-cart-line-total {
543
- font-weight: 600;
544
- font-variant-numeric: tabular-nums;
545
- min-width: 60px;
546
- text-align: right;
547
- }
548
-
549
- .smart-cart-divider {
550
- height: 1px;
551
- background: var(--color-outline-variant, #334155);
552
- margin: 8px 0;
553
- }
554
-
555
- .smart-cart-summary-row {
556
- display: flex;
557
- justify-content: space-between;
558
- padding: 4px 12px;
559
- font-size: 0.9rem;
560
- }
561
-
562
- .smart-cart-summary-row.total {
563
- font-weight: 700;
564
- font-size: 1rem;
565
- padding-top: 8px;
566
- border-top: 1px solid var(--color-outline-variant, #334155);
567
- margin-top: 4px;
568
- }
569
-
570
- /* Panels Container */
571
- .smart-panels {
572
- display: grid;
573
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
574
- gap: 16px;
575
- }
576
-
577
- .smart-panels.cols-2 { grid-template-columns: repeat(2, 1fr); }
578
- .smart-panels.cols-3 { grid-template-columns: repeat(3, 1fr); }
579
- .smart-panels.cols-4 { grid-template-columns: repeat(4, 1fr); }
580
-
581
- .smart-panel {
582
- border: 1px solid var(--color-outline-variant, #334155);
583
- border-radius: 8px;
584
- overflow: hidden;
585
- }
586
-
587
- .smart-panel-header {
588
- padding: 8px 12px;
589
- font-size: 0.75rem;
590
- font-weight: 600;
591
- color: #64748b;
592
- text-transform: uppercase;
593
- letter-spacing: 0.06em;
594
- border-bottom: 1px solid var(--color-outline-variant, #334155);
595
- }
596
-
597
- .smart-panel-content {
598
- padding: 8px;
599
- }
600
-
601
- /* Tabs Container */
602
- .smart-tabs-bar {
603
- display: flex;
604
- border-bottom: 1px solid var(--color-outline-variant, #334155);
605
- margin-bottom: 12px;
606
- }
607
-
608
- .smart-tab {
609
- padding: 8px 16px;
610
- border-bottom: 2px solid transparent;
611
- color: #64748b;
612
- font-weight: 500;
613
- cursor: pointer;
614
- }
615
-
616
- .smart-tab.active {
617
- color: #6366f1;
618
- border-bottom-color: #6366f1;
619
- }
620
-
621
- .smart-tab-content { display: none; }
622
- .smart-tab-content.active { display: block; }
623
-
624
- /* Accordion Container */
625
- .smart-accordion {
626
- border: 1px solid var(--color-outline-variant, #334155);
627
- border-radius: 8px;
628
- overflow: hidden;
629
- }
630
-
631
- .smart-accordion-header {
632
- display: flex;
633
- align-items: center;
634
- justify-content: space-between;
635
- padding: 8px 12px;
636
- cursor: pointer;
637
- background: rgba(255,255,255,0.02);
638
- font-weight: 500;
639
- border-bottom: 1px solid var(--color-outline-variant, #334155);
640
- }
641
-
642
- .smart-accordion-header:last-child { border-bottom: none; }
643
- .smart-accordion-body { display: none; padding: 8px 12px; }
644
- .smart-accordion-body.expanded { display: block; }
645
-
646
- /* Stack Container */
647
- .smart-stack {
648
- display: flex;
649
- flex-direction: column;
650
- gap: 12px;
651
- }
652
-
653
- .smart-stack-item {
654
- border: 1px solid var(--color-outline-variant, #334155);
655
- border-radius: 8px;
656
- overflow: hidden;
657
- }
658
-
659
- .smart-stack-label {
660
- padding: 6px 12px;
661
- font-size: 0.75rem;
662
- font-weight: 600;
663
- color: #64748b;
664
- text-transform: uppercase;
665
- letter-spacing: 0.06em;
666
- border-bottom: 1px solid var(--color-outline-variant, #334155);
667
- }
668
-
669
- .smart-stack-content {
670
- padding: 8px;
671
- }
672
-
673
- /* Columns Container */
674
- .smart-columns {
675
- display: grid;
676
- gap: 16px;
677
- }
678
-
679
- .smart-columns.cols-2 { grid-template-columns: repeat(2, 1fr); }
680
- .smart-columns.cols-3 { grid-template-columns: repeat(3, 1fr); }
681
- .smart-columns.cols-4 { grid-template-columns: repeat(4, 1fr); }
682
-
683
- /* JSON Syntax Highlighting */
684
- .json-highlighted {
685
- margin: 0;
686
- font-family: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
687
- font-size: 13px;
688
- line-height: 1.5;
689
- }
690
-
691
- .json-key {
692
- color: #9cdcfe;
693
- }
694
-
695
- .json-string {
696
- color: #ce9178;
697
- }
698
-
699
- .json-number {
700
- color: #b5cea8;
701
- }
702
-
703
- .json-boolean {
704
- color: #569cd6;
705
- }
706
-
707
- .json-null {
708
- color: #808080;
709
- }
710
- `;
711
- }
712
- /**
713
- * Generate JavaScript for component renderers (to embed in HTML)
714
- */
715
- export function generateComponentsJS() {
716
- return `
717
- // Component Renderers
718
-
719
- // JSON Syntax Highlighting
720
- function syntaxHighlightJson(json) {
721
- if (typeof json !== 'string') {
722
- json = JSON.stringify(json, null, 2);
723
- }
724
- var result = '';
725
- var i = 0;
726
- while (i < json.length) {
727
- var ch = json[i];
728
- if (ch === '"') {
729
- var start = i;
730
- i++;
731
- while (i < json.length && !(json[i] === '"' && json[i-1] !== String.fromCharCode(92))) i++;
732
- i++;
733
- var str = json.substring(start, i);
734
- var rest = json.substring(i).trimStart();
735
- if (rest[0] === ':') {
736
- result += '<span class="json-key">' + escapeHtml(str) + '</span>';
737
- } else {
738
- result += '<span class="json-string">' + escapeHtml(str) + '</span>';
739
- }
740
- } else if (/[0-9-]/.test(ch)) {
741
- var start = i;
742
- while (i < json.length && /[0-9.eE+-]/.test(json[i])) i++;
743
- result += '<span class="json-number">' + json.substring(start, i) + '</span>';
744
- } else if (json.substring(i, i+4) === 'true') {
745
- result += '<span class="json-boolean">true</span>';
746
- i += 4;
747
- } else if (json.substring(i, i+5) === 'false') {
748
- result += '<span class="json-boolean">false</span>';
749
- i += 5;
750
- } else if (json.substring(i, i+4) === 'null') {
751
- result += '<span class="json-null">null</span>';
752
- i += 4;
753
- } else {
754
- result += ch;
755
- i++;
756
- }
757
- }
758
- return result;
759
- }
760
-
761
- function renderSmartResult(data, format, layoutHints) {
762
- // Get layout type
763
- const layout = selectLayout(data, format, layoutHints);
764
-
765
- // Get field analysis
766
- const mapping = analyzeFields(data);
767
- const typeHints = detectFieldTypes(data);
768
-
769
- // Merge with explicit hints
770
- const finalMapping = { ...mapping, ...layoutHints };
771
-
772
- // Render based on layout
773
- switch (layout) {
774
- case 'list':
775
- return renderList(data, finalMapping, typeHints, layoutHints?.style, layoutHints?.accessory);
776
- case 'card':
777
- return renderCard(data, finalMapping, typeHints);
778
- case 'grid':
779
- return renderGrid(data, finalMapping, typeHints, layoutHints?.columns);
780
- case 'tree':
781
- return renderTree(data);
782
- case 'chips':
783
- return renderChips(data);
784
- case 'kv':
785
- return renderKeyValueTable(data);
786
- case 'text':
787
- return renderText(data);
788
- case 'markdown':
789
- return renderMarkdown(data);
790
- case 'mermaid':
791
- // Handle in parent (needs async)
792
- return null;
793
- case 'html':
794
- // Raw HTML - return as-is (assumes data is HTML string)
795
- return typeof data === 'string' ? data : (data?.html || String(data));
796
- case 'code':
797
- return '<pre class="code-block">' + escapeHtml(String(data)) + '</pre>';
798
- case 'metric':
799
- return renderMetric(data);
800
- case 'gauge':
801
- return renderGauge(data);
802
- case 'timeline':
803
- return renderTimeline(data);
804
- case 'dashboard':
805
- return renderDashboard(data);
806
- case 'cart':
807
- return renderCart(data);
808
- case 'panels':
809
- return renderPanels(data, layoutHints);
810
- case 'tabs':
811
- return renderTabs(data, layoutHints);
812
- case 'accordion':
813
- return renderAccordion(data, layoutHints);
814
- case 'stack':
815
- return renderStack(data, layoutHints);
816
- case 'columns':
817
- return renderColumns(data, layoutHints);
818
- case 'chart':
819
- // Charts require Chart.js (only in Beam). Fallback to table/JSON in playground.
820
- return '<pre class="json-highlighted">' + syntaxHighlightJson(data) + '</pre>';
821
- case 'json':
822
- default:
823
- return '<pre class="json-highlighted">' + syntaxHighlightJson(data) + '</pre>';
824
- }
825
- }
826
-
827
- function renderList(data, mapping, typeHints, style, accessory) {
828
- if (!Array.isArray(data) || data.length === 0) {
829
- return '<div class="smart-text muted">No items</div>';
830
- }
831
-
832
- const styleClass = style ? 'style-' + style : '';
833
- const items = data.map(item => renderListItem(item, mapping, typeHints, accessory)).join('');
834
-
835
- return '<div class="smart-list ' + styleClass + '">' + items + '</div>';
836
- }
837
-
838
- function renderListItem(item, mapping, typeHints, accessory) {
839
- let html = '<div class="list-item">';
840
-
841
- // Handle primitive items (strings, numbers, booleans)
842
- if (typeof item !== 'object' || item === null) {
843
- html += '<div class="list-item-content">';
844
- html += '<div class="list-item-title">' + escapeHtml(String(item)) + '</div>';
845
- html += '</div>';
846
- if (accessory && accessory !== 'none') {
847
- html += '<div class="list-item-accessory ' + accessory + '"></div>';
848
- }
849
- html += '</div>';
850
- return html;
851
- }
852
-
853
- // Leading (icon/avatar)
854
- if (mapping.icon && item[mapping.icon] !== undefined) {
855
- const iconValue = item[mapping.icon];
856
- const isEmoji = typeof iconValue === 'string' && iconValue.length <= 2;
857
- const isImage = typeof iconValue === 'string' && /\\.(jpg|jpeg|png|gif|webp|svg)/i.test(iconValue);
858
-
859
- if (isImage) {
860
- html += '<div class="list-item-leading"><img src="' + escapeHtml(iconValue) + '" alt=""></div>';
861
- } else {
862
- html += '<div class="list-item-leading' + (isEmoji ? ' emoji' : '') + '">' + escapeHtml(String(iconValue)) + '</div>';
863
- }
864
- }
865
-
866
- // Content (title + subtitle)
867
- html += '<div class="list-item-content">';
868
- if (mapping.title && item[mapping.title] !== undefined) {
869
- html += '<div class="list-item-title">' + escapeHtml(String(item[mapping.title])) + '</div>';
870
- }
871
- if (mapping.subtitle && item[mapping.subtitle] !== undefined) {
872
- const subtitleValue = item[mapping.subtitle];
873
- const isEmail = typeHints.find(h => h.field === mapping.subtitle && h.type === 'email');
874
- if (isEmail) {
875
- html += '<div class="list-item-subtitle"><a href="mailto:' + escapeHtml(subtitleValue) + '">' + escapeHtml(subtitleValue) + '</a></div>';
876
- } else {
877
- html += '<div class="list-item-subtitle">' + escapeHtml(String(subtitleValue)) + '</div>';
878
- }
879
- }
880
- html += '</div>';
881
-
882
- // Trailing (detail + badge)
883
- html += '<div class="list-item-trailing">';
884
- if (mapping.detail && item[mapping.detail] !== undefined) {
885
- html += '<span>' + renderFieldValue(item[mapping.detail], mapping.detail, typeHints) + '</span>';
886
- }
887
- if (mapping.badge && item[mapping.badge] !== undefined) {
888
- const badgeValue = String(item[mapping.badge]).toLowerCase();
889
- const statusClass = getStatusClass(badgeValue);
890
- html += '<span class="list-item-badge ' + statusClass + '">' + escapeHtml(String(item[mapping.badge])) + '</span>';
891
- }
892
- html += '</div>';
893
-
894
- // Accessory
895
- if (accessory && accessory !== 'none') {
896
- html += '<div class="list-item-accessory ' + accessory + '"></div>';
897
- }
898
-
899
- html += '</div>';
900
- return html;
901
- }
902
-
903
- function renderCard(data, mapping, typeHints) {
904
- if (!data || typeof data !== 'object') {
905
- return renderText(data);
906
- }
907
-
908
- let html = '<div class="smart-card">';
909
-
910
- // Header (icon + title + subtitle)
911
- const hasHeader = mapping.icon || mapping.title || mapping.subtitle;
912
- if (hasHeader) {
913
- html += '<div class="smart-card-header">';
914
-
915
- if (mapping.icon && data[mapping.icon] !== undefined) {
916
- const iconValue = data[mapping.icon];
917
- const isImage = typeof iconValue === 'string' && /\\.(jpg|jpeg|png|gif|webp|svg)/i.test(iconValue);
918
- if (isImage) {
919
- html += '<div class="smart-card-icon"><img src="' + escapeHtml(iconValue) + '" alt=""></div>';
920
- } else {
921
- html += '<div class="smart-card-icon">' + escapeHtml(String(iconValue)) + '</div>';
922
- }
923
- }
924
-
925
- html += '<div class="smart-card-header-content">';
926
- if (mapping.title && data[mapping.title] !== undefined) {
927
- html += '<div class="smart-card-title">' + escapeHtml(String(data[mapping.title])) + '</div>';
928
- }
929
- if (mapping.subtitle && data[mapping.subtitle] !== undefined) {
930
- html += '<div class="smart-card-subtitle">' + escapeHtml(String(data[mapping.subtitle])) + '</div>';
931
- }
932
- html += '</div></div>';
933
- }
934
-
935
- // Body (remaining fields as key-value rows)
936
- const excludeFields = new Set([mapping.icon, mapping.title, mapping.subtitle, mapping.id].filter(Boolean));
937
- const bodyFields = Object.keys(data).filter(k => !excludeFields.has(k));
938
-
939
- if (bodyFields.length > 0) {
940
- html += '<div class="smart-card-body">';
941
- for (const field of bodyFields) {
942
- html += '<div class="smart-card-row">';
943
- html += '<span class="smart-card-label">' + formatFieldLabel(field) + '</span>';
944
- html += '<span class="smart-card-value">' + renderFieldValue(data[field], field, typeHints) + '</span>';
945
- html += '</div>';
946
- }
947
- html += '</div>';
948
- }
949
-
950
- html += '</div>';
951
- return html;
952
- }
953
-
954
- function renderGrid(data, mapping, typeHints, columns) {
955
- if (!Array.isArray(data) || data.length === 0) {
956
- return '<div class="smart-text muted">No items</div>';
957
- }
958
-
959
- const colsClass = columns ? 'cols-' + columns : '';
960
- let html = '<div class="smart-grid ' + colsClass + '">';
961
-
962
- for (const item of data) {
963
- html += '<div class="grid-item">';
964
-
965
- // Image
966
- const imageField = mapping.image || Object.keys(item).find(k => /image|photo|thumbnail/i.test(k));
967
- if (imageField && item[imageField]) {
968
- html += '<img class="grid-item-image" src="' + escapeHtml(item[imageField]) + '" alt="">';
969
- } else {
970
- html += '<div class="grid-item-image"></div>';
971
- }
972
-
973
- // Content
974
- html += '<div class="grid-item-content">';
975
- if (mapping.title && item[mapping.title] !== undefined) {
976
- html += '<div class="grid-item-title">' + escapeHtml(String(item[mapping.title])) + '</div>';
977
- }
978
- if (mapping.detail && item[mapping.detail] !== undefined) {
979
- html += '<div class="grid-item-detail">' + renderFieldValue(item[mapping.detail], mapping.detail, typeHints) + '</div>';
980
- }
981
- html += '</div></div>';
982
- }
983
-
984
- html += '</div>';
985
- return html;
986
- }
987
-
988
- function renderTree(data, depth = 0) {
989
- if (data === null) return '<span class="tree-value null">null</span>';
990
- if (data === undefined) return '<span class="tree-value null">undefined</span>';
991
-
992
- if (typeof data !== 'object') {
993
- const typeClass = typeof data;
994
- if (typeof data === 'string') {
995
- return '<span class="tree-value string">"' + escapeHtml(data) + '"</span>';
996
- }
997
- return '<span class="tree-value ' + typeClass + '">' + escapeHtml(String(data)) + '</span>';
998
- }
999
-
1000
- if (Array.isArray(data)) {
1001
- if (data.length === 0) return '<span class="tree-value">[]</span>';
1002
- let html = '<div class="tree-node">[';
1003
- html += '<div class="tree-node-inner">';
1004
- data.forEach((item, i) => {
1005
- html += '<div>' + renderTree(item, depth + 1);
1006
- if (i < data.length - 1) html += ',';
1007
- html += '</div>';
1008
- });
1009
- html += '</div>]</div>';
1010
- return html;
1011
- }
1012
-
1013
- const keys = Object.keys(data);
1014
- if (keys.length === 0) return '<span class="tree-value">{}</span>';
1015
-
1016
- let html = '<div class="tree-node">{';
1017
- html += '<div class="tree-node-inner">';
1018
- keys.forEach((key, i) => {
1019
- html += '<div><span class="tree-key">' + escapeHtml(key) + '</span>: ' + renderTree(data[key], depth + 1);
1020
- if (i < keys.length - 1) html += ',';
1021
- html += '</div>';
1022
- });
1023
- html += '</div>}</div>';
1024
- return html;
1025
- }
1026
-
1027
- function renderChips(data) {
1028
- if (!Array.isArray(data) || data.length === 0) {
1029
- return '<div class="smart-text muted">No items</div>';
1030
- }
1031
-
1032
- const chips = data.map(item => '<span class="chip">' + escapeHtml(String(item)) + '</span>').join('');
1033
- return '<div class="smart-chips">' + chips + '</div>';
1034
- }
1035
-
1036
- function renderText(data) {
1037
- if (data === null || data === undefined) {
1038
- return '<div class="smart-text muted">—</div>';
1039
- }
1040
-
1041
- const text = String(data);
1042
-
1043
- // Large display for short text/numbers
1044
- if (text.length < 20 && !text.includes('\\n')) {
1045
- return '<div class="smart-text large">' + escapeHtml(text) + '</div>';
1046
- }
1047
-
1048
- return '<div class="smart-text">' + escapeHtml(text) + '</div>';
1049
- }
1050
-
1051
- function renderFieldValue(value, field, typeHints) {
1052
- if (value === null || value === undefined) return '—';
1053
- if (typeof value === 'boolean') return value ? '✓' : '✗';
1054
-
1055
- const hint = typeHints.find(h => h.field === field);
1056
-
1057
- if (hint) {
1058
- switch (hint.type) {
1059
- case 'email':
1060
- return '<a href="mailto:' + escapeHtml(value) + '">' + escapeHtml(value) + '</a>';
1061
- case 'url':
1062
- return '<a href="' + escapeHtml(value) + '" target="_blank">' + escapeHtml(value) + '</a>';
1063
- case 'date':
1064
- try {
1065
- return new Date(value).toLocaleDateString();
1066
- } catch {
1067
- return escapeHtml(String(value));
1068
- }
1069
- case 'currency':
1070
- if (typeof value === 'number') return '$' + value.toFixed(2);
1071
- return escapeHtml(String(value));
1072
- }
1073
- }
1074
-
1075
- if (typeof value === 'object') {
1076
- return escapeHtml(JSON.stringify(value));
1077
- }
1078
-
1079
- return escapeHtml(String(value));
1080
- }
1081
-
1082
- function getStatusClass(value) {
1083
- const lower = value.toLowerCase();
1084
- if (/active|success|complete|done|enabled|yes|true/.test(lower)) return 'status-active';
1085
- if (/inactive|error|failed|disabled|no|false/.test(lower)) return 'status-inactive';
1086
- if (/pending|warning|waiting|processing/.test(lower)) return 'status-pending';
1087
- return '';
1088
- }
1089
-
1090
- function renderMetric(data) {
1091
- if (!data || typeof data !== 'object') {
1092
- if (typeof data === 'number') {
1093
- return '<div style="text-align:center;padding:24px;"><div style="font-size:3rem;font-weight:700;">' + data.toLocaleString() + '</div></div>';
1094
- }
1095
- return '<div>No metric data</div>';
1096
- }
1097
- var keys = Object.keys(data);
1098
- var numericKey = keys.find(function(k) { return typeof data[k] === 'number'; });
1099
- if (!numericKey) return '<pre class="json-highlighted">' + syntaxHighlightJson(data) + '</pre>';
1100
- var value = data[numericKey];
1101
- var label = data.label || data.name || data.title || (numericKey !== 'value' ? formatFieldLabel(numericKey) : '');
1102
- var delta = data.delta || data.change || data.diff;
1103
- var html = '<div style="text-align:center;padding:24px;">';
1104
- html += '<div style="font-size:3rem;font-weight:700;">' + value.toLocaleString() + '</div>';
1105
- if (label) html += '<div style="font-size:0.85rem;color:#64748b;text-transform:uppercase;letter-spacing:0.08em;margin-top:4px;">' + escapeHtml(label) + '</div>';
1106
- if (delta) {
1107
- var color = String(delta).startsWith('+') ? '#16a34a' : String(delta).startsWith('-') ? '#dc2626' : '#64748b';
1108
- html += '<div style="display:inline-block;padding:2px 10px;border-radius:12px;margin-top:8px;font-weight:600;color:' + color + ';">' + escapeHtml(String(delta)) + '</div>';
1109
- }
1110
- html += '</div>';
1111
- return html;
1112
- }
1113
-
1114
- function renderGauge(data) {
1115
- if (!data || typeof data !== 'object') return '<div>No gauge data</div>';
1116
- var value, min = 0, max = 100, label;
1117
- if ('progress' in data && typeof data.progress === 'number') {
1118
- value = data.progress * 100;
1119
- label = data.label || 'Progress';
1120
- } else {
1121
- value = data.value || 0;
1122
- min = data.min || 0;
1123
- max = data.max || 100;
1124
- label = data.label;
1125
- }
1126
- var pct = Math.max(0, Math.min(100, ((value - min) / (max - min)) * 100));
1127
- var displayVal = data.progress !== undefined ? Math.round(value) + '%' : Math.round(value);
1128
- var html = '<div style="text-align:center;padding:16px;">';
1129
- html += '<div style="width:160px;margin:0 auto;">';
1130
- html += '<div style="position:relative;width:160px;height:12px;background:#334155;border-radius:6px;overflow:hidden;">';
1131
- html += '<div style="height:100%;width:' + pct + '%;background:linear-gradient(90deg,#22c55e,#eab308,#ef4444);border-radius:6px;transition:width 0.5s;"></div>';
1132
- html += '</div>';
1133
- html += '<div style="font-size:1.5rem;font-weight:700;margin-top:8px;">' + displayVal + '</div>';
1134
- if (label) html += '<div style="font-size:0.8rem;color:#64748b;text-transform:uppercase;">' + escapeHtml(label) + '</div>';
1135
- html += '</div></div>';
1136
- return html;
1137
- }
1138
-
1139
- function renderTimeline(data) {
1140
- if (!Array.isArray(data) || data.length === 0) return '<div>No timeline data</div>';
1141
- var datePattern = /^(date|time|createdAt|updatedAt|created|updated|timestamp)/i;
1142
- var titlePattern = /^(title|event|name|label|subject|action)/i;
1143
- var descPattern = /^(description|details|body|content|message|summary)/i;
1144
- var sample = data[0];
1145
- var dateField, titleField, descField;
1146
- var fields = Object.keys(sample);
1147
- for (var i = 0; i < fields.length; i++) {
1148
- if (!dateField && datePattern.test(fields[i])) dateField = fields[i];
1149
- if (!titleField && titlePattern.test(fields[i])) titleField = fields[i];
1150
- if (!descField && descPattern.test(fields[i])) descField = fields[i];
1151
- }
1152
- var html = '<div style="position:relative;padding-left:24px;">';
1153
- html += '<div style="position:absolute;left:9px;top:0;bottom:0;width:2px;background:#334155;"></div>';
1154
- for (var j = 0; j < data.length; j++) {
1155
- var item = data[j];
1156
- html += '<div style="position:relative;padding:8px 0 8px 16px;">';
1157
- html += '<div style="position:absolute;left:-4px;top:14px;width:10px;height:10px;border-radius:50%;background:#6366f1;border:2px solid #0f172a;z-index:1;"></div>';
1158
- if (titleField) html += '<div style="font-weight:600;">' + escapeHtml(String(item[titleField])) + '</div>';
1159
- if (dateField) {
1160
- try { html += '<div style="font-size:0.75rem;color:#64748b;">' + new Date(item[dateField]).toLocaleString() + '</div>'; }
1161
- catch(e) { html += '<div style="font-size:0.75rem;color:#64748b;">' + escapeHtml(String(item[dateField])) + '</div>'; }
1162
- }
1163
- if (descField && item[descField]) html += '<div style="font-size:0.85rem;color:#94a3b8;margin-top:4px;">' + escapeHtml(String(item[descField])) + '</div>';
1164
- html += '</div>';
1165
- }
1166
- html += '</div>';
1167
- return html;
1168
- }
1169
-
1170
- function renderDashboard(data) {
1171
- if (!data || typeof data !== 'object') return '<div>No dashboard data</div>';
1172
- var keys = Object.keys(data);
1173
- var html = '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px;">';
1174
- for (var i = 0; i < keys.length; i++) {
1175
- var key = keys[i];
1176
- var val = data[key];
1177
- html += '<div style="border:1px solid #334155;border-radius:8px;overflow:hidden;">';
1178
- html += '<div style="padding:8px 12px;font-size:0.75rem;font-weight:600;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;border-bottom:1px solid #334155;">' + formatFieldLabel(key) + '</div>';
1179
- html += '<div style="padding:8px;">';
1180
- if (typeof val === 'number') {
1181
- html += '<div style="text-align:center;padding:16px;font-size:2rem;font-weight:700;">' + val.toLocaleString() + '</div>';
1182
- } else if (Array.isArray(val)) {
1183
- html += renderSmartResult(val, null, null);
1184
- } else if (typeof val === 'object' && val !== null) {
1185
- if ('value' in val && typeof val.value === 'number') {
1186
- html += renderMetric(val);
1187
- } else if ('progress' in val && typeof val.progress === 'number') {
1188
- html += renderGauge(val);
1189
- } else {
1190
- html += renderSmartResult(val, null, null);
1191
- }
1192
- } else {
1193
- html += '<div style="padding:8px;">' + escapeHtml(String(val)) + '</div>';
1194
- }
1195
- html += '</div></div>';
1196
- }
1197
- html += '</div>';
1198
- return html;
1199
- }
1200
-
1201
- function renderInnerContent(data, innerLayout) {
1202
- if (innerLayout) {
1203
- return renderSmartResult(data, innerLayout, null);
1204
- }
1205
- // Auto-detect
1206
- return renderSmartResult(data, null, null);
1207
- }
1208
-
1209
- function renderCart(data) {
1210
- if (!data) return '<div>No cart data</div>';
1211
- var items, summary = {};
1212
- if (Array.isArray(data)) {
1213
- items = data;
1214
- } else {
1215
- items = data.items || [];
1216
- for (var k in data) {
1217
- if (k !== 'items' && typeof data[k] === 'number') summary[k] = data[k];
1218
- }
1219
- }
1220
- if (items.length === 0) return '<div>Cart is empty</div>';
1221
- var computedTotal = 0;
1222
- for (var i = 0; i < items.length; i++) {
1223
- var qty = items[i].quantity || items[i].qty || 1;
1224
- computedTotal += (items[i].price || 0) * qty;
1225
- }
1226
- if (Object.keys(summary).length === 0) summary = { total: computedTotal };
1227
- var html = '<div>';
1228
- for (var i = 0; i < items.length; i++) {
1229
- var item = items[i];
1230
- var qty = item.quantity || item.qty || 1;
1231
- var lineTotal = (item.price || 0) * qty;
1232
- var name = item.name || item.title || item.label || item.product || 'Item';
1233
- html += '<div class="smart-cart-item">';
1234
- if (item.image) html += '<img class="smart-cart-item-image" src="' + escapeHtml(item.image) + '" alt="">';
1235
- html += '<div class="smart-cart-item-info"><div class="smart-cart-item-name">' + escapeHtml(name) + '</div></div>';
1236
- if (qty > 1) html += '<span class="smart-cart-qty">&times;' + qty + '</span>';
1237
- html += '<span class="smart-cart-line-total">$' + lineTotal.toFixed(2) + '</span>';
1238
- html += '</div>';
1239
- }
1240
- html += '<div class="smart-cart-divider"></div>';
1241
- var summaryKeys = Object.keys(summary);
1242
- for (var i = 0; i < summaryKeys.length; i++) {
1243
- var sk = summaryKeys[i];
1244
- var isTotal = sk.toLowerCase() === 'total';
1245
- html += '<div class="smart-cart-summary-row' + (isTotal ? ' total' : '') + '">';
1246
- html += '<span>' + formatFieldLabel(sk) + '</span>';
1247
- html += '<span>$' + summary[sk].toFixed(2) + '</span>';
1248
- html += '</div>';
1249
- }
1250
- html += '</div>';
1251
- return html;
1252
- }
1253
-
1254
- function renderPanels(data, layoutHints) {
1255
- if (!data || typeof data !== 'object' || Array.isArray(data)) return '<div>Panels require an object</div>';
1256
- var keys = Object.keys(data);
1257
- var cols = layoutHints && layoutHints.columns ? parseInt(layoutHints.columns) : 0;
1258
- var colsClass = cols >= 2 && cols <= 4 ? ' cols-' + cols : '';
1259
- var inner = layoutHints ? layoutHints.inner : null;
1260
- var html = '<div class="smart-panels' + colsClass + '">';
1261
- for (var i = 0; i < keys.length; i++) {
1262
- html += '<div class="smart-panel">';
1263
- html += '<div class="smart-panel-header">' + formatFieldLabel(keys[i]) + '</div>';
1264
- html += '<div class="smart-panel-content">' + renderInnerContent(data[keys[i]], inner) + '</div>';
1265
- html += '</div>';
1266
- }
1267
- html += '</div>';
1268
- return html;
1269
- }
1270
-
1271
- function renderTabs(data, layoutHints) {
1272
- if (!data || typeof data !== 'object' || Array.isArray(data)) return '<div>Tabs require an object</div>';
1273
- var keys = Object.keys(data);
1274
- var inner = layoutHints ? layoutHints.inner : null;
1275
- var tabId = 'tabs-' + Math.random().toString(36).slice(2, 8);
1276
- var html = '<div>';
1277
- html += '<div class="smart-tabs-bar">';
1278
- for (var i = 0; i < keys.length; i++) {
1279
- html += '<div class="smart-tab' + (i === 0 ? ' active' : '') + '" onclick="(function(el){var bar=el.parentElement;var tabs=bar.parentElement.querySelectorAll(\\'.smart-tab-content\\');bar.querySelectorAll(\\'.smart-tab\\').forEach(function(t){t.classList.remove(\\'active\\')});el.classList.add(\\'active\\');tabs.forEach(function(t){t.classList.remove(\\'active\\')});tabs[' + i + '].classList.add(\\'active\\');})(this)">' + formatFieldLabel(keys[i]) + '</div>';
1280
- }
1281
- html += '</div>';
1282
- for (var i = 0; i < keys.length; i++) {
1283
- html += '<div class="smart-tab-content' + (i === 0 ? ' active' : '') + '">';
1284
- html += renderInnerContent(data[keys[i]], inner);
1285
- html += '</div>';
1286
- }
1287
- html += '</div>';
1288
- return html;
1289
- }
1290
-
1291
- function renderAccordion(data, layoutHints) {
1292
- if (!data || typeof data !== 'object' || Array.isArray(data)) return '<div>Accordion requires an object</div>';
1293
- var keys = Object.keys(data);
1294
- var inner = layoutHints ? layoutHints.inner : null;
1295
- var html = '<div class="smart-accordion">';
1296
- for (var i = 0; i < keys.length; i++) {
1297
- var bodyId = 'acc-' + Math.random().toString(36).slice(2, 8);
1298
- html += '<div class="smart-accordion-header" onclick="var b=document.getElementById(\\'' + bodyId + '\\');b.classList.toggle(\\'expanded\\')">';
1299
- html += '<span>' + formatFieldLabel(keys[i]) + '</span><span>&#x25B6;</span>';
1300
- html += '</div>';
1301
- html += '<div id="' + bodyId + '" class="smart-accordion-body' + (i === 0 ? ' expanded' : '') + '">';
1302
- html += renderInnerContent(data[keys[i]], inner);
1303
- html += '</div>';
1304
- }
1305
- html += '</div>';
1306
- return html;
1307
- }
1308
-
1309
- function renderStack(data, layoutHints) {
1310
- if (!data || typeof data !== 'object' || Array.isArray(data)) return '<div>Stack requires an object</div>';
1311
- var keys = Object.keys(data);
1312
- var inner = layoutHints ? layoutHints.inner : null;
1313
- var html = '<div class="smart-stack">';
1314
- for (var i = 0; i < keys.length; i++) {
1315
- html += '<div class="smart-stack-item">';
1316
- html += '<div class="smart-stack-label">' + formatFieldLabel(keys[i]) + '</div>';
1317
- html += '<div class="smart-stack-content">' + renderInnerContent(data[keys[i]], inner) + '</div>';
1318
- html += '</div>';
1319
- }
1320
- html += '</div>';
1321
- return html;
1322
- }
1323
-
1324
- function renderColumns(data, layoutHints) {
1325
- if (!data || typeof data !== 'object' || Array.isArray(data)) return '<div>Columns require an object</div>';
1326
- var keys = Object.keys(data);
1327
- var cols = layoutHints && layoutHints.columns ? Math.min(Math.max(parseInt(layoutHints.columns), 2), 4) : Math.min(keys.length, 4);
1328
- var inner = layoutHints ? layoutHints.inner : null;
1329
- var html = '<div class="smart-columns cols-' + cols + '">';
1330
- for (var i = 0; i < keys.length; i++) {
1331
- html += '<div>';
1332
- html += '<div style="font-size:0.75rem;font-weight:600;color:#64748b;text-transform:uppercase;letter-spacing:0.06em;margin-bottom:4px;">' + formatFieldLabel(keys[i]) + '</div>';
1333
- html += renderInnerContent(data[keys[i]], inner);
1334
- html += '</div>';
1335
- }
1336
- html += '</div>';
1337
- return html;
1338
- }
1339
- `;
1340
- }
1341
- //# sourceMappingURL=components.js.map