@portel/photon 1.20.0 → 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 (149) 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/routes/api-config.d.ts.map +1 -1
  9. package/dist/auto-ui/beam/routes/api-config.js +161 -20
  10. package/dist/auto-ui/beam/routes/api-config.js.map +1 -1
  11. package/dist/auto-ui/beam.d.ts.map +1 -1
  12. package/dist/auto-ui/beam.js +24 -31
  13. package/dist/auto-ui/beam.js.map +1 -1
  14. package/dist/auto-ui/bridge/index.d.ts.map +1 -1
  15. package/dist/auto-ui/bridge/index.js +107 -11
  16. package/dist/auto-ui/bridge/index.js.map +1 -1
  17. package/dist/auto-ui/bridge/renderers.d.ts +14 -0
  18. package/dist/auto-ui/bridge/renderers.d.ts.map +1 -1
  19. package/dist/auto-ui/bridge/renderers.js +692 -61
  20. package/dist/auto-ui/bridge/renderers.js.map +1 -1
  21. package/dist/auto-ui/frontend/index.html +3 -3
  22. package/dist/auto-ui/frontend/pure-view.html +19 -19
  23. package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
  24. package/dist/auto-ui/streamable-http-transport.js +144 -28
  25. package/dist/auto-ui/streamable-http-transport.js.map +1 -1
  26. package/dist/auto-ui/ui-resolver.d.ts +25 -0
  27. package/dist/auto-ui/ui-resolver.d.ts.map +1 -0
  28. package/dist/auto-ui/ui-resolver.js +95 -0
  29. package/dist/auto-ui/ui-resolver.js.map +1 -0
  30. package/dist/beam-form.bundle.js +26 -189
  31. package/dist/beam-form.bundle.js.map +4 -4
  32. package/dist/beam.bundle.js +1646 -494
  33. package/dist/beam.bundle.js.map +4 -4
  34. package/dist/cli/commands/beam.d.ts.map +1 -1
  35. package/dist/cli/commands/beam.js +47 -30
  36. package/dist/cli/commands/beam.js.map +1 -1
  37. package/dist/cli/commands/build.d.ts.map +1 -1
  38. package/dist/cli/commands/build.js +36 -7
  39. package/dist/cli/commands/build.js.map +1 -1
  40. package/dist/cli/commands/daemon.d.ts.map +1 -1
  41. package/dist/cli/commands/daemon.js +12 -6
  42. package/dist/cli/commands/daemon.js.map +1 -1
  43. package/dist/cli/commands/init.d.ts.map +1 -1
  44. package/dist/cli/commands/init.js +90 -50
  45. package/dist/cli/commands/init.js.map +1 -1
  46. package/dist/cli/commands/mcp.d.ts.map +1 -1
  47. package/dist/cli/commands/mcp.js +18 -6
  48. package/dist/cli/commands/mcp.js.map +1 -1
  49. package/dist/cli/commands/publish.d.ts +14 -0
  50. package/dist/cli/commands/publish.d.ts.map +1 -0
  51. package/dist/cli/commands/publish.js +126 -0
  52. package/dist/cli/commands/publish.js.map +1 -0
  53. package/dist/cli/commands/run.d.ts.map +1 -1
  54. package/dist/cli/commands/run.js +2 -0
  55. package/dist/cli/commands/run.js.map +1 -1
  56. package/dist/cli/commands/serve.d.ts.map +1 -1
  57. package/dist/cli/commands/serve.js +14 -2
  58. package/dist/cli/commands/serve.js.map +1 -1
  59. package/dist/cli/index.d.ts.map +1 -1
  60. package/dist/cli/index.js +3 -0
  61. package/dist/cli/index.js.map +1 -1
  62. package/dist/cli-alias.d.ts.map +1 -1
  63. package/dist/cli-alias.js +2 -3
  64. package/dist/cli-alias.js.map +1 -1
  65. package/dist/context-store.d.ts +4 -4
  66. package/dist/context-store.d.ts.map +1 -1
  67. package/dist/context-store.js +18 -15
  68. package/dist/context-store.js.map +1 -1
  69. package/dist/context.d.ts +31 -2
  70. package/dist/context.d.ts.map +1 -1
  71. package/dist/context.js +86 -9
  72. package/dist/context.js.map +1 -1
  73. package/dist/daemon/client.d.ts +9 -1
  74. package/dist/daemon/client.d.ts.map +1 -1
  75. package/dist/daemon/client.js +58 -2
  76. package/dist/daemon/client.js.map +1 -1
  77. package/dist/daemon/manager.d.ts +5 -0
  78. package/dist/daemon/manager.d.ts.map +1 -1
  79. package/dist/daemon/manager.js +116 -34
  80. package/dist/daemon/manager.js.map +1 -1
  81. package/dist/daemon/ownership.d.ts +12 -0
  82. package/dist/daemon/ownership.d.ts.map +1 -0
  83. package/dist/daemon/ownership.js +55 -0
  84. package/dist/daemon/ownership.js.map +1 -0
  85. package/dist/daemon/protocol.d.ts +3 -1
  86. package/dist/daemon/protocol.d.ts.map +1 -1
  87. package/dist/daemon/protocol.js +14 -2
  88. package/dist/daemon/protocol.js.map +1 -1
  89. package/dist/daemon/server.js +587 -77
  90. package/dist/daemon/server.js.map +1 -1
  91. package/dist/daemon/session-manager.d.ts +9 -1
  92. package/dist/daemon/session-manager.d.ts.map +1 -1
  93. package/dist/daemon/session-manager.js +54 -1
  94. package/dist/daemon/session-manager.js.map +1 -1
  95. package/dist/daemon/worker-host.js +7 -0
  96. package/dist/daemon/worker-host.js.map +1 -1
  97. package/dist/daemon/worker-manager.d.ts +12 -0
  98. package/dist/daemon/worker-manager.d.ts.map +1 -1
  99. package/dist/daemon/worker-manager.js +147 -16
  100. package/dist/daemon/worker-manager.js.map +1 -1
  101. package/dist/daemon/worker-protocol.d.ts +3 -0
  102. package/dist/daemon/worker-protocol.d.ts.map +1 -1
  103. package/dist/deploy/cloudflare.d.ts.map +1 -1
  104. package/dist/deploy/cloudflare.js +2 -4
  105. package/dist/deploy/cloudflare.js.map +1 -1
  106. package/dist/loader.d.ts +10 -9
  107. package/dist/loader.d.ts.map +1 -1
  108. package/dist/loader.js +224 -115
  109. package/dist/loader.js.map +1 -1
  110. package/dist/marketplace-manager.d.ts +1 -1
  111. package/dist/marketplace-manager.d.ts.map +1 -1
  112. package/dist/marketplace-manager.js +5 -4
  113. package/dist/marketplace-manager.js.map +1 -1
  114. package/dist/photon-cli-runner.d.ts.map +1 -1
  115. package/dist/photon-cli-runner.js +66 -23
  116. package/dist/photon-cli-runner.js.map +1 -1
  117. package/dist/photon-doc-extractor.d.ts.map +1 -1
  118. package/dist/photon-doc-extractor.js +59 -15
  119. package/dist/photon-doc-extractor.js.map +1 -1
  120. package/dist/photons/canvas/ui/canvas.photon.html +1493 -0
  121. package/dist/photons/canvas.photon.d.ts +400 -0
  122. package/dist/photons/canvas.photon.d.ts.map +1 -0
  123. package/dist/photons/canvas.photon.js +662 -0
  124. package/dist/photons/canvas.photon.js.map +1 -0
  125. package/dist/photons/canvas.photon.ts +814 -0
  126. package/dist/photons/publish.photon.d.ts +97 -0
  127. package/dist/photons/publish.photon.d.ts.map +1 -0
  128. package/dist/photons/publish.photon.js +569 -0
  129. package/dist/photons/publish.photon.js.map +1 -0
  130. package/dist/photons/publish.photon.ts +683 -0
  131. package/dist/photons/ui/canvas.photon.html +624 -0
  132. package/dist/resource-server.d.ts.map +1 -1
  133. package/dist/resource-server.js +7 -1
  134. package/dist/resource-server.js.map +1 -1
  135. package/dist/server.d.ts.map +1 -1
  136. package/dist/server.js +14 -16
  137. package/dist/server.js.map +1 -1
  138. package/dist/shared-utils.d.ts +4 -0
  139. package/dist/shared-utils.d.ts.map +1 -1
  140. package/dist/shared-utils.js +24 -2
  141. package/dist/shared-utils.js.map +1 -1
  142. package/dist/template-manager.d.ts.map +1 -1
  143. package/dist/template-manager.js +56 -234
  144. package/dist/template-manager.js.map +1 -1
  145. package/dist/tsx-compiler.d.ts +23 -0
  146. package/dist/tsx-compiler.d.ts.map +1 -0
  147. package/dist/tsx-compiler.js +221 -0
  148. package/dist/tsx-compiler.js.map +1 -0
  149. package/package.json +7 -7
@@ -18105,9 +18105,9 @@ var theme = i`
18105
18105
  --radius-full: 9999px;
18106
18106
 
18107
18107
  /* Typography - same for all themes */
18108
- --font-display: 'Space Grotesk', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
18109
- --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
18110
- --font-mono: 'JetBrains Mono', monospace;
18108
+ --font-display: 'Sora', 'Space Grotesk', -apple-system, BlinkMacSystemFont, sans-serif;
18109
+ --font-sans: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
18110
+ --font-mono: 'Berkeley Mono', 'JetBrains Mono', 'Fira Code', monospace;
18111
18111
 
18112
18112
  /* Type scale */
18113
18113
  --text-3xl: 2rem;
@@ -18134,17 +18134,17 @@ var theme = i`
18134
18134
  /* Shared Utility Classes */
18135
18135
  .glass {
18136
18136
  background: var(--bg-glass);
18137
- backdrop-filter: blur(16px);
18138
- -webkit-backdrop-filter: blur(16px);
18139
18137
  border: 1px solid var(--border-glass);
18138
+ border-top-color: color-mix(in srgb, var(--border-glass) 100%, white 8%);
18139
+ border-left-color: color-mix(in srgb, var(--border-glass) 100%, white 5%);
18140
18140
  box-shadow: var(--shadow-md);
18141
18141
  }
18142
18142
 
