@portel/photon 1.10.0 → 1.12.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 +874 -20
- 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 +16 -2
- package/dist/auto-ui/streamable-http-transport.js.map +1 -1
- package/dist/auto-ui/types.d.ts +1 -1
- package/dist/auto-ui/types.d.ts.map +1 -1
- package/dist/auto-ui/types.js.map +1 -1
- package/dist/beam.bundle.js +2836 -357
- package/dist/beam.bundle.js.map +4 -4
- 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/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/server.js +303 -6
- package/dist/daemon/server.js.map +1 -1
- package/dist/loader.d.ts +21 -0
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +277 -0
- package/dist/loader.js.map +1 -1
- package/dist/photon-cli-runner.d.ts.map +1 -1
- package/dist/photon-cli-runner.js +21 -1
- 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.map +1 -1
- package/dist/server.js +27 -2
- 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/package.json +22 -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 {
|
|
@@ -15822,45 +15826,10 @@ var iconPaths = {
|
|
|
15822
15826
|
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
15827
|
expand: `<path d="M15 3h6v6"/><path d="m21 3-7 7"/><path d="m3 21 7-7"/><path d="M9 21H3v-6"/>`,
|
|
15824
15828
|
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"
|
|
15829
|
+
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"/>`,
|
|
15830
|
+
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
15831
|
};
|
|
15827
15832
|
|
|
15828
|
-
// src/auto-ui/frontend/utils/format-label.ts
|
|
15829
|
-
function formatLabel(name2) {
|
|
15830
|
-
if (!name2) return name2;
|
|
15831
|
-
let cleaned = name2.replace(/^_+/, "");
|
|
15832
|
-
let spaced = cleaned.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2");
|
|
15833
|
-
spaced = spaced.replace(/[_-]+/g, " ");
|
|
15834
|
-
let result = spaced.split(/\s+/).map((word) => {
|
|
15835
|
-
if (!word) return "";
|
|
15836
|
-
const upper = word.toUpperCase();
|
|
15837
|
-
if ([
|
|
15838
|
-
"AI",
|
|
15839
|
-
"ID",
|
|
15840
|
-
"IDS",
|
|
15841
|
-
"URL",
|
|
15842
|
-
"API",
|
|
15843
|
-
"UI",
|
|
15844
|
-
"IP",
|
|
15845
|
-
"HTTP",
|
|
15846
|
-
"HTTPS",
|
|
15847
|
-
"JSON",
|
|
15848
|
-
"XML",
|
|
15849
|
-
"HTML",
|
|
15850
|
-
"CSS",
|
|
15851
|
-
"SQL",
|
|
15852
|
-
"MCP",
|
|
15853
|
-
"SSH",
|
|
15854
|
-
"CLI"
|
|
15855
|
-
].includes(upper)) {
|
|
15856
|
-
if (upper === "IDS") return "IDs";
|
|
15857
|
-
return upper;
|
|
15858
|
-
}
|
|
15859
|
-
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
15860
|
-
}).join(" ");
|
|
15861
|
-
return result;
|
|
15862
|
-
}
|
|
15863
|
-
|
|
15864
15833
|
// node_modules/@portel/photon-core/dist/design-system/oklch.js
|
|
15865
15834
|
function oklchToSRGB(L3, C3, H3) {
|
|
15866
15835
|
const hRad = H3 * Math.PI / 180;
|
|
@@ -16545,7 +16514,8 @@ var buttons = i`
|
|
|
16545
16514
|
color: var(--t-primary);
|
|
16546
16515
|
}
|
|
16547
16516
|
|
|
16548
|
-
.btn-primary:disabled
|
|
16517
|
+
.btn-primary:disabled,
|
|
16518
|
+
.btn-secondary:disabled {
|
|
16549
16519
|
opacity: 0.6;
|
|
16550
16520
|
cursor: not-allowed;
|
|
16551
16521
|
transform: none;
|
|
@@ -16585,7 +16555,21 @@ var forms = i`
|
|
|
16585
16555
|
padding: var(--space-sm);
|
|
16586
16556
|
border-radius: var(--radius-sm);
|
|
16587
16557
|
font-family: var(--font-sans);
|
|
16558
|
+
font-size: var(--text-md);
|
|
16588
16559
|
box-sizing: border-box;
|
|
16560
|
+
transition:
|
|
16561
|
+
border-color 0.15s ease,
|
|
16562
|
+
box-shadow 0.15s ease;
|
|
16563
|
+
}
|
|
16564
|
+
|
|
16565
|
+
input:hover,
|
|
16566
|
+
textarea:hover,
|
|
16567
|
+
select:hover {
|
|
16568
|
+
border-color: var(--accent-secondary);
|
|
16569
|
+
}
|
|
16570
|
+
|
|
16571
|
+
textarea {
|
|
16572
|
+
resize: vertical;
|
|
16589
16573
|
}
|
|
16590
16574
|
|
|
16591
16575
|
::placeholder {
|
|
@@ -16601,12 +16585,12 @@ var forms = i`
|
|
|
16601
16585
|
display: block;
|
|
16602
16586
|
margin-bottom: var(--space-xs);
|
|
16603
16587
|
font-weight: 500;
|
|
16604
|
-
font-size:
|
|
16588
|
+
font-size: var(--text-md);
|
|
16605
16589
|
}
|
|
16606
16590
|
|
|
16607
16591
|
.error-text {
|
|
16608
16592
|
color: var(--color-error);
|
|
16609
|
-
font-size:
|
|
16593
|
+
font-size: var(--text-xs);
|
|
16610
16594
|
margin-top: var(--space-xs);
|
|
16611
16595
|
}
|
|
16612
16596
|
|
|
@@ -16626,7 +16610,7 @@ var forms = i`
|
|
|
16626
16610
|
var badges = i`
|
|
16627
16611
|
.type-badge {
|
|
16628
16612
|
display: inline-block;
|
|
16629
|
-
font-size:
|
|
16613
|
+
font-size: var(--text-2xs);
|
|
16630
16614
|
font-weight: 600;
|
|
16631
16615
|
text-transform: uppercase;
|
|
16632
16616
|
letter-spacing: 0.04em;
|
|
@@ -16660,7 +16644,7 @@ var badges = i`
|
|
|
16660
16644
|
}
|
|
16661
16645
|
|
|
16662
16646
|
.param-tag {
|
|
16663
|
-
font-size:
|
|
16647
|
+
font-size: var(--text-2xs);
|
|
16664
16648
|
padding: 1px 6px;
|
|
16665
16649
|
border-radius: var(--radius-xs);
|
|
16666
16650
|
background: var(--param-tag-bg, hsla(220, 10%, 80%, 0.08));
|
|
@@ -17236,6 +17220,307 @@ function loadSavedThemeConfig() {
|
|
|
17236
17220
|
return null;
|
|
17237
17221
|
}
|
|
17238
17222
|
|
|
17223
|
+
// src/auto-ui/frontend/services/photon-instance-manager.ts
|
|
17224
|
+
var SimpleEventEmitter = class {
|
|
17225
|
+
constructor() {
|
|
17226
|
+
this._listeners = /* @__PURE__ */ new Map();
|
|
17227
|
+
}
|
|
17228
|
+
on(event, callback2) {
|
|
17229
|
+
if (!this._listeners.has(event)) {
|
|
17230
|
+
this._listeners.set(event, /* @__PURE__ */ new Set());
|
|
17231
|
+
}
|
|
17232
|
+
this._listeners.get(event).add(callback2);
|
|
17233
|
+
}
|
|
17234
|
+
off(event, callback2) {
|
|
17235
|
+
const listeners = this._listeners.get(event);
|
|
17236
|
+
if (listeners) {
|
|
17237
|
+
listeners.delete(callback2);
|
|
17238
|
+
}
|
|
17239
|
+
}
|
|
17240
|
+
emit(event, ...args) {
|
|
17241
|
+
const listeners = this._listeners.get(event);
|
|
17242
|
+
if (listeners) {
|
|
17243
|
+
for (const callback2 of listeners) {
|
|
17244
|
+
callback2(...args);
|
|
17245
|
+
}
|
|
17246
|
+
}
|
|
17247
|
+
}
|
|
17248
|
+
};
|
|
17249
|
+
var PhotonSessionProxy = class extends SimpleEventEmitter {
|
|
17250
|
+
constructor(options) {
|
|
17251
|
+
super();
|
|
17252
|
+
this._paginationState = /* @__PURE__ */ new Map();
|
|
17253
|
+
this._pendingPatches = [];
|
|
17254
|
+
this._isApplyingPatches = false;
|
|
17255
|
+
this._name = options.name;
|
|
17256
|
+
this._state = { ...options.initialState };
|
|
17257
|
+
}
|
|
17258
|
+
/**
|
|
17259
|
+
* Get the photon name
|
|
17260
|
+
*/
|
|
17261
|
+
get name() {
|
|
17262
|
+
return this._name;
|
|
17263
|
+
}
|
|
17264
|
+
/**
|
|
17265
|
+
* Get current state
|
|
17266
|
+
*/
|
|
17267
|
+
get state() {
|
|
17268
|
+
return this._state;
|
|
17269
|
+
}
|
|
17270
|
+
/**
|
|
17271
|
+
* Apply JSON Patch array to instance state
|
|
17272
|
+
* Patches from: https://tools.ietf.org/html/rfc6902
|
|
17273
|
+
*/
|
|
17274
|
+
applyPatches(patches) {
|
|
17275
|
+
if (!Array.isArray(patches) || patches.length === 0) {
|
|
17276
|
+
return;
|
|
17277
|
+
}
|
|
17278
|
+
this._pendingPatches.push(...patches);
|
|
17279
|
+
if (!this._isApplyingPatches) {
|
|
17280
|
+
this._isApplyingPatches = true;
|
|
17281
|
+
queueMicrotask(() => this._processPendingPatches());
|
|
17282
|
+
}
|
|
17283
|
+
}
|
|
17284
|
+
/**
|
|
17285
|
+
* Update pagination state for a property (e.g., 'items')
|
|
17286
|
+
*/
|
|
17287
|
+
setPaginationState(property2, state) {
|
|
17288
|
+
const current = this._paginationState.get(property2) || {
|
|
17289
|
+
pageSize: 20,
|
|
17290
|
+
currentPage: 0,
|
|
17291
|
+
hasMore: true,
|
|
17292
|
+
isLoading: false
|
|
17293
|
+
};
|
|
17294
|
+
this._paginationState.set(property2, { ...current, ...state });
|
|
17295
|
+
}
|
|
17296
|
+
/**
|
|
17297
|
+
* Get pagination state for a property
|
|
17298
|
+
*/
|
|
17299
|
+
getPaginationState(property2) {
|
|
17300
|
+
return this._paginationState.get(property2) || {
|
|
17301
|
+
pageSize: 20,
|
|
17302
|
+
currentPage: 0,
|
|
17303
|
+
hasMore: true,
|
|
17304
|
+
isLoading: false
|
|
17305
|
+
};
|
|
17306
|
+
}
|
|
17307
|
+
/**
|
|
17308
|
+
* Create a getter/setter for property access
|
|
17309
|
+
*/
|
|
17310
|
+
_createPropertyDescriptor(key) {
|
|
17311
|
+
return {
|
|
17312
|
+
configurable: true,
|
|
17313
|
+
enumerable: true,
|
|
17314
|
+
get: () => this._state[key],
|
|
17315
|
+
set: (value) => {
|
|
17316
|
+
this._state[key] = value;
|
|
17317
|
+
this.emit("propertyChanged", { property: key, value });
|
|
17318
|
+
}
|
|
17319
|
+
};
|
|
17320
|
+
}
|
|
17321
|
+
/**
|
|
17322
|
+
* Make a property accessible on the proxy
|
|
17323
|
+
*/
|
|
17324
|
+
makeProperty(key) {
|
|
17325
|
+
Object.defineProperty(this, key, this._createPropertyDescriptor(key));
|
|
17326
|
+
}
|
|
17327
|
+
/**
|
|
17328
|
+
* Get all top-level properties (useful for initialization)
|
|
17329
|
+
*/
|
|
17330
|
+
getProperties() {
|
|
17331
|
+
return Object.keys(this._state);
|
|
17332
|
+
}
|
|
17333
|
+
/**
|
|
17334
|
+
* Process pending patches
|
|
17335
|
+
*/
|
|
17336
|
+
_processPendingPatches() {
|
|
17337
|
+
const patches = this._pendingPatches.splice(0);
|
|
17338
|
+
try {
|
|
17339
|
+
for (const patch of patches) {
|
|
17340
|
+
this._applyPatch(patch);
|
|
17341
|
+
}
|
|
17342
|
+
this.emit("state-changed", patches);
|
|
17343
|
+
} finally {
|
|
17344
|
+
this._isApplyingPatches = false;
|
|
17345
|
+
if (this._pendingPatches.length > 0) {
|
|
17346
|
+
queueMicrotask(() => this._processPendingPatches());
|
|
17347
|
+
}
|
|
17348
|
+
}
|
|
17349
|
+
}
|
|
17350
|
+
/**
|
|
17351
|
+
* Apply a single JSON Patch operation
|
|
17352
|
+
*/
|
|
17353
|
+
_applyPatch(patch) {
|
|
17354
|
+
const { op, path, value } = patch;
|
|
17355
|
+
if (!path || typeof path !== "string") {
|
|
17356
|
+
console.warn("Invalid patch: missing or invalid path", patch);
|
|
17357
|
+
return;
|
|
17358
|
+
}
|
|
17359
|
+
const parts = path.split("/").filter((p5) => p5 !== "");
|
|
17360
|
+
let current = this._state;
|
|
17361
|
+
try {
|
|
17362
|
+
for (let i7 = 0; i7 < parts.length - 1; i7++) {
|
|
17363
|
+
const part = this._unescapePath(parts[i7]);
|
|
17364
|
+
if (!(part in current)) {
|
|
17365
|
+
current[part] = {};
|
|
17366
|
+
}
|
|
17367
|
+
current = current[part];
|
|
17368
|
+
}
|
|
17369
|
+
const lastPart = this._unescapePath(parts[parts.length - 1]);
|
|
17370
|
+
switch (op) {
|
|
17371
|
+
case "add":
|
|
17372
|
+
if (Array.isArray(current) && !isNaN(Number(lastPart))) {
|
|
17373
|
+
const index2 = Number(lastPart);
|
|
17374
|
+
current.splice(index2, 0, value);
|
|
17375
|
+
} else {
|
|
17376
|
+
current[lastPart] = value;
|
|
17377
|
+
}
|
|
17378
|
+
break;
|
|
17379
|
+
case "remove":
|
|
17380
|
+
if (Array.isArray(current) && !isNaN(Number(lastPart))) {
|
|
17381
|
+
const index2 = Number(lastPart);
|
|
17382
|
+
current.splice(index2, 1);
|
|
17383
|
+
} else {
|
|
17384
|
+
delete current[lastPart];
|
|
17385
|
+
}
|
|
17386
|
+
break;
|
|
17387
|
+
case "replace":
|
|
17388
|
+
current[lastPart] = value;
|
|
17389
|
+
break;
|
|
17390
|
+
case "move":
|
|
17391
|
+
const fromParts = patch.from.split("/").filter((p5) => p5 !== "");
|
|
17392
|
+
let fromCurrent = this._state;
|
|
17393
|
+
for (let i7 = 0; i7 < fromParts.length - 1; i7++) {
|
|
17394
|
+
fromCurrent = fromCurrent[this._unescapePath(fromParts[i7])];
|
|
17395
|
+
}
|
|
17396
|
+
const fromLast = this._unescapePath(fromParts[fromParts.length - 1]);
|
|
17397
|
+
const movedValue = fromCurrent[fromLast];
|
|
17398
|
+
if (Array.isArray(fromCurrent)) {
|
|
17399
|
+
fromCurrent.splice(Number(fromLast), 1);
|
|
17400
|
+
} else {
|
|
17401
|
+
delete fromCurrent[fromLast];
|
|
17402
|
+
}
|
|
17403
|
+
if (Array.isArray(current)) {
|
|
17404
|
+
current.splice(Number(lastPart), 0, movedValue);
|
|
17405
|
+
} else {
|
|
17406
|
+
current[lastPart] = movedValue;
|
|
17407
|
+
}
|
|
17408
|
+
break;
|
|
17409
|
+
case "copy":
|
|
17410
|
+
const copyFromParts = patch.from.split("/").filter((p5) => p5 !== "");
|
|
17411
|
+
let copyCurrent = this._state;
|
|
17412
|
+
for (let i7 = 0; i7 < copyFromParts.length - 1; i7++) {
|
|
17413
|
+
copyCurrent = copyCurrent[this._unescapePath(copyFromParts[i7])];
|
|
17414
|
+
}
|
|
17415
|
+
const copyFromLast = this._unescapePath(copyFromParts[copyFromParts.length - 1]);
|
|
17416
|
+
const copiedValue = JSON.parse(JSON.stringify(copyCurrent[copyFromLast]));
|
|
17417
|
+
current[lastPart] = copiedValue;
|
|
17418
|
+
break;
|
|
17419
|
+
case "test":
|
|
17420
|
+
if (current[lastPart] !== value) {
|
|
17421
|
+
throw new Error(`Test failed at ${path}: expected ${value}, got ${current[lastPart]}`);
|
|
17422
|
+
}
|
|
17423
|
+
break;
|
|
17424
|
+
default:
|
|
17425
|
+
console.warn(`Unknown patch operation: ${op}`);
|
|
17426
|
+
}
|
|
17427
|
+
} catch (error2) {
|
|
17428
|
+
console.error("Failed to apply patch", { patch, error: error2 });
|
|
17429
|
+
throw error2;
|
|
17430
|
+
}
|
|
17431
|
+
}
|
|
17432
|
+
/**
|
|
17433
|
+
* Unescape JSON Pointer path component
|
|
17434
|
+
* See: https://tools.ietf.org/html/rfc6901
|
|
17435
|
+
*/
|
|
17436
|
+
_unescapePath(part) {
|
|
17437
|
+
return part.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
17438
|
+
}
|
|
17439
|
+
/**
|
|
17440
|
+
* Clear all state
|
|
17441
|
+
*/
|
|
17442
|
+
reset(newState) {
|
|
17443
|
+
this._state = { ...newState };
|
|
17444
|
+
this._paginationState.clear();
|
|
17445
|
+
this.emit("reset");
|
|
17446
|
+
}
|
|
17447
|
+
};
|
|
17448
|
+
var GlobalSessionManager = class {
|
|
17449
|
+
constructor() {
|
|
17450
|
+
this._sessions = /* @__PURE__ */ new Map();
|
|
17451
|
+
}
|
|
17452
|
+
/**
|
|
17453
|
+
* Create or get a photon session
|
|
17454
|
+
*/
|
|
17455
|
+
createOrGetSession(name2, initialState) {
|
|
17456
|
+
if (this._sessions.has(name2)) {
|
|
17457
|
+
return this._sessions.get(name2);
|
|
17458
|
+
}
|
|
17459
|
+
const session = new PhotonSessionProxy({
|
|
17460
|
+
name: name2,
|
|
17461
|
+
initialState
|
|
17462
|
+
});
|
|
17463
|
+
Object.keys(initialState).forEach((key) => {
|
|
17464
|
+
session.makeProperty(key);
|
|
17465
|
+
});
|
|
17466
|
+
this._sessions.set(name2, session);
|
|
17467
|
+
return session;
|
|
17468
|
+
}
|
|
17469
|
+
/**
|
|
17470
|
+
* Get existing session
|
|
17471
|
+
*/
|
|
17472
|
+
getSession(name2) {
|
|
17473
|
+
return this._sessions.get(name2);
|
|
17474
|
+
}
|
|
17475
|
+
/**
|
|
17476
|
+
* Apply patches to a session
|
|
17477
|
+
*/
|
|
17478
|
+
applyPatches(name2, patches) {
|
|
17479
|
+
const session = this._sessions.get(name2);
|
|
17480
|
+
if (!session) {
|
|
17481
|
+
console.warn(`No session found for: ${name2}`);
|
|
17482
|
+
return false;
|
|
17483
|
+
}
|
|
17484
|
+
session.applyPatches(patches);
|
|
17485
|
+
return true;
|
|
17486
|
+
}
|
|
17487
|
+
/**
|
|
17488
|
+
* Remove session
|
|
17489
|
+
*/
|
|
17490
|
+
removeSession(name2) {
|
|
17491
|
+
this._sessions.delete(name2);
|
|
17492
|
+
}
|
|
17493
|
+
/**
|
|
17494
|
+
* Get all session names
|
|
17495
|
+
*/
|
|
17496
|
+
getSessionNames() {
|
|
17497
|
+
return Array.from(this._sessions.keys());
|
|
17498
|
+
}
|
|
17499
|
+
};
|
|
17500
|
+
var globalSessionManager = null;
|
|
17501
|
+
function getGlobalSessionManager() {
|
|
17502
|
+
if (!globalSessionManager) {
|
|
17503
|
+
globalSessionManager = new GlobalSessionManager();
|
|
17504
|
+
if (typeof window !== "undefined") {
|
|
17505
|
+
window.__photonSessionManager = globalSessionManager;
|
|
17506
|
+
}
|
|
17507
|
+
}
|
|
17508
|
+
return globalSessionManager;
|
|
17509
|
+
}
|
|
17510
|
+
function initializeGlobalPhotonSession(photonName, initialState) {
|
|
17511
|
+
const manager = getGlobalSessionManager();
|
|
17512
|
+
const session = manager.createOrGetSession(photonName, initialState);
|
|
17513
|
+
if (typeof window !== "undefined") {
|
|
17514
|
+
const varName = photonName.charAt(0).toLocaleLowerCase() + photonName.slice(1);
|
|
17515
|
+
window[varName] = session;
|
|
17516
|
+
if (photonName === "Boards") {
|
|
17517
|
+
window.boards = session;
|
|
17518
|
+
window.boardsSession = session;
|
|
17519
|
+
}
|
|
17520
|
+
}
|
|
17521
|
+
return session;
|
|
17522
|
+
}
|
|
17523
|
+
|
|
17239
17524
|
// src/auto-ui/frontend/services/mcp-client.ts
|
|
17240
17525
|
var MCPClientService = class {
|
|
17241
17526
|
// Discard operations older than 30s
|
|
@@ -17940,9 +18225,21 @@ var MCPClientService = class {
|
|
|
17940
18225
|
case "photon/refresh-needed":
|
|
17941
18226
|
this.emit("refresh-needed", notification.params);
|
|
17942
18227
|
break;
|
|
17943
|
-
case "
|
|
18228
|
+
case "state-changed":
|
|
18229
|
+
const params = notification.params;
|
|
18230
|
+
if (params?.instance && params?.patches) {
|
|
18231
|
+
try {
|
|
18232
|
+
const manager = getGlobalSessionManager();
|
|
18233
|
+
manager.applyPatches(params.instance, params.patches);
|
|
18234
|
+
} catch (error2) {
|
|
18235
|
+
console.error("Failed to apply patches to session", error2);
|
|
18236
|
+
}
|
|
18237
|
+
}
|
|
17944
18238
|
this.emit("state-changed", notification.params);
|
|
17945
18239
|
break;
|
|
18240
|
+
case "photon/notification":
|
|
18241
|
+
this.emit("photon-notification", notification.params);
|
|
18242
|
+
break;
|
|
17946
18243
|
// MCP Apps standard notifications
|
|
17947
18244
|
case "ui/notifications/tool-result":
|
|
17948
18245
|
this.emit("ui-tool-result", notification.params);
|
|
@@ -17967,6 +18264,439 @@ var MCPClientService = class {
|
|
|
17967
18264
|
};
|
|
17968
18265
|
var mcpClient = new MCPClientService();
|
|
17969
18266
|
|
|
18267
|
+
// src/auto-ui/frontend/services/viewport-aware-proxy.ts
|
|
18268
|
+
var ViewportAwareProxy = class {
|
|
18269
|
+
constructor(photonName, methodName, mcpClient2, options = {}) {
|
|
18270
|
+
// Cache management
|
|
18271
|
+
this._cache = /* @__PURE__ */ new Map();
|
|
18272
|
+
this._viewport = { start: 0, end: 20 };
|
|
18273
|
+
this._pendingRanges = /* @__PURE__ */ new Set();
|
|
18274
|
+
this._pagination = {
|
|
18275
|
+
totalCount: 0,
|
|
18276
|
+
start: 0,
|
|
18277
|
+
end: 0,
|
|
18278
|
+
hasMore: false
|
|
18279
|
+
};
|
|
18280
|
+
// Event listeners
|
|
18281
|
+
this._listeners = /* @__PURE__ */ new Map();
|
|
18282
|
+
this._photonName = photonName;
|
|
18283
|
+
this._methodName = methodName;
|
|
18284
|
+
this._mcpClient = mcpClient2;
|
|
18285
|
+
this._fetchOptions = {
|
|
18286
|
+
pageSize: options.pageSize ?? 20,
|
|
18287
|
+
bufferSize: options.bufferSize ?? 5,
|
|
18288
|
+
maxCacheSize: options.maxCacheSize ?? 1e3
|
|
18289
|
+
};
|
|
18290
|
+
}
|
|
18291
|
+
/**
|
|
18292
|
+
* Initialize with paginated response from server
|
|
18293
|
+
* Server should return: { items: [...], _pagination: {...} }
|
|
18294
|
+
*/
|
|
18295
|
+
initializeWithResponse(response) {
|
|
18296
|
+
if (!response || typeof response !== "object") {
|
|
18297
|
+
return;
|
|
18298
|
+
}
|
|
18299
|
+
const { items = [], _pagination } = response;
|
|
18300
|
+
if (_pagination) {
|
|
18301
|
+
this._pagination = _pagination;
|
|
18302
|
+
items.forEach((item, offset) => {
|
|
18303
|
+
this._cache.set(_pagination.start + offset, item);
|
|
18304
|
+
});
|
|
18305
|
+
this._emit("initialized", { pagination: this._pagination });
|
|
18306
|
+
}
|
|
18307
|
+
}
|
|
18308
|
+
/**
|
|
18309
|
+
* Set visible viewport (what user sees on screen)
|
|
18310
|
+
* Automatically fetches data for this range + buffer
|
|
18311
|
+
*/
|
|
18312
|
+
async setViewport(start, end) {
|
|
18313
|
+
this._viewport = { start, end };
|
|
18314
|
+
const bufferedStart = Math.max(0, start - this._fetchOptions.bufferSize);
|
|
18315
|
+
const bufferedEnd = Math.min(this._pagination.totalCount, end + this._fetchOptions.bufferSize);
|
|
18316
|
+
const missingRanges = this._findMissingRanges(bufferedStart, bufferedEnd);
|
|
18317
|
+
await Promise.all(
|
|
18318
|
+
missingRanges.map(
|
|
18319
|
+
(range) => this._fetchRange(range.start, range.end).catch((err) => {
|
|
18320
|
+
console.error(`Failed to fetch range [${range.start}, ${range.end}]`, err);
|
|
18321
|
+
})
|
|
18322
|
+
)
|
|
18323
|
+
);
|
|
18324
|
+
}
|
|
18325
|
+
/**
|
|
18326
|
+
* Get items in current viewport (array-like interface)
|
|
18327
|
+
*/
|
|
18328
|
+
get items() {
|
|
18329
|
+
const items = [];
|
|
18330
|
+
for (let i7 = this._viewport.start; i7 < this._viewport.end; i7++) {
|
|
18331
|
+
if (this._cache.has(i7)) {
|
|
18332
|
+
items.push(this._cache.get(i7));
|
|
18333
|
+
}
|
|
18334
|
+
}
|
|
18335
|
+
return items;
|
|
18336
|
+
}
|
|
18337
|
+
/**
|
|
18338
|
+
* Get item by index
|
|
18339
|
+
*/
|
|
18340
|
+
getItem(index2) {
|
|
18341
|
+
return this._cache.get(index2);
|
|
18342
|
+
}
|
|
18343
|
+
/**
|
|
18344
|
+
* Get total count of items (if available)
|
|
18345
|
+
*/
|
|
18346
|
+
get totalCount() {
|
|
18347
|
+
return this._pagination.totalCount;
|
|
18348
|
+
}
|
|
18349
|
+
/**
|
|
18350
|
+
* Get current pagination state
|
|
18351
|
+
*/
|
|
18352
|
+
get pagination() {
|
|
18353
|
+
return { ...this._pagination };
|
|
18354
|
+
}
|
|
18355
|
+
/**
|
|
18356
|
+
* Get current viewport
|
|
18357
|
+
*/
|
|
18358
|
+
get viewport() {
|
|
18359
|
+
return { ...this._viewport };
|
|
18360
|
+
}
|
|
18361
|
+
/**
|
|
18362
|
+
* Get cache size (for debugging)
|
|
18363
|
+
*/
|
|
18364
|
+
get cacheSize() {
|
|
18365
|
+
return this._cache.size;
|
|
18366
|
+
}
|
|
18367
|
+
/**
|
|
18368
|
+
* Check if a range is cached
|
|
18369
|
+
*/
|
|
18370
|
+
isCached(start, end) {
|
|
18371
|
+
for (let i7 = start; i7 < end; i7++) {
|
|
18372
|
+
if (!this._cache.has(i7)) {
|
|
18373
|
+
return false;
|
|
18374
|
+
}
|
|
18375
|
+
}
|
|
18376
|
+
return true;
|
|
18377
|
+
}
|
|
18378
|
+
/**
|
|
18379
|
+
* Subscribe to events
|
|
18380
|
+
*/
|
|
18381
|
+
on(event, callback2) {
|
|
18382
|
+
if (!this._listeners.has(event)) {
|
|
18383
|
+
this._listeners.set(event, /* @__PURE__ */ new Set());
|
|
18384
|
+
}
|
|
18385
|
+
this._listeners.get(event).add(callback2);
|
|
18386
|
+
}
|
|
18387
|
+
/**
|
|
18388
|
+
* Unsubscribe from events
|
|
18389
|
+
*/
|
|
18390
|
+
off(event, callback2) {
|
|
18391
|
+
const listeners = this._listeners.get(event);
|
|
18392
|
+
if (listeners) {
|
|
18393
|
+
listeners.delete(callback2);
|
|
18394
|
+
}
|
|
18395
|
+
}
|
|
18396
|
+
/**
|
|
18397
|
+
* Clear cache
|
|
18398
|
+
*/
|
|
18399
|
+
clearCache() {
|
|
18400
|
+
this._cache.clear();
|
|
18401
|
+
this._emit("cache-cleared");
|
|
18402
|
+
}
|
|
18403
|
+
/**
|
|
18404
|
+
* Apply patches from state-changed events
|
|
18405
|
+
* Updates cache with new/modified items
|
|
18406
|
+
*/
|
|
18407
|
+
applyPatches(patches) {
|
|
18408
|
+
for (const patch of patches) {
|
|
18409
|
+
this._applyPatch(patch);
|
|
18410
|
+
}
|
|
18411
|
+
this._emit("patched", { patches });
|
|
18412
|
+
}
|
|
18413
|
+
/**
|
|
18414
|
+
* Find which ranges need to be fetched
|
|
18415
|
+
*/
|
|
18416
|
+
_findMissingRanges(start, end) {
|
|
18417
|
+
const missing = [];
|
|
18418
|
+
for (let i7 = start; i7 < end; i7++) {
|
|
18419
|
+
if (!this._cache.has(i7)) {
|
|
18420
|
+
missing.push(i7);
|
|
18421
|
+
}
|
|
18422
|
+
}
|
|
18423
|
+
const ranges = [];
|
|
18424
|
+
if (missing.length === 0) return ranges;
|
|
18425
|
+
let rangeStart = missing[0];
|
|
18426
|
+
let rangeEnd2 = missing[0];
|
|
18427
|
+
for (let i7 = 1; i7 < missing.length; i7++) {
|
|
18428
|
+
if (missing[i7] === rangeEnd2 + 1) {
|
|
18429
|
+
rangeEnd2 = missing[i7];
|
|
18430
|
+
} else {
|
|
18431
|
+
ranges.push({ start: rangeStart, end: rangeEnd2 + 1 });
|
|
18432
|
+
rangeStart = missing[i7];
|
|
18433
|
+
rangeEnd2 = missing[i7];
|
|
18434
|
+
}
|
|
18435
|
+
}
|
|
18436
|
+
ranges.push({ start: rangeStart, end: rangeEnd2 + 1 });
|
|
18437
|
+
return ranges;
|
|
18438
|
+
}
|
|
18439
|
+
/**
|
|
18440
|
+
* Fetch a range of items via MCP
|
|
18441
|
+
*/
|
|
18442
|
+
async _fetchRange(start, end) {
|
|
18443
|
+
const rangeKey = `${start}-${end}`;
|
|
18444
|
+
if (this._pendingRanges.has(rangeKey)) {
|
|
18445
|
+
return;
|
|
18446
|
+
}
|
|
18447
|
+
this._pendingRanges.add(rangeKey);
|
|
18448
|
+
try {
|
|
18449
|
+
const toolName = `${this._photonName}/${this._methodName}`;
|
|
18450
|
+
const result = await this._mcpClient.callTool(toolName, {
|
|
18451
|
+
start,
|
|
18452
|
+
limit: Math.min(end - start, this._fetchOptions.pageSize)
|
|
18453
|
+
});
|
|
18454
|
+
if (result.isError) {
|
|
18455
|
+
console.error(`Failed to fetch ${toolName}[${start}:${end}]`, result);
|
|
18456
|
+
return;
|
|
18457
|
+
}
|
|
18458
|
+
const parsed = this._mcpClient.parseToolResult(result);
|
|
18459
|
+
if (parsed && typeof parsed === "object") {
|
|
18460
|
+
const { items = [], _pagination } = parsed;
|
|
18461
|
+
if (_pagination) {
|
|
18462
|
+
this._pagination = _pagination;
|
|
18463
|
+
}
|
|
18464
|
+
items.forEach((item, offset) => {
|
|
18465
|
+
this._cache.set(start + offset, item);
|
|
18466
|
+
});
|
|
18467
|
+
if (this._cache.size > this._fetchOptions.maxCacheSize) {
|
|
18468
|
+
this._pruneCache();
|
|
18469
|
+
}
|
|
18470
|
+
this._emit("fetched", { start, end, itemCount: items.length });
|
|
18471
|
+
}
|
|
18472
|
+
} finally {
|
|
18473
|
+
this._pendingRanges.delete(rangeKey);
|
|
18474
|
+
}
|
|
18475
|
+
}
|
|
18476
|
+
/**
|
|
18477
|
+
* Apply a single JSON Patch to cache
|
|
18478
|
+
*/
|
|
18479
|
+
_applyPatch(patch) {
|
|
18480
|
+
const { op, path } = patch;
|
|
18481
|
+
const match = path.match(/\/items\/(\d+)/);
|
|
18482
|
+
if (!match) return;
|
|
18483
|
+
const index2 = parseInt(match[1], 10);
|
|
18484
|
+
switch (op) {
|
|
18485
|
+
case "add": {
|
|
18486
|
+
const newCache = /* @__PURE__ */ new Map();
|
|
18487
|
+
for (const [key, value] of this._cache) {
|
|
18488
|
+
if (key >= index2) {
|
|
18489
|
+
newCache.set(key + 1, value);
|
|
18490
|
+
} else {
|
|
18491
|
+
newCache.set(key, value);
|
|
18492
|
+
}
|
|
18493
|
+
}
|
|
18494
|
+
newCache.set(index2, patch.value);
|
|
18495
|
+
this._cache = newCache;
|
|
18496
|
+
this._pagination.totalCount++;
|
|
18497
|
+
break;
|
|
18498
|
+
}
|
|
18499
|
+
case "remove": {
|
|
18500
|
+
const newCache = /* @__PURE__ */ new Map();
|
|
18501
|
+
for (const [key, value] of this._cache) {
|
|
18502
|
+
if (key > index2) {
|
|
18503
|
+
newCache.set(key - 1, value);
|
|
18504
|
+
} else if (key < index2) {
|
|
18505
|
+
newCache.set(key, value);
|
|
18506
|
+
}
|
|
18507
|
+
}
|
|
18508
|
+
this._cache = newCache;
|
|
18509
|
+
this._pagination.totalCount--;
|
|
18510
|
+
break;
|
|
18511
|
+
}
|
|
18512
|
+
case "replace": {
|
|
18513
|
+
this._cache.set(index2, patch.value);
|
|
18514
|
+
break;
|
|
18515
|
+
}
|
|
18516
|
+
}
|
|
18517
|
+
}
|
|
18518
|
+
/**
|
|
18519
|
+
* Remove least-recently-used items from cache when it gets too large
|
|
18520
|
+
*/
|
|
18521
|
+
_pruneCache() {
|
|
18522
|
+
const toRemove = this._cache.size - this._fetchOptions.maxCacheSize;
|
|
18523
|
+
if (toRemove <= 0) return;
|
|
18524
|
+
const viewportCenter = this._viewport.start + (this._viewport.end - this._viewport.start) / 2;
|
|
18525
|
+
const sortedKeys = Array.from(this._cache.keys()).sort(
|
|
18526
|
+
(a5, b3) => Math.abs(a5 - viewportCenter) - Math.abs(b3 - viewportCenter)
|
|
18527
|
+
);
|
|
18528
|
+
for (let i7 = 0; i7 < toRemove && i7 < sortedKeys.length; i7++) {
|
|
18529
|
+
this._cache.delete(sortedKeys[i7]);
|
|
18530
|
+
}
|
|
18531
|
+
}
|
|
18532
|
+
/**
|
|
18533
|
+
* Emit event to listeners
|
|
18534
|
+
*/
|
|
18535
|
+
_emit(event, data) {
|
|
18536
|
+
const listeners = this._listeners.get(event);
|
|
18537
|
+
if (listeners) {
|
|
18538
|
+
for (const callback2 of listeners) {
|
|
18539
|
+
try {
|
|
18540
|
+
callback2(data);
|
|
18541
|
+
} catch (err) {
|
|
18542
|
+
console.error(`Error in ${event} listener:`, err);
|
|
18543
|
+
}
|
|
18544
|
+
}
|
|
18545
|
+
}
|
|
18546
|
+
}
|
|
18547
|
+
};
|
|
18548
|
+
|
|
18549
|
+
// src/auto-ui/frontend/services/viewport-manager.ts
|
|
18550
|
+
function getPageSizeForClient() {
|
|
18551
|
+
if (typeof window !== "undefined" && window.innerWidth < 600) {
|
|
18552
|
+
return 10;
|
|
18553
|
+
}
|
|
18554
|
+
if (typeof window !== "undefined" && window.innerWidth < 1024) {
|
|
18555
|
+
return 25;
|
|
18556
|
+
}
|
|
18557
|
+
return 50;
|
|
18558
|
+
}
|
|
18559
|
+
var ViewportManager = class {
|
|
18560
|
+
constructor(config3) {
|
|
18561
|
+
this.observer = null;
|
|
18562
|
+
this.visibleSentinels = /* @__PURE__ */ new Set();
|
|
18563
|
+
this.lastVisibleRange = { start: 0, end: 0 };
|
|
18564
|
+
this.lastScrollDirection = "none";
|
|
18565
|
+
this.changeCallbacks = [];
|
|
18566
|
+
this.element = config3.element;
|
|
18567
|
+
this.pageSize = config3.pageSize;
|
|
18568
|
+
this.paddingAbove = config3.paddingAbove ?? this.pageSize;
|
|
18569
|
+
this.paddingBelow = config3.paddingBelow ?? this.pageSize * 2;
|
|
18570
|
+
this.debug = config3.debug ?? false;
|
|
18571
|
+
this.log("ViewportManager initialized", {
|
|
18572
|
+
pageSize: this.pageSize,
|
|
18573
|
+
paddingAbove: this.paddingAbove,
|
|
18574
|
+
paddingBelow: this.paddingBelow
|
|
18575
|
+
});
|
|
18576
|
+
this.initializeObserver();
|
|
18577
|
+
}
|
|
18578
|
+
initializeObserver() {
|
|
18579
|
+
const options = {
|
|
18580
|
+
root: null,
|
|
18581
|
+
rootMargin: "100px",
|
|
18582
|
+
threshold: 0
|
|
18583
|
+
};
|
|
18584
|
+
this.observer = new IntersectionObserver((entries) => {
|
|
18585
|
+
for (const entry of entries) {
|
|
18586
|
+
const index2 = this.getSentinelIndex(entry.target);
|
|
18587
|
+
if (index2 !== null) {
|
|
18588
|
+
if (entry.isIntersecting) {
|
|
18589
|
+
this.visibleSentinels.add(index2);
|
|
18590
|
+
} else {
|
|
18591
|
+
this.visibleSentinels.delete(index2);
|
|
18592
|
+
}
|
|
18593
|
+
}
|
|
18594
|
+
}
|
|
18595
|
+
this.updateVisibleRange();
|
|
18596
|
+
}, options);
|
|
18597
|
+
}
|
|
18598
|
+
createSentinel(index2) {
|
|
18599
|
+
const sentinel = document.createElement("div");
|
|
18600
|
+
sentinel.setAttribute("data-viewport-sentinel", String(index2));
|
|
18601
|
+
sentinel.style.height = "0px";
|
|
18602
|
+
sentinel.style.overflow = "hidden";
|
|
18603
|
+
return sentinel;
|
|
18604
|
+
}
|
|
18605
|
+
observeSentinel(sentinel) {
|
|
18606
|
+
if (this.observer) {
|
|
18607
|
+
this.observer.observe(sentinel);
|
|
18608
|
+
}
|
|
18609
|
+
}
|
|
18610
|
+
unobserveSentinel(sentinel) {
|
|
18611
|
+
if (this.observer) {
|
|
18612
|
+
this.observer.unobserve(sentinel);
|
|
18613
|
+
}
|
|
18614
|
+
}
|
|
18615
|
+
getSentinelIndex(element) {
|
|
18616
|
+
const attr = element.getAttribute("data-viewport-sentinel");
|
|
18617
|
+
return attr !== null ? parseInt(attr, 10) : null;
|
|
18618
|
+
}
|
|
18619
|
+
updateVisibleRange() {
|
|
18620
|
+
if (this.visibleSentinels.size === 0) {
|
|
18621
|
+
return;
|
|
18622
|
+
}
|
|
18623
|
+
const indices = Array.from(this.visibleSentinels).sort((a5, b3) => a5 - b3);
|
|
18624
|
+
const visibleStart = indices[0];
|
|
18625
|
+
const visibleEnd = indices[indices.length - 1] + 1;
|
|
18626
|
+
const direction = this.determineScrollDirection(visibleStart);
|
|
18627
|
+
const bufferStart = Math.max(
|
|
18628
|
+
0,
|
|
18629
|
+
visibleStart - Math.ceil(this.paddingAbove / this.pageSize) * this.pageSize
|
|
18630
|
+
);
|
|
18631
|
+
const bufferEnd = visibleEnd + Math.ceil(this.paddingBelow / this.pageSize) * this.pageSize;
|
|
18632
|
+
const rangeChanged = visibleStart !== this.lastVisibleRange.start || visibleEnd !== this.lastVisibleRange.end;
|
|
18633
|
+
if (rangeChanged) {
|
|
18634
|
+
this.lastVisibleRange = { start: visibleStart, end: visibleEnd };
|
|
18635
|
+
this.lastScrollDirection = direction;
|
|
18636
|
+
const event = {
|
|
18637
|
+
visibleRange: { start: visibleStart, end: visibleEnd },
|
|
18638
|
+
bufferRange: { start: bufferStart, end: bufferEnd },
|
|
18639
|
+
scrollDirection: direction,
|
|
18640
|
+
timestamp: Date.now()
|
|
18641
|
+
};
|
|
18642
|
+
this.log("Viewport changed", event);
|
|
18643
|
+
for (const callback2 of this.changeCallbacks) {
|
|
18644
|
+
callback2(event);
|
|
18645
|
+
}
|
|
18646
|
+
}
|
|
18647
|
+
}
|
|
18648
|
+
determineScrollDirection(newStart) {
|
|
18649
|
+
if (newStart < this.lastVisibleRange.start) {
|
|
18650
|
+
return "up";
|
|
18651
|
+
} else if (newStart > this.lastVisibleRange.start) {
|
|
18652
|
+
return "down";
|
|
18653
|
+
}
|
|
18654
|
+
return "none";
|
|
18655
|
+
}
|
|
18656
|
+
getVisibleRange() {
|
|
18657
|
+
return this.lastVisibleRange;
|
|
18658
|
+
}
|
|
18659
|
+
getBufferRange(totalItems) {
|
|
18660
|
+
const { start, end } = this.lastVisibleRange;
|
|
18661
|
+
const bufferStart = Math.max(0, start - this.paddingAbove);
|
|
18662
|
+
const bufferEnd = Math.min(totalItems, end + this.paddingBelow);
|
|
18663
|
+
return { start: bufferStart, end: bufferEnd };
|
|
18664
|
+
}
|
|
18665
|
+
getScrollDirection() {
|
|
18666
|
+
return this.lastScrollDirection;
|
|
18667
|
+
}
|
|
18668
|
+
getPageSize() {
|
|
18669
|
+
return this.pageSize;
|
|
18670
|
+
}
|
|
18671
|
+
onChange(callback2) {
|
|
18672
|
+
this.changeCallbacks.push(callback2);
|
|
18673
|
+
}
|
|
18674
|
+
offChange(callback2) {
|
|
18675
|
+
this.changeCallbacks = this.changeCallbacks.filter((cb) => cb !== callback2);
|
|
18676
|
+
}
|
|
18677
|
+
setPageSize(newPageSize) {
|
|
18678
|
+
if (newPageSize !== this.pageSize) {
|
|
18679
|
+
this.pageSize = newPageSize;
|
|
18680
|
+
this.log("Page size updated", { newPageSize });
|
|
18681
|
+
this.updateVisibleRange();
|
|
18682
|
+
}
|
|
18683
|
+
}
|
|
18684
|
+
destroy() {
|
|
18685
|
+
if (this.observer) {
|
|
18686
|
+
this.observer.disconnect();
|
|
18687
|
+
this.observer = null;
|
|
18688
|
+
}
|
|
18689
|
+
this.changeCallbacks = [];
|
|
18690
|
+
this.visibleSentinels.clear();
|
|
18691
|
+
this.log("ViewportManager destroyed");
|
|
18692
|
+
}
|
|
18693
|
+
log(message, data) {
|
|
18694
|
+
if (this.debug) {
|
|
18695
|
+
console.log(`[ViewportManager] ${message}`, data);
|
|
18696
|
+
}
|
|
18697
|
+
}
|
|
18698
|
+
};
|
|
18699
|
+
|
|
17970
18700
|
// src/auto-ui/frontend/components/beam-app.ts
|
|
17971
18701
|
var THEME_STORAGE_KEY = "beam-theme";
|
|
17972
18702
|
var PROTOCOL_STORAGE_KEY = "beam-protocol";
|
|
@@ -18030,6 +18760,10 @@ var BeamApp = class extends i4 {
|
|
|
18030
18760
|
this._promptArguments = {};
|
|
18031
18761
|
this._renderedPrompt = "";
|
|
18032
18762
|
this._resourceContent = "";
|
|
18763
|
+
this._splitPanels = [];
|
|
18764
|
+
this._methodPickerOpen = false;
|
|
18765
|
+
this._methodPickerPanelId = null;
|
|
18766
|
+
this._nextPanelId = 0;
|
|
18033
18767
|
// Collection auto-subscription for ReactiveArray/Map/Set events
|
|
18034
18768
|
this._collectionUnsubscribes = [];
|
|
18035
18769
|
this._currentCollectionName = null;
|
|
@@ -18040,6 +18774,10 @@ var BeamApp = class extends i4 {
|
|
|
18040
18774
|
this._fileIdCounter = 0;
|
|
18041
18775
|
// Deep link URL for setOpenInAppUrl
|
|
18042
18776
|
this._openInAppUrl = null;
|
|
18777
|
+
// PWA install state
|
|
18778
|
+
this._pwaInstallPrompt = null;
|
|
18779
|
+
this._pwaIsStandalone = false;
|
|
18780
|
+
this._pwaCurrentPhoton = null;
|
|
18043
18781
|
this._handleDocumentClick = (e8) => {
|
|
18044
18782
|
const path = e8.composedPath();
|
|
18045
18783
|
if (this._showSettingsMenu) {
|
|
@@ -18057,11 +18795,11 @@ var BeamApp = class extends i4 {
|
|
|
18057
18795
|
}
|
|
18058
18796
|
};
|
|
18059
18797
|
this._initialConnectDone = false;
|
|
18060
|
-
this.
|
|
18798
|
+
this._handleRouteChange = () => {
|
|
18061
18799
|
void (async () => {
|
|
18062
|
-
const
|
|
18063
|
-
const
|
|
18064
|
-
const [photonName, methodName] =
|
|
18800
|
+
const fullPath = window.location.pathname.slice(1);
|
|
18801
|
+
const queryPart = window.location.search.slice(1);
|
|
18802
|
+
const [photonName, methodName] = fullPath.split("/");
|
|
18065
18803
|
let sharedParams = {};
|
|
18066
18804
|
if (queryPart) {
|
|
18067
18805
|
const params = new URLSearchParams(queryPart);
|
|
@@ -18078,6 +18816,9 @@ var BeamApp = class extends i4 {
|
|
|
18078
18816
|
}
|
|
18079
18817
|
}
|
|
18080
18818
|
}
|
|
18819
|
+
this._methodPickerOpen = false;
|
|
18820
|
+
this._methodPickerPanelId = null;
|
|
18821
|
+
this._splitPanels = [];
|
|
18081
18822
|
if (!photonName || photonName === "home") {
|
|
18082
18823
|
this._selectedPhoton = null;
|
|
18083
18824
|
this._selectedMethod = null;
|
|
@@ -18104,7 +18845,8 @@ var BeamApp = class extends i4 {
|
|
|
18104
18845
|
return;
|
|
18105
18846
|
}
|
|
18106
18847
|
if (methodName && photon.methods) {
|
|
18107
|
-
const
|
|
18848
|
+
const [firstMethodName, secondMethodName] = methodName.split("+");
|
|
18849
|
+
const method = photon.methods.find((m3) => m3.name === firstMethodName);
|
|
18108
18850
|
if (method) {
|
|
18109
18851
|
if (Object.keys(sharedParams).length > 0) {
|
|
18110
18852
|
this._sharedFormParams = sharedParams;
|
|
@@ -18115,6 +18857,22 @@ var BeamApp = class extends i4 {
|
|
|
18115
18857
|
}
|
|
18116
18858
|
this._selectedMethod = method;
|
|
18117
18859
|
this._view = "form";
|
|
18860
|
+
if (secondMethodName) {
|
|
18861
|
+
const urlPath = location.pathname;
|
|
18862
|
+
const methodPart = urlPath.split("/").pop() || "";
|
|
18863
|
+
const methodNames = methodPart.split("+");
|
|
18864
|
+
for (let i7 = 1; i7 < methodNames.length; i7++) {
|
|
18865
|
+
const name2 = methodNames[i7];
|
|
18866
|
+
if (name2 === "source") {
|
|
18867
|
+
this._addPanel("source");
|
|
18868
|
+
} else {
|
|
18869
|
+
const panelMethod = photon.methods.find((m3) => m3.name === name2);
|
|
18870
|
+
if (panelMethod) {
|
|
18871
|
+
this._addPanel("method", panelMethod);
|
|
18872
|
+
}
|
|
18873
|
+
}
|
|
18874
|
+
}
|
|
18875
|
+
}
|
|
18118
18876
|
if (Object.keys(sharedParams).length === 0) {
|
|
18119
18877
|
this._maybeAutoInvoke(method);
|
|
18120
18878
|
}
|
|
@@ -18134,18 +18892,15 @@ var BeamApp = class extends i4 {
|
|
|
18134
18892
|
}
|
|
18135
18893
|
})();
|
|
18136
18894
|
};
|
|
18137
|
-
this._handlePopState = () => {
|
|
18138
|
-
void this._handleHashChange();
|
|
18139
|
-
};
|
|
18140
18895
|
this._goHome = () => {
|
|
18141
18896
|
this._selectedPhoton = null;
|
|
18142
18897
|
this._selectedMethod = null;
|
|
18143
18898
|
this._lastResult = null;
|
|
18144
|
-
this.
|
|
18899
|
+
this._updateRoute();
|
|
18145
18900
|
};
|
|
18146
18901
|
this._runTests = async () => {
|
|
18147
18902
|
if (!this._selectedPhoton || this._runningTests) return;
|
|
18148
|
-
const testMethods = this.
|
|
18903
|
+
const testMethods = await this._fetchTestList(this._selectedPhoton.name);
|
|
18149
18904
|
if (testMethods.length === 0) return;
|
|
18150
18905
|
this._runningTests = true;
|
|
18151
18906
|
this._testResults = [];
|
|
@@ -18231,6 +18986,7 @@ var BeamApp = class extends i4 {
|
|
|
18231
18986
|
`All photon tests: ${passed}/${total} passed`
|
|
18232
18987
|
);
|
|
18233
18988
|
};
|
|
18989
|
+
this._pickerDismissHandler = null;
|
|
18234
18990
|
this._toggleSettingsMenu = () => {
|
|
18235
18991
|
this._showSettingsMenu = !this._showSettingsMenu;
|
|
18236
18992
|
};
|
|
@@ -18249,8 +19005,45 @@ var BeamApp = class extends i4 {
|
|
|
18249
19005
|
};
|
|
18250
19006
|
this._launchAsApp = () => {
|
|
18251
19007
|
this._closeSettingsMenu();
|
|
18252
|
-
if (this._selectedPhoton)
|
|
18253
|
-
|
|
19008
|
+
if (!this._selectedPhoton) return;
|
|
19009
|
+
if (this._pwaInstallPrompt) {
|
|
19010
|
+
void (async () => {
|
|
19011
|
+
try {
|
|
19012
|
+
await fetch("/api/pwa/configure", {
|
|
19013
|
+
method: "POST",
|
|
19014
|
+
headers: { "Content-Type": "application/json" },
|
|
19015
|
+
body: JSON.stringify({
|
|
19016
|
+
photon: this._selectedPhoton.name,
|
|
19017
|
+
port: location.port || "4100"
|
|
19018
|
+
}),
|
|
19019
|
+
signal: AbortSignal.timeout(5e3)
|
|
19020
|
+
});
|
|
19021
|
+
} catch {
|
|
19022
|
+
}
|
|
19023
|
+
const photonName = this._selectedPhoton.name;
|
|
19024
|
+
const onInstalled = () => {
|
|
19025
|
+
window.open(`/app/${encodeURIComponent(photonName)}`, "_blank");
|
|
19026
|
+
};
|
|
19027
|
+
window.addEventListener("appinstalled", onInstalled, { once: true });
|
|
19028
|
+
const result = await this._pwaInstallPrompt.prompt();
|
|
19029
|
+
this._log("info", `PWA install prompt result: ${result?.outcome}`);
|
|
19030
|
+
if (result?.outcome !== "accepted") {
|
|
19031
|
+
window.removeEventListener("appinstalled", onInstalled);
|
|
19032
|
+
}
|
|
19033
|
+
this._pwaInstallPrompt = null;
|
|
19034
|
+
})();
|
|
19035
|
+
} else {
|
|
19036
|
+
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
19037
|
+
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
|
|
19038
|
+
if (isSafari || isIOS) {
|
|
19039
|
+
const hint = isIOS ? 'Tap the Share button, then "Add to Home Screen"' : "Use File > Add to Dock to install this app";
|
|
19040
|
+
showToast(hint, "info");
|
|
19041
|
+
} else {
|
|
19042
|
+
showToast(
|
|
19043
|
+
"Install not ready yet \u2014 the service worker needs a moment to generate icons. Try again in a few seconds.",
|
|
19044
|
+
"info"
|
|
19045
|
+
);
|
|
19046
|
+
}
|
|
18254
19047
|
}
|
|
18255
19048
|
};
|
|
18256
19049
|
this._handleRemove = async () => {
|
|
@@ -18416,7 +19209,7 @@ var BeamApp = class extends i4 {
|
|
|
18416
19209
|
}
|
|
18417
19210
|
}
|
|
18418
19211
|
this._view = "config";
|
|
18419
|
-
this.
|
|
19212
|
+
this._updateRoute();
|
|
18420
19213
|
};
|
|
18421
19214
|
this._toggleRememberValues = () => {
|
|
18422
19215
|
this._rememberFormValues = !this._rememberFormValues;
|
|
@@ -19001,7 +19794,7 @@ var BeamApp = class extends i4 {
|
|
|
19001
19794
|
}
|
|
19002
19795
|
if (e8.key === "Enter" && this._selectedMethod && this._view === "list") {
|
|
19003
19796
|
this._view = "form";
|
|
19004
|
-
this.
|
|
19797
|
+
this._updateRoute();
|
|
19005
19798
|
return;
|
|
19006
19799
|
}
|
|
19007
19800
|
if (e8.key === "r") {
|
|
@@ -19037,12 +19830,12 @@ var BeamApp = class extends i4 {
|
|
|
19037
19830
|
this._focusMode = !this._focusMode;
|
|
19038
19831
|
if (this._focusMode) {
|
|
19039
19832
|
this.classList.add("focus-mode");
|
|
19040
|
-
const
|
|
19041
|
-
history.replaceState(null, "",
|
|
19833
|
+
const path = window.location.pathname;
|
|
19834
|
+
history.replaceState(null, "", path + "?focus=1");
|
|
19042
19835
|
} else {
|
|
19043
19836
|
this.classList.remove("focus-mode");
|
|
19044
|
-
const
|
|
19045
|
-
history.replaceState(null, "",
|
|
19837
|
+
const path = window.location.pathname;
|
|
19838
|
+
history.replaceState(null, "", path);
|
|
19046
19839
|
}
|
|
19047
19840
|
};
|
|
19048
19841
|
this._handleFullscreen = () => {
|
|
@@ -19141,9 +19934,25 @@ var BeamApp = class extends i4 {
|
|
|
19141
19934
|
case "fullscreen":
|
|
19142
19935
|
this._handleFullscreen();
|
|
19143
19936
|
break;
|
|
19937
|
+
case "install-app":
|
|
19938
|
+
this._launchAsApp();
|
|
19939
|
+
break;
|
|
19940
|
+
}
|
|
19941
|
+
break;
|
|
19942
|
+
}
|
|
19943
|
+
case "split-view:add":
|
|
19944
|
+
this._showMethodPicker();
|
|
19945
|
+
break;
|
|
19946
|
+
case "split-view:change": {
|
|
19947
|
+
const method = this._selectedPhoton?.methods?.find((m3) => m3.name === e8.detail.method);
|
|
19948
|
+
if (method && this._splitPanels.length > 0) {
|
|
19949
|
+
this._changePanelMethod(this._splitPanels[0].id, method);
|
|
19144
19950
|
}
|
|
19145
19951
|
break;
|
|
19146
19952
|
}
|
|
19953
|
+
case "split-view:remove":
|
|
19954
|
+
this._closeSecondPanel();
|
|
19955
|
+
break;
|
|
19147
19956
|
}
|
|
19148
19957
|
};
|
|
19149
19958
|
this._startEditingDescription = () => {
|
|
@@ -19343,7 +20152,7 @@ var BeamApp = class extends i4 {
|
|
|
19343
20152
|
if (method) {
|
|
19344
20153
|
this._selectedMethod = method;
|
|
19345
20154
|
this._view = "form";
|
|
19346
|
-
this.
|
|
20155
|
+
this._updateRoute();
|
|
19347
20156
|
this._log("info", `Starting ${targetName}/${action}...`);
|
|
19348
20157
|
showToast(`Starting ${action}...`, "info");
|
|
19349
20158
|
} else {
|
|
@@ -19370,15 +20179,21 @@ var BeamApp = class extends i4 {
|
|
|
19370
20179
|
*/
|
|
19371
20180
|
_handleGlobalMethodSelect(photon, method) {
|
|
19372
20181
|
this._teardownActiveCustomUI();
|
|
20182
|
+
if (this._selectedPhoton?.name !== photon.name) {
|
|
20183
|
+
this._closeSecondPanel();
|
|
20184
|
+
}
|
|
19373
20185
|
this._selectedPhoton = photon;
|
|
19374
20186
|
if (this._willAutoInvoke(method)) {
|
|
19375
20187
|
this._isExecuting = true;
|
|
19376
20188
|
}
|
|
19377
20189
|
this._selectedMethod = method;
|
|
19378
20190
|
this._view = "form";
|
|
19379
|
-
this.
|
|
20191
|
+
this._updateRoute();
|
|
19380
20192
|
this._maybeAutoInvoke(method);
|
|
19381
20193
|
}
|
|
20194
|
+
get _splitViewEnabled() {
|
|
20195
|
+
return this._splitPanels.length > 0;
|
|
20196
|
+
}
|
|
19382
20197
|
connectedCallback() {
|
|
19383
20198
|
super.connectedCallback();
|
|
19384
20199
|
const savedTheme = localStorage.getItem(THEME_STORAGE_KEY);
|
|
@@ -19410,20 +20225,114 @@ var BeamApp = class extends i4 {
|
|
|
19410
20225
|
}
|
|
19411
20226
|
document.addEventListener("click", this._handleDocumentClick);
|
|
19412
20227
|
void this._connectMCP();
|
|
19413
|
-
|
|
19414
|
-
window.addEventListener("popstate", this.
|
|
20228
|
+
this._setupNotificationHandlers();
|
|
20229
|
+
window.addEventListener("popstate", this._handleRouteChange);
|
|
19415
20230
|
window.addEventListener("message", this._handleBridgeMessage);
|
|
19416
20231
|
window.addEventListener("keydown", this._handleKeydown);
|
|
20232
|
+
this._initPWA();
|
|
19417
20233
|
}
|
|
19418
20234
|
disconnectedCallback() {
|
|
19419
20235
|
super.disconnectedCallback();
|
|
19420
|
-
window.removeEventListener("
|
|
19421
|
-
window.removeEventListener("popstate", this._handlePopState);
|
|
20236
|
+
window.removeEventListener("popstate", this._handleRouteChange);
|
|
19422
20237
|
window.removeEventListener("message", this._handleBridgeMessage);
|
|
19423
20238
|
window.removeEventListener("keydown", this._handleKeydown);
|
|
19424
20239
|
document.removeEventListener("click", this._handleDocumentClick);
|
|
19425
20240
|
this._cleanupCollectionSubscriptions();
|
|
19426
20241
|
}
|
|
20242
|
+
willUpdate(changedProperties) {
|
|
20243
|
+
super.willUpdate(changedProperties);
|
|
20244
|
+
if (changedProperties.has("_selectedPhoton")) {
|
|
20245
|
+
const name2 = this._selectedPhoton?.name || null;
|
|
20246
|
+
if (name2 !== this._pwaCurrentPhoton) {
|
|
20247
|
+
this._pwaCurrentPhoton = name2;
|
|
20248
|
+
if (name2) {
|
|
20249
|
+
this._setupPWAManifest(name2);
|
|
20250
|
+
}
|
|
20251
|
+
}
|
|
20252
|
+
}
|
|
20253
|
+
}
|
|
20254
|
+
// ---------------------------------------------------------------------------
|
|
20255
|
+
// PWA — Progressive Web App support
|
|
20256
|
+
// ---------------------------------------------------------------------------
|
|
20257
|
+
_initPWA() {
|
|
20258
|
+
this._pwaIsStandalone = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true;
|
|
20259
|
+
if ("serviceWorker" in navigator) {
|
|
20260
|
+
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));
|
|
20261
|
+
}
|
|
20262
|
+
window.addEventListener("beforeinstallprompt", (e8) => {
|
|
20263
|
+
this._pwaInstallPrompt = e8;
|
|
20264
|
+
});
|
|
20265
|
+
window.addEventListener("appinstalled", () => {
|
|
20266
|
+
this._pwaInstallPrompt = null;
|
|
20267
|
+
this._log("info", "PWA app installed");
|
|
20268
|
+
});
|
|
20269
|
+
}
|
|
20270
|
+
/**
|
|
20271
|
+
* Set up notification handlers for photon notifications.
|
|
20272
|
+
* When a notification arrives for a photon that cares about that event type,
|
|
20273
|
+
* bring the window to focus (especially important for PWAs/background tabs).
|
|
20274
|
+
*/
|
|
20275
|
+
_setupNotificationHandlers() {
|
|
20276
|
+
mcpClient.on("photon-notification", (notification) => {
|
|
20277
|
+
const { photon, type, priority } = notification;
|
|
20278
|
+
if (!photon || !type) return;
|
|
20279
|
+
const sidebarElement = this.querySelector("beam-sidebar");
|
|
20280
|
+
if (sidebarElement && sidebarElement.isNotificationWatched) {
|
|
20281
|
+
const isWatched = sidebarElement.isNotificationWatched(photon, type);
|
|
20282
|
+
if (isWatched) {
|
|
20283
|
+
window.focus();
|
|
20284
|
+
console.log(`\u{1F4E1} Window focused for ${photon} notification: ${type}`);
|
|
20285
|
+
sidebarElement.updatePhotonWarmth?.(photon);
|
|
20286
|
+
}
|
|
20287
|
+
}
|
|
20288
|
+
});
|
|
20289
|
+
}
|
|
20290
|
+
/**
|
|
20291
|
+
* Set up the PWA manifest & icons for the currently selected photon.
|
|
20292
|
+
* Called whenever the selected photon changes. The manifest points to
|
|
20293
|
+
* /api/pwa/icon-png URLs which the service worker intercepts and renders
|
|
20294
|
+
* as real PNGs via OffscreenCanvas — no client-side blob URL needed.
|
|
20295
|
+
*/
|
|
20296
|
+
_setupPWAManifest(photonName) {
|
|
20297
|
+
let manifestLink = document.head.querySelector('link[rel="manifest"]');
|
|
20298
|
+
if (!manifestLink) {
|
|
20299
|
+
manifestLink = document.createElement("link");
|
|
20300
|
+
manifestLink.rel = "manifest";
|
|
20301
|
+
document.head.appendChild(manifestLink);
|
|
20302
|
+
}
|
|
20303
|
+
manifestLink.href = `/api/pwa/manifest.json?photon=${encodeURIComponent(photonName)}`;
|
|
20304
|
+
let appleIcon = document.head.querySelector('link[rel="apple-touch-icon"]');
|
|
20305
|
+
if (!appleIcon) {
|
|
20306
|
+
appleIcon = document.createElement("link");
|
|
20307
|
+
appleIcon.rel = "apple-touch-icon";
|
|
20308
|
+
document.head.appendChild(appleIcon);
|
|
20309
|
+
}
|
|
20310
|
+
appleIcon.href = `/api/pwa/icon?photon=${encodeURIComponent(photonName)}`;
|
|
20311
|
+
let appleTitleMeta = document.head.querySelector(
|
|
20312
|
+
'meta[name="apple-mobile-web-app-title"]'
|
|
20313
|
+
);
|
|
20314
|
+
if (!appleTitleMeta) {
|
|
20315
|
+
appleTitleMeta = document.createElement("meta");
|
|
20316
|
+
appleTitleMeta.name = "apple-mobile-web-app-title";
|
|
20317
|
+
document.head.appendChild(appleTitleMeta);
|
|
20318
|
+
}
|
|
20319
|
+
appleTitleMeta.content = photonName;
|
|
20320
|
+
this._prewarmIconCache(photonName);
|
|
20321
|
+
this._log("info", `PWA manifest set for "${photonName}"`, true);
|
|
20322
|
+
}
|
|
20323
|
+
/**
|
|
20324
|
+
* Pre-warm the service worker icon cache by fetching the PNG icon URLs.
|
|
20325
|
+
* This ensures the rendered emoji icons are cached before the user
|
|
20326
|
+
* attempts to install the PWA, improving the install dialog appearance.
|
|
20327
|
+
*/
|
|
20328
|
+
_prewarmIconCache(photonName) {
|
|
20329
|
+
const sizes = [192, 512];
|
|
20330
|
+
sizes.forEach((size) => {
|
|
20331
|
+
const url2 = `/api/pwa/icon-png?photon=${encodeURIComponent(photonName)}&size=${size}`;
|
|
20332
|
+
fetch(url2, { mode: "no-cors" }).catch(() => {
|
|
20333
|
+
});
|
|
20334
|
+
});
|
|
20335
|
+
}
|
|
19427
20336
|
async _connectMCP() {
|
|
19428
20337
|
try {
|
|
19429
20338
|
mcpClient.on("connect", () => {
|
|
@@ -19451,12 +20360,24 @@ var BeamApp = class extends i4 {
|
|
|
19451
20360
|
}
|
|
19452
20361
|
this._initialConnectDone = true;
|
|
19453
20362
|
void this._checkForUpdates();
|
|
19454
|
-
if (window.location.
|
|
19455
|
-
void this.
|
|
20363
|
+
if (window.location.pathname !== "/") {
|
|
20364
|
+
void this._handleRouteChange();
|
|
19456
20365
|
} else if (!this._selectedPhoton && this._photons.length > 0) {
|
|
19457
20366
|
const firstUserPhoton = this._photons.find((p5) => !p5.internal);
|
|
19458
|
-
if (firstUserPhoton)
|
|
19459
|
-
|
|
20367
|
+
if (firstUserPhoton) {
|
|
20368
|
+
this._selectedPhoton = firstUserPhoton;
|
|
20369
|
+
if (firstUserPhoton.isApp && firstUserPhoton.appEntry) {
|
|
20370
|
+
if (this._willAutoInvoke(firstUserPhoton.appEntry)) {
|
|
20371
|
+
this._isExecuting = true;
|
|
20372
|
+
}
|
|
20373
|
+
this._selectedMethod = firstUserPhoton.appEntry;
|
|
20374
|
+
this._view = "form";
|
|
20375
|
+
this._maybeAutoInvoke(firstUserPhoton.appEntry);
|
|
20376
|
+
} else {
|
|
20377
|
+
this._view = "list";
|
|
20378
|
+
}
|
|
20379
|
+
}
|
|
20380
|
+
this._updateRoute(true);
|
|
19460
20381
|
}
|
|
19461
20382
|
})();
|
|
19462
20383
|
});
|
|
@@ -19475,15 +20396,37 @@ var BeamApp = class extends i4 {
|
|
|
19475
20396
|
this._photons = photons;
|
|
19476
20397
|
this._externalMCPs = externalMCPs;
|
|
19477
20398
|
this._addUnconfiguredPhotons();
|
|
19478
|
-
if (
|
|
19479
|
-
const
|
|
19480
|
-
|
|
19481
|
-
|
|
19482
|
-
|
|
19483
|
-
this.
|
|
19484
|
-
|
|
19485
|
-
|
|
19486
|
-
|
|
20399
|
+
if (this._selectedPhoton) {
|
|
20400
|
+
const updated = this._photons.find((p5) => p5.name === this._selectedPhoton?.name);
|
|
20401
|
+
if (updated) {
|
|
20402
|
+
const wasApp = this._selectedPhoton.isApp;
|
|
20403
|
+
this._selectedPhoton = updated;
|
|
20404
|
+
if (!wasApp && updated.isApp && updated.appEntry && this._view === "list") {
|
|
20405
|
+
if (this._willAutoInvoke(updated.appEntry)) {
|
|
20406
|
+
this._isExecuting = true;
|
|
20407
|
+
}
|
|
20408
|
+
this._selectedMethod = updated.appEntry;
|
|
20409
|
+
this._view = "form";
|
|
20410
|
+
this._updateRoute(true);
|
|
20411
|
+
this._maybeAutoInvoke(updated.appEntry);
|
|
20412
|
+
}
|
|
20413
|
+
}
|
|
20414
|
+
}
|
|
20415
|
+
if (!this._selectedPhoton && window.location.pathname !== "/") {
|
|
20416
|
+
const pathPhotonName = window.location.pathname.slice(1).split("/")[0];
|
|
20417
|
+
const routePhoton = pathPhotonName ? this._photons.find((p5) => p5.name === pathPhotonName) : null;
|
|
20418
|
+
if (routePhoton) {
|
|
20419
|
+
void this._handleRouteChange();
|
|
20420
|
+
} else {
|
|
20421
|
+
const newUserPhoton = this._photons.find(
|
|
20422
|
+
(p5) => !p5.internal && p5.configured && !prevNames.has(p5.name)
|
|
20423
|
+
);
|
|
20424
|
+
if (newUserPhoton) {
|
|
20425
|
+
this._selectedPhoton = newUserPhoton;
|
|
20426
|
+
this._welcomePhase = "welcome";
|
|
20427
|
+
this._view = "list";
|
|
20428
|
+
this._updateRoute(true);
|
|
20429
|
+
}
|
|
19487
20430
|
}
|
|
19488
20431
|
}
|
|
19489
20432
|
})();
|
|
@@ -19547,7 +20490,7 @@ var BeamApp = class extends i4 {
|
|
|
19547
20490
|
this._selectedPhoton = updated;
|
|
19548
20491
|
}
|
|
19549
20492
|
} else {
|
|
19550
|
-
if (window.location.
|
|
20493
|
+
if (window.location.pathname === "/") return;
|
|
19551
20494
|
const newUserPhoton = this._photons.find(
|
|
19552
20495
|
(p5) => !p5.internal && p5.configured && !prevNames.has(p5.name)
|
|
19553
20496
|
);
|
|
@@ -19576,7 +20519,7 @@ var BeamApp = class extends i4 {
|
|
|
19576
20519
|
} else {
|
|
19577
20520
|
this._view = "list";
|
|
19578
20521
|
}
|
|
19579
|
-
this.
|
|
20522
|
+
this._updateRoute(true);
|
|
19580
20523
|
}
|
|
19581
20524
|
}
|
|
19582
20525
|
}
|
|
@@ -19628,7 +20571,7 @@ var BeamApp = class extends i4 {
|
|
|
19628
20571
|
} else {
|
|
19629
20572
|
this._view = "list";
|
|
19630
20573
|
}
|
|
19631
|
-
this.
|
|
20574
|
+
this._updateRoute(true);
|
|
19632
20575
|
}
|
|
19633
20576
|
}
|
|
19634
20577
|
});
|
|
@@ -19739,20 +20682,27 @@ var BeamApp = class extends i4 {
|
|
|
19739
20682
|
}
|
|
19740
20683
|
}
|
|
19741
20684
|
}
|
|
19742
|
-
|
|
19743
|
-
let
|
|
20685
|
+
_updateRoute(replace2 = false) {
|
|
20686
|
+
let path;
|
|
19744
20687
|
if (!this._selectedPhoton) {
|
|
19745
|
-
|
|
20688
|
+
path = "/";
|
|
19746
20689
|
} else {
|
|
19747
|
-
|
|
20690
|
+
path = "/" + this._selectedPhoton.name;
|
|
19748
20691
|
if (this._selectedMethod) {
|
|
19749
|
-
|
|
20692
|
+
path += `/${this._selectedMethod.name}`;
|
|
20693
|
+
for (const panel of this._splitPanels) {
|
|
20694
|
+
if (panel.type === "method" && panel.method) {
|
|
20695
|
+
path += `+${panel.method.name}`;
|
|
20696
|
+
} else if (panel.type === "source") {
|
|
20697
|
+
path += `+source`;
|
|
20698
|
+
}
|
|
20699
|
+
}
|
|
19750
20700
|
}
|
|
19751
20701
|
}
|
|
19752
20702
|
if (replace2) {
|
|
19753
|
-
history.replaceState(null, "",
|
|
20703
|
+
history.replaceState(null, "", path);
|
|
19754
20704
|
} else {
|
|
19755
|
-
history.pushState(null, "",
|
|
20705
|
+
history.pushState(null, "", path);
|
|
19756
20706
|
}
|
|
19757
20707
|
}
|
|
19758
20708
|
/**
|
|
@@ -19803,6 +20753,21 @@ var BeamApp = class extends i4 {
|
|
|
19803
20753
|
if (!this._selectedPhoton?.methods) return [];
|
|
19804
20754
|
return this._selectedPhoton.methods.filter((m3) => m3.name.startsWith("test_") || m3.name.startsWith("test")).map((m3) => m3.name);
|
|
19805
20755
|
}
|
|
20756
|
+
/** Fetch all tests (external .test.ts + inline) from the server */
|
|
20757
|
+
async _fetchTestList(photonName) {
|
|
20758
|
+
try {
|
|
20759
|
+
const res = await fetch(`/api/test/list?photon=${encodeURIComponent(photonName)}`, {
|
|
20760
|
+
signal: AbortSignal.timeout(5e3)
|
|
20761
|
+
});
|
|
20762
|
+
if (!res.ok) return this._getTestMethods();
|
|
20763
|
+
const data = await res.json();
|
|
20764
|
+
if (data.tests && data.tests.length > 0) {
|
|
20765
|
+
return data.tests.map((t8) => t8.name);
|
|
20766
|
+
}
|
|
20767
|
+
} catch {
|
|
20768
|
+
}
|
|
20769
|
+
return this._getTestMethods();
|
|
20770
|
+
}
|
|
19806
20771
|
_getAllTestMethods() {
|
|
19807
20772
|
const results = [];
|
|
19808
20773
|
for (const p5 of this._photons) {
|
|
@@ -20126,7 +21091,7 @@ var BeamApp = class extends i4 {
|
|
|
20126
21091
|
}}
|
|
20127
21092
|
@diagnostics=${() => {
|
|
20128
21093
|
this._view = "diagnostics";
|
|
20129
|
-
this.
|
|
21094
|
+
this._updateRoute();
|
|
20130
21095
|
}}
|
|
20131
21096
|
@open-studio=${(e8) => {
|
|
20132
21097
|
const photon = this._photons.find((p5) => p5.name === e8.detail.photonName);
|
|
@@ -20146,7 +21111,39 @@ var BeamApp = class extends i4 {
|
|
|
20146
21111
|
></beam-sidebar>
|
|
20147
21112
|
</nav>
|
|
20148
21113
|
|
|
20149
|
-
<main
|
|
21114
|
+
<main
|
|
21115
|
+
class="main-area"
|
|
21116
|
+
id="main-content"
|
|
21117
|
+
tabindex="-1"
|
|
21118
|
+
aria-label="Main content"
|
|
21119
|
+
style="${this._splitViewEnabled ? "overflow: hidden !important;" : ""}"
|
|
21120
|
+
>
|
|
21121
|
+
${this._selectedPhoton && this._selectedMethod ? b2`<button
|
|
21122
|
+
class="beam-back-btn"
|
|
21123
|
+
@click=${() => this._handleBackFromMethod()}
|
|
21124
|
+
@mouseenter=${(e8) => {
|
|
21125
|
+
e8.target.style.color = "var(--t-primary)";
|
|
21126
|
+
e8.target.style.borderColor = "var(--accent-primary)";
|
|
21127
|
+
}}
|
|
21128
|
+
@mouseleave=${(e8) => {
|
|
21129
|
+
e8.target.style.color = "var(--t-muted)";
|
|
21130
|
+
e8.target.style.borderColor = "var(--border-glass)";
|
|
21131
|
+
}}
|
|
21132
|
+
title="Back to ${this._selectedPhoton.name}"
|
|
21133
|
+
>
|
|
21134
|
+
<svg
|
|
21135
|
+
width="16"
|
|
21136
|
+
height="16"
|
|
21137
|
+
viewBox="0 0 24 24"
|
|
21138
|
+
fill="none"
|
|
21139
|
+
stroke="currentColor"
|
|
21140
|
+
stroke-width="2"
|
|
21141
|
+
stroke-linecap="round"
|
|
21142
|
+
stroke-linejoin="round"
|
|
21143
|
+
>
|
|
21144
|
+
<path d="m15 18-6-6 6-6" />
|
|
21145
|
+
</svg>
|
|
21146
|
+
</button>` : ""}
|
|
20150
21147
|
${this._selectedPhoton ? b2`<button
|
|
20151
21148
|
class="beam-fullscreen-btn"
|
|
20152
21149
|
@click=${this._toggleFocusMode}
|
|
@@ -20582,7 +21579,7 @@ var BeamApp = class extends i4 {
|
|
|
20582
21579
|
}}
|
|
20583
21580
|
@click=${() => {
|
|
20584
21581
|
this._view = "diagnostics";
|
|
20585
|
-
this.
|
|
21582
|
+
this._updateRoute();
|
|
20586
21583
|
}}
|
|
20587
21584
|
>
|
|
20588
21585
|
<span style="font-size: 1rem; width: 20px; text-align: center;">🔍</span>
|
|
@@ -20791,7 +21788,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
20791
21788
|
@select=${(e8) => {
|
|
20792
21789
|
this._selectedMethod = e8.detail.method;
|
|
20793
21790
|
this._view = "form";
|
|
20794
|
-
this.
|
|
21791
|
+
this._updateRoute();
|
|
20795
21792
|
}}
|
|
20796
21793
|
></method-card>
|
|
20797
21794
|
`
|
|
@@ -20808,7 +21805,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
20808
21805
|
if (this._selectedMethod.linkedUi) {
|
|
20809
21806
|
const isAppMain = this._selectedPhoton.isApp && this._selectedMethod.name === "main";
|
|
20810
21807
|
const otherMethods = isAppMain ? this._getVisibleMethods().filter((m3) => m3.name !== "main") : [];
|
|
20811
|
-
const
|
|
21808
|
+
const isExternalMCP = this._selectedPhoton.isExternalMCP;
|
|
20812
21809
|
const appRenderer = this._isExecuting ? b2`
|
|
20813
21810
|
<div
|
|
20814
21811
|
style="display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; height: calc(100vh - 140px);"
|
|
@@ -20818,7 +21815,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
20818
21815
|
${this._progress?.message || "Starting up\u2026"}
|
|
20819
21816
|
</span>
|
|
20820
21817
|
</div>
|
|
20821
|
-
` :
|
|
21818
|
+
` : isExternalMCP ? b2`
|
|
20822
21819
|
<mcp-app-renderer
|
|
20823
21820
|
.mcpName=${this._selectedPhoton.name}
|
|
20824
21821
|
.appUri=${`ui://${this._selectedPhoton.name}/${this._selectedMethod.linkedUi}`}
|
|
@@ -20837,7 +21834,48 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
20837
21834
|
></custom-ui-renderer>
|
|
20838
21835
|
`;
|
|
20839
21836
|
if (isAppMain) {
|
|
21837
|
+
if (this._splitPanels.length > 0) {
|
|
21838
|
+
return b2`
|
|
21839
|
+
<div style="display: flex; gap: 1px; height: calc(100vh - 60px); overflow: hidden;">
|
|
21840
|
+
<!-- App Panel (primary) — no title bar, app has its own chrome -->
|
|
21841
|
+
<div style="flex: 1; min-height: 0; overflow: hidden;">${appRenderer}</div>
|
|
21842
|
+
|
|
21843
|
+
<!-- Additional Panels -->
|
|
21844
|
+
${this._splitPanels.map(
|
|
21845
|
+
(panel) => b2`
|
|
21846
|
+
<div style="flex: 1; min-height: 0; background: var(--bg-panel);">
|
|
21847
|
+
${panel.type === "method" ? this._renderSinglePanel(this._buildAdditionalPanelOpts(panel)) : this._renderSourcePanel(panel.id)}
|
|
21848
|
+
</div>
|
|
21849
|
+
`
|
|
21850
|
+
)}
|
|
21851
|
+
</div>
|
|
21852
|
+
`;
|
|
21853
|
+
}
|
|
20840
21854
|
return b2`
|
|
21855
|
+
<!-- Floating add-panel button for app view — sits next to focus button -->
|
|
21856
|
+
<div
|
|
21857
|
+
style="position: sticky; top: calc(-1 * var(--space-lg)); float: right; z-index: 100; margin-top: calc(-1 * var(--space-lg)); margin-right: 6px;"
|
|
21858
|
+
>
|
|
21859
|
+
<button
|
|
21860
|
+
@click=${() => {
|
|
21861
|
+
this._methodPickerOpen = !this._methodPickerOpen;
|
|
21862
|
+
this._methodPickerPanelId = null;
|
|
21863
|
+
}}
|
|
21864
|
+
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);"
|
|
21865
|
+
@mouseenter=${(e8) => {
|
|
21866
|
+
e8.target.style.color = "var(--accent-secondary)";
|
|
21867
|
+
e8.target.style.borderColor = "var(--accent-secondary)";
|
|
21868
|
+
}}
|
|
21869
|
+
@mouseleave=${(e8) => {
|
|
21870
|
+
e8.target.style.color = "var(--t-muted)";
|
|
21871
|
+
e8.target.style.borderColor = "var(--border-glass)";
|
|
21872
|
+
}}
|
|
21873
|
+
title="Add panel"
|
|
21874
|
+
>
|
|
21875
|
+
+
|
|
21876
|
+
</button>
|
|
21877
|
+
${this._methodPickerOpen && this._methodPickerPanelId === null ? this._renderMethodPickerPopover() : ""}
|
|
21878
|
+
</div>
|
|
20841
21879
|
<app-layout
|
|
20842
21880
|
.photonName=${this._selectedPhoton.name}
|
|
20843
21881
|
.photonIcon=${this._selectedPhoton.appEntry?.icon || "\u{1F4F1}"}
|
|
@@ -20880,61 +21918,72 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
20880
21918
|
</app-layout>
|
|
20881
21919
|
`;
|
|
20882
21920
|
}
|
|
21921
|
+
if (this._splitPanels.length > 0) {
|
|
21922
|
+
return b2`
|
|
21923
|
+
<div style="display: flex; gap: 1px; height: calc(100vh - 60px); overflow: hidden;">
|
|
21924
|
+
<!-- Linked UI Panel (primary) -->
|
|
21925
|
+
<div
|
|
21926
|
+
style="flex: 1; min-height: 0; display: flex; flex-direction: column; position: relative;"
|
|
21927
|
+
>
|
|
21928
|
+
<div
|
|
21929
|
+
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;"
|
|
21930
|
+
>
|
|
21931
|
+
<span style="font-size: 12px; font-weight: 500; color: var(--t-primary);"
|
|
21932
|
+
>${this._selectedMethod.name}</span
|
|
21933
|
+
>
|
|
21934
|
+
<div style="position: relative; flex-shrink: 0;">
|
|
21935
|
+
<button
|
|
21936
|
+
@click=${() => {
|
|
21937
|
+
this._methodPickerOpen = !this._methodPickerOpen;
|
|
21938
|
+
this._methodPickerPanelId = null;
|
|
21939
|
+
}}
|
|
21940
|
+
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;"
|
|
21941
|
+
title="Add panel"
|
|
21942
|
+
>
|
|
21943
|
+
+
|
|
21944
|
+
</button>
|
|
21945
|
+
${this._methodPickerOpen && this._methodPickerPanelId === null ? this._renderMethodPickerPopover() : ""}
|
|
21946
|
+
</div>
|
|
21947
|
+
</div>
|
|
21948
|
+
<div style="flex: 1; min-height: 0; overflow: hidden;">${appRenderer}</div>
|
|
21949
|
+
</div>
|
|
21950
|
+
|
|
21951
|
+
<!-- Additional Panels -->
|
|
21952
|
+
${this._splitPanels.map(
|
|
21953
|
+
(panel) => b2`
|
|
21954
|
+
<div style="flex: 1; min-height: 0; background: var(--bg-panel);">
|
|
21955
|
+
${panel.type === "method" ? this._renderSinglePanel(this._buildAdditionalPanelOpts(panel)) : this._renderSourcePanel(panel.id)}
|
|
21956
|
+
</div>
|
|
21957
|
+
`
|
|
21958
|
+
)}
|
|
21959
|
+
</div>
|
|
21960
|
+
`;
|
|
21961
|
+
}
|
|
20883
21962
|
return b2`
|
|
20884
|
-
<
|
|
20885
|
-
|
|
20886
|
-
|
|
20887
|
-
|
|
20888
|
-
|
|
20889
|
-
|
|
20890
|
-
|
|
20891
|
-
|
|
20892
|
-
|
|
20893
|
-
|
|
20894
|
-
|
|
20895
|
-
|
|
20896
|
-
|
|
20897
|
-
|
|
20898
|
-
|
|
20899
|
-
|
|
20900
|
-
|
|
20901
|
-
|
|
20902
|
-
|
|
20903
|
-
|
|
20904
|
-
style="padding: 0; overflow: hidden; min-height: calc(100vh - 80px); margin-top: var(--space-md);"
|
|
20905
|
-
>
|
|
20906
|
-
${appRenderer}
|
|
21963
|
+
<div style="position: relative;">
|
|
21964
|
+
<div style="position: absolute; top: 16px; right: 16px; z-index: 50;">
|
|
21965
|
+
<button
|
|
21966
|
+
@click=${() => {
|
|
21967
|
+
this._methodPickerOpen = !this._methodPickerOpen;
|
|
21968
|
+
this._methodPickerPanelId = null;
|
|
21969
|
+
}}
|
|
21970
|
+
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);"
|
|
21971
|
+
title="Add panel"
|
|
21972
|
+
>
|
|
21973
|
+
+
|
|
21974
|
+
</button>
|
|
21975
|
+
${this._methodPickerOpen && this._methodPickerPanelId === null ? this._renderMethodPickerPopover() : ""}
|
|
21976
|
+
</div>
|
|
21977
|
+
<div
|
|
21978
|
+
class="glass-panel"
|
|
21979
|
+
style="padding: 0; overflow: hidden; min-height: calc(100vh - 80px); margin-top: var(--space-md);"
|
|
21980
|
+
>
|
|
21981
|
+
${appRenderer}
|
|
21982
|
+
</div>
|
|
20907
21983
|
</div>
|
|
20908
21984
|
`;
|
|
20909
21985
|
}
|
|
20910
|
-
|
|
20911
|
-
return b2`
|
|
20912
|
-
<context-bar
|
|
20913
|
-
.photon=${this._selectedPhoton}
|
|
20914
|
-
.breadcrumbs=${[
|
|
20915
|
-
{
|
|
20916
|
-
label: this._currentInstance !== "default" ? `${this._selectedPhoton.name}:${this._currentInstance}` : this._selectedPhoton.name,
|
|
20917
|
-
action: "back"
|
|
20918
|
-
},
|
|
20919
|
-
{ label: formatLabel(this._selectedMethod.name) }
|
|
20920
|
-
]}
|
|
20921
|
-
.live=${this._currentCollectionName !== null}
|
|
20922
|
-
.showEdit=${false}
|
|
20923
|
-
.showConfigure=${false}
|
|
20924
|
-
.showCopyConfig=${false}
|
|
20925
|
-
.overflowItems=${this._buildOverflowItems({
|
|
20926
|
-
showRefresh: !isExternalMCP,
|
|
20927
|
-
showRename: false,
|
|
20928
|
-
showViewSource: false,
|
|
20929
|
-
showDelete: false,
|
|
20930
|
-
showHelp: !isExternalMCP
|
|
20931
|
-
})}
|
|
20932
|
-
.instanceSelectorMode=${this._instanceSelectorMode}
|
|
20933
|
-
.autoInstance=${this._autoInstance}
|
|
20934
|
-
@context-action=${this._handleContextAction}
|
|
20935
|
-
></context-bar>
|
|
20936
|
-
${this._renderMethodContent()}
|
|
20937
|
-
`;
|
|
21986
|
+
return b2` ${this._renderMethodContent()} `;
|
|
20938
21987
|
}
|
|
20939
21988
|
return b2`
|
|
20940
21989
|
${this._renderPhotonToolbar()} ${this._editingIcon ? this._renderEmojiPicker() : ""}
|
|
@@ -21062,6 +22111,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21062
22111
|
}
|
|
21063
22112
|
}
|
|
21064
22113
|
async _handlePhotonSelect(e8) {
|
|
22114
|
+
this._closeSecondPanel();
|
|
21065
22115
|
this._selectedPhoton = e8.detail.photon;
|
|
21066
22116
|
this._selectedMethod = null;
|
|
21067
22117
|
this._lastResult = null;
|
|
@@ -21069,12 +22119,12 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21069
22119
|
this._currentInstance = "default";
|
|
21070
22120
|
if (this._selectedPhoton.configured === false) {
|
|
21071
22121
|
this._view = "config";
|
|
21072
|
-
this.
|
|
22122
|
+
this._updateRoute();
|
|
21073
22123
|
return;
|
|
21074
22124
|
}
|
|
21075
22125
|
if (this._selectedPhoton.isExternalMCP && this._selectedPhoton.hasMcpApp) {
|
|
21076
22126
|
this._view = "mcp-app";
|
|
21077
|
-
this.
|
|
22127
|
+
this._updateRoute();
|
|
21078
22128
|
return;
|
|
21079
22129
|
}
|
|
21080
22130
|
if (this._selectedPhoton.stateful && this._selectedPhoton.configured) {
|
|
@@ -21101,13 +22151,13 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21101
22151
|
}
|
|
21102
22152
|
this._selectedMethod = this._selectedPhoton.appEntry;
|
|
21103
22153
|
this._view = "form";
|
|
21104
|
-
this.
|
|
22154
|
+
this._updateRoute();
|
|
21105
22155
|
this._maybeAutoInvoke(this._selectedPhoton.appEntry);
|
|
21106
22156
|
return;
|
|
21107
22157
|
} else {
|
|
21108
22158
|
this._view = "list";
|
|
21109
22159
|
}
|
|
21110
|
-
this.
|
|
22160
|
+
this._updateRoute();
|
|
21111
22161
|
}
|
|
21112
22162
|
/** Fetch available instances for a stateful photon from the server */
|
|
21113
22163
|
async _fetchInstances(photonName) {
|
|
@@ -21150,7 +22200,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21150
22200
|
/**
|
|
21151
22201
|
* Trigger instance switch via MCP elicitation (calls _use without name).
|
|
21152
22202
|
* The transport layer shows an elicitation modal with available instances.
|
|
21153
|
-
* After _use succeeds, the transport broadcasts
|
|
22203
|
+
* After _use succeeds, the transport broadcasts state-changed which
|
|
21154
22204
|
* triggers _silentRefresh() to update the result and notifies custom UIs.
|
|
21155
22205
|
*/
|
|
21156
22206
|
async _switchInstance() {
|
|
@@ -21186,7 +22236,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21186
22236
|
this._selectedMethod = e8.detail.method;
|
|
21187
22237
|
this._lastResult = null;
|
|
21188
22238
|
this._view = "form";
|
|
21189
|
-
this.
|
|
22239
|
+
this._updateRoute();
|
|
21190
22240
|
this._maybeAutoInvoke(e8.detail.method);
|
|
21191
22241
|
}
|
|
21192
22242
|
/**
|
|
@@ -21248,57 +22298,507 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21248
22298
|
</div>
|
|
21249
22299
|
`;
|
|
21250
22300
|
}
|
|
22301
|
+
if (this._splitPanels.length > 0) {
|
|
22302
|
+
return b2`
|
|
22303
|
+
<div style="display: flex; gap: 1px; height: 100%; overflow: hidden;">
|
|
22304
|
+
<!-- Primary Panel -->
|
|
22305
|
+
<div style="flex: 1; min-height: 0; background: var(--bg-panel);">
|
|
22306
|
+
${this._renderSinglePanel({
|
|
22307
|
+
photon: this._selectedPhoton,
|
|
22308
|
+
method: this._selectedMethod,
|
|
22309
|
+
result: this._lastResult,
|
|
22310
|
+
executing: this._isExecuting,
|
|
22311
|
+
progress: this._progress,
|
|
22312
|
+
formParams: this._lastFormParams,
|
|
22313
|
+
onSubmit: (e8) => void this._handleExecute(e8),
|
|
22314
|
+
onCancel: () => this._handleBackFromMethod(),
|
|
22315
|
+
panelLabel: "Primary",
|
|
22316
|
+
instance: this._currentInstance,
|
|
22317
|
+
instances: this._instances,
|
|
22318
|
+
onInstanceChange: (instance) => this._handleLeftPanelInstanceChange(instance),
|
|
22319
|
+
allMethods: this._selectedPhoton?.methods || [],
|
|
22320
|
+
onMethodChange: (method) => this._handleLeftPanelMethodChange(method),
|
|
22321
|
+
panelSide: "primary",
|
|
22322
|
+
onPanelAction: (action) => this._handlePrimaryPanelAction(action),
|
|
22323
|
+
onInstanceAction: (detail) => void this._handleInstanceAction(detail),
|
|
22324
|
+
isStateful: !!this._selectedPhoton?.stateful,
|
|
22325
|
+
isLive: this._currentCollectionName !== null,
|
|
22326
|
+
overflowItems: this._buildOverflowItems({
|
|
22327
|
+
showRefresh: !this._selectedPhoton?.isExternalMCP,
|
|
22328
|
+
showRename: false,
|
|
22329
|
+
showViewSource: false,
|
|
22330
|
+
showDelete: false,
|
|
22331
|
+
showHelp: !this._selectedPhoton?.isExternalMCP
|
|
22332
|
+
}),
|
|
22333
|
+
onOverflowSelect: (id2) => this._handleOverflowAction(id2)
|
|
22334
|
+
})}
|
|
22335
|
+
</div>
|
|
22336
|
+
|
|
22337
|
+
<!-- Additional Panels -->
|
|
22338
|
+
${this._splitPanels.map(
|
|
22339
|
+
(panel) => b2`
|
|
22340
|
+
<div style="flex: 1; min-height: 0; background: var(--bg-panel);">
|
|
22341
|
+
${panel.type === "method" ? this._renderSinglePanel(this._buildAdditionalPanelOpts(panel)) : this._renderSourcePanel(panel.id)}
|
|
22342
|
+
</div>
|
|
22343
|
+
`
|
|
22344
|
+
)}
|
|
22345
|
+
</div>
|
|
22346
|
+
`;
|
|
22347
|
+
}
|
|
22348
|
+
return this._renderSinglePanel({
|
|
22349
|
+
photon: this._selectedPhoton,
|
|
22350
|
+
method: this._selectedMethod,
|
|
22351
|
+
result: this._lastResult,
|
|
22352
|
+
executing: this._isExecuting,
|
|
22353
|
+
progress: this._progress,
|
|
22354
|
+
formParams: this._lastFormParams,
|
|
22355
|
+
onSubmit: (e8) => void this._handleExecute(e8),
|
|
22356
|
+
onCancel: () => this._handleBackFromMethod(),
|
|
22357
|
+
panelLabel: "Primary",
|
|
22358
|
+
instance: this._currentInstance,
|
|
22359
|
+
instances: this._instances,
|
|
22360
|
+
allMethods: this._selectedPhoton?.methods || [],
|
|
22361
|
+
onMethodChange: (method) => {
|
|
22362
|
+
this._selectedMethod = method;
|
|
22363
|
+
this._lastResult = null;
|
|
22364
|
+
this._lastFormParams = {};
|
|
22365
|
+
if (this._willAutoInvoke(method)) {
|
|
22366
|
+
void this._handleExecute(new CustomEvent("execute", { detail: { args: {} } }));
|
|
22367
|
+
}
|
|
22368
|
+
this._updateRoute();
|
|
22369
|
+
},
|
|
22370
|
+
panelSide: "primary",
|
|
22371
|
+
onPanelAction: (action) => this._handlePrimaryPanelAction(action),
|
|
22372
|
+
onInstanceAction: (detail) => void this._handleInstanceAction(detail),
|
|
22373
|
+
isStateful: !!this._selectedPhoton?.stateful,
|
|
22374
|
+
isLive: this._currentCollectionName !== null,
|
|
22375
|
+
overflowItems: this._buildOverflowItems({
|
|
22376
|
+
showRefresh: !this._selectedPhoton?.isExternalMCP,
|
|
22377
|
+
showRename: false,
|
|
22378
|
+
showViewSource: false,
|
|
22379
|
+
showDelete: false,
|
|
22380
|
+
showHelp: !this._selectedPhoton?.isExternalMCP
|
|
22381
|
+
}),
|
|
22382
|
+
onOverflowSelect: (id2) => this._handleOverflowAction(id2)
|
|
22383
|
+
});
|
|
22384
|
+
}
|
|
22385
|
+
/** Render a single panel with self-contained header */
|
|
22386
|
+
_renderSinglePanel(opts) {
|
|
22387
|
+
const isSplit = this._splitPanels.length > 0;
|
|
21251
22388
|
return b2`
|
|
21252
|
-
<div
|
|
21253
|
-
|
|
21254
|
-
${
|
|
21255
|
-
|
|
21256
|
-
|
|
21257
|
-
|
|
21258
|
-
|
|
21259
|
-
|
|
21260
|
-
|
|
21261
|
-
|
|
21262
|
-
|
|
21263
|
-
|
|
22389
|
+
<div
|
|
22390
|
+
class="glass-panel method-detail"
|
|
22391
|
+
style="${isSplit ? "border-radius: 0; height: 100%;" : ""} display: flex; flex-direction: column;"
|
|
22392
|
+
>
|
|
22393
|
+
<!-- Panel Header: LED + Method ▼ + instance-panel + [+] + [⋯] + [×] -->
|
|
22394
|
+
<div
|
|
22395
|
+
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;"
|
|
22396
|
+
>
|
|
22397
|
+
<!-- LED dot (stateful/live indicator) -->
|
|
22398
|
+
${opts.isStateful ? b2`<span
|
|
22399
|
+
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"};"
|
|
22400
|
+
title="${opts.isLive ? "Live \u2014 stateful photon with active subscription" : "Stateful photon"}"
|
|
22401
|
+
></span>` : ""}
|
|
22402
|
+
|
|
22403
|
+
<!-- Method Selector (name as dropdown) -->
|
|
22404
|
+
<select
|
|
22405
|
+
.value=${opts.method.name}
|
|
22406
|
+
@change=${(e8) => {
|
|
22407
|
+
const methodName = e8.target.value;
|
|
22408
|
+
const method = opts.allMethods?.find((m3) => m3.name === methodName);
|
|
22409
|
+
if (method && opts.onMethodChange) {
|
|
22410
|
+
opts.onMethodChange(method);
|
|
22411
|
+
}
|
|
21264
22412
|
}}
|
|
21265
|
-
|
|
21266
|
-
|
|
22413
|
+
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;"
|
|
22414
|
+
>
|
|
22415
|
+
${opts.allMethods?.map(
|
|
22416
|
+
(m3) => b2`<option .selected=${m3.name === opts.method.name} value=${m3.name}>
|
|
22417
|
+
${m3.name}
|
|
22418
|
+
</option>`
|
|
22419
|
+
) || b2`<option value=${opts.method.name}>${opts.method.name}</option>`}
|
|
22420
|
+
</select>
|
|
21267
22421
|
|
|
21268
|
-
|
|
21269
|
-
|
|
21270
|
-
|
|
21271
|
-
|
|
21272
|
-
|
|
21273
|
-
|
|
21274
|
-
|
|
22422
|
+
<div style="flex: 1;"></div>
|
|
22423
|
+
|
|
22424
|
+
<!-- Rich Instance Selector -->
|
|
22425
|
+
${opts.isStateful && opts.instances && opts.instances.length > 0 && opts.onInstanceAction ? b2`
|
|
22426
|
+
<instance-panel
|
|
22427
|
+
.instanceName=${opts.instance || "default"}
|
|
22428
|
+
.instances=${opts.instances}
|
|
22429
|
+
.photonName=${opts.photon.name}
|
|
22430
|
+
.selectorMode=${this._instanceSelectorMode}
|
|
22431
|
+
.autoInstance=${this._autoInstance}
|
|
22432
|
+
@instance-action=${(e8) => opts.onInstanceAction?.(e8.detail)}
|
|
22433
|
+
></instance-panel>
|
|
22434
|
+
` : ""}
|
|
22435
|
+
|
|
22436
|
+
<!-- Add panel button (primary only) -->
|
|
22437
|
+
${opts.panelSide === "primary" ? b2`
|
|
22438
|
+
<div style="position: relative; flex-shrink: 0;">
|
|
22439
|
+
<button
|
|
22440
|
+
@click=${() => opts.onPanelAction?.("toggle-picker")}
|
|
22441
|
+
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;"
|
|
22442
|
+
title="Add panel"
|
|
22443
|
+
>
|
|
22444
|
+
+
|
|
22445
|
+
</button>
|
|
22446
|
+
${this._methodPickerOpen && this._methodPickerPanelId === null ? this._renderMethodPickerPopover() : ""}
|
|
21275
22447
|
</div>
|
|
21276
|
-
|
|
21277
|
-
|
|
21278
|
-
|
|
21279
|
-
|
|
21280
|
-
|
|
21281
|
-
|
|
21282
|
-
|
|
22448
|
+
` : ""}
|
|
22449
|
+
|
|
22450
|
+
<!-- Overflow menu -->
|
|
22451
|
+
${opts.overflowItems && opts.overflowItems.length > 0 ? b2`
|
|
22452
|
+
<overflow-menu
|
|
22453
|
+
.items=${opts.overflowItems}
|
|
22454
|
+
@menu-select=${(e8) => opts.onOverflowSelect?.(e8.detail.id)}
|
|
22455
|
+
></overflow-menu>
|
|
22456
|
+
` : ""}
|
|
22457
|
+
|
|
22458
|
+
<!-- Close button (additional panels only) -->
|
|
22459
|
+
${opts.panelSide === "additional" ? b2`
|
|
22460
|
+
<button
|
|
22461
|
+
@click=${() => opts.onPanelAction?.("close")}
|
|
22462
|
+
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;"
|
|
22463
|
+
title="Close panel"
|
|
22464
|
+
>
|
|
22465
|
+
×
|
|
22466
|
+
</button>
|
|
22467
|
+
` : ""}
|
|
22468
|
+
</div>
|
|
22469
|
+
<!-- Panel Content (scrollable) -->
|
|
22470
|
+
<div
|
|
22471
|
+
style="display: flex; flex-direction: column; flex: 1; min-height: 0; overflow-y: auto;"
|
|
22472
|
+
>
|
|
22473
|
+
${this._renderDescription(opts.method.description)}
|
|
22474
|
+
<invoke-form
|
|
22475
|
+
.params=${opts.method.params}
|
|
22476
|
+
.loading=${opts.executing}
|
|
22477
|
+
.photonName=${opts.photon.name}
|
|
22478
|
+
.methodName=${opts.method.name}
|
|
22479
|
+
.rememberValues=${this._rememberFormValues}
|
|
22480
|
+
.sharedValues=${opts.formParams}
|
|
22481
|
+
@submit=${opts.onSubmit}
|
|
22482
|
+
@cancel=${opts.onCancel}
|
|
22483
|
+
></invoke-form>
|
|
22484
|
+
|
|
22485
|
+
${opts.progress ? b2`
|
|
22486
|
+
<div class="progress-container">
|
|
22487
|
+
<div class="progress-bar-wrapper">
|
|
22488
|
+
<div
|
|
22489
|
+
class="progress-bar ${opts.progress.value < 0 ? "indeterminate" : ""}"
|
|
22490
|
+
style="width: ${opts.progress.value < 0 ? "30%" : Math.round(opts.progress.value * 100) + "%"}"
|
|
22491
|
+
></div>
|
|
22492
|
+
</div>
|
|
22493
|
+
<div class="progress-text">
|
|
22494
|
+
<span>${opts.progress.message}</span>
|
|
22495
|
+
</div>
|
|
22496
|
+
</div>
|
|
22497
|
+
` : ""}
|
|
22498
|
+
${opts.result !== null ? b2`
|
|
22499
|
+
<result-viewer
|
|
22500
|
+
.result=${opts.result}
|
|
22501
|
+
.outputFormat=${opts.method?.outputFormat}
|
|
22502
|
+
.layoutHints=${opts.method?.layoutHints}
|
|
22503
|
+
.theme=${this._theme}
|
|
22504
|
+
.live=${this._currentCollectionName !== null}
|
|
22505
|
+
.resultKey=${opts.photon && opts.method ? `${opts.photon.name}/${opts.method.name}` : void 0}
|
|
22506
|
+
@share=${() => this._handleShareResult()}
|
|
22507
|
+
></result-viewer>
|
|
22508
|
+
` : b2`
|
|
22509
|
+
<div class="empty-state-inline result-empty">
|
|
22510
|
+
<span class="empty-state-icon">${play}</span>
|
|
22511
|
+
<span>Run the method to see results here</span>
|
|
22512
|
+
</div>
|
|
22513
|
+
`}
|
|
22514
|
+
</div>
|
|
22515
|
+
</div>
|
|
22516
|
+
`;
|
|
22517
|
+
}
|
|
22518
|
+
/** Close all split panels and return to single-panel mode */
|
|
22519
|
+
_closeSecondPanel() {
|
|
22520
|
+
this._splitPanels = [];
|
|
22521
|
+
this._methodPickerOpen = false;
|
|
22522
|
+
this._methodPickerPanelId = null;
|
|
22523
|
+
this._updateRoute();
|
|
22524
|
+
}
|
|
22525
|
+
/** Handle instance change for primary panel */
|
|
22526
|
+
_handleLeftPanelInstanceChange(instance) {
|
|
22527
|
+
this._currentInstance = instance;
|
|
22528
|
+
sessionStorage.setItem(`photon-instance:${this._selectedPhoton.name}`, instance);
|
|
22529
|
+
this._lastResult = null;
|
|
22530
|
+
}
|
|
22531
|
+
/** Add a new split panel */
|
|
22532
|
+
_addPanel(type, method) {
|
|
22533
|
+
if (this._splitPanels.length >= 2) return;
|
|
22534
|
+
const panel = {
|
|
22535
|
+
id: `panel-${++this._nextPanelId}`,
|
|
22536
|
+
type,
|
|
22537
|
+
method,
|
|
22538
|
+
result: null,
|
|
22539
|
+
executing: false,
|
|
22540
|
+
progress: null,
|
|
22541
|
+
formParams: {},
|
|
22542
|
+
instance: this._currentInstance || "default"
|
|
22543
|
+
};
|
|
22544
|
+
this._splitPanels = [...this._splitPanels, panel];
|
|
22545
|
+
if (type === "method" && method && this._willAutoInvoke(method)) {
|
|
22546
|
+
void this._executePanelMethod(panel.id, {});
|
|
22547
|
+
}
|
|
22548
|
+
this._methodPickerOpen = false;
|
|
22549
|
+
this._methodPickerPanelId = null;
|
|
22550
|
+
this._cleanupPickerDismiss();
|
|
22551
|
+
this._updateRoute();
|
|
22552
|
+
}
|
|
22553
|
+
/** Remove a split panel by id */
|
|
22554
|
+
_removePanel(panelId) {
|
|
22555
|
+
this._splitPanels = this._splitPanels.filter((p5) => p5.id !== panelId);
|
|
22556
|
+
this._updateRoute();
|
|
22557
|
+
}
|
|
22558
|
+
/** Update a split panel's state */
|
|
22559
|
+
_updatePanel(panelId, updates) {
|
|
22560
|
+
this._splitPanels = this._splitPanels.map((p5) => p5.id === panelId ? { ...p5, ...updates } : p5);
|
|
22561
|
+
}
|
|
22562
|
+
/** Execute a method in a split panel */
|
|
22563
|
+
async _executePanelMethod(panelId, args) {
|
|
22564
|
+
const panel = this._splitPanels.find((p5) => p5.id === panelId);
|
|
22565
|
+
if (!panel || panel.type !== "method" || !panel.method) return;
|
|
22566
|
+
this._updatePanel(panelId, { executing: true, result: null, progress: null, formParams: args });
|
|
22567
|
+
try {
|
|
22568
|
+
const toolName = `${this._selectedPhoton.name}/${panel.method.name}`;
|
|
22569
|
+
const result = await mcpClient.callTool(
|
|
22570
|
+
toolName,
|
|
22571
|
+
args,
|
|
22572
|
+
void 0,
|
|
22573
|
+
panel.instance || this._currentInstance,
|
|
22574
|
+
(progress) => {
|
|
22575
|
+
this._updatePanel(panelId, { progress });
|
|
22576
|
+
}
|
|
22577
|
+
);
|
|
22578
|
+
this._updatePanel(panelId, {
|
|
22579
|
+
result: mcpClient.parseToolResult(result),
|
|
22580
|
+
executing: false,
|
|
22581
|
+
progress: null
|
|
22582
|
+
});
|
|
22583
|
+
} catch (error2) {
|
|
22584
|
+
showToast(`Error: ${error2.message}`, { type: "error" });
|
|
22585
|
+
this._updatePanel(panelId, {
|
|
22586
|
+
result: { error: error2.message },
|
|
22587
|
+
executing: false,
|
|
22588
|
+
progress: null
|
|
22589
|
+
});
|
|
22590
|
+
}
|
|
22591
|
+
}
|
|
22592
|
+
/** Change the method in a split panel */
|
|
22593
|
+
_changePanelMethod(panelId, method) {
|
|
22594
|
+
this._updatePanel(panelId, { method, result: null, formParams: {} });
|
|
22595
|
+
if (this._willAutoInvoke(method)) {
|
|
22596
|
+
void this._executePanelMethod(panelId, {});
|
|
22597
|
+
}
|
|
22598
|
+
this._updateRoute();
|
|
22599
|
+
}
|
|
22600
|
+
/** Change the instance in a split panel */
|
|
22601
|
+
_changePanelInstance(panelId, instance) {
|
|
22602
|
+
this._updatePanel(panelId, { instance, result: null });
|
|
22603
|
+
}
|
|
22604
|
+
/** Open a method in a new split panel (backwards-compatible entry point) */
|
|
22605
|
+
_openInSecondPanel(photon, method) {
|
|
22606
|
+
this._addPanel("method", method);
|
|
22607
|
+
}
|
|
22608
|
+
/** Show method picker popover */
|
|
22609
|
+
_showMethodPicker() {
|
|
22610
|
+
this._methodPickerOpen = !this._methodPickerOpen;
|
|
22611
|
+
this._methodPickerPanelId = null;
|
|
22612
|
+
}
|
|
22613
|
+
/** Clean up picker dismiss listener */
|
|
22614
|
+
_cleanupPickerDismiss() {
|
|
22615
|
+
if (this._pickerDismissHandler) {
|
|
22616
|
+
window.removeEventListener("mousedown", this._pickerDismissHandler, true);
|
|
22617
|
+
this._pickerDismissHandler = null;
|
|
22618
|
+
}
|
|
22619
|
+
}
|
|
22620
|
+
/** Handle method change in primary panel */
|
|
22621
|
+
_handleLeftPanelMethodChange(method) {
|
|
22622
|
+
this._selectedMethod = method;
|
|
22623
|
+
this._lastResult = null;
|
|
22624
|
+
this._lastFormParams = {};
|
|
22625
|
+
this._updateRoute();
|
|
22626
|
+
}
|
|
22627
|
+
/** Handle panel action for primary panel */
|
|
22628
|
+
_handlePrimaryPanelAction(action) {
|
|
22629
|
+
if (action === "toggle-picker") {
|
|
22630
|
+
this._methodPickerOpen = !this._methodPickerOpen;
|
|
22631
|
+
this._methodPickerPanelId = null;
|
|
22632
|
+
}
|
|
22633
|
+
}
|
|
22634
|
+
/** Build opts for an additional (non-primary) split panel */
|
|
22635
|
+
_buildAdditionalPanelOpts(panel) {
|
|
22636
|
+
return {
|
|
22637
|
+
photon: this._selectedPhoton,
|
|
22638
|
+
method: panel.method,
|
|
22639
|
+
result: panel.result,
|
|
22640
|
+
executing: panel.executing || false,
|
|
22641
|
+
progress: panel.progress,
|
|
22642
|
+
formParams: panel.formParams || {},
|
|
22643
|
+
onSubmit: (e8) => {
|
|
22644
|
+
const args = e8.detail?.args || {};
|
|
22645
|
+
void this._executePanelMethod(panel.id, args);
|
|
22646
|
+
},
|
|
22647
|
+
onCancel: () => this._removePanel(panel.id),
|
|
22648
|
+
panelLabel: panel.id,
|
|
22649
|
+
instance: panel.instance,
|
|
22650
|
+
instances: this._instances,
|
|
22651
|
+
onInstanceChange: (inst) => this._changePanelInstance(panel.id, inst),
|
|
22652
|
+
allMethods: this._selectedPhoton?.methods || [],
|
|
22653
|
+
onMethodChange: (m3) => this._changePanelMethod(panel.id, m3),
|
|
22654
|
+
panelSide: "additional",
|
|
22655
|
+
onPanelAction: (action) => {
|
|
22656
|
+
if (action === "close") this._removePanel(panel.id);
|
|
22657
|
+
},
|
|
22658
|
+
onInstanceAction: (detail) => {
|
|
22659
|
+
if (detail.action === "switch") {
|
|
22660
|
+
this._changePanelInstance(panel.id, detail.instance);
|
|
22661
|
+
}
|
|
22662
|
+
},
|
|
22663
|
+
isStateful: !!this._selectedPhoton?.stateful,
|
|
22664
|
+
isLive: this._currentCollectionName !== null,
|
|
22665
|
+
overflowItems: this._buildOverflowItems({
|
|
22666
|
+
showRefresh: false,
|
|
22667
|
+
showRename: false,
|
|
22668
|
+
showViewSource: false,
|
|
22669
|
+
showDelete: false,
|
|
22670
|
+
showHelp: false,
|
|
22671
|
+
showRunTests: false
|
|
22672
|
+
}),
|
|
22673
|
+
onOverflowSelect: (id2) => this._handleOverflowAction(id2)
|
|
22674
|
+
};
|
|
22675
|
+
}
|
|
22676
|
+
/** Handle overflow menu actions from panel headers */
|
|
22677
|
+
_handleOverflowAction(id2) {
|
|
22678
|
+
switch (id2) {
|
|
22679
|
+
case "refresh":
|
|
22680
|
+
if (this._selectedMethod && this._willAutoInvoke(this._selectedMethod)) {
|
|
22681
|
+
void this._handleExecute(new CustomEvent("execute", { detail: { args: {} } }));
|
|
22682
|
+
}
|
|
22683
|
+
break;
|
|
22684
|
+
case "remember-values":
|
|
22685
|
+
this._rememberFormValues = !this._rememberFormValues;
|
|
22686
|
+
break;
|
|
22687
|
+
case "verbose-logging":
|
|
22688
|
+
this._verboseLogging = !this._verboseLogging;
|
|
22689
|
+
break;
|
|
22690
|
+
case "run-tests":
|
|
22691
|
+
void this._runTests();
|
|
22692
|
+
break;
|
|
22693
|
+
case "help":
|
|
22694
|
+
this._showPhotonHelp = true;
|
|
22695
|
+
break;
|
|
22696
|
+
default:
|
|
22697
|
+
this._handleContextAction(new CustomEvent("context-action", { detail: { action: id2 } }));
|
|
22698
|
+
break;
|
|
22699
|
+
}
|
|
22700
|
+
}
|
|
22701
|
+
/** Render source panel for split view */
|
|
22702
|
+
_renderSourcePanel(panelId) {
|
|
22703
|
+
return b2`
|
|
22704
|
+
<div style="height: 100%; overflow: hidden;">
|
|
22705
|
+
<photon-studio
|
|
22706
|
+
.photonName=${this._selectedPhoton?.name}
|
|
22707
|
+
.theme=${this._theme}
|
|
22708
|
+
@studio-saved=${() => this._handleStudioSaved?.()}
|
|
22709
|
+
@studio-close=${() => this._removePanel(panelId)}
|
|
22710
|
+
></photon-studio>
|
|
22711
|
+
</div>
|
|
22712
|
+
`;
|
|
22713
|
+
}
|
|
22714
|
+
/** Render the method picker popover for adding new panels */
|
|
22715
|
+
_renderMethodPickerPopover() {
|
|
22716
|
+
const methods = this._getVisibleMethods();
|
|
22717
|
+
const openMethodNames = /* @__PURE__ */ new Set();
|
|
22718
|
+
if (this._selectedMethod) openMethodNames.add(this._selectedMethod.name);
|
|
22719
|
+
for (const p5 of this._splitPanels) {
|
|
22720
|
+
if (p5.type === "method" && p5.method) openMethodNames.add(p5.method.name);
|
|
22721
|
+
}
|
|
22722
|
+
const availableMethods = methods.filter((m3) => !openMethodNames.has(m3.name));
|
|
22723
|
+
const hasSourcePanel = this._splitPanels.some((p5) => p5.type === "source");
|
|
22724
|
+
const canAddMore = this._splitPanels.length < 2;
|
|
22725
|
+
if (!canAddMore) return "";
|
|
22726
|
+
if (!this._pickerDismissHandler) {
|
|
22727
|
+
const handler = (e8) => {
|
|
22728
|
+
const path = e8.composedPath();
|
|
22729
|
+
const popover = this.renderRoot.querySelector(".method-picker-popover");
|
|
22730
|
+
if (popover && path.includes(popover)) return;
|
|
22731
|
+
this._methodPickerOpen = false;
|
|
22732
|
+
this._pickerDismissHandler = null;
|
|
22733
|
+
window.removeEventListener("mousedown", handler, true);
|
|
22734
|
+
};
|
|
22735
|
+
this._pickerDismissHandler = handler;
|
|
22736
|
+
setTimeout(() => window.addEventListener("mousedown", handler, true), 0);
|
|
22737
|
+
}
|
|
22738
|
+
return b2`
|
|
22739
|
+
<div
|
|
22740
|
+
class="method-picker-popover"
|
|
22741
|
+
@click=${(e8) => e8.stopPropagation()}
|
|
22742
|
+
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;"
|
|
22743
|
+
>
|
|
22744
|
+
<!-- Header -->
|
|
22745
|
+
<div style="padding: 10px 12px 8px; border-bottom: 1px solid var(--border-glass);">
|
|
22746
|
+
<div
|
|
22747
|
+
style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--t-tertiary);"
|
|
22748
|
+
>
|
|
22749
|
+
Split Pane
|
|
22750
|
+
</div>
|
|
22751
|
+
</div>
|
|
22752
|
+
|
|
22753
|
+
<!-- Methods section -->
|
|
22754
|
+
${availableMethods.length > 0 ? b2`
|
|
22755
|
+
<div style="padding: 4px 0;">
|
|
22756
|
+
<div
|
|
22757
|
+
style="padding: 4px 12px 2px; font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: var(--t-tertiary);"
|
|
22758
|
+
>
|
|
22759
|
+
Methods
|
|
21283
22760
|
</div>
|
|
22761
|
+
${availableMethods.map(
|
|
22762
|
+
(m3) => b2`
|
|
22763
|
+
<div
|
|
22764
|
+
@click=${() => this._addPanel("method", m3)}
|
|
22765
|
+
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;"
|
|
22766
|
+
@mouseenter=${(e8) => e8.target.style.background = "var(--bg-hover)"}
|
|
22767
|
+
@mouseleave=${(e8) => e8.target.style.background = "transparent"}
|
|
22768
|
+
>
|
|
22769
|
+
<span style="color: var(--t-tertiary); font-size: 10px;">▸</span>
|
|
22770
|
+
${m3.name}
|
|
22771
|
+
</div>
|
|
22772
|
+
`
|
|
22773
|
+
)}
|
|
21284
22774
|
</div>
|
|
21285
|
-
` : ""}
|
|
21286
|
-
${this._lastResult !== null ? b2`
|
|
21287
|
-
<result-viewer
|
|
21288
|
-
.result=${this._lastResult}
|
|
21289
|
-
.outputFormat=${this._selectedMethod?.outputFormat}
|
|
21290
|
-
.layoutHints=${this._selectedMethod?.layoutHints}
|
|
21291
|
-
.theme=${this._theme}
|
|
21292
|
-
.live=${this._currentCollectionName !== null}
|
|
21293
|
-
.resultKey=${this._selectedPhoton && this._selectedMethod ? `${this._selectedPhoton.name}/${this._selectedMethod.name}` : void 0}
|
|
21294
|
-
@share=${() => this._handleShareResult()}
|
|
21295
|
-
></result-viewer>
|
|
21296
22775
|
` : b2`
|
|
21297
|
-
<div
|
|
21298
|
-
|
|
21299
|
-
|
|
22776
|
+
<div
|
|
22777
|
+
style="padding: 8px 12px; font-size: 11px; color: var(--t-tertiary); font-style: italic;"
|
|
22778
|
+
>
|
|
22779
|
+
All methods already open
|
|
21300
22780
|
</div>
|
|
21301
22781
|
`}
|
|
22782
|
+
|
|
22783
|
+
<!-- Tools section -->
|
|
22784
|
+
${!hasSourcePanel ? b2`
|
|
22785
|
+
<div style="border-top: 1px solid var(--border-glass); padding: 4px 0;">
|
|
22786
|
+
<div
|
|
22787
|
+
style="padding: 4px 12px 2px; font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: var(--t-tertiary);"
|
|
22788
|
+
>
|
|
22789
|
+
Tools
|
|
22790
|
+
</div>
|
|
22791
|
+
<div
|
|
22792
|
+
@click=${() => this._addPanel("source")}
|
|
22793
|
+
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;"
|
|
22794
|
+
@mouseenter=${(e8) => e8.target.style.background = "var(--bg-hover)"}
|
|
22795
|
+
@mouseleave=${(e8) => e8.target.style.background = "transparent"}
|
|
22796
|
+
>
|
|
22797
|
+
<span style="font-size: 11px; color: var(--accent-primary);"></></span>
|
|
22798
|
+
Source Editor
|
|
22799
|
+
</div>
|
|
22800
|
+
</div>
|
|
22801
|
+
` : ""}
|
|
21302
22802
|
</div>
|
|
21303
22803
|
`;
|
|
21304
22804
|
}
|
|
@@ -21327,10 +22827,11 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21327
22827
|
if (form?.isDirty && !confirm("You have unsaved changes. Discard them?")) {
|
|
21328
22828
|
return;
|
|
21329
22829
|
}
|
|
22830
|
+
this._closeSecondPanel();
|
|
21330
22831
|
if (this._selectedPhoton.isApp && this._selectedPhoton.appEntry) {
|
|
21331
22832
|
this._selectedMethod = this._selectedPhoton.appEntry;
|
|
21332
22833
|
this._view = "form";
|
|
21333
|
-
this.
|
|
22834
|
+
this._updateRoute(true);
|
|
21334
22835
|
void this.updateComplete.then(() => {
|
|
21335
22836
|
setTimeout(() => {
|
|
21336
22837
|
const mainArea = this.shadowRoot?.querySelector(".main-area");
|
|
@@ -21344,11 +22845,11 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21344
22845
|
this._selectedPhoton = null;
|
|
21345
22846
|
this._welcomePhase = "welcome";
|
|
21346
22847
|
this._view = "list";
|
|
21347
|
-
this.
|
|
22848
|
+
this._updateRoute(true);
|
|
21348
22849
|
} else {
|
|
21349
22850
|
this._view = "list";
|
|
21350
22851
|
this._selectedMethod = null;
|
|
21351
|
-
this.
|
|
22852
|
+
this._updateRoute(true);
|
|
21352
22853
|
}
|
|
21353
22854
|
}
|
|
21354
22855
|
async _openForkDialog() {
|
|
@@ -21422,7 +22923,17 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21422
22923
|
}
|
|
21423
22924
|
} else {
|
|
21424
22925
|
this._lastResult = mcpClient.parseToolResult(result);
|
|
22926
|
+
if (this._selectedPhoton?.stateful && Array.isArray(this._lastResult) && this._selectedMethod) {
|
|
22927
|
+
this._lastResult = this._autoWrapPaginationIfNeeded(
|
|
22928
|
+
this._lastResult,
|
|
22929
|
+
this._selectedPhoton.name,
|
|
22930
|
+
this._selectedMethod
|
|
22931
|
+
);
|
|
22932
|
+
}
|
|
21425
22933
|
this._log("success", "Execution completed", false, execDuration);
|
|
22934
|
+
if (this._selectedPhoton?.stateful && this._lastResult != null && typeof this._lastResult === "object") {
|
|
22935
|
+
this._initializeGlobalInstance(this._selectedPhoton.name, this._lastResult);
|
|
22936
|
+
}
|
|
21426
22937
|
void this.updateComplete.then(() => {
|
|
21427
22938
|
const rv2 = this.shadowRoot?.querySelector("result-viewer");
|
|
21428
22939
|
if (rv2 && window.innerWidth <= 768) {
|
|
@@ -21457,6 +22968,16 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21457
22968
|
const result = await mcpClient.callTool(toolName, this._lastFormParams || {});
|
|
21458
22969
|
if (!result.isError) {
|
|
21459
22970
|
this._lastResult = mcpClient.parseToolResult(result);
|
|
22971
|
+
if (this._selectedPhoton.stateful && Array.isArray(this._lastResult) && this._selectedMethod) {
|
|
22972
|
+
this._lastResult = this._autoWrapPaginationIfNeeded(
|
|
22973
|
+
this._lastResult,
|
|
22974
|
+
this._selectedPhoton.name,
|
|
22975
|
+
this._selectedMethod
|
|
22976
|
+
);
|
|
22977
|
+
}
|
|
22978
|
+
if (this._selectedPhoton.stateful && this._lastResult != null && typeof this._lastResult === "object") {
|
|
22979
|
+
this._initializeGlobalInstance(this._selectedPhoton.name, this._lastResult);
|
|
22980
|
+
}
|
|
21460
22981
|
}
|
|
21461
22982
|
} catch {
|
|
21462
22983
|
} finally {
|
|
@@ -21507,6 +23028,162 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21507
23028
|
this._collectionUnsubscribes = [];
|
|
21508
23029
|
this._currentCollectionName = null;
|
|
21509
23030
|
}
|
|
23031
|
+
/**
|
|
23032
|
+
* Initialize global photon instance for @stateful photons
|
|
23033
|
+
* Makes the photon instance available as window.{photonName}
|
|
23034
|
+
* and keeps it in sync with server state via state-changed patches
|
|
23035
|
+
* Wraps paginated array properties with ViewportAwareProxy for smart fetching
|
|
23036
|
+
*/
|
|
23037
|
+
/**
|
|
23038
|
+
* Auto-wrap array results with pagination metadata for @stateful photons
|
|
23039
|
+
* If method has (start, limit) parameters, detect them and use global instance
|
|
23040
|
+
* to calculate pagination metadata from the full array
|
|
23041
|
+
*/
|
|
23042
|
+
_autoWrapPaginationIfNeeded(items, photonName, method) {
|
|
23043
|
+
const hasStartLimitParams = method.parameters?.some(
|
|
23044
|
+
(p5) => (p5.name === "start" || p5.name === "limit") && p5.required !== true
|
|
23045
|
+
);
|
|
23046
|
+
if (!hasStartLimitParams || items.length === 0) {
|
|
23047
|
+
return items;
|
|
23048
|
+
}
|
|
23049
|
+
try {
|
|
23050
|
+
const manager = getGlobalInstanceManager();
|
|
23051
|
+
const instance = manager.getInstance(photonName);
|
|
23052
|
+
if (!instance) {
|
|
23053
|
+
return items;
|
|
23054
|
+
}
|
|
23055
|
+
const arrayProp = Object.keys(instance).find((key) => {
|
|
23056
|
+
const value = instance[key];
|
|
23057
|
+
return Array.isArray(value) && value.length > 0;
|
|
23058
|
+
});
|
|
23059
|
+
if (!arrayProp) {
|
|
23060
|
+
return items;
|
|
23061
|
+
}
|
|
23062
|
+
const fullArray = instance[arrayProp];
|
|
23063
|
+
const totalCount = fullArray.length;
|
|
23064
|
+
const start = 0;
|
|
23065
|
+
const end = items.length;
|
|
23066
|
+
return {
|
|
23067
|
+
items,
|
|
23068
|
+
_pagination: {
|
|
23069
|
+
totalCount,
|
|
23070
|
+
start,
|
|
23071
|
+
end,
|
|
23072
|
+
hasMore: end < totalCount
|
|
23073
|
+
}
|
|
23074
|
+
};
|
|
23075
|
+
} catch (error2) {
|
|
23076
|
+
if (this._verboseLogging) {
|
|
23077
|
+
const msg = error2 instanceof Error ? error2.message : "Unknown error";
|
|
23078
|
+
this._log("warn", `Could not auto-wrap pagination: ${msg}`);
|
|
23079
|
+
}
|
|
23080
|
+
return items;
|
|
23081
|
+
}
|
|
23082
|
+
}
|
|
23083
|
+
_initializeGlobalInstance(photonName, initialState) {
|
|
23084
|
+
try {
|
|
23085
|
+
const paginatedProps = this._detectPaginatedProperties(initialState);
|
|
23086
|
+
const instance = initializeGlobalPhotonSession(photonName, initialState);
|
|
23087
|
+
for (const [propName, paginationMeta] of Object.entries(paginatedProps)) {
|
|
23088
|
+
this._wrapWithViewportProxy(instance, propName, paginationMeta);
|
|
23089
|
+
}
|
|
23090
|
+
if (this._verboseLogging) {
|
|
23091
|
+
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()}`;
|
|
23092
|
+
this._log("info", message);
|
|
23093
|
+
}
|
|
23094
|
+
} catch (error2) {
|
|
23095
|
+
console.error("Failed to initialize global photon instance", error2);
|
|
23096
|
+
}
|
|
23097
|
+
}
|
|
23098
|
+
/**
|
|
23099
|
+
* Detect which properties have pagination metadata
|
|
23100
|
+
*/
|
|
23101
|
+
_detectPaginatedProperties(initialState) {
|
|
23102
|
+
const paginated = /* @__PURE__ */ new Map();
|
|
23103
|
+
if (!initialState || typeof initialState !== "object") {
|
|
23104
|
+
return paginated;
|
|
23105
|
+
}
|
|
23106
|
+
for (const [key, value] of Object.entries(initialState)) {
|
|
23107
|
+
if (value && typeof value === "object" && value._pagination) {
|
|
23108
|
+
paginated.set(key, value._pagination);
|
|
23109
|
+
}
|
|
23110
|
+
}
|
|
23111
|
+
return paginated;
|
|
23112
|
+
}
|
|
23113
|
+
/**
|
|
23114
|
+
* Wrap a property with ViewportAwareProxy for smart pagination
|
|
23115
|
+
*/
|
|
23116
|
+
_wrapWithViewportProxy(instance, propertyName2, paginationMeta) {
|
|
23117
|
+
try {
|
|
23118
|
+
const pageSize = getPageSizeForClient();
|
|
23119
|
+
const proxy = new ViewportAwareProxy(
|
|
23120
|
+
this._selectedPhoton?.name || "unknown",
|
|
23121
|
+
this._selectedMethod?.name || propertyName2,
|
|
23122
|
+
mcpClient,
|
|
23123
|
+
{
|
|
23124
|
+
pageSize,
|
|
23125
|
+
bufferSize: 5,
|
|
23126
|
+
// Items to buffer above/below viewport
|
|
23127
|
+
maxCacheSize: 500
|
|
23128
|
+
// Max items to keep in cache
|
|
23129
|
+
}
|
|
23130
|
+
);
|
|
23131
|
+
proxy.initializeWithResponse({
|
|
23132
|
+
items: instance[propertyName2] || [],
|
|
23133
|
+
_pagination: paginationMeta
|
|
23134
|
+
});
|
|
23135
|
+
instance.makeProperty(propertyName2);
|
|
23136
|
+
Object.defineProperty(instance, propertyName2, {
|
|
23137
|
+
configurable: true,
|
|
23138
|
+
enumerable: true,
|
|
23139
|
+
get: () => proxy.items,
|
|
23140
|
+
set: (value) => {
|
|
23141
|
+
proxy.clearCache();
|
|
23142
|
+
proxy.initializeWithResponse({
|
|
23143
|
+
items: value || [],
|
|
23144
|
+
_pagination: paginationMeta
|
|
23145
|
+
});
|
|
23146
|
+
}
|
|
23147
|
+
});
|
|
23148
|
+
const patchHandler = (data) => {
|
|
23149
|
+
if (data?.patches) {
|
|
23150
|
+
proxy.applyPatches(data.patches);
|
|
23151
|
+
}
|
|
23152
|
+
};
|
|
23153
|
+
instance.on("state-changed", patchHandler);
|
|
23154
|
+
queueMicrotask(() => {
|
|
23155
|
+
try {
|
|
23156
|
+
const resultViewer = this._resultViewer;
|
|
23157
|
+
if (resultViewer?.shadowRoot) {
|
|
23158
|
+
const scrollContainer = resultViewer.shadowRoot.querySelector(
|
|
23159
|
+
".result-content"
|
|
23160
|
+
);
|
|
23161
|
+
if (scrollContainer) {
|
|
23162
|
+
const manager = new ViewportManager(proxy, {
|
|
23163
|
+
container: scrollContainer,
|
|
23164
|
+
itemSelector: "[data-index]",
|
|
23165
|
+
pageSize,
|
|
23166
|
+
bufferSize: 5
|
|
23167
|
+
});
|
|
23168
|
+
manager.start();
|
|
23169
|
+
}
|
|
23170
|
+
}
|
|
23171
|
+
} catch (error2) {
|
|
23172
|
+
if (this._verboseLogging) {
|
|
23173
|
+
this._log("warn", `Could not set up automatic viewport tracking for ${propertyName2}`);
|
|
23174
|
+
}
|
|
23175
|
+
}
|
|
23176
|
+
});
|
|
23177
|
+
if (this._verboseLogging) {
|
|
23178
|
+
this._log(
|
|
23179
|
+
"info",
|
|
23180
|
+
`\u2728 Paginated proxy enabled for ${propertyName2} (page size: ${pageSize})`
|
|
23181
|
+
);
|
|
23182
|
+
}
|
|
23183
|
+
} catch (error2) {
|
|
23184
|
+
console.error(`Failed to wrap ${propertyName2} with ViewportAwareProxy`, error2);
|
|
23185
|
+
}
|
|
23186
|
+
}
|
|
21510
23187
|
async _handleConfigure(e8) {
|
|
21511
23188
|
const { photon, config: config3 } = e8.detail;
|
|
21512
23189
|
this._log("info", `Configuring ${photon}...`);
|
|
@@ -21541,8 +23218,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21541
23218
|
showToast("No method selected to share", "error");
|
|
21542
23219
|
return;
|
|
21543
23220
|
}
|
|
21544
|
-
const
|
|
21545
|
-
const hash2 = `${this._selectedPhoton.name}/${this._selectedMethod.name}`;
|
|
23221
|
+
const pathSegment2 = `${this._selectedPhoton.name}/${this._selectedMethod.name}`;
|
|
21546
23222
|
const params = new URLSearchParams();
|
|
21547
23223
|
for (const [key, value] of Object.entries(this._lastFormParams)) {
|
|
21548
23224
|
if (value !== void 0 && value !== null && value !== "") {
|
|
@@ -21553,7 +23229,7 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21553
23229
|
}
|
|
21554
23230
|
}
|
|
21555
23231
|
}
|
|
21556
|
-
let shareUrl = `${
|
|
23232
|
+
let shareUrl = `${window.location.origin}/${pathSegment2}`;
|
|
21557
23233
|
if (params.toString()) {
|
|
21558
23234
|
shareUrl += `?${params.toString()}`;
|
|
21559
23235
|
}
|
|
@@ -21787,7 +23463,8 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21787
23463
|
showHelp = true,
|
|
21788
23464
|
showRunTests = this._getTestMethods().length > 0,
|
|
21789
23465
|
showRemove = false,
|
|
21790
|
-
showFullscreen = false
|
|
23466
|
+
showFullscreen = false,
|
|
23467
|
+
showInstallApp = !this._pwaIsStandalone && !!this._selectedPhoton?.isApp
|
|
21791
23468
|
} = opts;
|
|
21792
23469
|
const items = [];
|
|
21793
23470
|
if (showFullscreen) {
|
|
@@ -21833,6 +23510,13 @@ ${photon.errorMessage || "Unknown error"}</pre
|
|
|
21833
23510
|
toggle: true,
|
|
21834
23511
|
toggleActive: this._verboseLogging
|
|
21835
23512
|
});
|
|
23513
|
+
if (showInstallApp) {
|
|
23514
|
+
items.push({
|
|
23515
|
+
id: "install-app",
|
|
23516
|
+
label: "Install as App",
|
|
23517
|
+
iconSvg: iconSvgString(iconPaths.installApp)
|
|
23518
|
+
});
|
|
23519
|
+
}
|
|
21836
23520
|
if (showRename || showViewSource || showFork || showContribute || showDelete || showRemove) {
|
|
21837
23521
|
const first = [
|
|
21838
23522
|
showRename,
|
|
@@ -22758,6 +24442,10 @@ BeamApp.styles = [
|
|
|
22758
24442
|
display: none;
|
|
22759
24443
|
}
|
|
22760
24444
|
|
|
24445
|
+
:host(.focus-mode) .main-area {
|
|
24446
|
+
padding: var(--space-sm);
|
|
24447
|
+
}
|
|
24448
|
+
|
|
22761
24449
|
.main-area {
|
|
22762
24450
|
flex: 1;
|
|
22763
24451
|
position: relative;
|
|
@@ -22766,10 +24454,10 @@ BeamApp.styles = [
|
|
|
22766
24454
|
padding: var(--space-lg);
|
|
22767
24455
|
}
|
|
22768
24456
|
|
|
24457
|
+
.beam-back-btn,
|
|
22769
24458
|
.beam-fullscreen-btn {
|
|
22770
24459
|
position: sticky;
|
|
22771
24460
|
top: calc(-1 * var(--space-lg));
|
|
22772
|
-
float: right;
|
|
22773
24461
|
z-index: 100;
|
|
22774
24462
|
width: 28px;
|
|
22775
24463
|
height: 28px;
|
|
@@ -22783,6 +24471,18 @@ BeamApp.styles = [
|
|
|
22783
24471
|
align-items: center;
|
|
22784
24472
|
justify-content: center;
|
|
22785
24473
|
transition: all 0.2s ease;
|
|
24474
|
+
backdrop-filter: blur(8px);
|
|
24475
|
+
}
|
|
24476
|
+
|
|
24477
|
+
.beam-back-btn {
|
|
24478
|
+
float: left;
|
|
24479
|
+
margin-top: calc(-1 * var(--space-lg));
|
|
24480
|
+
margin-left: calc(-1 * var(--space-lg) + 1px);
|
|
24481
|
+
margin-bottom: calc(-28px + var(--space-lg));
|
|
24482
|
+
}
|
|
24483
|
+
|
|
24484
|
+
.beam-fullscreen-btn {
|
|
24485
|
+
float: right;
|
|
22786
24486
|
margin-top: calc(-1 * var(--space-lg));
|
|
22787
24487
|
margin-right: calc(-1 * var(--space-lg) + 1px);
|
|
22788
24488
|
margin-bottom: calc(-28px + var(--space-lg));
|
|
@@ -23813,7 +25513,7 @@ BeamApp.styles = [
|
|
|
23813
25513
|
min-width: 120px;
|
|
23814
25514
|
font-family: var(--font-mono);
|
|
23815
25515
|
font-size: var(--text-md);
|
|
23816
|
-
color:
|
|
25516
|
+
color: var(--color-warning);
|
|
23817
25517
|
}
|
|
23818
25518
|
|
|
23819
25519
|
.variable-input input {
|
|
@@ -24002,7 +25702,7 @@ BeamApp.styles = [
|
|
|
24002
25702
|
|
|
24003
25703
|
.progress-bar-wrapper {
|
|
24004
25704
|
height: 8px;
|
|
24005
|
-
background:
|
|
25705
|
+
background: var(--bg-glass);
|
|
24006
25706
|
border-radius: var(--radius-xs);
|
|
24007
25707
|
overflow: hidden;
|
|
24008
25708
|
}
|
|
@@ -24120,6 +25820,25 @@ BeamApp.styles = [
|
|
|
24120
25820
|
padding-top: calc(var(--space-md) + 60px); /* Space for mobile menu button */
|
|
24121
25821
|
}
|
|
24122
25822
|
|
|
25823
|
+
.beam-back-btn,
|
|
25824
|
+
.beam-fullscreen-btn {
|
|
25825
|
+
position: fixed;
|
|
25826
|
+
top: var(--space-md);
|
|
25827
|
+
float: none;
|
|
25828
|
+
margin: 0;
|
|
25829
|
+
width: 44px;
|
|
25830
|
+
height: 44px;
|
|
25831
|
+
box-shadow: var(--shadow-md);
|
|
25832
|
+
}
|
|
25833
|
+
|
|
25834
|
+
.beam-back-btn {
|
|
25835
|
+
left: calc(var(--space-md) + 44px + var(--space-sm));
|
|
25836
|
+
}
|
|
25837
|
+
|
|
25838
|
+
.beam-fullscreen-btn {
|
|
25839
|
+
right: var(--space-md);
|
|
25840
|
+
}
|
|
25841
|
+
|
|
24123
25842
|
.photon-header {
|
|
24124
25843
|
flex-direction: column;
|
|
24125
25844
|
align-items: flex-start;
|
|
@@ -24134,10 +25853,9 @@ BeamApp.styles = [
|
|
|
24134
25853
|
grid-template-columns: 1fr;
|
|
24135
25854
|
}
|
|
24136
25855
|
|
|
24137
|
-
/* Touch-friendly targets - min 44px */
|
|
25856
|
+
/* Touch-friendly targets - min 44px (exclude small inline buttons) */
|
|
24138
25857
|
.asset-card,
|
|
24139
25858
|
.method-card,
|
|
24140
|
-
button,
|
|
24141
25859
|
.filter-btn {
|
|
24142
25860
|
min-height: 44px;
|
|
24143
25861
|
}
|
|
@@ -24418,6 +26136,15 @@ __decorateClass([
|
|
|
24418
26136
|
__decorateClass([
|
|
24419
26137
|
r5()
|
|
24420
26138
|
], BeamApp.prototype, "_resourceContent", 2);
|
|
26139
|
+
__decorateClass([
|
|
26140
|
+
r5()
|
|
26141
|
+
], BeamApp.prototype, "_splitPanels", 2);
|
|
26142
|
+
__decorateClass([
|
|
26143
|
+
r5()
|
|
26144
|
+
], BeamApp.prototype, "_methodPickerOpen", 2);
|
|
26145
|
+
__decorateClass([
|
|
26146
|
+
r5()
|
|
26147
|
+
], BeamApp.prototype, "_methodPickerPanelId", 2);
|
|
24421
26148
|
__decorateClass([
|
|
24422
26149
|
e7("beam-sidebar")
|
|
24423
26150
|
], BeamApp.prototype, "_sidebar", 2);
|
|
@@ -24456,6 +26183,7 @@ var BeamSidebar = class extends i4 {
|
|
|
24456
26183
|
this._favorites = /* @__PURE__ */ new Set();
|
|
24457
26184
|
this._collapsedSections = /* @__PURE__ */ new Set();
|
|
24458
26185
|
this._recentPhotons = [];
|
|
26186
|
+
this._notificationWarmth = /* @__PURE__ */ new Map();
|
|
24459
26187
|
}
|
|
24460
26188
|
connectedCallback() {
|
|
24461
26189
|
super.connectedCallback();
|
|
@@ -24826,7 +26554,7 @@ var BeamSidebar = class extends i4 {
|
|
|
24826
26554
|
}
|
|
24827
26555
|
return b2`
|
|
24828
26556
|
<li
|
|
24829
|
-
class="photon-item ${this.selectedPhoton === photon.name ? "active" : ""} ${photon.internal ? "internal" : ""}"
|
|
26557
|
+
class="photon-item ${this.selectedPhoton === photon.name ? "active" : ""} ${photon.internal ? "internal" : ""} ${this._isPhotonWarm(photon.name) ? "warmth" : ""}"
|
|
24830
26558
|
role="option"
|
|
24831
26559
|
aria-selected="${this.selectedPhoton === photon.name}"
|
|
24832
26560
|
tabindex="0"
|
|
@@ -25023,6 +26751,28 @@ ${photon.path}` : ""}"
|
|
|
25023
26751
|
}
|
|
25024
26752
|
});
|
|
25025
26753
|
}
|
|
26754
|
+
/**
|
|
26755
|
+
* Check if a photon currently has a warmth indicator (notification received within last 5 seconds)
|
|
26756
|
+
*/
|
|
26757
|
+
_isPhotonWarm(photonName) {
|
|
26758
|
+
const lastNotificationTime = this._notificationWarmth.get(photonName);
|
|
26759
|
+
if (!lastNotificationTime) return false;
|
|
26760
|
+
return Date.now() - lastNotificationTime < 5e3;
|
|
26761
|
+
}
|
|
26762
|
+
/**
|
|
26763
|
+
* Update the warmth indicator for a photon when a notification arrives
|
|
26764
|
+
*/
|
|
26765
|
+
updatePhotonWarmth(photonName) {
|
|
26766
|
+
this._notificationWarmth.set(photonName, Date.now());
|
|
26767
|
+
this.requestUpdate();
|
|
26768
|
+
}
|
|
26769
|
+
/**
|
|
26770
|
+
* Check if a notification type is watched by a photon
|
|
26771
|
+
* This will be called by beam-app to determine if window.focus() should be triggered
|
|
26772
|
+
*/
|
|
26773
|
+
isNotificationWatched(photonName, notificationType) {
|
|
26774
|
+
return true;
|
|
26775
|
+
}
|
|
25026
26776
|
};
|
|
25027
26777
|
BeamSidebar.styles = [
|
|
25028
26778
|
theme,
|
|
@@ -25257,7 +27007,7 @@ BeamSidebar.styles = [
|
|
|
25257
27007
|
}
|
|
25258
27008
|
|
|
25259
27009
|
.section-header:hover {
|
|
25260
|
-
color: var(--t-
|
|
27010
|
+
color: var(--t-primary);
|
|
25261
27011
|
background: var(--bg-panel);
|
|
25262
27012
|
}
|
|
25263
27013
|
|
|
@@ -25319,7 +27069,7 @@ BeamSidebar.styles = [
|
|
|
25319
27069
|
}
|
|
25320
27070
|
|
|
25321
27071
|
.photon-item:hover {
|
|
25322
|
-
background:
|
|
27072
|
+
background: var(--bg-glass);
|
|
25323
27073
|
}
|
|
25324
27074
|
|
|
25325
27075
|
.photon-item.active {
|
|
@@ -25333,13 +27083,28 @@ BeamSidebar.styles = [
|
|
|
25333
27083
|
|
|
25334
27084
|
@keyframes flash-highlight {
|
|
25335
27085
|
0% {
|
|
25336
|
-
background:
|
|
27086
|
+
background: var(--glow-primary);
|
|
25337
27087
|
}
|
|
25338
27088
|
100% {
|
|
25339
27089
|
background: transparent;
|
|
25340
27090
|
}
|
|
25341
27091
|
}
|
|
25342
27092
|
|
|
27093
|
+
.photon-item.warmth {
|
|
27094
|
+
animation: warmth-fade 5s ease-out forwards;
|
|
27095
|
+
}
|
|
27096
|
+
|
|
27097
|
+
@keyframes warmth-fade {
|
|
27098
|
+
0% {
|
|
27099
|
+
background: var(--color-warning);
|
|
27100
|
+
opacity: 0.15;
|
|
27101
|
+
}
|
|
27102
|
+
100% {
|
|
27103
|
+
background: var(--color-warning);
|
|
27104
|
+
opacity: 0;
|
|
27105
|
+
}
|
|
27106
|
+
}
|
|
27107
|
+
|
|
25343
27108
|
.photon-icon {
|
|
25344
27109
|
width: 28px;
|
|
25345
27110
|
height: 28px;
|
|
@@ -25430,7 +27195,7 @@ BeamSidebar.styles = [
|
|
|
25430
27195
|
gap: 3px;
|
|
25431
27196
|
font-size: var(--text-2xs);
|
|
25432
27197
|
padding: 2px 5px;
|
|
25433
|
-
background:
|
|
27198
|
+
background: var(--bg-glass);
|
|
25434
27199
|
border: 1px solid var(--border-glass);
|
|
25435
27200
|
border-radius: var(--radius-full);
|
|
25436
27201
|
font-weight: 500;
|
|
@@ -25513,7 +27278,7 @@ BeamSidebar.styles = [
|
|
|
25513
27278
|
.marketplace-btn:hover {
|
|
25514
27279
|
background: var(--bg-panel);
|
|
25515
27280
|
border-color: var(--accent-secondary);
|
|
25516
|
-
box-shadow:
|
|
27281
|
+
box-shadow: var(--shadow-sm);
|
|
25517
27282
|
transform: translateY(-1px);
|
|
25518
27283
|
}
|
|
25519
27284
|
|
|
@@ -25745,6 +27510,9 @@ __decorateClass([
|
|
|
25745
27510
|
__decorateClass([
|
|
25746
27511
|
r5()
|
|
25747
27512
|
], BeamSidebar.prototype, "_recentPhotons", 2);
|
|
27513
|
+
__decorateClass([
|
|
27514
|
+
r5()
|
|
27515
|
+
], BeamSidebar.prototype, "_notificationWarmth", 2);
|
|
25748
27516
|
BeamSidebar = __decorateClass([
|
|
25749
27517
|
t4("beam-sidebar")
|
|
25750
27518
|
], BeamSidebar);
|
|
@@ -25791,6 +27559,7 @@ var MethodCard = class extends i4 {
|
|
|
25791
27559
|
const isThrottled = !!this.method.throttled;
|
|
25792
27560
|
const isDebounced = !!this.method.debounced;
|
|
25793
27561
|
const isQueued = !!this.method.queued;
|
|
27562
|
+
const emitsEvent = !!this.method.emitsEvent;
|
|
25794
27563
|
const isTyped = isAutorun || isWebhook || isCron || isLocked || isDeprecated;
|
|
25795
27564
|
const typeAccent = isDeprecated ? "hsl(0, 0%, 50%)" : isWebhook ? "hsl(45, 80%, 50%)" : isCron ? "hsl(215, 80%, 60%)" : isLocked ? "hsl(0, 65%, 55%)" : isAutorun ? "hsl(160, 60%, 45%)" : "";
|
|
25796
27565
|
return b2`
|
|
@@ -25817,8 +27586,7 @@ var MethodCard = class extends i4 {
|
|
|
25817
27586
|
` : ""}
|
|
25818
27587
|
<span class="editable">
|
|
25819
27588
|
<h3 class="title">
|
|
25820
|
-
<span class="title-name">${
|
|
25821
|
-
>${this._renderParamSignature()}
|
|
27589
|
+
<span class="title-name">${this.method.name}</span>${this._renderParamSignature()}
|
|
25822
27590
|
</h3>
|
|
25823
27591
|
<span
|
|
25824
27592
|
class="edit-pencil"
|
|
@@ -25834,30 +27602,18 @@ var MethodCard = class extends i4 {
|
|
|
25834
27602
|
</div>
|
|
25835
27603
|
${this.method.isTemplate ? b2`<span class="badge prompt">Prompt</span>` : ""}
|
|
25836
27604
|
${isCron ? b2`<span
|
|
25837
|
-
class="badge"
|
|
25838
|
-
style="background:hsla(215,80%,60%,0.15);color:hsl(215,80%,65%)"
|
|
27605
|
+
class="badge scheduled"
|
|
25839
27606
|
title="Runs automatically on schedule: ${this.method.scheduled}"
|
|
25840
27607
|
>⏱ Scheduled</span
|
|
25841
27608
|
>` : ""}
|
|
25842
|
-
${isDeprecated ? b2`<span
|
|
25843
|
-
|
|
25844
|
-
|
|
25845
|
-
|
|
25846
|
-
|
|
25847
|
-
|
|
25848
|
-
|
|
25849
|
-
|
|
25850
|
-
>Cached</span
|
|
25851
|
-
>` : ""}
|
|
25852
|
-
${isThrottled ? b2`<span
|
|
25853
|
-
class="badge"
|
|
25854
|
-
style="background:hsla(30,80%,50%,0.15);color:hsl(30,80%,60%)"
|
|
25855
|
-
>Throttled</span
|
|
25856
|
-
>` : ""}
|
|
25857
|
-
${isQueued ? b2`<span
|
|
25858
|
-
class="badge"
|
|
25859
|
-
style="background:hsla(200,70%,50%,0.15);color:hsl(200,70%,60%)"
|
|
25860
|
-
>Queued</span
|
|
27609
|
+
${isDeprecated ? b2`<span class="badge deprecated">Deprecated</span>` : ""}
|
|
27610
|
+
${isCached ? b2`<span class="badge cached">Cached</span>` : ""}
|
|
27611
|
+
${isThrottled ? b2`<span class="badge throttled">Throttled</span>` : ""}
|
|
27612
|
+
${isQueued ? b2`<span class="badge queued">Queued</span>` : ""}
|
|
27613
|
+
${emitsEvent ? b2`<span
|
|
27614
|
+
class="badge event"
|
|
27615
|
+
title="Automatically emits event: ${this.method.eventName}"
|
|
27616
|
+
>📡 Event</span
|
|
25861
27617
|
>` : ""}
|
|
25862
27618
|
</div>
|
|
25863
27619
|
${this._editingDescription ? b2`
|
|
@@ -26101,7 +27857,7 @@ MethodCard.styles = [
|
|
|
26101
27857
|
|
|
26102
27858
|
.card:hover {
|
|
26103
27859
|
transform: translateY(-2px);
|
|
26104
|
-
box-shadow:
|
|
27860
|
+
box-shadow: var(--shadow-lg);
|
|
26105
27861
|
border-left-color: var(--accent-primary);
|
|
26106
27862
|
}
|
|
26107
27863
|
|
|
@@ -26279,7 +28035,7 @@ MethodCard.styles = [
|
|
|
26279
28035
|
font-size: var(--text-xs);
|
|
26280
28036
|
padding: 2px 8px;
|
|
26281
28037
|
border-radius: var(--radius-md);
|
|
26282
|
-
background:
|
|
28038
|
+
background: var(--bg-glass);
|
|
26283
28039
|
color: var(--t-muted);
|
|
26284
28040
|
flex-shrink: 0;
|
|
26285
28041
|
}
|
|
@@ -26289,6 +28045,37 @@ MethodCard.styles = [
|
|
|
26289
28045
|
color: hsl(45, 80%, 60%);
|
|
26290
28046
|
}
|
|
26291
28047
|
|
|
28048
|
+
.badge.scheduled {
|
|
28049
|
+
background: hsla(215, 80%, 60%, 0.15);
|
|
28050
|
+
color: hsl(215, 80%, 65%);
|
|
28051
|
+
}
|
|
28052
|
+
|
|
28053
|
+
.badge.deprecated {
|
|
28054
|
+
background: hsla(0, 0%, 50%, 0.15);
|
|
28055
|
+
color: hsl(0, 0%, 60%);
|
|
28056
|
+
text-decoration: line-through;
|
|
28057
|
+
}
|
|
28058
|
+
|
|
28059
|
+
.badge.cached {
|
|
28060
|
+
background: hsla(280, 60%, 50%, 0.15);
|
|
28061
|
+
color: hsl(280, 60%, 65%);
|
|
28062
|
+
}
|
|
28063
|
+
|
|
28064
|
+
.badge.throttled {
|
|
28065
|
+
background: hsla(30, 80%, 50%, 0.15);
|
|
28066
|
+
color: hsl(30, 80%, 60%);
|
|
28067
|
+
}
|
|
28068
|
+
|
|
28069
|
+
.badge.queued {
|
|
28070
|
+
background: hsla(200, 70%, 50%, 0.15);
|
|
28071
|
+
color: hsl(200, 70%, 60%);
|
|
28072
|
+
}
|
|
28073
|
+
|
|
28074
|
+
.badge.event {
|
|
28075
|
+
background: hsla(100, 70%, 50%, 0.15);
|
|
28076
|
+
color: hsl(100, 70%, 60%);
|
|
28077
|
+
}
|
|
28078
|
+
|
|
26292
28079
|
.param-tags {
|
|
26293
28080
|
display: flex;
|
|
26294
28081
|
flex-wrap: wrap;
|
|
@@ -26302,9 +28089,9 @@ MethodCard.styles = [
|
|
|
26302
28089
|
font-size: var(--text-xs);
|
|
26303
28090
|
padding: 4px 10px;
|
|
26304
28091
|
border-radius: var(--radius-xs);
|
|
26305
|
-
background: hsla(260, 60%, 50%, 0.12);
|
|
26306
|
-
color: var(--t-primary);
|
|
26307
|
-
border: 1px solid hsla(260, 60%, 50%, 0.2);
|
|
28092
|
+
background: var(--param-tag-bg, hsla(260, 60%, 50%, 0.12));
|
|
28093
|
+
color: var(--param-tag-color, var(--t-primary));
|
|
28094
|
+
border: 1px solid var(--param-tag-border, hsla(260, 60%, 50%, 0.2));
|
|
26308
28095
|
font-weight: 500;
|
|
26309
28096
|
}
|
|
26310
28097
|
|
|
@@ -26313,8 +28100,8 @@ MethodCard.styles = [
|
|
|
26313
28100
|
min-width: 20px;
|
|
26314
28101
|
height: 20px;
|
|
26315
28102
|
border-radius: var(--radius-sm);
|
|
26316
|
-
background: hsla(45, 80%, 50%, 0.2);
|
|
26317
|
-
color: hsl(45, 80%, 60%);
|
|
28103
|
+
background: var(--color-warning-bg, hsla(45, 80%, 50%, 0.2));
|
|
28104
|
+
color: var(--color-warning, hsl(45, 80%, 60%));
|
|
26318
28105
|
display: inline-flex;
|
|
26319
28106
|
align-items: center;
|
|
26320
28107
|
justify-content: center;
|
|
@@ -26344,7 +28131,7 @@ MethodCard.styles = [
|
|
|
26344
28131
|
align-items: center;
|
|
26345
28132
|
justify-content: center;
|
|
26346
28133
|
border-radius: var(--radius-sm);
|
|
26347
|
-
background:
|
|
28134
|
+
background: var(--bg-glass);
|
|
26348
28135
|
}
|
|
26349
28136
|
|
|
26350
28137
|
.card:hover .action-icon {
|
|
@@ -26359,7 +28146,7 @@ MethodCard.styles = [
|
|
|
26359
28146
|
border: 1px solid var(--border-glass);
|
|
26360
28147
|
border-radius: var(--radius-md);
|
|
26361
28148
|
padding: var(--space-sm);
|
|
26362
|
-
box-shadow:
|
|
28149
|
+
box-shadow: var(--shadow-lg);
|
|
26363
28150
|
z-index: 100;
|
|
26364
28151
|
display: grid;
|
|
26365
28152
|
grid-template-columns: repeat(6, 1fr);
|
|
@@ -26466,6 +28253,42 @@ MethodCard = __decorateClass([
|
|
|
26466
28253
|
// node_modules/lit-html/directives/if-defined.js
|
|
26467
28254
|
var o8 = (o9) => o9 ?? A;
|
|
26468
28255
|
|
|
28256
|
+
// src/auto-ui/frontend/utils/format-label.ts
|
|
28257
|
+
function formatLabel(name2) {
|
|
28258
|
+
if (!name2) return name2;
|
|
28259
|
+
let cleaned = name2.replace(/^_+/, "");
|
|
28260
|
+
let spaced = cleaned.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2");
|
|
28261
|
+
spaced = spaced.replace(/[_-]+/g, " ");
|
|
28262
|
+
let result = spaced.split(/\s+/).map((word) => {
|
|
28263
|
+
if (!word) return "";
|
|
28264
|
+
const upper = word.toUpperCase();
|
|
28265
|
+
if ([
|
|
28266
|
+
"AI",
|
|
28267
|
+
"ID",
|
|
28268
|
+
"IDS",
|
|
28269
|
+
"URL",
|
|
28270
|
+
"API",
|
|
28271
|
+
"UI",
|
|
28272
|
+
"IP",
|
|
28273
|
+
"HTTP",
|
|
28274
|
+
"HTTPS",
|
|
28275
|
+
"JSON",
|
|
28276
|
+
"XML",
|
|
28277
|
+
"HTML",
|
|
28278
|
+
"CSS",
|
|
28279
|
+
"SQL",
|
|
28280
|
+
"MCP",
|
|
28281
|
+
"SSH",
|
|
28282
|
+
"CLI"
|
|
28283
|
+
].includes(upper)) {
|
|
28284
|
+
if (upper === "IDS") return "IDs";
|
|
28285
|
+
return upper;
|
|
28286
|
+
}
|
|
28287
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
28288
|
+
}).join(" ");
|
|
28289
|
+
return result;
|
|
28290
|
+
}
|
|
28291
|
+
|
|
26469
28292
|
// src/auto-ui/frontend/components/invoke-form.ts
|
|
26470
28293
|
function capitalizeEnumValue(val) {
|
|
26471
28294
|
return formatLabel(val);
|
|
@@ -26492,6 +28315,30 @@ function singularize(word) {
|
|
|
26492
28315
|
if (lower.endsWith("s") && !lower.endsWith("ss")) return word.slice(0, -1);
|
|
26493
28316
|
return word;
|
|
26494
28317
|
}
|
|
28318
|
+
function isValidCharForFormat(char, format, position) {
|
|
28319
|
+
if (!format) return true;
|
|
28320
|
+
switch (format.toLowerCase()) {
|
|
28321
|
+
case "email":
|
|
28322
|
+
return /[a-zA-Z0-9@.\-_+]/.test(char);
|
|
28323
|
+
case "url":
|
|
28324
|
+
case "uri":
|
|
28325
|
+
return /[a-zA-Z0-9:\/\-_.?=&#%@+~;,!]/.test(char);
|
|
28326
|
+
case "uuid":
|
|
28327
|
+
return /[0-9a-fA-F\-]/.test(char);
|
|
28328
|
+
case "ipv4":
|
|
28329
|
+
return /[0-9.]/.test(char);
|
|
28330
|
+
case "ipv6":
|
|
28331
|
+
return /[0-9a-fA-F:]/.test(char);
|
|
28332
|
+
case "slug":
|
|
28333
|
+
return /[a-z0-9\-]/.test(char);
|
|
28334
|
+
case "hex":
|
|
28335
|
+
return position === 0 && char === "#" ? true : /[0-9a-fA-F]/.test(char);
|
|
28336
|
+
case "phone":
|
|
28337
|
+
return /[0-9+\-() ]/.test(char);
|
|
28338
|
+
default:
|
|
28339
|
+
return true;
|
|
28340
|
+
}
|
|
28341
|
+
}
|
|
26495
28342
|
var InvokeForm = class extends i4 {
|
|
26496
28343
|
constructor() {
|
|
26497
28344
|
super(...arguments);
|
|
@@ -26746,9 +28593,7 @@ var InvokeForm = class extends i4 {
|
|
|
26746
28593
|
this._handleChange(key, arr.length > 0 ? arr : raw);
|
|
26747
28594
|
}}
|
|
26748
28595
|
/>
|
|
26749
|
-
<div class="hint"
|
|
26750
|
-
Comma-separated values
|
|
26751
|
-
</div>
|
|
28596
|
+
<div class="hint">Comma-separated values</div>
|
|
26752
28597
|
</div>
|
|
26753
28598
|
`;
|
|
26754
28599
|
}
|
|
@@ -26799,9 +28644,12 @@ var InvokeForm = class extends i4 {
|
|
|
26799
28644
|
min="${min}"
|
|
26800
28645
|
max="${max}"
|
|
26801
28646
|
step="${step2}"
|
|
28647
|
+
style="${this._sliderFillStyle(Number(currentValue2), min, max)}"
|
|
26802
28648
|
.value=${String(currentValue2)}
|
|
26803
28649
|
@input=${(e8) => {
|
|
26804
|
-
const
|
|
28650
|
+
const el2 = e8.target;
|
|
28651
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
28652
|
+
el2.style.cssText = this._sliderFillStyle(v2, min, max);
|
|
26805
28653
|
this._handleChange(key, v2);
|
|
26806
28654
|
}}
|
|
26807
28655
|
/>
|
|
@@ -26814,7 +28662,14 @@ var InvokeForm = class extends i4 {
|
|
|
26814
28662
|
step="${step2}"
|
|
26815
28663
|
.value=${displayValue2}
|
|
26816
28664
|
@input=${(e8) => {
|
|
26817
|
-
const
|
|
28665
|
+
const raw = e8.target.value;
|
|
28666
|
+
if (raw === "" || raw === "-") return;
|
|
28667
|
+
this._handleChange(key, Number(raw));
|
|
28668
|
+
}}
|
|
28669
|
+
@change=${(e8) => {
|
|
28670
|
+
const el2 = e8.target;
|
|
28671
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
28672
|
+
el2.value = String(v2);
|
|
26818
28673
|
this._handleChange(key, v2);
|
|
26819
28674
|
}}
|
|
26820
28675
|
/>
|
|
@@ -26833,14 +28688,31 @@ var InvokeForm = class extends i4 {
|
|
|
26833
28688
|
return b2`
|
|
26834
28689
|
<input
|
|
26835
28690
|
id=${o8(inputId)}
|
|
26836
|
-
type="
|
|
26837
|
-
class="${errorClass}"
|
|
28691
|
+
type="text"
|
|
28692
|
+
class="number-input-clean ${errorClass}"
|
|
28693
|
+
inputmode=${isInteger ? "numeric" : "decimal"}
|
|
26838
28694
|
${hasMin ? `min="${schema.minimum}"` : ""}
|
|
26839
|
-
step="${step}"
|
|
26840
28695
|
placeholder="${defaultVal2}"
|
|
26841
28696
|
.value=${displayValue}
|
|
28697
|
+
@keypress=${(e8) => {
|
|
28698
|
+
const char = e8.key;
|
|
28699
|
+
const isDigit = /\d/.test(char);
|
|
28700
|
+
const isMinus = char === "-";
|
|
28701
|
+
const isDecimal = char === "." && !isInteger;
|
|
28702
|
+
if (!isDigit && !isMinus && !isDecimal) {
|
|
28703
|
+
e8.preventDefault();
|
|
28704
|
+
}
|
|
28705
|
+
}}
|
|
26842
28706
|
@input=${(e8) => {
|
|
26843
|
-
|
|
28707
|
+
let text = e8.target.value;
|
|
28708
|
+
if (isInteger) {
|
|
28709
|
+
const cleaned = text.replace(/[^\d-]/g, "");
|
|
28710
|
+
text = cleaned.match(/-.*-/) ? cleaned.replace(/-/g, "").replace(/^/, "-") : cleaned;
|
|
28711
|
+
}
|
|
28712
|
+
let v2 = text === "" || text === "-" ? defaultVal2 : Number(text);
|
|
28713
|
+
if (isNaN(v2)) {
|
|
28714
|
+
v2 = defaultVal2;
|
|
28715
|
+
}
|
|
26844
28716
|
this._handleChange(key, v2);
|
|
26845
28717
|
}}
|
|
26846
28718
|
/>
|
|
@@ -26928,6 +28800,8 @@ var InvokeForm = class extends i4 {
|
|
|
26928
28800
|
}
|
|
26929
28801
|
const defaultVal = schema.default;
|
|
26930
28802
|
const placeholder = defaultVal != null ? String(defaultVal) : "";
|
|
28803
|
+
const format = schema.format;
|
|
28804
|
+
const pattern = schema.pattern;
|
|
26931
28805
|
return b2`
|
|
26932
28806
|
<input
|
|
26933
28807
|
id=${o8(inputId)}
|
|
@@ -26935,6 +28809,23 @@ var InvokeForm = class extends i4 {
|
|
|
26935
28809
|
class="${errorClass}"
|
|
26936
28810
|
placeholder="${placeholder}"
|
|
26937
28811
|
.value=${this._values[key] || ""}
|
|
28812
|
+
@keypress=${(e8) => {
|
|
28813
|
+
if (!isValidCharForFormat(e8.key, format)) {
|
|
28814
|
+
e8.preventDefault();
|
|
28815
|
+
return;
|
|
28816
|
+
}
|
|
28817
|
+
if (pattern) {
|
|
28818
|
+
try {
|
|
28819
|
+
const currentValue = e8.target.value;
|
|
28820
|
+
const newValue = currentValue + e8.key;
|
|
28821
|
+
const regex = new RegExp(pattern);
|
|
28822
|
+
if (!regex.test(newValue)) {
|
|
28823
|
+
e8.preventDefault();
|
|
28824
|
+
}
|
|
28825
|
+
} catch (err) {
|
|
28826
|
+
}
|
|
28827
|
+
}
|
|
28828
|
+
}}
|
|
26938
28829
|
@input=${(e8) => this._handleChange(key, e8.target.value)}
|
|
26939
28830
|
/>
|
|
26940
28831
|
`;
|
|
@@ -27059,7 +28950,11 @@ var InvokeForm = class extends i4 {
|
|
|
27059
28950
|
*/
|
|
27060
28951
|
_cleanDescription(desc, schema) {
|
|
27061
28952
|
if (!desc) return desc;
|
|
27062
|
-
let cleaned = desc
|
|
28953
|
+
let cleaned = desc;
|
|
28954
|
+
const lines = cleaned.split("\n").filter((line) => !line.trim().startsWith("@"));
|
|
28955
|
+
cleaned = lines.join("\n").trim();
|
|
28956
|
+
cleaned = cleaned.replace(/\s*@\w+[\s\S]*?(?=[.!?\n]|$)/g, "").trim();
|
|
28957
|
+
cleaned = cleaned.replace(
|
|
27063
28958
|
/['"][\w-]+['"]\s*(?:\([^)]*\)\s*)?(?:\|\s*['"][\w-]+['"]\s*(?:\([^)]*\)\s*)?)+/g,
|
|
27064
28959
|
""
|
|
27065
28960
|
);
|
|
@@ -27095,6 +28990,23 @@ var InvokeForm = class extends i4 {
|
|
|
27095
28990
|
this._savePersistedValues();
|
|
27096
28991
|
}
|
|
27097
28992
|
}
|
|
28993
|
+
_sliderFillStyle(value, min, max) {
|
|
28994
|
+
const pct = max > min ? (value - min) / (max - min) * 100 : 0;
|
|
28995
|
+
return `background: linear-gradient(to right, var(--accent-primary) ${pct}%, var(--border-glass) ${pct}%)`;
|
|
28996
|
+
}
|
|
28997
|
+
/** Clamp to [min, max] and round to nearest step (integer-safe). */
|
|
28998
|
+
_sanitizeSliderValue(raw, min, max, step) {
|
|
28999
|
+
let v2 = Number.isFinite(raw) ? raw : min;
|
|
29000
|
+
v2 = Math.min(max, Math.max(min, v2));
|
|
29001
|
+
if (step > 0) {
|
|
29002
|
+
v2 = min + Math.round((v2 - min) / step) * step;
|
|
29003
|
+
if (v2 > max) v2 = max;
|
|
29004
|
+
}
|
|
29005
|
+
if (Number.isInteger(step) && step >= 1) {
|
|
29006
|
+
v2 = Math.round(v2);
|
|
29007
|
+
}
|
|
29008
|
+
return v2;
|
|
29009
|
+
}
|
|
27098
29010
|
_handleChange(key, value) {
|
|
27099
29011
|
this._values = { ...this._values, [key]: value };
|
|
27100
29012
|
if (this.rememberValues) {
|
|
@@ -27102,7 +29014,7 @@ var InvokeForm = class extends i4 {
|
|
|
27102
29014
|
}
|
|
27103
29015
|
}
|
|
27104
29016
|
_buildCliCommand() {
|
|
27105
|
-
const parts = [
|
|
29017
|
+
const parts = [this.photonName, this.methodName];
|
|
27106
29018
|
for (const [key, value] of Object.entries(this._values)) {
|
|
27107
29019
|
if (value === void 0 || value === null || value === "") continue;
|
|
27108
29020
|
const strVal = typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
@@ -27226,7 +29138,9 @@ var InvokeForm = class extends i4 {
|
|
|
27226
29138
|
>
|
|
27227
29139
|
<option value="">Select...</option>
|
|
27228
29140
|
${schema.enum.map(
|
|
27229
|
-
(opt) => b2`
|
|
29141
|
+
(opt) => b2`
|
|
29142
|
+
<option value=${opt} ?selected=${opt === value}>${capitalizeEnumValue(opt)}</option>
|
|
29143
|
+
`
|
|
27230
29144
|
)}
|
|
27231
29145
|
</select>
|
|
27232
29146
|
`;
|
|
@@ -27262,8 +29176,14 @@ var InvokeForm = class extends i4 {
|
|
|
27262
29176
|
min="${min}"
|
|
27263
29177
|
max="${max}"
|
|
27264
29178
|
step="${step2}"
|
|
29179
|
+
style="${this._sliderFillStyle(Number(currentVal2), min, max)}"
|
|
27265
29180
|
.value=${String(currentVal2)}
|
|
27266
|
-
@input=${(e8) =>
|
|
29181
|
+
@input=${(e8) => {
|
|
29182
|
+
const el2 = e8.target;
|
|
29183
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
29184
|
+
el2.style.cssText = this._sliderFillStyle(v2, min, max);
|
|
29185
|
+
onChange(propKey, v2);
|
|
29186
|
+
}}
|
|
27267
29187
|
/>
|
|
27268
29188
|
<input
|
|
27269
29189
|
type="number"
|
|
@@ -27272,7 +29192,17 @@ var InvokeForm = class extends i4 {
|
|
|
27272
29192
|
max="${max}"
|
|
27273
29193
|
step="${step2}"
|
|
27274
29194
|
.value=${displayVal2}
|
|
27275
|
-
@input=${(e8) =>
|
|
29195
|
+
@input=${(e8) => {
|
|
29196
|
+
const raw = e8.target.value;
|
|
29197
|
+
if (raw === "" || raw === "-") return;
|
|
29198
|
+
onChange(propKey, Number(raw));
|
|
29199
|
+
}}
|
|
29200
|
+
@change=${(e8) => {
|
|
29201
|
+
const el2 = e8.target;
|
|
29202
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
29203
|
+
el2.value = String(v2);
|
|
29204
|
+
onChange(propKey, v2);
|
|
29205
|
+
}}
|
|
27276
29206
|
/>
|
|
27277
29207
|
</div>
|
|
27278
29208
|
<div class="range-labels">
|
|
@@ -27439,18 +29369,23 @@ var InvokeForm = class extends i4 {
|
|
|
27439
29369
|
>
|
|
27440
29370
|
<option value="">Select...</option>
|
|
27441
29371
|
${schema.enum.map(
|
|
27442
|
-
(opt) => b2`
|
|
29372
|
+
(opt) => b2`
|
|
29373
|
+
<option value=${opt} ?selected=${opt === value}>${capitalizeEnumValue(opt)}</option>
|
|
29374
|
+
`
|
|
27443
29375
|
)}
|
|
27444
29376
|
</select>
|
|
27445
29377
|
`;
|
|
27446
29378
|
}
|
|
27447
29379
|
if (schema.type === "boolean") {
|
|
27448
29380
|
return b2`
|
|
27449
|
-
<
|
|
27450
|
-
|
|
27451
|
-
|
|
27452
|
-
|
|
27453
|
-
|
|
29381
|
+
<label class="switch">
|
|
29382
|
+
<input
|
|
29383
|
+
type="checkbox"
|
|
29384
|
+
.checked=${!!value}
|
|
29385
|
+
@change=${(e8) => handleNestedChange(e8.target.checked)}
|
|
29386
|
+
/>
|
|
29387
|
+
<span class="slider"></span>
|
|
29388
|
+
</label>
|
|
27454
29389
|
`;
|
|
27455
29390
|
}
|
|
27456
29391
|
if (schema.type === "number" || schema.type === "integer") {
|
|
@@ -27472,8 +29407,14 @@ var InvokeForm = class extends i4 {
|
|
|
27472
29407
|
min="${min}"
|
|
27473
29408
|
max="${max}"
|
|
27474
29409
|
step="${step2}"
|
|
29410
|
+
style="${this._sliderFillStyle(Number(currentVal2), min, max)}"
|
|
27475
29411
|
.value=${String(currentVal2)}
|
|
27476
|
-
@input=${(e8) =>
|
|
29412
|
+
@input=${(e8) => {
|
|
29413
|
+
const el2 = e8.target;
|
|
29414
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
29415
|
+
el2.style.cssText = this._sliderFillStyle(v2, min, max);
|
|
29416
|
+
handleNestedChange(v2);
|
|
29417
|
+
}}
|
|
27477
29418
|
/>
|
|
27478
29419
|
<input
|
|
27479
29420
|
type="number"
|
|
@@ -27482,7 +29423,17 @@ var InvokeForm = class extends i4 {
|
|
|
27482
29423
|
max="${max}"
|
|
27483
29424
|
step="${step2}"
|
|
27484
29425
|
.value=${displayVal2}
|
|
27485
|
-
@input=${(e8) =>
|
|
29426
|
+
@input=${(e8) => {
|
|
29427
|
+
const raw = e8.target.value;
|
|
29428
|
+
if (raw === "" || raw === "-") return;
|
|
29429
|
+
handleNestedChange(Number(raw));
|
|
29430
|
+
}}
|
|
29431
|
+
@change=${(e8) => {
|
|
29432
|
+
const el2 = e8.target;
|
|
29433
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step2);
|
|
29434
|
+
el2.value = String(v2);
|
|
29435
|
+
handleNestedChange(v2);
|
|
29436
|
+
}}
|
|
27486
29437
|
/>
|
|
27487
29438
|
</div>
|
|
27488
29439
|
<div class="range-labels">
|
|
@@ -27833,6 +29784,7 @@ InvokeForm.styles = [
|
|
|
27833
29784
|
font-size: var(--text-xs);
|
|
27834
29785
|
padding: 2px 6px;
|
|
27835
29786
|
border-radius: var(--radius-xs);
|
|
29787
|
+
transition: background 0.15s ease;
|
|
27836
29788
|
}
|
|
27837
29789
|
|
|
27838
29790
|
.array-item-remove:hover {
|
|
@@ -27909,11 +29861,17 @@ InvokeForm.styles = [
|
|
|
27909
29861
|
margin-top: var(--space-xs);
|
|
27910
29862
|
}
|
|
27911
29863
|
|
|
29864
|
+
.hint {
|
|
29865
|
+
font-size: var(--text-xs);
|
|
29866
|
+
color: var(--t-muted);
|
|
29867
|
+
margin-top: 2px;
|
|
29868
|
+
}
|
|
29869
|
+
|
|
27912
29870
|
/* Slider-First Numeric Input */
|
|
27913
29871
|
.slider-group {
|
|
27914
29872
|
display: flex;
|
|
27915
29873
|
flex-direction: column;
|
|
27916
|
-
gap:
|
|
29874
|
+
gap: 4px;
|
|
27917
29875
|
}
|
|
27918
29876
|
|
|
27919
29877
|
.slider-row {
|
|
@@ -27924,56 +29882,140 @@ InvokeForm.styles = [
|
|
|
27924
29882
|
|
|
27925
29883
|
.slider-row input[type='range'] {
|
|
27926
29884
|
flex: 1;
|
|
27927
|
-
height:
|
|
27928
|
-
|
|
27929
|
-
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
27930
|
-
border-radius: 3px;
|
|
29885
|
+
height: 4px;
|
|
29886
|
+
border-radius: var(--radius-full, 9999px);
|
|
27931
29887
|
-webkit-appearance: none;
|
|
27932
29888
|
cursor: pointer;
|
|
27933
29889
|
margin: 8px 0;
|
|
29890
|
+
border: none;
|
|
29891
|
+
outline: none;
|
|
29892
|
+
/* Default unfilled track — overridden by inline style for fill effect */
|
|
29893
|
+
background: var(--border-glass);
|
|
27934
29894
|
}
|
|
27935
29895
|
|
|
27936
29896
|
.slider-row input[type='range']::-webkit-slider-thumb {
|
|
27937
29897
|
-webkit-appearance: none;
|
|
27938
|
-
width:
|
|
27939
|
-
height:
|
|
29898
|
+
width: 16px;
|
|
29899
|
+
height: 16px;
|
|
27940
29900
|
background: var(--accent-primary);
|
|
29901
|
+
border: 2px solid var(--bg-panel, var(--bg-glass));
|
|
27941
29902
|
border-radius: 50%;
|
|
27942
29903
|
cursor: pointer;
|
|
27943
|
-
box-shadow:
|
|
29904
|
+
box-shadow:
|
|
29905
|
+
0 0 0 2px var(--accent-primary),
|
|
29906
|
+
0 1px 4px rgba(0, 0, 0, 0.3);
|
|
29907
|
+
transition:
|
|
29908
|
+
box-shadow 0.15s ease,
|
|
29909
|
+
transform 0.15s ease;
|
|
29910
|
+
}
|
|
29911
|
+
|
|
29912
|
+
.slider-row input[type='range']::-webkit-slider-thumb:hover {
|
|
29913
|
+
box-shadow:
|
|
29914
|
+
0 0 0 3px var(--accent-primary),
|
|
29915
|
+
0 0 8px var(--glow-primary);
|
|
29916
|
+
transform: scale(1.1);
|
|
29917
|
+
}
|
|
29918
|
+
|
|
29919
|
+
.slider-row input[type='range']:active::-webkit-slider-thumb {
|
|
29920
|
+
transform: scale(0.95);
|
|
27944
29921
|
}
|
|
27945
29922
|
|
|
27946
29923
|
.slider-row input[type='range']::-moz-range-track {
|
|
27947
|
-
height:
|
|
27948
|
-
background:
|
|
27949
|
-
border-radius:
|
|
27950
|
-
border:
|
|
29924
|
+
height: 4px;
|
|
29925
|
+
background: var(--border-glass);
|
|
29926
|
+
border-radius: var(--radius-full, 9999px);
|
|
29927
|
+
border: none;
|
|
29928
|
+
}
|
|
29929
|
+
|
|
29930
|
+
.slider-row input[type='range']::-moz-range-progress {
|
|
29931
|
+
height: 4px;
|
|
29932
|
+
background: var(--accent-primary);
|
|
29933
|
+
border-radius: var(--radius-full, 9999px);
|
|
27951
29934
|
}
|
|
27952
29935
|
|
|
27953
29936
|
.slider-row input[type='range']::-moz-range-thumb {
|
|
27954
|
-
width:
|
|
27955
|
-
height:
|
|
29937
|
+
width: 12px;
|
|
29938
|
+
height: 12px;
|
|
27956
29939
|
background: var(--accent-primary);
|
|
29940
|
+
border: 2px solid var(--bg-panel, var(--bg-glass));
|
|
27957
29941
|
border-radius: 50%;
|
|
27958
29942
|
cursor: pointer;
|
|
27959
|
-
|
|
27960
|
-
|
|
29943
|
+
box-shadow:
|
|
29944
|
+
0 0 0 2px var(--accent-primary),
|
|
29945
|
+
0 1px 4px rgba(0, 0, 0, 0.3);
|
|
29946
|
+
transition:
|
|
29947
|
+
box-shadow 0.15s ease,
|
|
29948
|
+
transform 0.15s ease;
|
|
27961
29949
|
}
|
|
27962
29950
|
|
|
27963
|
-
.slider-
|
|
27964
|
-
|
|
29951
|
+
.slider-row input[type='range']::-moz-range-thumb:hover {
|
|
29952
|
+
box-shadow:
|
|
29953
|
+
0 0 0 3px var(--accent-primary),
|
|
29954
|
+
0 0 8px var(--glow-primary);
|
|
29955
|
+
}
|
|
29956
|
+
|
|
29957
|
+
.slider-number-input {
|
|
29958
|
+
width: 64px;
|
|
27965
29959
|
text-align: center;
|
|
29960
|
+
font-size: var(--text-sm);
|
|
29961
|
+
font-weight: 500;
|
|
29962
|
+
font-variant-numeric: tabular-nums;
|
|
29963
|
+
padding: 4px 6px;
|
|
29964
|
+
background: var(--bg-glass);
|
|
29965
|
+
border: 1px solid var(--border-glass) !important;
|
|
29966
|
+
border-radius: var(--radius-sm);
|
|
29967
|
+
color: var(--t-primary);
|
|
29968
|
+
-moz-appearance: textfield;
|
|
29969
|
+
transition:
|
|
29970
|
+
border-color 0.15s ease,
|
|
29971
|
+
box-shadow 0.15s ease;
|
|
29972
|
+
}
|
|
29973
|
+
|
|
29974
|
+
.slider-number-input::-webkit-outer-spin-button,
|
|
29975
|
+
.slider-number-input::-webkit-inner-spin-button {
|
|
29976
|
+
-webkit-appearance: none;
|
|
29977
|
+
margin: 0;
|
|
29978
|
+
}
|
|
29979
|
+
|
|
29980
|
+
.slider-number-input:focus-visible {
|
|
29981
|
+
outline: none;
|
|
29982
|
+
border-color: var(--accent-primary) !important;
|
|
29983
|
+
box-shadow: 0 0 0 2px var(--glow-primary);
|
|
29984
|
+
}
|
|
29985
|
+
|
|
29986
|
+
/* Clean numeric input — no spinner, mouse wheel support */
|
|
29987
|
+
.number-input-clean {
|
|
29988
|
+
width: 100%;
|
|
29989
|
+
padding: 8px 12px;
|
|
27966
29990
|
font-size: var(--text-md);
|
|
27967
|
-
|
|
29991
|
+
background: var(--bg-glass);
|
|
29992
|
+
border: 1px solid var(--border-glass);
|
|
29993
|
+
border-radius: var(--radius-sm);
|
|
27968
29994
|
color: var(--t-primary);
|
|
27969
|
-
|
|
29995
|
+
appearance: none;
|
|
29996
|
+
-moz-appearance: textfield;
|
|
29997
|
+
-webkit-appearance: none;
|
|
29998
|
+
transition:
|
|
29999
|
+
border-color 0.15s ease,
|
|
30000
|
+
box-shadow 0.15s ease;
|
|
27970
30001
|
}
|
|
27971
30002
|
|
|
27972
|
-
.
|
|
27973
|
-
|
|
27974
|
-
|
|
27975
|
-
|
|
27976
|
-
|
|
30003
|
+
.number-input-clean::-webkit-outer-spin-button,
|
|
30004
|
+
.number-input-clean::-webkit-inner-spin-button {
|
|
30005
|
+
-webkit-appearance: none;
|
|
30006
|
+
appearance: none;
|
|
30007
|
+
display: none;
|
|
30008
|
+
margin: 0;
|
|
30009
|
+
}
|
|
30010
|
+
|
|
30011
|
+
.number-input-clean:hover {
|
|
30012
|
+
border-color: var(--accent-primary);
|
|
30013
|
+
}
|
|
30014
|
+
|
|
30015
|
+
.number-input-clean:focus-visible {
|
|
30016
|
+
outline: none;
|
|
30017
|
+
border-color: var(--accent-primary);
|
|
30018
|
+
box-shadow: 0 0 0 2px var(--glow-primary);
|
|
27977
30019
|
}
|
|
27978
30020
|
|
|
27979
30021
|
.range-labels {
|
|
@@ -28022,6 +30064,15 @@ InvokeForm.styles = [
|
|
|
28022
30064
|
flex-shrink: 0;
|
|
28023
30065
|
}
|
|
28024
30066
|
|
|
30067
|
+
select {
|
|
30068
|
+
appearance: none;
|
|
30069
|
+
-webkit-appearance: none;
|
|
30070
|
+
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");
|
|
30071
|
+
background-repeat: no-repeat;
|
|
30072
|
+
background-position: right 12px center;
|
|
30073
|
+
padding-right: 32px;
|
|
30074
|
+
}
|
|
30075
|
+
|
|
28025
30076
|
/* ===== Responsive Design ===== */
|
|
28026
30077
|
@media (max-width: 768px) {
|
|
28027
30078
|
.form-container {
|
|
@@ -28224,7 +30275,7 @@ ActivityLog.styles = [
|
|
|
28224
30275
|
font-size: var(--text-sm);
|
|
28225
30276
|
text-transform: uppercase;
|
|
28226
30277
|
letter-spacing: 0.1em;
|
|
28227
|
-
color: var(--t-
|
|
30278
|
+
color: var(--t-primary);
|
|
28228
30279
|
font-weight: 600;
|
|
28229
30280
|
}
|
|
28230
30281
|
|
|
@@ -28239,7 +30290,7 @@ ActivityLog.styles = [
|
|
|
28239
30290
|
}
|
|
28240
30291
|
|
|
28241
30292
|
.clear-btn:hover {
|
|
28242
|
-
background:
|
|
30293
|
+
background: var(--bg-glass);
|
|
28243
30294
|
color: var(--t-primary);
|
|
28244
30295
|
}
|
|
28245
30296
|
|
|
@@ -28258,14 +30309,14 @@ ActivityLog.styles = [
|
|
|
28258
30309
|
}
|
|
28259
30310
|
|
|
28260
30311
|
.filter-btn:hover {
|
|
28261
|
-
background:
|
|
30312
|
+
background: var(--bg-glass);
|
|
28262
30313
|
color: var(--t-primary);
|
|
28263
30314
|
}
|
|
28264
30315
|
|
|
28265
30316
|
.filter-btn.active {
|
|
28266
30317
|
border-color: var(--accent-secondary);
|
|
28267
30318
|
color: var(--accent-secondary);
|
|
28268
|
-
background:
|
|
30319
|
+
background: var(--bg-glass);
|
|
28269
30320
|
}
|
|
28270
30321
|
|
|
28271
30322
|
.visually-hidden {
|
|
@@ -28325,7 +30376,7 @@ ActivityLog.styles = [
|
|
|
28325
30376
|
display: inline-block;
|
|
28326
30377
|
font-size: var(--text-xs);
|
|
28327
30378
|
color: var(--t-muted);
|
|
28328
|
-
background:
|
|
30379
|
+
background: var(--bg-glass);
|
|
28329
30380
|
padding: 1px 6px;
|
|
28330
30381
|
border-radius: var(--radius-full);
|
|
28331
30382
|
margin-left: var(--space-sm);
|
|
@@ -28484,6 +30535,8 @@ var ResultViewer = class extends i4 {
|
|
|
28484
30535
|
this._previousResult = null;
|
|
28485
30536
|
// Recency heat: track when items were last added/updated
|
|
28486
30537
|
this._itemHeatTimestamps = /* @__PURE__ */ new Map();
|
|
30538
|
+
// Audit trail expansion state: track which items have expanded audit trails
|
|
30539
|
+
this._expandedAuditTrails = /* @__PURE__ */ new Set();
|
|
28487
30540
|
// The detected ID field for the current result (shared across diff, animation, warmth)
|
|
28488
30541
|
this._activeIdField = "id";
|
|
28489
30542
|
// Chart.js instance for reactive updates
|
|
@@ -28786,19 +30839,32 @@ var ResultViewer = class extends i4 {
|
|
|
28786
30839
|
/**
|
|
28787
30840
|
* Get the warmth class based on recency heat.
|
|
28788
30841
|
* Reads timestamp from item data first (survives refresh), falls back to in-memory map.
|
|
30842
|
+
* Prioritizes __meta timestamps (most recent), then standard timestamp fields.
|
|
28789
30843
|
*/
|
|
28790
30844
|
_getItemWarmthClass(item) {
|
|
28791
30845
|
const idField = this._activeIdField;
|
|
28792
30846
|
let timestamp;
|
|
28793
30847
|
if (item && typeof item === "object") {
|
|
28794
30848
|
const rec = item;
|
|
28795
|
-
|
|
28796
|
-
|
|
28797
|
-
if (
|
|
28798
|
-
const parsed =
|
|
28799
|
-
if (!isNaN(parsed))
|
|
28800
|
-
|
|
28801
|
-
|
|
30849
|
+
const meta4 = rec.__meta;
|
|
30850
|
+
if (meta4 && typeof meta4 === "object") {
|
|
30851
|
+
if (meta4.modifiedAt) {
|
|
30852
|
+
const parsed = new Date(meta4.modifiedAt).getTime();
|
|
30853
|
+
if (!isNaN(parsed)) timestamp = parsed;
|
|
30854
|
+
} else if (meta4.createdAt) {
|
|
30855
|
+
const parsed = new Date(meta4.createdAt).getTime();
|
|
30856
|
+
if (!isNaN(parsed)) timestamp = parsed;
|
|
30857
|
+
}
|
|
30858
|
+
}
|
|
30859
|
+
if (timestamp === void 0) {
|
|
30860
|
+
for (const field of ResultViewer._TIMESTAMP_FIELDS) {
|
|
30861
|
+
const val = rec[field];
|
|
30862
|
+
if (val !== void 0 && val !== null) {
|
|
30863
|
+
const parsed = typeof val === "number" ? val : new Date(typeof val === "string" ? val : String(val)).getTime();
|
|
30864
|
+
if (!isNaN(parsed)) {
|
|
30865
|
+
timestamp = parsed;
|
|
30866
|
+
break;
|
|
30867
|
+
}
|
|
28802
30868
|
}
|
|
28803
30869
|
}
|
|
28804
30870
|
}
|
|
@@ -29307,7 +31373,8 @@ var ResultViewer = class extends i4 {
|
|
|
29307
31373
|
"tabs",
|
|
29308
31374
|
"accordion",
|
|
29309
31375
|
"stack",
|
|
29310
|
-
"columns"
|
|
31376
|
+
"columns",
|
|
31377
|
+
"qr"
|
|
29311
31378
|
].includes(format)) {
|
|
29312
31379
|
return format;
|
|
29313
31380
|
}
|
|
@@ -29474,6 +31541,8 @@ var ResultViewer = class extends i4 {
|
|
|
29474
31541
|
return this._renderStack(filteredData);
|
|
29475
31542
|
case "columns":
|
|
29476
31543
|
return this._renderColumns(filteredData);
|
|
31544
|
+
case "qr":
|
|
31545
|
+
return this._renderQR(filteredData);
|
|
29477
31546
|
case "mermaid":
|
|
29478
31547
|
return this._renderMermaid(filteredData);
|
|
29479
31548
|
case "json":
|
|
@@ -29716,6 +31785,136 @@ var ResultViewer = class extends i4 {
|
|
|
29716
31785
|
</div>
|
|
29717
31786
|
`
|
|
29718
31787
|
)}
|
|
31788
|
+
${this._renderAuditTrail(data)}
|
|
31789
|
+
`;
|
|
31790
|
+
}
|
|
31791
|
+
/**
|
|
31792
|
+
* Render audit trail from __meta object if present
|
|
31793
|
+
*/
|
|
31794
|
+
_renderAuditTrail(data) {
|
|
31795
|
+
if (!data || typeof data !== "object") return "";
|
|
31796
|
+
const meta4 = data.__meta;
|
|
31797
|
+
if (!meta4 || typeof meta4 !== "object") return "";
|
|
31798
|
+
const idField = this._activeIdField;
|
|
31799
|
+
const itemId = data[idField] ? String(data[idField]) : Math.random().toString(36);
|
|
31800
|
+
const auditKey = `audit-${itemId}`;
|
|
31801
|
+
const isExpanded = this._expandedAuditTrails.has(auditKey);
|
|
31802
|
+
const formatTime = (isoString) => {
|
|
31803
|
+
if (!isoString) return "N/A";
|
|
31804
|
+
const date4 = new Date(isoString);
|
|
31805
|
+
return date4.toLocaleString();
|
|
31806
|
+
};
|
|
31807
|
+
const createdAt = formatTime(meta4.createdAt);
|
|
31808
|
+
const modifiedAt = meta4.modifiedAt ? formatTime(meta4.modifiedAt) : null;
|
|
31809
|
+
return b2`
|
|
31810
|
+
<div
|
|
31811
|
+
style="margin-top: var(--space-md); border-top: 1px solid var(--border-glass); padding-top: var(--space-md);"
|
|
31812
|
+
>
|
|
31813
|
+
<details
|
|
31814
|
+
?open="${isExpanded}"
|
|
31815
|
+
@toggle="${(e8) => {
|
|
31816
|
+
const detail = e8.target;
|
|
31817
|
+
if (detail.open) {
|
|
31818
|
+
this._expandedAuditTrails.add(auditKey);
|
|
31819
|
+
} else {
|
|
31820
|
+
this._expandedAuditTrails.delete(auditKey);
|
|
31821
|
+
}
|
|
31822
|
+
}}"
|
|
31823
|
+
>
|
|
31824
|
+
<summary
|
|
31825
|
+
style="cursor: pointer; font-weight: 500; display: flex; align-items: center; gap: var(--space-sm);"
|
|
31826
|
+
>
|
|
31827
|
+
<span
|
|
31828
|
+
style="display: inline-block; width: 0.5em; height: 0.5em; border-radius: 50%; background: var(--text-secondary); margin-right: var(--space-xs);"
|
|
31829
|
+
></span>
|
|
31830
|
+
Audit Trail
|
|
31831
|
+
${meta4.modifications?.length ? b2`<span style="font-size: 0.85em; color: var(--text-secondary);"
|
|
31832
|
+
>(${meta4.modifications.length} changes)</span
|
|
31833
|
+
>` : ""}
|
|
31834
|
+
</summary>
|
|
31835
|
+
|
|
31836
|
+
<div
|
|
31837
|
+
style="margin-top: var(--space-md); padding: var(--space-sm) var(--space-md); background: var(--bg-secondary); border-radius: var(--radius-sm);"
|
|
31838
|
+
>
|
|
31839
|
+
<table style="width: 100%; font-size: 0.9em;">
|
|
31840
|
+
<tbody>
|
|
31841
|
+
<tr style="border-bottom: 1px solid var(--border-subtle);">
|
|
31842
|
+
<td
|
|
31843
|
+
style="padding: var(--space-xs); color: var(--text-secondary); font-weight: 500;"
|
|
31844
|
+
>
|
|
31845
|
+
Created
|
|
31846
|
+
</td>
|
|
31847
|
+
<td style="padding: var(--space-xs);">${createdAt}</td>
|
|
31848
|
+
${meta4.createdBy ? b2`<td
|
|
31849
|
+
style="padding: var(--space-xs); color: var(--text-secondary); font-size: 0.85em;"
|
|
31850
|
+
>
|
|
31851
|
+
(by: ${meta4.createdBy})
|
|
31852
|
+
</td>` : ""}
|
|
31853
|
+
</tr>
|
|
31854
|
+
${modifiedAt ? b2`
|
|
31855
|
+
<tr style="border-bottom: 1px solid var(--border-subtle);">
|
|
31856
|
+
<td
|
|
31857
|
+
style="padding: var(--space-xs); color: var(--text-secondary); font-weight: 500;"
|
|
31858
|
+
>
|
|
31859
|
+
Modified
|
|
31860
|
+
</td>
|
|
31861
|
+
<td style="padding: var(--space-xs);">${modifiedAt}</td>
|
|
31862
|
+
${meta4.modifiedBy ? b2`<td
|
|
31863
|
+
style="padding: var(--space-xs); color: var(--text-secondary); font-size: 0.85em;"
|
|
31864
|
+
>
|
|
31865
|
+
(by: ${meta4.modifiedBy})
|
|
31866
|
+
</td>` : ""}
|
|
31867
|
+
</tr>
|
|
31868
|
+
` : ""}
|
|
31869
|
+
</tbody>
|
|
31870
|
+
</table>
|
|
31871
|
+
|
|
31872
|
+
${meta4.modifications && Array.isArray(meta4.modifications) && meta4.modifications.length > 0 ? b2`
|
|
31873
|
+
<div style="margin-top: var(--space-md);">
|
|
31874
|
+
<div
|
|
31875
|
+
style="font-weight: 500; margin-bottom: var(--space-sm); color: var(--text-secondary);"
|
|
31876
|
+
>
|
|
31877
|
+
Changes
|
|
31878
|
+
</div>
|
|
31879
|
+
<ul style="list-style: none; padding: 0; margin: 0;">
|
|
31880
|
+
${meta4.modifications.map(
|
|
31881
|
+
(mod, idx) => b2`
|
|
31882
|
+
<li
|
|
31883
|
+
key="${idx}"
|
|
31884
|
+
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;"
|
|
31885
|
+
>
|
|
31886
|
+
<div style="margin-bottom: 2px;">
|
|
31887
|
+
<span style="font-weight: 500; color: var(--text-primary);"
|
|
31888
|
+
>${mod.field}</span
|
|
31889
|
+
>
|
|
31890
|
+
<span style="color: var(--text-secondary); margin: 0 var(--space-xs);"
|
|
31891
|
+
>→</span
|
|
31892
|
+
>
|
|
31893
|
+
<span style="color: var(--text-secondary); font-size: 0.85em;"
|
|
31894
|
+
>${formatTime(mod.timestamp || (/* @__PURE__ */ new Date()).toISOString())}</span
|
|
31895
|
+
>
|
|
31896
|
+
</div>
|
|
31897
|
+
<div
|
|
31898
|
+
style="font-family: monospace; font-size: 0.85em; color: var(--text-secondary); margin-left: var(--space-sm);"
|
|
31899
|
+
>
|
|
31900
|
+
<span style="color: #d87070;">${JSON.stringify(mod.oldValue)}</span>
|
|
31901
|
+
<span style="margin: 0 4px;">→</span>
|
|
31902
|
+
<span style="color: #7cb342;">${JSON.stringify(mod.newValue)}</span>
|
|
31903
|
+
</div>
|
|
31904
|
+
${mod.modifiedBy ? b2`<div
|
|
31905
|
+
style="font-size: 0.8em; color: var(--text-secondary); margin-top: 2px;"
|
|
31906
|
+
>
|
|
31907
|
+
<em>by: ${mod.modifiedBy}</em>
|
|
31908
|
+
</div>` : ""}
|
|
31909
|
+
</li>
|
|
31910
|
+
`
|
|
31911
|
+
)}
|
|
31912
|
+
</ul>
|
|
31913
|
+
</div>
|
|
31914
|
+
` : ""}
|
|
31915
|
+
</div>
|
|
31916
|
+
</details>
|
|
31917
|
+
</div>
|
|
29719
31918
|
`;
|
|
29720
31919
|
}
|
|
29721
31920
|
/** Returns true for arrays of objects or large nested objects that deserve their own section */
|
|
@@ -30174,6 +32373,163 @@ ${code}</pre>`;
|
|
|
30174
32373
|
style="position: relative; background: ${bgColor}; border-radius: var(--radius-sm); padding: 16px; margin: 16px 0; min-height: 120px;"
|
|
30175
32374
|
></div>`;
|
|
30176
32375
|
}
|
|
32376
|
+
_renderQR(data) {
|
|
32377
|
+
const text = typeof data === "object" && data !== null ? String(data.url || data.link || data.value || JSON.stringify(data)) : String(data);
|
|
32378
|
+
const isUrl = /^https?:\/\//i.test(text);
|
|
32379
|
+
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(text);
|
|
32380
|
+
const isPhone = /^[+]?[\d\s\-().]{7,}$/.test(text.trim());
|
|
32381
|
+
let href = "";
|
|
32382
|
+
let linkLabel = text;
|
|
32383
|
+
if (isUrl) {
|
|
32384
|
+
href = text;
|
|
32385
|
+
try {
|
|
32386
|
+
linkLabel = new URL(text).hostname + new URL(text).pathname;
|
|
32387
|
+
} catch {
|
|
32388
|
+
}
|
|
32389
|
+
} else if (isEmail) {
|
|
32390
|
+
href = `mailto:${text}`;
|
|
32391
|
+
} else if (isPhone) {
|
|
32392
|
+
href = `tel:${text.replace(/[\s\-().]/g, "")}`;
|
|
32393
|
+
}
|
|
32394
|
+
setTimeout(() => {
|
|
32395
|
+
if (this._qrContainer) {
|
|
32396
|
+
this._qrContainer.innerHTML = "";
|
|
32397
|
+
try {
|
|
32398
|
+
const containerWidth = this._qrContainer.clientWidth;
|
|
32399
|
+
const qrSize = Math.max(200, Math.min(containerWidth - 48, 400));
|
|
32400
|
+
new window.QRCode(this._qrContainer, {
|
|
32401
|
+
text,
|
|
32402
|
+
width: qrSize,
|
|
32403
|
+
height: qrSize,
|
|
32404
|
+
correctLevel: window.QRCode?.CorrectLevel?.H,
|
|
32405
|
+
colorDark: "#000000",
|
|
32406
|
+
colorLight: "#ffffff"
|
|
32407
|
+
});
|
|
32408
|
+
} catch (error2) {
|
|
32409
|
+
console.error("Failed to generate QR code:", error2);
|
|
32410
|
+
}
|
|
32411
|
+
}
|
|
32412
|
+
}, 0);
|
|
32413
|
+
const message = typeof data === "object" && data !== null ? data.message : void 0;
|
|
32414
|
+
const extraFields = [];
|
|
32415
|
+
if (typeof data === "object" && data !== null) {
|
|
32416
|
+
for (const [k3, v2] of Object.entries(data)) {
|
|
32417
|
+
if (["url", "link", "value", "message", "port"].includes(k3) || v2 == null || typeof v2 === "object")
|
|
32418
|
+
continue;
|
|
32419
|
+
extraFields.push({ label: k3, value: `${v2}` });
|
|
32420
|
+
}
|
|
32421
|
+
}
|
|
32422
|
+
return b2`<div
|
|
32423
|
+
style="
|
|
32424
|
+
display: flex; flex-direction: column; align-items: center; gap: 0;
|
|
32425
|
+
padding: 0; border-radius: var(--radius-md);
|
|
32426
|
+
border: 1px solid var(--border-glass);
|
|
32427
|
+
background: var(--bg-subtle); overflow: hidden;
|
|
32428
|
+
width: 40%; min-width: 280px; max-width: 480px;
|
|
32429
|
+
margin: 16px auto;
|
|
32430
|
+
"
|
|
32431
|
+
>
|
|
32432
|
+
<div
|
|
32433
|
+
id="qr-container"
|
|
32434
|
+
style="
|
|
32435
|
+
width: 100%; padding: 24px;
|
|
32436
|
+
display: flex; justify-content: center; align-items: center;
|
|
32437
|
+
background: #ffffff; border-radius: var(--radius-md) var(--radius-md) 0 0;
|
|
32438
|
+
"
|
|
32439
|
+
></div>
|
|
32440
|
+
|
|
32441
|
+
<div
|
|
32442
|
+
style="
|
|
32443
|
+
width: 100%; padding: 16px 20px;
|
|
32444
|
+
display: flex; flex-direction: column; gap: 10px;
|
|
32445
|
+
border-top: 1px solid var(--border-glass);
|
|
32446
|
+
"
|
|
32447
|
+
>
|
|
32448
|
+
${message ? b2`<div
|
|
32449
|
+
style="
|
|
32450
|
+
font-size: 0.8rem; color: var(--t-secondary, #a0a0a0);
|
|
32451
|
+
text-align: center; font-weight: 500;
|
|
32452
|
+
"
|
|
32453
|
+
>
|
|
32454
|
+
${message}
|
|
32455
|
+
</div>` : ""}
|
|
32456
|
+
${href ? b2`<div
|
|
32457
|
+
style="display: flex; align-items: center; gap: 10px; justify-content: center;"
|
|
32458
|
+
>
|
|
32459
|
+
<a
|
|
32460
|
+
href="${href}"
|
|
32461
|
+
target="_blank"
|
|
32462
|
+
rel="noopener noreferrer"
|
|
32463
|
+
style="
|
|
32464
|
+
font-size: 0.85rem; color: var(--accent, #3b82f6);
|
|
32465
|
+
text-decoration: none; font-weight: 500;
|
|
32466
|
+
text-align: center; word-break: break-word;
|
|
32467
|
+
"
|
|
32468
|
+
@mouseenter=${(e8) => e8.target.style.textDecoration = "underline"}
|
|
32469
|
+
@mouseleave=${(e8) => e8.target.style.textDecoration = "none"}
|
|
32470
|
+
>${linkLabel}</a
|
|
32471
|
+
>
|
|
32472
|
+
<button
|
|
32473
|
+
title="Copy to clipboard"
|
|
32474
|
+
style="
|
|
32475
|
+
background: var(--bg-subtle, rgba(255,255,255,0.06));
|
|
32476
|
+
border: 1px solid var(--border-glass);
|
|
32477
|
+
border-radius: 6px; padding: 6px 10px; cursor: pointer;
|
|
32478
|
+
color: var(--t-muted); font-size: 0.85rem; flex-shrink: 0;
|
|
32479
|
+
transition: all 0.15s; line-height: 1;
|
|
32480
|
+
"
|
|
32481
|
+
@mouseenter=${(e8) => {
|
|
32482
|
+
e8.target.style.color = "var(--accent, #3b82f6)";
|
|
32483
|
+
e8.target.style.borderColor = "var(--accent, #3b82f6)";
|
|
32484
|
+
}}
|
|
32485
|
+
@mouseleave=${(e8) => {
|
|
32486
|
+
e8.target.style.color = "var(--t-muted)";
|
|
32487
|
+
e8.target.style.borderColor = "var(--border-glass)";
|
|
32488
|
+
}}
|
|
32489
|
+
@click=${(e8) => {
|
|
32490
|
+
void navigator.clipboard.writeText(text);
|
|
32491
|
+
const btn = e8.target;
|
|
32492
|
+
const orig = btn.textContent;
|
|
32493
|
+
btn.textContent = "\u2713 Copied";
|
|
32494
|
+
btn.style.color = "var(--accent, #3b82f6)";
|
|
32495
|
+
setTimeout(() => {
|
|
32496
|
+
btn.textContent = orig;
|
|
32497
|
+
btn.style.color = "var(--t-muted)";
|
|
32498
|
+
}, 1500);
|
|
32499
|
+
}}
|
|
32500
|
+
>
|
|
32501
|
+
Copy
|
|
32502
|
+
</button>
|
|
32503
|
+
</div>` : b2`<div
|
|
32504
|
+
style="
|
|
32505
|
+
font-size: 0.875rem; color: var(--t-muted);
|
|
32506
|
+
text-align: center; word-break: break-all;
|
|
32507
|
+
"
|
|
32508
|
+
>
|
|
32509
|
+
${text}
|
|
32510
|
+
</div>`}
|
|
32511
|
+
${extraFields.length > 0 ? b2`<div
|
|
32512
|
+
style="
|
|
32513
|
+
display: flex; flex-direction: column; gap: 6px;
|
|
32514
|
+
padding-top: 10px; border-top: 1px solid var(--border-glass);
|
|
32515
|
+
font-size: 0.8rem;
|
|
32516
|
+
"
|
|
32517
|
+
>
|
|
32518
|
+
${extraFields.map(
|
|
32519
|
+
(f5) => b2`<div style="display: flex; justify-content: space-between; gap: 12px;">
|
|
32520
|
+
<span style="color: var(--t-muted); text-transform: capitalize;"
|
|
32521
|
+
>${f5.label}</span
|
|
32522
|
+
>
|
|
32523
|
+
<span
|
|
32524
|
+
style="color: var(--t-primary); font-family: var(--font-mono, monospace); word-break: break-all; text-align: right;"
|
|
32525
|
+
>${f5.value}</span
|
|
32526
|
+
>
|
|
32527
|
+
</div>`
|
|
32528
|
+
)}
|
|
32529
|
+
</div>` : ""}
|
|
32530
|
+
</div>
|
|
32531
|
+
</div>`;
|
|
32532
|
+
}
|
|
30177
32533
|
_renderText(data) {
|
|
30178
32534
|
const text = String(data);
|
|
30179
32535
|
if (this._isMermaidString(text)) {
|
|
@@ -31433,7 +33789,7 @@ ResultViewer.styles = [
|
|
|
31433
33789
|
}
|
|
31434
33790
|
|
|
31435
33791
|
button:hover {
|
|
31436
|
-
background:
|
|
33792
|
+
background: var(--bg-glass);
|
|
31437
33793
|
color: var(--t-primary);
|
|
31438
33794
|
}
|
|
31439
33795
|
|
|
@@ -31584,7 +33940,7 @@ ResultViewer.styles = [
|
|
|
31584
33940
|
}
|
|
31585
33941
|
|
|
31586
33942
|
.smart-table tr:hover td {
|
|
31587
|
-
background:
|
|
33943
|
+
background: var(--bg-glass);
|
|
31588
33944
|
}
|
|
31589
33945
|
|
|
31590
33946
|
/* Key-Value Table (single object) */
|
|
@@ -32271,7 +34627,7 @@ ResultViewer.styles = [
|
|
|
32271
34627
|
}
|
|
32272
34628
|
|
|
32273
34629
|
.tree-item:hover {
|
|
32274
|
-
background:
|
|
34630
|
+
background: var(--bg-glass);
|
|
32275
34631
|
}
|
|
32276
34632
|
|
|
32277
34633
|
.tree-toggle {
|
|
@@ -32300,16 +34656,16 @@ ResultViewer.styles = [
|
|
|
32300
34656
|
}
|
|
32301
34657
|
|
|
32302
34658
|
.tree-value.string {
|
|
32303
|
-
color:
|
|
34659
|
+
color: var(--syntax-string);
|
|
32304
34660
|
}
|
|
32305
34661
|
.tree-value.number {
|
|
32306
|
-
color:
|
|
34662
|
+
color: var(--syntax-number);
|
|
32307
34663
|
}
|
|
32308
34664
|
.tree-value.boolean {
|
|
32309
|
-
color:
|
|
34665
|
+
color: var(--syntax-boolean);
|
|
32310
34666
|
}
|
|
32311
34667
|
.tree-value.null {
|
|
32312
|
-
color:
|
|
34668
|
+
color: var(--syntax-null);
|
|
32313
34669
|
}
|
|
32314
34670
|
|
|
32315
34671
|
.tree-type {
|
|
@@ -32571,9 +34927,9 @@ ResultViewer.styles = [
|
|
|
32571
34927
|
}
|
|
32572
34928
|
|
|
32573
34929
|
.expand-btn:hover {
|
|
32574
|
-
background: var(--primary);
|
|
34930
|
+
background: var(--accent-primary);
|
|
32575
34931
|
color: white;
|
|
32576
|
-
border-color: var(--primary);
|
|
34932
|
+
border-color: var(--accent-primary);
|
|
32577
34933
|
}
|
|
32578
34934
|
|
|
32579
34935
|
/* Markdown items (array rendering with filter transitions) */
|
|
@@ -32811,13 +35167,13 @@ ResultViewer.styles = [
|
|
|
32811
35167
|
}
|
|
32812
35168
|
|
|
32813
35169
|
.metric-delta.up {
|
|
32814
|
-
color:
|
|
32815
|
-
background:
|
|
35170
|
+
color: var(--color-success);
|
|
35171
|
+
background: var(--color-success-bg);
|
|
32816
35172
|
}
|
|
32817
35173
|
|
|
32818
35174
|
.metric-delta.down {
|
|
32819
|
-
color:
|
|
32820
|
-
background:
|
|
35175
|
+
color: var(--color-error);
|
|
35176
|
+
background: var(--color-error-bg);
|
|
32821
35177
|
}
|
|
32822
35178
|
|
|
32823
35179
|
.metric-delta.neutral {
|
|
@@ -32952,7 +35308,7 @@ ResultViewer.styles = [
|
|
|
32952
35308
|
|
|
32953
35309
|
.timeline-description {
|
|
32954
35310
|
font-size: var(--text-md);
|
|
32955
|
-
color: var(--t-
|
|
35311
|
+
color: var(--t-muted);
|
|
32956
35312
|
margin-top: 2px;
|
|
32957
35313
|
line-height: 1.4;
|
|
32958
35314
|
}
|
|
@@ -33099,7 +35455,7 @@ ResultViewer.styles = [
|
|
|
33099
35455
|
justify-content: space-between;
|
|
33100
35456
|
padding: 4px 0;
|
|
33101
35457
|
font-size: var(--text-md);
|
|
33102
|
-
color: var(--t-
|
|
35458
|
+
color: var(--t-muted);
|
|
33103
35459
|
}
|
|
33104
35460
|
|
|
33105
35461
|
.cart-summary-row.total {
|
|
@@ -33377,6 +35733,9 @@ __decorateClass([
|
|
|
33377
35733
|
__decorateClass([
|
|
33378
35734
|
r5()
|
|
33379
35735
|
], ResultViewer.prototype, "_internalResult", 2);
|
|
35736
|
+
__decorateClass([
|
|
35737
|
+
e7("#qr-container")
|
|
35738
|
+
], ResultViewer.prototype, "_qrContainer", 2);
|
|
33380
35739
|
__decorateClass([
|
|
33381
35740
|
n4({ type: String })
|
|
33382
35741
|
], ResultViewer.prototype, "collectionProperty", 2);
|
|
@@ -83446,9 +85805,13 @@ var ElicitationModal = class extends i4 {
|
|
|
83446
85805
|
min="${min}"
|
|
83447
85806
|
max="${max}"
|
|
83448
85807
|
step="${step}"
|
|
85808
|
+
style="${this._sliderFillStyle(Number(currentValue), min, max)}"
|
|
83449
85809
|
.value=${String(currentValue)}
|
|
83450
85810
|
@input=${(e8) => {
|
|
83451
|
-
|
|
85811
|
+
const el2 = e8.target;
|
|
85812
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step);
|
|
85813
|
+
el2.style.cssText = this._sliderFillStyle(v2, min, max);
|
|
85814
|
+
this._inputValue = v2;
|
|
83452
85815
|
}}
|
|
83453
85816
|
/>
|
|
83454
85817
|
<input
|
|
@@ -83459,7 +85822,15 @@ var ElicitationModal = class extends i4 {
|
|
|
83459
85822
|
step="${step}"
|
|
83460
85823
|
.value=${String(currentValue)}
|
|
83461
85824
|
@input=${(e8) => {
|
|
83462
|
-
|
|
85825
|
+
const raw = e8.target.value;
|
|
85826
|
+
if (raw === "" || raw === "-") return;
|
|
85827
|
+
this._inputValue = Number(raw);
|
|
85828
|
+
}}
|
|
85829
|
+
@change=${(e8) => {
|
|
85830
|
+
const el2 = e8.target;
|
|
85831
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step);
|
|
85832
|
+
el2.value = String(v2);
|
|
85833
|
+
this._inputValue = v2;
|
|
83463
85834
|
}}
|
|
83464
85835
|
@keydown=${(e8) => this._handleKeydown(e8)}
|
|
83465
85836
|
autofocus
|
|
@@ -83703,9 +86074,13 @@ var ElicitationModal = class extends i4 {
|
|
|
83703
86074
|
min="${min}"
|
|
83704
86075
|
max="${max}"
|
|
83705
86076
|
step="${step}"
|
|
86077
|
+
style="${this._sliderFillStyle(Number(currentValue), min, max)}"
|
|
83706
86078
|
.value=${String(currentValue)}
|
|
83707
86079
|
@input=${(e8) => {
|
|
83708
|
-
|
|
86080
|
+
const el2 = e8.target;
|
|
86081
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step);
|
|
86082
|
+
el2.style.cssText = this._sliderFillStyle(v2, min, max);
|
|
86083
|
+
this._updateFormValue(field.name, v2);
|
|
83709
86084
|
}}
|
|
83710
86085
|
/>
|
|
83711
86086
|
<input
|
|
@@ -83716,7 +86091,15 @@ var ElicitationModal = class extends i4 {
|
|
|
83716
86091
|
step="${step}"
|
|
83717
86092
|
.value=${String(currentValue)}
|
|
83718
86093
|
@input=${(e8) => {
|
|
83719
|
-
|
|
86094
|
+
const raw = e8.target.value;
|
|
86095
|
+
if (raw === "" || raw === "-") return;
|
|
86096
|
+
this._updateFormValue(field.name, Number(raw));
|
|
86097
|
+
}}
|
|
86098
|
+
@change=${(e8) => {
|
|
86099
|
+
const el2 = e8.target;
|
|
86100
|
+
const v2 = this._sanitizeSliderValue(Number(el2.value), min, max, step);
|
|
86101
|
+
el2.value = String(v2);
|
|
86102
|
+
this._updateFormValue(field.name, v2);
|
|
83720
86103
|
}}
|
|
83721
86104
|
/>
|
|
83722
86105
|
</div>
|
|
@@ -83737,6 +86120,23 @@ var ElicitationModal = class extends i4 {
|
|
|
83737
86120
|
/>
|
|
83738
86121
|
`;
|
|
83739
86122
|
}
|
|
86123
|
+
_sliderFillStyle(value, min, max) {
|
|
86124
|
+
const pct = max > min ? (value - min) / (max - min) * 100 : 0;
|
|
86125
|
+
return `background: linear-gradient(to right, var(--accent-primary) ${pct}%, var(--border-glass) ${pct}%)`;
|
|
86126
|
+
}
|
|
86127
|
+
/** Clamp to [min, max] and round to nearest step (integer-safe). */
|
|
86128
|
+
_sanitizeSliderValue(raw, min, max, step) {
|
|
86129
|
+
let v2 = Number.isFinite(raw) ? raw : min;
|
|
86130
|
+
v2 = Math.min(max, Math.max(min, v2));
|
|
86131
|
+
if (step > 0) {
|
|
86132
|
+
v2 = min + Math.round((v2 - min) / step) * step;
|
|
86133
|
+
if (v2 > max) v2 = max;
|
|
86134
|
+
}
|
|
86135
|
+
if (Number.isInteger(step) && step >= 1) {
|
|
86136
|
+
v2 = Math.round(v2);
|
|
86137
|
+
}
|
|
86138
|
+
return v2;
|
|
86139
|
+
}
|
|
83740
86140
|
_updateFormValue(name2, value) {
|
|
83741
86141
|
this._formValues = { ...this._formValues, [name2]: value };
|
|
83742
86142
|
}
|
|
@@ -83861,11 +86261,19 @@ ElicitationModal.styles = [
|
|
|
83861
86261
|
color: white;
|
|
83862
86262
|
}
|
|
83863
86263
|
|
|
86264
|
+
.btn-success:hover {
|
|
86265
|
+
filter: brightness(1.1);
|
|
86266
|
+
}
|
|
86267
|
+
|
|
83864
86268
|
.btn-danger {
|
|
83865
86269
|
background: var(--color-error);
|
|
83866
86270
|
color: white;
|
|
83867
86271
|
}
|
|
83868
86272
|
|
|
86273
|
+
.btn-danger:hover {
|
|
86274
|
+
filter: brightness(1.1);
|
|
86275
|
+
}
|
|
86276
|
+
|
|
83869
86277
|
/* Confirm buttons */
|
|
83870
86278
|
.confirm-actions {
|
|
83871
86279
|
display: flex;
|
|
@@ -83975,7 +86383,7 @@ ElicitationModal.styles = [
|
|
|
83975
86383
|
.slider-group {
|
|
83976
86384
|
display: flex;
|
|
83977
86385
|
flex-direction: column;
|
|
83978
|
-
gap:
|
|
86386
|
+
gap: 4px;
|
|
83979
86387
|
}
|
|
83980
86388
|
|
|
83981
86389
|
.slider-row {
|
|
@@ -83986,47 +86394,104 @@ ElicitationModal.styles = [
|
|
|
83986
86394
|
|
|
83987
86395
|
.slider-row input[type='range'] {
|
|
83988
86396
|
flex: 1;
|
|
83989
|
-
height:
|
|
83990
|
-
|
|
83991
|
-
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
83992
|
-
border-radius: 3px;
|
|
86397
|
+
height: 4px;
|
|
86398
|
+
border-radius: var(--radius-full, 9999px);
|
|
83993
86399
|
-webkit-appearance: none;
|
|
83994
86400
|
cursor: pointer;
|
|
83995
86401
|
margin: 8px 0;
|
|
86402
|
+
border: none;
|
|
86403
|
+
outline: none;
|
|
86404
|
+
background: var(--border-glass);
|
|
83996
86405
|
}
|
|
83997
86406
|
|
|
83998
86407
|
.slider-row input[type='range']::-webkit-slider-thumb {
|
|
83999
86408
|
-webkit-appearance: none;
|
|
84000
|
-
width:
|
|
84001
|
-
height:
|
|
86409
|
+
width: 16px;
|
|
86410
|
+
height: 16px;
|
|
84002
86411
|
background: var(--accent-primary);
|
|
86412
|
+
border: 2px solid var(--bg-panel, var(--bg-glass));
|
|
84003
86413
|
border-radius: 50%;
|
|
84004
86414
|
cursor: pointer;
|
|
84005
|
-
box-shadow:
|
|
86415
|
+
box-shadow:
|
|
86416
|
+
0 0 0 2px var(--accent-primary),
|
|
86417
|
+
0 1px 4px rgba(0, 0, 0, 0.3);
|
|
86418
|
+
transition:
|
|
86419
|
+
box-shadow 0.15s ease,
|
|
86420
|
+
transform 0.15s ease;
|
|
86421
|
+
}
|
|
86422
|
+
|
|
86423
|
+
.slider-row input[type='range']::-webkit-slider-thumb:hover {
|
|
86424
|
+
box-shadow:
|
|
86425
|
+
0 0 0 3px var(--accent-primary),
|
|
86426
|
+
0 0 8px var(--glow-primary);
|
|
86427
|
+
transform: scale(1.1);
|
|
86428
|
+
}
|
|
86429
|
+
|
|
86430
|
+
.slider-row input[type='range']:active::-webkit-slider-thumb {
|
|
86431
|
+
transform: scale(0.95);
|
|
84006
86432
|
}
|
|
84007
86433
|
|
|
84008
86434
|
.slider-row input[type='range']::-moz-range-track {
|
|
84009
|
-
height:
|
|
84010
|
-
background:
|
|
84011
|
-
border-radius:
|
|
84012
|
-
border:
|
|
86435
|
+
height: 4px;
|
|
86436
|
+
background: var(--border-glass);
|
|
86437
|
+
border-radius: var(--radius-full, 9999px);
|
|
86438
|
+
border: none;
|
|
86439
|
+
}
|
|
86440
|
+
|
|
86441
|
+
.slider-row input[type='range']::-moz-range-progress {
|
|
86442
|
+
height: 4px;
|
|
86443
|
+
background: var(--accent-primary);
|
|
86444
|
+
border-radius: var(--radius-full, 9999px);
|
|
84013
86445
|
}
|
|
84014
86446
|
|
|
84015
86447
|
.slider-row input[type='range']::-moz-range-thumb {
|
|
84016
|
-
width:
|
|
84017
|
-
height:
|
|
86448
|
+
width: 12px;
|
|
86449
|
+
height: 12px;
|
|
84018
86450
|
background: var(--accent-primary);
|
|
86451
|
+
border: 2px solid var(--bg-panel, var(--bg-glass));
|
|
84019
86452
|
border-radius: 50%;
|
|
84020
86453
|
cursor: pointer;
|
|
84021
|
-
|
|
84022
|
-
|
|
86454
|
+
box-shadow:
|
|
86455
|
+
0 0 0 2px var(--accent-primary),
|
|
86456
|
+
0 1px 4px rgba(0, 0, 0, 0.3);
|
|
86457
|
+
transition:
|
|
86458
|
+
box-shadow 0.15s ease,
|
|
86459
|
+
transform 0.15s ease;
|
|
86460
|
+
}
|
|
86461
|
+
|
|
86462
|
+
.slider-row input[type='range']::-moz-range-thumb:hover {
|
|
86463
|
+
box-shadow:
|
|
86464
|
+
0 0 0 3px var(--accent-primary),
|
|
86465
|
+
0 0 8px var(--glow-primary);
|
|
84023
86466
|
}
|
|
84024
86467
|
|
|
84025
86468
|
.slider-number-input {
|
|
84026
|
-
width:
|
|
84027
|
-
text-align:
|
|
86469
|
+
width: 64px;
|
|
86470
|
+
text-align: center;
|
|
84028
86471
|
font-size: var(--text-sm);
|
|
84029
|
-
|
|
86472
|
+
font-weight: 500;
|
|
86473
|
+
font-variant-numeric: tabular-nums;
|
|
86474
|
+
padding: 4px 6px;
|
|
86475
|
+
background: var(--bg-glass);
|
|
86476
|
+
border: 1px solid var(--border-glass) !important;
|
|
86477
|
+
border-radius: var(--radius-sm);
|
|
86478
|
+
color: var(--t-primary);
|
|
86479
|
+
-moz-appearance: textfield;
|
|
86480
|
+
transition:
|
|
86481
|
+
border-color 0.15s ease,
|
|
86482
|
+
box-shadow 0.15s ease;
|
|
86483
|
+
}
|
|
86484
|
+
|
|
86485
|
+
.slider-number-input::-webkit-outer-spin-button,
|
|
86486
|
+
.slider-number-input::-webkit-inner-spin-button {
|
|
86487
|
+
-webkit-appearance: none;
|
|
86488
|
+
margin: 0;
|
|
86489
|
+
}
|
|
86490
|
+
|
|
86491
|
+
.slider-number-input:focus-visible {
|
|
86492
|
+
outline: none;
|
|
86493
|
+
border-color: var(--accent-primary) !important;
|
|
86494
|
+
box-shadow: 0 0 0 2px var(--glow-primary);
|
|
84030
86495
|
}
|
|
84031
86496
|
|
|
84032
86497
|
.range-labels {
|
|
@@ -84085,7 +86550,13 @@ ElicitationModal.styles = [
|
|
|
84085
86550
|
background: var(--bg-glass-strong);
|
|
84086
86551
|
border-radius: 12px;
|
|
84087
86552
|
cursor: pointer;
|
|
84088
|
-
transition:
|
|
86553
|
+
transition:
|
|
86554
|
+
background 0.2s,
|
|
86555
|
+
box-shadow 0.2s;
|
|
86556
|
+
}
|
|
86557
|
+
|
|
86558
|
+
.toggle-track:hover {
|
|
86559
|
+
background: var(--bg-glass);
|
|
84089
86560
|
}
|
|
84090
86561
|
|
|
84091
86562
|
.toggle-track::after {
|
|
@@ -84104,6 +86575,14 @@ ElicitationModal.styles = [
|
|
|
84104
86575
|
background: var(--accent-primary);
|
|
84105
86576
|
}
|
|
84106
86577
|
|
|
86578
|
+
.toggle-switch input:checked + .toggle-track:hover {
|
|
86579
|
+
background: var(--accent-secondary);
|
|
86580
|
+
}
|
|
86581
|
+
|
|
86582
|
+
.toggle-switch input:focus-visible + .toggle-track {
|
|
86583
|
+
box-shadow: 0 0 0 2px var(--glow-primary);
|
|
86584
|
+
}
|
|
86585
|
+
|
|
84107
86586
|
.toggle-switch input:checked + .toggle-track::after {
|
|
84108
86587
|
transform: translateX(20px);
|
|
84109
86588
|
}
|
|
@@ -84239,7 +86718,7 @@ var OverflowMenu = class extends i4 {
|
|
|
84239
86718
|
return b2`
|
|
84240
86719
|
<button
|
|
84241
86720
|
class="trigger"
|
|
84242
|
-
@click=${() => this._toggle()}
|
|
86721
|
+
@click=${(e8) => this._toggle(e8)}
|
|
84243
86722
|
title="More actions"
|
|
84244
86723
|
aria-label="More actions"
|
|
84245
86724
|
>
|
|
@@ -84519,7 +86998,7 @@ var InstancePanel = class extends i4 {
|
|
|
84519
86998
|
return b2`
|
|
84520
86999
|
<button
|
|
84521
87000
|
class="instance-pill"
|
|
84522
|
-
@click=${() => this._toggle()}
|
|
87001
|
+
@click=${(e8) => this._toggle(e8)}
|
|
84523
87002
|
title="Instances are separate data containers — like multiple accounts in the same app. Click to switch."
|
|
84524
87003
|
aria-label="Current instance: ${display}"
|
|
84525
87004
|
aria-haspopup="true"
|
|
@@ -85746,7 +88225,7 @@ ContextBar.styles = [
|
|
|
85746
88225
|
backdrop-filter: blur(20px);
|
|
85747
88226
|
border: 1px solid var(--border-glass);
|
|
85748
88227
|
border-radius: var(--radius-md);
|
|
85749
|
-
box-shadow:
|
|
88228
|
+
box-shadow: var(--shadow-lg);
|
|
85750
88229
|
padding: 4px;
|
|
85751
88230
|
z-index: 100;
|
|
85752
88231
|
}
|
|
@@ -85757,7 +88236,7 @@ ContextBar.styles = [
|
|
|
85757
88236
|
padding: 6px 10px;
|
|
85758
88237
|
border: none;
|
|
85759
88238
|
background: none;
|
|
85760
|
-
color: var(--t-
|
|
88239
|
+
color: var(--t-muted);
|
|
85761
88240
|
font-size: var(--text-sm);
|
|
85762
88241
|
font-family: inherit;
|
|
85763
88242
|
text-align: left;
|
|
@@ -85783,7 +88262,7 @@ ContextBar.styles = [
|
|
|
85783
88262
|
font-size: var(--text-2xs);
|
|
85784
88263
|
font-weight: 700;
|
|
85785
88264
|
letter-spacing: 0.08em;
|
|
85786
|
-
color:
|
|
88265
|
+
color: var(--color-success);
|
|
85787
88266
|
text-transform: uppercase;
|
|
85788
88267
|
margin-left: auto;
|
|
85789
88268
|
}
|
|
@@ -85792,8 +88271,8 @@ ContextBar.styles = [
|
|
|
85792
88271
|
width: 6px;
|
|
85793
88272
|
height: 6px;
|
|
85794
88273
|
border-radius: 50%;
|
|
85795
|
-
background:
|
|
85796
|
-
box-shadow: 0 0 6px 2px
|
|
88274
|
+
background: var(--color-success);
|
|
88275
|
+
box-shadow: 0 0 6px 2px var(--color-success-glow);
|
|
85797
88276
|
animation: live-pulse 2s ease-in-out infinite;
|
|
85798
88277
|
}
|
|
85799
88278
|
|
|
@@ -85801,11 +88280,11 @@ ContextBar.styles = [
|
|
|
85801
88280
|
0%,
|
|
85802
88281
|
100% {
|
|
85803
88282
|
opacity: 1;
|
|
85804
|
-
box-shadow: 0 0 6px 2px
|
|
88283
|
+
box-shadow: 0 0 6px 2px var(--color-success-glow);
|
|
85805
88284
|
}
|
|
85806
88285
|
50% {
|
|
85807
88286
|
opacity: 0.5;
|
|
85808
|
-
box-shadow: 0 0 3px 1px
|
|
88287
|
+
box-shadow: 0 0 3px 1px var(--color-success-glow);
|
|
85809
88288
|
}
|
|
85810
88289
|
}
|
|
85811
88290
|
|