@portel/photon 1.20.1 → 1.21.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 (106) hide show
  1. package/README.md +5 -5
  2. package/dist/ag-ui/adapter.d.ts.map +1 -1
  3. package/dist/ag-ui/adapter.js +25 -0
  4. package/dist/ag-ui/adapter.js.map +1 -1
  5. package/dist/auto-ui/beam/routes/api-browse.d.ts.map +1 -1
  6. package/dist/auto-ui/beam/routes/api-browse.js +8 -49
  7. package/dist/auto-ui/beam/routes/api-browse.js.map +1 -1
  8. package/dist/auto-ui/beam.d.ts.map +1 -1
  9. package/dist/auto-ui/beam.js +23 -31
  10. package/dist/auto-ui/beam.js.map +1 -1
  11. package/dist/auto-ui/bridge/index.d.ts.map +1 -1
  12. package/dist/auto-ui/bridge/index.js +107 -11
  13. package/dist/auto-ui/bridge/index.js.map +1 -1
  14. package/dist/auto-ui/bridge/renderers.d.ts +14 -0
  15. package/dist/auto-ui/bridge/renderers.d.ts.map +1 -1
  16. package/dist/auto-ui/bridge/renderers.js +680 -57
  17. package/dist/auto-ui/bridge/renderers.js.map +1 -1
  18. package/dist/auto-ui/frontend/index.html +3 -3
  19. package/dist/auto-ui/frontend/pure-view.html +19 -19
  20. package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
  21. package/dist/auto-ui/streamable-http-transport.js +29 -0
  22. package/dist/auto-ui/streamable-http-transport.js.map +1 -1
  23. package/dist/auto-ui/ui-resolver.d.ts +25 -0
  24. package/dist/auto-ui/ui-resolver.d.ts.map +1 -0
  25. package/dist/auto-ui/ui-resolver.js +95 -0
  26. package/dist/auto-ui/ui-resolver.js.map +1 -0
  27. package/dist/beam-form.bundle.js +7 -7
  28. package/dist/beam-form.bundle.js.map +1 -1
  29. package/dist/beam.bundle.js +905 -185
  30. package/dist/beam.bundle.js.map +4 -4
  31. package/dist/cli/commands/build.d.ts.map +1 -1
  32. package/dist/cli/commands/build.js +9 -5
  33. package/dist/cli/commands/build.js.map +1 -1
  34. package/dist/cli/commands/init.d.ts.map +1 -1
  35. package/dist/cli/commands/init.js +90 -50
  36. package/dist/cli/commands/init.js.map +1 -1
  37. package/dist/cli/commands/publish.d.ts +14 -0
  38. package/dist/cli/commands/publish.d.ts.map +1 -0
  39. package/dist/cli/commands/publish.js +126 -0
  40. package/dist/cli/commands/publish.js.map +1 -0
  41. package/dist/cli/commands/run.d.ts.map +1 -1
  42. package/dist/cli/commands/run.js +2 -0
  43. package/dist/cli/commands/run.js.map +1 -1
  44. package/dist/cli/index.d.ts.map +1 -1
  45. package/dist/cli/index.js +3 -0
  46. package/dist/cli/index.js.map +1 -1
  47. package/dist/context.d.ts +6 -0
  48. package/dist/context.d.ts.map +1 -1
  49. package/dist/context.js +17 -5
  50. package/dist/context.js.map +1 -1
  51. package/dist/daemon/client.d.ts +9 -1
  52. package/dist/daemon/client.d.ts.map +1 -1
  53. package/dist/daemon/client.js +54 -1
  54. package/dist/daemon/client.js.map +1 -1
  55. package/dist/daemon/manager.d.ts +3 -0
  56. package/dist/daemon/manager.d.ts.map +1 -1
  57. package/dist/daemon/manager.js +88 -38
  58. package/dist/daemon/manager.js.map +1 -1
  59. package/dist/daemon/ownership.d.ts +12 -0
  60. package/dist/daemon/ownership.d.ts.map +1 -0
  61. package/dist/daemon/ownership.js +55 -0
  62. package/dist/daemon/ownership.js.map +1 -0
  63. package/dist/daemon/protocol.d.ts +3 -1
  64. package/dist/daemon/protocol.d.ts.map +1 -1
  65. package/dist/daemon/protocol.js +14 -2
  66. package/dist/daemon/protocol.js.map +1 -1
  67. package/dist/daemon/server.js +549 -83
  68. package/dist/daemon/server.js.map +1 -1
  69. package/dist/daemon/session-manager.d.ts +9 -1
  70. package/dist/daemon/session-manager.d.ts.map +1 -1
  71. package/dist/daemon/session-manager.js +54 -1
  72. package/dist/daemon/session-manager.js.map +1 -1
  73. package/dist/daemon/worker-manager.d.ts +12 -0
  74. package/dist/daemon/worker-manager.d.ts.map +1 -1
  75. package/dist/daemon/worker-manager.js +89 -6
  76. package/dist/daemon/worker-manager.js.map +1 -1
  77. package/dist/loader.d.ts +3 -9
  78. package/dist/loader.d.ts.map +1 -1
  79. package/dist/loader.js +168 -113
  80. package/dist/loader.js.map +1 -1
  81. package/dist/photon-cli-runner.d.ts.map +1 -1
  82. package/dist/photon-cli-runner.js +26 -2
  83. package/dist/photon-cli-runner.js.map +1 -1
  84. package/dist/photons/canvas/ui/canvas.photon.html +1493 -0
  85. package/dist/photons/canvas.photon.d.ts +400 -0
  86. package/dist/photons/canvas.photon.d.ts.map +1 -0
  87. package/dist/photons/canvas.photon.js +662 -0
  88. package/dist/photons/canvas.photon.js.map +1 -0
  89. package/dist/photons/canvas.photon.ts +814 -0
  90. package/dist/photons/publish.photon.d.ts +97 -0
  91. package/dist/photons/publish.photon.d.ts.map +1 -0
  92. package/dist/photons/publish.photon.js +569 -0
  93. package/dist/photons/publish.photon.js.map +1 -0
  94. package/dist/photons/publish.photon.ts +683 -0
  95. package/dist/photons/ui/canvas.photon.html +624 -0
  96. package/dist/resource-server.d.ts.map +1 -1
  97. package/dist/resource-server.js +7 -1
  98. package/dist/resource-server.js.map +1 -1
  99. package/dist/shared-utils.d.ts.map +1 -1
  100. package/dist/shared-utils.js +2 -2
  101. package/dist/shared-utils.js.map +1 -1
  102. package/dist/tsx-compiler.d.ts +23 -0
  103. package/dist/tsx-compiler.d.ts.map +1 -0
  104. package/dist/tsx-compiler.js +221 -0
  105. package/dist/tsx-compiler.js.map +1 -0
  106. 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') &&