18143
18143
  .glass-panel {
18144
18144
  background: var(--bg-glass-strong);
18145
- backdrop-filter: blur(24px);
18146
- -webkit-backdrop-filter: blur(24px);
18147
18145
  border: 1px solid var(--border-glass);
18146
+ border-top-color: color-mix(in srgb, var(--border-glass) 100%, white 8%);
18147
+ border-left-color: color-mix(in srgb, var(--border-glass) 100%, white 5%);
18148
18148
  border-radius: var(--radius-md);
18149
18149
  box-shadow: var(--shadow-sm);
18150
18150
  color: inherit;
@@ -19269,187 +19269,33 @@ function showToast(message, type = "info", duration4 = 3e3, action) {
19269
19269
  ToastManager.show(message, type, duration4, action);
19270
19270
  }
19271
19271
 
19272
- // src/auto-ui/frontend/components/confirm-dialog.ts
19273
- var ConfirmDialog = class extends i4 {
19274
- constructor() {
19275
- super(...arguments);
19276
- this.open = false;
19277
- this.message = "";
19278
- this.confirmLabel = "OK";
19279
- this.cancelLabel = "Cancel";
19280
- this.destructive = false;
19281
- }
19282
- show(message, options) {
19283
- this.message = message;
19284
- this.confirmLabel = options?.confirm ?? "OK";
19285
- this.cancelLabel = options?.cancel ?? "Cancel";
19286
- this.destructive = options?.destructive ?? false;
19287
- this.open = true;
19288
- return new Promise((resolve2) => {
19289
- this._resolve = resolve2;
19290
- });
19291
- }
19292
- _handleConfirm() {
19293
- this.open = false;
19294
- this._resolve?.(true);
19295
- }
19296
- _handleCancel() {
19297
- this.open = false;
19298
- this._resolve?.(false);
19299
- }
19300
- _handleKeydown(e8) {
19301
- if (e8.key === "Escape") this._handleCancel();
19302
- if (e8.key === "Enter") this._handleConfirm();
19303
- }
19304
- render() {
19305
- return b2`
19306
- <div class="dialog" @keydown=${(e8) => this._handleKeydown(e8)}>
19307
- <div class="message">${this.message}</div>
19308
- <div class="actions">
19309
- <button class="btn-cancel" @click=${() => this._handleCancel()}>
19310
- ${this.cancelLabel}
19311
- </button>
19312
- <button
19313
- class="btn-confirm ${this.destructive ? "destructive" : ""}"
19314
- @click=${() => this._handleConfirm()}
19315
- >
19316
- ${this.confirmLabel}
19317
- </button>
19318
- </div>
19319
- </div>
19320
- `;
19321
- }
19322
- };
19323
- ConfirmDialog.styles = [
19324
- theme,
19325
- i`
19326
- :host {
19327
- display: none;
19328
- }
19329
-
19330
- @keyframes backdrop-in {
19331
- from {
19332
- opacity: 0;
19333
- }
19334
- to {
19335
- opacity: 1;
19336
- }
19337
- }
19338
-
19339
- @keyframes content-in {
19340
- from {
19341
- opacity: 0;
19342
- transform: scale(0.95) translateY(8px);
19343
- }
19344
- to {
19345
- opacity: 1;
19346
- transform: scale(1) translateY(0);
19347
- }
19348
- }
19349
-
19350
- :host([open]) {
19351
- display: flex;
19352
- position: fixed;
19353
- inset: 0;
19354
- background: rgba(0, 0, 0, 0.6);
19355
- backdrop-filter: blur(4px);
19356
- z-index: 10001;
19357
- align-items: center;
19358
- justify-content: center;
19359
- animation: backdrop-in 0.15s ease-out both;
19360
- }
19361
-
19362
- .dialog {
19363
- background: var(--bg-panel);
19364
- border: 1px solid var(--border-glass);
19365
- border-radius: var(--radius-md, 12px);
19366
- padding: 24px;
19367
- max-width: 400px;
19368
- width: 90%;
19369
- box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.4);
19370
- animation: content-in 0.2s cubic-bezier(0.16, 1, 0.3, 1) both;
19371
- animation-delay: 0.05s;
19372
- }
19373
-
19374
- .message {
19375
- font-size: 14px;
19376
- line-height: 1.5;
19377
- color: var(--t-primary);
19378
- margin-bottom: 20px;
19379
- }
19380
-
19381
- .actions {
19382
- display: flex;
19383
- justify-content: flex-end;
19384
- gap: 8px;
19385
- }
19386
-
19387
- button {
19388
- padding: 8px 16px;
19389
- border-radius: var(--radius-sm, 6px);
19390
- font-size: 13px;
19391
- font-weight: 500;
19392
- cursor: pointer;
19393
- transition: all 0.15s ease;
19394
- font-family: inherit;
19395
- border: none;
19396
- }
19397
-
19398
- .btn-cancel {
19399
- background: var(--bg-glass);
19400
- color: var(--t-primary);
19401
- border: 1px solid var(--border-glass);
19402
- }
19403
-
19404
- .btn-cancel:hover {
19405
- background: var(--bg-glass-strong);
19406
- }
19407
-
19408
- .btn-confirm {
19409
- background: var(--accent);
19410
- color: #fff;
19411
- }
19412
-
19413
- .btn-confirm:hover {
19414
- opacity: 0.9;
19415
- }
19416
-
19417
- .btn-confirm.destructive {
19418
- background: hsl(0, 60%, 50%);
19419
- }
19420
-
19421
- .btn-confirm.destructive:hover {
19422
- background: hsl(0, 60%, 45%);
19423
- }
19424
- `
19425
- ];
19426
- __decorateClass([
19427
- n4({ type: Boolean, reflect: true })
19428
- ], ConfirmDialog.prototype, "open", 2);
19429
- __decorateClass([
19430
- n4({ type: String })
19431
- ], ConfirmDialog.prototype, "message", 2);
19432
- __decorateClass([
19433
- n4({ type: String })
19434
- ], ConfirmDialog.prototype, "confirmLabel", 2);
19435
- __decorateClass([
19436
- n4({ type: String })
19437
- ], ConfirmDialog.prototype, "cancelLabel", 2);
19438
- __decorateClass([
19439
- n4({ type: Boolean })
19440
- ], ConfirmDialog.prototype, "destructive", 2);
19441
- ConfirmDialog = __decorateClass([
19442
- t4("confirm-dialog")
19443
- ], ConfirmDialog);
19444
- async function confirmDialog(message, options) {
19445
- const beamApp = document.querySelector("beam-app");
19446
- const root = beamApp?.shadowRoot ?? document.body;
19447
- let dialog = root.querySelector("confirm-dialog");
19448
- if (!dialog) {
19449
- dialog = document.createElement("confirm-dialog");
19450
- root.appendChild(dialog);
19451
- }
19452
- return dialog.show(message, options);
19272
+ // src/auto-ui/frontend/utils/elicit.ts
19273
+ function elicit(data) {
19274
+ return new Promise((resolve2) => {
19275
+ document.dispatchEvent(
19276
+ new CustomEvent("beam:elicit-local", {
19277
+ detail: { data, resolve: resolve2 }
19278
+ })
19279
+ );
19280
+ });
19281
+ }
19282
+ async function confirmElicit(message, options) {
19283
+ const result = await elicit({
19284
+ ask: "confirm",
19285
+ message,
19286
+ default: false,
19287
+ ...options?.confirm && { placeholder: options.confirm }
19288
+ });
19289
+ return result.action === "accept" && result.value !== false;
19290
+ }
19291
+ async function promptElicit(message, defaultValue = "") {
19292
+ const result = await elicit({
19293
+ ask: "text",
19294
+ message,
19295
+ default: defaultValue
19296
+ });
19297
+ if (result.action === "cancel") return null;
19298
+ return result.value ?? null;
19453
19299
  }
19454
19300
 
19455
19301
  // node_modules/lit-html/directives/unsafe-svg.js
@@ -19682,10 +19528,10 @@ function oklchToRgba(L3, C3, H3, alpha2) {
19682
19528
  return `rgba(${Math.round(clamp01(r7) * 255)}, ${Math.round(clamp01(g3) * 255)}, ${Math.round(clamp01(b3) * 255)}, ${alpha2})`;
19683
19529
  }
19684
19530
  var themePresets = [
19685
- { name: "Default Violet", config: { hue: 260, chroma: 0.15, lightness: 0.65 } },
19531
+ { name: "Amber", config: { hue: 75, chroma: 0.14, lightness: 0.7 } },
19686
19532
  { name: "Ocean Blue", config: { hue: 220, chroma: 0.12, lightness: 0.6 } },
19687
19533
  { name: "Emerald", config: { hue: 155, chroma: 0.14, lightness: 0.6 } },
19688
- { name: "Amber", config: { hue: 75, chroma: 0.14, lightness: 0.7 } },
19534
+ { name: "Violet", config: { hue: 260, chroma: 0.15, lightness: 0.65 } },
19689
19535
  { name: "Rose", config: { hue: 350, chroma: 0.14, lightness: 0.62 } },
19690
19536
  { name: "Monochrome", config: { hue: 0, chroma: 0, lightness: 0.65 } }
19691
19537
  ];
@@ -19898,20 +19744,20 @@ var colorPalette = {
19898
19744
  95: "#f2f2f2",
19899
19745
  100: "#ffffff"
19900
19746
  },
19901
- // Light-theme neutrals (warm cream/beige undertone)
19747
+ // Light-theme neutrals (cool mineral paper)
19902
19748
  neutralLight: {
19903
- 85: "#C8C0B8",
19749
+ 85: "#B0BCCC",
19904
19750
  // heavy borders / dividers
19905
- 88: "#D0C9C1",
19751
+ 88: "#D8E0EA",
19906
19752
  // surface-container-highest
19907
- 91: "#DDD7CF",
19753
+ 91: "#E4EAF1",
19908
19754
  // surface-container-high
19909
- 94: "#EAE4DD",
19910
- // bg-app — warm cream structure
19911
- 96: "#F0EBE5",
19755
+ 94: "#EEF1F5",
19756
+ // bg-app — mineral paper
19757
+ 96: "#F5F7FA",
19912
19758
  // surface-container
19913
- 98: "#F8F5F1"
19914
- // surface — warm off-white panels
19759
+ 98: "#FFFFFF"
19760
+ // surface — white panels
19915
19761
  },
19916
19762
  // Primary (blue - trust, action)
19917
19763
  primary: {
@@ -20004,24 +19850,24 @@ var colorsDark = {
20004
19850
  scrim: "rgba(0, 0, 0, 0.5)"
20005
19851
  };
20006
19852
  var colorsLight = {
20007
- // Surfaces (cool blue-gray, higher contrast between levels)
19853
+ // Surfaces (cool mineral paper)
20008
19854
  surface: colorPalette.neutralLight[98],
20009
- // #F6F7F9 — panels
19855
+ // #FFFFFF — panels
20010
19856
  surfaceContainer: colorPalette.neutralLight[96],
20011
- // #EBEEF2 — containers
19857
+ // #F5F7FA — containers
20012
19858
  surfaceContainerHigh: colorPalette.neutralLight[91],
20013
- // #D5DBE1
19859
+ // #E4EAF1
20014
19860
  surfaceContainerHighest: colorPalette.neutralLight[88],
20015
- // #C4CDD5
19861
+ // #D8E0EA
20016
19862
  surfaceBright: colorPalette.neutral[100],
20017
19863
  // #FFFFFF — overlays/modals
20018
- // Text on surfaces (warm charcoal, high contrast)
20019
- onSurface: "#2C2420",
20020
- // warm brown-charcoal — WCAG AAA
20021
- onSurfaceVariant: "#4A3F38",
20022
- // warm dark brown for readability
20023
- onSurfaceMuted: "#6B5E54",
20024
- // warm muted brown — WCAG AA
19864
+ // Text on surfaces (cool ink, high contrast)
19865
+ onSurface: "#0D1420",
19866
+ // dark ink — WCAG AAA
19867
+ onSurfaceVariant: "#3A4A5C",
19868
+ // cool dark for readability
19869
+ onSurfaceMuted: "#5F6B7A",
19870
+ // steel muted — WCAG AA
20025
19871
  // Primary (darker for light theme)
20026
19872
  primary: colorPalette.primary[40],
20027
19873
  primaryContainer: colorPalette.primary[90],
@@ -20046,11 +19892,11 @@ var colorsLight = {
20046
19892
  onError: colorPalette.neutral[100],
20047
19893
  // white text
20048
19894
  onErrorContainer: colorPalette.error[10],
20049
- // Outline (warm, visible but not harsh)
20050
- outline: "#9B9088",
20051
- // warm gray-brown for visibility
20052
- outlineVariant: "#D5CFC8",
20053
- // warm border, not washed out
19895
+ // Outline (cool, visible but not harsh)
19896
+ outline: "#8893A0",
19897
+ // cool steel for visibility
19898
+ outlineVariant: "#C8D2DE",
19899
+ // cool border, not washed out
20054
19900
  // Scrim (overlay — lighter than dark theme's 0.5)
20055
19901
  scrim: "rgba(0, 0, 0, 0.2)"
20056
19902
  };
@@ -20297,10 +20143,10 @@ var ThemeSettings = class extends i4 {
20297
20143
  constructor() {
20298
20144
  super(...arguments);
20299
20145
  this.currentTheme = "dark";
20300
- this._hue = 260;
20301
- this._chroma = 0.15;
20302
- this._lightness = 0.65;
20303
- this._presetName = "Default Violet";
20146
+ this._hue = 75;
20147
+ this._chroma = 0.14;
20148
+ this._lightness = 0.7;
20149
+ this._presetName = "Amber";
20304
20150
  this._previousConfig = null;
20305
20151
  }
20306
20152
  connectedCallback() {
@@ -20387,10 +20233,10 @@ var ThemeSettings = class extends i4 {
20387
20233
  }
20388
20234
  _reset() {
20389
20235
  localStorage.removeItem(THEME_CONFIG_KEY);
20390
- this._hue = 260;
20391
- this._chroma = 0.15;
20392
- this._lightness = 0.65;
20393
- this._presetName = "Default Violet";
20236
+ this._hue = 75;
20237
+ this._chroma = 0.14;
20238
+ this._lightness = 0.7;
20239
+ this._presetName = "Amber";
20394
20240
  this.dispatchEvent(new CustomEvent("oklch-theme-reset", { bubbles: true, composed: true }));
20395
20241
  }
20396
20242
  _revert() {
@@ -20715,16 +20561,16 @@ ThemeSettings.styles = [
20715
20561
  .chroma-slider {
20716
20562
  background: linear-gradient(
20717
20563
  to right,
20718
- oklch(0.65 0 var(--hue-val, 260)),
20719
- oklch(0.65 0.3 var(--hue-val, 260))
20564
+ oklch(0.65 0 var(--hue-val, 75)),
20565
+ oklch(0.65 0.3 var(--hue-val, 75))
20720
20566
  );
20721
20567
  }
20722
20568
 
20723
20569
  .lightness-slider {
20724
20570
  background: linear-gradient(
20725
20571
  to right,
20726
- oklch(0.2 0.1 var(--hue-val, 260)),
20727
- oklch(0.9 0.1 var(--hue-val, 260))
20572
+ oklch(0.2 0.1 var(--hue-val, 75)),
20573
+ oklch(0.9 0.1 var(--hue-val, 75))
20728
20574
  );
20729
20575
  }
20730
20576
 
@@ -20857,6 +20703,258 @@ function loadSavedThemeConfig() {
20857
20703
  return null;
20858
20704
  }
20859
20705
 
20706
+ // src/auto-ui/frontend/components/pending-approvals.ts
20707
+ var PendingApprovals = class extends i4 {
20708
+ constructor() {
20709
+ super(...arguments);
20710
+ this.approvals = [];
20711
+ this._resolving = /* @__PURE__ */ new Set();
20712
+ }
20713
+ render() {
20714
+ return b2`
20715
+ <div class="header">
20716
+ <span class="header-title">${shieldCheck} Pending Approvals</span>
20717
+ <button
20718
+ class="close-btn"
20719
+ @click=${() => this.dispatchEvent(new CustomEvent("close", { bubbles: true, composed: true }))}
20720
+ aria-label="Close"
20721
+ >
20722
+ ${xMark}
20723
+ </button>
20724
+ </div>
20725
+
20726
+ <div class="content">
20727
+ ${this.approvals.length === 0 ? b2`
20728
+ <div class="empty">
20729
+ ${shieldCheck}
20730
+ <div>No pending approvals</div>
20731
+ </div>
20732
+ ` : this.approvals.map((a5) => this._renderApproval(a5))}
20733
+ </div>
20734
+ `;
20735
+ }
20736
+ _renderApproval(approval) {
20737
+ const isResolving = this._resolving.has(approval.id);
20738
+ const timeLeft = this._formatTimeLeft(approval.expiresAt);
20739
+ return b2`
20740
+ <div class="approval-card ${approval.destructive ? "destructive" : ""}">
20741
+ <div class="approval-meta">
20742
+ <span>${approval.photon}.${approval.method}</span>
20743
+ ${approval.destructive ? b2`<span class="destructive-label">${warning} destructive</span>` : A}
20744
+ </div>
20745
+ <div class="approval-message">${approval.message}</div>
20746
+ ${approval.preview ? b2`<div class="preview">
20747
+ ${typeof approval.preview === "string" ? approval.preview : JSON.stringify(approval.preview, null, 2)}
20748
+ </div>` : A}
20749
+ <div class="expiry">Expires ${timeLeft}</div>
20750
+ <div class="actions">
20751
+ <button
20752
+ class="btn btn-reject"
20753
+ ?disabled=${isResolving}
20754
+ @click=${() => this._respond(approval, false)}
20755
+ >
20756
+ ${xMark} Reject
20757
+ </button>
20758
+ <button
20759
+ class="btn btn-approve"
20760
+ ?disabled=${isResolving}
20761
+ @click=${() => this._respond(approval, true)}
20762
+ >
20763
+ ${check} Approve
20764
+ </button>
20765
+ </div>
20766
+ </div>
20767
+ `;
20768
+ }
20769
+ _respond(approval, approved) {
20770
+ this._resolving.add(approval.id);
20771
+ this.requestUpdate();
20772
+ this.dispatchEvent(
20773
+ new CustomEvent("approval-response", {
20774
+ detail: { approvalId: approval.id, photon: approval.photon, approved },
20775
+ bubbles: true,
20776
+ composed: true
20777
+ })
20778
+ );
20779
+ }
20780
+ _formatTimeLeft(expiresAt) {
20781
+ const diff = new Date(expiresAt).getTime() - Date.now();
20782
+ if (diff <= 0) return "expired";
20783
+ const hours = Math.floor(diff / (1e3 * 60 * 60));
20784
+ const minutes = Math.floor(diff % (1e3 * 60 * 60) / (1e3 * 60));
20785
+ if (hours > 0) return `in ${hours}h ${minutes}m`;
20786
+ return `in ${minutes}m`;
20787
+ }
20788
+ };
20789
+ PendingApprovals.styles = [
20790
+ theme,
20791
+ buttons,
20792
+ i`
20793
+ :host {
20794
+ display: flex;
20795
+ flex-direction: column;
20796
+ height: 100%;
20797
+ color: var(--t-primary);
20798
+ }
20799
+
20800
+ .header {
20801
+ display: flex;
20802
+ align-items: center;
20803
+ justify-content: space-between;
20804
+ padding: var(--space-sm) var(--space-md);
20805
+ border-bottom: 1px solid var(--t-border);
20806
+ }
20807
+
20808
+ .header-title {
20809
+ display: flex;
20810
+ align-items: center;
20811
+ gap: var(--space-xs);
20812
+ font-weight: 600;
20813
+ font-size: var(--text-sm);
20814
+ }
20815
+
20816
+ .close-btn {
20817
+ background: none;
20818
+ border: none;
20819
+ color: var(--t-secondary);
20820
+ cursor: pointer;
20821
+ padding: var(--space-xs);
20822
+ border-radius: var(--radius-sm);
20823
+ display: flex;
20824
+ align-items: center;
20825
+ }
20826
+
20827
+ .close-btn:hover {
20828
+ background: var(--t-hover);
20829
+ }
20830
+
20831
+ .content {
20832
+ flex: 1;
20833
+ overflow-y: auto;
20834
+ padding: var(--space-sm);
20835
+ }
20836
+
20837
+ .empty {
20838
+ display: flex;
20839
+ flex-direction: column;
20840
+ align-items: center;
20841
+ justify-content: center;
20842
+ padding: var(--space-xl);
20843
+ text-align: center;
20844
+ color: var(--t-secondary);
20845
+ }
20846
+
20847
+ .empty svg {
20848
+ opacity: 0.4;
20849
+ margin-bottom: var(--space-sm);
20850
+ width: 32px;
20851
+ height: 32px;
20852
+ }
20853
+
20854
+ .approval-card {
20855
+ border: 1px solid var(--t-border);
20856
+ border-radius: var(--radius-md);
20857
+ padding: var(--space-sm) var(--space-md);
20858
+ margin-bottom: var(--space-sm);
20859
+ background: var(--t-surface);
20860
+ }
20861
+
20862
+ .approval-card.destructive {
20863
+ border-color: hsl(0, 60%, 50%);
20864
+ }
20865
+
20866
+ .approval-meta {
20867
+ display: flex;
20868
+ align-items: center;
20869
+ gap: var(--space-xs);
20870
+ font-size: var(--text-xs);
20871
+ color: var(--t-secondary);
20872
+ margin-bottom: var(--space-xs);
20873
+ }
20874
+
20875
+ .approval-message {
20876
+ font-size: var(--text-sm);
20877
+ margin-bottom: var(--space-sm);
20878
+ }
20879
+
20880
+ .preview {
20881
+ font-size: var(--text-xs);
20882
+ color: var(--t-secondary);
20883
+ background: var(--t-bg);
20884
+ padding: var(--space-xs) var(--space-sm);
20885
+ border-radius: var(--radius-sm);
20886
+ margin-bottom: var(--space-sm);
20887
+ max-height: 80px;
20888
+ overflow-y: auto;
20889
+ font-family: var(--font-mono);
20890
+ white-space: pre-wrap;
20891
+ }
20892
+
20893
+ .expiry {
20894
+ font-size: var(--text-xs);
20895
+ color: var(--t-secondary);
20896
+ }
20897
+
20898
+ .actions {
20899
+ display: flex;
20900
+ gap: var(--space-xs);
20901
+ margin-top: var(--space-sm);
20902
+ }
20903
+
20904
+ .btn {
20905
+ flex: 1;
20906
+ padding: var(--space-xs) var(--space-sm);
20907
+ border: 1px solid var(--t-border);
20908
+ border-radius: var(--radius-sm);
20909
+ cursor: pointer;
20910
+ font-size: var(--text-xs);
20911
+ font-weight: 600;
20912
+ display: flex;
20913
+ align-items: center;
20914
+ justify-content: center;
20915
+ gap: var(--space-xs);
20916
+ transition: all 0.15s;
20917
+ }
20918
+
20919
+ .btn-approve {
20920
+ background: hsl(142, 60%, 45%);
20921
+ color: white;
20922
+ border-color: hsl(142, 60%, 40%);
20923
+ }
20924
+
20925
+ .btn-approve:hover {
20926
+ background: hsl(142, 60%, 40%);
20927
+ }
20928
+
20929
+ .btn-reject {
20930
+ background: var(--t-surface);
20931
+ color: var(--t-primary);
20932
+ }
20933
+
20934
+ .btn-reject:hover {
20935
+ background: var(--t-hover);
20936
+ }
20937
+
20938
+ .destructive-label {
20939
+ display: inline-flex;
20940
+ align-items: center;
20941
+ gap: 2px;
20942
+ color: hsl(0, 70%, 55%);
20943
+ font-size: var(--text-2xs);
20944
+ font-weight: 600;
20945
+ }
20946
+ `
20947
+ ];
20948
+ __decorateClass([
20949
+ n4({ type: Array })
20950
+ ], PendingApprovals.prototype, "approvals", 2);
20951
+ __decorateClass([
20952
+ r5()
20953
+ ], PendingApprovals.prototype, "_resolving", 2);
20954
+ PendingApprovals = __decorateClass([
20955
+ t4("pending-approvals")
20956
+ ], PendingApprovals);
20957
+
20860
20958
  // src/auto-ui/frontend/services/photon-instance-manager.ts
20861
20959
  var SimpleEventEmitter = class {
20862
20960
  constructor() {
@@ -21645,6 +21743,32 @@ var MCPClientService = class {
21645
21743
  return { success: false };
21646
21744
  }
21647
21745
  }
21746
+ /**
21747
+ * Send approval response (approve/reject) for a pending approval
21748
+ */
21749
+ async sendApprovalResponse(approvalId, photon, approved) {
21750
+ try {
21751
+ await this.sendRequest("beam/approval-response", {
21752
+ approvalId,
21753
+ photon,
21754
+ approved
21755
+ });
21756
+ return { success: true };
21757
+ } catch {
21758
+ return { success: false };
21759
+ }
21760
+ }
21761
+ /**
21762
+ * Fetch all pending approvals from the server
21763
+ */
21764
+ async fetchPendingApprovals() {
21765
+ try {
21766
+ const result = await this.sendRequest("beam/approvals-list", {});
21767
+ return result?.approvals || [];
21768
+ } catch {
21769
+ return [];
21770
+ }
21771
+ }
21648
21772
  /**
21649
21773
  * Get rich help documentation for a photon via beam/photon-help tool
21650
21774
  */
@@ -21938,6 +22062,12 @@ var MCPClientService = class {
21938
22062
  case "beam/elicitation":
21939
22063
  this.emit("elicitation", notification.params);
21940
22064
  break;
22065
+ case "beam/elicitation-deferred":
22066
+ this.emit("elicitation-deferred", notification.params);
22067
+ break;
22068
+ case "beam/approval-resolved":
22069
+ this.emit("approval-resolved", notification.params);
22070
+ break;
21941
22071
  case "beam/result":
21942
22072
  this.emit("result", notification.params);
21943
22073
  break;
@@ -21959,6 +22089,9 @@ var MCPClientService = class {
21959
22089
  case "beam/render":
21960
22090
  this.emit("render", notification.params);
21961
22091
  break;
22092
+ case "beam/canvas":
22093
+ this.emit("canvas", notification.params);
22094
+ break;
21962
22095
  case "photon/board-update":
21963
22096
  this.emit("board-update", notification.params);
21964
22097
  break;
@@ -22528,6 +22661,7 @@ var BeamApp = class extends i4 {
22528
22661
  this._runningTests = false;
22529
22662
  this._selectedMethod = null;
22530
22663
  this._lastResult = null;
22664
+ this._canvasActive = false;
22531
22665
  this._customUiRevision = 0;
22532
22666
  this._customFormatUri = null;
22533
22667
  this._lastFormParams = {};
@@ -22542,6 +22676,8 @@ var BeamApp = class extends i4 {
22542
22676
  this._photonHelpLoading = false;
22543
22677
  this._elicitationData = null;
22544
22678
  this._showElicitation = false;
22679
+ this._showApprovals = false;
22680
+ this._pendingApprovalsList = [];
22545
22681
  this._protocolMode = "legacy";
22546
22682
  this._selectedMcpAppUri = null;
22547
22683
  this._mcpReady = false;
@@ -22889,7 +23025,7 @@ var BeamApp = class extends i4 {
22889
23025
  this._handleRemove = async () => {
22890
23026
  this._closeSettingsMenu();
22891
23027
  if (this._selectedPhoton && this._mcpReady) {
22892
- if (await confirmDialog(`Remove ${this._selectedPhoton.name} from this workspace?`, {
23028
+ if (await confirmElicit(`Remove ${this._selectedPhoton.name} from this workspace?`, {
22893
23029
  confirm: "Remove",
22894
23030
  destructive: true
22895
23031
  })) {
@@ -22900,22 +23036,42 @@ var BeamApp = class extends i4 {
22900
23036
  }
22901
23037
  }
22902
23038
  };
22903
- this._handleCopyMCPConfig = async () => {
23039
+ this._copyConfigSnippet = async (transport) => {
22904
23040
  if (!this._selectedPhoton) return;
23041
+ const name2 = this._selectedPhoton.name;
22905
23042
  try {
22906
- const res = await fetch(
22907
- `/api/export/mcp-config?photon=${encodeURIComponent(this._selectedPhoton.name)}`,
22908
- {
22909
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
23043
+ let config3;
23044
+ if (transport === "url") {
23045
+ const beamUrl = `${location.protocol}//${location.host}/mcp`;
23046
+ config3 = { mcpServers: { [name2]: { url: beamUrl } } };
23047
+ } else {
23048
+ const res = await fetch("/api/export/mcp-config", {
23049
+ signal: AbortSignal.timeout(3e3)
23050
+ });
23051
+ if (res.ok) {
23052
+ const all = await res.json();
23053
+ const entry = all.mcpServers?.[name2];
23054
+ if (entry) {
23055
+ config3 = { mcpServers: { [name2]: entry } };
23056
+ } else {
23057
+ config3 = {
23058
+ mcpServers: {
23059
+ [name2]: { command: "npx", args: ["-y", "@portel/photon", "mcp", name2] }
23060
+ }
23061
+ };
23062
+ }
23063
+ } else {
23064
+ config3 = {
23065
+ mcpServers: { [name2]: { command: "npx", args: ["-y", "@portel/photon", "mcp", name2] } }
23066
+ };
22910
23067
  }
22911
- );
22912
- if (!res.ok) throw new Error("Failed to fetch config");
22913
- const config3 = await res.json();
23068
+ }
22914
23069
  await navigator.clipboard.writeText(JSON.stringify(config3, null, 2));
22915
- showToast("MCP config copied \u2014 paste into Claude Desktop settings", "success");
23070
+ const label = transport === "url" ? "HTTP config" : "Claude Desktop config";
23071
+ showToast(`${label} copied to clipboard`, "success");
22916
23072
  } catch (error2) {
22917
23073
  console.warn("Copy MCP config failed:", error2);
22918
- showToast("Failed to copy MCP config", "error");
23074
+ showToast("Failed to copy config", "error");
22919
23075
  }
22920
23076
  };
22921
23077
  this._handleUpgrade = async () => {
@@ -23124,6 +23280,7 @@ var BeamApp = class extends i4 {
23124
23280
  return;
23125
23281
  }
23126
23282
  const isEditable = this._selectedPhoton?.editable && !this._selectedPhoton?.isExternalMCP;
23283
+ this._mainTab = "source";
23127
23284
  if (isEditable) {
23128
23285
  this._view = "studio";
23129
23286
  } else {
@@ -23280,7 +23437,7 @@ var BeamApp = class extends i4 {
23280
23437
  };
23281
23438
  this._handleDeletePhoton = async () => {
23282
23439
  this._closeSettingsMenu();
23283
- if (await confirmDialog(`Remove "${this._selectedPhoton?.name}"? It will be moved to trash.`, {
23440
+ if (await confirmElicit(`Remove "${this._selectedPhoton?.name}"? It will be moved to trash.`, {
23284
23441
  confirm: "Remove",
23285
23442
  destructive: true
23286
23443
  })) {
@@ -23381,6 +23538,11 @@ var BeamApp = class extends i4 {
23381
23538
  }
23382
23539
  }
23383
23540
  }
23541
+ if (msg.type === "photon:toast") {
23542
+ const validTypes = ["success", "error", "info", "warning"];
23543
+ const toastType = validTypes.includes(msg.toastType) ? msg.toastType : "info";
23544
+ showToast(msg.message || "Notification", toastType, msg.duration || 3e3);
23545
+ }
23384
23546
  if (msg.type === "photon:viewing") {
23385
23547
  const photonId = this._selectedPhoton?.id;
23386
23548
  const itemId = msg.itemId || msg.board;
@@ -23466,22 +23628,35 @@ var BeamApp = class extends i4 {
23466
23628
  this._broadcastThemeToIframes();
23467
23629
  };
23468
23630
  this._handleOklchThemeReset = () => {
23469
- this._oklchEnabled = false;
23470
- const cssVars = beamThemeToCSS(
23631
+ const oldVars = beamThemeToCSS(
23471
23632
  generateBeamThemeColors({ hue: 0, chroma: 0, lightness: 0.5, theme: "dark" })
23472
23633
  );
23473
- for (const prop of Object.keys(cssVars)) {
23634
+ for (const prop of Object.keys(oldVars)) {
23474
23635
  this.style.removeProperty(prop);
23475
23636
  }
23476
- this._applyTheme();
23637
+ const theme3 = this._theme || "dark";
23638
+ const defaultAmber = { hue: 75, chroma: 0.14, lightness: 0.7, theme: theme3 };
23639
+ this._oklchEnabled = true;
23640
+ this._applyOklchTheme(defaultAmber);
23477
23641
  this._broadcastThemeToIframes();
23478
23642
  showToast("Theme reset to default", "info");
23479
23643
  };
23644
+ this._handleLocalElicit = (e8) => {
23645
+ const { data, resolve: resolve2 } = e8.detail;
23646
+ this._localElicitResolve = resolve2;
23647
+ this._elicitationData = { ...data };
23648
+ this._showElicitation = true;
23649
+ };
23480
23650
  this._handleElicitationSubmit = async (e8) => {
23481
23651
  const { value } = e8.detail;
23482
23652
  const elicitationId = this._elicitationData?.elicitationId;
23483
23653
  this._showElicitation = false;
23484
23654
  this._elicitationData = null;
23655
+ if (this._localElicitResolve) {
23656
+ this._localElicitResolve({ action: "accept", value });
23657
+ this._localElicitResolve = void 0;
23658
+ return;
23659
+ }
23485
23660
  const pendingWindow = elicitationId ? this._pendingBridgeCalls.get(elicitationId) : null;
23486
23661
  if (pendingWindow) {
23487
23662
  this._pendingBridgeCalls.delete(elicitationId);
@@ -23508,6 +23683,11 @@ var BeamApp = class extends i4 {
23508
23683
  this._showElicitation = false;
23509
23684
  this._elicitationData = null;
23510
23685
  this._isExecuting = false;
23686
+ if (this._localElicitResolve) {
23687
+ this._localElicitResolve({ action: "cancel" });
23688
+ this._localElicitResolve = void 0;
23689
+ return;
23690
+ }
23511
23691
  const pendingWindow = elicitationId ? this._pendingBridgeCalls.get(elicitationId) : null;
23512
23692
  if (pendingWindow) {
23513
23693
  this._pendingBridgeCalls.delete(elicitationId);
@@ -23523,6 +23703,18 @@ var BeamApp = class extends i4 {
23523
23703
  this._log("info", "Input cancelled");
23524
23704
  showToast("Input cancelled", "info");
23525
23705
  };
23706
+ this._handleApprovalResponse = async (e8) => {
23707
+ const { approvalId, photon, approved } = e8.detail;
23708
+ this._pendingApprovalsList = this._pendingApprovalsList.filter((a5) => a5.id !== approvalId);
23709
+ if (this._pendingApprovalsList.length === 0) {
23710
+ this._showApprovals = false;
23711
+ }
23712
+ const result = await mcpClient.sendApprovalResponse(approvalId, photon, approved);
23713
+ if (!result.success) {
23714
+ showToast("Failed to send approval response", "error");
23715
+ void this._fetchPendingApprovals();
23716
+ }
23717
+ };
23526
23718
  this._handleOAuthComplete = async (e8) => {
23527
23719
  const { elicitationId, success: success2 } = e8.detail;
23528
23720
  this._showElicitation = false;
@@ -23755,7 +23947,7 @@ var BeamApp = class extends i4 {
23755
23947
  this._handleReconfigure();
23756
23948
  break;
23757
23949
  case "copy-config":
23758
- void this._handleCopyMCPConfig();
23950
+ void this._copyConfigSnippet("stdio");
23759
23951
  break;
23760
23952
  case "upgrade":
23761
23953
  void this._handleUpgrade();
@@ -24047,6 +24239,28 @@ var BeamApp = class extends i4 {
24047
24239
  this._showError("Photon not found", `Method '${action}' not found on ${targetName}`);
24048
24240
  }
24049
24241
  }
24242
+ async _handleCreatePhoton(filename, template = "blank") {
24243
+ try {
24244
+ const res = await fetch("/api/create-photon", {
24245
+ method: "POST",
24246
+ headers: { "Content-Type": "application/json" },
24247
+ body: JSON.stringify({ filename, template })
24248
+ });
24249
+ if (!res.ok) {
24250
+ const err = await res.json().catch(() => ({ error: "Failed to create photon" }));
24251
+ this._showError("Create failed", err.error);
24252
+ return;
24253
+ }
24254
+ const { name: name2 } = await res.json();
24255
+ showToast(`Created ${filename}`, "success");
24256
+ this._pendingStudioOpen = true;
24257
+ setTimeout(() => {
24258
+ this._sidebar?.scrollPhotonIntoView(name2);
24259
+ }, 1500);
24260
+ } catch (err) {
24261
+ this._showError("Create failed", err.message);
24262
+ }
24263
+ }
24050
24264
  /**
24051
24265
  * Collect static methods from all internal photons for global display
24052
24266
  */
@@ -24130,6 +24344,7 @@ var BeamApp = class extends i4 {
24130
24344
  this._verboseLogging = true;
24131
24345
  }
24132
24346
  document.addEventListener("click", this._handleDocumentClick);
24347
+ document.addEventListener("beam:elicit-local", this._handleLocalElicit);
24133
24348
  void this._connectMCP();
24134
24349
  this._setupNotificationHandlers();
24135
24350
  window.addEventListener("popstate", this._handleRouteChange);
@@ -24174,6 +24389,7 @@ var BeamApp = class extends i4 {
24174
24389
  window.removeEventListener("message", this._handleBridgeMessage);
24175
24390
  window.removeEventListener("keydown", this._handleKeydown);
24176
24391
  document.removeEventListener("click", this._handleDocumentClick);
24392
+ document.removeEventListener("beam:elicit-local", this._handleLocalElicit);
24177
24393
  this._cleanupCollectionSubscriptions();
24178
24394
  }
24179
24395
  willUpdate(changedProperties) {
@@ -24297,6 +24513,7 @@ var BeamApp = class extends i4 {
24297
24513
  }
24298
24514
  this._initialConnectDone = true;
24299
24515
  void this._checkForUpdates();
24516
+ this._startApprovalsPolling();
24300
24517
  if (window.location.pathname !== "/") {
24301
24518
  void this._handleRouteChange();
24302
24519
  } else if (!this._selectedPhoton && this._photons.length > 0) {
@@ -24323,6 +24540,7 @@ var BeamApp = class extends i4 {
24323
24540
  this._connected = false;
24324
24541
  this._reconnecting = true;
24325
24542
  this._reconnectAttempt++;
24543
+ this._stopApprovalsPolling();
24326
24544
  showToast("Connection lost. Reconnecting...", "warning");
24327
24545
  });
24328
24546
  mcpClient.on("tools-changed", () => {
@@ -24471,6 +24689,25 @@ var BeamApp = class extends i4 {
24471
24689
  this.requestUpdate();
24472
24690
  }
24473
24691
  });
24692
+ mcpClient.on("canvas", (data) => {
24693
+ if (!data?.photon || !data?.method) return;
24694
+ const currentPhoton = this._selectedPhoton?.name;
24695
+ const currentMethod = this._selectedMethod?.name;
24696
+ if (data.photon !== currentPhoton || data.method !== currentMethod) return;
24697
+ if (!this._canvasActive) {
24698
+ this._canvasActive = true;
24699
+ this.requestUpdate();
24700
+ }
24701
+ void this.updateComplete.then(() => {
24702
+ const canvas = this.shadowRoot?.querySelector("canvas-renderer");
24703
+ if (!canvas) return;
24704
+ if (data.type === "ui") {
24705
+ canvas.pushUI(data.html);
24706
+ } else if (data.type === "data") {
24707
+ canvas.pushData(data.slot, data.data);
24708
+ }
24709
+ });
24710
+ });
24474
24711
  mcpClient.on("photons", (data) => {
24475
24712
  if (data?.photons) {
24476
24713
  const prevNames = new Set(this._photons.filter((p5) => !p5.internal).map((p5) => p5.name));
@@ -24481,6 +24718,31 @@ var BeamApp = class extends i4 {
24481
24718
  this._photons = data.photons.map(
24482
24719
  (p5) => updateFlags.has(p5.name) ? { ...p5, hasUpdate: true } : p5
24483
24720
  );
24721
+ if (this._pendingStudioOpen) {
24722
+ const newPhoton = this._photons.find((p5) => !p5.internal && !prevNames.has(p5.name));
24723
+ if (newPhoton) {
24724
+ this._pendingStudioOpen = false;
24725
+ this._selectedPhoton = newPhoton;
24726
+ this._view = "studio";
24727
+ if (this._pendingTemplateSource) {
24728
+ const tpl = this._pendingTemplateSource;
24729
+ this._pendingTemplateSource = void 0;
24730
+ requestAnimationFrame(() => {
24731
+ const studio = this.shadowRoot?.querySelector("photon-studio");
24732
+ if (studio?.applyTemplate) {
24733
+ studio.applyTemplate({
24734
+ source: tpl,
24735
+ id: "custom",
24736
+ name: "",
24737
+ description: "",
24738
+ icon: ""
24739
+ });
24740
+ }
24741
+ });
24742
+ }
24743
+ this._updateRoute(true);
24744
+ }
24745
+ }
24484
24746
  if (this._selectedPhoton) {
24485
24747
  const updated = this._photons.find((p5) => p5.name === this._selectedPhoton?.name);
24486
24748
  if (updated) {
@@ -24494,28 +24756,7 @@ var BeamApp = class extends i4 {
24494
24756
  if (newUserPhoton) {
24495
24757
  this._selectedPhoton = newUserPhoton;
24496
24758
  this._welcomePhase = "welcome";
24497
- if (this._pendingStudioOpen) {
24498
- this._pendingStudioOpen = false;
24499
- this._view = "studio";
24500
- if (this._pendingTemplateSource) {
24501
- const tpl = this._pendingTemplateSource;
24502
- this._pendingTemplateSource = void 0;
24503
- requestAnimationFrame(() => {
24504
- const studio = this.shadowRoot?.querySelector("photon-studio");
24505
- if (studio?.applyTemplate) {
24506
- studio.applyTemplate({
24507
- source: tpl,
24508
- id: "custom",
24509
- name: "",
24510
- description: "",
24511
- icon: ""
24512
- });
24513
- }
24514
- });
24515
- }
24516
- } else {
24517
- this._view = "list";
24518
- }
24759
+ this._view = "list";
24519
24760
  this._updateRoute(true);
24520
24761
  }
24521
24762
  }
@@ -24584,6 +24825,26 @@ var BeamApp = class extends i4 {
24584
24825
  this._log("info", `Input required: ${data.message || elicitationData.ask}`);
24585
24826
  }
24586
24827
  });
24828
+ mcpClient.on("elicitation-deferred", (data) => {
24829
+ if (data) {
24830
+ if (this._elicitationData && this._elicitationData.elicitationId === data.elicitationId) {
24831
+ this._showElicitation = false;
24832
+ this._elicitationData = null;
24833
+ }
24834
+ void this._fetchPendingApprovals();
24835
+ this._log("info", `Moved to pending approvals: ${data.message || "Approval required"}`);
24836
+ }
24837
+ });
24838
+ mcpClient.on("approval-resolved", (data) => {
24839
+ if (data) {
24840
+ this._pendingApprovalsList = this._pendingApprovalsList.filter(
24841
+ (a5) => a5.id !== data.approvalId
24842
+ );
24843
+ if (this._pendingApprovalsList.length === 0) {
24844
+ this._showApprovals = false;
24845
+ }
24846
+ }
24847
+ });
24587
24848
  mcpClient.on("channel-event", (data) => {
24588
24849
  this._forwardToIframes({
24589
24850
  jsonrpc: "2.0",
@@ -25049,8 +25310,6 @@ var BeamApp = class extends i4 {
25049
25310
  </div>
25050
25311
  ` : ""}
25051
25312
 
25052
- <div class="background-glow" aria-hidden="true"></div>
25053
-
25054
25313
  <!-- Mobile Menu Button: shows back arrow when in method detail, hamburger otherwise -->
25055
25314
  <button
25056
25315
  class="mobile-menu-btn ${this._sidebarVisible ? "open" : ""}"
@@ -25097,6 +25356,7 @@ var BeamApp = class extends i4 {
25097
25356
  .connected=${this._connected}
25098
25357
  .reconnecting=${this._reconnecting}
25099
25358
  .updatesAvailable=${this._updatesAvailable.length}
25359
+ .pendingApprovals=${this._pendingApprovalsList.length}
25100
25360
  .mainTab=${this._mainTab}
25101
25361
  .isApp=${!!(this._selectedPhoton?.isApp || this._selectedPhoton?.isExternalMCP && this._selectedPhoton?.hasMcpApp)}
25102
25362
  .hasSettings=${!!(this._selectedPhoton?.hasSettings && !this._selectedPhoton?.isExternalMCP)}
@@ -25154,12 +25414,19 @@ var BeamApp = class extends i4 {
25154
25414
  @theme-change=${this._handleThemeChange}
25155
25415
  @open-theme-settings=${() => this._showThemeSettings = true}
25156
25416
  @show-shortcuts=${this._showHelpModal}
25417
+ @show-approvals=${() => {
25418
+ this._showApprovals = true;
25419
+ void this._fetchPendingApprovals();
25420
+ }}
25157
25421
  @reconnect-mcp=${(e8) => {
25158
25422
  void this._handleReconnectMCP(e8);
25159
25423
  }}
25160
25424
  @diagnostics=${() => {
25161
25425
  this._view = "diagnostics";
25162
25426
  this._updateRoute();
25427
+ }}
25428
+ @create-photon=${(e8) => {
25429
+ void this._handleCreatePhoton(e8.detail.name, e8.detail.template);
25163
25430
  }}
25164
25431
  @open-studio=${(e8) => {
25165
25432
  const photon = this._photons.find((p5) => p5.name === e8.detail.photonName);
@@ -25230,7 +25497,7 @@ var BeamApp = class extends i4 {
25230
25497
  ${collapse}
25231
25498
  </button>
25232
25499
  </div>` : ""}
25233
- ${this._selectedPhoton && !this._selectedMethod && this._mainTab === "methods" ? b2`<div class="main-toolbar">
25500
+ ${this._selectedPhoton && !this._selectedMethod && this._mainTab === "methods" && this._view !== "studio" ? b2`<div class="main-toolbar">
25234
25501
  <div style="flex: 1; min-width: 0;">${this._renderPhotonToolbar()}</div>
25235
25502
  </div>` : ""}
25236
25503
  ${this._mainTab === "log" ? b2`<activity-log
@@ -25281,6 +25548,17 @@ var BeamApp = class extends i4 {
25281
25548
  @cancel=${this._handleElicitationCancel}
25282
25549
  @oauth-complete=${this._handleOAuthComplete}
25283
25550
  ></elicitation-modal>
25551
+
25552
+ ${this._showApprovals ? b2`
25553
+ <div class="approvals-overlay" @click=${() => this._showApprovals = false}></div>
25554
+ <div class="approvals-panel glass-panel">
25555
+ <pending-approvals
25556
+ .approvals=${this._pendingApprovalsList}
25557
+ @approval-response=${this._handleApprovalResponse}
25558
+ @close=${() => this._showApprovals = false}
25559
+ ></pending-approvals>
25560
+ </div>
25561
+ ` : ""}
25284
25562
  `;
25285
25563
  }
25286
25564
  _renderMethodsBentoOnly() {
@@ -25328,6 +25606,7 @@ var BeamApp = class extends i4 {
25328
25606
  return b2`<photon-studio
25329
25607
  .photonName=${this._selectedPhoton?.name || ""}
25330
25608
  .theme=${this._theme}
25609
+ .hideCloseButton=${true}
25331
25610
  @studio-close=${() => this._view = "list"}
25332
25611
  @studio-saved=${async () => {
25333
25612
  const tools = await mcpClient.listTools();
@@ -26460,6 +26739,7 @@ ${photon.errorMessage || "Unknown error"}</pre
26460
26739
  }
26461
26740
  _handleMethodSelect(e8) {
26462
26741
  this._teardownActiveCustomUI();
26742
+ this._canvasActive = false;
26463
26743
  this._lastFormParams = {};
26464
26744
  if (this._viewMode === "full") {
26465
26745
  this._sharedFormParams = null;
@@ -26810,7 +27090,7 @@ ${photon.errorMessage || "Unknown error"}</pre
26810
27090
  </div>
26811
27091
  </div>
26812
27092
  ` : ""}
26813
- ${opts.result !== null ? this._customFormatUri ? b2`
27093
+ ${opts.result !== null || this._canvasActive ? this._customFormatUri ? b2`
26814
27094
  <custom-ui-renderer
26815
27095
  .photon=${opts.photon?.name || ""}
26816
27096
  .method=${opts.method?.name || ""}
@@ -26842,17 +27122,21 @@ ${photon.errorMessage || "Unknown error"}</pre
26842
27122
  <button @click=${() => this._handleShareResult()}>Share</button>
26843
27123
  </div>
26844
27124
  </div>` : ""}
26845
- <result-viewer
26846
- .result=${opts.result}
26847
- .outputFormat=${opts.method?.outputFormat}
26848
- .layoutHints=${opts.method?.layoutHints}
26849
- .photonName=${opts.photon?.name}
26850
- .theme=${this._theme}
26851
- .live=${this._currentCollectionName !== null}
26852
- .resultKey=${opts.photon && opts.method ? `${opts.photon.name}/${opts.method.name}` : void 0}
26853
- @share=${() => this._handleShareResult()}
26854
- @checklist-action=${(e8) => this._handleChecklistAction(e8)}
26855
- ></result-viewer>
27125
+ ${this._canvasActive ? b2`<canvas-renderer
27126
+ .photon=${opts.photon?.name || ""}
27127
+ .method=${opts.method?.name || ""}
27128
+ .theme=${this._theme}
27129
+ ></canvas-renderer>` : b2`<result-viewer
27130
+ .result=${opts.result}
27131
+ .outputFormat=${opts.method?.outputFormat}
27132
+ .layoutHints=${opts.method?.layoutHints}
27133
+ .photonName=${opts.photon?.name}
27134
+ .theme=${this._theme}
27135
+ .live=${this._currentCollectionName !== null}
27136
+ .resultKey=${opts.photon && opts.method ? `${opts.photon.name}/${opts.method.name}` : void 0}
27137
+ @share=${() => this._handleShareResult()}
27138
+ @checklist-action=${(e8) => this._handleChecklistAction(e8)}
27139
+ ></result-viewer>`}
26856
27140
  ` : b2`
26857
27141
  <div class="empty-state-inline result-empty">
26858
27142
  <span class="empty-state-icon">${play}</span>
@@ -27037,6 +27321,12 @@ ${photon.errorMessage || "Unknown error"}</pre
27037
27321
  case "run-tests":
27038
27322
  void this._runTests();
27039
27323
  break;
27324
+ case "copy-config-stdio":
27325
+ void this._copyConfigSnippet("stdio");
27326
+ break;
27327
+ case "copy-config-url":
27328
+ void this._copyConfigSnippet("url");
27329
+ break;
27040
27330
  case "help":
27041
27331
  this._mainTab = "help";
27042
27332
  void this._loadPhotonHelp();
@@ -27175,7 +27465,7 @@ ${photon.errorMessage || "Unknown error"}</pre
27175
27465
  }
27176
27466
  async _handleBackFromMethod() {
27177
27467
  const form = this.shadowRoot?.querySelector("invoke-form");
27178
- if (form?.isDirty && !await confirmDialog("You have unsaved changes. Discard them?", {
27468
+ if (form?.isDirty && !await confirmElicit("You have unsaved changes. Discard them?", {
27179
27469
  confirm: "Discard",
27180
27470
  destructive: true
27181
27471
  })) {
@@ -27569,7 +27859,7 @@ ${photon.errorMessage || "Unknown error"}</pre
27569
27859
  */
27570
27860
  _forwardToIframes(message) {
27571
27861
  const iframes = [];
27572
- this.shadowRoot?.querySelectorAll("custom-ui-renderer").forEach((renderer) => {
27862
+ this.shadowRoot?.querySelectorAll("custom-ui-renderer, canvas-renderer").forEach((renderer) => {
27573
27863
  const iframe = renderer.shadowRoot?.querySelector("iframe");
27574
27864
  if (iframe) iframes.push(iframe);
27575
27865
  });
@@ -27622,6 +27912,21 @@ ${photon.errorMessage || "Unknown error"}</pre
27622
27912
  this.style.setProperty(prop, value);
27623
27913
  }
27624
27914
  }
27915
+ async _fetchPendingApprovals() {
27916
+ if (!this._mcpReady) return;
27917
+ this._pendingApprovalsList = await mcpClient.fetchPendingApprovals();
27918
+ }
27919
+ _startApprovalsPolling() {
27920
+ this._stopApprovalsPolling();
27921
+ void this._fetchPendingApprovals();
27922
+ this._approvalsRefreshInterval = setInterval(() => void this._fetchPendingApprovals(), 6e4);
27923
+ }
27924
+ _stopApprovalsPolling() {
27925
+ if (this._approvalsRefreshInterval) {
27926
+ clearInterval(this._approvalsRefreshInterval);
27927
+ this._approvalsRefreshInterval = void 0;
27928
+ }
27929
+ }
27625
27930
  _applyTheme() {
27626
27931
  this.setAttribute("data-theme", this._theme);
27627
27932
  }
@@ -27989,6 +28294,17 @@ ${photon.errorMessage || "Unknown error"}</pre
27989
28294
  toggle: true,
27990
28295
  toggleActive: this._verboseLogging
27991
28296
  });
28297
+ items.push({
28298
+ id: "copy-config-stdio",
28299
+ label: "Copy Config (Claude Desktop)",
28300
+ iconSvg: iconSvgString(iconPaths.clone),
28301
+ dividerBefore: true
28302
+ });
28303
+ items.push({
28304
+ id: "copy-config-url",
28305
+ label: "Copy Config (HTTP)",
28306
+ iconSvg: iconSvgString(iconPaths.clone)
28307
+ });
27992
28308
  if (showInstallApp) {
27993
28309
  items.push({
27994
28310
  id: "install-app",
@@ -28913,47 +29229,47 @@ BeamApp.styles = [
28913
29229
  theme,
28914
29230
  i`
28915
29231
  :host {
28916
- /* ===== Dark Theme (Default) ===== */
28917
- --bg-app: hsl(220, 15%, 10%);
28918
- --bg-glass: hsla(220, 15%, 14%, 0.6);
28919
- --bg-glass-strong: hsla(220, 15%, 14%, 0.85);
28920
- --bg-panel: hsl(220, 15%, 12%);
28921
- --t-primary: hsl(220, 10%, 95%);
28922
- --t-muted: hsl(220, 10%, 65%);
28923
- --border-glass: hsla(220, 10%, 80%, 0.1);
28924
- --accent-primary: hsl(260, 100%, 65%);
28925
- --accent-secondary: hsl(190, 100%, 50%);
28926
- --glow-primary: hsla(260, 100%, 65%, 0.3);
29232
+ /* ===== Dark Theme (Default) — Precision Optics ===== */
29233
+ --bg-app: #0b1018;
29234
+ --bg-glass: hsla(215, 25%, 12%, 0.6);
29235
+ --bg-glass-strong: hsla(215, 25%, 12%, 0.85);
29236
+ --bg-panel: #131b28;
29237
+ --t-primary: #f0ede6;
29238
+ --t-muted: #6b8a8a;
29239
+ --border-glass: hsla(210, 20%, 50%, 0.12);
29240
+ --accent-primary: #ffb000;
29241
+ --accent-secondary: #78e6ff;
29242
+ --glow-primary: rgba(255, 176, 0, 0.3);
28927
29243
 
28928
29244
  /* Semantic status colors */
28929
- --color-error: #ff4444;
28930
- --color-error-glow: rgba(255, 68, 68, 0.6);
28931
- --color-error-bg: rgba(255, 68, 68, 0.1);
28932
- --color-success: #00e676;
28933
- --color-success-glow: rgba(0, 230, 118, 0.6);
28934
- --color-success-bg: rgba(0, 230, 118, 0.15);
28935
- --color-warning: #ffab00;
28936
- --color-warning-bg: rgba(255, 171, 0, 0.15);
28937
- --color-warning-glow: rgba(255, 171, 0, 0.6);
29245
+ --color-error: #ff6b6b;
29246
+ --color-error-glow: rgba(255, 107, 107, 0.6);
29247
+ --color-error-bg: rgba(255, 107, 107, 0.1);
29248
+ --color-success: #58d68d;
29249
+ --color-success-glow: rgba(88, 214, 141, 0.6);
29250
+ --color-success-bg: rgba(88, 214, 141, 0.15);
29251
+ --color-warning: #ffb347;
29252
+ --color-warning-bg: rgba(255, 179, 71, 0.15);
29253
+ --color-warning-glow: rgba(255, 179, 71, 0.6);
28938
29254
  --color-info: var(--accent-secondary);
28939
29255
 
28940
29256
  /* CLI preview */
28941
- --cli-bg: hsl(220, 15%, 6%);
28942
- --cli-border: hsl(220, 10%, 20%);
28943
- --cli-text: hsl(142, 76%, 57%);
28944
- --cli-muted: hsl(220, 10%, 40%);
28945
- --cli-hover-bg: hsl(220, 15%, 10%);
29257
+ --cli-bg: #080c12;
29258
+ --cli-border: #1e2d3d;
29259
+ --cli-text: #58d68d;
29260
+ --cli-muted: #4a6565;
29261
+ --cli-hover-bg: #0b1018;
28946
29262
 
28947
29263
  /* Initials icon (marketplace cards) */
28948
- --initials-bg-sat: 35%;
28949
- --initials-bg-lum: 22%;
28950
- --initials-fg-sat: 60%;
28951
- --initials-fg-lum: 75%;
29264
+ --initials-bg-sat: 25%;
29265
+ --initials-bg-lum: 18%;
29266
+ --initials-fg-sat: 50%;
29267
+ --initials-fg-lum: 70%;
28952
29268
 
28953
29269
  /* Shadow tokens (dark defaults) */
28954
- --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
28955
- --shadow-md: 0 4px 24px -1px rgba(0, 0, 0, 0.2);
28956
- --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.3);
29270
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
29271
+ --shadow-md: 0 4px 24px -1px rgba(0, 0, 0, 0.3);
29272
+ --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.35);
28957
29273
 
28958
29274
  display: flex;
28959
29275
  height: 100vh;
@@ -28964,52 +29280,52 @@ BeamApp.styles = [
28964
29280
  overflow: visible; /* Allow focus rings and shadows to display */
28965
29281
  }
28966
29282
 
28967
- /* ===== Light Theme - "Warm, Soft, Professional" ===== */
29283
+ /* ===== Light Theme Mineral Paper ===== */
28968
29284
  :host([data-theme='light']) {
28969
- --bg-app: #eae4dd;
28970
- --bg-glass: rgba(255, 253, 250, 0.75);
28971
- --bg-glass-strong: rgba(255, 253, 250, 0.9);
28972
- --bg-panel: #f8f5f1;
28973
- --t-primary: #2c2420;
28974
- --t-muted: #6b5e54;
28975
- --border-glass: rgba(120, 90, 60, 0.2);
28976
- --accent-primary: hsl(215, 55%, 45%);
28977
- --accent-secondary: hsl(165, 45%, 35%);
28978
- --glow-primary: hsla(215, 55%, 45%, 0.15);
28979
-
28980
- /* Semantic status colors — light theme (same vivid LED colors) */
28981
- --color-error: #e53935;
28982
- --color-error-glow: rgba(229, 57, 53, 0.5);
28983
- --color-error-bg: rgba(229, 57, 53, 0.08);
28984
- --color-success: #00c853;
28985
- --color-success-glow: rgba(0, 200, 83, 0.55);
28986
- --color-success-bg: rgba(0, 200, 83, 0.1);
28987
- --color-warning: #ff8f00;
28988
- --color-warning-bg: rgba(255, 143, 0, 0.1);
28989
- --color-warning-glow: rgba(255, 143, 0, 0.5);
29285
+ --bg-app: #eef1f5;
29286
+ --bg-glass: rgba(255, 255, 255, 0.75);
29287
+ --bg-glass-strong: rgba(255, 255, 255, 0.9);
29288
+ --bg-panel: #ffffff;
29289
+ --t-primary: #0d1420;
29290
+ --t-muted: #5f6b7a;
29291
+ --border-glass: rgba(100, 120, 150, 0.15);
29292
+ --accent-primary: #d98a00;
29293
+ --accent-secondary: #0ea5c6;
29294
+ --glow-primary: rgba(217, 138, 0, 0.15);
29295
+
29296
+ /* Semantic status colors — light theme */
29297
+ --color-error: #d64545;
29298
+ --color-error-glow: rgba(214, 69, 69, 0.5);
29299
+ --color-error-bg: rgba(214, 69, 69, 0.08);
29300
+ --color-success: #1f9d68;
29301
+ --color-success-glow: rgba(31, 157, 104, 0.55);
29302
+ --color-success-bg: rgba(31, 157, 104, 0.1);
29303
+ --color-warning: #d98a00;
29304
+ --color-warning-bg: rgba(217, 138, 0, 0.1);
29305
+ --color-warning-glow: rgba(217, 138, 0, 0.5);
28990
29306
  --color-info: var(--accent-secondary);
28991
29307
 
28992
29308
  /* CLI preview — light theme */
28993
- --cli-bg: hsl(30, 15%, 95%);
29309
+ --cli-bg: #f5f7fa;
28994
29310
  --cli-border: var(--border-glass);
28995
- --cli-text: hsl(142, 45%, 32%);
29311
+ --cli-text: #1f9d68;
28996
29312
  --cli-muted: var(--t-muted);
28997
- --cli-hover-bg: hsl(30, 15%, 91%);
29313
+ --cli-hover-bg: #e8ecf2;
28998
29314
 
28999
- /* Light-mode shadows — warm, visible but not harsh */
29000
- --shadow-sm: 0px 1px 3px rgba(80, 60, 40, 0.1), 0px 1px 2px rgba(80, 60, 40, 0.08);
29001
- --shadow-md: 0px 2px 6px rgba(80, 60, 40, 0.1), 0px 4px 8px rgba(80, 60, 40, 0.06);
29002
- --shadow-lg: 0px 4px 8px rgba(80, 60, 40, 0.1), 0px 10px 20px rgba(80, 60, 40, 0.06);
29315
+ /* Light-mode shadows — cool, clean */
29316
+ --shadow-sm: 0px 1px 3px rgba(0, 20, 50, 0.06), 0px 1px 2px rgba(0, 20, 50, 0.04);
29317
+ --shadow-md: 0px 2px 6px rgba(0, 20, 50, 0.06), 0px 4px 8px rgba(0, 20, 50, 0.04);
29318
+ --shadow-lg: 0px 4px 8px rgba(0, 20, 50, 0.06), 0px 10px 20px rgba(0, 20, 50, 0.04);
29003
29319
 
29004
29320
  /* Initials icon (marketplace cards) */
29005
- --initials-bg-sat: 30%;
29006
- --initials-bg-lum: 90%;
29007
- --initials-fg-sat: 50%;
29321
+ --initials-bg-sat: 20%;
29322
+ --initials-bg-lum: 92%;
29323
+ --initials-fg-sat: 40%;
29008
29324
  --initials-fg-lum: 35%;
29009
29325
 
29010
- /* Parameter tags — warm chip style for light backgrounds */
29011
- --param-tag-bg: hsla(25, 20%, 55%, 0.12);
29012
- --param-tag-color: hsl(20, 15%, 40%);
29326
+ /* Parameter tags — cool chip style for light backgrounds */
29327
+ --param-tag-bg: rgba(100, 120, 150, 0.1);
29328
+ --param-tag-color: #3a4a5c;
29013
29329
  }
29014
29330
 
29015
29331
  /* Skip to main content link — WCAG 2.4.1 */
@@ -29106,12 +29422,12 @@ BeamApp.styles = [
29106
29422
  :host(.view-result) .result-empty,
29107
29423
  :host(.view-form) result-viewer,
29108
29424
  :host(.view-form) custom-ui-renderer,
29425
+ :host(.view-form) canvas-renderer,
29109
29426
  :host(.view-form) .result-empty {
29110
29427
  display: none !important;
29111
29428
  }
29112
29429
 
29113
29430
  :host(.view-result) .mobile-menu-btn,
29114
- :host(.view-result) .background-glow,
29115
29431
  :host(.view-result) .focus-toolbar,
29116
29432
  :host(.view-result) .main-toolbar,
29117
29433
  :host(.view-result) .method-toolbar,
@@ -29122,7 +29438,6 @@ BeamApp.styles = [
29122
29438
  :host(.view-result) app-layout,
29123
29439
  :host(.view-result) .result-chrome,
29124
29440
  :host(.view-form) .mobile-menu-btn,
29125
- :host(.view-form) .background-glow,
29126
29441
  :host(.view-form) .focus-toolbar,
29127
29442
  :host(.view-form) .main-toolbar,
29128
29443
  :host(.view-form) .method-toolbar,
@@ -29566,9 +29881,9 @@ BeamApp.styles = [
29566
29881
  }
29567
29882
 
29568
29883
  .photon-badge.app {
29569
- background: hsla(260, 100%, 65%, 0.15);
29570
- border-color: hsla(260, 100%, 65%, 0.3);
29571
- color: hsl(260, 100%, 75%);
29884
+ background: rgba(255, 176, 0, 0.15);
29885
+ border-color: rgba(255, 176, 0, 0.3);
29886
+ color: #ffca4d;
29572
29887
  }
29573
29888
 
29574
29889
  .photon-badge.update {
@@ -29909,17 +30224,6 @@ BeamApp.styles = [
29909
30224
  font-weight: 500;
29910
30225
  }
29911
30226
 
29912
- .background-glow {
29913
- position: absolute;
29914
- top: -20%;
29915
- left: -10%;
29916
- width: 50%;
29917
- height: 50%;
29918
- background: radial-gradient(circle, var(--glow-primary) 0%, transparent 70%);
29919
- pointer-events: none;
29920
- z-index: 0;
29921
- }
29922
-
29923
30227
  .connection-banner {
29924
30228
  position: fixed;
29925
30229
  top: 0;
@@ -30540,7 +30844,8 @@ BeamApp.styles = [
30540
30844
  }
30541
30845
 
30542
30846
  /* ===== Theme Settings Panel ===== */
30543
- .theme-settings-overlay {
30847
+ .theme-settings-overlay,
30848
+ .approvals-overlay {
30544
30849
  position: fixed;
30545
30850
  inset: 0;
30546
30851
  background: rgba(0, 0, 0, 0.3);
@@ -30559,6 +30864,29 @@ BeamApp.styles = [
30559
30864
  animation: slideInRight 0.2s ease;
30560
30865
  }
30561
30866
 
30867
+ .approvals-panel {
30868
+ position: fixed;
30869
+ bottom: var(--space-xl);
30870
+ left: var(--space-md);
30871
+ width: 340px;
30872
+ max-height: 60vh;
30873
+ z-index: 1001;
30874
+ overflow-y: auto;
30875
+ border-radius: var(--radius-md);
30876
+ animation: slideInUp 0.2s ease;
30877
+ }
30878
+
30879
+ @keyframes slideInUp {
30880
+ from {
30881
+ transform: translateY(20px);
30882
+ opacity: 0;
30883
+ }
30884
+ to {
30885
+ transform: translateY(0);
30886
+ opacity: 1;
30887
+ }
30888
+ }
30889
+
30562
30890
  @keyframes slideInRight {
30563
30891
  from {
30564
30892
  transform: translateX(20px);
@@ -30946,6 +31274,9 @@ __decorateClass([
30946
31274
  __decorateClass([
30947
31275
  r5()
30948
31276
  ], BeamApp.prototype, "_lastResult", 2);
31277
+ __decorateClass([
31278
+ r5()
31279
+ ], BeamApp.prototype, "_canvasActive", 2);
30949
31280
  __decorateClass([
30950
31281
  r5()
30951
31282
  ], BeamApp.prototype, "_customUiRevision", 2);
@@ -30988,6 +31319,12 @@ __decorateClass([
30988
31319
  __decorateClass([
30989
31320
  r5()
30990
31321
  ], BeamApp.prototype, "_showElicitation", 2);
31322
+ __decorateClass([
31323
+ r5()
31324
+ ], BeamApp.prototype, "_showApprovals", 2);
31325
+ __decorateClass([
31326
+ r5()
31327
+ ], BeamApp.prototype, "_pendingApprovalsList", 2);
30991
31328
  __decorateClass([
30992
31329
  r5()
30993
31330
  ], BeamApp.prototype, "_protocolMode", 2);
@@ -31121,7 +31458,12 @@ var BeamSidebar = class extends i4 {
31121
31458
  this._showFavoritesOnly = false;
31122
31459
  this._favorites = /* @__PURE__ */ new Set();
31123
31460
  this._collapsedSections = /* @__PURE__ */ new Set();
31461
+ /** Live recency list — saved to localStorage but NOT used for rendering.
31462
+ * Only applied on next page load via _initialRecentOrder. */
31124
31463
  this._recentPhotons = [];
31464
+ /** Snapshot of recency order captured at page load — used for sorting.
31465
+ * Stays stable during the session so the sidebar doesn't jump around. */
31466
+ this._initialRecentOrder = [];
31125
31467
  this._notificationWarmth = /* @__PURE__ */ new Map();
31126
31468
  }
31127
31469
  connectedCallback() {
@@ -31144,7 +31486,10 @@ var BeamSidebar = class extends i4 {
31144
31486
  _loadRecent() {
31145
31487
  try {
31146
31488
  const stored = localStorage.getItem(BeamSidebar.RECENT_KEY);
31147
- if (stored) this._recentPhotons = JSON.parse(stored);
31489
+ if (stored) {
31490
+ this._recentPhotons = JSON.parse(stored);
31491
+ this._initialRecentOrder = [...this._recentPhotons];
31492
+ }
31148
31493
  } catch {
31149
31494
  }
31150
31495
  }
@@ -31251,9 +31596,10 @@ var BeamSidebar = class extends i4 {
31251
31596
  get _nonAppExternalMCPs() {
31252
31597
  return this._filteredExternalMCPs.filter((m3) => !m3.hasMcpApp);
31253
31598
  }
31254
- /** Sort items by recency — recently used items float to the top */
31599
+ /** Sort items by recency — uses the order snapshot from page load,
31600
+ * so the list stays stable during the session and only reorders on refresh. */
31255
31601
  _sortByRecency(items) {
31256
- const recentIndex = new Map(this._recentPhotons.map((name2, i7) => [name2, i7]));
31602
+ const recentIndex = new Map(this._initialRecentOrder.map((name2, i7) => [name2, i7]));
31257
31603
  return [...items].sort((a5, b3) => {
31258
31604
  const aIdx = recentIndex.get(a5.name);
31259
31605
  const bIdx = recentIndex.get(b3.name);
@@ -31289,11 +31635,11 @@ var BeamSidebar = class extends i4 {
31289
31635
  <button
31290
31636
  class="sidebar-minimize-btn"
31291
31637
  @click=${() => this.dispatchEvent(new CustomEvent("toggle-focus"))}
31292
- title="Minimize sidebar"
31638
+ title="Hide sidebar"
31293
31639
  >
31294
31640
  <svg
31295
- width="14"
31296
- height="14"
31641
+ width="18"
31642
+ height="18"
31297
31643
  viewBox="0 0 24 24"
31298
31644
  fill="none"
31299
31645
  stroke="currentColor"
@@ -31301,20 +31647,31 @@ var BeamSidebar = class extends i4 {
31301
31647
  stroke-linecap="round"
31302
31648
  stroke-linejoin="round"
31303
31649
  >
31304
- <path d="M11 19H4a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h5" />
31305
- <polyline points="13 15 9 12 13 9" />
31650
+ <rect width="18" height="18" x="3" y="3" rx="2" />
31651
+ <path d="M9 3v18" />
31652
+ <path d="m16 15-3-3 3-3" />
31306
31653
  </svg>
31307
31654
  </button>
31308
31655
  </div>
31309
- <div class="search-box" role="search">
31310
- <input
31311
- type="search"
31312
- placeholder="Search photons... (⌘K)"
31313
- .value=${this._searchQuery}
31314
- @input=${(e8) => this._handleSearch(e8)}
31315
- @keydown=${(e8) => this._handleSearchKeydown(e8)}
31316
- aria-label="Search photons"
31317
- />
31656
+ <div class="search-row">
31657
+ <div class="search-box" role="search">
31658
+ <input
31659
+ type="search"
31660
+ placeholder="Search photons... (⌘K)"
31661
+ .value=${this._searchQuery}
31662
+ @input=${(e8) => this._handleSearch(e8)}
31663
+ @keydown=${(e8) => this._handleSearchKeydown(e8)}
31664
+ aria-label="Search photons"
31665
+ />
31666
+ </div>
31667
+ <button
31668
+ class="sidebar-minimize-btn create-btn"
31669
+ @click=${() => this._createPhoton()}
31670
+ title="Create new photon"
31671
+ aria-label="Create new photon"
31672
+ >
31673
+ ${plus}
31674
+ </button>
31318
31675
  </div>
31319
31676
  <div class="filter-row" role="group" aria-label="Filter options">
31320
31677
  <button
@@ -31409,19 +31766,18 @@ var BeamSidebar = class extends i4 {
31409
31766
  </nav>
31410
31767
 
31411
31768
  <div class="sidebar-footer">
31412
- ${this.pendingApprovals > 0 ? b2`
31413
- <button
31414
- class="footer-link approval-badge-btn"
31415
- @click=${() => this.dispatchEvent(
31769
+ <button
31770
+ class="footer-link approval-badge-btn ${this.pendingApprovals === 0 ? "disabled" : ""}"
31771
+ @click=${() => this.pendingApprovals > 0 && this.dispatchEvent(
31416
31772
  new CustomEvent("show-approvals", { bubbles: true, composed: true })
31417
31773
  )}
31418
- title="Pending approvals (${this.pendingApprovals})"
31419
- aria-label="Show pending approvals"
31420
- >
31421
- ${shieldCheck}
31422
- <span class="approval-badge">${this.pendingApprovals}</span>
31423
- </button>
31424
- ` : ""}
31774
+ title="${this.pendingApprovals > 0 ? `Pending approvals (${this.pendingApprovals})` : "No pending approvals"}"
31775
+ aria-label="Show pending approvals"
31776
+ ?disabled=${this.pendingApprovals === 0}
31777
+ >
31778
+ ${shieldCheck}
31779
+ <span class="approval-badge">${this.pendingApprovals}</span>
31780
+ </button>
31425
31781
  <button
31426
31782
  class="footer-link"
31427
31783
  @click=${() => this._showShortcuts()}
@@ -31456,6 +31812,41 @@ var BeamSidebar = class extends i4 {
31456
31812
  _showShortcuts() {
31457
31813
  this.dispatchEvent(new CustomEvent("show-shortcuts", { bubbles: true, composed: true }));
31458
31814
  }
31815
+ async _createPhoton() {
31816
+ const result = await elicit({
31817
+ ask: "form",
31818
+ icon: "\u2728",
31819
+ message: "Create a new photon",
31820
+ description: "Give your photon a name and we\u2019ll set up everything for you. Use lowercase letters and hyphens \u2014 like my-api or weather-bot.",
31821
+ submitLabel: "Create",
31822
+ cancelLabel: "Cancel",
31823
+ fields: [
31824
+ { name: "name", label: "Name", placeholder: "e.g. my-api", required: true },
31825
+ {
31826
+ name: "template",
31827
+ label: "Template",
31828
+ type: "text",
31829
+ enum: ["Hello World", "API Tool", "Stateful", "App"],
31830
+ default: "Hello World"
31831
+ }
31832
+ ]
31833
+ });
31834
+ if (result.action === "cancel") return;
31835
+ const form = result.value;
31836
+ if (!form?.name?.trim()) return;
31837
+ let filename = form.name.trim().toLowerCase().replace(/[^a-z0-9.-]/g, "-");
31838
+ if (!filename.endsWith(".photon.ts")) {
31839
+ filename = filename.replace(/\.photon$/, "") + ".photon.ts";
31840
+ }
31841
+ const template = (form.template || "Blank").toLowerCase().replace(/\s+/g, "-");
31842
+ this.dispatchEvent(
31843
+ new CustomEvent("create-photon", {
31844
+ detail: { name: filename, template },
31845
+ bubbles: true,
31846
+ composed: true
31847
+ })
31848
+ );
31849
+ }
31459
31850
  _openStudio(photonName) {
31460
31851
  this.dispatchEvent(
31461
31852
  new CustomEvent("open-studio", {
@@ -31534,15 +31925,15 @@ var BeamSidebar = class extends i4 {
31534
31925
  title="${photon.description || photon.name}${photon.path ? `
31535
31926
  ${photon.path}` : ""}"
31536
31927
  >
31928
+ <div
31929
+ class="photon-icon ${isEmoji ? "emoji-icon" : ""}"
31930
+ style="${initialsStyle}"
31931
+ aria-hidden="true"
31932
+ >
31933
+ ${displayIcon}
31934
+ </div>
31537
31935
  <div class="photon-item-body">
31538
31936
  <div class="photon-main-row">
31539
- <div
31540
- class="photon-icon ${isEmoji ? "emoji-icon" : ""}"
31541
- style="${initialsStyle}"
31542
- aria-hidden="true"
31543
- >
31544
- ${displayIcon}
31545
- </div>
31546
31937
  <div class="photon-info">
31547
31938
  <div class="photon-name">${photon.name}</div>
31548
31939
  ${photon.internal ? b2`<span class="internal-badge">System</span>` : ""}
@@ -31582,9 +31973,9 @@ ${photon.path}` : ""}"
31582
31973
  title="${mcp.description || "External MCP server"}${mcp.errorMessage ? `
31583
31974
  \u26A0\uFE0F ${mcp.errorMessage}` : ""}"
31584
31975
  >
31976
+ <div class="photon-icon external-mcp-icon" aria-hidden="true">${displayIcon}</div>
31585
31977
  <div class="photon-item-body">
31586
31978
  <div class="photon-main-row">
31587
- <div class="photon-icon external-mcp-icon" aria-hidden="true">${displayIcon}</div>
31588
31979
  <div class="photon-info">
31589
31980
  <div class="photon-name">${mcp.name}</div>
31590
31981
  </div>
@@ -31980,32 +32371,32 @@ BeamSidebar.styles = [
31980
32371
  }
31981
32372
 
31982
32373
  .status-indicator {
31983
- width: 8px;
31984
- height: 8px;
32374
+ width: 9px;
32375
+ height: 9px;
31985
32376
  border-radius: 50%;
31986
32377
  flex-shrink: 0;
31987
32378
  }
31988
32379
 
31989
32380
  .status-indicator.connected {
31990
- background: var(--color-success);
32381
+ background: #22dd44;
31991
32382
  box-shadow:
31992
- 0 0 4px 1px var(--color-success-glow),
31993
- 0 0 8px 2px var(--color-success-glow);
32383
+ 0 0 4px 2px rgba(34, 221, 68, 0.6),
32384
+ 0 0 10px 4px rgba(34, 221, 68, 0.3);
31994
32385
  }
31995
32386
 
31996
32387
  .status-indicator.reconnecting {
31997
- background: var(--color-warning);
32388
+ background: #ffbb33;
31998
32389
  box-shadow:
31999
- 0 0 4px 1px var(--color-warning-glow),
32000
- 0 0 8px 2px var(--color-warning-glow);
32390
+ 0 0 4px 2px rgba(255, 187, 51, 0.6),
32391
+ 0 0 10px 4px rgba(255, 187, 51, 0.3);
32001
32392
  animation: pulse 1s ease-in-out infinite;
32002
32393
  }
32003
32394
 
32004
32395
  .status-indicator.disconnected {
32005
- background: var(--color-error);
32396
+ background: #ff4444;
32006
32397
  box-shadow:
32007
- 0 0 4px 1px rgba(248, 113, 113, 0.5),
32008
- 0 0 8px 2px rgba(248, 113, 113, 0.3);
32398
+ 0 0 4px 2px rgba(255, 68, 68, 0.6),
32399
+ 0 0 10px 4px rgba(255, 68, 68, 0.3);
32009
32400
  }
32010
32401
 
32011
32402
  @keyframes pulse {
@@ -32056,17 +32447,29 @@ BeamSidebar.styles = [
32056
32447
  background: var(--bg-glass-strong);
32057
32448
  }
32058
32449
 
32059
- .search-box {
32450
+ .search-row {
32451
+ display: flex;
32452
+ align-items: center;
32453
+ gap: var(--space-xs);
32060
32454
  margin-top: var(--space-md);
32455
+ }
32456
+
32457
+ .search-box {
32458
+ flex: 1;
32061
32459
  position: relative;
32062
32460
  }
32063
32461
 
32462
+ .create-btn {
32463
+ flex-shrink: 0;
32464
+ margin-top: 0 !important;
32465
+ }
32466
+
32064
32467
  .sidebar-minimize-btn {
32065
- width: 28px;
32066
- height: 28px;
32468
+ width: 32px;
32469
+ height: 32px;
32067
32470
  border-radius: var(--radius-sm);
32068
- background: transparent;
32069
- border: none;
32471
+ background: var(--bg-glass);
32472
+ border: 1px solid var(--border-glass);
32070
32473
  color: var(--t-muted);
32071
32474
  cursor: pointer;
32072
32475
  display: flex;
@@ -32079,7 +32482,8 @@ BeamSidebar.styles = [
32079
32482
 
32080
32483
  .sidebar-minimize-btn:hover {
32081
32484
  color: var(--t-primary);
32082
- background: var(--bg-glass);
32485
+ background: var(--bg-glass-strong);
32486
+ border-color: color-mix(in srgb, var(--accent-primary) 30%, var(--border-glass));
32083
32487
  }
32084
32488
 
32085
32489
  input {
@@ -32088,15 +32492,16 @@ BeamSidebar.styles = [
32088
32492
 
32089
32493
  .section-header {
32090
32494
  font-family: var(--font-display);
32091
- padding: var(--space-sm) var(--space-md);
32092
- font-size: var(--text-xs);
32495
+ padding: var(--space-xs) var(--space-md);
32496
+ font-size: 10px;
32093
32497
  font-weight: 600;
32094
32498
  text-transform: uppercase;
32095
- letter-spacing: 0.1em;
32499
+ letter-spacing: 0.12em;
32096
32500
  color: var(--t-muted);
32097
- margin-top: var(--space-sm);
32098
- border-left: 2px solid var(--accent-primary);
32099
- background: var(--bg-glass-strong);
32501
+ opacity: 0.75;
32502
+ margin-top: var(--space-md);
32503
+ border-left: none;
32504
+ background: color-mix(in srgb, var(--t-muted) 8%, transparent);
32100
32505
  cursor: pointer;
32101
32506
  user-select: none;
32102
32507
  display: flex;
@@ -32105,18 +32510,17 @@ BeamSidebar.styles = [
32105
32510
  }
32106
32511
 
32107
32512
  .section-header:hover {
32513
+ opacity: 1;
32108
32514
  color: var(--t-primary);
32109
- background: var(--bg-panel);
32110
32515
  }
32111
32516
 
32112
32517
  .section-header.attention {
32113
32518
  color: var(--color-warning);
32114
- border-left-color: var(--color-warning);
32115
32519
  }
32116
32520
 
32117
32521
  .section-header.attention:hover {
32118
32522
  color: var(--color-warning);
32119
- opacity: 0.85;
32523
+ opacity: 1;
32120
32524
  }
32121
32525
 
32122
32526
  .section-label {
@@ -32175,12 +32579,12 @@ BeamSidebar.styles = [
32175
32579
  border-left: 2px solid var(--accent-primary);
32176
32580
  color: var(--accent-primary);
32177
32581
  font-weight: 500;
32178
- align-items: stretch;
32582
+ align-items: center;
32179
32583
  padding-top: calc(var(--space-sm) + 2px);
32180
32584
  padding-bottom: calc(var(--space-sm) + 2px);
32181
32585
  }
32182
32586
 
32183
- .photon-item.flash-highlight {
32587
+ .photon-item.flash-highlight:not(.active) {
32184
32588
  animation: flash-highlight 0.6s ease-out;
32185
32589
  }
32186
32590
 
@@ -32193,7 +32597,7 @@ BeamSidebar.styles = [
32193
32597
  }
32194
32598
  }
32195
32599
 
32196
- .photon-item.warmth {
32600
+ .photon-item.warmth:not(.active) {
32197
32601
  animation: warmth-fade 5s ease-out forwards;
32198
32602
  }
32199
32603
 
@@ -32219,6 +32623,10 @@ BeamSidebar.styles = [
32219
32623
  color: var(--t-primary);
32220
32624
  flex-shrink: 0;
32221
32625
  letter-spacing: 0.5px;
32626
+ transition:
32627
+ width 0.25s ease,
32628
+ height 0.25s ease,
32629
+ font-size 0.25s ease;
32222
32630
  }
32223
32631
 
32224
32632
  .photon-icon.emoji-icon {
@@ -32227,6 +32635,17 @@ BeamSidebar.styles = [
32227
32635
  overflow: hidden;
32228
32636
  }
32229
32637
 
32638
+ /* Scale icon up when the row is expanded with view tabs */
32639
+ .photon-item.active .photon-icon {
32640
+ width: 42px;
32641
+ height: 42px;
32642
+ font-size: 15px;
32643
+ }
32644
+
32645
+ .photon-item.active .photon-icon.emoji-icon {
32646
+ font-size: 30px;
32647
+ }
32648
+
32230
32649
  .photon-item.internal {
32231
32650
  opacity: 0.85;
32232
32651
  }
@@ -32286,7 +32705,6 @@ BeamSidebar.styles = [
32286
32705
  display: flex;
32287
32706
  align-items: center;
32288
32707
  gap: 4px;
32289
- margin-left: calc(28px + var(--space-sm));
32290
32708
  }
32291
32709
 
32292
32710
  .photon-view-tab {
@@ -32422,6 +32840,16 @@ BeamSidebar.styles = [
32422
32840
  position: relative;
32423
32841
  }
32424
32842
 
32843
+ .approval-badge-btn.disabled {
32844
+ opacity: 0.4;
32845
+ cursor: default;
32846
+ }
32847
+
32848
+ .approval-badge-btn.disabled:hover {
32849
+ color: var(--t-muted);
32850
+ background: none;
32851
+ }
32852
+
32425
32853
  .approval-badge {
32426
32854
  position: absolute;
32427
32855
  top: -2px;
@@ -32709,9 +33137,6 @@ __decorateClass([
32709
33137
  __decorateClass([
32710
33138
  r5()
32711
33139
  ], BeamSidebar.prototype, "_collapsedSections", 2);
32712
- __decorateClass([
32713
- r5()
32714
- ], BeamSidebar.prototype, "_recentPhotons", 2);
32715
33140
  __decorateClass([
32716
33141
  r5()
32717
33142
  ], BeamSidebar.prototype, "_notificationWarmth", 2);
@@ -35056,7 +35481,7 @@ var InvokeForm = class extends i4 {
35056
35481
  }
35057
35482
  /** Cancel with dirty check. Called by parent chrome wrapper. */
35058
35483
  async handleCancel() {
35059
- if (this.isDirty && !await confirmDialog("You have unsaved changes. Discard them?", {
35484
+ if (this.isDirty && !await confirmElicit("You have unsaved changes. Discard them?", {
35060
35485
  confirm: "Discard",
35061
35486
  destructive: true
35062
35487
  })) {
@@ -36185,6 +36610,9 @@ var ResultViewer = class extends i4 {
36185
36610
  this._expandedAuditTrails = /* @__PURE__ */ new Set();
36186
36611
  // The detected ID field for the current result (shared across diff, animation, warmth)
36187
36612
  this._activeIdField = "id";
36613
+ // Column format pipe cache (invalidated when layoutHints changes)
36614
+ this._columnPipes = null;
36615
+ this._expandedRows = /* @__PURE__ */ new Set();
36188
36616
  // Chart.js instance for reactive updates
36189
36617
  this._chartInstance = null;
36190
36618
  this._chartInstances = /* @__PURE__ */ new Map();
@@ -36354,6 +36782,15 @@ var ResultViewer = class extends i4 {
36354
36782
  }
36355
36783
  this._chartInstances.forEach((chart) => chart.destroy());
36356
36784
  this._chartInstances.clear();
36785
+ for (const timer of this._slidesRefreshTimers) clearInterval(timer);
36786
+ this._slidesRefreshTimers = [];
36787
+ this._slidesBoundElements.forEach((el2) => {
36788
+ const cleanup = el2._renderCleanup;
36789
+ if (typeof cleanup === "function") cleanup();
36790
+ });
36791
+ this._slidesBoundElements.clear();
36792
+ this._slidesResizeObserver?.disconnect();
36793
+ this._slidesResizeObserver = null;
36357
36794
  }
36358
36795
  _closeFullscreen() {
36359
36796
  this._fullscreenImage = null;
@@ -37254,6 +37691,8 @@ var ResultViewer = class extends i4 {
37254
37691
  case "metric":
37255
37692
  case "gauge":
37256
37693
  return typeof data === "object" && !Array.isArray(data) && (data.value !== void 0 || data.count !== void 0 || data.total !== void 0 || data.current !== void 0);
37694
+ case "ring":
37695
+ return typeof data === "number" || typeof data === "object" && !Array.isArray(data) && (data.value !== void 0 || data.progress !== void 0);
37257
37696
  case "chart":
37258
37697
  return typeof data !== "string";
37259
37698
  case "mermaid":
@@ -37312,6 +37751,8 @@ var ResultViewer = class extends i4 {
37312
37751
  return this._renderMetric(filteredData);
37313
37752
  case "gauge":
37314
37753
  return this._renderGauge(filteredData);
37754
+ case "ring":
37755
+ return this._renderRing(filteredData);
37315
37756
  case "timeline":
37316
37757
  return this._renderTimeline(filteredData);
37317
37758
  case "dashboard":
@@ -37393,10 +37834,12 @@ var ResultViewer = class extends i4 {
37393
37834
  const startIndex = this._currentPage * this._pageSize;
37394
37835
  const endIndex = Math.min(startIndex + this._pageSize, totalItems);
37395
37836
  const pageData = sortedData.slice(startIndex, endIndex);
37837
+ const idField = this._detectIdField(originalData);
37396
37838
  return b2`
37397
37839
  <table class="smart-table">
37398
37840
  <thead>
37399
37841
  <tr>
37842
+ <th class="row-expand-th"></th>
37400
37843
  ${columns.map(
37401
37844
  (col) => b2`<th
37402
37845
  class="sortable ${this._sortColumn === col ? "sorted" : ""}"
@@ -37410,15 +37853,42 @@ var ResultViewer = class extends i4 {
37410
37853
  </tr>
37411
37854
  </thead>
37412
37855
  <tbody class="motion-stagger">
37413
- ${pageData.map(
37414
- (row) => b2`
37415
- <tr class="${this._getItemAnimationClass(row)} ${this._getItemWarmthClass(row)}">
37856
+ ${pageData.map((row, idx) => {
37857
+ const rowId = String(row[idField] ?? `__idx_${startIndex + idx}`);
37858
+ const isExpanded = this._expandedRows.has(rowId);
37859
+ return b2`
37860
+ <tr
37861
+ class="${this._getItemAnimationClass(row)} ${this._getItemWarmthClass(
37862
+ row
37863
+ )} ${isExpanded ? "row-expanded" : ""}"
37864
+ @click=${() => this._toggleRowExpansion(rowId)}
37865
+ style="cursor: pointer;"
37866
+ >
37867
+ <td class="row-expand-td">
37868
+ <span class="row-expand-chevron ${isExpanded ? "open" : ""}">▶</span>
37869
+ </td>
37416
37870
  ${columns.map(
37417
37871
  (col) => b2`<td>${this._formatCellValue(row[col], col, true)}</td>`
37418
37872
  )}
37419
37873
  </tr>
37420
- `
37421
- )}
37874
+ ${isExpanded ? b2`<tr class="detail-row">
37875
+ <td colspan="${columns.length + 1}">
37876
+ <div class="detail-panel">
37877
+ ${Object.entries(row).filter(([k3]) => k3 !== "__meta").map(
37878
+ ([k3, v2]) => b2`
37879
+ <div class="detail-field">
37880
+ <span class="detail-key">${this._formatColumnName(k3)}</span>
37881
+ <span class="detail-value"
37882
+ >${this._formatCellValue(v2, k3, true)}</span
37883
+ >
37884
+ </div>
37885
+ `
37886
+ )}
37887
+ </div>
37888
+ </td>
37889
+ </tr>` : ""}
37890
+ `;
37891
+ })}
37422
37892
  </tbody>
37423
37893
  </table>
37424
37894
  ${totalItems > this._pageSize ? this._renderPagination(totalItems, totalPages) : ""}
@@ -37433,6 +37903,15 @@ var ResultViewer = class extends i4 {
37433
37903
  }
37434
37904
  this._currentPage = 0;
37435
37905
  }
37906
+ _toggleRowExpansion(rowId) {
37907
+ const next = new Set(this._expandedRows);
37908
+ if (next.has(rowId)) {
37909
+ next.delete(rowId);
37910
+ } else {
37911
+ next.add(rowId);
37912
+ }
37913
+ this._expandedRows = next;
37914
+ }
37436
37915
  _renderPagination(totalItems, totalPages) {
37437
37916
  const startItem = this._currentPage * this._pageSize + 1;
37438
37917
  const endItem = Math.min((this._currentPage + 1) * this._pageSize, totalItems);
@@ -37977,6 +38456,9 @@ ${rows}`);
37977
38456
  }
37978
38457
  updated(changedProperties) {
37979
38458
  super.updated(changedProperties);
38459
+ if (changedProperties.has("layoutHints")) {
38460
+ this._columnPipes = null;
38461
+ }
37980
38462
  if (changedProperties.has("result") && this.result && typeof this.result === "object" && !Array.isArray(this.result) && typeof this.result._photonType === "string") {
37981
38463
  const data = this.result;
37982
38464
  const photonType = data._photonType;
@@ -41281,9 +41763,70 @@ ${footerText || pageNum ? `<div class="slide-footer"><span>${footerText || ""}</
41281
41763
  _formatColumnName(name2) {
41282
41764
  return formatLabel(name2);
41283
41765
  }
41766
+ _getColumnPipes() {
41767
+ if (this._columnPipes) return this._columnPipes;
41768
+ this._columnPipes = /* @__PURE__ */ new Map();
41769
+ const raw = this.layoutHints?.columnFormats;
41770
+ if (!raw) return this._columnPipes;
41771
+ for (const part of raw.split(",")) {
41772
+ const trimmed = part.trim();
41773
+ const colonIdx = trimmed.indexOf(":");
41774
+ if (colonIdx <= 0) continue;
41775
+ const col = trimmed.slice(0, colonIdx).trim();
41776
+ const pipeSpec = trimmed.slice(colonIdx + 1).trim();
41777
+ const pipeMatch = pipeSpec.match(/^(\w+)(?:\((\d+)\))?$/);
41778
+ if (col && pipeMatch) {
41779
+ this._columnPipes.set(col, { pipe: pipeMatch[1], arg: pipeMatch[2] });
41780
+ }
41781
+ }
41782
+ return this._columnPipes;
41783
+ }
41784
+ _applyPipe(value, pipe2, arg) {
41785
+ if (value === null || value === void 0) return "\u2014";
41786
+ switch (pipe2) {
41787
+ case "currency":
41788
+ return typeof value === "number" ? value.toLocaleString(void 0, { style: "currency", currency: arg || "USD" }) : String(value);
41789
+ case "percent": {
41790
+ if (typeof value === "number") {
41791
+ const pct = Math.abs(value) <= 1 ? value * 100 : value;
41792
+ const digits = arg ? parseInt(arg, 10) : 1;
41793
+ return `${pct.toFixed(digits)}%`;
41794
+ }
41795
+ return String(value);
41796
+ }
41797
+ case "date": {
41798
+ const d5 = new Date(value);
41799
+ return isNaN(d5.getTime()) ? String(value) : d5.toLocaleDateString();
41800
+ }
41801
+ case "truncate": {
41802
+ const max = parseInt(arg || "30", 10);
41803
+ const str = String(value);
41804
+ return str.length > max ? str.slice(0, max) + "\u2026" : str;
41805
+ }
41806
+ case "number":
41807
+ return typeof value === "number" ? value.toLocaleString() : String(value);
41808
+ case "compact": {
41809
+ if (typeof value !== "number") return String(value);
41810
+ if (Math.abs(value) >= 1e9) return (value / 1e9).toFixed(1) + "B";
41811
+ if (Math.abs(value) >= 1e6) return (value / 1e6).toFixed(1) + "M";
41812
+ if (Math.abs(value) >= 1e3) return (value / 1e3).toFixed(1) + "K";
41813
+ return value.toLocaleString();
41814
+ }
41815
+ default:
41816
+ return String(value);
41817
+ }
41818
+ }
41284
41819
  _formatCellValue(value, key, highlight = false) {
41285
41820
  if (value === null || value === void 0) return "\u2014";
41286
41821
  if (typeof value === "boolean") return value ? "\u2713" : "\u2717";
41822
+ const pipes = this._getColumnPipes();
41823
+ if (pipes.size > 0) {
41824
+ const pipe2 = pipes.get(key);
41825
+ if (pipe2) {
41826
+ const formatted = this._applyPipe(value, pipe2.pipe, pipe2.arg);
41827
+ return highlight ? this._highlightText(formatted) : formatted;
41828
+ }
41829
+ }
41287
41830
  if (this._isImageUrl(value)) {
41288
41831
  return b2`
41289
41832
  <div>
@@ -41709,9 +42252,157 @@ ${str}</pre
41709
42252
  const dateKeys = keys2.filter(
41710
42253
  (k3) => /^(date|time|createdAt|updatedAt|created|updated|timestamp|.*At|.*Date|.*Time)$/i.test(k3) || typeof sample2[k3] === "string" && /^\d{4}-\d{2}-\d{2}/.test(sample2[k3])
41711
42254
  );
42255
+ if (chartType === "histogram") {
42256
+ const field = this.layoutHints?.x || numericKeys[0];
42257
+ if (!field) return null;
42258
+ const values = items.map((i7) => i7[field]).filter((v2) => typeof v2 === "number");
42259
+ if (values.length === 0) return null;
42260
+ const binCount = Math.min(20, Math.max(5, Math.ceil(Math.sqrt(values.length))));
42261
+ const minVal = Math.min(...values);
42262
+ const maxVal = Math.max(...values);
42263
+ const binWidth = (maxVal - minVal) / binCount || 1;
42264
+ const bins = Array(binCount).fill(0);
42265
+ for (const v2 of values) {
42266
+ const idx = Math.min(binCount - 1, Math.floor((v2 - minVal) / binWidth));
42267
+ bins[idx]++;
42268
+ }
42269
+ const labels2 = bins.map((_3, i7) => `${(minVal + i7 * binWidth).toFixed(1)}`);
42270
+ return {
42271
+ type: "bar",
42272
+ data: {
42273
+ labels: labels2,
42274
+ datasets: [
42275
+ {
42276
+ label: this._formatColumnName(field),
42277
+ data: bins,
42278
+ backgroundColor: this._hexToRgba(palette2[0], 0.7),
42279
+ borderColor: palette2[0],
42280
+ borderWidth: 1
42281
+ }
42282
+ ]
42283
+ },
42284
+ options: {
42285
+ responsive: true,
42286
+ maintainAspectRatio: true,
42287
+ animation: { duration: 600, easing: "easeOutQuart" },
42288
+ plugins: {
42289
+ legend: { display: false },
42290
+ tooltip: {
42291
+ backgroundColor: "rgba(15, 23, 42, 0.9)",
42292
+ titleColor: "#e2e8f0",
42293
+ bodyColor: "#e2e8f0",
42294
+ borderColor: "rgba(99, 102, 241, 0.3)",
42295
+ borderWidth: 1,
42296
+ cornerRadius: 8,
42297
+ padding: 10
42298
+ }
42299
+ },
42300
+ scales: {
42301
+ x: { grid: { color: gridColor }, ticks: { color: textColor, maxRotation: 45 } },
42302
+ y: { grid: { color: gridColor }, ticks: { color: textColor }, beginAtZero: true }
42303
+ }
42304
+ }
42305
+ };
42306
+ }
42307
+ if (chartType === "scatter") {
42308
+ const xField = this.layoutHints?.x || numericKeys[0];
42309
+ const yField = this.layoutHints?.y || numericKeys[1];
42310
+ if (!xField || !yField) return null;
42311
+ return {
42312
+ type: "scatter",
42313
+ data: {
42314
+ datasets: [
42315
+ {
42316
+ label: `${this._formatColumnName(xField)} vs ${this._formatColumnName(yField)}`,
42317
+ data: items.map((item) => ({ x: item[xField], y: item[yField] })),
42318
+ backgroundColor: this._hexToRgba(palette2[0], 0.7),
42319
+ borderColor: palette2[0],
42320
+ pointRadius: 5,
42321
+ pointHoverRadius: 8
42322
+ }
42323
+ ]
42324
+ },
42325
+ options: {
42326
+ responsive: true,
42327
+ maintainAspectRatio: true,
42328
+ animation: { duration: 600, easing: "easeOutQuart" },
42329
+ plugins: {
42330
+ legend: { display: false },
42331
+ tooltip: {
42332
+ backgroundColor: "rgba(15, 23, 42, 0.9)",
42333
+ titleColor: "#e2e8f0",
42334
+ bodyColor: "#e2e8f0",
42335
+ borderColor: "rgba(99, 102, 241, 0.3)",
42336
+ borderWidth: 1,
42337
+ cornerRadius: 8,
42338
+ padding: 10
42339
+ }
42340
+ },
42341
+ scales: {
42342
+ x: {
42343
+ type: "linear",
42344
+ title: { display: true, text: this._formatColumnName(xField), color: textColor },
42345
+ grid: { color: gridColor },
42346
+ ticks: { color: textColor }
42347
+ },
42348
+ y: {
42349
+ type: "linear",
42350
+ title: { display: true, text: this._formatColumnName(yField), color: textColor },
42351
+ grid: { color: gridColor },
42352
+ ticks: { color: textColor }
42353
+ }
42354
+ }
42355
+ }
42356
+ };
42357
+ }
41712
42358
  const labelField = this.layoutHints?.label || this.layoutHints?.x || dateKeys[0] || stringKeys[0];
41713
42359
  const valueFields = this.layoutHints?.y ? [this.layoutHints.y] : this.layoutHints?.value ? [this.layoutHints.value] : numericKeys;
41714
42360
  if (!labelField || valueFields.length === 0) return null;
42361
+ if (chartType === "radar" && items.length === 1) {
42362
+ const labels2 = valueFields.map((f5) => this._formatColumnName(f5));
42363
+ return {
42364
+ type: "radar",
42365
+ data: {
42366
+ labels: labels2,
42367
+ datasets: [
42368
+ {
42369
+ label: items[0][stringKeys[0]] || "Values",
42370
+ data: valueFields.map((f5) => items[0][f5] ?? 0),
42371
+ backgroundColor: this._hexToRgba(palette2[0], 0.2),
42372
+ borderColor: palette2[0],
42373
+ borderWidth: 2,
42374
+ pointRadius: 4,
42375
+ pointHoverRadius: 6,
42376
+ fill: true
42377
+ }
42378
+ ]
42379
+ },
42380
+ options: {
42381
+ responsive: true,
42382
+ maintainAspectRatio: true,
42383
+ animation: { duration: 600, easing: "easeOutQuart" },
42384
+ plugins: {
42385
+ legend: { display: false },
42386
+ tooltip: {
42387
+ backgroundColor: "rgba(15, 23, 42, 0.9)",
42388
+ titleColor: "#e2e8f0",
42389
+ bodyColor: "#e2e8f0",
42390
+ borderColor: "rgba(99, 102, 241, 0.3)",
42391
+ borderWidth: 1,
42392
+ cornerRadius: 8,
42393
+ padding: 10
42394
+ }
42395
+ },
42396
+ scales: {
42397
+ r: {
42398
+ grid: { color: gridColor },
42399
+ pointLabels: { color: textColor },
42400
+ ticks: { color: textColor, backdropColor: "transparent" }
42401
+ }
42402
+ }
42403
+ }
42404
+ };
42405
+ }
41715
42406
  const labels = items.map((item) => {
41716
42407
  const val = item[labelField];
41717
42408
  if (dateKeys.includes(labelField) && typeof val === "string") {
@@ -41733,9 +42424,10 @@ ${str}</pre
41733
42424
  borderColor: palette2[i7 % palette2.length],
41734
42425
  borderWidth: chartType === "pie" || chartType === "doughnut" ? 0 : 2,
41735
42426
  tension: 0.3,
41736
- fill: chartType === "line" && valueFields.length === 1 ? "origin" : false,
41737
- pointRadius: chartType === "scatter" ? 5 : 3,
41738
- pointHoverRadius: chartType === "scatter" ? 8 : 5
42427
+ fill: chartType === "radar" ? true : chartType === "line" && valueFields.length === 1 ? "origin" : false,
42428
+ pointRadius: 3,
42429
+ pointHoverRadius: 5,
42430
+ ...chartType === "radar" ? { backgroundColor: this._hexToRgba(palette2[i7 % palette2.length], 0.2) } : {}
41739
42431
  }));
41740
42432
  const isPolar = chartType === "pie" || chartType === "doughnut" || chartType === "radar";
41741
42433
  return {
@@ -41767,7 +42459,13 @@ ${str}</pre
41767
42459
  padding: 10
41768
42460
  }
41769
42461
  },
41770
- scales: isPolar ? {} : {
42462
+ scales: chartType === "radar" ? {
42463
+ r: {
42464
+ grid: { color: gridColor },
42465
+ pointLabels: { color: textColor },
42466
+ ticks: { color: textColor, backdropColor: "transparent" }
42467
+ }
42468
+ } : isPolar ? {} : {
41771
42469
  x: {
41772
42470
  grid: { color: gridColor },
41773
42471
  ticks: { color: textColor, maxRotation: 45 }
@@ -41801,8 +42499,12 @@ ${str}</pre
41801
42499
  const keys2 = Object.keys(sample2);
41802
42500
  const numericKeys = keys2.filter((k3) => typeof sample2[k3] === "number");
41803
42501
  const hasDate = this._hasDateLikeFields(sample2);
42502
+ const stringKeys = keys2.filter((k3) => typeof sample2[k3] === "string");
41804
42503
  if (hasDate && numericKeys.length >= 1) return "line";
42504
+ if (numericKeys.length >= 2 && stringKeys.length === 0 && items.length > 1) return "scatter";
41805
42505
  if (keys2.length === 2 && numericKeys.length === 1 && items.length <= 8) return "pie";
42506
+ if (items.length === 1 && numericKeys.length >= 5) return "radar";
42507
+ if (items.length <= 5 && numericKeys.length >= 4 && stringKeys.length === 1) return "radar";
41806
42508
  return "bar";
41807
42509
  }
41808
42510
  _hexToRgba(hex4, alpha2) {
@@ -41946,6 +42648,74 @@ ${str}</pre
41946
42648
  }
41947
42649
  }
41948
42650
  // ═══════════════════════════════════════════════════════════════════════════
42651
+ // Ring (Circular Progress) Rendering
42652
+ // ═══════════════════════════════════════════════════════════════════════════
42653
+ _renderRing(data) {
42654
+ let value;
42655
+ let max = 100;
42656
+ let label;
42657
+ if (typeof data === "number") {
42658
+ value = data;
42659
+ } else if (data && typeof data === "object") {
42660
+ if ("progress" in data && typeof data.progress === "number") {
42661
+ value = data.progress * 100;
42662
+ } else {
42663
+ value = data.value ?? 0;
42664
+ }
42665
+ max = parseFloat(this.layoutHints?.max ?? String(data.max ?? 100));
42666
+ label = data.label || this.layoutHints?.title;
42667
+ } else {
42668
+ return b2`<div class="empty-state">No ring data</div>`;
42669
+ }
42670
+ const normalized = Math.max(0, Math.min(1, value / max));
42671
+ const cx = 60;
42672
+ const cy = 60;
42673
+ const r7 = 50;
42674
+ const circumference = 2 * Math.PI * r7;
42675
+ const dashOffset = circumference * (1 - normalized);
42676
+ const color2 = this._getGaugeColor(normalized);
42677
+ const displayValue = data?.progress !== void 0 ? `${Math.round(value)}%` : String(Math.round(value));
42678
+ return b2`
42679
+ <div class="ring-container ${this._objectJustChanged ? "value-flash" : ""}">
42680
+ <svg viewBox="0 0 120 120" width="120" height="120">
42681
+ <circle
42682
+ cx="${cx}"
42683
+ cy="${cy}"
42684
+ r="${r7}"
42685
+ fill="none"
42686
+ stroke="${this.theme === "light" ? "#e2e8f0" : "#334155"}"
42687
+ stroke-width="8"
42688
+ />
42689
+ <circle
42690
+ cx="${cx}"
42691
+ cy="${cy}"
42692
+ r="${r7}"
42693
+ fill="none"
42694
+ stroke="${color2}"
42695
+ stroke-width="8"
42696
+ stroke-dasharray="${circumference}"
42697
+ stroke-dashoffset="${dashOffset}"
42698
+ stroke-linecap="round"
42699
+ transform="rotate(-90 ${cx} ${cy})"
42700
+ />
42701
+ <text
42702
+ x="${cx}"
42703
+ y="${cy}"
42704
+ text-anchor="middle"
42705
+ dominant-baseline="central"
42706
+ font-size="20"
42707
+ font-weight="700"
42708
+ font-variant-numeric="tabular-nums"
42709
+ fill="${this.theme === "light" ? "#1e293b" : "#e2e8f0"}"
42710
+ >
42711
+ ${displayValue}
42712
+ </text>
42713
+ </svg>
42714
+ ${label ? b2`<div class="ring-label">${label}</div>` : ""}
42715
+ </div>
42716
+ `;
42717
+ }
42718
+ // ═══════════════════════════════════════════════════════════════════════════
41949
42719
  // Timeline Rendering
41950
42720
  // ═══════════════════════════════════════════════════════════════════════════
41951
42721
  _renderTimeline(data) {
@@ -42674,6 +43444,67 @@ ResultViewer.styles = [
42674
43444
  background: var(--bg-glass);
42675
43445
  }
42676
43446
 
43447
+ /* Row expansion */
43448
+ .row-expand-th {
43449
+ width: 32px;
43450
+ padding: 0 !important;
43451
+ }
43452
+ .row-expand-td {
43453
+ width: 32px;
43454
+ padding: 4px 6px !important;
43455
+ text-align: center;
43456
+ }
43457
+ .row-expand-chevron {
43458
+ display: inline-block;
43459
+ font-size: 0.6em;
43460
+ color: var(--t-muted);
43461
+ transition: transform 0.2s ease;
43462
+ }
43463
+ .row-expand-chevron.open {
43464
+ transform: rotate(90deg);
43465
+ }
43466
+ .row-expanded td {
43467
+ border-bottom: none;
43468
+ }
43469
+ .detail-row td {
43470
+ padding: 0 !important;
43471
+ border-bottom: 1px solid var(--border-glass);
43472
+ }
43473
+ .detail-panel {
43474
+ display: grid;
43475
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
43476
+ gap: var(--space-xs) var(--space-md);
43477
+ padding: var(--space-sm) var(--space-md) var(--space-sm) 40px;
43478
+ background: var(--bg-glass);
43479
+ animation: detail-slide-down 0.2s ease-out;
43480
+ }
43481
+ .detail-field {
43482
+ display: flex;
43483
+ flex-direction: column;
43484
+ gap: 2px;
43485
+ }
43486
+ .detail-key {
43487
+ font-size: var(--text-xs);
43488
+ font-weight: 600;
43489
+ color: var(--t-muted);
43490
+ text-transform: uppercase;
43491
+ letter-spacing: 0.05em;
43492
+ }
43493
+ .detail-value {
43494
+ font-size: var(--text-md);
43495
+ color: var(--t-primary);
43496
+ }
43497
+ @keyframes detail-slide-down {
43498
+ from {
43499
+ opacity: 0;
43500
+ transform: translateY(-4px);
43501
+ }
43502
+ to {
43503
+ opacity: 1;
43504
+ transform: translateY(0);
43505
+ }
43506
+ }
43507
+
42677
43508
  /* Key-Value Table (single object) */
42678
43509
  .kv-table {
42679
43510
  max-width: 600px;
@@ -44465,6 +45296,28 @@ ResultViewer.styles = [
44465
45296
  stroke 0.3s ease-out;
44466
45297
  }
44467
45298
 
45299
+ /* ═══════════════════════════════════════════════════════════════
45300
+ Ring (Circular Progress)
45301
+ ═══════════════════════════════════════════════════════════════ */
45302
+ .ring-container {
45303
+ display: flex;
45304
+ flex-direction: column;
45305
+ align-items: center;
45306
+ padding: 12px;
45307
+ }
45308
+ .ring-container svg circle {
45309
+ transition:
45310
+ stroke-dashoffset 0.6s ease-out,
45311
+ stroke 0.3s ease-out;
45312
+ }
45313
+ .ring-label {
45314
+ font-size: var(--text-md);
45315
+ color: var(--t-muted);
45316
+ margin-top: var(--space-xs);
45317
+ text-transform: uppercase;
45318
+ letter-spacing: 0.06em;
45319
+ }
45320
+
44468
45321
  /* ═══════════════════════════════════════════════════════════════
44469
45322
  Timeline Component
44470
45323
  ═══════════════════════════════════════════════════════════════ */
@@ -45093,6 +45946,9 @@ __decorateClass([
45093
45946
  __decorateClass([
45094
45947
  r5()
45095
45948
  ], ResultViewer.prototype, "_checklistToggledDone", 2);
45949
+ __decorateClass([
45950
+ r5()
45951
+ ], ResultViewer.prototype, "_expandedRows", 2);
45096
45952
  __decorateClass([
45097
45953
  n4({ type: String })
45098
45954
  ], ResultViewer.prototype, "collectionProperty", 2);
@@ -46423,7 +47279,7 @@ var MarketplaceView = class extends i4 {
46423
47279
  this._items = items;
46424
47280
  }
46425
47281
  async _removeSource(name2) {
46426
- if (!await confirmDialog(`Remove marketplace "${name2}"? This will not uninstall any photons.`, {
47282
+ if (!await confirmElicit(`Remove marketplace "${name2}"? This will not uninstall any photons.`, {
46427
47283
  confirm: "Remove",
46428
47284
  destructive: true
46429
47285
  })) {
@@ -46490,7 +47346,7 @@ var MarketplaceView = class extends i4 {
46490
47346
  }
46491
47347
  }
46492
47348
  async _remove(item) {
46493
- if (!await confirmDialog(`Remove "${item.name}"? This will delete the photon files.`, {
47349
+ if (!await confirmElicit(`Remove "${item.name}"? This will delete the photon files.`, {
46494
47350
  confirm: "Remove",
46495
47351
  destructive: true
46496
47352
  }))
@@ -47550,7 +48406,7 @@ MarketplaceView = __decorateClass([
47550
48406
 
47551
48407
  // src/auto-ui/frontend/styles/beam-tokens.ts
47552
48408
  var beamTypographyTokens = {
47553
- "--font-display": "'Space Grotesk', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif",
48409
+ "--font-display": "'Sora', 'Space Grotesk', -apple-system, BlinkMacSystemFont, sans-serif",
47554
48410
  "--text-3xl": "2rem",
47555
48411
  "--text-2xl": "1.5rem",
47556
48412
  "--text-xl": "1.25rem",
@@ -47565,17 +48421,17 @@ var beamTypographyTokens = {
47565
48421
  function getBeamThemeTokens(themeMode) {
47566
48422
  const tokens = getThemeTokens(themeMode);
47567
48423
  if (themeMode === "dark") {
47568
- tokens["--color-surface"] = "hsl(220, 15%, 10%)";
47569
- tokens["--color-surface-container"] = "hsl(220, 15%, 12%)";
47570
- tokens["--color-surface-container-high"] = "hsl(220, 15%, 14%)";
47571
- tokens["--color-surface-container-highest"] = "hsl(220, 15%, 16%)";
47572
- tokens["--bg"] = "hsl(220, 15%, 10%)";
48424
+ tokens["--color-surface"] = "#0B1018";
48425
+ tokens["--color-surface-container"] = "#131B28";
48426
+ tokens["--color-surface-container-high"] = "#1A2433";
48427
+ tokens["--color-surface-container-highest"] = "#212D3E";
48428
+ tokens["--bg"] = "#0B1018";
47573
48429
  } else {
47574
- tokens["--color-surface"] = "#eae4dd";
47575
- tokens["--color-surface-container"] = "#f8f5f1";
47576
- tokens["--color-surface-container-high"] = "#f0ebe5";
47577
- tokens["--color-surface-container-highest"] = "#e8e2db";
47578
- tokens["--bg"] = "#eae4dd";
48430
+ tokens["--color-surface"] = "#EEF1F5";
48431
+ tokens["--color-surface-container"] = "#FFFFFF";
48432
+ tokens["--color-surface-container-high"] = "#E4EAF1";
48433
+ tokens["--color-surface-container-highest"] = "#D8E0EA";
48434
+ tokens["--bg"] = "#EEF1F5";
47579
48435
  }
47580
48436
  return tokens;
47581
48437
  }
@@ -47947,7 +48803,8 @@ var CustomUiRenderer = class extends i4 {
47947
48803
  if (body) {
47948
48804
  const bodyOverflow = iframe.contentDocument?.defaultView ? getComputedStyle(iframe.contentDocument.body).overflow : "";
47949
48805
  const isFullHeightApp = bodyOverflow === "hidden";
47950
- if (!isFullHeightApp) {
48806
+ const hostHasExplicitHeight = this.style.height && this.style.height !== "auto";
48807
+ if (!isFullHeightApp && !hostHasExplicitHeight) {
47951
48808
  this._contentResizeObserver = new ResizeObserver(() => {
47952
48809
  const scrollH = iframe.contentDocument?.body.scrollHeight ?? 0;
47953
48810
  const containerH = this.offsetHeight || 500;
@@ -48154,6 +49011,273 @@ CustomUiRenderer = __decorateClass([
48154
49011
  t4("custom-ui-renderer")
48155
49012
  ], CustomUiRenderer);
48156
49013
 
49014
+ // src/auto-ui/frontend/components/canvas-renderer.ts
49015
+ function getBeamThemeTokens2(themeMode) {
49016
+ const tokens = getThemeTokens(themeMode);
49017
+ if (themeMode === "dark") {
49018
+ tokens["--color-surface"] = "#0B1018";
49019
+ tokens["--color-surface-container"] = "#131B28";
49020
+ tokens["--color-surface-container-high"] = "#1A2433";
49021
+ tokens["--color-surface-container-highest"] = "#212D3E";
49022
+ tokens["--bg"] = "#0B1018";
49023
+ } else {
49024
+ tokens["--color-surface"] = "#EEF1F5";
49025
+ tokens["--color-surface-container"] = "#FFFFFF";
49026
+ tokens["--color-surface-container-high"] = "#E4EAF1";
49027
+ tokens["--color-surface-container-highest"] = "#D8E0EA";
49028
+ tokens["--bg"] = "#EEF1F5";
49029
+ }
49030
+ return tokens;
49031
+ }
49032
+ var CanvasRenderer = class extends i4 {
49033
+ constructor() {
49034
+ super(...arguments);
49035
+ this.photon = "";
49036
+ this.method = "";
49037
+ this.theme = "dark";
49038
+ this._loading = true;
49039
+ this._iframeRef = null;
49040
+ this._blobUrl = null;
49041
+ this._iframeReady = false;
49042
+ this._messageBuffer = [];
49043
+ this._resizeObserver = null;
49044
+ }
49045
+ connectedCallback() {
49046
+ super.connectedCallback();
49047
+ void this._buildAndMount();
49048
+ }
49049
+ disconnectedCallback() {
49050
+ super.disconnectedCallback();
49051
+ if (this._blobUrl) {
49052
+ URL.revokeObjectURL(this._blobUrl);
49053
+ this._blobUrl = null;
49054
+ }
49055
+ }
49056
+ /**
49057
+ * Push a canvas/ui message to the iframe (HTML layout with data-slot placeholders)
49058
+ */
49059
+ pushUI(htmlContent) {
49060
+ this._postOrBuffer({
49061
+ jsonrpc: "2.0",
49062
+ method: "canvas/ui",
49063
+ params: { html: htmlContent }
49064
+ });
49065
+ }
49066
+ /**
49067
+ * Push a canvas/data message to the iframe (JSON data targeting a named slot)
49068
+ */
49069
+ pushData(slot, data) {
49070
+ this._postOrBuffer({
49071
+ jsonrpc: "2.0",
49072
+ method: "canvas/data",
49073
+ params: { slot, data }
49074
+ });
49075
+ }
49076
+ _postOrBuffer(message) {
49077
+ if (this._iframeReady && this._iframeRef?.contentWindow) {
49078
+ this._iframeRef.contentWindow.postMessage(message, "*");
49079
+ } else {
49080
+ this._messageBuffer.push(message);
49081
+ }
49082
+ }
49083
+ _flushBuffer() {
49084
+ if (!this._iframeRef?.contentWindow) return;
49085
+ for (const msg of this._messageBuffer) {
49086
+ this._iframeRef.contentWindow.postMessage(msg, "*");
49087
+ }
49088
+ this._messageBuffer = [];
49089
+ }
49090
+ async _buildAndMount() {
49091
+ this._loading = true;
49092
+ try {
49093
+ const bridgeRes = await fetch(
49094
+ `/api/platform-bridge?photon=${encodeURIComponent(this.photon)}&method=${encodeURIComponent(this.method)}&theme=${encodeURIComponent(this.theme)}`,
49095
+ { signal: AbortSignal.timeout(1e4) }
49096
+ );
49097
+ if (!bridgeRes.ok) throw new Error("Failed to load platform bridge");
49098
+ const bridgeScript = await bridgeRes.text();
49099
+ const baseCSS = `<style>
49100
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
49101
+ body {
49102
+ font-family: var(--font-family-sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
49103
+ background: var(--color-surface);
49104
+ color: var(--color-on-surface);
49105
+ font-size: var(--font-size-sm, 14px);
49106
+ line-height: 1.5;
49107
+ padding: var(--space-4, 16px);
49108
+ }
49109
+ a { color: var(--color-primary); }
49110
+ [data-slot] {
49111
+ min-height: 40px;
49112
+ transition: opacity 0.2s ease;
49113
+ }
49114
+ [data-slot].photon-loading {
49115
+ opacity: 0.4;
49116
+ }
49117
+ [data-slot][data-rendered] {
49118
+ opacity: 1;
49119
+ }
49120
+ </style>`;
49121
+ const renderersScript = `<script src="/api/photon-renderers.js"><\/script>`;
49122
+ const shellHtml = `<html>
49123
+ <head>
49124
+ <meta name="photon-canvas" content="true">
49125
+ ${bridgeScript}
49126
+ ${baseCSS}
49127
+ ${renderersScript}
49128
+ </head>
49129
+ <body></body>
49130
+ </html>`;
49131
+ const blob = new Blob([shellHtml], { type: "text/html" });
49132
+ this._blobUrl = URL.createObjectURL(blob);
49133
+ await this.updateComplete;
49134
+ const container = this.shadowRoot?.querySelector(".iframe-host");
49135
+ if (!container) return;
49136
+ const old = container.querySelector("iframe");
49137
+ if (old) old.remove();
49138
+ const iframe = document.createElement("iframe");
49139
+ iframe.setAttribute(
49140
+ "sandbox",
49141
+ "allow-scripts allow-forms allow-same-origin allow-popups allow-modals"
49142
+ );
49143
+ iframe.setAttribute("allowtransparency", "true");
49144
+ iframe.addEventListener("load", () => this._handleIframeLoad(iframe));
49145
+ iframe.src = this._blobUrl;
49146
+ container.appendChild(iframe);
49147
+ } catch (e8) {
49148
+ console.error("[canvas-renderer] Failed to build:", e8);
49149
+ this._loading = false;
49150
+ }
49151
+ }
49152
+ _handleIframeLoad(iframe) {
49153
+ this._iframeRef = iframe;
49154
+ this._loading = false;
49155
+ const themeTokens = getBeamThemeTokens2(this.theme);
49156
+ iframe.contentWindow?.postMessage(
49157
+ {
49158
+ jsonrpc: "2.0",
49159
+ method: "ui/notifications/host-context-changed",
49160
+ params: {
49161
+ theme: this.theme,
49162
+ styles: { variables: themeTokens }
49163
+ }
49164
+ },
49165
+ "*"
49166
+ );
49167
+ iframe.contentWindow?.postMessage(
49168
+ {
49169
+ type: "photon:theme-change",
49170
+ theme: this.theme,
49171
+ themeTokens: { ...themeTokens, ...beamTypographyTokens }
49172
+ },
49173
+ "*"
49174
+ );
49175
+ this._iframeReady = true;
49176
+ this._flushBuffer();
49177
+ this._startAutoResize(iframe);
49178
+ }
49179
+ _startAutoResize(iframe) {
49180
+ const resize = () => {
49181
+ try {
49182
+ const height = iframe.contentDocument?.body?.scrollHeight;
49183
+ if (height && height > 0) {
49184
+ iframe.style.height = `${height + 16}px`;
49185
+ this.style.minHeight = `${height + 16}px`;
49186
+ }
49187
+ } catch (_3) {
49188
+ }
49189
+ };
49190
+ try {
49191
+ const body = iframe.contentDocument?.body;
49192
+ if (body) {
49193
+ this._resizeObserver = new MutationObserver(resize);
49194
+ this._resizeObserver.observe(body, { childList: true, subtree: true, attributes: true });
49195
+ }
49196
+ } catch (_3) {
49197
+ }
49198
+ const interval = setInterval(resize, 500);
49199
+ setTimeout(() => clearInterval(interval), 1e4);
49200
+ }
49201
+ updated(changedProperties) {
49202
+ if (changedProperties.has("theme") && this._iframeRef?.contentWindow) {
49203
+ const themeTokens = getBeamThemeTokens2(this.theme);
49204
+ this._iframeRef.contentWindow.postMessage(
49205
+ {
49206
+ jsonrpc: "2.0",
49207
+ method: "ui/notifications/host-context-changed",
49208
+ params: {
49209
+ theme: this.theme,
49210
+ styles: { variables: themeTokens }
49211
+ }
49212
+ },
49213
+ "*"
49214
+ );
49215
+ }
49216
+ }
49217
+ render() {
49218
+ return b2`
49219
+ <div class="iframe-host"></div>
49220
+ ${this._loading ? b2`<div class="loading"><span>Preparing canvas…</span></div>` : ""}
49221
+ `;
49222
+ }
49223
+ };
49224
+ CanvasRenderer.styles = [
49225
+ theme,
49226
+ i`
49227
+ :host {
49228
+ display: block;
49229
+ position: relative;
49230
+ width: 100%;
49231
+ height: 100%;
49232
+ min-height: 400px;
49233
+ background: transparent;
49234
+ border-radius: var(--radius-md);
49235
+ overflow: visible;
49236
+ }
49237
+
49238
+ .iframe-host {
49239
+ width: 100%;
49240
+ height: 100%;
49241
+ }
49242
+
49243
+ iframe {
49244
+ width: 100%;
49245
+ height: 100%;
49246
+ border: none;
49247
+ display: block;
49248
+ will-change: transform;
49249
+ }
49250
+
49251
+ .loading {
49252
+ position: absolute;
49253
+ inset: 0;
49254
+ z-index: 1;
49255
+ display: flex;
49256
+ flex-direction: column;
49257
+ align-items: center;
49258
+ justify-content: center;
49259
+ gap: 12px;
49260
+ color: var(--t-muted);
49261
+ font-size: 13px;
49262
+ }
49263
+ `
49264
+ ];
49265
+ __decorateClass([
49266
+ n4({ type: String })
49267
+ ], CanvasRenderer.prototype, "photon", 2);
49268
+ __decorateClass([
49269
+ n4({ type: String })
49270
+ ], CanvasRenderer.prototype, "method", 2);
49271
+ __decorateClass([
49272
+ n4({ type: String })
49273
+ ], CanvasRenderer.prototype, "theme", 2);
49274
+ __decorateClass([
49275
+ r5()
49276
+ ], CanvasRenderer.prototype, "_loading", 2);
49277
+ CanvasRenderer = __decorateClass([
49278
+ t4("canvas-renderer")
49279
+ ], CanvasRenderer);
49280
+
48157
49281
  // node_modules/zod/v4/core/core.js
48158
49282
  var NEVER = Object.freeze({
48159
49283
  status: "aborted"
@@ -67962,20 +69086,20 @@ function X_(r7, i7) {
67962
69086
  }
67963
69087
 
67964
69088
  // src/auto-ui/frontend/components/mcp-app-renderer.ts
67965
- function getBeamThemeTokens2(themeMode) {
69089
+ function getBeamThemeTokens3(themeMode) {
67966
69090
  const tokens = getThemeTokens(themeMode);
67967
69091
  if (themeMode === "dark") {
67968
- tokens["--color-surface"] = "hsl(220, 15%, 10%)";
67969
- tokens["--color-surface-container"] = "hsl(220, 15%, 12%)";
67970
- tokens["--color-surface-container-high"] = "hsl(220, 15%, 14%)";
67971
- tokens["--color-surface-container-highest"] = "hsl(220, 15%, 16%)";
67972
- tokens["--bg"] = "hsl(220, 15%, 10%)";
69092
+ tokens["--color-surface"] = "#0B1018";
69093
+ tokens["--color-surface-container"] = "#131B28";
69094
+ tokens["--color-surface-container-high"] = "#1A2433";
69095
+ tokens["--color-surface-container-highest"] = "#212D3E";
69096
+ tokens["--bg"] = "#0B1018";
67973
69097
  } else {
67974
- tokens["--color-surface"] = "#eae4dd";
67975
- tokens["--color-surface-container"] = "#f8f5f1";
67976
- tokens["--color-surface-container-high"] = "#f0ebe5";
67977
- tokens["--color-surface-container-highest"] = "#e8e2db";
67978
- tokens["--bg"] = "#eae4dd";
69098
+ tokens["--color-surface"] = "#EEF1F5";
69099
+ tokens["--color-surface-container"] = "#FFFFFF";
69100
+ tokens["--color-surface-container-high"] = "#E4EAF1";
69101
+ tokens["--color-surface-container-highest"] = "#D8E0EA";
69102
+ tokens["--bg"] = "#EEF1F5";
67979
69103
  }
67980
69104
  return tokens;
67981
69105
  }
@@ -68107,14 +69231,14 @@ var McpAppRenderer = class extends i4 {
68107
69231
  willUpdate(changedProperties) {
68108
69232
  if (changedProperties.has("theme")) {
68109
69233
  if (this._bridge) {
68110
- const specTokens = filterSpecVariables(getBeamThemeTokens2(this.theme));
69234
+ const specTokens = filterSpecVariables(getBeamThemeTokens3(this.theme));
68111
69235
  this._bridge.setHostContext({
68112
69236
  theme: this.theme,
68113
69237
  styles: { variables: specTokens }
68114
69238
  });
68115
69239
  }
68116
69240
  if (this._iframeRef?.contentWindow) {
68117
- const themeTokens = getBeamThemeTokens2(this.theme);
69241
+ const themeTokens = getBeamThemeTokens3(this.theme);
68118
69242
  this._iframeRef.contentWindow.postMessage(
68119
69243
  {
68120
69244
  jsonrpc: "2.0",
@@ -68228,7 +69352,7 @@ var McpAppRenderer = class extends i4 {
68228
69352
  const iframe = e8.target;
68229
69353
  this._iframeRef = iframe;
68230
69354
  if (!iframe.contentWindow) return;
68231
- const themeTokens = getBeamThemeTokens2(this.theme);
69355
+ const themeTokens = getBeamThemeTokens3(this.theme);
68232
69356
  iframe.contentWindow.postMessage(
68233
69357
  {
68234
69358
  jsonrpc: "2.0",
@@ -68272,7 +69396,7 @@ var McpAppRenderer = class extends i4 {
68272
69396
  const msg = event.data;
68273
69397
  if (!msg || typeof msg !== "object") return;
68274
69398
  if (msg.jsonrpc === "2.0" && msg.method === "ui/initialize" && msg.id != null) {
68275
- const themeTokens2 = getBeamThemeTokens2(this.theme);
69399
+ const themeTokens2 = getBeamThemeTokens3(this.theme);
68276
69400
  iframe.contentWindow?.postMessage(
68277
69401
  {
68278
69402
  jsonrpc: "2.0",
@@ -68341,7 +69465,7 @@ var McpAppRenderer = class extends i4 {
68341
69465
  void asyncMessageHandler(event);
68342
69466
  };
68343
69467
  window.addEventListener("message", this._messageHandler);
68344
- const specTokens = filterSpecVariables(getBeamThemeTokens2(this.theme));
69468
+ const specTokens = filterSpecVariables(getBeamThemeTokens3(this.theme));
68345
69469
  this._bridge = new W_(
68346
69470
  null,
68347
69471
  { name: "Photon Beam", version: "1.0.0" },
@@ -95191,6 +96315,7 @@ var PhotonStudio = class extends i4 {
95191
96315
  super(...arguments);
95192
96316
  this.photonName = "";
95193
96317
  this.theme = "dark";
96318
+ this.hideCloseButton = false;
95194
96319
  this._source = "";
95195
96320
  this._originalSource = "";
95196
96321
  this._dirty = false;
@@ -95682,7 +96807,7 @@ ${indent}* ` },
95682
96807
  return;
95683
96808
  }
95684
96809
  const currentName = seedPlan.symbolName.replace(/^\(alias\)\s*/, "").trim();
95685
- const nextName = window.prompt("Rename symbol to:", currentName);
96810
+ const nextName = await promptElicit("Rename symbol to:", currentName);
95686
96811
  if (!nextName || nextName === currentName) return;
95687
96812
  const renamePlan = await this._tsWorkerClient.rename(this._filePath, this._source, pos, nextName).catch((error2) => {
95688
96813
  showToast(error2 instanceof Error ? error2.message : String(error2), "error");
@@ -96098,7 +97223,7 @@ ${indent}* ` },
96098
97223
  }
96099
97224
  async _close() {
96100
97225
  if (this._dirty) {
96101
- if (!await confirmDialog("You have unsaved changes. Close anyway?", {
97226
+ if (!await confirmElicit("You have unsaved changes. Close anyway?", {
96102
97227
  confirm: "Close",
96103
97228
  destructive: true
96104
97229
  }))
@@ -96111,7 +97236,7 @@ ${indent}* ` },
96111
97236
  return b2`
96112
97237
  <div class="toolbar">
96113
97238
  <span class="toolbar-title">Studio</span>
96114
- <button class="close-btn" @click=${() => this._close()}>&times;</button>
97239
+ ${!this.hideCloseButton ? b2`<button class="close-btn" @click=${() => this._close()}>&times;</button>` : ""}
96115
97240
  </div>
96116
97241
  <div class="loading-state">Loading source...</div>
96117
97242
  `;
@@ -96119,8 +97244,8 @@ ${indent}* ` },
96119
97244
  if (this._error) {
96120
97245
  return b2`
96121
97246
  <div class="toolbar">
96122
- <span class="toolbar-title">Studio</span>
96123
- <button class="close-btn" @click=${() => this._close()}>&times;</button>
97247
+ <span class="toolbar-title">Studio Error</span>
97248
+ ${!this.hideCloseButton ? b2`<button class="close-btn" @click=${() => this._close()}>&times;</button>` : ""}
96124
97249
  </div>
96125
97250
  <div class="error-state">
96126
97251
  <span>${this._error}</span>
@@ -96195,9 +97320,9 @@ ${indent}* ` },
96195
97320
  ${this._saving ? "Saving..." : "Save"}
96196
97321
  </button>
96197
97322
 
96198
- <button class="close-btn" @click=${() => this._close()} title="Close Studio">
96199
- &times;
96200
- </button>
97323
+ ${!this.hideCloseButton ? b2`<button class="close-btn" @click=${() => this._close()} title="Close Studio">
97324
+ &times;
97325
+ </button>` : ""}
96201
97326
  </div>
96202
97327
 
96203
97328
  <div class="studio-body">
@@ -97241,6 +98366,9 @@ __decorateClass([
97241
98366
  __decorateClass([
97242
98367
  n4()
97243
98368
  ], PhotonStudio.prototype, "theme", 2);
98369
+ __decorateClass([
98370
+ n4({ type: Boolean })
98371
+ ], PhotonStudio.prototype, "hideCloseButton", 2);
97244
98372
  __decorateClass([
97245
98373
  r5()
97246
98374
  ], PhotonStudio.prototype, "_source", 2);
@@ -97783,7 +98911,11 @@ var ElicitationModal = class extends i4 {
97783
98911
  aria-label="${this.data?.message || "Input required"}"
97784
98912
  @click=${(e8) => e8.stopPropagation()}
97785
98913
  >
97786
- <h3>${this.data.message || "Input Required"}</h3>
98914
+ ${this.data.icon ? b2`<div class="modal-icon">${this.data.icon}</div>` : A}
98915
+ <h3 class="${this.data.description ? "has-description" : ""}">
98916
+ ${this.data.message || "Input Required"}
98917
+ </h3>
98918
+ ${this.data.description ? b2`<p class="modal-description">${this.data.description}</p>` : A}
97787
98919
  ${this._renderContent()}
97788
98920
  </div>
97789
98921
  `;
@@ -97823,8 +98955,12 @@ var ElicitationModal = class extends i4 {
97823
98955
  />
97824
98956
  </div>
97825
98957
  <div class="actions">
97826
- <button class="btn-secondary" @click=${() => this._cancel()}>Cancel</button>
97827
- <button class="btn-primary" @click=${() => this._submit()}>Submit</button>
98958
+ <button class="btn-secondary" @click=${() => this._cancel()}>
98959
+ ${this.data?.cancelLabel || "Cancel"}
98960
+ </button>
98961
+ <button class="btn-primary" @click=${() => this._submit()}>
98962
+ ${this.data?.submitLabel || "Submit"}
98963
+ </button>
97828
98964
  </div>
97829
98965
  `;
97830
98966
  }
@@ -98321,13 +99457,31 @@ ElicitationModal.styles = [
98321
99457
  animation-delay: 0.05s;
98322
99458
  }
98323
99459
 
99460
+ .modal-icon {
99461
+ font-size: 2.5rem;
99462
+ text-align: center;
99463
+ margin-bottom: var(--space-sm);
99464
+ line-height: 1;
99465
+ }
99466
+
98324
99467
  h3 {
98325
- margin: 0 0 var(--space-lg) 0;
99468
+ margin: 0 0 var(--space-sm) 0;
98326
99469
  font-size: var(--text-xl);
98327
99470
  font-weight: 600;
98328
99471
  color: var(--t-primary);
98329
99472
  }
98330
99473
 
99474
+ .modal-description {
99475
+ margin: 0 0 var(--space-lg) 0;
99476
+ font-size: var(--text-md);
99477
+ color: var(--t-muted);
99478
+ line-height: 1.5;
99479
+ }
99480
+
99481
+ h3:not(.has-description) {
99482
+ margin-bottom: var(--space-lg);
99483
+ }
99484
+
98331
99485
  .actions {
98332
99486
  display: flex;
98333
99487
  gap: var(--space-sm);
@@ -98866,7 +100020,7 @@ var OverflowMenu = class extends i4 {
98866
100020
  border: 1px solid ${borderGlass};
98867
100021
  border-radius: ${radiusMd};
98868
100022
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
98869
- font-family: 'Inter', sans-serif;
100023
+ font-family: 'DM Sans', sans-serif;
98870
100024
  padding: 4px 0;
98871
100025
  `;
98872
100026
  this.items.forEach((item) => {
@@ -99184,7 +100338,7 @@ var InstancePanel = class extends i4 {
99184
100338
  border: 1px solid ${borderGlass};
99185
100339
  border-radius: ${radiusMd};
99186
100340
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
99187
- font-family: 'Inter', sans-serif;
100341
+ font-family: 'DM Sans', sans-serif;
99188
100342
  padding: 8px;
99189
100343
  `;
99190
100344
  const addFocusGlow = (el2) => {
@@ -99939,9 +101093,7 @@ var ContextBar = class extends i4 {
99939
101093
  ${this.showConfigure && !p5.isExternalMCP ? b2`<button class="action-btn" @click=${() => this._emit("configure")}>
99940
101094
  Reconfigure
99941
101095
  </button>` : ""}
99942
- ${this.showCopyConfig ? b2`<button class="action-btn" @click=${() => this._emit("copy-config")}>
99943
- ${clipboard} Copy MCP Config
99944
- </button>` : ""}
101096
+ ${""}<!-- Copy MCP Config moved to overflow menu -->
99945
101097
  ${this.overflowItems.length > 0 ? b2`<overflow-menu
99946
101098
  .items=${this.overflowItems}
99947
101099
  @menu-select=${(e8) => this._emit("overflow", e8.detail)}