@portel/photon 1.11.0 → 1.13.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.
- package/README.md +81 -72
- package/dist/auto-ui/beam/photon-management.d.ts.map +1 -1
- package/dist/auto-ui/beam/photon-management.js +5 -0
- package/dist/auto-ui/beam/photon-management.js.map +1 -1
- package/dist/auto-ui/beam/routes/api-browse.d.ts +1 -2
- package/dist/auto-ui/beam/routes/api-browse.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-browse.js +140 -191
- package/dist/auto-ui/beam/routes/api-browse.js.map +1 -1
- package/dist/auto-ui/beam/routes/api-config.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-config.js +44 -1
- package/dist/auto-ui/beam/routes/api-config.js.map +1 -1
- package/dist/auto-ui/beam.d.ts.map +1 -1
- package/dist/auto-ui/beam.js +994 -34
- package/dist/auto-ui/beam.js.map +1 -1
- package/dist/auto-ui/frontend/index.html +83 -60
- package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
- package/dist/auto-ui/streamable-http-transport.js +53 -12
- package/dist/auto-ui/streamable-http-transport.js.map +1 -1
- package/dist/auto-ui/types.d.ts +28 -1
- package/dist/auto-ui/types.d.ts.map +1 -1
- package/dist/auto-ui/types.js +23 -0
- package/dist/auto-ui/types.js.map +1 -1
- package/dist/beam.bundle.js +2894 -329
- package/dist/beam.bundle.js.map +4 -4
- package/dist/cli/commands/build.d.ts +3 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +339 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/package-app.d.ts.map +1 -1
- package/dist/cli/commands/package-app.js +116 -35
- package/dist/cli/commands/package-app.js.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +2 -0
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/context-store.d.ts +5 -0
- package/dist/context-store.d.ts.map +1 -1
- package/dist/context-store.js +9 -0
- package/dist/context-store.js.map +1 -1
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +81 -0
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/protocol.d.ts +3 -1
- package/dist/daemon/protocol.d.ts.map +1 -1
- package/dist/daemon/protocol.js +1 -1
- package/dist/daemon/protocol.js.map +1 -1
- package/dist/daemon/server.js +513 -18
- package/dist/daemon/server.js.map +1 -1
- package/dist/embedded-runtime.d.ts +38 -0
- package/dist/embedded-runtime.d.ts.map +1 -0
- package/dist/embedded-runtime.js +326 -0
- package/dist/embedded-runtime.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +38 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +455 -15
- package/dist/loader.js.map +1 -1
- package/dist/photon-cli-runner.d.ts +22 -0
- package/dist/photon-cli-runner.d.ts.map +1 -1
- package/dist/photon-cli-runner.js +244 -12
- package/dist/photon-cli-runner.js.map +1 -1
- package/dist/photon-doc-extractor.d.ts +6 -0
- package/dist/photon-doc-extractor.d.ts.map +1 -1
- package/dist/photon-doc-extractor.js +22 -0
- package/dist/photon-doc-extractor.js.map +1 -1
- package/dist/photons/tunnel.photon.d.ts +5 -9
- package/dist/photons/tunnel.photon.d.ts.map +1 -1
- package/dist/photons/tunnel.photon.js +36 -96
- package/dist/photons/tunnel.photon.js.map +1 -1
- package/dist/photons/tunnel.photon.ts +40 -112
- package/dist/server.d.ts +30 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +155 -10
- package/dist/server.js.map +1 -1
- package/dist/test-runner.d.ts +13 -1
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +529 -122
- package/dist/test-runner.js.map +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +10 -2
- package/dist/version.js.map +1 -1
- package/package.json +23 -6
package/dist/beam.bundle.js
CHANGED
|
@@ -15357,10 +15357,14 @@ var theme = i`
|
|
|
15357
15357
|
bottom: 0;
|
|
15358
15358
|
background-color: var(--bg-glass);
|
|
15359
15359
|
border: 1px solid var(--border-glass);
|
|
15360
|
-
transition: 0.
|
|
15360
|
+
transition: 0.2s;
|
|
15361
15361
|
border-radius: var(--radius-full);
|
|
15362
15362
|
}
|
|
15363
15363
|
|
|
15364
|
+
.slider:hover {
|
|
15365
|
+
border-color: var(--accent-secondary);
|
|
15366
|
+
}
|
|
15367
|
+
|
|
15364
15368
|
.slider:before {
|
|
15365
15369
|
position: absolute;
|
|
15366
15370
|
content: '';
|
|
@@ -15369,7 +15373,7 @@ var theme = i`
|
|
|
15369
15373
|
left: 2px;
|
|
15370
15374
|
bottom: 2px;
|
|
15371
15375
|
background-color: var(--t-muted);
|
|
15372
|
-
transition: 0.
|
|
15376
|
+
transition: 0.2s;
|
|
15373
15377
|
border-radius: 50%;
|
|
15374
15378
|
}
|
|
15375
15379
|
|
|
@@ -15544,7 +15548,7 @@ ToastManager.styles = [
|
|
|
15544
15548
|
pointer-events: auto;
|
|
15545
15549
|
animation: slideIn 0.3s ease-out;
|
|
15546
15550
|
max-width: 350px;
|
|
15547
|
-
box-shadow:
|
|
15551
|
+
box-shadow: var(--shadow-lg);
|
|
15548
15552
|
}
|
|
15549
15553
|
|
|
15550
15554
|
.toast.exiting {
|
|
@@ -15622,7 +15626,7 @@ ToastManager.styles = [
|
|
|
15622
15626
|
|
|
15623
15627
|
.close:hover {
|
|
15624
15628
|
color: var(--t-primary);
|
|
15625
|
-
background:
|
|
15629
|
+
background: var(--bg-glass);
|
|
15626
15630
|
}
|
|
15627
15631
|
|
|
15628
15632
|
.toast-action {
|
|
@@ -15808,6 +15812,15 @@ var activity = icon(
|
|
|
15808
15812
|
var eye = icon(
|
|
15809
15813
|
`<path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/>`
|
|
15810
15814
|
);
|
|
15815
|
+
var user = icon(
|
|
15816
|
+
`<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>`
|
|
15817
|
+
);
|
|
15818
|
+
var bot = icon(
|
|
15819
|
+
`<path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/>`
|
|
15820
|
+
);
|
|
15821
|
+
var users = icon(
|
|
15822
|
+
`<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>`
|
|
15823
|
+
);
|
|
15811
15824
|
var iconPaths = {
|
|
15812
15825
|
refresh: `<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M8 16H3v5"/>`,
|
|
15813
15826
|
flask: `<path d="M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2"/><path d="M6.453 15h11.094"/><path d="M8.5 2h7"/>`,
|
|
@@ -15822,8 +15835,16 @@ var iconPaths = {
|
|
|
15822
15835
|
docs: `<path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/>`,
|
|
15823
15836
|
expand: `<path d="M15 3h6v6"/><path d="m21 3-7 7"/><path d="m3 21 7-7"/><path d="M9 21H3v-6"/>`,
|
|
15824
15837
|
plus: `<path d="M5 12h14"/><path d="M12 5v14"/>`,
|
|
15825
|
-
clone: `<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"
|
|
15838
|
+
clone: `<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>`,
|
|
15839
|
+
installApp: `<path d="M12 3v12"/><path d="m17 11-5 5-5-5"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>`
|
|
15826
15840
|
};
|
|
15841
|
+
function sizedIcon(iconTpl, size) {
|
|
15842
|
+
return b2`<span
|
|
15843
|
+
class="icon"
|
|
15844
|
+
style="display:inline-flex;align-items:center;justify-content:center;width:${size}px;height:${size}px"
|
|
15845
|
+
>${iconTpl}</span
|
|
15846
|
+
>`;
|
|
15847
|
+
}
|
|
15827
15848
|
|
|
15828
15849
|
// node_modules/@portel/photon-core/dist/design-system/oklch.js
|
|
15829
15850
|
function oklchToSRGB(L3, C3, H3) {
|
|
@@ -16509,7 +16530,8 @@ var buttons = i`
|
|
|
16509
16530
|
color: var(--t-primary);
|
|
16510
16531
|
}
|
|
16511
16532
|
|
|
16512
|
-
.btn-primary:disabled
|
|
16533
|
+
.btn-primary:disabled,
|
|
16534
|
+
.btn-secondary:disabled {
|
|
16513
16535
|
opacity: 0.6;
|
|
16514
16536
|
cursor: not-allowed;
|
|
16515
16537
|
transform: none;
|
|
@@ -16549,7 +16571,21 @@ var forms = i`
|
|
|
16549
16571
|
padding: var(--space-sm);
|
|
16550
16572
|
border-radius: var(--radius-sm);
|
|
16551
16573
|
font-family: var(--font-sans);
|
|
16574
|
+
font-size: var(--text-md);
|
|
16552
16575
|
box-sizing: border-box;
|
|
16576
|
+
transition:
|
|
16577
|
+
border-color 0.15s ease,
|
|
16578
|
+
box-shadow 0.15s ease;
|
|
16579
|
+
}
|
|
16580
|
+
|
|
16581
|
+
input:hover,
|
|
16582
|
+
textarea:hover,
|
|
16583
|
+
select:hover {
|
|
16584
|
+
border-color: var(--accent-secondary);
|
|
16585
|
+
}
|
|
16586
|
+
|
|
16587
|
+
textarea {
|
|
16588
|
+
resize: vertical;
|
|
16553
16589
|
}
|
|
16554
16590
|
|
|
16555
16591
|
::placeholder {
|
|
@@ -16565,12 +16601,12 @@ var forms = i`
|
|
|
16565
16601
|
display: block;
|
|
16566
16602
|
margin-bottom: var(--space-xs);
|
|
16567
16603
|
font-weight: 500;
|
|
16568
|
-
font-size:
|
|
16604
|
+
font-size: var(--text-md);
|
|
16569
16605
|
}
|
|
16570
16606
|
|
|
16571
16607
|
.error-text {
|
|
16572
16608
|
color: var(--color-error);
|
|
16573
|
-
font-size:
|
|
16609
|
+
font-size: var(--text-xs);
|
|
16574
16610
|
margin-top: var(--space-xs);
|
|
16575
16611
|
}
|
|
16576
16612
|
|
|
@@ -16590,7 +16626,7 @@ var forms = i`
|
|
|
16590
16626
|
var badges = i`
|
|
16591
16627
|
.type-badge {
|
|
16592
16628
|
display: inline-block;
|
|
16593
|
-
font-size:
|
|
16629
|
+
font-size: var(--text-2xs);
|
|
16594
16630
|
font-weight: 600;
|
|
16595
16631
|
text-transform: uppercase;
|
|
16596
16632
|
letter-spacing: 0.04em;
|
|
@@ -16624,7 +16660,7 @@ var badges = i`
|
|
|
16624
16660
|
}
|
|
16625
16661
|
|
|
16626
16662
|
.param-tag {
|
|
16627
|
-
font-size:
|
|
16663
|
+
font-size: var(--text-2xs);
|
|
16628
16664
|
padding: 1px 6px;
|
|
16629
16665
|
border-radius: var(--radius-xs);
|
|
16630
16666
|
background: var(--param-tag-bg, hsla(220, 10%, 80%, 0.08));
|
|
@@ -17200,6 +17236,307 @@ function loadSavedThemeConfig() {
|
|
|
17200
17236
|
return null;
|
|
17201
17237
|
}
|
|
17202
17238
|
|
|
17239
|
+
// src/auto-ui/frontend/services/photon-instance-manager.ts
|
|
17240
|
+
var SimpleEventEmitter = class {
|
|
17241
|
+
constructor() {
|
|
17242
|
+
this._listeners = /* @__PURE__ */ new Map();
|
|
17243
|
+
}
|
|
17244
|
+
on(event, callback2) {
|
|
17245
|
+
if (!this._listeners.has(event)) {
|
|
17246
|
+
this._listeners.set(event, /* @__PURE__ */ new Set());
|
|
17247
|
+
}
|
|
17248
|
+
this._listeners.get(event).add(callback2);
|
|
17249
|
+
}
|
|
17250
|
+
off(event, callback2) {
|
|
17251
|
+
const listeners = this._listeners.get(event);
|
|
17252
|
+
if (listeners) {
|
|
17253
|
+
listeners.delete(callback2);
|
|
17254
|
+
}
|
|
17255
|
+
}
|
|
17256
|
+
emit(event, ...args) {
|
|
17257
|
+
const listeners = this._listeners.get(event);
|
|
17258
|
+
if (listeners) {
|
|
17259
|
+
for (const callback2 of listeners) {
|
|
17260
|
+
callback2(...args);
|
|
17261
|
+
}
|
|
17262
|
+
}
|
|
17263
|
+
}
|
|
17264
|
+
};
|
|
17265
|
+
var PhotonSessionProxy = class extends SimpleEventEmitter {
|
|
17266
|
+
constructor(options) {
|
|
17267
|
+
super();
|
|
17268
|
+
this._paginationState = /* @__PURE__ */ new Map();
|
|
17269
|
+
this._pendingPatches = [];
|
|
17270
|
+
this._isApplyingPatches = false;
|
|
17271
|
+
this._name = options.name;
|
|
17272
|
+
this._state = { ...options.initialState };
|
|
17273
|
+
}
|
|
17274
|
+
/**
|
|
17275
|
+
* Get the photon name
|
|
17276
|
+
*/
|
|
17277
|
+
get name() {
|
|
17278
|
+
return this._name;
|
|
17279
|
+
}
|
|
17280
|
+
/**
|
|
17281
|
+
* Get current state
|
|
17282
|
+
*/
|
|
17283
|
+
get state() {
|
|
17284
|
+
return this._state;
|
|
17285
|
+
}
|
|
17286
|
+
/**
|
|
17287
|
+
* Apply JSON Patch array to instance state
|
|
17288
|
+
* Patches from: https://tools.ietf.org/html/rfc6902
|
|
17289
|
+
*/
|
|
17290
|
+
applyPatches(patches) {
|
|
17291
|
+
if (!Array.isArray(patches) || patches.length === 0) {
|
|
17292
|
+
return;
|
|
17293
|
+
}
|
|
17294
|
+
this._pendingPatches.push(...patches);
|
|
17295
|
+
if (!this._isApplyingPatches) {
|
|
17296
|
+
this._isApplyingPatches = true;
|
|
17297
|
+
queueMicrotask(() => this._processPendingPatches());
|
|
17298
|
+
}
|
|
17299
|
+
}
|
|
17300
|
+
/**
|
|
17301
|
+
* Update pagination state for a property (e.g., 'items')
|
|
17302
|
+
*/
|
|
17303
|
+
setPaginationState(property2, state) {
|
|
17304
|
+
const current = this._paginationState.get(property2) || {
|
|
17305
|
+
pageSize: 20,
|
|
17306
|
+
currentPage: 0,
|
|
17307
|
+
hasMore: true,
|
|
17308
|
+
isLoading: false
|
|
17309
|
+
};
|
|
17310
|
+
this._paginationState.set(property2, { ...current, ...state });
|
|
17311
|
+
}
|
|
17312
|
+
/**
|
|
17313
|
+
* Get pagination state for a property
|
|
17314
|
+
*/
|
|
17315
|
+
getPaginationState(property2) {
|
|
17316
|
+
return this._paginationState.get(property2) || {
|
|
17317
|
+
pageSize: 20,
|
|
17318
|
+
currentPage: 0,
|
|
17319
|
+
hasMore: true,
|
|
17320
|
+
isLoading: false
|
|
17321
|
+
};
|
|
17322
|
+
}
|
|
17323
|
+
/**
|
|
17324
|
+
* Create a getter/setter for property access
|
|
17325
|
+
*/
|
|
17326
|
+
_createPropertyDescriptor(key) {
|
|
17327
|
+
return {
|
|
17328
|
+
configurable: true,
|
|
17329
|
+
enumerable: true,
|
|
17330
|
+
get: () => this._state[key],
|
|
17331
|
+
set: (value) => {
|
|
17332
|
+
this._state[key] = value;
|
|
17333
|
+
this.emit("propertyChanged", { property: key, value });
|
|
17334
|
+
}
|
|
17335
|
+
};
|
|
17336
|
+
}
|
|
17337
|
+
/**
|
|
17338
|
+
* Make a property accessible on the proxy
|
|
17339
|
+
*/
|
|
17340
|
+
makeProperty(key) {
|
|
17341
|
+
Object.defineProperty(this, key, this._createPropertyDescriptor(key));
|
|
17342
|
+
}
|
|
17343
|
+
/**
|
|
17344
|
+
* Get all top-level properties (useful for initialization)
|
|
17345
|
+
*/
|
|
17346
|
+
getProperties() {
|
|
17347
|
+
return Object.keys(this._state);
|
|
17348
|
+
}
|
|
17349
|
+
/**
|
|
17350
|
+
* Process pending patches
|
|
17351
|
+
*/
|
|
17352
|
+
_processPendingPatches() {
|
|
17353
|
+
const patches = this._pendingPatches.splice(0);
|
|
17354
|
+
try {
|
|
17355
|
+
for (const patch of patches) {
|
|
17356
|
+
this._applyPatch(patch);
|
|
17357
|
+
}
|
|
17358
|
+
this.emit("state-changed", patches);
|
|
17359
|
+
} finally {
|
|
17360
|
+
this._isApplyingPatches = false;
|
|
17361
|
+
if (this._pendingPatches.length > 0) {
|
|
17362
|
+
queueMicrotask(() => this._processPendingPatches());
|
|
17363
|
+
}
|
|
17364
|
+
}
|
|
17365
|
+
}
|
|
17366
|
+
/**
|
|
17367
|
+
* Apply a single JSON Patch operation
|
|
17368
|
+
*/
|
|
17369
|
+
_applyPatch(patch) {
|
|
17370
|
+
const { op, path, value } = patch;
|
|
17371
|
+
if (!path || typeof path !== "string") {
|
|
17372
|
+
console.warn("Invalid patch: missing or invalid path", patch);
|
|
17373
|
+
return;
|
|
17374
|
+
}
|
|
17375
|
+
const parts = path.split("/").filter((p5) => p5 !== "");
|
|
17376
|
+
let current = this._state;
|
|
17377
|
+
try {
|
|
17378
|
+
for (let i7 = 0; i7 < parts.length - 1; i7++) {
|
|
17379
|
+
const part = this._unescapePath(parts[i7]);
|
|
17380
|
+
if (!(part in current)) {
|
|
17381
|
+
current[part] = {};
|
|
17382
|
+
}
|
|
17383
|
+
current = current[part];
|
|
17384
|
+
}
|
|
17385
|
+
const lastPart = this._unescapePath(parts[parts.length - 1]);
|
|
17386
|
+
switch (op) {
|
|
17387
|
+
case "add":
|
|
17388
|
+
if (Array.isArray(current) && !isNaN(Number(lastPart))) {
|
|
17389
|
+
const index2 = Number(lastPart);
|
|
17390
|
+
current.splice(index2, 0, value);
|
|
17391
|
+
} else {
|
|
17392
|
+
current[lastPart] = value;
|
|
17393
|
+
}
|
|
17394
|
+
break;
|
|
17395
|
+
case "remove":
|
|
17396
|
+
if (Array.isArray(current) && !isNaN(Number(lastPart))) {
|
|
17397
|
+
const index2 = Number(lastPart);
|
|
17398
|
+
current.splice(index2, 1);
|
|
17399
|
+
} else {
|
|
17400
|
+
delete current[lastPart];
|
|
17401
|
+
}
|
|
17402
|
+
break;
|
|
17403
|
+
case "replace":
|
|
17404
|
+
current[lastPart] = value;
|
|
17405
|
+
break;
|
|
17406
|
+
case "move":
|
|
17407
|
+
const fromParts = patch.from.split("/").filter((p5) => p5 !== "");
|
|
17408
|
+
let fromCurrent = this._state;
|
|
17409
|
+
for (let i7 = 0; i7 < fromParts.length - 1; i7++) {
|
|
17410
|
+
fromCurrent = fromCurrent[this._unescapePath(fromParts[i7])];
|
|
17411
|
+
}
|
|
17412
|
+
const fromLast = this._unescapePath(fromParts[fromParts.length - 1]);
|
|
17413
|
+
const movedValue = fromCurrent[fromLast];
|
|
17414
|
+
if (Array.isArray(fromCurrent)) {
|
|
17415
|
+
fromCurrent.splice(Number(fromLast), 1);
|
|
17416
|
+
} else {
|
|
17417
|
+
delete fromCurrent[fromLast];
|
|
17418
|
+
}
|
|
17419
|
+
if (Array.isArray(current)) {
|
|
17420
|
+
current.splice(Number(lastPart), 0, movedValue);
|
|
17421
|
+
} else {
|
|
17422
|
+
current[lastPart] = movedValue;
|
|
17423
|
+
}
|
|
17424
|
+
break;
|
|
17425
|
+
case "copy":
|
|
17426
|
+
const copyFromParts = patch.from.split("/").filter((p5) => p5 !== "");
|
|
17427
|
+
let copyCurrent = this._state;
|
|
17428
|
+
for (let i7 = 0; i7 < copyFromParts.length - 1; i7++) {
|
|
17429
|
+
copyCurrent = copyCurrent[this._unescapePath(copyFromParts[i7])];
|
|
17430
|
+
}
|
|
17431
|
+
const copyFromLast = this._unescapePath(copyFromParts[copyFromParts.length - 1]);
|
|
17432
|
+
const copiedValue = JSON.parse(JSON.stringify(copyCurrent[copyFromLast]));
|
|
17433
|
+
current[lastPart] = copiedValue;
|
|
17434
|
+
break;
|
|
17435
|
+
case "test":
|
|
17436
|
+
if (current[lastPart] !== value) {
|
|
17437
|
+
throw new Error(`Test failed at ${path}: expected ${value}, got ${current[lastPart]}`);
|
|
17438
|
+
}
|
|
17439
|
+
break;
|
|
17440
|
+
default:
|
|
17441
|
+
console.warn(`Unknown patch operation: ${op}`);
|
|
17442
|
+
}
|
|
17443
|
+
} catch (error2) {
|
|
17444
|
+
console.error("Failed to apply patch", { patch, error: error2 });
|
|
17445
|
+
throw error2;
|
|
17446
|
+
}
|
|
17447
|
+
}
|
|
17448
|
+
/**
|
|
17449
|
+
* Unescape JSON Pointer path component
|
|
17450
|
+
* See: https://tools.ietf.org/html/rfc6901
|
|
17451
|
+
*/
|
|
17452
|
+
_unescapePath(part) {
|
|
17453
|
+
return part.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
17454
|
+
}
|
|
17455
|
+
/**
|
|
17456
|
+
* Clear all state
|
|
17457
|
+
*/
|
|
17458
|
+
reset(newState) {
|
|
17459
|
+
this._state = { ...newState };
|
|
17460
|
+
this._paginationState.clear();
|
|
17461
|
+
this.emit("reset");
|
|
17462
|
+
}
|
|
17463
|
+
};
|
|
17464
|
+
var GlobalSessionManager = class {
|
|
17465
|
+
constructor() {
|
|
17466
|
+
this._sessions = /* @__PURE__ */ new Map();
|
|
17467
|
+
}
|
|
17468
|
+
/**
|
|
17469
|
+
* Create or get a photon session
|
|
17470
|
+
*/
|
|
17471
|
+
createOrGetSession(name2, initialState) {
|
|
17472
|
+
if (this._sessions.has(name2)) {
|
|
17473
|
+
return this._sessions.get(name2);
|
|
17474
|
+
}
|
|
17475
|
+
const session = new PhotonSessionProxy({
|
|
17476
|
+
name: name2,
|
|
17477
|
+
initialState
|
|
17478
|
+
});
|
|
17479
|
+
Object.keys(initialState).forEach((key) => {
|
|
17480
|
+
session.makeProperty(key);
|
|
17481
|
+
});
|
|
17482
|
+
this._sessions.set(name2, session);
|
|
17483
|
+
return session;
|
|
17484
|
+
}
|
|
17485
|
+
/**
|
|
17486
|
+
* Get existing session
|
|
17487
|
+
*/
|
|
17488
|
+
getSession(name2) {
|
|
17489
|
+
return this._sessions.get(name2);
|
|
17490
|
+
}
|
|
17491
|
+
/**
|
|
17492
|
+
* Apply patches to a session
|
|
17493
|
+
*/
|
|
17494
|
+
applyPatches(name2, patches) {
|
|
17495
|
+
const session = this._sessions.get(name2);
|
|
17496
|
+
if (!session) {
|
|
17497
|
+
console.warn(`No session found for: ${name2}`);
|
|
17498
|
+
return false;
|
|
17499
|
+
}
|
|
17500
|
+
session.applyPatches(patches);
|
|
17501
|
+
return true;
|
|
17502
|
+
}
|
|
17503
|
+
/**
|
|
17504
|
+
* Remove session
|
|
17505
|
+
*/
|
|
17506
|
+
removeSession(name2) {
|
|
17507
|
+
this._sessions.delete(name2);
|
|
17508
|
+
}
|
|
17509
|
+
/**
|
|
17510
|
+
* Get all session names
|
|
17511
|
+
*/
|
|
17512
|
+
getSessionNames() {
|
|
17513
|
+
return Array.from(this._sessions.keys());
|
|
17514
|
+
}
|
|
17515
|
+
};
|
|
17516
|
+
var globalSessionManager = null;
|
|
17517
|
+
function getGlobalSessionManager() {
|
|
17518
|
+
if (!globalSessionManager) {
|
|
17519
|
+
globalSessionManager = new GlobalSessionManager();
|
|
17520
|
+
if (typeof window !== "undefined") {
|
|
17521
|
+
window.__photonSessionManager = globalSessionManager;
|
|
17522
|
+
}
|
|
17523
|
+
}
|
|
17524
|
+
return globalSessionManager;
|
|
17525
|
+
}
|
|
17526
|
+
function initializeGlobalPhotonSession(photonName, initialState) {
|
|
17527
|
+
const manager = getGlobalSessionManager();
|
|
17528
|
+
const session = manager.createOrGetSession(photonName, initialState);
|
|
17529
|
+
if (typeof window !== "undefined") {
|
|
17530
|
+
const varName = photonName.charAt(0).toLocaleLowerCase() + photonName.slice(1);
|
|
17531
|
+
window[varName] = session;
|
|
17532
|
+
if (photonName === "Boards") {
|
|
17533
|
+
window.boards = session;
|
|
17534
|
+
window.boardsSession = session;
|
|
17535
|
+
}
|
|
17536
|
+
}
|
|
17537
|
+
return session;
|
|
17538
|
+
}
|
|
17539
|
+
|
|
17203
17540
|
// src/auto-ui/frontend/services/mcp-client.ts
|
|
17204
17541
|
var MCPClientService = class {
|
|
17205
17542
|
// Discard operations older than 30s
|
|
@@ -17904,9 +18241,21 @@ var MCPClientService = class {
|
|
|
17904
18241
|
case "photon/refresh-needed":
|
|
17905
18242
|
this.emit("refresh-needed", notification.params);
|
|
17906
18243
|
break;
|
|
17907
|
-
case "
|
|
18244
|
+
case "state-changed":
|
|
18245
|
+
const params = notification.params;
|
|
18246
|
+
if (params?.instance && params?.patches) {
|
|
18247
|
+
try {
|
|
18248
|
+
const manager = getGlobalSessionManager();
|
|
18249
|
+
manager.applyPatches(params.instance, params.patches);
|
|
18250
|
+
} catch (error2) {
|
|
18251
|
+
console.error("Failed to apply patches to session", error2);
|
|
18252
|
+
}
|
|
18253
|
+
}
|
|
17908
18254
|
this.emit("state-changed", notification.params);
|
|
17909
18255
|
break;
|
|
18256
|
+
case "photon/notification":
|
|
18257
|
+
this.emit("photon-notification", notification.params);
|
|
18258
|
+
break;
|
|
17910
18259
|
// MCP Apps standard notifications
|
|
17911
18260
|
case "ui/notifications/tool-result":
|
|
17912
18261
|
this.emit("ui-tool-result", notification.params);
|
|
@@ -17931,6 +18280,439 @@ var MCPClientService = class {
|
|
|
17931
18280
|
};
|
|
17932
18281
|
var mcpClient = new MCPClientService();
|
|
17933
18282
|
|
|
18283
|
+
// src/auto-ui/frontend/services/viewport-aware-proxy.ts
|
|
18284
|
+
var ViewportAwareProxy = class {
|
|
18285
|
+
constructor(photonName, methodName, mcpClient2, options = {}) {
|
|
18286
|
+
// Cache management
|
|
18287
|
+
this._cache = /* @__PURE__ */ new Map();
|
|
18288
|
+
this._viewport = { start: 0, end: 20 };
|
|
18289
|
+
this._pendingRanges = /* @__PURE__ */ new Set();
|
|
18290
|
+
this._pagination = {
|
|
18291
|
+
totalCount: 0,
|
|
18292
|
+
start: 0,
|
|
18293
|
+
end: 0,
|
|
18294
|
+
hasMore: false
|
|
18295
|
+
};
|
|
18296
|
+
// Event listeners
|
|
18297
|
+
this._listeners = /* @__PURE__ */ new Map();
|
|
18298
|
+
this._photonName = photonName;
|
|
18299
|
+
this._methodName = methodName;
|
|
18300
|
+
this._mcpClient = mcpClient2;
|
|
18301
|
+
this._fetchOptions = {
|
|
18302
|
+
pageSize: options.pageSize ?? 20,
|
|
18303
|
+
bufferSize: options.bufferSize ?? 5,
|
|
18304
|
+
maxCacheSize: options.maxCacheSize ?? 1e3
|
|
18305
|
+
};
|
|
18306
|
+
}
|
|
18307
|
+
/**
|
|
18308
|
+
* Initialize with paginated response from server
|
|
18309
|
+
* Server should return: { items: [...], _pagination: {...} }
|
|
18310
|
+
*/
|
|
18311
|
+
initializeWithResponse(response) {
|
|
18312
|
+
if (!response || typeof response !== "object") {
|
|
18313
|
+
return;
|
|
18314
|
+
}
|
|
18315
|
+
const { items = [], _pagination } = response;
|
|
18316
|
+
if (_pagination) {
|
|
18317
|
+
this._pagination = _pagination;
|
|
18318
|
+
items.forEach((item, offset) => {
|
|
18319
|
+
this._cache.set(_pagination.start + offset, item);
|
|
18320
|
+
});
|
|
18321
|
+
this._emit("initialized", { pagination: this._pagination });
|
|
18322
|
+
}
|
|
18323
|
+
}
|
|
18324
|
+
/**
|
|
18325
|
+
* Set visible viewport (what user sees on screen)
|
|
18326
|
+
* Automatically fetches data for this range + buffer
|
|
18327
|
+
*/
|
|
18328
|
+
async setViewport(start, end) {
|
|
18329
|
+
this._viewport = { start, end };
|
|
18330
|
+
const bufferedStart = Math.max(0, start - this._fetchOptions.bufferSize);
|
|
18331
|
+
const bufferedEnd = Math.min(this._pagination.totalCount, end + this._fetchOptions.bufferSize);
|
|
18332
|
+
const missingRanges = this._findMissingRanges(bufferedStart, bufferedEnd);
|
|
18333
|
+
await Promise.all(
|
|
18334
|
+
missingRanges.map(
|
|
18335
|
+
(range) => this._fetchRange(range.start, range.end).catch((err) => {
|
|
18336
|
+
console.error(`Failed to fetch range [${range.start}, ${range.end}]`, err);
|
|
18337
|
+
})
|
|
18338
|
+
)
|
|
18339
|
+
);
|
|
18340
|
+
}
|
|
18341
|
+
/**
|
|
18342
|
+
* Get items in current viewport (array-like interface)
|
|
18343
|
+
*/
|
|
18344
|
+
get items() {
|
|
18345
|
+
const items = [];
|
|
18346
|
+
for (let i7 = this._viewport.start; i7 < this._viewport.end; i7++) {
|
|
18347
|
+
if (this._cache.has(i7)) {
|
|
18348
|
+
items.push(this._cache.get(i7));
|
|
18349
|
+
}
|
|
18350
|
+
}
|
|
18351
|
+
return items;
|
|
18352
|
+
}
|
|
18353
|
+
/**
|
|
18354
|
+
* Get item by index
|
|
18355
|
+
*/
|
|
18356
|
+
getItem(index2) {
|
|
18357
|
+
return this._cache.get(index2);
|
|
18358
|
+
}
|
|
18359
|
+
/**
|
|
18360
|
+
* Get total count of items (if available)
|
|
18361
|
+
*/
|
|
18362
|
+
get totalCount() {
|
|
18363
|
+
return this._pagination.totalCount;
|
|
18364
|
+
}
|
|
18365
|
+
/**
|
|
18366
|
+
* Get current pagination state
|
|
18367
|
+
*/
|
|
18368
|
+
get pagination() {
|
|
18369
|
+
return { ...this._pagination };
|
|
18370
|
+
}
|
|
18371
|
+
/**
|
|
18372
|
+
* Get current viewport
|
|
18373
|
+
*/
|
|
18374
|
+
get viewport() {
|
|
18375
|
+
return { ...this._viewport };
|
|
18376
|
+
}
|
|
18377
|
+
/**
|
|
18378
|
+
* Get cache size (for debugging)
|
|
18379
|
+
*/
|
|
18380
|
+
get cacheSize() {
|
|
18381
|
+
return this._cache.size;
|
|
18382
|
+
}
|
|
18383
|
+
/**
|
|
18384
|
+
* Check if a range is cached
|
|
18385
|
+
*/
|
|
18386
|
+
isCached(start, end) {
|
|
18387
|
+
for (let i7 = start; i7 < end; i7++) {
|
|
18388
|
+
if (!this._cache.has(i7)) {
|
|
18389
|
+
return false;
|
|
18390
|
+
}
|
|
18391
|
+
}
|
|
18392
|
+
return true;
|
|
18393
|
+
}
|
|
18394
|
+
/**
|
|
18395
|
+
* Subscribe to events
|
|
18396
|
+
*/
|
|
18397
|
+
on(event, callback2) {
|
|
18398
|
+
if (!this._listeners.has(event)) {
|
|
18399
|
+
this._listeners.set(event, /* @__PURE__ */ new Set());
|
|
18400
|
+
}
|
|
18401
|
+
this._listeners.get(event).add(callback2);
|
|
18402
|
+
}
|
|
18403
|
+
/**
|
|
18404
|
+
* Unsubscribe from events
|
|
18405
|
+
*/
|
|
18406
|
+
off(event, callback2) {
|
|
18407
|
+
const listeners = this._listeners.get(event);
|
|
18408
|
+
if (listeners) {
|
|
18409
|
+
listeners.delete(callback2);
|
|
18410
|
+
}
|
|
18411
|
+
}
|
|
18412
|
+
/**
|
|
18413
|
+
* Clear cache
|
|
18414
|
+
*/
|
|
18415
|
+
clearCache() {
|
|
18416
|
+
this._cache.clear();
|
|
18417
|
+
this._emit("cache-cleared");
|
|
18418
|
+
}
|
|
18419
|
+
/**
|
|
18420
|
+
* Apply patches from state-changed events
|
|
18421
|
+
* Updates cache with new/modified items
|
|
18422
|
+
*/
|
|
18423
|
+
applyPatches(patches) {
|
|
18424
|
+
for (const patch of patches) {
|
|
18425
|
+
this._applyPatch(patch);
|
|
18426
|
+
}
|
|
18427
|
+
this._emit("patched", { patches });
|
|
18428
|
+
}
|
|
18429
|
+
/**
|
|
18430
|
+
* Find which ranges need to be fetched
|
|
18431
|
+
*/
|
|
18432
|
+
_findMissingRanges(start, end) {
|
|
18433
|
+
const missing = [];
|
|
18434
|
+
for (let i7 = start; i7 < end; i7++) {
|
|
18435
|
+
if (!this._cache.has(i7)) {
|
|
18436
|
+
missing.push(i7);
|
|
18437
|
+
}
|
|
18438
|
+
}
|
|
18439
|
+
const ranges = [];
|
|
18440
|
+
if (missing.length === 0) return ranges;
|
|
18441
|
+
let rangeStart = missing[0];
|
|
18442
|
+
let rangeEnd2 = missing[0];
|
|
18443
|
+
for (let i7 = 1; i7 < missing.length; i7++) {
|
|
18444
|
+
if (missing[i7] === rangeEnd2 + 1) {
|
|
18445
|
+
rangeEnd2 = missing[i7];
|
|
18446
|
+
} else {
|
|
18447
|
+
ranges.push({ start: rangeStart, end: rangeEnd2 + 1 });
|
|
18448
|
+
rangeStart = missing[i7];
|
|
18449
|
+
rangeEnd2 = missing[i7];
|
|
18450
|
+
}
|
|
18451
|
+
}
|
|
18452
|
+
ranges.push({ start: rangeStart, end: rangeEnd2 + 1 });
|
|
18453
|
+
return ranges;
|
|
18454
|
+
}
|
|
18455
|
+
/**
|
|
18456
|
+
* Fetch a range of items via MCP
|
|
18457
|
+
*/
|
|
18458
|
+
async _fetchRange(start, end) {
|
|
18459
|
+
const rangeKey = `${start}-${end}`;
|
|
18460
|
+
if (this._pendingRanges.has(rangeKey)) {
|
|
18461
|
+
return;
|
|
18462
|
+
}
|
|
18463
|
+
this._pendingRanges.add(rangeKey);
|
|
18464
|
+
try {
|
|
18465
|
+
const toolName = `${this._photonName}/${this._methodName}`;
|
|
18466
|
+
const result = await this._mcpClient.callTool(toolName, {
|
|
18467
|
+
start,
|
|
18468
|
+
limit: Math.min(end - start, this._fetchOptions.pageSize)
|
|
18469
|
+
});
|
|
18470
|
+
if (result.isError) {
|
|
18471
|
+
console.error(`Failed to fetch ${toolName}[${start}:${end}]`, result);
|
|
18472
|
+
return;
|
|
18473
|
+
}
|
|
18474
|
+
const parsed = this._mcpClient.parseToolResult(result);
|
|
18475
|
+
if (parsed && typeof parsed === "object") {
|
|
18476
|
+
const { items = [], _pagination } = parsed;
|
|
18477
|
+
if (_pagination) {
|
|
18478
|
+
this._pagination = _pagination;
|
|
18479
|
+
}
|
|
18480
|
+
items.forEach((item, offset) => {
|
|
18481
|
+
this._cache.set(start + offset, item);
|
|
18482
|
+
});
|
|
18483
|
+
if (this._cache.size > this._fetchOptions.maxCacheSize) {
|
|
18484
|
+
this._pruneCache();
|
|
18485
|
+
}
|
|
18486
|
+
this._emit("fetched", { start, end, itemCount: items.length });
|
|
18487
|
+
}
|
|
18488
|
+
} finally {
|
|
18489
|
+
this._pendingRanges.delete(rangeKey);
|
|
18490
|
+
}
|
|
18491
|
+
}
|
|
18492
|
+
/**
|
|
18493
|
+
* Apply a single JSON Patch to cache
|
|
18494
|
+
*/
|
|
18495
|
+
_applyPatch(patch) {
|
|
18496
|
+
const { op, path } = patch;
|
|
18497
|
+
const match = path.match(/\/items\/(\d+)/);
|
|
18498
|
+
if (!match) return;
|
|
18499
|
+
const index2 = parseInt(match[1], 10);
|
|
18500
|
+
switch (op) {
|
|
18501
|
+
case "add": {
|
|
18502
|
+
const newCache = /* @__PURE__ */ new Map();
|
|
18503
|
+
for (const [key, value] of this._cache) {
|
|
18504
|
+
if (key >= index2) {
|
|
18505
|
+
newCache.set(key + 1, value);
|
|
18506
|
+
} else {
|
|
18507
|
+
newCache.set(key, value);
|
|
18508
|
+
}
|
|
18509
|
+
}
|
|
18510
|
+
newCache.set(index2, patch.value);
|
|
18511
|
+
this._cache = newCache;
|
|
18512
|
+
this._pagination.totalCount++;
|
|
18513
|
+
break;
|
|
18514
|
+
}
|
|
18515
|
+
case "remove": {
|
|
18516
|
+
const newCache = /* @__PURE__ */ new Map();
|
|
18517
|
+
for (const [key, value] of this._cache) {
|
|
18518
|
+
if (key > index2) {
|
|
18519
|
+
newCache.set(key - 1, value);
|
|
18520
|
+
} else if (key < index2) {
|
|
18521
|
+
newCache.set(key, value);
|
|
18522
|
+
}
|
|
18523
|
+
}
|
|
18524
|
+
this._cache = newCache;
|
|
18525
|
+
this._pagination.totalCount--;
|
|
18526
|
+
break;
|
|
18527
|
+
}
|
|
18528
|
+
case "replace": {
|
|
18529
|
+
this._cache.set(index2, patch.value);
|
|
18530
|
+
break;
|
|
18531
|
+
}
|
|
18532
|
+
}
|
|
18533
|
+
}
|
|
18534
|
+
/**
|
|
18535
|
+
* Remove least-recently-used items from cache when it gets too large
|
|
18536
|
+
*/
|
|
18537
|
+
_pruneCache() {
|
|
18538
|
+
const toRemove = this._cache.size - this._fetchOptions.maxCacheSize;
|
|
18539
|
+
if (toRemove <= 0) return;
|
|
18540
|
+
const viewportCenter = this._viewport.start + (this._viewport.end - this._viewport.start) / 2;
|
|
18541
|
+
const sortedKeys = Array.from(this._cache.keys()).sort(
|
|
18542
|
+
(a5, b3) => Math.abs(a5 - viewportCenter) - Math.abs(b3 - viewportCenter)
|
|
18543
|
+
);
|
|
18544
|
+
for (let i7 = 0; i7 < toRemove && i7 < sortedKeys.length; i7++) {
|
|
18545
|
+
this._cache.delete(sortedKeys[i7]);
|
|
18546
|
+
}
|
|
18547
|
+
}
|
|
18548
|
+
/**
|
|
18549
|
+
* Emit event to listeners
|
|
18550
|
+
*/
|
|
18551
|
+
_emit(event, data) {
|
|
18552
|
+
const listeners = this._listeners.get(event);
|
|
18553
|
+
if (listeners) {
|
|
18554
|
+
for (const callback2 of listeners) {
|
|
18555
|
+
try {
|
|
18556
|
+
callback2(data);
|
|
18557
|
+
} catch (err) {
|
|
18558
|
+
console.error(`Error in ${event} listener:`, err);
|
|
18559
|
+
}
|
|
18560
|
+
}
|
|
18561
|
+
}
|
|
18562
|
+
}
|
|
18563
|
+
};
|
|
18564
|
+
|
|
18565
|
+
// src/auto-ui/frontend/services/viewport-manager.ts
|
|
18566
|
+
function getPageSizeForClient() {
|
|
18567
|
+
if (typeof window !== "undefined" && window.innerWidth < 600) {
|
|
18568
|
+
return 10;
|
|
18569
|
+
}
|
|
18570
|
+
if (typeof window !== "undefined" && window.innerWidth < 1024) {
|
|
18571
|
+
return 25;
|
|
18572
|
+
}
|
|
18573
|
+
return 50;
|
|
18574
|
+
}
|
|
18575
|
+
var ViewportManager = class {
|
|
18576
|
+
constructor(config3) {
|
|
18577
|
+
this.observer = null;
|
|
18578
|
+
this.visibleSentinels = /* @__PURE__ */ new Set();
|
|
18579
|
+
this.lastVisibleRange = { start: 0, end: 0 };
|
|
18580
|
+
this.lastScrollDirection = "none";
|
|
18581
|
+
this.changeCallbacks = [];
|
|
18582
|
+
this.element = config3.element;
|
|
18583
|
+
this.pageSize = config3.pageSize;
|
|
18584
|
+
this.paddingAbove = config3.paddingAbove ?? this.pageSize;
|
|
18585
|
+
this.paddingBelow = config3.paddingBelow ?? this.pageSize * 2;
|
|
18586
|
+
this.debug = config3.debug ?? false;
|
|
18587
|
+
this.log("ViewportManager initialized", {
|
|
18588
|
+
pageSize: this.pageSize,
|
|
18589
|
+
paddingAbove: this.paddingAbove,
|
|
18590
|
+
paddingBelow: this.paddingBelow
|
|
18591
|
+
});
|
|
18592
|
+
this.initializeObserver();
|
|
18593
|
+
}
|
|
18594
|
+
initializeObserver() {
|
|
18595
|
+
const options = {
|
|
18596
|
+
root: null,
|
|
18597
|
+
rootMargin: "100px",
|
|
18598
|
+
threshold: 0
|
|
18599
|
+
};
|
|
18600
|
+
this.observer = new IntersectionObserver((entries) => {
|
|
18601
|
+
for (const entry of entries) {
|
|
18602
|
+
const index2 = this.getSentinelIndex(entry.target);
|
|
18603
|
+
if (index2 !== null) {
|
|
18604
|
+
if (entry.isIntersecting) {
|
|
18605
|
+
this.visibleSentinels.add(index2);
|
|
18606
|
+
} else {
|
|
18607
|
+
this.visibleSentinels.delete(index2);
|
|
18608
|
+
}
|
|
18609
|
+
}
|
|
18610
|
+
}
|
|
18611
|
+
this.updateVisibleRange();
|
|
18612
|
+
}, options);
|
|
18613
|
+
}
|
|
18614
|
+
createSentinel(index2) {
|
|
18615
|
+
const sentinel = document.createElement("div");
|
|
18616
|
+
sentinel.setAttribute("data-viewport-sentinel", String(index2));
|
|
18617
|
+
sentinel.style.height = "0px";
|
|
18618
|
+
sentinel.style.overflow = "hidden";
|
|
18619
|
+
return sentinel;
|
|
18620
|
+
}
|
|
18621
|
+
observeSentinel(sentinel) {
|
|
18622
|
+
if (this.observer) {
|
|
18623
|
+
this.observer.observe(sentinel);
|
|
18624
|
+
}
|
|
18625
|
+
}
|
|
18626
|
+
unobserveSentinel(sentinel) {
|
|
18627
|
+
if (this.observer) {
|
|
18628
|
+
this.observer.unobserve(sentinel);
|
|
18629
|
+
}
|
|
18630
|
+
}
|
|
18631
|
+
getSentinelIndex(element) {
|
|
18632
|
+
const attr = element.getAttribute("data-viewport-sentinel");
|
|
18633
|
+
return attr !== null ? parseInt(attr, 10) : null;
|
|
18634
|
+
}
|
|
18635
|
+
updateVisibleRange() {
|
|
18636
|
+
if (this.visibleSentinels.size === 0) {
|
|
18637
|
+
return;
|
|
18638
|
+
}
|
|
18639
|
+
const indices = Array.from(this.visibleSentinels).sort((a5, b3) => a5 - b3);
|
|
18640
|
+
const visibleStart = indices[0];
|
|
18641
|
+
const visibleEnd = indices[indices.length - 1] + 1;
|
|
18642
|
+
const direction = this.determineScrollDirection(visibleStart);
|
|
18643
|
+
const bufferStart = Math.max(
|
|
18644
|
+
0,
|
|
18645
|
+
visibleStart - Math.ceil(this.paddingAbove / this.pageSize) * this.pageSize
|
|
18646
|
+
);
|
|
18647
|
+
const bufferEnd = visibleEnd + Math.ceil(this.paddingBelow / this.pageSize) * this.pageSize;
|
|
18648
|
+
const rangeChanged = visibleStart !== this.lastVisibleRange.start || visibleEnd !== this.lastVisibleRange.end;
|
|
18649
|
+
if (rangeChanged) {
|
|
18650
|
+
this.lastVisibleRange = { start: visibleStart, end: visibleEnd };
|
|
18651
|
+
this.lastScrollDirection = direction;
|
|
18652
|
+
const event = {
|
|
18653
|
+
visibleRange: { start: visibleStart, end: visibleEnd },
|
|
18654
|
+
bufferRange: { start: bufferStart, end: bufferEnd },
|
|
18655
|
+
scrollDirection: direction,
|
|
18656
|
+
timestamp: Date.now()
|
|
18657
|
+
};
|
|
18658
|
+
this.log("Viewport changed", event);
|
|
18659
|
+
for (const callback2 of this.changeCallbacks) {
|
|
18660
|
+
callback2(event);
|
|
18661
|
+
}
|
|
18662
|
+
}
|
|
18663
|
+
}
|
|
18664
|
+
determineScrollDirection(newStart) {
|
|
18665
|
+
if (newStart < this.lastVisibleRange.start) {
|
|
18666
|
+
return "up";
|
|
18667
|
+
} else if (newStart > this.lastVisibleRange.start) {
|
|
18668
|
+
return "down";
|
|
18669
|
+
}
|
|
18670
|
+
return "none";
|
|
18671
|
+
}
|
|
18672
|
+
getVisibleRange() {
|
|
18673
|
+
return this.lastVisibleRange;
|
|
18674
|
+
}
|
|
18675
|
+
getBufferRange(totalItems) {
|
|
18676
|
+
const { start, end } = this.lastVisibleRange;
|
|
18677
|
+
const bufferStart = Math.max(0, start - this.paddingAbove);
|
|
18678
|
+
const bufferEnd = Math.min(totalItems, end + this.paddingBelow);
|
|
18679
|
+
return { start: bufferStart, end: bufferEnd };
|
|
18680
|
+
}
|
|
18681
|
+
getScrollDirection() {
|
|
18682
|
+
return this.lastScrollDirection;
|
|
18683
|
+
}
|
|
18684
|
+
getPageSize() {
|
|
18685
|
+
return this.pageSize;
|
|
18686
|
+
}
|
|
18687
|
+
onChange(callback2) {
|
|
18688
|
+
this.changeCallbacks.push(callback2);
|
|
18689
|
+
}
|
|
18690
|
+
offChange(callback2) {
|
|
18691
|
+
this.changeCallbacks = this.changeCallbacks.filter((cb) => cb !== callback2);
|
|
18692
|
+
}
|
|
18693
|
+
setPageSize(newPageSize) {
|
|
18694
|
+
if (newPageSize !== this.pageSize) {
|
|
18695
|
+
this.pageSize = newPageSize;
|
|
18696
|
+
this.log("Page size updated", { newPageSize });
|
|
18697
|
+
this.updateVisibleRange();
|
|
18698
|
+
}
|
|
18699
|
+
}
|
|
18700
|
+
destroy() {
|
|
18701
|
+
if (this.observer) {
|
|
18702
|
+
this.observer.disconnect();
|
|
18703
|
+
this.observer = null;
|
|
18704
|
+
}
|
|
18705
|
+
this.changeCallbacks = [];
|
|
18706
|
+
this.visibleSentinels.clear();
|
|
18707
|
+
this.log("ViewportManager destroyed");
|
|
18708
|
+
}
|
|
18709
|
+
log(message, data) {
|
|
18710
|
+
if (this.debug) {
|
|
18711
|
+
console.log(`[ViewportManager] ${message}`, data);
|
|
18712
|
+
}
|
|
18713
|
+
}
|
|
18714
|
+
};
|
|
18715
|
+
|
|
17934
18716
|
// src/auto-ui/frontend/components/beam-app.ts
|
|
17935
18717
|
var THEME_STORAGE_KEY = "beam-theme";
|
|
17936
18718
|
var PROTOCOL_STORAGE_KEY = "beam-protocol";
|
|
@@ -17994,6 +18776,10 @@ var BeamApp = class extends i4 {
|
|
|
17994
18776
|
this._promptArguments = {};
|
|
17995
18777
|
this._renderedPrompt = "";
|
|
17996
18778
|
this._resourceContent = "";
|
|
18779
|
+
this._splitPanels = [];
|
|
18780
|
+
this._methodPickerOpen = false;
|
|
18781
|
+
this._methodPickerPanelId = null;
|
|
18782
|
+
this._nextPanelId = 0;
|
|
17997
18783
|
// Collection auto-subscription for ReactiveArray/Map/Set events
|
|
17998
18784
|
this._collectionUnsubscribes = [];
|
|
17999
18785
|
this._currentCollectionName = null;
|
|
@@ -18004,6 +18790,10 @@ var BeamApp = class extends i4 {
|
|
|
18004
18790
|
this._fileIdCounter = 0;
|
|
18005
18791
|
// Deep link URL for setOpenInAppUrl
|
|
18006
18792
|
this._openInAppUrl = null;
|
|
18793
|
+
// PWA install state
|
|
18794
|
+
this._pwaInstallPrompt = null;
|
|
18795
|
+
this._pwaIsStandalone = false;
|
|
18796
|
+
this._pwaCurrentPhoton = null;
|
|
18007
18797
|
this._handleDocumentClick = (e8) => {
|
|
18008
18798
|
const path = e8.composedPath();
|
|
18009
18799
|
if (this._showSettingsMenu) {
|
|
@@ -18021,11 +18811,11 @@ var BeamApp = class extends i4 {
|
|
|
18021
18811
|
}
|
|
18022
18812
|
};
|
|
18023
18813
|
this._initialConnectDone = false;
|
|
18024
|
-
this.
|
|
18814
|
+
this._handleRouteChange = () => {
|
|
18025
18815
|
void (async () => {
|
|
18026
|
-
const
|
|
18027
|
-
const
|
|
18028
|
-
const [photonName, methodName] =
|
|
18816
|
+
const fullPath = window.location.pathname.slice(1);
|
|
18817
|
+
const queryPart = window.location.search.slice(1);
|
|
18818
|
+
const [photonName, methodName] = fullPath.split("/");
|
|
18029
18819
|
let sharedParams = {};
|
|
18030
18820
|
if (queryPart) {
|
|
18031
18821
|
const params = new URLSearchParams(queryPart);
|
|
@@ -18042,6 +18832,9 @@ var BeamApp = class extends i4 {
|
|
|
18042
18832
|
}
|
|
18043
18833
|
}
|
|
18044
18834
|
}
|
|
18835
|
+
this._methodPickerOpen = false;
|
|
18836
|
+
this._methodPickerPanelId = null;
|
|
18837
|
+
this._splitPanels = [];
|
|
18045
18838
|
if (!photonName || photonName === "home") {
|
|
18046
18839
|
this._selectedPhoton = null;
|
|
18047
18840
|
this._selectedMethod = null;
|
|
@@ -18068,7 +18861,8 @@ var BeamApp = class extends i4 {
|
|
|
18068
18861
|
return;
|
|
18069
18862
|
}
|
|
18070
18863
|
if (methodName && photon.methods) {
|
|
18071
|
-
const
|
|
18864
|
+
const [firstMethodName, secondMethodName] = methodName.split("+");
|
|
18865
|
+
const method = photon.methods.find((m3) => m3.name === firstMethodName);
|
|
18072
18866
|
if (method) {
|
|
18073
18867
|
if (Object.keys(sharedParams).length > 0) {
|
|
18074
18868
|
this._sharedFormParams = sharedParams;
|
|
@@ -18079,6 +18873,22 @@ var BeamApp = class extends i4 {
|
|
|
18079
18873
|
}
|
|
18080
18874
|
this._selectedMethod = method;
|
|
18081
18875
|
this._view = "form";
|
|
18876
|
+
if (secondMethodName) {
|
|
18877
|
+
const urlPath = location.pathname;
|
|
18878
|
+
const methodPart = urlPath.split("/").pop() || "";
|
|
18879
|
+
const methodNames = methodPart.split("+");
|
|
18880
|
+
for (let i7 = 1; i7 < methodNames.length; i7++) {
|
|
18881
|
+
const name2 = methodNames[i7];
|
|
18882
|
+
if (name2 === "source") {
|
|
18883
|
+
this._addPanel("source");
|
|
18884
|
+
} else {
|
|
18885
|
+
const panelMethod = photon.methods.find((m3) => m3.name === name2);
|
|
18886
|
+
if (panelMethod) {
|
|
18887
|
+
this._addPanel("method", panelMethod);
|
|
18888
|
+
}
|
|
18889
|
+
}
|
|
18890
|
+
}
|
|
18891
|
+
}
|
|
18082
18892
|
if (Object.keys(sharedParams).length === 0) {
|
|
18083
18893
|
this._maybeAutoInvoke(method);
|
|
18084
18894
|
}
|
|
@@ -18098,18 +18908,15 @@ var BeamApp = class extends i4 {
|
|
|
18098
18908
|
}
|
|
18099
18909
|
})();
|
|
18100
18910
|
};
|
|
18101
|
-
this._handlePopState = () => {
|
|
18102
|
-
void this._handleHashChange();
|
|
18103
|
-
};
|
|
18104
18911
|
this._goHome = () => {
|
|
18105
18912
|
this._selectedPhoton = null;
|
|
18106
18913
|
this._selectedMethod = null;
|
|
18107
18914
|
this._lastResult = null;
|
|
18108
|
-
this.
|
|
18915
|
+
this._updateRoute();
|
|
18109
18916
|
};
|
|
18110
18917
|
this._runTests = async () => {
|
|
18111
18918
|
if (!this._selectedPhoton || this._runningTests) return;
|
|
18112
|
-
const testMethods = this.
|
|
18919
|
+
const testMethods = await this._fetchTestList(this._selectedPhoton.name);
|
|
18113
18920
|
if (testMethods.length === 0) return;
|
|
18114
18921
|
this._runningTests = true;
|
|
18115
18922
|
this._testResults = [];
|
|
@@ -18195,6 +19002,7 @@ var BeamApp = class extends i4 {
|
|
|
18195
19002
|
`All photon tests: ${passed}/${total} passed`
|
|
18196
19003
|
);
|
|
18197
19004
|
};
|
|
19005
|
+
this._pickerDismissHandler = null;
|
|
18198
19006
|
this._toggleSettingsMenu = () => {
|
|
18199
19007
|
this._showSettingsMenu = !this._showSettingsMenu;
|
|
18200
19008
|
};
|
|
@@ -18213,8 +19021,45 @@ var BeamApp = class extends i4 {
|
|
|
18213
19021
|
};
|
|
18214
19022
|
this._launchAsApp = () => {
|
|
18215
19023
|
this._closeSettingsMenu();
|
|
18216
|
-
if (this._selectedPhoton)
|
|
18217
|
-
|
|
19024
|
+
if (!this._selectedPhoton) return;
|
|
19025
|
+
if (this._pwaInstallPrompt) {
|
|
19026
|
+
void (async () => {
|
|
19027
|
+
try {
|
|
19028
|
+
await fetch("/api/pwa/configure", {
|
|
19029
|
+
method: "POST",
|
|
19030
|
+
headers: { "Content-Type": "application/json" },
|
|
19031
|
+
body: JSON.stringify({
|
|
19032
|
+
photon: this._selectedPhoton.name,
|
|
19033
|
+
port: location.port || "4100"
|
|
19034
|
+
}),
|
|
19035
|
+
signal: AbortSignal.timeout(5e3)
|
|
19036
|
+
});
|
|
19037
|
+
} catch {
|
|
19038
|
+
}
|
|
19039
|
+
const photonName = this._selectedPhoton.name;
|
|
19040
|
+
const onInstalled = () => {
|
|
19041
|
+
window.open(`/app/${encodeURIComponent(photonName)}`, "_blank");
|
|
19042
|
+
};
|
|
19043
|
+
window.addEventListener("appinstalled", onInstalled, { once: true });
|
|
19044
|
+
const result = await this._pwaInstallPrompt.prompt();
|
|
19045
|
+
this._log("info", `PWA install prompt result: ${result?.outcome}`);
|
|
19046
|
+
if (result?.outcome !== "accepted") {
|
|
19047
|
+
window.removeEventListener("appinstalled", onInstalled);
|
|
19048
|
+
}
|
|
19049
|
+
this._pwaInstallPrompt = null;
|
|
19050
|
+
})();
|
|
19051
|
+
} else {
|
|
19052
|
+
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
19053
|
+
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
|
|
19054
|
+
if (isSafari || isIOS) {
|
|
19055
|
+
const hint = isIOS ? 'Tap the Share button, then "Add to Home Screen"' : "Use File > Add to Dock to install this app";
|
|
19056
|
+
showToast(hint, "info");
|
|
19057
|
+
} else {
|
|
19058
|
+
showToast(
|
|
19059
|
+
"Install not ready yet \u2014 the service worker needs a moment to generate icons. Try again in a few seconds.",
|
|
19060
|
+
"info"
|
|
19061
|
+
);
|
|
19062
|
+
}
|
|
18218
19063
|
}
|
|
18219
19064
|
};
|
|
18220
19065
|
this._handleRemove = async () => {
|
|
@@ -18380,7 +19225,7 @@ var BeamApp = class extends i4 {
|
|
|
18380
19225
|
}
|
|
18381
19226
|
}
|
|
18382
19227
|
this._view = "config";
|
|
18383
|
-
this.
|
|
19228
|
+
this._updateRoute();
|
|
18384
19229
|
};
|
|
18385
19230
|
this._toggleRememberValues = () => {
|
|
18386
19231
|
this._rememberFormValues = !this._rememberFormValues;
|
|
@@ -18965,7 +19810,7 @@ var BeamApp = class extends i4 {
|
|
|
18965
19810
|
}
|
|
18966
19811
|
if (e8.key === "Enter" && this._selectedMethod && this._view === "list") {
|
|
18967
19812
|
this._view = "form";
|
|
18968
|
-
this.
|
|
19813
|
+
this._updateRoute();
|
|
18969
19814
|
return;
|
|
18970
19815
|
}
|
|
18971
19816
|
if (e8.key === "r") {
|
|
@@ -19001,12 +19846,12 @@ var BeamApp = class extends i4 {
|
|
|
19001
19846
|
this._focusMode = !this._focusMode;
|
|
19002
19847
|
if (this._focusMode) {
|
|
19003
19848
|
this.classList.add("focus-mode");
|
|
19004
|
-
const
|
|
19005
|
-
history.replaceState(null, "",
|
|
19849
|
+
const path = window.location.pathname;
|
|
19850
|
+
history.replaceState(null, "", path + "?focus=1");
|
|
19006
19851
|
} else {
|
|
19007
19852
|
this.classList.remove("focus-mode");
|
|
19008
|
-
const
|
|
19009
|
-
history.replaceState(null, "",
|
|
19853
|
+
const path = window.location.pathname;
|
|
19854
|
+
history.replaceState(null, "", path);
|
|
19010
19855
|
}
|
|
19011
19856
|
};
|
|
19012
19857
|
this._handleFullscreen = () => {
|
|
@@ -19105,9 +19950,25 @@ var BeamApp = class extends i4 {
|
|
|
19105
19950
|
case "fullscreen":
|
|
19106
19951
|
this._handleFullscreen();
|
|
19107
19952
|
break;
|
|
19953
|
+
case "install-app":
|
|
19954
|
+
this._launchAsApp();
|
|
19955
|
+
break;
|
|
19956
|
+
}
|
|
19957
|
+
break;
|
|
19958
|
+
}
|
|
19959
|
+
case "split-view:add":
|
|
19960
|
+
this._showMethodPicker();
|
|
19961
|
+
break;
|
|
19962
|
+
case "split-view:change": {
|
|
19963
|
+
const method = this._selectedPhoton?.methods?.find((m3) => m3.name === e8.detail.method);
|
|
19964
|
+
if (method && this._splitPanels.length > 0) {
|
|
19965
|
+
this._changePanelMethod(this._splitPanels[0].id, method);
|
|
19108
19966
|
}
|
|
19109
19967
|
break;
|
|
19110
19968
|
}
|
|
19969
|
+
case "split-view:remove":
|
|
19970
|
+
this._closeSecondPanel();
|
|
19971
|
+
break;
|
|
19111
19972
|
}
|
|
19112
19973
|
};
|
|
19113
19974
|
this._startEditingDescription = () => {
|
|
@@ -19307,7 +20168,7 @@ var BeamApp = class extends i4 {
|
|
|
19307
20168
|
if (method) {
|
|
19308
20169
|
this._selectedMethod = method;
|
|
19309
20170
|
this._view = "form";
|
|
19310
|
-
this.
|
|
20171
|
+
this._updateRoute();
|
|
19311
20172
|
this._log("info", `Starting ${targetName}/${action}...`);
|
|
19312
20173
|
showToast(`Starting ${action}...`, "info");
|
|
19313
20174
|
} else {
|
|
@@ -19334,15 +20195,21 @@ var BeamApp = class extends i4 {
|
|
|
19334
20195
|
*/
|
|
19335
20196
|
_handleGlobalMethodSelect(photon, method) {
|
|
19336
20197
|
this._teardownActiveCustomUI();
|
|
20198
|
+
if (this._selectedPhoton?.name !== photon.name) {
|
|
20199
|
+
this._closeSecondPanel();
|
|
20200
|
+
}
|
|
19337
20201
|
this._selectedPhoton = photon;
|
|
19338
20202
|
if (this._willAutoInvoke(method)) {
|
|
19339
20203
|
this._isExecuting = true;
|
|
19340
20204
|
}
|
|
19341
20205
|
this._selectedMethod = method;
|
|
19342
20206
|
this._view = "form";
|
|
19343
|
-
this.
|
|
20207
|
+
this._updateRoute();
|
|
19344
20208
|
this._maybeAutoInvoke(method);
|
|
19345
20209
|
}
|
|
20210
|
+
get _splitViewEnabled() {
|
|
20211
|
+
return this._splitPanels.length > 0;
|
|
20212
|
+
}
|
|
19346
20213
|
connectedCallback() {
|
|
19347
20214
|
super.connectedCallback();
|
|
19348
20215
|
const savedTheme = localStorage.getItem(THEME_STORAGE_KEY);
|
|
@@ -19374,20 +20241,114 @@ var BeamApp = class extends i4 {
|
|
|
19374
20241
|
}
|
|
19375
20242
|
document.addEventListener("click", this._handleDocumentClick);
|
|
19376
20243
|
void this._connectMCP();
|
|
19377
|
-
|
|
19378
|
-
window.addEventListener("popstate", this.
|
|
20244
|
+
this._setupNotificationHandlers();
|
|
20245
|
+
window.addEventListener("popstate", this._handleRouteChange);
|
|
19379
20246
|
window.addEventListener("message", this._handleBridgeMessage);
|
|
19380
20247
|
window.addEventListener("keydown", this._handleKeydown);
|
|
20248
|
+
this._initPWA();
|
|
19381
20249
|
}
|
|
19382
20250
|
disconnectedCallback() {
|
|
19383
20251
|
super.disconnectedCallback();
|
|
19384
|
-
window.removeEventListener("
|
|
19385
|
-
window.removeEventListener("popstate", this._handlePopState);
|
|
20252
|
+
window.removeEventListener("popstate", this._handleRouteChange);
|
|
19386
20253
|
window.removeEventListener("message", this._handleBridgeMessage);
|
|
19387
20254
|
window.removeEventListener("keydown", this._handleKeydown);
|
|
19388
20255
|
document.removeEventListener("click", this._handleDocumentClick);
|
|
19389
20256
|
this._cleanupCollectionSubscriptions();
|
|
19390
20257
|
}
|
|
20258
|
+
willUpdate(changedProperties) {
|
|
20259
|
+
super.willUpdate(changedProperties);
|
|
20260
|
+
if (changedProperties.has("_selectedPhoton")) {
|
|
20261
|
+
const name2 = this._selectedPhoton?.name || null;
|
|
20262
|
+
if (name2 !== this._pwaCurrentPhoton) {
|
|
20263
|
+
this._pwaCurrentPhoton = name2;
|
|
20264
|
+
if (name2) {
|
|
20265
|
+
this._setupPWAManifest(name2);
|
|
20266
|
+
}
|
|
20267
|
+
}
|
|
20268
|
+
}
|
|
20269
|
+
}
|
|
20270
|
+
// ---------------------------------------------------------------------------
|
|
20271
|
+
// PWA — Progressive Web App support
|
|
20272
|
+
// ---------------------------------------------------------------------------
|
|
20273
|
+
_initPWA() {
|
|
20274
|
+
this._pwaIsStandalone = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true;
|
|
20275
|
+
if ("serviceWorker" in navigator) {
|
|
20276
|
+
navigator.serviceWorker.register("/sw.js", { scope: "/" }).then((reg) => this._log("info", `PWA SW registered: ${reg.scope}`, true)).catch((err) => this._log("warn", `PWA SW registration failed: ${err}`, true));
|
|
20277
|
+
}
|
|
20278
|
+
window.addEventListener("beforeinstallprompt", (e8) => {
|
|
20279
|
+
this._pwaInstallPrompt = e8;
|
|
20280
|
+
});
|
|
20281
|
+
window.addEventListener("appinstalled", () => {
|
|
20282
|
+
this._pwaInstallPrompt = null;
|
|
20283
|
+
this._log("info", "PWA app installed");
|
|
20284
|
+
});
|
|
20285
|
+
}
|
|
20286
|
+
/**
|
|
20287
|
+
* Set up notification handlers for photon notifications.
|
|
20288
|
+
* When a notification arrives for a photon that cares about that event type,
|
|
20289
|
+
* bring the window to focus (especially important for PWAs/background tabs).
|
|
20290
|
+
*/
|
|
20291
|
+
_setupNotificationHandlers() {
|
|
20292
|
+
mcpClient.on("photon-notification", (notification) => {
|
|
20293
|
+
const { photon, type, priority } = notification;
|
|
20294
|
+
if (!photon || !type) return;
|
|
20295
|
+
const sidebarElement = this.querySelector("beam-sidebar");
|
|
20296
|
+
if (sidebarElement && sidebarElement.isNotificationWatched) {
|
|
20297
|
+
const isWatched = sidebarElement.isNotificationWatched(photon, type);
|
|
20298
|
+
if (isWatched) {
|
|
20299
|
+
window.focus();
|
|
20300
|
+
console.log(`\u{1F4E1} Window focused for ${photon} notification: ${type}`);
|
|
20301
|
+
sidebarElement.updatePhotonWarmth?.(photon);
|
|
20302
|
+
}
|
|
20303
|
+
}
|
|
20304
|
+
});
|
|
20305
|
+
}
|
|
20306
|
+
/**
|
|
20307
|
+
* Set up the PWA manifest & icons for the currently selected photon.
|
|
20308
|
+
* Called whenever the selected photon changes. The manifest points to
|
|
20309
|
+
* /api/pwa/icon-png URLs which the service worker intercepts and renders
|
|
20310
|
+
* as real PNGs via OffscreenCanvas — no client-side blob URL needed.
|
|
20311
|
+
*/
|
|
20312
|
+
_setupPWAManifest(photonName) {
|
|
20313
|
+
let manifestLink = document.head.querySelector('link[rel="manifest"]');
|
|
20314
|
+
if (!manifestLink) {
|
|
20315
|
+
manifestLink = document.createElement("link");
|
|
20316
|
+
manifestLink.rel = "manifest";
|
|
20317
|
+
document.head.appendChild(manifestLink);
|
|
20318
|
+
}
|
|
20319
|
+
manifestLink.href = `/api/pwa/manifest.json?photon=${encodeURIComponent(photonName)}`;
|
|
20320
|
+
let appleIcon = document.head.querySelector('link[rel="apple-touch-icon"]');
|
|
20321
|
+
if (!appleIcon) {
|
|
20322
|
+
appleIcon = document.createElement("link");
|
|
20323
|
+
appleIcon.rel = "apple-touch-icon";
|
|
20324
|
+
document.head.appendChild(appleIcon);
|
|
20325
|
+
}
|
|
20326
|
+
appleIcon.href = `/api/pwa/icon?photon=${encodeURIComponent(photonName)}`;
|
|
20327
|
+
let appleTitleMeta = document.head.querySelector(
|
|
20328
|
+
'meta[name="apple-mobile-web-app-title"]'
|
|
20329
|
+
);
|
|
20330
|
+
if (!appleTitleMeta) {
|
|
20331
|
+
appleTitleMeta = document.createElement("meta");
|
|
20332
|
+
appleTitleMeta.name = "apple-mobile-web-app-title";
|
|
20333
|
+
document.head.appendChild(appleTitleMeta);
|
|
20334
|
+
}
|
|
20335
|
+
appleTitleMeta.content = photonName;
|
|
20336
|
+
this._prewarmIconCache(photonName);
|
|
20337
|
+
this._log("info", `PWA manifest set for "${photonName}"`, true);
|
|
20338
|
+
}
|
|
20339
|
+
/**
|
|
20340
|
+
* Pre-warm the service worker icon cache by fetching the PNG icon URLs.
|
|
20341
|
+
* This ensures the rendered emoji icons are cached before the user
|
|
20342
|
+
* attempts to install the PWA, improving the install dialog appearance.
|
|
20343
|
+
*/
|
|
20344
|
+
_prewarmIconCache(photonName) {
|
|
20345
|
+
const sizes = [192, 512];
|
|
20346
|
+
sizes.forEach((size) => {
|
|
20347
|
+
const url2 = `/api/pwa/icon-png?photon=${encodeURIComponent(photonName)}&size=${size}`;
|
|
20348
|
+
fetch(url2, { mode: "no-cors" }).catch(() => {
|
|
20349
|
+
});
|
|
20350
|
+
});
|
|
20351
|
+
}
|
|
19391
20352
|
async _connectMCP() {
|
|
19392
20353
|
try {
|
|
19393
20354
|
mcpClient.on("connect", () => {
|
|
@@ -19415,12 +20376,24 @@ var BeamApp = class extends i4 {
|
|
|
19415
20376
|
}
|
|
19416
20377
|
this._initialConnectDone = true;
|
|
19417
20378
|
void this._checkForUpdates();
|
|
19418
|
-
if (window.location.
|
|
19419
|
-
void this.
|
|
20379
|
+
if (window.location.pathname !== "/") {
|
|
20380
|
+
void this._handleRouteChange();
|
|
19420
20381
|
} else if (!this._selectedPhoton && this._photons.length > 0) {
|
|
19421
20382
|
const firstUserPhoton = this._photons.find((p5) => !p5.internal);
|
|
19422
|
-
if (firstUserPhoton)
|
|
19423
|
-
|
|
20383
|
+
if (firstUserPhoton) {
|
|
20384
|
+
this._selectedPhoton = firstUserPhoton;
|
|
20385
|
+
if (firstUserPhoton.isApp && firstUserPhoton.appEntry) {
|
|
20386
|
+
if (this._willAutoInvoke(firstUserPhoton.appEntry)) {
|
|
20387
|
+
this._isExecuting = true;
|
|
20388
|
+
}
|
|
20389
|
+
this._selectedMethod = firstUserPhoton.appEntry;
|
|
20390
|
+
this._view = "form";
|
|
20391
|
+
this._maybeAutoInvoke(firstUserPhoton.appEntry);
|
|
20392
|
+
} else {
|
|
20393
|
+
this._view = "list";
|
|
20394
|
+
}
|
|
20395
|
+
}
|
|
20396
|
+
this._updateRoute(true);
|
|
19424
20397
|
}
|
|
19425
20398
|
})();
|
|
19426
20399
|
});
|
|
@@ -19439,15 +20412,37 @@ var BeamApp = class extends i4 {
|
|
|
19439
20412
|
this._photons = photons;
|
|
19440
20413
|
this._externalMCPs = externalMCPs;
|
|
19441
20414
|
this._addUnconfiguredPhotons();
|
|
19442
|
-
if (
|
|
19443
|
-
const
|
|
19444
|
-
|
|
19445
|
-
|
|
19446
|
-
|
|
19447
|
-
this.
|
|
19448
|
-
|
|
19449
|
-
|
|
19450
|
-
|
|
20415
|
+
if (this._selectedPhoton) {
|
|
20416
|
+
const updated = this._photons.find((p5) => p5.name === this._selectedPhoton?.name);
|
|
20417
|
+
if (updated) {
|
|
20418
|
+
const wasApp = this._selectedPhoton.isApp;
|
|
20419
|
+
this._selectedPhoton = updated;
|
|
20420
|
+
if (!wasApp && updated.isApp && updated.appEntry && this._view === "list") {
|
|
20421
|
+
if (this._willAutoInvoke(updated.appEntry)) {
|
|
20422
|
+
this._isExecuting = true;
|
|
20423
|
+
}
|
|
20424
|
+
this._selectedMethod = updated.appEntry;
|
|
20425
|
+
this._view = "form";
|
|
20426
|
+
this._updateRoute(true);
|
|
20427
|
+
this._maybeAutoInvoke(updated.appEntry);
|
|
20428
|
+
}
|
|
20429
|
+
}
|
|
20430
|
+
}
|
|
20431
|
+
if (!this._selectedPhoton && window.location.pathname !== "/") {
|
|
20432
|
+
const pathPhotonName = window.location.pathname.slice(1).split("/")[0];
|
|
20433
|
+
const routePhoton = pathPhotonName ? this._photons.find((p5) => p5.name === pathPhotonName) : null;
|
|
20434
|
+
if (routePhoton) {
|
|
20435
|
+
void this._handleRouteChange();
|
|
20436
|
+
} else {
|
|
20437
|
+
const newUserPhoton = this._photons.find(
|
|
20438
|
+
(p5) => !p5.internal && p5.configured && !prevNames.has(p5.name)
|
|
20439
|
+
);
|
|
20440
|
+
if (newUserPhoton) {
|
|
20441
|
+
this._selectedPhoton = newUserPhoton;
|
|
20442
|
+
this._welcomePhase = "welcome";
|
|
20443
|
+
this._view = "list";
|
|
20444
|
+
this._updateRoute(true);
|
|
20445
|
+
}
|
|
19451
20446
|
}
|
|
19452
20447
|
}
|
|
19453
20448
|
})();
|
|
@@ -19511,7 +20506,7 @@ var BeamApp = class extends i4 {
|
|
|
19511
20506
|
this._selectedPhoton = updated;
|
|
19512
20507
|
}
|
|
19513
20508
|
} else {
|
|
19514
|
-
if (window.location.
|
|
20509
|
+
if (window.location.pathname === "/") return;
|
|
19515
20510
|
const newUserPhoton = this._photons.find(
|
|
19516
20511
|
(p5) => !p5.internal && p5.configured && !prevNames.has(p5.name)
|
|
19517
20512
|
);
|
|
@@ -19540,7 +20535,7 @@ var BeamApp = class extends i4 {
|
|
|
19540
20535
|
} else {
|
|
19541
20536
|
this._view = "list";
|
|
19542
20537
|
}
|
|
19543
|
-
this.
|
|
20538
|
+
this._updateRoute(true);
|
|
19544
20539
|
}
|
|
19545
20540
|
}
|
|
19546
20541
|
}
|
|
@@ -19592,7 +20587,7 @@ var BeamApp = class extends i4 {
|
|
|
19592
20587
|
} else {
|
|
19593
20588
|
this._view = "list";
|
|
19594
20589
|
}
|
|
19595
|
-
this.
|
|
20590
|
+
this._updateRoute(true);
|
|
19596
20591
|
}
|
|
19597
20592
|
}
|
|
19598
20593
|
});
|
|
@@ -19703,20 +20698,27 @@ var BeamApp = class extends i4 {
|
|
|
19703
20698
|
}
|
|
19704
20699
|
}
|
|
19705
20700
|
}
|
|
19706
|
-
|
|
19707
|
-
let
|
|
20701
|
+
_updateRoute(replace2 = false) {
|
|
20702
|
+
let path;
|
|
19708
20703
|
if (!this._selectedPhoton) {
|
|
19709
|
-
|
|
20704
|
+
path = "/";
|
|
19710
20705
|
} else {
|
|
19711
|
-
|
|
20706
|
+
path = "/" + this._selectedPhoton.name;
|
|
19712
20707
|
if (this._selectedMethod) {
|
|
19713
|
-
|
|
20708
|
+
path += `/${this._selectedMethod.name}`;
|
|
20709
|
+
for (const panel of this._splitPanels) {
|
|
20710
|
+
if (panel.type === "method" && panel.method) {
|
|
20711
|
+
path += `+${panel.method.name}`;
|
|
20712
|
+
} else if (panel.type === "source") {
|
|
20713
|
+
path += `+source`;
|
|
20714
|
+
}
|
|
20715
|
+
}
|
|
19714
20716
|
}
|
|
19715
20717
|
}
|
|
19716
20718
|
if (replace2) {
|
|
19717
|
-
history.replaceState(null, "",
|
|
20719
|
+
history.replaceState(null, "", path);
|
|
19718
20720
|
} else {
|
|
19719
|
-
history.pushState(null, "",
|
|
20721
|
+
history.pushState(null, "", path);
|
|
19720
20722
|
}
|
|
19721
20723
|
}
|
|
19722
20724
|
/**
|
|
@@ -19767,6 +20769,21 @@ var BeamApp = class extends i4 {
|
|
|
19767
20769
|
if (!this._selectedPhoton?.methods) return [];
|
|
19768
20770
|
return this._selectedPhoton.methods.filter((m3) => m3.name.startsWith("test_") || m3.name.startsWith("test")).map((m3) => m3.name);
|
|
19769
20771
|
}
|
|
20772
|
+
/** Fetch all tests (external .test.ts + inline) from the server */
|
|
20773
|
+
async _fetchTestList(photonName) {
|
|
20774
|
+
try {
|
|
20775
|
+
const res = await fetch(`/api/test/list?photon=${encodeURIComponent(photonName)}`, {
|
|
20776
|
+
signal: AbortSignal.timeout(5e3)
|
|
20777
|
+
});
|
|
20778
|
+
if (!res.ok) return this._getTestMethods();
|
|
20779
|
+
const data = await res.json();
|
|
20780
|
+
if (data.tests && data.tests.length > 0) {
|
|
20781
|
+
return data.tests.map((t8) => t8.name);
|
|
20782
|
+
}
|
|
20783
|
+
} catch {
|
|
20784
|
+
}
|
|
20785
|
+
return this._getTestMethods();
|
|
20786
|
+
}
|
|
19770
20787
|
_getAllTestMethods() {
|
|
19771
20788
|
const results = [];
|
|
19772
20789
|
for (const p5 of this._photons) {
|
|
@@ -20090,7 +21107,7 @@ var BeamApp = class extends i4 {
|
|
|
20090
21107
|
}}
|
|
20091
21108
|
@diagnostics=${() => {
|
|
20092
21109
|
this._view = "diagnostics";
|
|
20093
|
-
this.
|
|
21110
|
+
this._updateRoute();
|
|
20094
21111
|
}}
|
|
20095
21112
|
@open-studio=${(e8) => {
|
|
20096
21113
|
const photon = this._photons.find((p5) => p5.name === e8.detail.photonName);
|
|
@@ -20110,7 +21127,39 @@ var BeamApp = class extends i4 {
|
|
|
20110
21127
|
></beam-sidebar>
|
|
20111
21128
|
</nav>
|
|
20112
21129
|
|
|
20113
|
-
<main
|
|
21130
|
+
<main
|
|
21131
|
+
class="main-area"
|
|
21132
|
+
id="main-content"
|
|
21133
|
+
tabindex="-1"
|
|
21134
|
+
aria-label="Main content"
|
|
21135
|
+
style="${this._splitViewEnabled ? "overflow: hidden !important;" : ""}"
|
|
21136
|
+
>
|
|
21137
|
+
${this._selectedPhoton && this._selectedMethod ? b2`<button
|
|
21138
|
+
class="beam-back-btn"
|
|
21139
|
+
@click=${() => this._handleBackFromMethod()}
|
|
21140
|
+
@mouseenter=${(e8) => {
|
|
21141
|
+
e8.target.style.color = "var(--t-primary)";
|
|
21142
|
+
e8.target.style.borderColor = "var(--accent-primary)";
|
|
21143
|
+
}}
|
|
21144
|
+
@mouseleave=${(e8) => {
|
|
21145
|
+
e8.target.style.color = "var(--t-muted)";
|
|
21146
|
+
e8.target.style.borderColor = "var(--border-glass)";
|
|
21147
|
+
}}
|
|
21148
|
+
title="Back to ${this._selectedPhoton.name}"
|
|
21149
|
+
>
|
|
21150
|
+
<svg
|
|
21151
|
+
width="16"
|
|
21152
|
+
height="16"
|
|
21153
|
+
viewBox="0 0 24 24"
|
|
21154
|
+
fill="none"
|
|
21155
|
+
stroke="currentColor"
|
|
21156
|
+
stroke-width="2"
|
|
21157
|
+
stroke-linecap="round"
|
|
21158
|
+
stroke-linejoin="round"
|
|
21159
|
+
>
|
|
21160
|
+
<path d="m15 18-6-6 6-6" />
|
|
21161
|
+
</svg>
|
|
21162
|
+
</button>` : ""}
|
|
20114
21163
|
${this._selectedPhoton ? b2`<button
|
|
20115
21164
|
class="beam-fullscreen-btn"
|
|
20116
21165
|
@click=${this._toggleFocusMode}
|
|
@@ -20546,7 +21595,7 @@ var BeamApp = class extends i4 {
|
|
|
20546
21595
|
}}
|
|
20547
21596
|
@click=${() => {
|
|
20548
21597
|
this._view = "diagnostics";
|
|
20549
|
-
this.
|
|
21598
|
+
this._updateRoute();
|
|
20550
21599
|
}}
|
|
20551
21600
|
>
|
|
20552
21601
|
<span style="font-size: 1rem; width: 20px; text-align: center;">🔍</span>
|
|
@@ -20755,7 +21804,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
20755
21804
|
@select=${(e8) => {
|
|
20756
21805
|
this._selectedMethod = e8.detail.method;
|
|
20757
21806
|
this._view = "form";
|
|
20758
|
-
this.
|
|
21807
|
+
this._updateRoute();
|
|
20759
21808
|
}}
|
|
20760
21809
|
></method-card>
|
|
20761
21810
|
`
|
|
@@ -20772,7 +21821,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
20772
21821
|
if (this._selectedMethod.linkedUi) {
|
|
20773
21822
|
const isAppMain = this._selectedPhoton.isApp && this._selectedMethod.name === "main";
|
|
20774
21823
|
const otherMethods = isAppMain ? this._getVisibleMethods().filter((m3) => m3.name !== "main") : [];
|
|
20775
|
-
const
|
|
21824
|
+
const isExternalMCP = this._selectedPhoton.isExternalMCP;
|
|
20776
21825
|
const appRenderer = this._isExecuting ? b2`
|
|
20777
21826
|
<div
|
|
20778
21827
|
style="display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; height: calc(100vh - 140px);"
|
|
@@ -20782,7 +21831,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
20782
21831
|
${this._progress?.message || "Starting up\u2026"}
|
|
20783
21832
|
</span>
|
|
20784
21833
|
</div>
|
|
20785
|
-
` :
|
|
21834
|
+
` : isExternalMCP ? b2`
|
|
20786
21835
|
<mcp-app-renderer
|
|
20787
21836
|
.mcpName=${this._selectedPhoton.name}
|
|
20788
21837
|
.appUri=${`ui://${this._selectedPhoton.name}/${this._selectedMethod.linkedUi}`}
|
|
@@ -20801,7 +21850,48 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
20801
21850
|
></custom-ui-renderer>
|
|
20802
21851
|
`;
|
|
20803
21852
|
if (isAppMain) {
|
|
21853
|
+
if (this._splitPanels.length > 0) {
|
|
21854
|
+
return b2`
|
|
21855
|
+
<div style="display: flex; gap: 1px; height: calc(100vh - 60px); overflow: hidden;">
|
|
21856
|
+
<!-- App Panel (primary) — no title bar, app has its own chrome -->
|
|
21857
|
+
<div style="flex: 1; min-height: 0; overflow: hidden;">${appRenderer}</div>
|
|
21858
|
+
|
|
21859
|
+
<!-- Additional Panels -->
|
|
21860
|
+
${this._splitPanels.map(
|
|
21861
|
+
(panel) => b2`
|
|
21862
|
+
<div style="flex: 1; min-height: 0; background: var(--bg-panel);">
|
|
21863
|
+
${panel.type === "method" ? this._renderSinglePanel(this._buildAdditionalPanelOpts(panel)) : this._renderSourcePanel(panel.id)}
|
|
21864
|
+
</div>
|
|
21865
|
+
`
|
|
21866
|
+
)}
|
|
21867
|
+
</div>
|
|
21868
|
+
`;
|
|
21869
|
+
}
|
|
20804
21870
|
return b2`
|
|
21871
|
+
<!-- Floating add-panel button for app view — sits next to focus button -->
|
|
21872
|
+
<div
|
|
21873
|
+
style="position: sticky; top: calc(-1 * var(--space-lg)); float: right; z-index: 100; margin-top: calc(-1 * var(--space-lg)); margin-right: 6px;"
|
|
21874
|
+
>
|
|
21875
|
+
<button
|
|
21876
|
+
@click=${() => {
|
|
21877
|
+
this._methodPickerOpen = !this._methodPickerOpen;
|
|
21878
|
+
this._methodPickerPanelId = null;
|
|
21879
|
+
}}
|
|
21880
|
+
style="width: 28px; height: 28px; border-radius: var(--radius-sm); background: var(--bg-glass); border: 1px solid var(--border-glass); color: var(--t-muted); cursor: pointer; font-size: 14px; font-weight: 700; display: flex; align-items: center; justify-content: center; transition: all 0.2s ease; backdrop-filter: blur(8px);"
|
|
21881
|
+
@mouseenter=${(e8) => {
|
|
21882
|
+
e8.target.style.color = "var(--accent-secondary)";
|
|
21883
|
+
e8.target.style.borderColor = "var(--accent-secondary)";
|
|
21884
|
+
}}
|
|
21885
|
+
@mouseleave=${(e8) => {
|
|
21886
|
+
e8.target.style.color = "var(--t-muted)";
|
|
21887
|
+
e8.target.style.borderColor = "var(--border-glass)";
|
|
21888
|
+
}}
|
|
21889
|
+
title="Add panel"
|
|
21890
|
+
>
|
|
21891
|
+
+
|
|
21892
|
+
</button>
|
|
21893
|
+
${this._methodPickerOpen && this._methodPickerPanelId === null ? this._renderMethodPickerPopover() : ""}
|
|
21894
|
+
</div>
|
|
20805
21895
|
<app-layout
|
|
20806
21896
|
.photonName=${this._selectedPhoton.name}
|
|
20807
21897
|
.photonIcon=${this._selectedPhoton.appEntry?.icon || "\u{1F4F1}"}
|
|
@@ -20844,61 +21934,72 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
20844
21934
|
</app-layout>
|
|
20845
21935
|
`;
|
|
20846
21936
|
}
|
|
21937
|
+
if (this._splitPanels.length > 0) {
|
|
21938
|
+
return b2`
|
|
21939
|
+
<div style="display: flex; gap: 1px; height: calc(100vh - 60px); overflow: hidden;">
|
|
21940
|
+
<!-- Linked UI Panel (primary) -->
|
|
21941
|
+
<div
|
|
21942
|
+
style="flex: 1; min-height: 0; display: flex; flex-direction: column; position: relative;"
|
|
21943
|
+
>
|
|
21944
|
+
<div
|
|
21945
|
+
style="display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; border-bottom: 1px solid var(--border-glass); background: var(--bg-glass); flex-shrink: 0;"
|
|
21946
|
+
>
|
|
21947
|
+
<span style="font-size: 12px; font-weight: 500; color: var(--t-primary);"
|
|
21948
|
+
>${this._selectedMethod.name}</span
|
|
21949
|
+
>
|
|
21950
|
+
<div style="position: relative; flex-shrink: 0;">
|
|
21951
|
+
<button
|
|
21952
|
+
@click=${() => {
|
|
21953
|
+
this._methodPickerOpen = !this._methodPickerOpen;
|
|
21954
|
+
this._methodPickerPanelId = null;
|
|
21955
|
+
}}
|
|
21956
|
+
style="padding: 4px 8px; background: none; color: var(--accent-secondary); border: 1px solid var(--accent-secondary); border-radius: 3px; cursor: pointer; font-size: 14px; font-weight: 700; transition: all 0.2s ease;"
|
|
21957
|
+
title="Add panel"
|
|
21958
|
+
>
|
|
21959
|
+
+
|
|
21960
|
+
</button>
|
|
21961
|
+
${this._methodPickerOpen && this._methodPickerPanelId === null ? this._renderMethodPickerPopover() : ""}
|
|
21962
|
+
</div>
|
|
21963
|
+
</div>
|
|
21964
|
+
<div style="flex: 1; min-height: 0; overflow: hidden;">${appRenderer}</div>
|
|
21965
|
+
</div>
|
|
21966
|
+
|
|
21967
|
+
<!-- Additional Panels -->
|
|
21968
|
+
${this._splitPanels.map(
|
|
21969
|
+
(panel) => b2`
|
|
21970
|
+
<div style="flex: 1; min-height: 0; background: var(--bg-panel);">
|
|
21971
|
+
${panel.type === "method" ? this._renderSinglePanel(this._buildAdditionalPanelOpts(panel)) : this._renderSourcePanel(panel.id)}
|
|
21972
|
+
</div>
|
|
21973
|
+
`
|
|
21974
|
+
)}
|
|
21975
|
+
</div>
|
|
21976
|
+
`;
|
|
21977
|
+
}
|
|
20847
21978
|
return b2`
|
|
20848
|
-
<
|
|
20849
|
-
|
|
20850
|
-
|
|
20851
|
-
|
|
20852
|
-
|
|
20853
|
-
|
|
20854
|
-
|
|
20855
|
-
|
|
20856
|
-
|
|
20857
|
-
|
|
20858
|
-
|
|
20859
|
-
|
|
20860
|
-
|
|
20861
|
-
|
|
20862
|
-
|
|
20863
|
-
|
|
20864
|
-
|
|
20865
|
-
|
|
20866
|
-
|
|
20867
|
-
|
|
20868
|
-
style="padding: 0; overflow: hidden; min-height: calc(100vh - 80px); margin-top: var(--space-md);"
|
|
20869
|
-
>
|
|
20870
|
-
${appRenderer}
|
|
21979
|
+
<div style="position: relative;">
|
|
21980
|
+
<div style="position: absolute; top: 16px; right: 16px; z-index: 50;">
|
|
21981
|
+
<button
|
|
21982
|
+
@click=${() => {
|
|
21983
|
+
this._methodPickerOpen = !this._methodPickerOpen;
|
|
21984
|
+
this._methodPickerPanelId = null;
|
|
21985
|
+
}}
|
|
21986
|
+
style="padding: 4px 8px; background: var(--bg-glass); color: var(--accent-secondary); border: 1px solid var(--accent-secondary); border-radius: 3px; cursor: pointer; font-size: 14px; font-weight: 700; transition: all 0.2s ease; backdrop-filter: blur(8px);"
|
|
21987
|
+
title="Add panel"
|
|
21988
|
+
>
|
|
21989
|
+
+
|
|
21990
|
+
</button>
|
|
21991
|
+
${this._methodPickerOpen && this._methodPickerPanelId === null ? this._renderMethodPickerPopover() : ""}
|
|
21992
|
+
</div>
|
|
21993
|
+
<div
|
|
21994
|
+
class="glass-panel"
|
|
21995
|
+
style="padding: 0; overflow: hidden; min-height: calc(100vh - 80px); margin-top: var(--space-md);"
|
|
21996
|
+
>
|
|
21997
|
+
${appRenderer}
|
|
21998
|
+
</div>
|
|
20871
21999
|
</div>
|
|
20872
22000
|
`;
|
|
20873
22001
|
}
|
|
20874
|
-
|
|
20875
|
-
return b2`
|
|
20876
|
-
<context-bar
|
|
20877
|
-
.photon=${this._selectedPhoton}
|
|
20878
|
-
.breadcrumbs=${[
|
|
20879
|
-
{
|
|
20880
|
-
label: this._currentInstance !== "default" ? `${this._selectedPhoton.name}:${this._currentInstance}` : this._selectedPhoton.name,
|
|
20881
|
-
action: "back"
|
|
20882
|
-
},
|
|
20883
|
-
{ label: this._selectedMethod.name }
|
|
20884
|
-
]}
|
|
20885
|
-
.live=${this._currentCollectionName !== null}
|
|
20886
|
-
.showEdit=${false}
|
|
20887
|
-
.showConfigure=${false}
|
|
20888
|
-
.showCopyConfig=${false}
|
|
20889
|
-
.overflowItems=${this._buildOverflowItems({
|
|
20890
|
-
showRefresh: !isExternalMCP,
|
|
20891
|
-
showRename: false,
|
|
20892
|
-
showViewSource: false,
|
|
20893
|
-
showDelete: false,
|
|
20894
|
-
showHelp: !isExternalMCP
|
|
20895
|
-
})}
|
|
20896
|
-
.instanceSelectorMode=${this._instanceSelectorMode}
|
|
20897
|
-
.autoInstance=${this._autoInstance}
|
|
20898
|
-
@context-action=${this._handleContextAction}
|
|
20899
|
-
></context-bar>
|
|
20900
|
-
${this._renderMethodContent()}
|
|
20901
|
-
`;
|
|
22002
|
+
return b2` ${this._renderMethodContent()} `;
|
|
20902
22003
|
}
|
|
20903
22004
|
return b2`
|
|
20904
22005
|
${this._renderPhotonToolbar()} ${this._editingIcon ? this._renderEmojiPicker() : ""}
|
|
@@ -21026,6 +22127,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21026
22127
|
}
|
|
21027
22128
|
}
|
|
21028
22129
|
async _handlePhotonSelect(e8) {
|
|
22130
|
+
this._closeSecondPanel();
|
|
21029
22131
|
this._selectedPhoton = e8.detail.photon;
|
|
21030
22132
|
this._selectedMethod = null;
|
|
21031
22133
|
this._lastResult = null;
|
|
@@ -21033,12 +22135,12 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21033
22135
|
this._currentInstance = "default";
|
|
21034
22136
|
if (this._selectedPhoton.configured === false) {
|
|
21035
22137
|
this._view = "config";
|
|
21036
|
-
this.
|
|
22138
|
+
this._updateRoute();
|
|
21037
22139
|
return;
|
|
21038
22140
|
}
|
|
21039
22141
|
if (this._selectedPhoton.isExternalMCP && this._selectedPhoton.hasMcpApp) {
|
|
21040
22142
|
this._view = "mcp-app";
|
|
21041
|
-
this.
|
|
22143
|
+
this._updateRoute();
|
|
21042
22144
|
return;
|
|
21043
22145
|
}
|
|
21044
22146
|
if (this._selectedPhoton.stateful && this._selectedPhoton.configured) {
|
|
@@ -21065,13 +22167,13 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21065
22167
|
}
|
|
21066
22168
|
this._selectedMethod = this._selectedPhoton.appEntry;
|
|
21067
22169
|
this._view = "form";
|
|
21068
|
-
this.
|
|
22170
|
+
this._updateRoute();
|
|
21069
22171
|
this._maybeAutoInvoke(this._selectedPhoton.appEntry);
|
|
21070
22172
|
return;
|
|
21071
22173
|
} else {
|
|
21072
22174
|
this._view = "list";
|
|
21073
22175
|
}
|
|
21074
|
-
this.
|
|
22176
|
+
this._updateRoute();
|
|
21075
22177
|
}
|
|
21076
22178
|
/** Fetch available instances for a stateful photon from the server */
|
|
21077
22179
|
async _fetchInstances(photonName) {
|
|
@@ -21114,7 +22216,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21114
22216
|
/**
|
|
21115
22217
|
* Trigger instance switch via MCP elicitation (calls _use without name).
|
|
21116
22218
|
* The transport layer shows an elicitation modal with available instances.
|
|
21117
|
-
* After _use succeeds, the transport broadcasts
|
|
22219
|
+
* After _use succeeds, the transport broadcasts state-changed which
|
|
21118
22220
|
* triggers _silentRefresh() to update the result and notifies custom UIs.
|
|
21119
22221
|
*/
|
|
21120
22222
|
async _switchInstance() {
|
|
@@ -21150,7 +22252,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21150
22252
|
this._selectedMethod = e8.detail.method;
|
|
21151
22253
|
this._lastResult = null;
|
|
21152
22254
|
this._view = "form";
|
|
21153
|
-
this.
|
|
22255
|
+
this._updateRoute();
|
|
21154
22256
|
this._maybeAutoInvoke(e8.detail.method);
|
|
21155
22257
|
}
|
|
21156
22258
|
/**
|
|
@@ -21212,57 +22314,507 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21212
22314
|
</div>
|
|
21213
22315
|
`;
|
|
21214
22316
|
}
|
|
22317
|
+
if (this._splitPanels.length > 0) {
|
|
22318
|
+
return b2`
|
|
22319
|
+
<div style="display: flex; gap: 1px; height: 100%; overflow: hidden;">
|
|
22320
|
+
<!-- Primary Panel -->
|
|
22321
|
+
<div style="flex: 1; min-height: 0; background: var(--bg-panel);">
|
|
22322
|
+
${this._renderSinglePanel({
|
|
22323
|
+
photon: this._selectedPhoton,
|
|
22324
|
+
method: this._selectedMethod,
|
|
22325
|
+
result: this._lastResult,
|
|
22326
|
+
executing: this._isExecuting,
|
|
22327
|
+
progress: this._progress,
|
|
22328
|
+
formParams: this._lastFormParams,
|
|
22329
|
+
onSubmit: (e8) => void this._handleExecute(e8),
|
|
22330
|
+
onCancel: () => this._handleBackFromMethod(),
|
|
22331
|
+
panelLabel: "Primary",
|
|
22332
|
+
instance: this._currentInstance,
|
|
22333
|
+
instances: this._instances,
|
|
22334
|
+
onInstanceChange: (instance) => this._handleLeftPanelInstanceChange(instance),
|
|
22335
|
+
allMethods: this._selectedPhoton?.methods || [],
|
|
22336
|
+
onMethodChange: (method) => this._handleLeftPanelMethodChange(method),
|
|
22337
|
+
panelSide: "primary",
|
|
22338
|
+
onPanelAction: (action) => this._handlePrimaryPanelAction(action),
|
|
22339
|
+
onInstanceAction: (detail) => void this._handleInstanceAction(detail),
|
|
22340
|
+
isStateful: !!this._selectedPhoton?.stateful,
|
|
22341
|
+
isLive: this._currentCollectionName !== null,
|
|
22342
|
+
overflowItems: this._buildOverflowItems({
|
|
22343
|
+
showRefresh: !this._selectedPhoton?.isExternalMCP,
|
|
22344
|
+
showRename: false,
|
|
22345
|
+
showViewSource: false,
|
|
22346
|
+
showDelete: false,
|
|
22347
|
+
showHelp: !this._selectedPhoton?.isExternalMCP
|
|
22348
|
+
}),
|
|
22349
|
+
onOverflowSelect: (id2) => this._handleOverflowAction(id2)
|
|
22350
|
+
})}
|
|
22351
|
+
</div>
|
|
22352
|
+
|
|
22353
|
+
<!-- Additional Panels -->
|
|
22354
|
+
${this._splitPanels.map(
|
|
22355
|
+
(panel) => b2`
|
|
22356
|
+
<div style="flex: 1; min-height: 0; background: var(--bg-panel);">
|
|
22357
|
+
${panel.type === "method" ? this._renderSinglePanel(this._buildAdditionalPanelOpts(panel)) : this._renderSourcePanel(panel.id)}
|
|
22358
|
+
</div>
|
|
22359
|
+
`
|
|
22360
|
+
)}
|
|
22361
|
+
</div>
|
|
22362
|
+
`;
|
|
22363
|
+
}
|
|
22364
|
+
return this._renderSinglePanel({
|
|
22365
|
+
photon: this._selectedPhoton,
|
|
22366
|
+
method: this._selectedMethod,
|
|
22367
|
+
result: this._lastResult,
|
|
22368
|
+
executing: this._isExecuting,
|
|
22369
|
+
progress: this._progress,
|
|
22370
|
+
formParams: this._lastFormParams,
|
|
22371
|
+
onSubmit: (e8) => void this._handleExecute(e8),
|
|
22372
|
+
onCancel: () => this._handleBackFromMethod(),
|
|
22373
|
+
panelLabel: "Primary",
|
|
22374
|
+
instance: this._currentInstance,
|
|
22375
|
+
instances: this._instances,
|
|
22376
|
+
allMethods: this._selectedPhoton?.methods || [],
|
|
22377
|
+
onMethodChange: (method) => {
|
|
22378
|
+
this._selectedMethod = method;
|
|
22379
|
+
this._lastResult = null;
|
|
22380
|
+
this._lastFormParams = {};
|
|
22381
|
+
if (this._willAutoInvoke(method)) {
|
|
22382
|
+
void this._handleExecute(new CustomEvent("execute", { detail: { args: {} } }));
|
|
22383
|
+
}
|
|
22384
|
+
this._updateRoute();
|
|
22385
|
+
},
|
|
22386
|
+
panelSide: "primary",
|
|
22387
|
+
onPanelAction: (action) => this._handlePrimaryPanelAction(action),
|
|
22388
|
+
onInstanceAction: (detail) => void this._handleInstanceAction(detail),
|
|
22389
|
+
isStateful: !!this._selectedPhoton?.stateful,
|
|
22390
|
+
isLive: this._currentCollectionName !== null,
|
|
22391
|
+
overflowItems: this._buildOverflowItems({
|
|
22392
|
+
showRefresh: !this._selectedPhoton?.isExternalMCP,
|
|
22393
|
+
showRename: false,
|
|
22394
|
+
showViewSource: false,
|
|
22395
|
+
showDelete: false,
|
|
22396
|
+
showHelp: !this._selectedPhoton?.isExternalMCP
|
|
22397
|
+
}),
|
|
22398
|
+
onOverflowSelect: (id2) => this._handleOverflowAction(id2)
|
|
22399
|
+
});
|
|
22400
|
+
}
|
|
22401
|
+
/** Render a single panel with self-contained header */
|
|
22402
|
+
_renderSinglePanel(opts) {
|
|
22403
|
+
const isSplit = this._splitPanels.length > 0;
|
|
21215
22404
|
return b2`
|
|
21216
|
-
<div
|
|
21217
|
-
|
|
21218
|
-
${
|
|
21219
|
-
|
|
21220
|
-
|
|
21221
|
-
|
|
21222
|
-
|
|
21223
|
-
|
|
21224
|
-
|
|
21225
|
-
|
|
21226
|
-
|
|
21227
|
-
|
|
22405
|
+
<div
|
|
22406
|
+
class="glass-panel method-detail"
|
|
22407
|
+
style="${isSplit ? "border-radius: 0; height: 100%;" : ""} display: flex; flex-direction: column;"
|
|
22408
|
+
>
|
|
22409
|
+
<!-- Panel Header: LED + Method ▼ + instance-panel + [+] + [⋯] + [×] -->
|
|
22410
|
+
<div
|
|
22411
|
+
style="display: flex; align-items: center; gap: 8px; padding-bottom: 12px; margin-bottom: 12px; border-bottom: 1px solid var(--border-glass); flex-shrink: 0; position: relative;"
|
|
22412
|
+
>
|
|
22413
|
+
<!-- LED dot (stateful/live indicator) -->
|
|
22414
|
+
${opts.isStateful ? b2`<span
|
|
22415
|
+
style="width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: ${opts.isLive ? "var(--color-success, #22c55e)" : "var(--t-tertiary, #666)"}; box-shadow: ${opts.isLive ? "0 0 6px var(--color-success, #22c55e)" : "none"};"
|
|
22416
|
+
title="${opts.isLive ? "Live \u2014 stateful photon with active subscription" : "Stateful photon"}"
|
|
22417
|
+
></span>` : ""}
|
|
22418
|
+
|
|
22419
|
+
<!-- Method Selector (name as dropdown) -->
|
|
22420
|
+
<select
|
|
22421
|
+
.value=${opts.method.name}
|
|
22422
|
+
@change=${(e8) => {
|
|
22423
|
+
const methodName = e8.target.value;
|
|
22424
|
+
const method = opts.allMethods?.find((m3) => m3.name === methodName);
|
|
22425
|
+
if (method && opts.onMethodChange) {
|
|
22426
|
+
opts.onMethodChange(method);
|
|
22427
|
+
}
|
|
21228
22428
|
}}
|
|
21229
|
-
|
|
21230
|
-
|
|
22429
|
+
style="padding: 6px 8px; border-radius: 4px; border: 1px solid var(--border-glass); background: var(--bg-glass); color: var(--t-primary); font-size: 13px; font-weight: 600; flex-shrink: 0;"
|
|
22430
|
+
>
|
|
22431
|
+
${opts.allMethods?.map(
|
|
22432
|
+
(m3) => b2`<option .selected=${m3.name === opts.method.name} value=${m3.name}>
|
|
22433
|
+
${m3.name}
|
|
22434
|
+
</option>`
|
|
22435
|
+
) || b2`<option value=${opts.method.name}>${opts.method.name}</option>`}
|
|
22436
|
+
</select>
|
|
21231
22437
|
|
|
21232
|
-
|
|
21233
|
-
|
|
21234
|
-
|
|
21235
|
-
|
|
21236
|
-
|
|
21237
|
-
|
|
21238
|
-
|
|
22438
|
+
<div style="flex: 1;"></div>
|
|
22439
|
+
|
|
22440
|
+
<!-- Rich Instance Selector -->
|
|
22441
|
+
${opts.isStateful && opts.instances && opts.instances.length > 0 && opts.onInstanceAction ? b2`
|
|
22442
|
+
<instance-panel
|
|
22443
|
+
.instanceName=${opts.instance || "default"}
|
|
22444
|
+
.instances=${opts.instances}
|
|
22445
|
+
.photonName=${opts.photon.name}
|
|
22446
|
+
.selectorMode=${this._instanceSelectorMode}
|
|
22447
|
+
.autoInstance=${this._autoInstance}
|
|
22448
|
+
@instance-action=${(e8) => opts.onInstanceAction?.(e8.detail)}
|
|
22449
|
+
></instance-panel>
|
|
22450
|
+
` : ""}
|
|
22451
|
+
|
|
22452
|
+
<!-- Add panel button (primary only) -->
|
|
22453
|
+
${opts.panelSide === "primary" ? b2`
|
|
22454
|
+
<div style="position: relative; flex-shrink: 0;">
|
|
22455
|
+
<button
|
|
22456
|
+
@click=${() => opts.onPanelAction?.("toggle-picker")}
|
|
22457
|
+
style="padding: 4px 8px; background: none; color: var(--accent-secondary); border: 1px solid var(--accent-secondary); border-radius: 3px; cursor: pointer; font-size: 14px; font-weight: 700; transition: all 0.2s ease;"
|
|
22458
|
+
title="Add panel"
|
|
22459
|
+
>
|
|
22460
|
+
+
|
|
22461
|
+
</button>
|
|
22462
|
+
${this._methodPickerOpen && this._methodPickerPanelId === null ? this._renderMethodPickerPopover() : ""}
|
|
21239
22463
|
</div>
|
|
21240
|
-
|
|
21241
|
-
|
|
21242
|
-
|
|
21243
|
-
|
|
21244
|
-
|
|
21245
|
-
|
|
21246
|
-
|
|
22464
|
+
` : ""}
|
|
22465
|
+
|
|
22466
|
+
<!-- Overflow menu -->
|
|
22467
|
+
${opts.overflowItems && opts.overflowItems.length > 0 ? b2`
|
|
22468
|
+
<overflow-menu
|
|
22469
|
+
.items=${opts.overflowItems}
|
|
22470
|
+
@menu-select=${(e8) => opts.onOverflowSelect?.(e8.detail.id)}
|
|
22471
|
+
></overflow-menu>
|
|
22472
|
+
` : ""}
|
|
22473
|
+
|
|
22474
|
+
<!-- Close button (additional panels only) -->
|
|
22475
|
+
${opts.panelSide === "additional" ? b2`
|
|
22476
|
+
<button
|
|
22477
|
+
@click=${() => opts.onPanelAction?.("close")}
|
|
22478
|
+
style="padding: 4px 8px; background: none; color: var(--color-error); border: 1px solid var(--color-error); border-radius: 3px; cursor: pointer; font-size: 14px; font-weight: 700; flex-shrink: 0; transition: all 0.2s ease;"
|
|
22479
|
+
title="Close panel"
|
|
22480
|
+
>
|
|
22481
|
+
×
|
|
22482
|
+
</button>
|
|
22483
|
+
` : ""}
|
|
22484
|
+
</div>
|
|
22485
|
+
<!-- Panel Content (scrollable) -->
|
|
22486
|
+
<div
|
|
22487
|
+
style="display: flex; flex-direction: column; flex: 1; min-height: 0; overflow-y: auto;"
|
|
22488
|
+
>
|
|
22489
|
+
${this._renderDescription(opts.method.description)}
|
|
22490
|
+
<invoke-form
|
|
22491
|
+
.params=${opts.method.params}
|
|
22492
|
+
.loading=${opts.executing}
|
|
22493
|
+
.photonName=${opts.photon.name}
|
|
22494
|
+
.methodName=${opts.method.name}
|
|
22495
|
+
.rememberValues=${this._rememberFormValues}
|
|
22496
|
+
.sharedValues=${opts.formParams}
|
|
22497
|
+
@submit=${opts.onSubmit}
|
|
22498
|
+
@cancel=${opts.onCancel}
|
|
22499
|
+
></invoke-form>
|
|
22500
|
+
|
|
22501
|
+
${opts.progress ? b2`
|
|
22502
|
+
<div class="progress-container">
|
|
22503
|
+
<div class="progress-bar-wrapper">
|
|
22504
|
+
<div
|
|
22505
|
+
class="progress-bar ${opts.progress.value < 0 ? "indeterminate" : ""}"
|
|
22506
|
+
style="width: ${opts.progress.value < 0 ? "30%" : Math.round(opts.progress.value * 100) + "%"}"
|
|
22507
|
+
></div>
|
|
22508
|
+
</div>
|
|
22509
|
+
<div class="progress-text">
|
|
22510
|
+
<span>${opts.progress.message}</span>
|
|
22511
|
+
</div>
|
|
22512
|
+
</div>
|
|
22513
|
+
` : ""}
|
|
22514
|
+
${opts.result !== null ? b2`
|
|
22515
|
+
<result-viewer
|
|
22516
|
+
.result=${opts.result}
|
|
22517
|
+
.outputFormat=${opts.method?.outputFormat}
|
|
22518
|
+
.layoutHints=${opts.method?.layoutHints}
|
|
22519
|
+
.theme=${this._theme}
|
|
22520
|
+
.live=${this._currentCollectionName !== null}
|
|
22521
|
+
.resultKey=${opts.photon && opts.method ? `${opts.photon.name}/${opts.method.name}` : void 0}
|
|
22522
|
+
@share=${() => this._handleShareResult()}
|
|
22523
|
+
></result-viewer>
|
|
22524
|
+
` : b2`
|
|
22525
|
+
<div class="empty-state-inline result-empty">
|
|
22526
|
+
<span class="empty-state-icon">${play}</span>
|
|
22527
|
+
<span>Run the method to see results here</span>
|
|
21247
22528
|
</div>
|
|
22529
|
+
`}
|
|
22530
|
+
</div>
|
|
22531
|
+
</div>
|
|
22532
|
+
`;
|
|
22533
|
+
}
|
|
22534
|
+
/** Close all split panels and return to single-panel mode */
|
|
22535
|
+
_closeSecondPanel() {
|
|
22536
|
+
this._splitPanels = [];
|
|
22537
|
+
this._methodPickerOpen = false;
|
|
22538
|
+
this._methodPickerPanelId = null;
|
|
22539
|
+
this._updateRoute();
|
|
22540
|
+
}
|
|
22541
|
+
/** Handle instance change for primary panel */
|
|
22542
|
+
_handleLeftPanelInstanceChange(instance) {
|
|
22543
|
+
this._currentInstance = instance;
|
|
22544
|
+
sessionStorage.setItem(`photon-instance:${this._selectedPhoton.name}`, instance);
|
|
22545
|
+
this._lastResult = null;
|
|
22546
|
+
}
|
|
22547
|
+
/** Add a new split panel */
|
|
22548
|
+
_addPanel(type, method) {
|
|
22549
|
+
if (this._splitPanels.length >= 2) return;
|
|
22550
|
+
const panel = {
|
|
22551
|
+
id: `panel-${++this._nextPanelId}`,
|
|
22552
|
+
type,
|
|
22553
|
+
method,
|
|
22554
|
+
result: null,
|
|
22555
|
+
executing: false,
|
|
22556
|
+
progress: null,
|
|
22557
|
+
formParams: {},
|
|
22558
|
+
instance: this._currentInstance || "default"
|
|
22559
|
+
};
|
|
22560
|
+
this._splitPanels = [...this._splitPanels, panel];
|
|
22561
|
+
if (type === "method" && method && this._willAutoInvoke(method)) {
|
|
22562
|
+
void this._executePanelMethod(panel.id, {});
|
|
22563
|
+
}
|
|
22564
|
+
this._methodPickerOpen = false;
|
|
22565
|
+
this._methodPickerPanelId = null;
|
|
22566
|
+
this._cleanupPickerDismiss();
|
|
22567
|
+
this._updateRoute();
|
|
22568
|
+
}
|
|
22569
|
+
/** Remove a split panel by id */
|
|
22570
|
+
_removePanel(panelId) {
|
|
22571
|
+
this._splitPanels = this._splitPanels.filter((p5) => p5.id !== panelId);
|
|
22572
|
+
this._updateRoute();
|
|
22573
|
+
}
|
|
22574
|
+
/** Update a split panel's state */
|
|
22575
|
+
_updatePanel(panelId, updates) {
|
|
22576
|
+
this._splitPanels = this._splitPanels.map((p5) => p5.id === panelId ? { ...p5, ...updates } : p5);
|
|
22577
|
+
}
|
|
22578
|
+
/** Execute a method in a split panel */
|
|
22579
|
+
async _executePanelMethod(panelId, args) {
|
|
22580
|
+
const panel = this._splitPanels.find((p5) => p5.id === panelId);
|
|
22581
|
+
if (!panel || panel.type !== "method" || !panel.method) return;
|
|
22582
|
+
this._updatePanel(panelId, { executing: true, result: null, progress: null, formParams: args });
|
|
22583
|
+
try {
|
|
22584
|
+
const toolName = `${this._selectedPhoton.name}/${panel.method.name}`;
|
|
22585
|
+
const result = await mcpClient.callTool(
|
|
22586
|
+
toolName,
|
|
22587
|
+
args,
|
|
22588
|
+
void 0,
|
|
22589
|
+
panel.instance || this._currentInstance,
|
|
22590
|
+
(progress) => {
|
|
22591
|
+
this._updatePanel(panelId, { progress });
|
|
22592
|
+
}
|
|
22593
|
+
);
|
|
22594
|
+
this._updatePanel(panelId, {
|
|
22595
|
+
result: mcpClient.parseToolResult(result),
|
|
22596
|
+
executing: false,
|
|
22597
|
+
progress: null
|
|
22598
|
+
});
|
|
22599
|
+
} catch (error2) {
|
|
22600
|
+
showToast(`Error: ${error2.message}`, { type: "error" });
|
|
22601
|
+
this._updatePanel(panelId, {
|
|
22602
|
+
result: { error: error2.message },
|
|
22603
|
+
executing: false,
|
|
22604
|
+
progress: null
|
|
22605
|
+
});
|
|
22606
|
+
}
|
|
22607
|
+
}
|
|
22608
|
+
/** Change the method in a split panel */
|
|
22609
|
+
_changePanelMethod(panelId, method) {
|
|
22610
|
+
this._updatePanel(panelId, { method, result: null, formParams: {} });
|
|
22611
|
+
if (this._willAutoInvoke(method)) {
|
|
22612
|
+
void this._executePanelMethod(panelId, {});
|
|
22613
|
+
}
|
|
22614
|
+
this._updateRoute();
|
|
22615
|
+
}
|
|
22616
|
+
/** Change the instance in a split panel */
|
|
22617
|
+
_changePanelInstance(panelId, instance) {
|
|
22618
|
+
this._updatePanel(panelId, { instance, result: null });
|
|
22619
|
+
}
|
|
22620
|
+
/** Open a method in a new split panel (backwards-compatible entry point) */
|
|
22621
|
+
_openInSecondPanel(photon, method) {
|
|
22622
|
+
this._addPanel("method", method);
|
|
22623
|
+
}
|
|
22624
|
+
/** Show method picker popover */
|
|
22625
|
+
_showMethodPicker() {
|
|
22626
|
+
this._methodPickerOpen = !this._methodPickerOpen;
|
|
22627
|
+
this._methodPickerPanelId = null;
|
|
22628
|
+
}
|
|
22629
|
+
/** Clean up picker dismiss listener */
|
|
22630
|
+
_cleanupPickerDismiss() {
|
|
22631
|
+
if (this._pickerDismissHandler) {
|
|
22632
|
+
window.removeEventListener("mousedown", this._pickerDismissHandler, true);
|
|
22633
|
+
this._pickerDismissHandler = null;
|
|
22634
|
+
}
|
|
22635
|
+
}
|
|
22636
|
+
/** Handle method change in primary panel */
|
|
22637
|
+
_handleLeftPanelMethodChange(method) {
|
|
22638
|
+
this._selectedMethod = method;
|
|
22639
|
+
this._lastResult = null;
|
|
22640
|
+
this._lastFormParams = {};
|
|
22641
|
+
this._updateRoute();
|
|
22642
|
+
}
|
|
22643
|
+
/** Handle panel action for primary panel */
|
|
22644
|
+
_handlePrimaryPanelAction(action) {
|
|
22645
|
+
if (action === "toggle-picker") {
|
|
22646
|
+
this._methodPickerOpen = !this._methodPickerOpen;
|
|
22647
|
+
this._methodPickerPanelId = null;
|
|
22648
|
+
}
|
|
22649
|
+
}
|
|
22650
|
+
/** Build opts for an additional (non-primary) split panel */
|
|
22651
|
+
_buildAdditionalPanelOpts(panel) {
|
|
22652
|
+
return {
|
|
22653
|
+
photon: this._selectedPhoton,
|
|
22654
|
+
method: panel.method,
|
|
22655
|
+
result: panel.result,
|
|
22656
|
+
executing: panel.executing || false,
|
|
22657
|
+
progress: panel.progress,
|
|
22658
|
+
formParams: panel.formParams || {},
|
|
22659
|
+
onSubmit: (e8) => {
|
|
22660
|
+
const args = e8.detail?.args || {};
|
|
22661
|
+
void this._executePanelMethod(panel.id, args);
|
|
22662
|
+
},
|
|
22663
|
+
onCancel: () => this._removePanel(panel.id),
|
|
22664
|
+
panelLabel: panel.id,
|
|
22665
|
+
instance: panel.instance,
|
|
22666
|
+
instances: this._instances,
|
|
22667
|
+
onInstanceChange: (inst) => this._changePanelInstance(panel.id, inst),
|
|
22668
|
+
allMethods: this._selectedPhoton?.methods || [],
|
|
22669
|
+
onMethodChange: (m3) => this._changePanelMethod(panel.id, m3),
|
|
22670
|
+
panelSide: "additional",
|
|
22671
|
+
onPanelAction: (action) => {
|
|
22672
|
+
if (action === "close") this._removePanel(panel.id);
|
|
22673
|
+
},
|
|
22674
|
+
onInstanceAction: (detail) => {
|
|
22675
|
+
if (detail.action === "switch") {
|
|
22676
|
+
this._changePanelInstance(panel.id, detail.instance);
|
|
22677
|
+
}
|
|
22678
|
+
},
|
|
22679
|
+
isStateful: !!this._selectedPhoton?.stateful,
|
|
22680
|
+
isLive: this._currentCollectionName !== null,
|
|
22681
|
+
overflowItems: this._buildOverflowItems({
|
|
22682
|
+
showRefresh: false,
|
|
22683
|
+
showRename: false,
|
|
22684
|
+
showViewSource: false,
|
|
22685
|
+
showDelete: false,
|
|
22686
|
+
showHelp: false,
|
|
22687
|
+
showRunTests: false
|
|
22688
|
+
}),
|
|
22689
|
+
onOverflowSelect: (id2) => this._handleOverflowAction(id2)
|
|
22690
|
+
};
|
|
22691
|
+
}
|
|
22692
|
+
/** Handle overflow menu actions from panel headers */
|
|
22693
|
+
_handleOverflowAction(id2) {
|
|
22694
|
+
switch (id2) {
|
|
22695
|
+
case "refresh":
|
|
22696
|
+
if (this._selectedMethod && this._willAutoInvoke(this._selectedMethod)) {
|
|
22697
|
+
void this._handleExecute(new CustomEvent("execute", { detail: { args: {} } }));
|
|
22698
|
+
}
|
|
22699
|
+
break;
|
|
22700
|
+
case "remember-values":
|
|
22701
|
+
this._rememberFormValues = !this._rememberFormValues;
|
|
22702
|
+
break;
|
|
22703
|
+
case "verbose-logging":
|
|
22704
|
+
this._verboseLogging = !this._verboseLogging;
|
|
22705
|
+
break;
|
|
22706
|
+
case "run-tests":
|
|
22707
|
+
void this._runTests();
|
|
22708
|
+
break;
|
|
22709
|
+
case "help":
|
|
22710
|
+
this._showPhotonHelp = true;
|
|
22711
|
+
break;
|
|
22712
|
+
default:
|
|
22713
|
+
this._handleContextAction(new CustomEvent("context-action", { detail: { action: id2 } }));
|
|
22714
|
+
break;
|
|
22715
|
+
}
|
|
22716
|
+
}
|
|
22717
|
+
/** Render source panel for split view */
|
|
22718
|
+
_renderSourcePanel(panelId) {
|
|
22719
|
+
return b2`
|
|
22720
|
+
<div style="height: 100%; overflow: hidden;">
|
|
22721
|
+
<photon-studio
|
|
22722
|
+
.photonName=${this._selectedPhoton?.name}
|
|
22723
|
+
.theme=${this._theme}
|
|
22724
|
+
@studio-saved=${() => this._handleStudioSaved?.()}
|
|
22725
|
+
@studio-close=${() => this._removePanel(panelId)}
|
|
22726
|
+
></photon-studio>
|
|
22727
|
+
</div>
|
|
22728
|
+
`;
|
|
22729
|
+
}
|
|
22730
|
+
/** Render the method picker popover for adding new panels */
|
|
22731
|
+
_renderMethodPickerPopover() {
|
|
22732
|
+
const methods = this._getVisibleMethods();
|
|
22733
|
+
const openMethodNames = /* @__PURE__ */ new Set();
|
|
22734
|
+
if (this._selectedMethod) openMethodNames.add(this._selectedMethod.name);
|
|
22735
|
+
for (const p5 of this._splitPanels) {
|
|
22736
|
+
if (p5.type === "method" && p5.method) openMethodNames.add(p5.method.name);
|
|
22737
|
+
}
|
|
22738
|
+
const availableMethods = methods.filter((m3) => !openMethodNames.has(m3.name));
|
|
22739
|
+
const hasSourcePanel = this._splitPanels.some((p5) => p5.type === "source");
|
|
22740
|
+
const canAddMore = this._splitPanels.length < 2;
|
|
22741
|
+
if (!canAddMore) return "";
|
|
22742
|
+
if (!this._pickerDismissHandler) {
|
|
22743
|
+
const handler = (e8) => {
|
|
22744
|
+
const path = e8.composedPath();
|
|
22745
|
+
const popover = this.renderRoot.querySelector(".method-picker-popover");
|
|
22746
|
+
if (popover && path.includes(popover)) return;
|
|
22747
|
+
this._methodPickerOpen = false;
|
|
22748
|
+
this._pickerDismissHandler = null;
|
|
22749
|
+
window.removeEventListener("mousedown", handler, true);
|
|
22750
|
+
};
|
|
22751
|
+
this._pickerDismissHandler = handler;
|
|
22752
|
+
setTimeout(() => window.addEventListener("mousedown", handler, true), 0);
|
|
22753
|
+
}
|
|
22754
|
+
return b2`
|
|
22755
|
+
<div
|
|
22756
|
+
class="method-picker-popover"
|
|
22757
|
+
@click=${(e8) => e8.stopPropagation()}
|
|
22758
|
+
style="position: absolute; top: 100%; right: 0; z-index: 9999; min-width: 200px; max-height: 360px; overflow-y: auto; background: var(--bg-glass); border: 1px solid var(--border-glass); border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.3); backdrop-filter: blur(20px); margin-top: 4px;"
|
|
22759
|
+
>
|
|
22760
|
+
<!-- Header -->
|
|
22761
|
+
<div style="padding: 10px 12px 8px; border-bottom: 1px solid var(--border-glass);">
|
|
22762
|
+
<div
|
|
22763
|
+
style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--t-tertiary);"
|
|
22764
|
+
>
|
|
22765
|
+
Split Pane
|
|
22766
|
+
</div>
|
|
22767
|
+
</div>
|
|
22768
|
+
|
|
22769
|
+
<!-- Methods section -->
|
|
22770
|
+
${availableMethods.length > 0 ? b2`
|
|
22771
|
+
<div style="padding: 4px 0;">
|
|
22772
|
+
<div
|
|
22773
|
+
style="padding: 4px 12px 2px; font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: var(--t-tertiary);"
|
|
22774
|
+
>
|
|
22775
|
+
Methods
|
|
22776
|
+
</div>
|
|
22777
|
+
${availableMethods.map(
|
|
22778
|
+
(m3) => b2`
|
|
22779
|
+
<div
|
|
22780
|
+
@click=${() => this._addPanel("method", m3)}
|
|
22781
|
+
style="padding: 6px 12px 6px 16px; cursor: pointer; font-size: 12px; color: var(--t-primary); transition: background 0.15s ease; display: flex; align-items: center; gap: 6px;"
|
|
22782
|
+
@mouseenter=${(e8) => e8.target.style.background = "var(--bg-hover)"}
|
|
22783
|
+
@mouseleave=${(e8) => e8.target.style.background = "transparent"}
|
|
22784
|
+
>
|
|
22785
|
+
<span style="color: var(--t-tertiary); font-size: 10px;">▸</span>
|
|
22786
|
+
${m3.name}
|
|
22787
|
+
</div>
|
|
22788
|
+
`
|
|
22789
|
+
)}
|
|
21248
22790
|
</div>
|
|
21249
|
-
` : ""}
|
|
21250
|
-
${this._lastResult !== null ? b2`
|
|
21251
|
-
<result-viewer
|
|
21252
|
-
.result=${this._lastResult}
|
|
21253
|
-
.outputFormat=${this._selectedMethod?.outputFormat}
|
|
21254
|
-
.layoutHints=${this._selectedMethod?.layoutHints}
|
|
21255
|
-
.theme=${this._theme}
|
|
21256
|
-
.live=${this._currentCollectionName !== null}
|
|
21257
|
-
.resultKey=${this._selectedPhoton && this._selectedMethod ? `${this._selectedPhoton.name}/${this._selectedMethod.name}` : void 0}
|
|
21258
|
-
@share=${() => this._handleShareResult()}
|
|
21259
|
-
></result-viewer>
|
|
21260
22791
|
` : b2`
|
|
21261
|
-
<div
|
|
21262
|
-
|
|
21263
|
-
|
|
22792
|
+
<div
|
|
22793
|
+
style="padding: 8px 12px; font-size: 11px; color: var(--t-tertiary); font-style: italic;"
|
|
22794
|
+
>
|
|
22795
|
+
All methods already open
|
|
21264
22796
|
</div>
|
|
21265
22797
|
`}
|
|
22798
|
+
|
|
22799
|
+
<!-- Tools section -->
|
|
22800
|
+
${!hasSourcePanel ? b2`
|
|
22801
|
+
<div style="border-top: 1px solid var(--border-glass); padding: 4px 0;">
|
|
22802
|
+
<div
|
|
22803
|
+
style="padding: 4px 12px 2px; font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: var(--t-tertiary);"
|
|
22804
|
+
>
|
|
22805
|
+
Tools
|
|
22806
|
+
</div>
|
|
22807
|
+
<div
|
|
22808
|
+
@click=${() => this._addPanel("source")}
|
|
22809
|
+
style="padding: 6px 12px 6px 16px; cursor: pointer; font-size: 12px; color: var(--t-primary); transition: background 0.15s ease; display: flex; align-items: center; gap: 6px;"
|
|
22810
|
+
@mouseenter=${(e8) => e8.target.style.background = "var(--bg-hover)"}
|
|
22811
|
+
@mouseleave=${(e8) => e8.target.style.background = "transparent"}
|
|
22812
|
+
>
|
|
22813
|
+
<span style="font-size: 11px; color: var(--accent-primary);"></></span>
|
|
22814
|
+
Source Editor
|
|
22815
|
+
</div>
|
|
22816
|
+
</div>
|
|
22817
|
+
` : ""}
|
|
21266
22818
|
</div>
|
|
21267
22819
|
`;
|
|
21268
22820
|
}
|
|
@@ -21291,10 +22843,11 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21291
22843
|
if (form?.isDirty && !confirm("You have unsaved changes. Discard them?")) {
|
|
21292
22844
|
return;
|
|
21293
22845
|
}
|
|
22846
|
+
this._closeSecondPanel();
|
|
21294
22847
|
if (this._selectedPhoton.isApp && this._selectedPhoton.appEntry) {
|
|
21295
22848
|
this._selectedMethod = this._selectedPhoton.appEntry;
|
|
21296
22849
|
this._view = "form";
|
|
21297
|
-
this.
|
|
22850
|
+
this._updateRoute(true);
|
|
21298
22851
|
void this.updateComplete.then(() => {
|
|
21299
22852
|
setTimeout(() => {
|
|
21300
22853
|
const mainArea = this.shadowRoot?.querySelector(".main-area");
|
|
@@ -21308,11 +22861,11 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21308
22861
|
this._selectedPhoton = null;
|
|
21309
22862
|
this._welcomePhase = "welcome";
|
|
21310
22863
|
this._view = "list";
|
|
21311
|
-
this.
|
|
22864
|
+
this._updateRoute(true);
|
|
21312
22865
|
} else {
|
|
21313
22866
|
this._view = "list";
|
|
21314
22867
|
this._selectedMethod = null;
|
|
21315
|
-
this.
|
|
22868
|
+
this._updateRoute(true);
|
|
21316
22869
|
}
|
|
21317
22870
|
}
|
|
21318
22871
|
async _openForkDialog() {
|
|
@@ -21383,10 +22936,21 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21383
22936
|
if (errorText !== "Elicitation cancelled by user") {
|
|
21384
22937
|
this._log("error", errorText);
|
|
21385
22938
|
showToast(errorText, "error", 5e3);
|
|
22939
|
+
this._lastResult = { _error: true, message: errorText };
|
|
21386
22940
|
}
|
|
21387
22941
|
} else {
|
|
21388
22942
|
this._lastResult = mcpClient.parseToolResult(result);
|
|
22943
|
+
if (this._selectedPhoton?.stateful && Array.isArray(this._lastResult) && this._selectedMethod) {
|
|
22944
|
+
this._lastResult = this._autoWrapPaginationIfNeeded(
|
|
22945
|
+
this._lastResult,
|
|
22946
|
+
this._selectedPhoton.name,
|
|
22947
|
+
this._selectedMethod
|
|
22948
|
+
);
|
|
22949
|
+
}
|
|
21389
22950
|
this._log("success", "Execution completed", false, execDuration);
|
|
22951
|
+
if (this._selectedPhoton?.stateful && this._lastResult != null && typeof this._lastResult === "object") {
|
|
22952
|
+
this._initializeGlobalInstance(this._selectedPhoton.name, this._lastResult);
|
|
22953
|
+
}
|
|
21390
22954
|
void this.updateComplete.then(() => {
|
|
21391
22955
|
const rv2 = this.shadowRoot?.querySelector("result-viewer");
|
|
21392
22956
|
if (rv2 && window.innerWidth <= 768) {
|
|
@@ -21421,6 +22985,16 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21421
22985
|
const result = await mcpClient.callTool(toolName, this._lastFormParams || {});
|
|
21422
22986
|
if (!result.isError) {
|
|
21423
22987
|
this._lastResult = mcpClient.parseToolResult(result);
|
|
22988
|
+
if (this._selectedPhoton.stateful && Array.isArray(this._lastResult) && this._selectedMethod) {
|
|
22989
|
+
this._lastResult = this._autoWrapPaginationIfNeeded(
|
|
22990
|
+
this._lastResult,
|
|
22991
|
+
this._selectedPhoton.name,
|
|
22992
|
+
this._selectedMethod
|
|
22993
|
+
);
|
|
22994
|
+
}
|
|
22995
|
+
if (this._selectedPhoton.stateful && this._lastResult != null && typeof this._lastResult === "object") {
|
|
22996
|
+
this._initializeGlobalInstance(this._selectedPhoton.name, this._lastResult);
|
|
22997
|
+
}
|
|
21424
22998
|
}
|
|
21425
22999
|
} catch {
|
|
21426
23000
|
} finally {
|
|
@@ -21471,6 +23045,162 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21471
23045
|
this._collectionUnsubscribes = [];
|
|
21472
23046
|
this._currentCollectionName = null;
|
|
21473
23047
|
}
|
|
23048
|
+
/**
|
|
23049
|
+
* Initialize global photon instance for @stateful photons
|
|
23050
|
+
* Makes the photon instance available as window.{photonName}
|
|
23051
|
+
* and keeps it in sync with server state via state-changed patches
|
|
23052
|
+
* Wraps paginated array properties with ViewportAwareProxy for smart fetching
|
|
23053
|
+
*/
|
|
23054
|
+
/**
|
|
23055
|
+
* Auto-wrap array results with pagination metadata for @stateful photons
|
|
23056
|
+
* If method has (start, limit) parameters, detect them and use global instance
|
|
23057
|
+
* to calculate pagination metadata from the full array
|
|
23058
|
+
*/
|
|
23059
|
+
_autoWrapPaginationIfNeeded(items, photonName, method) {
|
|
23060
|
+
const hasStartLimitParams = method.parameters?.some(
|
|
23061
|
+
(p5) => (p5.name === "start" || p5.name === "limit") && p5.required !== true
|
|
23062
|
+
);
|
|
23063
|
+
if (!hasStartLimitParams || items.length === 0) {
|
|
23064
|
+
return items;
|
|
23065
|
+
}
|
|
23066
|
+
try {
|
|
23067
|
+
const manager = getGlobalInstanceManager();
|
|
23068
|
+
const instance = manager.getInstance(photonName);
|
|
23069
|
+
if (!instance) {
|
|
23070
|
+
return items;
|
|
23071
|
+
}
|
|
23072
|
+
const arrayProp = Object.keys(instance).find((key) => {
|
|
23073
|
+
const value = instance[key];
|
|
23074
|
+
return Array.isArray(value) && value.length > 0;
|
|
23075
|
+
});
|
|
23076
|
+
if (!arrayProp) {
|
|
23077
|
+
return items;
|
|
23078
|
+
}
|
|
23079
|
+
const fullArray = instance[arrayProp];
|
|
23080
|
+
const totalCount = fullArray.length;
|
|
23081
|
+
const start = 0;
|
|
23082
|
+
const end = items.length;
|
|
23083
|
+
return {
|
|
23084
|
+
items,
|
|
23085
|
+
_pagination: {
|
|
23086
|
+
totalCount,
|
|
23087
|
+
start,
|
|
23088
|
+
end,
|
|
23089
|
+
hasMore: end < totalCount
|
|
23090
|
+
}
|
|
23091
|
+
};
|
|
23092
|
+
} catch (error2) {
|
|
23093
|
+
if (this._verboseLogging) {
|
|
23094
|
+
const msg = error2 instanceof Error ? error2.message : "Unknown error";
|
|
23095
|
+
this._log("warn", `Could not auto-wrap pagination: ${msg}`);
|
|
23096
|
+
}
|
|
23097
|
+
return items;
|
|
23098
|
+
}
|
|
23099
|
+
}
|
|
23100
|
+
_initializeGlobalInstance(photonName, initialState) {
|
|
23101
|
+
try {
|
|
23102
|
+
const paginatedProps = this._detectPaginatedProperties(initialState);
|
|
23103
|
+
const instance = initializeGlobalPhotonSession(photonName, initialState);
|
|
23104
|
+
for (const [propName, paginationMeta] of Object.entries(paginatedProps)) {
|
|
23105
|
+
this._wrapWithViewportProxy(instance, propName, paginationMeta);
|
|
23106
|
+
}
|
|
23107
|
+
if (this._verboseLogging) {
|
|
23108
|
+
const message = paginatedProps.size > 0 ? `\u{1F4E1} Global instance initialized with ${paginatedProps.size} paginated array(s): window.${photonName.toLowerCase()}` : `\u{1F4E1} Global instance initialized: window.${photonName.toLowerCase()}`;
|
|
23109
|
+
this._log("info", message);
|
|
23110
|
+
}
|
|
23111
|
+
} catch (error2) {
|
|
23112
|
+
console.error("Failed to initialize global photon instance", error2);
|
|
23113
|
+
}
|
|
23114
|
+
}
|
|
23115
|
+
/**
|
|
23116
|
+
* Detect which properties have pagination metadata
|
|
23117
|
+
*/
|
|
23118
|
+
_detectPaginatedProperties(initialState) {
|
|
23119
|
+
const paginated = /* @__PURE__ */ new Map();
|
|
23120
|
+
if (!initialState || typeof initialState !== "object") {
|
|
23121
|
+
return paginated;
|
|
23122
|
+
}
|
|
23123
|
+
for (const [key, value] of Object.entries(initialState)) {
|
|
23124
|
+
if (value && typeof value === "object" && value._pagination) {
|
|
23125
|
+
paginated.set(key, value._pagination);
|
|
23126
|
+
}
|
|
23127
|
+
}
|
|
23128
|
+
return paginated;
|
|
23129
|
+
}
|
|
23130
|
+
/**
|
|
23131
|
+
* Wrap a property with ViewportAwareProxy for smart pagination
|
|
23132
|
+
*/
|
|
23133
|
+
_wrapWithViewportProxy(instance, propertyName2, paginationMeta) {
|
|
23134
|
+
try {
|
|
23135
|
+
const pageSize = getPageSizeForClient();
|
|
23136
|
+
const proxy = new ViewportAwareProxy(
|
|
23137
|
+
this._selectedPhoton?.name || "unknown",
|
|
23138
|
+
this._selectedMethod?.name || propertyName2,
|
|
23139
|
+
mcpClient,
|
|
23140
|
+
{
|
|
23141
|
+
pageSize,
|
|
23142
|
+
bufferSize: 5,
|
|
23143
|
+
// Items to buffer above/below viewport
|
|
23144
|
+
maxCacheSize: 500
|
|
23145
|
+
// Max items to keep in cache
|
|
23146
|
+
}
|
|
23147
|
+
);
|
|
23148
|
+
proxy.initializeWithResponse({
|
|
23149
|
+
items: instance[propertyName2] || [],
|
|
23150
|
+
_pagination: paginationMeta
|
|
23151
|
+
});
|
|
23152
|
+
instance.makeProperty(propertyName2);
|
|
23153
|
+
Object.defineProperty(instance, propertyName2, {
|
|
23154
|
+
configurable: true,
|
|
23155
|
+
enumerable: true,
|
|
23156
|
+
get: () => proxy.items,
|
|
23157
|
+
set: (value) => {
|
|
23158
|
+
proxy.clearCache();
|
|
23159
|
+
proxy.initializeWithResponse({
|
|
23160
|
+
items: value || [],
|
|
23161
|
+
_pagination: paginationMeta
|
|
23162
|
+
});
|
|
23163
|
+
}
|
|
23164
|
+
});
|
|
23165
|
+
const patchHandler = (data) => {
|
|
23166
|
+
if (data?.patches) {
|
|
23167
|
+
proxy.applyPatches(data.patches);
|
|
23168
|
+
}
|
|
23169
|
+
};
|
|
23170
|
+
instance.on("state-changed", patchHandler);
|
|
23171
|
+
queueMicrotask(() => {
|
|
23172
|
+
try {
|
|
23173
|
+
const resultViewer = this._resultViewer;
|
|
23174
|
+
if (resultViewer?.shadowRoot) {
|
|
23175
|
+
const scrollContainer = resultViewer.shadowRoot.querySelector(
|
|
23176
|
+
".result-content"
|
|
23177
|
+
);
|
|
23178
|
+
if (scrollContainer) {
|
|
23179
|
+
const manager = new ViewportManager(proxy, {
|
|
23180
|
+
container: scrollContainer,
|
|
23181
|
+
itemSelector: "[data-index]",
|
|
23182
|
+
pageSize,
|
|
23183
|
+
bufferSize: 5
|
|
23184
|
+
});
|
|
23185
|
+
manager.start();
|
|
23186
|
+
}
|
|
23187
|
+
}
|
|
23188
|
+
} catch (error2) {
|
|
23189
|
+
if (this._verboseLogging) {
|
|
23190
|
+
this._log("warn", `Could not set up automatic viewport tracking for ${propertyName2}`);
|
|
23191
|
+
}
|
|
23192
|
+
}
|
|
23193
|
+
});
|
|
23194
|
+
if (this._verboseLogging) {
|
|
23195
|
+
this._log(
|
|
23196
|
+
"info",
|
|
23197
|
+
`\u2728 Paginated proxy enabled for ${propertyName2} (page size: ${pageSize})`
|
|
23198
|
+
);
|
|
23199
|
+
}
|
|
23200
|
+
} catch (error2) {
|
|
23201
|
+
console.error(`Failed to wrap ${propertyName2} with ViewportAwareProxy`, error2);
|
|
23202
|
+
}
|
|
23203
|
+
}
|
|
21474
23204
|
async _handleConfigure(e8) {
|
|
21475
23205
|
const { photon, config: config3 } = e8.detail;
|
|
21476
23206
|
this._log("info", `Configuring ${photon}...`);
|
|
@@ -21505,8 +23235,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21505
23235
|
showToast("No method selected to share", "error");
|
|
21506
23236
|
return;
|
|
21507
23237
|
}
|
|
21508
|
-
const
|
|
21509
|
-
const hash2 = `${this._selectedPhoton.name}/${this._selectedMethod.name}`;
|
|
23238
|
+
const pathSegment2 = `${this._selectedPhoton.name}/${this._selectedMethod.name}`;
|
|
21510
23239
|
const params = new URLSearchParams();
|
|
21511
23240
|
for (const [key, value] of Object.entries(this._lastFormParams)) {
|
|
21512
23241
|
if (value !== void 0 && value !== null && value !== "") {
|
|
@@ -21517,7 +23246,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21517
23246
|
}
|
|
21518
23247
|
}
|
|
21519
23248
|
}
|
|
21520
|
-
let shareUrl = `${
|
|
23249
|
+
let shareUrl = `${window.location.origin}/${pathSegment2}`;
|
|
21521
23250
|
if (params.toString()) {
|
|
21522
23251
|
shareUrl += `?${params.toString()}`;
|
|
21523
23252
|
}
|
|
@@ -21643,9 +23372,8 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21643
23372
|
}
|
|
21644
23373
|
if (!photon.internal) {
|
|
21645
23374
|
const paramHints = (method.params || []).filter((p5) => p5.required).map((p5) => `--${p5.name} <${p5.type || "value"}>`).join(" ");
|
|
21646
|
-
|
|
21647
|
-
|
|
21648
|
-
);
|
|
23375
|
+
const cliPfx = window.__PHOTON_SHELL_INIT ? name2 : `photon cli ${name2}`;
|
|
23376
|
+
lines.push(`CLI: \`${cliPfx} ${method.name}${paramHints ? " " + paramHints : ""}\``);
|
|
21649
23377
|
lines.push("");
|
|
21650
23378
|
}
|
|
21651
23379
|
if (method.returnType) {
|
|
@@ -21751,7 +23479,8 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21751
23479
|
showHelp = true,
|
|
21752
23480
|
showRunTests = this._getTestMethods().length > 0,
|
|
21753
23481
|
showRemove = false,
|
|
21754
|
-
showFullscreen = false
|
|
23482
|
+
showFullscreen = false,
|
|
23483
|
+
showInstallApp = !this._pwaIsStandalone && !!this._selectedPhoton?.isApp
|
|
21755
23484
|
} = opts;
|
|
21756
23485
|
const items = [];
|
|
21757
23486
|
if (showFullscreen) {
|
|
@@ -21797,6 +23526,13 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21797
23526
|
toggle: true,
|
|
21798
23527
|
toggleActive: this._verboseLogging
|
|
21799
23528
|
});
|
|
23529
|
+
if (showInstallApp) {
|
|
23530
|
+
items.push({
|
|
23531
|
+
id: "install-app",
|
|
23532
|
+
label: "Install as App",
|
|
23533
|
+
iconSvg: iconSvgString(iconPaths.installApp)
|
|
23534
|
+
});
|
|
23535
|
+
}
|
|
21800
23536
|
if (showRename || showViewSource || showFork || showContribute || showDelete || showRemove) {
|
|
21801
23537
|
const first = [
|
|
21802
23538
|
showRename,
|
|
@@ -22722,6 +24458,10 @@ BeamApp.styles = [
|
|
|
22722
24458
|
display: none;
|
|
22723
24459
|
}
|
|
22724
24460
|
|
|
24461
|
+
:host(.focus-mode) .main-area {
|
|
24462
|
+
padding: var(--space-sm);
|
|
24463
|
+
}
|
|
24464
|
+
|
|
22725
24465
|
.main-area {
|
|
22726
24466
|
flex: 1;
|
|
22727
24467
|
position: relative;
|
|
@@ -22730,10 +24470,10 @@ BeamApp.styles = [
|
|
|
22730
24470
|
padding: var(--space-lg);
|
|
22731
24471
|
}
|
|
22732
24472
|
|
|
24473
|
+
.beam-back-btn,
|
|
22733
24474
|
.beam-fullscreen-btn {
|
|
22734
24475
|
position: sticky;
|
|
22735
24476
|
top: calc(-1 * var(--space-lg));
|
|
22736
|
-
float: right;
|
|
22737
24477
|
z-index: 100;
|
|
22738
24478
|
width: 28px;
|
|
22739
24479
|
height: 28px;
|
|
@@ -22747,6 +24487,18 @@ BeamApp.styles = [
|
|
|
22747
24487
|
align-items: center;
|
|
22748
24488
|
justify-content: center;
|
|
22749
24489
|
transition: all 0.2s ease;
|
|
24490
|
+
backdrop-filter: blur(8px);
|
|
24491
|
+
}
|
|
24492
|
+
|
|
24493
|
+
.beam-back-btn {
|
|
24494
|
+
float: left;
|
|
24495
|
+
margin-top: calc(-1 * var(--space-lg));
|
|
24496
|
+
margin-left: calc(-1 * var(--space-lg) + 1px);
|
|
24497
|
+
margin-bottom: calc(-28px + var(--space-lg));
|
|
24498
|
+
}
|
|
24499
|
+
|
|
24500
|
+
.beam-fullscreen-btn {
|
|
24501
|
+
float: right;
|
|
22750
24502
|
margin-top: calc(-1 * var(--space-lg));
|
|
22751
24503
|
margin-right: calc(-1 * var(--space-lg) + 1px);
|
|
22752
24504
|
margin-bottom: calc(-28px + var(--space-lg));
|
|
@@ -23777,7 +25529,7 @@ BeamApp.styles = [
|
|
|
23777
25529
|
min-width: 120px;
|
|
23778
25530
|
font-family: var(--font-mono);
|
|
23779
25531
|
font-size: var(--text-md);
|
|
23780
|
-
color:
|
|
25532
|
+
color: var(--color-warning);
|
|
23781
25533
|
}
|
|
23782
25534
|
|
|
23783
25535
|
.variable-input input {
|
|
@@ -23966,7 +25718,7 @@ BeamApp.styles = [
|
|
|
23966
25718
|
|
|
23967
25719
|
.progress-bar-wrapper {
|
|
23968
25720
|
height: 8px;
|
|
23969
|
-
background:
|
|
25721
|
+
background: var(--bg-glass);
|
|
23970
25722
|
border-radius: var(--radius-xs);
|
|
23971
25723
|
overflow: hidden;
|
|
23972
25724
|
}
|
|
@@ -24084,6 +25836,25 @@ BeamApp.styles = [
|
|
|
24084
25836
|
padding-top: calc(var(--space-md) + 60px); /* Space for mobile menu button */
|
|
24085
25837
|
}
|
|
24086
25838
|
|
|
25839
|
+
.beam-back-btn,
|
|
25840
|
+
.beam-fullscreen-btn {
|
|
25841
|
+
position: fixed;
|
|
25842
|
+
top: var(--space-md);
|
|
25843
|
+
float: none;
|
|
25844
|
+
margin: 0;
|
|
25845
|
+
width: 44px;
|
|
25846
|
+
height: 44px;
|
|
25847
|
+
box-shadow: var(--shadow-md);
|
|
25848
|
+
}
|
|
25849
|
+
|
|
25850
|
+
.beam-back-btn {
|
|
25851
|
+
left: calc(var(--space-md) + 44px + var(--space-sm));
|
|
25852
|
+
}
|
|
25853
|
+
|
|
25854
|
+
.beam-fullscreen-btn {
|
|
25855
|
+
right: var(--space-md);
|
|
25856
|
+
}
|
|
25857
|
+
|
|
24087
25858
|
.photon-header {
|
|
24088
25859
|
flex-direction: column;
|
|
24089
25860
|
align-items: flex-start;
|
|
@@ -24098,10 +25869,9 @@ BeamApp.styles = [
|
|
|
24098
25869
|
grid-template-columns: 1fr;
|
|
24099
25870
|
}
|
|
24100
25871
|
|
|
24101
|
-
/* Touch-friendly targets - min 44px */
|
|
25872
|
+
/* Touch-friendly targets - min 44px (exclude small inline buttons) */
|
|
24102
25873
|
.asset-card,
|
|
24103
25874
|
.method-card,
|
|
24104
|
-
button,
|
|
24105
25875
|
.filter-btn {
|
|
24106
25876
|
min-height: 44px;
|
|
24107
25877
|
}
|
|
@@ -24382,6 +26152,15 @@ __decorateClass([
|
|
|
24382
26152
|
__decorateClass([
|
|
24383
26153
|
r5()
|
|
24384
26154
|
], BeamApp.prototype, "_resourceContent", 2);
|
|
26155
|
+
__decorateClass([
|
|
26156
|
+
r5()
|
|
26157
|
+
], BeamApp.prototype, "_splitPanels", 2);
|
|
26158
|
+
__decorateClass([
|
|
26159
|
+
r5()
|
|
26160
|
+
], BeamApp.prototype, "_methodPickerOpen", 2);
|
|
26161
|
+
__decorateClass([
|
|
26162
|
+
r5()
|
|
26163
|
+
], BeamApp.prototype, "_methodPickerPanelId", 2);
|
|
24385
26164
|
__decorateClass([
|
|
24386
26165
|
e7("beam-sidebar")
|
|
24387
26166
|
], BeamApp.prototype, "_sidebar", 2);
|
|
@@ -24420,6 +26199,7 @@ var BeamSidebar = class extends i4 {
|
|
|
24420
26199
|
this._favorites = /* @__PURE__ */ new Set();
|
|
24421
26200
|
this._collapsedSections = /* @__PURE__ */ new Set();
|
|
24422
26201
|
this._recentPhotons = [];
|
|
26202
|
+
this._notificationWarmth = /* @__PURE__ */ new Map();
|
|
24423
26203
|
}
|
|
24424
26204
|
connectedCallback() {
|
|
24425
26205
|
super.connectedCallback();
|
|
@@ -24790,7 +26570,7 @@ var BeamSidebar = class extends i4 {
|
|
|
24790
26570
|
}
|
|
24791
26571
|
return b2`
|
|
24792
26572
|
<li
|
|
24793
|
-
class="photon-item ${this.selectedPhoton === photon.name ? "active" : ""} ${photon.internal ? "internal" : ""}"
|
|
26573
|
+
class="photon-item ${this.selectedPhoton === photon.name ? "active" : ""} ${photon.internal ? "internal" : ""} ${this._isPhotonWarm(photon.name) ? "warmth" : ""}"
|
|
24794
26574
|
role="option"
|
|
24795
26575
|
aria-selected="${this.selectedPhoton === photon.name}"
|
|
24796
26576
|
tabindex="0"
|
|
@@ -24987,6 +26767,28 @@ ${photon.path}` : ""}"
|
|
|
24987
26767
|
}
|
|
24988
26768
|
});
|
|
24989
26769
|
}
|
|
26770
|
+
/**
|
|
26771
|
+
* Check if a photon currently has a warmth indicator (notification received within last 5 seconds)
|
|
26772
|
+
*/
|
|
26773
|
+
_isPhotonWarm(photonName) {
|
|
26774
|
+
const lastNotificationTime = this._notificationWarmth.get(photonName);
|
|
26775
|
+
if (!lastNotificationTime) return false;
|
|
26776
|
+
return Date.now() - lastNotificationTime < 5e3;
|
|
26777
|
+
}
|
|
26778
|
+
/**
|
|
26779
|
+
* Update the warmth indicator for a photon when a notification arrives
|
|
26780
|
+
*/
|
|
26781
|
+
updatePhotonWarmth(photonName) {
|
|
26782
|
+
this._notificationWarmth.set(photonName, Date.now());
|
|
26783
|
+
this.requestUpdate();
|
|
26784
|
+
}
|
|
26785
|
+
/**
|
|
26786
|
+
* Check if a notification type is watched by a photon
|
|
26787
|
+
* This will be called by beam-app to determine if window.focus() should be triggered
|
|
26788
|
+
*/
|
|
26789
|
+
isNotificationWatched(photonName, notificationType) {
|
|
26790
|
+
return true;
|
|
26791
|
+
}
|
|
24990
26792
|
};
|
|
24991
26793
|
BeamSidebar.styles = [
|
|
24992
26794
|
theme,
|
|
@@ -25221,7 +27023,7 @@ BeamSidebar.styles = [
|
|
|
25221
27023
|
}
|
|
25222
27024
|
|
|
25223
27025
|
.section-header:hover {
|
|
25224
|
-
color: var(--t-
|
|
27026
|
+
color: var(--t-primary);
|
|
25225
27027
|
background: var(--bg-panel);
|
|
25226
27028
|
}
|
|
25227
27029
|
|
|
@@ -25283,7 +27085,7 @@ BeamSidebar.styles = [
|
|
|
25283
27085
|
}
|
|
25284
27086
|
|
|
25285
27087
|
.photon-item:hover {
|
|
25286
|
-
background:
|
|
27088
|
+
background: var(--bg-glass);
|
|
25287
27089
|
}
|
|
25288
27090
|
|
|
25289
27091
|
.photon-item.active {
|
|
@@ -25297,13 +27099,28 @@ BeamSidebar.styles = [
|
|
|
25297
27099
|
|
|
25298
27100
|
@keyframes flash-highlight {
|
|
25299
27101
|
0% {
|
|
25300
|
-
background:
|
|
27102
|
+
background: var(--glow-primary);
|
|
25301
27103
|
}
|
|
25302
27104
|
100% {
|
|
25303
27105
|
background: transparent;
|
|
25304
27106
|
}
|
|
25305
27107
|
}
|
|
25306
27108
|
|
|
27109
|
+
.photon-item.warmth {
|
|
27110
|
+
animation: warmth-fade 5s ease-out forwards;
|
|
27111
|
+
}
|
|
27112
|
+
|
|
27113
|
+
@keyframes warmth-fade {
|
|
27114
|
+
0% {
|
|
27115
|
+
background: var(--color-warning);
|
|
27116
|
+
opacity: 0.15;
|
|
27117
|
+
}
|
|
27118
|
+
100% {
|
|
27119
|
+
background: var(--color-warning);
|
|
27120
|
+
opacity: 0;
|
|
27121
|
+
}
|
|
27122
|
+
}
|
|
27123
|
+
|
|
25307
27124
|
.photon-icon {
|
|
25308
27125
|
width: 28px;
|
|
25309
27126
|
height: 28px;
|
|
@@ -25394,7 +27211,7 @@ BeamSidebar.styles = [
|
|
|
25394
27211
|
gap: 3px;
|
|
25395
27212
|
font-size: var(--text-2xs);
|
|
25396
27213
|
padding: 2px 5px;
|
|
25397
|
-
background:
|
|
27214
|
+
background: var(--bg-glass);
|
|
25398
27215
|
border: 1px solid var(--border-glass);
|
|
25399
27216
|
border-radius: var(--radius-full);
|
|
25400
27217
|
font-weight: 500;
|
|
@@ -25477,7 +27294,7 @@ BeamSidebar.styles = [
|
|
|
25477
27294
|
.marketplace-btn:hover {
|
|
25478
27295
|
background: var(--bg-panel);
|
|
25479
27296
|
border-color: var(--accent-secondary);
|
|
25480
|
-
box-shadow:
|
|
27297
|
+
box-shadow: var(--shadow-sm);
|
|
25481
27298
|
transform: translateY(-1px);
|
|
25482
27299
|
}
|
|
25483
27300
|
|
|
@@ -25709,6 +27526,9 @@ __decorateClass([
|
|
|
25709
27526
|
__decorateClass([
|
|
25710
27527
|
r5()
|
|
25711
27528
|
], BeamSidebar.prototype, "_recentPhotons", 2);
|
|
27529
|
+
__decorateClass([
|
|
27530
|
+
r5()
|
|
27531
|
+
], BeamSidebar.prototype, "_notificationWarmth", 2);
|
|
25712
27532
|
BeamSidebar = __decorateClass([
|
|
25713
27533
|
t4("beam-sidebar")
|
|
25714
27534
|
], BeamSidebar);
|
|
@@ -25798,37 +27618,24 @@ var MethodCard = class extends i4 {
|
|
|
25798
27618
|
</div>
|
|
25799
27619
|
${this.method.isTemplate ? b2`<span class="badge prompt">Prompt</span>` : ""}
|
|
25800
27620
|
${isCron ? b2`<span
|
|
25801
|
-
class="badge"
|
|
25802
|
-
style="background:hsla(215,80%,60%,0.15);color:hsl(215,80%,65%)"
|
|
27621
|
+
class="badge scheduled"
|
|
25803
27622
|
title="Runs automatically on schedule: ${this.method.scheduled}"
|
|
25804
27623
|
>⏱ Scheduled</span
|
|
25805
27624
|
>` : ""}
|
|
25806
|
-
${isDeprecated ? b2`<span
|
|
25807
|
-
|
|
25808
|
-
|
|
25809
|
-
|
|
25810
|
-
>` : ""}
|
|
25811
|
-
${isCached ? b2`<span
|
|
25812
|
-
class="badge"
|
|
25813
|
-
style="background:hsla(280,60%,50%,0.15);color:hsl(280,60%,65%)"
|
|
25814
|
-
>Cached</span
|
|
25815
|
-
>` : ""}
|
|
25816
|
-
${isThrottled ? b2`<span
|
|
25817
|
-
class="badge"
|
|
25818
|
-
style="background:hsla(30,80%,50%,0.15);color:hsl(30,80%,60%)"
|
|
25819
|
-
>Throttled</span
|
|
25820
|
-
>` : ""}
|
|
25821
|
-
${isQueued ? b2`<span
|
|
25822
|
-
class="badge"
|
|
25823
|
-
style="background:hsla(200,70%,50%,0.15);color:hsl(200,70%,60%)"
|
|
25824
|
-
>Queued</span
|
|
25825
|
-
>` : ""}
|
|
27625
|
+
${isDeprecated ? b2`<span class="badge deprecated">Deprecated</span>` : ""}
|
|
27626
|
+
${isCached ? b2`<span class="badge cached">Cached</span>` : ""}
|
|
27627
|
+
${isThrottled ? b2`<span class="badge throttled">Throttled</span>` : ""}
|
|
27628
|
+
${isQueued ? b2`<span class="badge queued">Queued</span>` : ""}
|
|
25826
27629
|
${emitsEvent ? b2`<span
|
|
25827
|
-
class="badge"
|
|
25828
|
-
style="background:hsla(100,70%,50%,0.15);color:hsl(100,70%,60%)"
|
|
27630
|
+
class="badge event"
|
|
25829
27631
|
title="Automatically emits event: ${this.method.eventName}"
|
|
25830
27632
|
>📡 Event</span
|
|
25831
27633
|
>` : ""}
|
|
27634
|
+
${this.method.audience ? b2`<span
|
|
27635
|
+
class="badge audience"
|
|
27636
|
+
title="Target audience: ${this.method.audience.join(", ")}"
|
|
27637
|
+
>${this.method.audience.includes("user") && this.method.audience.includes("assistant") ? sizedIcon(users, 12) : this.method.audience.includes("user") ? sizedIcon(user, 12) : sizedIcon(bot, 12)}</span
|
|
27638
|
+
>` : ""}
|
|
25832
27639
|
</div>
|
|
25833
27640
|
${this._editingDescription ? b2`
|
|
25834
27641
|
<div class="description editing" @click=${(e8) => e8.stopPropagation()}>
|
|
@@ -26071,7 +27878,7 @@ MethodCard.styles = [
|
|
|
26071
27878
|
|
|
26072
27879
|
.card:hover {
|
|
26073
27880
|
transform: translateY(-2px);
|
|
26074
|
-
box-shadow:
|
|
27881
|
+
box-shadow: var(--shadow-lg);
|
|
26075
27882
|
border-left-color: var(--accent-primary);
|
|
26076
27883
|
}
|
|
26077
27884
|
|
|
@@ -26249,7 +28056,7 @@ MethodCard.styles = [
|
|
|
26249
28056
|
font-size: var(--text-xs);
|
|
26250
28057
|
padding: 2px 8px;
|
|
26251
28058
|
border-radius: var(--radius-md);
|
|
26252
|
-
background:
|
|
28059
|
+
background: var(--bg-glass);
|
|
26253
28060
|
color: var(--t-muted);
|
|
26254
28061
|
flex-shrink: 0;
|
|
26255
28062
|
}
|
|
@@ -26259,6 +28066,42 @@ MethodCard.styles = [
|
|
|
26259
28066
|
color: hsl(45, 80%, 60%);
|
|
26260
28067
|
}
|
|
26261
28068
|
|
|
28069
|
+
.badge.scheduled {
|
|
28070
|
+
background: hsla(215, 80%, 60%, 0.15);
|
|
28071
|
+
color: hsl(215, 80%, 65%);
|
|
28072
|
+
}
|
|
28073
|
+
|
|
28074
|
+
.badge.deprecated {
|
|
28075
|
+
background: hsla(0, 0%, 50%, 0.15);
|
|
28076
|
+
color: hsl(0, 0%, 60%);
|
|
28077
|
+
text-decoration: line-through;
|
|
28078
|
+
}
|
|
28079
|
+
|
|
28080
|
+
.badge.cached {
|
|
28081
|
+
background: hsla(280, 60%, 50%, 0.15);
|
|
28082
|
+
color: hsl(280, 60%, 65%);
|
|
28083
|
+
}
|
|
28084
|
+
|
|
28085
|
+
.badge.throttled {
|
|
28086
|
+
background: hsla(30, 80%, 50%, 0.15);
|
|
28087
|
+
color: hsl(30, 80%, 60%);
|
|
28088
|
+
}
|
|
28089
|
+
|
|
28090
|
+
.badge.queued {
|
|
28091
|
+
background: hsla(200, 70%, 50%, 0.15);
|
|
28092
|
+
color: hsl(200, 70%, 60%);
|
|
28093
|
+
}
|
|
28094
|
+
|
|
28095
|
+
.badge.event {
|
|
28096
|
+
background: hsla(100, 70%, 50%, 0.15);
|
|
28097
|
+
color: hsl(100, 70%, 60%);
|
|
28098
|
+
}
|
|
28099
|
+
|
|
28100
|
+
.badge.audience {
|
|
28101
|
+
background: hsla(180, 60%, 50%, 0.15);
|
|
28102
|
+
color: hsl(180, 60%, 65%);
|
|
28103
|
+
}
|
|
28104
|
+
|
|
26262
28105
|
.param-tags {
|
|
26263
28106
|
display: flex;
|
|
26264
28107
|
flex-wrap: wrap;
|
|
@@ -26272,9 +28115,9 @@ MethodCard.styles = [
|
|
|
26272
28115
|
font-size: var(--text-xs);
|
|
26273
28116
|
padding: 4px 10px;
|
|
26274
28117
|
border-radius: var(--radius-xs);
|
|
26275
|
-
background: hsla(260, 60%, 50%, 0.12);
|
|
26276
|
-
color: var(--t-primary);
|
|
26277
|
-
border: 1px solid hsla(260, 60%, 50%, 0.2);
|
|
28118
|
+
background: var(--param-tag-bg, hsla(260, 60%, 50%, 0.12));
|
|
28119
|
+
color: var(--param-tag-color, var(--t-primary));
|
|
28120
|
+
border: 1px solid var(--param-tag-border, hsla(260, 60%, 50%, 0.2));
|
|
26278
28121
|
font-weight: 500;
|
|
26279
28122
|
}
|
|
26280
28123
|
|
|
@@ -26283,8 +28126,8 @@ MethodCard.styles = [
|
|
|
26283
28126
|
min-width: 20px;
|
|
26284
28127
|
height: 20px;
|
|
26285
28128
|
border-radius: var(--radius-sm);
|
|
26286
|
-
background: hsla(45, 80%, 50%, 0.2);
|
|
26287
|
-
color: hsl(45, 80%, 60%);
|
|
28129
|
+
background: var(--color-warning-bg, hsla(45, 80%, 50%, 0.2));
|
|
28130
|
+
color: var(--color-warning, hsl(45, 80%, 60%));
|
|
26288
28131
|
display: inline-flex;
|
|
26289
28132
|
align-items: center;
|
|
26290
28133
|
justify-content: center;
|
|
@@ -26314,7 +28157,7 @@ MethodCard.styles = [
|
|
|
26314
28157
|
align-items: center;
|
|
26315
28158
|
justify-content: center;
|
|
26316
28159
|
border-radius: var(--radius-sm);
|
|
26317
|
-
background:
|
|
28160
|
+
background: var(--bg-glass);
|
|
26318
28161
|
}
|
|
26319
28162
|
|
|
26320
28163
|
.card:hover .action-icon {
|
|
@@ -26329,7 +28172,7 @@ MethodCard.styles = [
|
|
|
26329
28172
|
border: 1px solid var(--border-glass);
|
|
26330
28173
|
border-radius: var(--radius-md);
|
|
26331
28174
|
padding: var(--space-sm);
|
|
26332
|
-
box-shadow:
|
|
28175
|
+
box-shadow: var(--shadow-lg);
|
|
26333
28176
|
z-index: 100;
|
|
26334
28177
|
display: grid;
|
|
26335
28178
|
grid-template-columns: repeat(6, 1fr);
|
|
@@ -26498,6 +28341,30 @@ function singularize(word) {
|
|
|
26498
28341
|
if (lower.endsWith("s") && !lower.endsWith("ss")) return word.slice(0, -1);
|
|
26499
28342
|
return word;
|
|
26500
28343
|
}
|
|
28344
|
+
function isValidCharForFormat(char, format, position) {
|
|
28345
|
+
if (!format) return true;
|
|
28346
|
+
switch (format.toLowerCase()) {
|
|
28347
|
+
case "email":
|
|
28348
|
+
return /[a-zA-Z0-9@.\-_+]/.test(char);
|
|
28349
|
+
case "url":
|
|
28350
|
+
case "uri":
|
|
28351
|
+
return /[a-zA-Z0-9:\/\-_.?=&#%@+~;,!]/.test(char);
|
|
28352
|
+
case "uuid":
|
|
28353
|
+
return /[0-9a-fA-F\-]/.test(char);
|
|
28354
|
+
case "ipv4":
|
|
28355
|
+
return /[0-9.]/.test(char);
|
|
28356
|
+
case "ipv6":
|
|
28357
|
+
return /[0-9a-fA-F:]/.test(char);
|
|
28358
|
+
case "slug":
|
|
28359
|
+
return /[a-z0-9\-]/.test(char);
|
|
28360
|
+
case "hex":
|
|
28361
|
+
return position === 0 && char === "#" ? true : /[0-9a-fA-F]/.test(char);
|
|
28362
|
+
case "phone":
|
|
28363
|
+
return /[0-9+\-() ]/.test(char);
|
|
28364
|
+
default:
|
|
28365
|
+
return true;
|
|
28366
|
+
}
|
|
28367
|
+
}
|
|
26501
28368
|
var InvokeForm = class extends i4 {
|
|
26502
28369
|
constructor() {
|
|
26503
28370
|
super(...arguments);
|
|
@@ -26752,9 +28619,7 @@ var InvokeForm = class extends i4 {
|
|
|
26752
28619
|
this._handleChange(key, arr.length > 0 ? arr : raw);
|
|
26753
28620
|
}}
|
|
26754
28621
|
/>
|
|
26755
|
-
<div class="hint"
|
|
26756
|
-
Comma-separated values
|
|
26757
|
-
</div>
|
|
28622
|
+
<div class="hint">Comma-separated values</div>
|
|
26758
28623
|
</div>
|
|
26759
28624
|
`;
|
|
26760
28625
|
}
|
|
@@ -26805,9 +28670,12 @@ var InvokeForm = class extends i4 {
|
|
|
26805
28670
|
min="${min}"
|
|
26806
28671
|
max="${max}"
|
|
26807
28672
|
step="${step2}"
|
|
28673
|
+
style="${this._sliderFillStyle(Number(currentValue2), min, max)}"
|
|
26808
28674
|
.value=${String(currentValue2)}
|
|
26809
28675
|
@input=${(e8) => {
|
|
26810
|
-
const
|
|
28676
|
+
const el2 = e8.target;
|
|
28677
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
28678
|
+
el2.style.cssText = this._sliderFillStyle(v2, min, max);
|
|
26811
28679
|
this._handleChange(key, v2);
|
|
26812
28680
|
}}
|
|
26813
28681
|
/>
|
|
@@ -26820,7 +28688,14 @@ var InvokeForm = class extends i4 {
|
|
|
26820
28688
|
step="${step2}"
|
|
26821
28689
|
.value=${displayValue2}
|
|
26822
28690
|
@input=${(e8) => {
|
|
26823
|
-
const
|
|
28691
|
+
const raw = e8.target.value;
|
|
28692
|
+
if (raw === "" || raw === "-") return;
|
|
28693
|
+
this._handleChange(key, Number(raw));
|
|
28694
|
+
}}
|
|
28695
|
+
@change=${(e8) => {
|
|
28696
|
+
const el2 = e8.target;
|
|
28697
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
28698
|
+
el2.value = String(v2);
|
|
26824
28699
|
this._handleChange(key, v2);
|
|
26825
28700
|
}}
|
|
26826
28701
|
/>
|
|
@@ -26839,14 +28714,31 @@ var InvokeForm = class extends i4 {
|
|
|
26839
28714
|
return b2`
|
|
26840
28715
|
<input
|
|
26841
28716
|
id=${o8(inputId)}
|
|
26842
|
-
type="
|
|
26843
|
-
class="${errorClass}"
|
|
28717
|
+
type="text"
|
|
28718
|
+
class="number-input-clean ${errorClass}"
|
|
28719
|
+
inputmode=${isInteger ? "numeric" : "decimal"}
|
|
26844
28720
|
${hasMin ? `min="${schema.minimum}"` : ""}
|
|
26845
|
-
step="${step}"
|
|
26846
28721
|
placeholder="${defaultVal2}"
|
|
26847
28722
|
.value=${displayValue}
|
|
28723
|
+
@keypress=${(e8) => {
|
|
28724
|
+
const char = e8.key;
|
|
28725
|
+
const isDigit = /\d/.test(char);
|
|
28726
|
+
const isMinus = char === "-";
|
|
28727
|
+
const isDecimal = char === "." && !isInteger;
|
|
28728
|
+
if (!isDigit && !isMinus && !isDecimal) {
|
|
28729
|
+
e8.preventDefault();
|
|
28730
|
+
}
|
|
28731
|
+
}}
|
|
26848
28732
|
@input=${(e8) => {
|
|
26849
|
-
|
|
28733
|
+
let text = e8.target.value;
|
|
28734
|
+
if (isInteger) {
|
|
28735
|
+
const cleaned = text.replace(/[^\d-]/g, "");
|
|
28736
|
+
text = cleaned.match(/-.*-/) ? cleaned.replace(/-/g, "").replace(/^/, "-") : cleaned;
|
|
28737
|
+
}
|
|
28738
|
+
let v2 = text === "" || text === "-" ? defaultVal2 : Number(text);
|
|
28739
|
+
if (isNaN(v2)) {
|
|
28740
|
+
v2 = defaultVal2;
|
|
28741
|
+
}
|
|
26850
28742
|
this._handleChange(key, v2);
|
|
26851
28743
|
}}
|
|
26852
28744
|
/>
|
|
@@ -26934,6 +28826,8 @@ var InvokeForm = class extends i4 {
|
|
|
26934
28826
|
}
|
|
26935
28827
|
const defaultVal = schema.default;
|
|
26936
28828
|
const placeholder = defaultVal != null ? String(defaultVal) : "";
|
|
28829
|
+
const format = schema.format;
|
|
28830
|
+
const pattern = schema.pattern;
|
|
26937
28831
|
return b2`
|
|
26938
28832
|
<input
|
|
26939
28833
|
id=${o8(inputId)}
|
|
@@ -26941,6 +28835,23 @@ var InvokeForm = class extends i4 {
|
|
|
26941
28835
|
class="${errorClass}"
|
|
26942
28836
|
placeholder="${placeholder}"
|
|
26943
28837
|
.value=${this._values[key] || ""}
|
|
28838
|
+
@keypress=${(e8) => {
|
|
28839
|
+
if (!isValidCharForFormat(e8.key, format)) {
|
|
28840
|
+
e8.preventDefault();
|
|
28841
|
+
return;
|
|
28842
|
+
}
|
|
28843
|
+
if (pattern) {
|
|
28844
|
+
try {
|
|
28845
|
+
const currentValue = e8.target.value;
|
|
28846
|
+
const newValue = currentValue + e8.key;
|
|
28847
|
+
const regex = new RegExp(pattern);
|
|
28848
|
+
if (!regex.test(newValue)) {
|
|
28849
|
+
e8.preventDefault();
|
|
28850
|
+
}
|
|
28851
|
+
} catch (err) {
|
|
28852
|
+
}
|
|
28853
|
+
}
|
|
28854
|
+
}}
|
|
26944
28855
|
@input=${(e8) => this._handleChange(key, e8.target.value)}
|
|
26945
28856
|
/>
|
|
26946
28857
|
`;
|
|
@@ -27065,7 +28976,11 @@ var InvokeForm = class extends i4 {
|
|
|
27065
28976
|
*/
|
|
27066
28977
|
_cleanDescription(desc, schema) {
|
|
27067
28978
|
if (!desc) return desc;
|
|
27068
|
-
let cleaned = desc
|
|
28979
|
+
let cleaned = desc;
|
|
28980
|
+
const lines = cleaned.split("\n").filter((line) => !line.trim().startsWith("@"));
|
|
28981
|
+
cleaned = lines.join("\n").trim();
|
|
28982
|
+
cleaned = cleaned.replace(/\s*@\w+[\s\S]*?(?=[.!?\n]|$)/g, "").trim();
|
|
28983
|
+
cleaned = cleaned.replace(
|
|
27069
28984
|
/['"][\w-]+['"]\s*(?:\([^)]*\)\s*)?(?:\|\s*['"][\w-]+['"]\s*(?:\([^)]*\)\s*)?)+/g,
|
|
27070
28985
|
""
|
|
27071
28986
|
);
|
|
@@ -27101,6 +29016,23 @@ var InvokeForm = class extends i4 {
|
|
|
27101
29016
|
this._savePersistedValues();
|
|
27102
29017
|
}
|
|
27103
29018
|
}
|
|
29019
|
+
_sliderFillStyle(value, min, max) {
|
|
29020
|
+
const pct = max > min ? (value - min) / (max - min) * 100 : 0;
|
|
29021
|
+
return `background: linear-gradient(to right, var(--accent-primary) ${pct}%, var(--border-glass) ${pct}%)`;
|
|
29022
|
+
}
|
|
29023
|
+
/** Clamp to [min, max] and round to nearest step (integer-safe). */
|
|
29024
|
+
_sanitizeSliderValue(raw, min, max, step) {
|
|
29025
|
+
let v2 = Number.isFinite(raw) ? raw : min;
|
|
29026
|
+
v2 = Math.min(max, Math.max(min, v2));
|
|
29027
|
+
if (step > 0) {
|
|
29028
|
+
v2 = min + Math.round((v2 - min) / step) * step;
|
|
29029
|
+
if (v2 > max) v2 = max;
|
|
29030
|
+
}
|
|
29031
|
+
if (Number.isInteger(step) && step >= 1) {
|
|
29032
|
+
v2 = Math.round(v2);
|
|
29033
|
+
}
|
|
29034
|
+
return v2;
|
|
29035
|
+
}
|
|
27104
29036
|
_handleChange(key, value) {
|
|
27105
29037
|
this._values = { ...this._values, [key]: value };
|
|
27106
29038
|
if (this.rememberValues) {
|
|
@@ -27108,7 +29040,7 @@ var InvokeForm = class extends i4 {
|
|
|
27108
29040
|
}
|
|
27109
29041
|
}
|
|
27110
29042
|
_buildCliCommand() {
|
|
27111
|
-
const parts = [
|
|
29043
|
+
const parts = [this.photonName, this.methodName];
|
|
27112
29044
|
for (const [key, value] of Object.entries(this._values)) {
|
|
27113
29045
|
if (value === void 0 || value === null || value === "") continue;
|
|
27114
29046
|
const strVal = typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
@@ -27232,7 +29164,9 @@ var InvokeForm = class extends i4 {
|
|
|
27232
29164
|
>
|
|
27233
29165
|
<option value="">Select...</option>
|
|
27234
29166
|
${schema.enum.map(
|
|
27235
|
-
(opt) => b2`
|
|
29167
|
+
(opt) => b2`
|
|
29168
|
+
<option value=${opt} ?selected=${opt === value}>${capitalizeEnumValue(opt)}</option>
|
|
29169
|
+
`
|
|
27236
29170
|
)}
|
|
27237
29171
|
</select>
|
|
27238
29172
|
`;
|
|
@@ -27268,8 +29202,14 @@ var InvokeForm = class extends i4 {
|
|
|
27268
29202
|
min="${min}"
|
|
27269
29203
|
max="${max}"
|
|
27270
29204
|
step="${step2}"
|
|
29205
|
+
style="${this._sliderFillStyle(Number(currentVal2), min, max)}"
|
|
27271
29206
|
.value=${String(currentVal2)}
|
|
27272
|
-
@input=${(e8) =>
|
|
29207
|
+
@input=${(e8) => {
|
|
29208
|
+
const el2 = e8.target;
|
|
29209
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
29210
|
+
el2.style.cssText = this._sliderFillStyle(v2, min, max);
|
|
29211
|
+
onChange(propKey, v2);
|
|
29212
|
+
}}
|
|
27273
29213
|
/>
|
|
27274
29214
|
<input
|
|
27275
29215
|
type="number"
|
|
@@ -27278,7 +29218,17 @@ var InvokeForm = class extends i4 {
|
|
|
27278
29218
|
max="${max}"
|
|
27279
29219
|
step="${step2}"
|
|
27280
29220
|
.value=${displayVal2}
|
|
27281
|
-
@input=${(e8) =>
|
|
29221
|
+
@input=${(e8) => {
|
|
29222
|
+
const raw = e8.target.value;
|
|
29223
|
+
if (raw === "" || raw === "-") return;
|
|
29224
|
+
onChange(propKey, Number(raw));
|
|
29225
|
+
}}
|
|
29226
|
+
@change=${(e8) => {
|
|
29227
|
+
const el2 = e8.target;
|
|
29228
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
29229
|
+
el2.value = String(v2);
|
|
29230
|
+
onChange(propKey, v2);
|
|
29231
|
+
}}
|
|
27282
29232
|
/>
|
|
27283
29233
|
</div>
|
|
27284
29234
|
<div class="range-labels">
|
|
@@ -27445,18 +29395,23 @@ var InvokeForm = class extends i4 {
|
|
|
27445
29395
|
>
|
|
27446
29396
|
<option value="">Select...</option>
|
|
27447
29397
|
${schema.enum.map(
|
|
27448
|
-
(opt) => b2`
|
|
29398
|
+
(opt) => b2`
|
|
29399
|
+
<option value=${opt} ?selected=${opt === value}>${capitalizeEnumValue(opt)}</option>
|
|
29400
|
+
`
|
|
27449
29401
|
)}
|
|
27450
29402
|
</select>
|
|
27451
29403
|
`;
|
|
27452
29404
|
}
|
|
27453
29405
|
if (schema.type === "boolean") {
|
|
27454
29406
|
return b2`
|
|
27455
|
-
<
|
|
27456
|
-
|
|
27457
|
-
|
|
27458
|
-
|
|
27459
|
-
|
|
29407
|
+
<label class="switch">
|
|
29408
|
+
<input
|
|
29409
|
+
type="checkbox"
|
|
29410
|
+
.checked=${!!value}
|
|
29411
|
+
@change=${(e8) => handleNestedChange(e8.target.checked)}
|
|
29412
|
+
/>
|
|
29413
|
+
<span class="slider"></span>
|
|
29414
|
+
</label>
|
|
27460
29415
|
`;
|
|
27461
29416
|
}
|
|
27462
29417
|
if (schema.type === "number" || schema.type === "integer") {
|
|
@@ -27478,8 +29433,14 @@ var InvokeForm = class extends i4 {
|
|
|
27478
29433
|
min="${min}"
|
|
27479
29434
|
max="${max}"
|
|
27480
29435
|
step="${step2}"
|
|
29436
|
+
style="${this._sliderFillStyle(Number(currentVal2), min, max)}"
|
|
27481
29437
|
.value=${String(currentVal2)}
|
|
27482
|
-
@input=${(e8) =>
|
|
29438
|
+
@input=${(e8) => {
|
|
29439
|
+
const el2 = e8.target;
|
|
29440
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
29441
|
+
el2.style.cssText = this._sliderFillStyle(v2, min, max);
|
|
29442
|
+
handleNestedChange(v2);
|
|
29443
|
+
}}
|
|
27483
29444
|
/>
|
|
27484
29445
|
<input
|
|
27485
29446
|
type="number"
|
|
@@ -27488,7 +29449,17 @@ var InvokeForm = class extends i4 {
|
|
|
27488
29449
|
max="${max}"
|
|
27489
29450
|
step="${step2}"
|
|
27490
29451
|
.value=${displayVal2}
|
|
27491
|
-
@input=${(e8) =>
|
|
29452
|
+
@input=${(e8) => {
|
|
29453
|
+
const raw = e8.target.value;
|
|
29454
|
+
if (raw === "" || raw === "-") return;
|
|
29455
|
+
handleNestedChange(Number(raw));
|
|
29456
|
+
}}
|
|
29457
|
+
@change=${(e8) => {
|
|
29458
|
+
const el2 = e8.target;
|
|
29459
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
29460
|
+
el2.value = String(v2);
|
|
29461
|
+
handleNestedChange(v2);
|
|
29462
|
+
}}
|
|
27492
29463
|
/>
|
|
27493
29464
|
</div>
|
|
27494
29465
|
<div class="range-labels">
|
|
@@ -27839,6 +29810,7 @@ InvokeForm.styles = [
|
|
|
27839
29810
|
font-size: var(--text-xs);
|
|
27840
29811
|
padding: 2px 6px;
|
|
27841
29812
|
border-radius: var(--radius-xs);
|
|
29813
|
+
transition: background 0.15s ease;
|
|
27842
29814
|
}
|
|
27843
29815
|
|
|
27844
29816
|
.array-item-remove:hover {
|
|
@@ -27915,11 +29887,17 @@ InvokeForm.styles = [
|
|
|
27915
29887
|
margin-top: var(--space-xs);
|
|
27916
29888
|
}
|
|
27917
29889
|
|
|
29890
|
+
.hint {
|
|
29891
|
+
font-size: var(--text-xs);
|
|
29892
|
+
color: var(--t-muted);
|
|
29893
|
+
margin-top: 2px;
|
|
29894
|
+
}
|
|
29895
|
+
|
|
27918
29896
|
/* Slider-First Numeric Input */
|
|
27919
29897
|
.slider-group {
|
|
27920
29898
|
display: flex;
|
|
27921
29899
|
flex-direction: column;
|
|
27922
|
-
gap:
|
|
29900
|
+
gap: 4px;
|
|
27923
29901
|
}
|
|
27924
29902
|
|
|
27925
29903
|
.slider-row {
|
|
@@ -27930,57 +29908,140 @@ InvokeForm.styles = [
|
|
|
27930
29908
|
|
|
27931
29909
|
.slider-row input[type='range'] {
|
|
27932
29910
|
flex: 1;
|
|
27933
|
-
height:
|
|
27934
|
-
|
|
27935
|
-
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
27936
|
-
border-radius: 3px;
|
|
29911
|
+
height: 4px;
|
|
29912
|
+
border-radius: var(--radius-full, 9999px);
|
|
27937
29913
|
-webkit-appearance: none;
|
|
27938
29914
|
cursor: pointer;
|
|
27939
29915
|
margin: 8px 0;
|
|
29916
|
+
border: none;
|
|
29917
|
+
outline: none;
|
|
29918
|
+
/* Default unfilled track — overridden by inline style for fill effect */
|
|
29919
|
+
background: var(--border-glass);
|
|
27940
29920
|
}
|
|
27941
29921
|
|
|
27942
29922
|
.slider-row input[type='range']::-webkit-slider-thumb {
|
|
27943
29923
|
-webkit-appearance: none;
|
|
27944
|
-
width:
|
|
27945
|
-
height:
|
|
29924
|
+
width: 16px;
|
|
29925
|
+
height: 16px;
|
|
27946
29926
|
background: var(--accent-primary);
|
|
29927
|
+
border: 2px solid var(--bg-panel, var(--bg-glass));
|
|
27947
29928
|
border-radius: 50%;
|
|
27948
29929
|
cursor: pointer;
|
|
27949
|
-
box-shadow:
|
|
29930
|
+
box-shadow:
|
|
29931
|
+
0 0 0 2px var(--accent-primary),
|
|
29932
|
+
0 1px 4px rgba(0, 0, 0, 0.3);
|
|
29933
|
+
transition:
|
|
29934
|
+
box-shadow 0.15s ease,
|
|
29935
|
+
transform 0.15s ease;
|
|
29936
|
+
}
|
|
29937
|
+
|
|
29938
|
+
.slider-row input[type='range']::-webkit-slider-thumb:hover {
|
|
29939
|
+
box-shadow:
|
|
29940
|
+
0 0 0 3px var(--accent-primary),
|
|
29941
|
+
0 0 8px var(--glow-primary);
|
|
29942
|
+
transform: scale(1.1);
|
|
29943
|
+
}
|
|
29944
|
+
|
|
29945
|
+
.slider-row input[type='range']:active::-webkit-slider-thumb {
|
|
29946
|
+
transform: scale(0.95);
|
|
27950
29947
|
}
|
|
27951
29948
|
|
|
27952
29949
|
.slider-row input[type='range']::-moz-range-track {
|
|
27953
|
-
height:
|
|
27954
|
-
background:
|
|
27955
|
-
border-radius:
|
|
27956
|
-
border:
|
|
29950
|
+
height: 4px;
|
|
29951
|
+
background: var(--border-glass);
|
|
29952
|
+
border-radius: var(--radius-full, 9999px);
|
|
29953
|
+
border: none;
|
|
29954
|
+
}
|
|
29955
|
+
|
|
29956
|
+
.slider-row input[type='range']::-moz-range-progress {
|
|
29957
|
+
height: 4px;
|
|
29958
|
+
background: var(--accent-primary);
|
|
29959
|
+
border-radius: var(--radius-full, 9999px);
|
|
27957
29960
|
}
|
|
27958
29961
|
|
|
27959
29962
|
.slider-row input[type='range']::-moz-range-thumb {
|
|
27960
|
-
width:
|
|
27961
|
-
height:
|
|
29963
|
+
width: 12px;
|
|
29964
|
+
height: 12px;
|
|
27962
29965
|
background: var(--accent-primary);
|
|
29966
|
+
border: 2px solid var(--bg-panel, var(--bg-glass));
|
|
27963
29967
|
border-radius: 50%;
|
|
27964
29968
|
cursor: pointer;
|
|
27965
|
-
|
|
27966
|
-
|
|
29969
|
+
box-shadow:
|
|
29970
|
+
0 0 0 2px var(--accent-primary),
|
|
29971
|
+
0 1px 4px rgba(0, 0, 0, 0.3);
|
|
29972
|
+
transition:
|
|
29973
|
+
box-shadow 0.15s ease,
|
|
29974
|
+
transform 0.15s ease;
|
|
27967
29975
|
}
|
|
27968
29976
|
|
|
27969
|
-
.slider-
|
|
27970
|
-
|
|
29977
|
+
.slider-row input[type='range']::-moz-range-thumb:hover {
|
|
29978
|
+
box-shadow:
|
|
29979
|
+
0 0 0 3px var(--accent-primary),
|
|
29980
|
+
0 0 8px var(--glow-primary);
|
|
29981
|
+
}
|
|
29982
|
+
|
|
29983
|
+
.slider-number-input {
|
|
29984
|
+
width: 64px;
|
|
27971
29985
|
text-align: center;
|
|
29986
|
+
font-size: var(--text-sm);
|
|
29987
|
+
font-weight: 500;
|
|
29988
|
+
font-variant-numeric: tabular-nums;
|
|
29989
|
+
padding: 4px 6px;
|
|
29990
|
+
background: var(--bg-glass);
|
|
29991
|
+
border: 1px solid var(--border-glass) !important;
|
|
29992
|
+
border-radius: var(--radius-sm);
|
|
29993
|
+
color: var(--t-primary);
|
|
29994
|
+
-moz-appearance: textfield;
|
|
29995
|
+
transition:
|
|
29996
|
+
border-color 0.15s ease,
|
|
29997
|
+
box-shadow 0.15s ease;
|
|
29998
|
+
}
|
|
29999
|
+
|
|
30000
|
+
.slider-number-input::-webkit-outer-spin-button,
|
|
30001
|
+
.slider-number-input::-webkit-inner-spin-button {
|
|
30002
|
+
-webkit-appearance: none;
|
|
30003
|
+
margin: 0;
|
|
30004
|
+
}
|
|
30005
|
+
|
|
30006
|
+
.slider-number-input:focus-visible {
|
|
30007
|
+
outline: none;
|
|
30008
|
+
border-color: var(--accent-primary) !important;
|
|
30009
|
+
box-shadow: 0 0 0 2px var(--glow-primary);
|
|
30010
|
+
}
|
|
30011
|
+
|
|
30012
|
+
/* Clean numeric input — no spinner, mouse wheel support */
|
|
30013
|
+
.number-input-clean {
|
|
30014
|
+
width: 100%;
|
|
30015
|
+
padding: 8px 12px;
|
|
27972
30016
|
font-size: var(--text-md);
|
|
27973
|
-
|
|
30017
|
+
background: var(--bg-glass);
|
|
30018
|
+
border: 1px solid var(--border-glass);
|
|
30019
|
+
border-radius: var(--radius-sm);
|
|
27974
30020
|
color: var(--t-primary);
|
|
27975
|
-
|
|
30021
|
+
appearance: none;
|
|
30022
|
+
-moz-appearance: textfield;
|
|
30023
|
+
-webkit-appearance: none;
|
|
30024
|
+
transition:
|
|
30025
|
+
border-color 0.15s ease,
|
|
30026
|
+
box-shadow 0.15s ease;
|
|
27976
30027
|
}
|
|
27977
30028
|
|
|
27978
|
-
.
|
|
27979
|
-
|
|
27980
|
-
|
|
27981
|
-
|
|
27982
|
-
|
|
27983
|
-
|
|
30029
|
+
.number-input-clean::-webkit-outer-spin-button,
|
|
30030
|
+
.number-input-clean::-webkit-inner-spin-button {
|
|
30031
|
+
-webkit-appearance: none;
|
|
30032
|
+
appearance: none;
|
|
30033
|
+
display: none;
|
|
30034
|
+
margin: 0;
|
|
30035
|
+
}
|
|
30036
|
+
|
|
30037
|
+
.number-input-clean:hover {
|
|
30038
|
+
border-color: var(--accent-primary);
|
|
30039
|
+
}
|
|
30040
|
+
|
|
30041
|
+
.number-input-clean:focus-visible {
|
|
30042
|
+
outline: none;
|
|
30043
|
+
border-color: var(--accent-primary);
|
|
30044
|
+
box-shadow: 0 0 0 2px var(--glow-primary);
|
|
27984
30045
|
}
|
|
27985
30046
|
|
|
27986
30047
|
.range-labels {
|
|
@@ -28029,6 +30090,15 @@ InvokeForm.styles = [
|
|
|
28029
30090
|
flex-shrink: 0;
|
|
28030
30091
|
}
|
|
28031
30092
|
|
|
30093
|
+
select {
|
|
30094
|
+
appearance: none;
|
|
30095
|
+
-webkit-appearance: none;
|
|
30096
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23888'/%3E%3C/svg%3E");
|
|
30097
|
+
background-repeat: no-repeat;
|
|
30098
|
+
background-position: right 12px center;
|
|
30099
|
+
padding-right: 32px;
|
|
30100
|
+
}
|
|
30101
|
+
|
|
28032
30102
|
/* ===== Responsive Design ===== */
|
|
28033
30103
|
@media (max-width: 768px) {
|
|
28034
30104
|
.form-container {
|
|
@@ -28231,7 +30301,7 @@ ActivityLog.styles = [
|
|
|
28231
30301
|
font-size: var(--text-sm);
|
|
28232
30302
|
text-transform: uppercase;
|
|
28233
30303
|
letter-spacing: 0.1em;
|
|
28234
|
-
color: var(--t-
|
|
30304
|
+
color: var(--t-primary);
|
|
28235
30305
|
font-weight: 600;
|
|
28236
30306
|
}
|
|
28237
30307
|
|
|
@@ -28246,7 +30316,7 @@ ActivityLog.styles = [
|
|
|
28246
30316
|
}
|
|
28247
30317
|
|
|
28248
30318
|
.clear-btn:hover {
|
|
28249
|
-
background:
|
|
30319
|
+
background: var(--bg-glass);
|
|
28250
30320
|
color: var(--t-primary);
|
|
28251
30321
|
}
|
|
28252
30322
|
|
|
@@ -28265,14 +30335,14 @@ ActivityLog.styles = [
|
|
|
28265
30335
|
}
|
|
28266
30336
|
|
|
28267
30337
|
.filter-btn:hover {
|
|
28268
|
-
background:
|
|
30338
|
+
background: var(--bg-glass);
|
|
28269
30339
|
color: var(--t-primary);
|
|
28270
30340
|
}
|
|
28271
30341
|
|
|
28272
30342
|
.filter-btn.active {
|
|
28273
30343
|
border-color: var(--accent-secondary);
|
|
28274
30344
|
color: var(--accent-secondary);
|
|
28275
|
-
background:
|
|
30345
|
+
background: var(--bg-glass);
|
|
28276
30346
|
}
|
|
28277
30347
|
|
|
28278
30348
|
.visually-hidden {
|
|
@@ -28332,7 +30402,7 @@ ActivityLog.styles = [
|
|
|
28332
30402
|
display: inline-block;
|
|
28333
30403
|
font-size: var(--text-xs);
|
|
28334
30404
|
color: var(--t-muted);
|
|
28335
|
-
background:
|
|
30405
|
+
background: var(--bg-glass);
|
|
28336
30406
|
padding: 1px 6px;
|
|
28337
30407
|
border-radius: var(--radius-full);
|
|
28338
30408
|
margin-left: var(--space-sm);
|
|
@@ -28491,6 +30561,8 @@ var ResultViewer = class extends i4 {
|
|
|
28491
30561
|
this._previousResult = null;
|
|
28492
30562
|
// Recency heat: track when items were last added/updated
|
|
28493
30563
|
this._itemHeatTimestamps = /* @__PURE__ */ new Map();
|
|
30564
|
+
// Audit trail expansion state: track which items have expanded audit trails
|
|
30565
|
+
this._expandedAuditTrails = /* @__PURE__ */ new Set();
|
|
28494
30566
|
// The detected ID field for the current result (shared across diff, animation, warmth)
|
|
28495
30567
|
this._activeIdField = "id";
|
|
28496
30568
|
// Chart.js instance for reactive updates
|
|
@@ -28793,19 +30865,32 @@ var ResultViewer = class extends i4 {
|
|
|
28793
30865
|
/**
|
|
28794
30866
|
* Get the warmth class based on recency heat.
|
|
28795
30867
|
* Reads timestamp from item data first (survives refresh), falls back to in-memory map.
|
|
30868
|
+
* Prioritizes __meta timestamps (most recent), then standard timestamp fields.
|
|
28796
30869
|
*/
|
|
28797
30870
|
_getItemWarmthClass(item) {
|
|
28798
30871
|
const idField = this._activeIdField;
|
|
28799
30872
|
let timestamp;
|
|
28800
30873
|
if (item && typeof item === "object") {
|
|
28801
30874
|
const rec = item;
|
|
28802
|
-
|
|
28803
|
-
|
|
28804
|
-
if (
|
|
28805
|
-
const parsed =
|
|
28806
|
-
if (!isNaN(parsed))
|
|
28807
|
-
|
|
28808
|
-
|
|
30875
|
+
const meta4 = rec.__meta;
|
|
30876
|
+
if (meta4 && typeof meta4 === "object") {
|
|
30877
|
+
if (meta4.modifiedAt) {
|
|
30878
|
+
const parsed = new Date(meta4.modifiedAt).getTime();
|
|
30879
|
+
if (!isNaN(parsed)) timestamp = parsed;
|
|
30880
|
+
} else if (meta4.createdAt) {
|
|
30881
|
+
const parsed = new Date(meta4.createdAt).getTime();
|
|
30882
|
+
if (!isNaN(parsed)) timestamp = parsed;
|
|
30883
|
+
}
|
|
30884
|
+
}
|
|
30885
|
+
if (timestamp === void 0) {
|
|
30886
|
+
for (const field of ResultViewer._TIMESTAMP_FIELDS) {
|
|
30887
|
+
const val = rec[field];
|
|
30888
|
+
if (val !== void 0 && val !== null) {
|
|
30889
|
+
const parsed = typeof val === "number" ? val : new Date(typeof val === "string" ? val : String(val)).getTime();
|
|
30890
|
+
if (!isNaN(parsed)) {
|
|
30891
|
+
timestamp = parsed;
|
|
30892
|
+
break;
|
|
30893
|
+
}
|
|
28809
30894
|
}
|
|
28810
30895
|
}
|
|
28811
30896
|
}
|
|
@@ -29314,7 +31399,8 @@ var ResultViewer = class extends i4 {
|
|
|
29314
31399
|
"tabs",
|
|
29315
31400
|
"accordion",
|
|
29316
31401
|
"stack",
|
|
29317
|
-
"columns"
|
|
31402
|
+
"columns",
|
|
31403
|
+
"qr"
|
|
29318
31404
|
].includes(format)) {
|
|
29319
31405
|
return format;
|
|
29320
31406
|
}
|
|
@@ -29436,10 +31522,46 @@ var ResultViewer = class extends i4 {
|
|
|
29436
31522
|
if (strFields === 1 && numFields >= 2 && keys2.length <= 6) return true;
|
|
29437
31523
|
return false;
|
|
29438
31524
|
}
|
|
31525
|
+
/**
|
|
31526
|
+
* Check if data matches the expected shape for a format.
|
|
31527
|
+
* Returns false when the data clearly doesn't fit, so the renderer
|
|
31528
|
+
* should fall through to the default (JSON) view instead of producing
|
|
31529
|
+
* a broken or nonsensical rendering.
|
|
31530
|
+
*/
|
|
31531
|
+
_matchesFormat(layout, data) {
|
|
31532
|
+
if (data === null || data === void 0) return true;
|
|
31533
|
+
switch (layout) {
|
|
31534
|
+
case "qr":
|
|
31535
|
+
if (typeof data === "string") return true;
|
|
31536
|
+
if (typeof data === "object") {
|
|
31537
|
+
return !!(data.qr || data.url || data.link || data.value);
|
|
31538
|
+
}
|
|
31539
|
+
return false;
|
|
31540
|
+
case "table":
|
|
31541
|
+
return Array.isArray(data) || typeof data === "object" && data !== null;
|
|
31542
|
+
case "metric":
|
|
31543
|
+
case "gauge":
|
|
31544
|
+
return typeof data === "object" && !Array.isArray(data) && (data.value !== void 0 || data.count !== void 0 || data.total !== void 0 || data.current !== void 0);
|
|
31545
|
+
case "chart":
|
|
31546
|
+
return typeof data !== "string";
|
|
31547
|
+
case "mermaid":
|
|
31548
|
+
return typeof data === "string";
|
|
31549
|
+
case "markdown":
|
|
31550
|
+
return typeof data === "string";
|
|
31551
|
+
default:
|
|
31552
|
+
return true;
|
|
31553
|
+
}
|
|
31554
|
+
}
|
|
29439
31555
|
_renderContent(layout, filteredData) {
|
|
29440
31556
|
if (filteredData === null) {
|
|
29441
31557
|
return b2`<div class="empty-state">No matches found</div>`;
|
|
29442
31558
|
}
|
|
31559
|
+
if (filteredData && filteredData._error) {
|
|
31560
|
+
return this._renderErrorCard(filteredData.message || "Unknown error");
|
|
31561
|
+
}
|
|
31562
|
+
if (!this._matchesFormat(layout, filteredData)) {
|
|
31563
|
+
return this._renderJson(filteredData);
|
|
31564
|
+
}
|
|
29443
31565
|
switch (layout) {
|
|
29444
31566
|
case "table":
|
|
29445
31567
|
return this._renderTable(filteredData);
|
|
@@ -29481,6 +31603,8 @@ var ResultViewer = class extends i4 {
|
|
|
29481
31603
|
return this._renderStack(filteredData);
|
|
29482
31604
|
case "columns":
|
|
29483
31605
|
return this._renderColumns(filteredData);
|
|
31606
|
+
case "qr":
|
|
31607
|
+
return this._renderQR(filteredData);
|
|
29484
31608
|
case "mermaid":
|
|
29485
31609
|
return this._renderMermaid(filteredData);
|
|
29486
31610
|
case "json":
|
|
@@ -29723,6 +31847,136 @@ var ResultViewer = class extends i4 {
|
|
|
29723
31847
|
</div>
|
|
29724
31848
|
`
|
|
29725
31849
|
)}
|
|
31850
|
+
${this._renderAuditTrail(data)}
|
|
31851
|
+
`;
|
|
31852
|
+
}
|
|
31853
|
+
/**
|
|
31854
|
+
* Render audit trail from __meta object if present
|
|
31855
|
+
*/
|
|
31856
|
+
_renderAuditTrail(data) {
|
|
31857
|
+
if (!data || typeof data !== "object") return "";
|
|
31858
|
+
const meta4 = data.__meta;
|
|
31859
|
+
if (!meta4 || typeof meta4 !== "object") return "";
|
|
31860
|
+
const idField = this._activeIdField;
|
|
31861
|
+
const itemId = data[idField] ? String(data[idField]) : Math.random().toString(36);
|
|
31862
|
+
const auditKey = `audit-${itemId}`;
|
|
31863
|
+
const isExpanded = this._expandedAuditTrails.has(auditKey);
|
|
31864
|
+
const formatTime = (isoString) => {
|
|
31865
|
+
if (!isoString) return "N/A";
|
|
31866
|
+
const date4 = new Date(isoString);
|
|
31867
|
+
return date4.toLocaleString();
|
|
31868
|
+
};
|
|
31869
|
+
const createdAt = formatTime(meta4.createdAt);
|
|
31870
|
+
const modifiedAt = meta4.modifiedAt ? formatTime(meta4.modifiedAt) : null;
|
|
31871
|
+
return b2`
|
|
31872
|
+
<div
|
|
31873
|
+
style="margin-top: var(--space-md); border-top: 1px solid var(--border-glass); padding-top: var(--space-md);"
|
|
31874
|
+
>
|
|
31875
|
+
<details
|
|
31876
|
+
?open="${isExpanded}"
|
|
31877
|
+
@toggle="${(e8) => {
|
|
31878
|
+
const detail = e8.target;
|
|
31879
|
+
if (detail.open) {
|
|
31880
|
+
this._expandedAuditTrails.add(auditKey);
|
|
31881
|
+
} else {
|
|
31882
|
+
this._expandedAuditTrails.delete(auditKey);
|
|
31883
|
+
}
|
|
31884
|
+
}}"
|
|
31885
|
+
>
|
|
31886
|
+
<summary
|
|
31887
|
+
style="cursor: pointer; font-weight: 500; display: flex; align-items: center; gap: var(--space-sm);"
|
|
31888
|
+
>
|
|
31889
|
+
<span
|
|
31890
|
+
style="display: inline-block; width: 0.5em; height: 0.5em; border-radius: 50%; background: var(--text-secondary); margin-right: var(--space-xs);"
|
|
31891
|
+
></span>
|
|
31892
|
+
Audit Trail
|
|
31893
|
+
${meta4.modifications?.length ? b2`<span style="font-size: 0.85em; color: var(--text-secondary);"
|
|
31894
|
+
>(${meta4.modifications.length} changes)</span
|
|
31895
|
+
>` : ""}
|
|
31896
|
+
</summary>
|
|
31897
|
+
|
|
31898
|
+
<div
|
|
31899
|
+
style="margin-top: var(--space-md); padding: var(--space-sm) var(--space-md); background: var(--bg-secondary); border-radius: var(--radius-sm);"
|
|
31900
|
+
>
|
|
31901
|
+
<table style="width: 100%; font-size: 0.9em;">
|
|
31902
|
+
<tbody>
|
|
31903
|
+
<tr style="border-bottom: 1px solid var(--border-subtle);">
|
|
31904
|
+
<td
|
|
31905
|
+
style="padding: var(--space-xs); color: var(--text-secondary); font-weight: 500;"
|
|
31906
|
+
>
|
|
31907
|
+
Created
|
|
31908
|
+
</td>
|
|
31909
|
+
<td style="padding: var(--space-xs);">${createdAt}</td>
|
|
31910
|
+
${meta4.createdBy ? b2`<td
|
|
31911
|
+
style="padding: var(--space-xs); color: var(--text-secondary); font-size: 0.85em;"
|
|
31912
|
+
>
|
|
31913
|
+
(by: ${meta4.createdBy})
|
|
31914
|
+
</td>` : ""}
|
|
31915
|
+
</tr>
|
|
31916
|
+
${modifiedAt ? b2`
|
|
31917
|
+
<tr style="border-bottom: 1px solid var(--border-subtle);">
|
|
31918
|
+
<td
|
|
31919
|
+
style="padding: var(--space-xs); color: var(--text-secondary); font-weight: 500;"
|
|
31920
|
+
>
|
|
31921
|
+
Modified
|
|
31922
|
+
</td>
|
|
31923
|
+
<td style="padding: var(--space-xs);">${modifiedAt}</td>
|
|
31924
|
+
${meta4.modifiedBy ? b2`<td
|
|
31925
|
+
style="padding: var(--space-xs); color: var(--text-secondary); font-size: 0.85em;"
|
|
31926
|
+
>
|
|
31927
|
+
(by: ${meta4.modifiedBy})
|
|
31928
|
+
</td>` : ""}
|
|
31929
|
+
</tr>
|
|
31930
|
+
` : ""}
|
|
31931
|
+
</tbody>
|
|
31932
|
+
</table>
|
|
31933
|
+
|
|
31934
|
+
${meta4.modifications && Array.isArray(meta4.modifications) && meta4.modifications.length > 0 ? b2`
|
|
31935
|
+
<div style="margin-top: var(--space-md);">
|
|
31936
|
+
<div
|
|
31937
|
+
style="font-weight: 500; margin-bottom: var(--space-sm); color: var(--text-secondary);"
|
|
31938
|
+
>
|
|
31939
|
+
Changes
|
|
31940
|
+
</div>
|
|
31941
|
+
<ul style="list-style: none; padding: 0; margin: 0;">
|
|
31942
|
+
${meta4.modifications.map(
|
|
31943
|
+
(mod, idx) => b2`
|
|
31944
|
+
<li
|
|
31945
|
+
key="${idx}"
|
|
31946
|
+
style="padding: var(--space-xs) var(--space-sm); margin-bottom: var(--space-xs); background: var(--bg-hover); border-left: 3px solid var(--primary); border-radius: 2px; font-size: 0.9em;"
|
|
31947
|
+
>
|
|
31948
|
+
<div style="margin-bottom: 2px;">
|
|
31949
|
+
<span style="font-weight: 500; color: var(--text-primary);"
|
|
31950
|
+
>${mod.field}</span
|
|
31951
|
+
>
|
|
31952
|
+
<span style="color: var(--text-secondary); margin: 0 var(--space-xs);"
|
|
31953
|
+
>→</span
|
|
31954
|
+
>
|
|
31955
|
+
<span style="color: var(--text-secondary); font-size: 0.85em;"
|
|
31956
|
+
>${formatTime(mod.timestamp || (/* @__PURE__ */ new Date()).toISOString())}</span
|
|
31957
|
+
>
|
|
31958
|
+
</div>
|
|
31959
|
+
<div
|
|
31960
|
+
style="font-family: monospace; font-size: 0.85em; color: var(--text-secondary); margin-left: var(--space-sm);"
|
|
31961
|
+
>
|
|
31962
|
+
<span style="color: #d87070;">${JSON.stringify(mod.oldValue)}</span>
|
|
31963
|
+
<span style="margin: 0 4px;">→</span>
|
|
31964
|
+
<span style="color: #7cb342;">${JSON.stringify(mod.newValue)}</span>
|
|
31965
|
+
</div>
|
|
31966
|
+
${mod.modifiedBy ? b2`<div
|
|
31967
|
+
style="font-size: 0.8em; color: var(--text-secondary); margin-top: 2px;"
|
|
31968
|
+
>
|
|
31969
|
+
<em>by: ${mod.modifiedBy}</em>
|
|
31970
|
+
</div>` : ""}
|
|
31971
|
+
</li>
|
|
31972
|
+
`
|
|
31973
|
+
)}
|
|
31974
|
+
</ul>
|
|
31975
|
+
</div>
|
|
31976
|
+
` : ""}
|
|
31977
|
+
</div>
|
|
31978
|
+
</details>
|
|
31979
|
+
</div>
|
|
29726
31980
|
`;
|
|
29727
31981
|
}
|
|
29728
31982
|
/** Returns true for arrays of objects or large nested objects that deserve their own section */
|
|
@@ -30181,6 +32435,163 @@ ${code}</pre>`;
|
|
|
30181
32435
|
style="position: relative; background: ${bgColor}; border-radius: var(--radius-sm); padding: 16px; margin: 16px 0; min-height: 120px;"
|
|
30182
32436
|
></div>`;
|
|
30183
32437
|
}
|
|
32438
|
+
_renderQR(data) {
|
|
32439
|
+
const text = typeof data === "object" && data !== null ? String(data.qr || data.url || data.link || data.value) : String(data);
|
|
32440
|
+
const isUrl = /^https?:\/\//i.test(text);
|
|
32441
|
+
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(text);
|
|
32442
|
+
const isPhone = /^[+]?[\d\s\-().]{7,}$/.test(text.trim());
|
|
32443
|
+
let href = "";
|
|
32444
|
+
let linkLabel = text;
|
|
32445
|
+
if (isUrl) {
|
|
32446
|
+
href = text;
|
|
32447
|
+
try {
|
|
32448
|
+
linkLabel = new URL(text).hostname + new URL(text).pathname;
|
|
32449
|
+
} catch {
|
|
32450
|
+
}
|
|
32451
|
+
} else if (isEmail) {
|
|
32452
|
+
href = `mailto:${text}`;
|
|
32453
|
+
} else if (isPhone) {
|
|
32454
|
+
href = `tel:${text.replace(/[\s\-().]/g, "")}`;
|
|
32455
|
+
}
|
|
32456
|
+
setTimeout(() => {
|
|
32457
|
+
if (this._qrContainer) {
|
|
32458
|
+
this._qrContainer.innerHTML = "";
|
|
32459
|
+
try {
|
|
32460
|
+
const containerWidth = this._qrContainer.clientWidth;
|
|
32461
|
+
const qrSize = Math.max(200, Math.min(containerWidth - 48, 400));
|
|
32462
|
+
new window.QRCode(this._qrContainer, {
|
|
32463
|
+
text,
|
|
32464
|
+
width: qrSize,
|
|
32465
|
+
height: qrSize,
|
|
32466
|
+
correctLevel: window.QRCode?.CorrectLevel?.H,
|
|
32467
|
+
colorDark: "#000000",
|
|
32468
|
+
colorLight: "#ffffff"
|
|
32469
|
+
});
|
|
32470
|
+
} catch (error2) {
|
|
32471
|
+
console.error("Failed to generate QR code:", error2);
|
|
32472
|
+
}
|
|
32473
|
+
}
|
|
32474
|
+
}, 0);
|
|
32475
|
+
const message = typeof data === "object" && data !== null ? data.message : void 0;
|
|
32476
|
+
const extraFields = [];
|
|
32477
|
+
if (typeof data === "object" && data !== null) {
|
|
32478
|
+
for (const [k3, v2] of Object.entries(data)) {
|
|
32479
|
+
if (["url", "link", "value", "message", "port"].includes(k3) || v2 == null || typeof v2 === "object")
|
|
32480
|
+
continue;
|
|
32481
|
+
extraFields.push({ label: k3, value: `${v2}` });
|
|
32482
|
+
}
|
|
32483
|
+
}
|
|
32484
|
+
return b2`<div
|
|
32485
|
+
style="
|
|
32486
|
+
display: flex; flex-direction: column; align-items: center; gap: 0;
|
|
32487
|
+
padding: 0; border-radius: var(--radius-md);
|
|
32488
|
+
border: 1px solid var(--border-glass);
|
|
32489
|
+
background: var(--bg-subtle); overflow: hidden;
|
|
32490
|
+
width: 40%; min-width: 280px; max-width: 480px;
|
|
32491
|
+
margin: 16px auto;
|
|
32492
|
+
"
|
|
32493
|
+
>
|
|
32494
|
+
<div
|
|
32495
|
+
id="qr-container"
|
|
32496
|
+
style="
|
|
32497
|
+
width: 100%; padding: 24px;
|
|
32498
|
+
display: flex; justify-content: center; align-items: center;
|
|
32499
|
+
background: #ffffff; border-radius: var(--radius-md) var(--radius-md) 0 0;
|
|
32500
|
+
"
|
|
32501
|
+
></div>
|
|
32502
|
+
|
|
32503
|
+
<div
|
|
32504
|
+
style="
|
|
32505
|
+
width: 100%; padding: 16px 20px;
|
|
32506
|
+
display: flex; flex-direction: column; gap: 10px;
|
|
32507
|
+
border-top: 1px solid var(--border-glass);
|
|
32508
|
+
"
|
|
32509
|
+
>
|
|
32510
|
+
${message ? b2`<div
|
|
32511
|
+
style="
|
|
32512
|
+
font-size: 0.8rem; color: var(--t-secondary, #a0a0a0);
|
|
32513
|
+
text-align: center; font-weight: 500;
|
|
32514
|
+
"
|
|
32515
|
+
>
|
|
32516
|
+
${message}
|
|
32517
|
+
</div>` : ""}
|
|
32518
|
+
${href ? b2`<div
|
|
32519
|
+
style="display: flex; align-items: center; gap: 10px; justify-content: center;"
|
|
32520
|
+
>
|
|
32521
|
+
<a
|
|
32522
|
+
href="${href}"
|
|
32523
|
+
target="_blank"
|
|
32524
|
+
rel="noopener noreferrer"
|
|
32525
|
+
style="
|
|
32526
|
+
font-size: 0.85rem; color: var(--accent, #3b82f6);
|
|
32527
|
+
text-decoration: none; font-weight: 500;
|
|
32528
|
+
text-align: center; word-break: break-word;
|
|
32529
|
+
"
|
|
32530
|
+
@mouseenter=${(e8) => e8.target.style.textDecoration = "underline"}
|
|
32531
|
+
@mouseleave=${(e8) => e8.target.style.textDecoration = "none"}
|
|
32532
|
+
>${linkLabel}</a
|
|
32533
|
+
>
|
|
32534
|
+
<button
|
|
32535
|
+
title="Copy to clipboard"
|
|
32536
|
+
style="
|
|
32537
|
+
background: var(--bg-subtle, rgba(255,255,255,0.06));
|
|
32538
|
+
border: 1px solid var(--border-glass);
|
|
32539
|
+
border-radius: 6px; padding: 6px 10px; cursor: pointer;
|
|
32540
|
+
color: var(--t-muted); font-size: 0.85rem; flex-shrink: 0;
|
|
32541
|
+
transition: all 0.15s; line-height: 1;
|
|
32542
|
+
"
|
|
32543
|
+
@mouseenter=${(e8) => {
|
|
32544
|
+
e8.target.style.color = "var(--accent, #3b82f6)";
|
|
32545
|
+
e8.target.style.borderColor = "var(--accent, #3b82f6)";
|
|
32546
|
+
}}
|
|
32547
|
+
@mouseleave=${(e8) => {
|
|
32548
|
+
e8.target.style.color = "var(--t-muted)";
|
|
32549
|
+
e8.target.style.borderColor = "var(--border-glass)";
|
|
32550
|
+
}}
|
|
32551
|
+
@click=${(e8) => {
|
|
32552
|
+
void navigator.clipboard.writeText(text);
|
|
32553
|
+
const btn = e8.target;
|
|
32554
|
+
const orig = btn.textContent;
|
|
32555
|
+
btn.textContent = "\u2713 Copied";
|
|
32556
|
+
btn.style.color = "var(--accent, #3b82f6)";
|
|
32557
|
+
setTimeout(() => {
|
|
32558
|
+
btn.textContent = orig;
|
|
32559
|
+
btn.style.color = "var(--t-muted)";
|
|
32560
|
+
}, 1500);
|
|
32561
|
+
}}
|
|
32562
|
+
>
|
|
32563
|
+
Copy
|
|
32564
|
+
</button>
|
|
32565
|
+
</div>` : b2`<div
|
|
32566
|
+
style="
|
|
32567
|
+
font-size: 0.875rem; color: var(--t-muted);
|
|
32568
|
+
text-align: center; word-break: break-all;
|
|
32569
|
+
"
|
|
32570
|
+
>
|
|
32571
|
+
${text}
|
|
32572
|
+
</div>`}
|
|
32573
|
+
${extraFields.length > 0 ? b2`<div
|
|
32574
|
+
style="
|
|
32575
|
+
display: flex; flex-direction: column; gap: 6px;
|
|
32576
|
+
padding-top: 10px; border-top: 1px solid var(--border-glass);
|
|
32577
|
+
font-size: 0.8rem;
|
|
32578
|
+
"
|
|
32579
|
+
>
|
|
32580
|
+
${extraFields.map(
|
|
32581
|
+
(f5) => b2`<div style="display: flex; justify-content: space-between; gap: 12px;">
|
|
32582
|
+
<span style="color: var(--t-muted); text-transform: capitalize;"
|
|
32583
|
+
>${f5.label}</span
|
|
32584
|
+
>
|
|
32585
|
+
<span
|
|
32586
|
+
style="color: var(--t-primary); font-family: var(--font-mono, monospace); word-break: break-all; text-align: right;"
|
|
32587
|
+
>${f5.value}</span
|
|
32588
|
+
>
|
|
32589
|
+
</div>`
|
|
32590
|
+
)}
|
|
32591
|
+
</div>` : ""}
|
|
32592
|
+
</div>
|
|
32593
|
+
</div>`;
|
|
32594
|
+
}
|
|
30184
32595
|
_renderText(data) {
|
|
30185
32596
|
const text = String(data);
|
|
30186
32597
|
if (this._isMermaidString(text)) {
|
|
@@ -30188,6 +32599,37 @@ ${code}</pre>`;
|
|
|
30188
32599
|
}
|
|
30189
32600
|
return this._highlightText(text);
|
|
30190
32601
|
}
|
|
32602
|
+
_renderErrorCard(message) {
|
|
32603
|
+
const lines = message.split("\n").filter((l3) => l3.trim());
|
|
32604
|
+
const messageLine = lines.find((l3) => l3.startsWith("Message: "));
|
|
32605
|
+
const suggestionLine = lines.find((l3) => l3.startsWith("Suggestion: "));
|
|
32606
|
+
const displayMessage = messageLine ? messageLine.replace("Message: ", "") : lines[0]?.replace(/^❌\s*/, "") || message;
|
|
32607
|
+
const suggestion = suggestionLine ? suggestionLine.replace("Suggestion: ", "") : "";
|
|
32608
|
+
return b2`<div
|
|
32609
|
+
style="
|
|
32610
|
+
padding: 20px; border-radius: var(--radius-md);
|
|
32611
|
+
border: 1px solid color-mix(in srgb, #ef4444 30%, transparent);
|
|
32612
|
+
background: color-mix(in srgb, #ef4444 5%, var(--bg-subtle));
|
|
32613
|
+
display: flex; flex-direction: column; gap: 8px;
|
|
32614
|
+
margin: 8px 0;
|
|
32615
|
+
"
|
|
32616
|
+
>
|
|
32617
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
32618
|
+
<span style="font-size: 1.1rem;">⚠️</span>
|
|
32619
|
+
<span style="font-weight: 600; color: var(--t-primary); font-size: 0.95rem;">
|
|
32620
|
+
${displayMessage}
|
|
32621
|
+
</span>
|
|
32622
|
+
</div>
|
|
32623
|
+
${suggestion ? b2`<div
|
|
32624
|
+
style="
|
|
32625
|
+
font-size: 0.85rem; color: var(--t-secondary);
|
|
32626
|
+
padding-left: 28px;
|
|
32627
|
+
"
|
|
32628
|
+
>
|
|
32629
|
+
${suggestion}
|
|
32630
|
+
</div>` : ""}
|
|
32631
|
+
</div>`;
|
|
32632
|
+
}
|
|
30191
32633
|
_renderJson(data) {
|
|
30192
32634
|
const jsonStr = JSON.stringify(data, null, 2);
|
|
30193
32635
|
const highlighted = jsonStr.replace(
|
|
@@ -31440,7 +33882,7 @@ ResultViewer.styles = [
|
|
|
31440
33882
|
}
|
|
31441
33883
|
|
|
31442
33884
|
button:hover {
|
|
31443
|
-
background:
|
|
33885
|
+
background: var(--bg-glass);
|
|
31444
33886
|
color: var(--t-primary);
|
|
31445
33887
|
}
|
|
31446
33888
|
|
|
@@ -31591,7 +34033,7 @@ ResultViewer.styles = [
|
|
|
31591
34033
|
}
|
|
31592
34034
|
|
|
31593
34035
|
.smart-table tr:hover td {
|
|
31594
|
-
background:
|
|
34036
|
+
background: var(--bg-glass);
|
|
31595
34037
|
}
|
|
31596
34038
|
|
|
31597
34039
|
/* Key-Value Table (single object) */
|
|
@@ -32278,7 +34720,7 @@ ResultViewer.styles = [
|
|
|
32278
34720
|
}
|
|
32279
34721
|
|
|
32280
34722
|
.tree-item:hover {
|
|
32281
|
-
background:
|
|
34723
|
+
background: var(--bg-glass);
|
|
32282
34724
|
}
|
|
32283
34725
|
|
|
32284
34726
|
.tree-toggle {
|
|
@@ -32307,16 +34749,16 @@ ResultViewer.styles = [
|
|
|
32307
34749
|
}
|
|
32308
34750
|
|
|
32309
34751
|
.tree-value.string {
|
|
32310
|
-
color:
|
|
34752
|
+
color: var(--syntax-string);
|
|
32311
34753
|
}
|
|
32312
34754
|
.tree-value.number {
|
|
32313
|
-
color:
|
|
34755
|
+
color: var(--syntax-number);
|
|
32314
34756
|
}
|
|
32315
34757
|
.tree-value.boolean {
|
|
32316
|
-
color:
|
|
34758
|
+
color: var(--syntax-boolean);
|
|
32317
34759
|
}
|
|
32318
34760
|
.tree-value.null {
|
|
32319
|
-
color:
|
|
34761
|
+
color: var(--syntax-null);
|
|
32320
34762
|
}
|
|
32321
34763
|
|
|
32322
34764
|
.tree-type {
|
|
@@ -32578,9 +35020,9 @@ ResultViewer.styles = [
|
|
|
32578
35020
|
}
|
|
32579
35021
|
|
|
32580
35022
|
.expand-btn:hover {
|
|
32581
|
-
background: var(--primary);
|
|
35023
|
+
background: var(--accent-primary);
|
|
32582
35024
|
color: white;
|
|
32583
|
-
border-color: var(--primary);
|
|
35025
|
+
border-color: var(--accent-primary);
|
|
32584
35026
|
}
|
|
32585
35027
|
|
|
32586
35028
|
/* Markdown items (array rendering with filter transitions) */
|
|
@@ -32818,13 +35260,13 @@ ResultViewer.styles = [
|
|
|
32818
35260
|
}
|
|
32819
35261
|
|
|
32820
35262
|
.metric-delta.up {
|
|
32821
|
-
color:
|
|
32822
|
-
background:
|
|
35263
|
+
color: var(--color-success);
|
|
35264
|
+
background: var(--color-success-bg);
|
|
32823
35265
|
}
|
|
32824
35266
|
|
|
32825
35267
|
.metric-delta.down {
|
|
32826
|
-
color:
|
|
32827
|
-
background:
|
|
35268
|
+
color: var(--color-error);
|
|
35269
|
+
background: var(--color-error-bg);
|
|
32828
35270
|
}
|
|
32829
35271
|
|
|
32830
35272
|
.metric-delta.neutral {
|
|
@@ -32959,7 +35401,7 @@ ResultViewer.styles = [
|
|
|
32959
35401
|
|
|
32960
35402
|
.timeline-description {
|
|
32961
35403
|
font-size: var(--text-md);
|
|
32962
|
-
color: var(--t-
|
|
35404
|
+
color: var(--t-muted);
|
|
32963
35405
|
margin-top: 2px;
|
|
32964
35406
|
line-height: 1.4;
|
|
32965
35407
|
}
|
|
@@ -33106,7 +35548,7 @@ ResultViewer.styles = [
|
|
|
33106
35548
|
justify-content: space-between;
|
|
33107
35549
|
padding: 4px 0;
|
|
33108
35550
|
font-size: var(--text-md);
|
|
33109
|
-
color: var(--t-
|
|
35551
|
+
color: var(--t-muted);
|
|
33110
35552
|
}
|
|
33111
35553
|
|
|
33112
35554
|
.cart-summary-row.total {
|
|
@@ -33384,6 +35826,9 @@ __decorateClass([
|
|
|
33384
35826
|
__decorateClass([
|
|
33385
35827
|
r5()
|
|
33386
35828
|
], ResultViewer.prototype, "_internalResult", 2);
|
|
35829
|
+
__decorateClass([
|
|
35830
|
+
e7("#qr-container")
|
|
35831
|
+
], ResultViewer.prototype, "_qrContainer", 2);
|
|
33387
35832
|
__decorateClass([
|
|
33388
35833
|
n4({ type: String })
|
|
33389
35834
|
], ResultViewer.prototype, "collectionProperty", 2);
|
|
@@ -66297,18 +68742,18 @@ var ViewState = class {
|
|
|
66297
68742
|
let viewFrom, viewTo;
|
|
66298
68743
|
if (wrapping) {
|
|
66299
68744
|
let marginHeight = margin / this.heightOracle.lineLength * this.heightOracle.lineHeight;
|
|
66300
|
-
let top2,
|
|
68745
|
+
let top2, bot2;
|
|
66301
68746
|
if (target != null) {
|
|
66302
68747
|
let targetFrac = findFraction(structure, target);
|
|
66303
68748
|
let spaceFrac = ((this.visibleBottom - this.visibleTop) / 2 + marginHeight) / line.height;
|
|
66304
68749
|
top2 = targetFrac - spaceFrac;
|
|
66305
|
-
|
|
68750
|
+
bot2 = targetFrac + spaceFrac;
|
|
66306
68751
|
} else {
|
|
66307
68752
|
top2 = (this.visibleTop - line.top - marginHeight) / line.height;
|
|
66308
|
-
|
|
68753
|
+
bot2 = (this.visibleBottom - line.top + marginHeight) / line.height;
|
|
66309
68754
|
}
|
|
66310
68755
|
viewFrom = findPosition(structure, top2);
|
|
66311
|
-
viewTo = findPosition(structure,
|
|
68756
|
+
viewTo = findPosition(structure, bot2);
|
|
66312
68757
|
} else {
|
|
66313
68758
|
let totalWidth = structure.total * this.heightOracle.charWidth;
|
|
66314
68759
|
let marginWidth = margin * this.heightOracle.charWidth;
|
|
@@ -83453,9 +85898,13 @@ var ElicitationModal = class extends i4 {
|
|
|
83453
85898
|
min="${min}"
|
|
83454
85899
|
max="${max}"
|
|
83455
85900
|
step="${step}"
|
|
85901
|
+
style="${this._sliderFillStyle(Number(currentValue), min, max)}"
|
|
83456
85902
|
.value=${String(currentValue)}
|
|
83457
85903
|
@input=${(e8) => {
|
|
83458
|
-
|
|
85904
|
+
const el2 = e8.target;
|
|
85905
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step);
|
|
85906
|
+
el2.style.cssText = this._sliderFillStyle(v2, min, max);
|
|
85907
|
+
this._inputValue = v2;
|
|
83459
85908
|
}}
|
|
83460
85909
|
/>
|
|
83461
85910
|
<input
|
|
@@ -83466,7 +85915,15 @@ var ElicitationModal = class extends i4 {
|
|
|
83466
85915
|
step="${step}"
|
|
83467
85916
|
.value=${String(currentValue)}
|
|
83468
85917
|
@input=${(e8) => {
|
|
83469
|
-
|
|
85918
|
+
const raw = e8.target.value;
|
|
85919
|
+
if (raw === "" || raw === "-") return;
|
|
85920
|
+
this._inputValue = Number(raw);
|
|
85921
|
+
}}
|
|
85922
|
+
@change=${(e8) => {
|
|
85923
|
+
const el2 = e8.target;
|
|
85924
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step);
|
|
85925
|
+
el2.value = String(v2);
|
|
85926
|
+
this._inputValue = v2;
|
|
83470
85927
|
}}
|
|
83471
85928
|
@keydown=${(e8) => this._handleKeydown(e8)}
|
|
83472
85929
|
autofocus
|
|
@@ -83710,9 +86167,13 @@ var ElicitationModal = class extends i4 {
|
|
|
83710
86167
|
min="${min}"
|
|
83711
86168
|
max="${max}"
|
|
83712
86169
|
step="${step}"
|
|
86170
|
+
style="${this._sliderFillStyle(Number(currentValue), min, max)}"
|
|
83713
86171
|
.value=${String(currentValue)}
|
|
83714
86172
|
@input=${(e8) => {
|
|
83715
|
-
|
|
86173
|
+
const el2 = e8.target;
|
|
86174
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step);
|
|
86175
|
+
el2.style.cssText = this._sliderFillStyle(v2, min, max);
|
|
86176
|
+
this._updateFormValue(field.name, v2);
|
|
83716
86177
|
}}
|
|
83717
86178
|
/>
|
|
83718
86179
|
<input
|
|
@@ -83723,7 +86184,15 @@ var ElicitationModal = class extends i4 {
|
|
|
83723
86184
|
step="${step}"
|
|
83724
86185
|
.value=${String(currentValue)}
|
|
83725
86186
|
@input=${(e8) => {
|
|
83726
|
-
|
|
86187
|
+
const raw = e8.target.value;
|
|
86188
|
+
if (raw === "" || raw === "-") return;
|
|
86189
|
+
this._updateFormValue(field.name, Number(raw));
|
|
86190
|
+
}}
|
|
86191
|
+
@change=${(e8) => {
|
|
86192
|
+
const el2 = e8.target;
|
|
86193
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step);
|
|
86194
|
+
el2.value = String(v2);
|
|
86195
|
+
this._updateFormValue(field.name, v2);
|
|
83727
86196
|
}}
|
|
83728
86197
|
/>
|
|
83729
86198
|
</div>
|
|
@@ -83744,6 +86213,23 @@ var ElicitationModal = class extends i4 {
|
|
|
83744
86213
|
/>
|
|
83745
86214
|
`;
|
|
83746
86215
|
}
|
|
86216
|
+
_sliderFillStyle(value, min, max) {
|
|
86217
|
+
const pct = max > min ? (value - min) / (max - min) * 100 : 0;
|
|
86218
|
+
return `background: linear-gradient(to right, var(--accent-primary) ${pct}%, var(--border-glass) ${pct}%)`;
|
|
86219
|
+
}
|
|
86220
|
+
/** Clamp to [min, max] and round to nearest step (integer-safe). */
|
|
86221
|
+
_sanitizeSliderValue(raw, min, max, step) {
|
|
86222
|
+
let v2 = Number.isFinite(raw) ? raw : min;
|
|
86223
|
+
v2 = Math.min(max, Math.max(min, v2));
|
|
86224
|
+
if (step > 0) {
|
|
86225
|
+
v2 = min + Math.round((v2 - min) / step) * step;
|
|
86226
|
+
if (v2 > max) v2 = max;
|
|
86227
|
+
}
|
|
86228
|
+
if (Number.isInteger(step) && step >= 1) {
|
|
86229
|
+
v2 = Math.round(v2);
|
|
86230
|
+
}
|
|
86231
|
+
return v2;
|
|
86232
|
+
}
|
|
83747
86233
|
_updateFormValue(name2, value) {
|
|
83748
86234
|
this._formValues = { ...this._formValues, [name2]: value };
|
|
83749
86235
|
}
|
|
@@ -83868,11 +86354,19 @@ ElicitationModal.styles = [
|
|
|
83868
86354
|
color: white;
|
|
83869
86355
|
}
|
|
83870
86356
|
|
|
86357
|
+
.btn-success:hover {
|
|
86358
|
+
filter: brightness(1.1);
|
|
86359
|
+
}
|
|
86360
|
+
|
|
83871
86361
|
.btn-danger {
|
|
83872
86362
|
background: var(--color-error);
|
|
83873
86363
|
color: white;
|
|
83874
86364
|
}
|
|
83875
86365
|
|
|
86366
|
+
.btn-danger:hover {
|
|
86367
|
+
filter: brightness(1.1);
|
|
86368
|
+
}
|
|
86369
|
+
|
|
83876
86370
|
/* Confirm buttons */
|
|
83877
86371
|
.confirm-actions {
|
|
83878
86372
|
display: flex;
|
|
@@ -83982,7 +86476,7 @@ ElicitationModal.styles = [
|
|
|
83982
86476
|
.slider-group {
|
|
83983
86477
|
display: flex;
|
|
83984
86478
|
flex-direction: column;
|
|
83985
|
-
gap:
|
|
86479
|
+
gap: 4px;
|
|
83986
86480
|
}
|
|
83987
86481
|
|
|
83988
86482
|
.slider-row {
|
|
@@ -83993,47 +86487,104 @@ ElicitationModal.styles = [
|
|
|
83993
86487
|
|
|
83994
86488
|
.slider-row input[type='range'] {
|
|
83995
86489
|
flex: 1;
|
|
83996
|
-
height:
|
|
83997
|
-
|
|
83998
|
-
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
83999
|
-
border-radius: 3px;
|
|
86490
|
+
height: 4px;
|
|
86491
|
+
border-radius: var(--radius-full, 9999px);
|
|
84000
86492
|
-webkit-appearance: none;
|
|
84001
86493
|
cursor: pointer;
|
|
84002
86494
|
margin: 8px 0;
|
|
86495
|
+
border: none;
|
|
86496
|
+
outline: none;
|
|
86497
|
+
background: var(--border-glass);
|
|
84003
86498
|
}
|
|
84004
86499
|
|
|
84005
86500
|
.slider-row input[type='range']::-webkit-slider-thumb {
|
|
84006
86501
|
-webkit-appearance: none;
|
|
84007
|
-
width:
|
|
84008
|
-
height:
|
|
86502
|
+
width: 16px;
|
|
86503
|
+
height: 16px;
|
|
84009
86504
|
background: var(--accent-primary);
|
|
86505
|
+
border: 2px solid var(--bg-panel, var(--bg-glass));
|
|
84010
86506
|
border-radius: 50%;
|
|
84011
86507
|
cursor: pointer;
|
|
84012
|
-
box-shadow:
|
|
86508
|
+
box-shadow:
|
|
86509
|
+
0 0 0 2px var(--accent-primary),
|
|
86510
|
+
0 1px 4px rgba(0, 0, 0, 0.3);
|
|
86511
|
+
transition:
|
|
86512
|
+
box-shadow 0.15s ease,
|
|
86513
|
+
transform 0.15s ease;
|
|
86514
|
+
}
|
|
86515
|
+
|
|
86516
|
+
.slider-row input[type='range']::-webkit-slider-thumb:hover {
|
|
86517
|
+
box-shadow:
|
|
86518
|
+
0 0 0 3px var(--accent-primary),
|
|
86519
|
+
0 0 8px var(--glow-primary);
|
|
86520
|
+
transform: scale(1.1);
|
|
86521
|
+
}
|
|
86522
|
+
|
|
86523
|
+
.slider-row input[type='range']:active::-webkit-slider-thumb {
|
|
86524
|
+
transform: scale(0.95);
|
|
84013
86525
|
}
|
|
84014
86526
|
|
|
84015
86527
|
.slider-row input[type='range']::-moz-range-track {
|
|
84016
|
-
height:
|
|
84017
|
-
background:
|
|
84018
|
-
border-radius:
|
|
84019
|
-
border:
|
|
86528
|
+
height: 4px;
|
|
86529
|
+
background: var(--border-glass);
|
|
86530
|
+
border-radius: var(--radius-full, 9999px);
|
|
86531
|
+
border: none;
|
|
86532
|
+
}
|
|
86533
|
+
|
|
86534
|
+
.slider-row input[type='range']::-moz-range-progress {
|
|
86535
|
+
height: 4px;
|
|
86536
|
+
background: var(--accent-primary);
|
|
86537
|
+
border-radius: var(--radius-full, 9999px);
|
|
84020
86538
|
}
|
|
84021
86539
|
|
|
84022
86540
|
.slider-row input[type='range']::-moz-range-thumb {
|
|
84023
|
-
width:
|
|
84024
|
-
height:
|
|
86541
|
+
width: 12px;
|
|
86542
|
+
height: 12px;
|
|
84025
86543
|
background: var(--accent-primary);
|
|
86544
|
+
border: 2px solid var(--bg-panel, var(--bg-glass));
|
|
84026
86545
|
border-radius: 50%;
|
|
84027
86546
|
cursor: pointer;
|
|
84028
|
-
|
|
84029
|
-
|
|
86547
|
+
box-shadow:
|
|
86548
|
+
0 0 0 2px var(--accent-primary),
|
|
86549
|
+
0 1px 4px rgba(0, 0, 0, 0.3);
|
|
86550
|
+
transition:
|
|
86551
|
+
box-shadow 0.15s ease,
|
|
86552
|
+
transform 0.15s ease;
|
|
86553
|
+
}
|
|
86554
|
+
|
|
86555
|
+
.slider-row input[type='range']::-moz-range-thumb:hover {
|
|
86556
|
+
box-shadow:
|
|
86557
|
+
0 0 0 3px var(--accent-primary),
|
|
86558
|
+
0 0 8px var(--glow-primary);
|
|
84030
86559
|
}
|
|
84031
86560
|
|
|
84032
86561
|
.slider-number-input {
|
|
84033
|
-
width:
|
|
84034
|
-
text-align:
|
|
86562
|
+
width: 64px;
|
|
86563
|
+
text-align: center;
|
|
84035
86564
|
font-size: var(--text-sm);
|
|
84036
|
-
|
|
86565
|
+
font-weight: 500;
|
|
86566
|
+
font-variant-numeric: tabular-nums;
|
|
86567
|
+
padding: 4px 6px;
|
|
86568
|
+
background: var(--bg-glass);
|
|
86569
|
+
border: 1px solid var(--border-glass) !important;
|
|
86570
|
+
border-radius: var(--radius-sm);
|
|
86571
|
+
color: var(--t-primary);
|
|
86572
|
+
-moz-appearance: textfield;
|
|
86573
|
+
transition:
|
|
86574
|
+
border-color 0.15s ease,
|
|
86575
|
+
box-shadow 0.15s ease;
|
|
86576
|
+
}
|
|
86577
|
+
|
|
86578
|
+
.slider-number-input::-webkit-outer-spin-button,
|
|
86579
|
+
.slider-number-input::-webkit-inner-spin-button {
|
|
86580
|
+
-webkit-appearance: none;
|
|
86581
|
+
margin: 0;
|
|
86582
|
+
}
|
|
86583
|
+
|
|
86584
|
+
.slider-number-input:focus-visible {
|
|
86585
|
+
outline: none;
|
|
86586
|
+
border-color: var(--accent-primary) !important;
|
|
86587
|
+
box-shadow: 0 0 0 2px var(--glow-primary);
|
|
84037
86588
|
}
|
|
84038
86589
|
|
|
84039
86590
|
.range-labels {
|
|
@@ -84092,7 +86643,13 @@ ElicitationModal.styles = [
|
|
|
84092
86643
|
background: var(--bg-glass-strong);
|
|
84093
86644
|
border-radius: 12px;
|
|
84094
86645
|
cursor: pointer;
|
|
84095
|
-
transition:
|
|
86646
|
+
transition:
|
|
86647
|
+
background 0.2s,
|
|
86648
|
+
box-shadow 0.2s;
|
|
86649
|
+
}
|
|
86650
|
+
|
|
86651
|
+
.toggle-track:hover {
|
|
86652
|
+
background: var(--bg-glass);
|
|
84096
86653
|
}
|
|
84097
86654
|
|
|
84098
86655
|
.toggle-track::after {
|
|
@@ -84111,6 +86668,14 @@ ElicitationModal.styles = [
|
|
|
84111
86668
|
background: var(--accent-primary);
|
|
84112
86669
|
}
|
|
84113
86670
|
|
|
86671
|
+
.toggle-switch input:checked + .toggle-track:hover {
|
|
86672
|
+
background: var(--accent-secondary);
|
|
86673
|
+
}
|
|
86674
|
+
|
|
86675
|
+
.toggle-switch input:focus-visible + .toggle-track {
|
|
86676
|
+
box-shadow: 0 0 0 2px var(--glow-primary);
|
|
86677
|
+
}
|
|
86678
|
+
|
|
84114
86679
|
.toggle-switch input:checked + .toggle-track::after {
|
|
84115
86680
|
transform: translateX(20px);
|
|
84116
86681
|
}
|
|
@@ -84246,7 +86811,7 @@ var OverflowMenu = class extends i4 {
|
|
|
84246
86811
|
return b2`
|
|
84247
86812
|
<button
|
|
84248
86813
|
class="trigger"
|
|
84249
|
-
@click=${() => this._toggle()}
|
|
86814
|
+
@click=${(e8) => this._toggle(e8)}
|
|
84250
86815
|
title="More actions"
|
|
84251
86816
|
aria-label="More actions"
|
|
84252
86817
|
>
|
|
@@ -85753,7 +88318,7 @@ ContextBar.styles = [
|
|
|
85753
88318
|
backdrop-filter: blur(20px);
|
|
85754
88319
|
border: 1px solid var(--border-glass);
|
|
85755
88320
|
border-radius: var(--radius-md);
|
|
85756
|
-
box-shadow:
|
|
88321
|
+
box-shadow: var(--shadow-lg);
|
|
85757
88322
|
padding: 4px;
|
|
85758
88323
|
z-index: 100;
|
|
85759
88324
|
}
|
|
@@ -85764,7 +88329,7 @@ ContextBar.styles = [
|
|
|
85764
88329
|
padding: 6px 10px;
|
|
85765
88330
|
border: none;
|
|
85766
88331
|
background: none;
|
|
85767
|
-
color: var(--t-
|
|
88332
|
+
color: var(--t-muted);
|
|
85768
88333
|
font-size: var(--text-sm);
|
|
85769
88334
|
font-family: inherit;
|
|
85770
88335
|
text-align: left;
|
|
@@ -85790,7 +88355,7 @@ ContextBar.styles = [
|
|
|
85790
88355
|
font-size: var(--text-2xs);
|
|
85791
88356
|
font-weight: 700;
|
|
85792
88357
|
letter-spacing: 0.08em;
|
|
85793
|
-
color:
|
|
88358
|
+
color: var(--color-success);
|
|
85794
88359
|
text-transform: uppercase;
|
|
85795
88360
|
margin-left: auto;
|
|
85796
88361
|
}
|
|
@@ -85799,8 +88364,8 @@ ContextBar.styles = [
|
|
|
85799
88364
|
width: 6px;
|
|
85800
88365
|
height: 6px;
|
|
85801
88366
|
border-radius: 50%;
|
|
85802
|
-
background:
|
|
85803
|
-
box-shadow: 0 0 6px 2px
|
|
88367
|
+
background: var(--color-success);
|
|
88368
|
+
box-shadow: 0 0 6px 2px var(--color-success-glow);
|
|
85804
88369
|
animation: live-pulse 2s ease-in-out infinite;
|
|
85805
88370
|
}
|
|
85806
88371
|
|
|
@@ -85808,11 +88373,11 @@ ContextBar.styles = [
|
|
|
85808
88373
|
0%,
|
|
85809
88374
|
100% {
|
|
85810
88375
|
opacity: 1;
|
|
85811
|
-
box-shadow: 0 0 6px 2px
|
|
88376
|
+
box-shadow: 0 0 6px 2px var(--color-success-glow);
|
|
85812
88377
|
}
|
|
85813
88378
|
50% {
|
|
85814
88379
|
opacity: 0.5;
|
|
85815
|
-
box-shadow: 0 0 3px 1px
|
|
88380
|
+
box-shadow: 0 0 3px 1px var(--color-success-glow);
|
|
85816
88381
|
}
|
|
85817
88382
|
}
|
|
85818
88383
|
|