@portel/photon 1.20.1 → 1.22.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 (148) hide show
  1. package/README.md +5 -5
  2. package/dist/ag-ui/adapter.d.ts +4 -1
  3. package/dist/ag-ui/adapter.d.ts.map +1 -1
  4. package/dist/ag-ui/adapter.js +58 -3
  5. package/dist/ag-ui/adapter.js.map +1 -1
  6. package/dist/ag-ui/types.d.ts +12 -0
  7. package/dist/ag-ui/types.d.ts.map +1 -1
  8. package/dist/auto-ui/beam/routes/api-browse.d.ts.map +1 -1
  9. package/dist/auto-ui/beam/routes/api-browse.js +8 -49
  10. package/dist/auto-ui/beam/routes/api-browse.js.map +1 -1
  11. package/dist/auto-ui/beam/routes/api-config.d.ts +1 -1
  12. package/dist/auto-ui/beam/routes/api-config.d.ts.map +1 -1
  13. package/dist/auto-ui/beam/routes/api-config.js +79 -1
  14. package/dist/auto-ui/beam/routes/api-config.js.map +1 -1
  15. package/dist/auto-ui/beam.d.ts.map +1 -1
  16. package/dist/auto-ui/beam.js +23 -31
  17. package/dist/auto-ui/beam.js.map +1 -1
  18. package/dist/auto-ui/bridge/index.d.ts.map +1 -1
  19. package/dist/auto-ui/bridge/index.js +107 -11
  20. package/dist/auto-ui/bridge/index.js.map +1 -1
  21. package/dist/auto-ui/bridge/renderers.d.ts +14 -0
  22. package/dist/auto-ui/bridge/renderers.d.ts.map +1 -1
  23. package/dist/auto-ui/bridge/renderers.js +680 -57
  24. package/dist/auto-ui/bridge/renderers.js.map +1 -1
  25. package/dist/auto-ui/frontend/index.html +3 -3
  26. package/dist/auto-ui/frontend/pure-view.html +19 -19
  27. package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
  28. package/dist/auto-ui/streamable-http-transport.js +53 -2
  29. package/dist/auto-ui/streamable-http-transport.js.map +1 -1
  30. package/dist/auto-ui/ui-resolver.d.ts +25 -0
  31. package/dist/auto-ui/ui-resolver.d.ts.map +1 -0
  32. package/dist/auto-ui/ui-resolver.js +95 -0
  33. package/dist/auto-ui/ui-resolver.js.map +1 -0
  34. package/dist/beam-form.bundle.js +7 -7
  35. package/dist/beam-form.bundle.js.map +1 -1
  36. package/dist/beam.bundle.js +905 -185
  37. package/dist/beam.bundle.js.map +4 -4
  38. package/dist/cli/commands/build.d.ts.map +1 -1
  39. package/dist/cli/commands/build.js +9 -5
  40. package/dist/cli/commands/build.js.map +1 -1
  41. package/dist/cli/commands/init.d.ts.map +1 -1
  42. package/dist/cli/commands/init.js +93 -53
  43. package/dist/cli/commands/init.js.map +1 -1
  44. package/dist/cli/commands/publish.d.ts +14 -0
  45. package/dist/cli/commands/publish.d.ts.map +1 -0
  46. package/dist/cli/commands/publish.js +126 -0
  47. package/dist/cli/commands/publish.js.map +1 -0
  48. package/dist/cli/commands/run.d.ts.map +1 -1
  49. package/dist/cli/commands/run.js +2 -0
  50. package/dist/cli/commands/run.js.map +1 -1
  51. package/dist/cli/index.d.ts.map +1 -1
  52. package/dist/cli/index.js +3 -0
  53. package/dist/cli/index.js.map +1 -1
  54. package/dist/cli.d.ts +4 -0
  55. package/dist/cli.d.ts.map +1 -1
  56. package/dist/cli.js +11 -1
  57. package/dist/cli.js.map +1 -1
  58. package/dist/context.d.ts +6 -0
  59. package/dist/context.d.ts.map +1 -1
  60. package/dist/context.js +17 -5
  61. package/dist/context.js.map +1 -1
  62. package/dist/daemon/client.d.ts +9 -1
  63. package/dist/daemon/client.d.ts.map +1 -1
  64. package/dist/daemon/client.js +54 -1
  65. package/dist/daemon/client.js.map +1 -1
  66. package/dist/daemon/manager.d.ts +3 -0
  67. package/dist/daemon/manager.d.ts.map +1 -1
  68. package/dist/daemon/manager.js +88 -38
  69. package/dist/daemon/manager.js.map +1 -1
  70. package/dist/daemon/ownership.d.ts +12 -0
  71. package/dist/daemon/ownership.d.ts.map +1 -0
  72. package/dist/daemon/ownership.js +55 -0
  73. package/dist/daemon/ownership.js.map +1 -0
  74. package/dist/daemon/protocol.d.ts +4 -2
  75. package/dist/daemon/protocol.d.ts.map +1 -1
  76. package/dist/daemon/protocol.js +15 -2
  77. package/dist/daemon/protocol.js.map +1 -1
  78. package/dist/daemon/server.js +557 -83
  79. package/dist/daemon/server.js.map +1 -1
  80. package/dist/daemon/session-manager.d.ts +9 -1
  81. package/dist/daemon/session-manager.d.ts.map +1 -1
  82. package/dist/daemon/session-manager.js +54 -1
  83. package/dist/daemon/session-manager.js.map +1 -1
  84. package/dist/daemon/worker-manager.d.ts +12 -0
  85. package/dist/daemon/worker-manager.d.ts.map +1 -1
  86. package/dist/daemon/worker-manager.js +89 -6
  87. package/dist/daemon/worker-manager.js.map +1 -1
  88. package/dist/loader.d.ts +17 -9
  89. package/dist/loader.d.ts.map +1 -1
  90. package/dist/loader.js +415 -141
  91. package/dist/loader.js.map +1 -1
  92. package/dist/photon-cli-runner.d.ts.map +1 -1
  93. package/dist/photon-cli-runner.js +26 -2
  94. package/dist/photon-cli-runner.js.map +1 -1
  95. package/dist/photons/canvas/ui/canvas.photon.html +1493 -0
  96. package/dist/photons/canvas.photon.d.ts +400 -0
  97. package/dist/photons/canvas.photon.d.ts.map +1 -0
  98. package/dist/photons/canvas.photon.js +662 -0
  99. package/dist/photons/canvas.photon.js.map +1 -0
  100. package/dist/photons/canvas.photon.ts +814 -0
  101. package/dist/photons/publish.photon.d.ts +97 -0
  102. package/dist/photons/publish.photon.d.ts.map +1 -0
  103. package/dist/photons/publish.photon.js +569 -0
  104. package/dist/photons/publish.photon.js.map +1 -0
  105. package/dist/photons/publish.photon.ts +683 -0
  106. package/dist/photons/ui/canvas.photon.html +624 -0
  107. package/dist/resource-server.d.ts.map +1 -1
  108. package/dist/resource-server.js +7 -1
  109. package/dist/resource-server.js.map +1 -1
  110. package/dist/server.d.ts +7 -0
  111. package/dist/server.d.ts.map +1 -1
  112. package/dist/server.js +67 -37
  113. package/dist/server.js.map +1 -1
  114. package/dist/shared/error-handler.d.ts +1 -0
  115. package/dist/shared/error-handler.d.ts.map +1 -1
  116. package/dist/shared/error-handler.js +68 -10
  117. package/dist/shared/error-handler.js.map +1 -1
  118. package/dist/shared/logger.d.ts.map +1 -1
  119. package/dist/shared/logger.js +34 -0
  120. package/dist/shared/logger.js.map +1 -1
  121. package/dist/shared-utils.d.ts.map +1 -1
  122. package/dist/shared-utils.js +2 -2
  123. package/dist/shared-utils.js.map +1 -1
  124. package/dist/telemetry/context.d.ts +24 -0
  125. package/dist/telemetry/context.d.ts.map +1 -0
  126. package/dist/telemetry/context.js +17 -0
  127. package/dist/telemetry/context.js.map +1 -0
  128. package/dist/telemetry/logs.d.ts +38 -0
  129. package/dist/telemetry/logs.d.ts.map +1 -0
  130. package/dist/telemetry/logs.js +108 -0
  131. package/dist/telemetry/logs.js.map +1 -0
  132. package/dist/telemetry/metrics.d.ts +71 -0
  133. package/dist/telemetry/metrics.d.ts.map +1 -0
  134. package/dist/telemetry/metrics.js +184 -0
  135. package/dist/telemetry/metrics.js.map +1 -0
  136. package/dist/telemetry/otel.d.ts +20 -1
  137. package/dist/telemetry/otel.d.ts.map +1 -1
  138. package/dist/telemetry/otel.js +79 -2
  139. package/dist/telemetry/otel.js.map +1 -1
  140. package/dist/telemetry/sdk.d.ts +49 -0
  141. package/dist/telemetry/sdk.d.ts.map +1 -0
  142. package/dist/telemetry/sdk.js +110 -0
  143. package/dist/telemetry/sdk.js.map +1 -0
  144. package/dist/tsx-compiler.d.ts +23 -0
  145. package/dist/tsx-compiler.d.ts.map +1 -0
  146. package/dist/tsx-compiler.js +221 -0
  147. package/dist/tsx-compiler.js.map +1 -0
  148. package/package.json +7 -7
@@ -0,0 +1,624 @@
1
+ <style>
2
+ * { box-sizing: border-box; margin: 0; padding: 0; }
3
+
4
+ body {
5
+ font-family: var(--font-family-sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
6
+ background: var(--color-surface, #1a1b26);
7
+ color: var(--color-on-surface, #e6e6e6);
8
+ overflow: hidden;
9
+ height: 100vh;
10
+ user-select: none;
11
+ }
12
+
13
+ /* ── Canvas Surface ── */
14
+ .canvas-surface {
15
+ position: relative;
16
+ width: 100%;
17
+ height: 100%;
18
+ overflow: auto;
19
+ cursor: default;
20
+ }
21
+
22
+ /* ── Grid dots background ── */
23
+ .canvas-surface::before {
24
+ content: '';
25
+ position: absolute;
26
+ inset: 0;
27
+ width: 4000px;
28
+ height: 4000px;
29
+ background-image: radial-gradient(circle, var(--color-outline-variant, #333) 1px, transparent 1px);
30
+ background-size: 24px 24px;
31
+ pointer-events: none;
32
+ opacity: 0.3;
33
+ }
34
+
35
+ /* ── Canvas Element ── */
36
+ .ce {
37
+ position: absolute;
38
+ background: var(--color-surface-container, #1e2030);
39
+ border: 1px solid var(--color-outline-variant, #333);
40
+ border-radius: 8px;
41
+ overflow: hidden;
42
+ display: flex;
43
+ flex-direction: column;
44
+ transition: box-shadow 0.15s ease;
45
+ }
46
+
47
+ .ce:hover {
48
+ border-color: var(--color-primary, #6366f1);
49
+ }
50
+
51
+ .ce.selected {
52
+ border-color: var(--color-primary, #6366f1);
53
+ box-shadow: 0 0 0 2px var(--color-primary, #6366f1);
54
+ }
55
+
56
+ /* ── Title Bar ── */
57
+ .ce-bar {
58
+ display: flex;
59
+ align-items: center;
60
+ gap: 6px;
61
+ padding: 4px 8px;
62
+ background: var(--color-surface-container-high, #252738);
63
+ cursor: grab;
64
+ font-size: 11px;
65
+ color: var(--color-on-surface-muted, #999);
66
+ min-height: 28px;
67
+ flex-shrink: 0;
68
+ }
69
+
70
+ .ce-bar:active { cursor: grabbing; }
71
+
72
+ .ce-bar .ce-label {
73
+ flex: 1;
74
+ overflow: hidden;
75
+ text-overflow: ellipsis;
76
+ white-space: nowrap;
77
+ }
78
+
79
+ .ce-bar .ce-format {
80
+ opacity: 0.5;
81
+ font-size: 10px;
82
+ font-family: var(--font-family-mono, monospace);
83
+ }
84
+
85
+ .ce-bar .ce-delete {
86
+ opacity: 0;
87
+ cursor: pointer;
88
+ padding: 2px 4px;
89
+ border-radius: 3px;
90
+ font-size: 12px;
91
+ line-height: 1;
92
+ transition: opacity 0.1s;
93
+ }
94
+
95
+ .ce:hover .ce-delete,
96
+ .ce.selected .ce-delete { opacity: 0.6; }
97
+ .ce-delete:hover { opacity: 1 !important; background: var(--color-error, #ef4444); color: #fff; }
98
+
99
+ /* ── Body (rendered content) ── */
100
+ .ce-body {
101
+ flex: 1;
102
+ overflow: auto;
103
+ padding: 8px;
104
+ min-height: 0;
105
+ }
106
+
107
+ /* ── Resize Handle ── */
108
+ .ce-resize {
109
+ position: absolute;
110
+ right: 0;
111
+ bottom: 0;
112
+ width: 16px;
113
+ height: 16px;
114
+ cursor: nwse-resize;
115
+ opacity: 0;
116
+ transition: opacity 0.1s;
117
+ }
118
+
119
+ .ce:hover .ce-resize,
120
+ .ce.selected .ce-resize { opacity: 1; }
121
+
122
+ .ce-resize::after {
123
+ content: '';
124
+ position: absolute;
125
+ right: 3px;
126
+ bottom: 3px;
127
+ width: 8px;
128
+ height: 8px;
129
+ border-right: 2px solid var(--color-primary, #6366f1);
130
+ border-bottom: 2px solid var(--color-primary, #6366f1);
131
+ border-radius: 0 0 2px 0;
132
+ }
133
+
134
+ /* ── Insert Button ── */
135
+ .insert-btn {
136
+ position: fixed;
137
+ bottom: 20px;
138
+ right: 20px;
139
+ width: 48px;
140
+ height: 48px;
141
+ border-radius: 50%;
142
+ background: var(--color-primary, #6366f1);
143
+ color: #fff;
144
+ border: none;
145
+ font-size: 24px;
146
+ cursor: pointer;
147
+ display: flex;
148
+ align-items: center;
149
+ justify-content: center;
150
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
151
+ z-index: 10000;
152
+ transition: transform 0.15s;
153
+ }
154
+
155
+ .insert-btn:hover { transform: scale(1.1); }
156
+
157
+ /* ── Format Picker ── */
158
+ .format-picker {
159
+ position: fixed;
160
+ bottom: 80px;
161
+ right: 20px;
162
+ width: 260px;
163
+ max-height: 400px;
164
+ overflow-y: auto;
165
+ background: var(--color-surface-container, #1e2030);
166
+ border: 1px solid var(--color-outline-variant, #333);
167
+ border-radius: 12px;
168
+ padding: 8px;
169
+ z-index: 10001;
170
+ box-shadow: 0 8px 24px rgba(0,0,0,0.4);
171
+ display: none;
172
+ }
173
+
174
+ .format-picker.open { display: block; }
175
+
176
+ .format-picker input {
177
+ width: 100%;
178
+ padding: 8px 10px;
179
+ background: var(--color-surface, #1a1b26);
180
+ border: 1px solid var(--color-outline-variant, #333);
181
+ border-radius: 6px;
182
+ color: var(--color-on-surface, #e6e6e6);
183
+ font-size: 13px;
184
+ margin-bottom: 6px;
185
+ outline: none;
186
+ }
187
+
188
+ .format-picker input:focus { border-color: var(--color-primary, #6366f1); }
189
+
190
+ .format-item {
191
+ padding: 6px 10px;
192
+ border-radius: 6px;
193
+ cursor: pointer;
194
+ font-size: 13px;
195
+ display: flex;
196
+ justify-content: space-between;
197
+ align-items: center;
198
+ }
199
+
200
+ .format-item:hover { background: var(--color-surface-container-high, #252738); }
201
+
202
+ .format-item .fi-name { font-weight: 500; }
203
+ .format-item .fi-shape { font-size: 11px; opacity: 0.5; font-family: var(--font-family-mono, monospace); }
204
+
205
+ /* ── Empty State ── */
206
+ .empty-state {
207
+ position: absolute;
208
+ inset: 0;
209
+ display: flex;
210
+ flex-direction: column;
211
+ align-items: center;
212
+ justify-content: center;
213
+ gap: 12px;
214
+ color: var(--color-on-surface-muted, #888);
215
+ pointer-events: none;
216
+ }
217
+
218
+ .empty-state .hint { font-size: 14px; opacity: 0.6; }
219
+ </style>
220
+
221
+ <div class="canvas-surface" id="surface"></div>
222
+
223
+ <div class="empty-state" id="empty">
224
+ <div style="font-size: 48px; opacity: 0.3;">+</div>
225
+ <div class="hint">Click + to add elements, or let AI place them</div>
226
+ </div>
227
+
228
+ <button class="insert-btn" id="insertBtn" title="Add element">+</button>
229
+
230
+ <div class="format-picker" id="formatPicker">
231
+ <input type="text" placeholder="Search formats..." id="formatSearch">
232
+ <div id="formatList"></div>
233
+ </div>
234
+
235
+ <script>
236
+ (function() {
237
+ 'use strict';
238
+
239
+ var surface = document.getElementById('surface');
240
+ var emptyEl = document.getElementById('empty');
241
+ var insertBtn = document.getElementById('insertBtn');
242
+ var formatPicker = document.getElementById('formatPicker');
243
+ var formatSearch = document.getElementById('formatSearch');
244
+ var formatList = document.getElementById('formatList');
245
+
246
+ // ── Scene State (local mirror) ──
247
+ var elements = {}; // id → { ...CanvasElement }
248
+ var containers = {}; // id → HTMLElement
249
+ var selected = null; // currently selected element ID
250
+
251
+ // ── Rendering ──
252
+
253
+ function upsertElement(el) {
254
+ elements[el.id] = el;
255
+
256
+ var container = containers[el.id];
257
+ if (!container) {
258
+ container = createContainer(el);
259
+ containers[el.id] = container;
260
+ surface.appendChild(container);
261
+ }
262
+
263
+ // Update position/size
264
+ container.style.left = el.x + 'px';
265
+ container.style.top = el.y + 'px';
266
+ container.style.width = el.w + 'px';
267
+ container.style.height = el.h + 'px';
268
+ container.style.zIndex = el.z;
269
+
270
+ // Update label
271
+ var labelEl = container.querySelector('.ce-label');
272
+ if (labelEl) labelEl.textContent = el.label || el.id;
273
+
274
+ var formatEl = container.querySelector('.ce-format');
275
+ if (formatEl) formatEl.textContent = el.format;
276
+
277
+ // Re-render content
278
+ var body = container.querySelector('.ce-body');
279
+ if (body && el.data !== undefined && el.data !== null) {
280
+ window.photon.render(body, el.data, el.format);
281
+ }
282
+
283
+ updateEmpty();
284
+ }
285
+
286
+ function removeElement(id) {
287
+ delete elements[id];
288
+ if (containers[id]) {
289
+ containers[id].remove();
290
+ delete containers[id];
291
+ }
292
+ if (selected === id) selected = null;
293
+ updateEmpty();
294
+ }
295
+
296
+ function clearAll() {
297
+ for (var id in containers) containers[id].remove();
298
+ elements = {};
299
+ containers = {};
300
+ selected = null;
301
+ updateEmpty();
302
+ }
303
+
304
+ function updateEmpty() {
305
+ emptyEl.style.display = Object.keys(elements).length === 0 ? 'flex' : 'none';
306
+ }
307
+
308
+ // ── Create Element Container ──
309
+
310
+ function createContainer(el) {
311
+ var div = document.createElement('div');
312
+ div.className = 'ce';
313
+ div.setAttribute('data-id', el.id);
314
+
315
+ // Title bar
316
+ var bar = document.createElement('div');
317
+ bar.className = 'ce-bar';
318
+
319
+ var label = document.createElement('span');
320
+ label.className = 'ce-label';
321
+ label.textContent = el.label || el.id;
322
+
323
+ var fmt = document.createElement('span');
324
+ fmt.className = 'ce-format';
325
+ fmt.textContent = el.format;
326
+
327
+ var del = document.createElement('span');
328
+ del.className = 'ce-delete';
329
+ del.textContent = '\u00d7';
330
+ del.addEventListener('click', function(e) {
331
+ e.stopPropagation();
332
+ window.photon.callTool('remove', { id: el.id });
333
+ });
334
+
335
+ bar.appendChild(label);
336
+ bar.appendChild(fmt);
337
+ bar.appendChild(del);
338
+
339
+ // Body
340
+ var body = document.createElement('div');
341
+ body.className = 'ce-body';
342
+
343
+ // Resize handle
344
+ var resize = document.createElement('div');
345
+ resize.className = 'ce-resize';
346
+
347
+ div.appendChild(bar);
348
+ div.appendChild(body);
349
+ div.appendChild(resize);
350
+
351
+ // ── Selection ──
352
+ div.addEventListener('pointerdown', function() {
353
+ selectElement(el.id);
354
+ });
355
+
356
+ // ── Drag (title bar) ──
357
+ setupDrag(bar, el.id);
358
+
359
+ // ── Resize (corner handle) ──
360
+ setupResize(resize, el.id);
361
+
362
+ return div;
363
+ }
364
+
365
+ function selectElement(id) {
366
+ // Deselect previous
367
+ if (selected && containers[selected]) {
368
+ containers[selected].classList.remove('selected');
369
+ }
370
+ selected = id;
371
+ if (containers[id]) {
372
+ containers[id].classList.add('selected');
373
+ // Bring to front
374
+ var maxZ = 0;
375
+ for (var k in elements) {
376
+ if (elements[k].z > maxZ) maxZ = elements[k].z;
377
+ }
378
+ if (elements[id] && elements[id].z <= maxZ) {
379
+ elements[id].z = maxZ + 1;
380
+ containers[id].style.zIndex = elements[id].z;
381
+ }
382
+ }
383
+ }
384
+
385
+ // ── Drag Logic ──
386
+
387
+ function setupDrag(handle, id) {
388
+ var dragging = false;
389
+ var startX, startY, origX, origY;
390
+
391
+ handle.addEventListener('pointerdown', function(e) {
392
+ if (e.button !== 0) return;
393
+ e.preventDefault();
394
+ e.stopPropagation();
395
+ dragging = true;
396
+ startX = e.clientX;
397
+ startY = e.clientY;
398
+ var el = elements[id];
399
+ origX = el ? el.x : 0;
400
+ origY = el ? el.y : 0;
401
+ handle.setPointerCapture(e.pointerId);
402
+ selectElement(id);
403
+ });
404
+
405
+ handle.addEventListener('pointermove', function(e) {
406
+ if (!dragging) return;
407
+ var dx = e.clientX - startX;
408
+ var dy = e.clientY - startY;
409
+ var newX = Math.max(0, origX + dx);
410
+ var newY = Math.max(0, origY + dy);
411
+ var container = containers[id];
412
+ if (container) {
413
+ container.style.left = newX + 'px';
414
+ container.style.top = newY + 'px';
415
+ }
416
+ });
417
+
418
+ handle.addEventListener('pointerup', function(e) {
419
+ if (!dragging) return;
420
+ dragging = false;
421
+ var dx = e.clientX - startX;
422
+ var dy = e.clientY - startY;
423
+ var newX = Math.max(0, origX + dx);
424
+ var newY = Math.max(0, origY + dy);
425
+ // Sync to server
426
+ window.photon.callTool('put', { id: id, x: newX, y: newY });
427
+ });
428
+ }
429
+
430
+ // ── Resize Logic ──
431
+
432
+ function setupResize(handle, id) {
433
+ var resizing = false;
434
+ var startX, startY, origW, origH;
435
+
436
+ handle.addEventListener('pointerdown', function(e) {
437
+ if (e.button !== 0) return;
438
+ e.preventDefault();
439
+ e.stopPropagation();
440
+ resizing = true;
441
+ startX = e.clientX;
442
+ startY = e.clientY;
443
+ var el = elements[id];
444
+ origW = el ? el.w : 300;
445
+ origH = el ? el.h : 200;
446
+ handle.setPointerCapture(e.pointerId);
447
+ });
448
+
449
+ handle.addEventListener('pointermove', function(e) {
450
+ if (!resizing) return;
451
+ var dx = e.clientX - startX;
452
+ var dy = e.clientY - startY;
453
+ var newW = Math.max(120, origW + dx);
454
+ var newH = Math.max(80, origH + dy);
455
+ var container = containers[id];
456
+ if (container) {
457
+ container.style.width = newW + 'px';
458
+ container.style.height = newH + 'px';
459
+ }
460
+ });
461
+
462
+ handle.addEventListener('pointerup', function(e) {
463
+ if (!resizing) return;
464
+ resizing = false;
465
+ var dx = e.clientX - startX;
466
+ var dy = e.clientY - startY;
467
+ var newW = Math.max(120, origW + dx);
468
+ var newH = Math.max(80, origH + dy);
469
+ // Sync to server
470
+ window.photon.callTool('put', { id: id, w: newW, h: newH });
471
+ });
472
+ }
473
+
474
+ // ── Deselect on surface click ──
475
+ surface.addEventListener('pointerdown', function(e) {
476
+ if (e.target === surface) {
477
+ if (selected && containers[selected]) {
478
+ containers[selected].classList.remove('selected');
479
+ }
480
+ selected = null;
481
+ }
482
+ });
483
+
484
+ // ── Delete with keyboard ──
485
+ document.addEventListener('keydown', function(e) {
486
+ if ((e.key === 'Delete' || e.key === 'Backspace') && selected) {
487
+ // Don't delete if typing in search
488
+ if (document.activeElement && document.activeElement.tagName === 'INPUT') return;
489
+ window.photon.callTool('remove', { id: selected });
490
+ }
491
+ });
492
+
493
+ // ── Format Picker ──
494
+
495
+ var pickerOpen = false;
496
+
497
+ insertBtn.addEventListener('click', function(e) {
498
+ e.stopPropagation();
499
+ pickerOpen = !pickerOpen;
500
+ formatPicker.classList.toggle('open', pickerOpen);
501
+ if (pickerOpen) {
502
+ formatSearch.value = '';
503
+ renderFormatList('');
504
+ formatSearch.focus();
505
+ }
506
+ });
507
+
508
+ document.addEventListener('pointerdown', function(e) {
509
+ if (pickerOpen && !formatPicker.contains(e.target) && e.target !== insertBtn) {
510
+ pickerOpen = false;
511
+ formatPicker.classList.remove('open');
512
+ }
513
+ });
514
+
515
+ formatSearch.addEventListener('input', function() {
516
+ renderFormatList(formatSearch.value.toLowerCase());
517
+ });
518
+
519
+ function renderFormatList(filter) {
520
+ var formats = window.photon.formats || [];
521
+ var catalog = {};
522
+ // formats might be array of names or object catalog
523
+ if (Array.isArray(formats)) {
524
+ formats.forEach(function(f) { catalog[f] = { data: '' }; });
525
+ } else {
526
+ catalog = formats;
527
+ }
528
+
529
+ var html = '';
530
+ var keys = Object.keys(catalog).sort();
531
+ for (var i = 0; i < keys.length; i++) {
532
+ var name = keys[i];
533
+ if (filter && name.indexOf(filter) === -1) continue;
534
+ var spec = catalog[name] || {};
535
+ html += '<div class="format-item" data-format="' + name + '">'
536
+ + '<span class="fi-name">' + name + '</span>'
537
+ + '<span class="fi-shape">' + (spec.data || '').substring(0, 30) + '</span>'
538
+ + '</div>';
539
+ }
540
+ formatList.innerHTML = html || '<div style="padding:8px;opacity:0.5">No formats found</div>';
541
+
542
+ // Bind clicks
543
+ var items = formatList.querySelectorAll('.format-item');
544
+ for (var j = 0; j < items.length; j++) {
545
+ items[j].addEventListener('click', function() {
546
+ var fmt = this.getAttribute('data-format');
547
+ insertElement(fmt);
548
+ pickerOpen = false;
549
+ formatPicker.classList.remove('open');
550
+ });
551
+ }
552
+ }
553
+
554
+ function insertElement(format) {
555
+ // Place near center of visible area
556
+ var scrollX = surface.scrollLeft || 0;
557
+ var scrollY = surface.scrollTop || 0;
558
+ var viewW = surface.clientWidth;
559
+ var viewH = surface.clientHeight;
560
+ var x = scrollX + Math.round(viewW / 2) - 150 + Math.round(Math.random() * 40 - 20);
561
+ var y = scrollY + Math.round(viewH / 2) - 100 + Math.round(Math.random() * 40 - 20);
562
+
563
+ var id = 'el_' + Date.now();
564
+
565
+ // Get example data from catalog
566
+ var catalog = window.photon.formats || {};
567
+ var spec = catalog[format];
568
+ var data = spec && spec.example ? spec.example : null;
569
+
570
+ window.photon.callTool('put', {
571
+ id: id,
572
+ format: format,
573
+ x: x,
574
+ y: y,
575
+ w: 300,
576
+ h: 200,
577
+ data: data,
578
+ label: format,
579
+ });
580
+ }
581
+
582
+ // ── Event Subscriptions ──
583
+
584
+ // Initial scene from main() result
585
+ window.photon.onResult(function(result) {
586
+ if (result && result.elements) {
587
+ for (var i = 0; i < result.elements.length; i++) {
588
+ upsertElement(result.elements[i]);
589
+ }
590
+ }
591
+ updateEmpty();
592
+ });
593
+
594
+ // Live updates from AI or other agents
595
+ window.photon.onEmit(function(event) {
596
+ if (!event) return;
597
+ if (event.emit === 'scene:put' && event.element) {
598
+ upsertElement(event.element);
599
+ } else if (event.emit === 'scene:remove' && event.id) {
600
+ removeElement(event.id);
601
+ } else if (event.emit === 'scene:clear') {
602
+ clearAll();
603
+ }
604
+ });
605
+
606
+ // Reconcile on load — fetch latest scene in case events were missed
607
+ setTimeout(function() {
608
+ window.photon.callTool('scene', {}).then(function(result) {
609
+ if (result && result.elements) {
610
+ // Clear and re-render from server truth
611
+ for (var id in containers) {
612
+ if (!result.elements.find(function(e) { return e.id === id; })) {
613
+ removeElement(id);
614
+ }
615
+ }
616
+ for (var i = 0; i < result.elements.length; i++) {
617
+ upsertElement(result.elements[i]);
618
+ }
619
+ }
620
+ }).catch(function() {});
621
+ }, 500);
622
+
623
+ })();
624
+ </script>
@@ -1 +1 @@
1
- {"version":3,"file":"resource-server.d.ts","sourceRoot":"","sources":["../src/resource-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,iFAAiF;AACjF,MAAM,WAAW,oBAAoB;IACnC,WAAW,CACT,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,GAAG,CAAC,CAAC;IAChB,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CACtD;AAED,sDAAsD;AACtD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC9D;AAED,qBAAa,cAAc;IAkBvB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,OAAO;IAlBjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAQrC;IAEF,0CAA0C;IAC1C,OAAO,CAAC,kBAAkB,CAGtB;gBAGM,YAAY,EAAE,oBAAoB,EAClC,OAAO,EAAE,qBAAqB;IAKxC;;OAEG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAI5D;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAK1E;;OAEG;IACH,aAAa,IAAI,MAAM;IAMvB;;;OAGG;IACH,iBAAiB,CACf,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAClE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAoC5E;;OAEG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAInC;;;OAGG;IACH,OAAO,CAAC,eAAe;IAMvB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAyBtB,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,GAAG;QAAE,SAAS,EAAE,GAAG,EAAE,CAAA;KAAE;IA2E1E,2BAA2B,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,GAAG;QAAE,iBAAiB,EAAE,GAAG,EAAE,CAAA;KAAE;IAiBpF,kBAAkB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,mBAAmB,GAAG,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC;IA2CrF;;OAEG;YACW,iBAAiB;IAgD/B;;OAEG;YACW,eAAe;IA+C7B;;OAEG;YACW,gBAAgB;IAW9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;;OAGG;IACH,qBAAqB,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,GAAG,MAAM;CA4W/D"}
1
+ {"version":3,"file":"resource-server.d.ts","sourceRoot":"","sources":["../src/resource-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,iFAAiF;AACjF,MAAM,WAAW,oBAAoB;IACnC,WAAW,CACT,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,GAAG,CAAC,CAAC;IAChB,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CACtD;AAED,sDAAsD;AACtD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC9D;AAED,qBAAa,cAAc;IAkBvB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,OAAO;IAlBjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAQrC;IAEF,0CAA0C;IAC1C,OAAO,CAAC,kBAAkB,CAGtB;gBAGM,YAAY,EAAE,oBAAoB,EAClC,OAAO,EAAE,qBAAqB;IAKxC;;OAEG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAI5D;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAK1E;;OAEG;IACH,aAAa,IAAI,MAAM;IAMvB;;;OAGG;IACH,iBAAiB,CACf,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAClE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAoC5E;;OAEG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAInC;;;OAGG;IACH,OAAO,CAAC,eAAe;IAMvB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAyBtB,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,GAAG;QAAE,SAAS,EAAE,GAAG,EAAE,CAAA;KAAE;IA2E1E,2BAA2B,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,GAAG;QAAE,iBAAiB,EAAE,GAAG,EAAE,CAAA;KAAE;IAiBpF,kBAAkB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,mBAAmB,GAAG,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC;IA2CrF;;OAEG;YACW,iBAAiB;IAqD/B;;OAEG;YACW,eAAe;IA+C7B;;OAEG;YACW,gBAAgB;IAW9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;;OAGG;IACH,qBAAqB,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,GAAG,MAAM;CA4W/D"}
@@ -269,7 +269,13 @@ export class ResourceServer {
269
269
  if (!ui || !ui.resolvedPath) {
270
270
  throw new Error(`UI asset not found: ${uri}`);
271
271
  }
272
- content = await readText(ui.resolvedPath);
272
+ if (ui.resolvedPath.endsWith('.tsx')) {
273
+ const { compileTsxCached } = await import('./tsx-compiler.js');
274
+ content = await compileTsxCached(ui.resolvedPath);
275
+ }
276
+ else {
277
+ content = await readText(ui.resolvedPath);
278
+ }
273
279
  }
274
280
  // Wrap .photon.html fragments in a full HTML document.
275
281
  const isFragment = !content.trimStart().toLowerCase().startsWith('<!doctype') &&