@elaraai/e3-ui-components 1.0.79 → 1.0.81
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 +1 -1
- package/dist/components/DatasetPreview.d.ts +10 -2
- package/dist/components/DatasetPreview.d.ts.map +1 -1
- package/dist/components/EastValueViewer.d.ts.map +1 -1
- package/dist/components/PagedDatasetPreview.d.ts +15 -1
- package/dist/components/PagedDatasetPreview.d.ts.map +1 -1
- package/dist/components/TaskPreview.d.ts.map +1 -1
- package/dist/components/UITaskPreview.d.ts +7 -3
- package/dist/components/UITaskPreview.d.ts.map +1 -1
- package/dist/decision/constraint-format.d.ts +15 -7
- package/dist/decision/constraint-format.d.ts.map +1 -1
- package/dist/decision/contract.d.ts +28 -0
- package/dist/decision/contract.d.ts.map +1 -0
- package/dist/decision/facets.d.ts +21 -3
- package/dist/decision/facets.d.ts.map +1 -1
- package/dist/decision/grouping.d.ts +11 -0
- package/dist/decision/grouping.d.ts.map +1 -1
- package/dist/decision/handle-runtime.d.ts.map +1 -1
- package/dist/decision/journal.d.ts.map +1 -1
- package/dist/decision/lever-editor.d.ts +11 -18
- package/dist/decision/lever-editor.d.ts.map +1 -1
- package/dist/decision/queue.d.ts.map +1 -1
- package/dist/diff/format.d.ts +20 -12
- package/dist/diff/format.d.ts.map +1 -1
- package/dist/diff/index.d.ts.map +1 -1
- package/dist/diff/manual.d.ts +37 -18
- package/dist/diff/manual.d.ts.map +1 -1
- package/dist/diff/walker.d.ts +14 -6
- package/dist/diff/walker.d.ts.map +1 -1
- package/dist/experiment/charts.d.ts +4 -1
- package/dist/experiment/charts.d.ts.map +1 -1
- package/dist/experiment/derive.d.ts +25 -5
- package/dist/experiment/derive.d.ts.map +1 -1
- package/dist/experiment/index.d.ts.map +1 -1
- package/dist/experiment/run-runtime.d.ts +4 -8
- package/dist/experiment/run-runtime.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/useDatasetValue.d.ts +13 -2
- package/dist/hooks/useDatasetValue.d.ts.map +1 -1
- package/dist/hooks/useTaskDetails.d.ts +1 -5
- package/dist/hooks/useTaskDetails.d.ts.map +1 -1
- package/dist/hooks/workspaces.d.ts +16 -3
- package/dist/hooks/workspaces.d.ts.map +1 -1
- package/dist/index.cjs +1361 -1028
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1385 -1052
- package/dist/index.js.map +1 -1
- package/dist/platform/bind-runtime.d.ts +14 -5
- package/dist/platform/bind-runtime.d.ts.map +1 -1
- package/dist/platform/dataset-hooks.d.ts +12 -4
- package/dist/platform/dataset-hooks.d.ts.map +1 -1
- package/dist/platform/dataset-store.d.ts +47 -11
- package/dist/platform/dataset-store.d.ts.map +1 -1
- package/dist/platform/func-runtime.d.ts +16 -6
- package/dist/platform/func-runtime.d.ts.map +1 -1
- package/dist/platform/index.d.ts +1 -1
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/paged-runtime.d.ts +183 -49
- package/dist/platform/paged-runtime.d.ts.map +1 -1
- package/dist/platform/record-runtime.d.ts +14 -4
- package/dist/platform/record-runtime.d.ts.map +1 -1
- package/dist/platform/staged-store.d.ts +19 -2
- package/dist/platform/staged-store.d.ts.map +1 -1
- package/package.json +16 -15
package/dist/index.cjs
CHANGED
|
@@ -2077,6 +2077,7 @@ const realClock = {
|
|
|
2077
2077
|
return { clear: () => clearInterval(id3) };
|
|
2078
2078
|
}
|
|
2079
2079
|
};
|
|
2080
|
+
const HASH_POLL_MS = 1e3;
|
|
2080
2081
|
function createDefaultDatasetApi(apiUrl, repo, getToken) {
|
|
2081
2082
|
const opts = () => ({ token: getToken() });
|
|
2082
2083
|
return {
|
|
@@ -2142,12 +2143,17 @@ class ReactiveDatasetCache {
|
|
|
2142
2143
|
__publicField(this, "keyVersions", /* @__PURE__ */ new Map());
|
|
2143
2144
|
// Workspace status polling — groups subscriptions by workspace for
|
|
2144
2145
|
// efficiency. Each entry holds the active interval handle from the
|
|
2145
|
-
// injected {@link Clock} so tests can drive ticking deterministically
|
|
2146
|
+
// injected {@link Clock} so tests can drive ticking deterministically,
|
|
2147
|
+
// and each polled path with how many watchers poll it.
|
|
2146
2148
|
__publicField(this, "workspacePollers", /* @__PURE__ */ new Map());
|
|
2147
2149
|
__publicField(this, "clock");
|
|
2148
2150
|
// In-flight poll dedup — concurrent callers (interval tick + a
|
|
2149
2151
|
// post-write trigger) share a single round-trip rather than racing.
|
|
2150
2152
|
__publicField(this, "inFlightPolls", /* @__PURE__ */ new Map());
|
|
2153
|
+
// Hash-only watches, by workspace and path: each callback with the hash it
|
|
2154
|
+
// was last told. A watched path rides its workspace's poll, but its
|
|
2155
|
+
// content is never fetched — a paged source reads windows, never the value.
|
|
2156
|
+
__publicField(this, "hashWatches", /* @__PURE__ */ new Map());
|
|
2151
2157
|
// Batching
|
|
2152
2158
|
__publicField(this, "batchDepth", 0);
|
|
2153
2159
|
__publicField(this, "changedKeys", /* @__PURE__ */ new Set());
|
|
@@ -2236,9 +2242,7 @@ class ReactiveDatasetCache {
|
|
|
2236
2242
|
hash: void 0,
|
|
2237
2243
|
status: east.variant("stale", null)
|
|
2238
2244
|
});
|
|
2239
|
-
|
|
2240
|
-
void this.pollWorkspaceStatus(workspace);
|
|
2241
|
-
}
|
|
2245
|
+
void this.refresh(workspace);
|
|
2242
2246
|
} catch (error3) {
|
|
2243
2247
|
if (!this.destroyed && this.writeEpochs.get(key) === myEpoch) {
|
|
2244
2248
|
const baseline = this.writeBaselines.get(key);
|
|
@@ -2344,15 +2348,15 @@ class ReactiveDatasetCache {
|
|
|
2344
2348
|
* 3. Only fetches full content when hash changes
|
|
2345
2349
|
*
|
|
2346
2350
|
* Multiple subscriptions to the same workspace share a single poller.
|
|
2347
|
-
* Pair with {@link clearRefetchInterval} on unmount so the
|
|
2348
|
-
* stop when nothing is watching.
|
|
2351
|
+
* Pair each call with one {@link clearRefetchInterval} on unmount so the
|
|
2352
|
+
* poller can stop when nothing is watching.
|
|
2349
2353
|
*/
|
|
2350
2354
|
setRefetchInterval(workspace, path2, intervalMs) {
|
|
2351
2355
|
var _a2;
|
|
2352
2356
|
const pathStr = datasetPathToString(path2);
|
|
2353
2357
|
let poller = this.workspacePollers.get(workspace);
|
|
2354
2358
|
if (poller) {
|
|
2355
|
-
poller.paths.
|
|
2359
|
+
poller.paths.set(pathStr, (poller.paths.get(pathStr) ?? 0) + 1);
|
|
2356
2360
|
if (intervalMs < poller.intervalMs) {
|
|
2357
2361
|
(_a2 = poller.handle) == null ? void 0 : _a2.clear();
|
|
2358
2362
|
poller.intervalMs = intervalMs;
|
|
@@ -2364,7 +2368,7 @@ class ReactiveDatasetCache {
|
|
|
2364
2368
|
} else {
|
|
2365
2369
|
poller = {
|
|
2366
2370
|
intervalMs,
|
|
2367
|
-
paths: /* @__PURE__ */ new
|
|
2371
|
+
paths: /* @__PURE__ */ new Map([[pathStr, 1]]),
|
|
2368
2372
|
handle: this.clock.setInterval(
|
|
2369
2373
|
() => this.pollWorkspaceStatus(workspace),
|
|
2370
2374
|
intervalMs
|
|
@@ -2375,23 +2379,79 @@ class ReactiveDatasetCache {
|
|
|
2375
2379
|
}
|
|
2376
2380
|
}
|
|
2377
2381
|
/**
|
|
2378
|
-
* Stop polling a dataset
|
|
2379
|
-
*
|
|
2382
|
+
* Stop polling a dataset for one watcher; the path goes when its last
|
|
2383
|
+
* watcher clears it, and the workspace poller is torn down when its last
|
|
2384
|
+
* path goes.
|
|
2380
2385
|
*/
|
|
2381
2386
|
clearRefetchInterval(workspace, path2) {
|
|
2382
|
-
var _a2;
|
|
2383
2387
|
const poller = this.workspacePollers.get(workspace);
|
|
2384
2388
|
if (!poller) return;
|
|
2385
|
-
|
|
2386
|
-
|
|
2389
|
+
const pathStr = datasetPathToString(path2);
|
|
2390
|
+
const watchers = (poller.paths.get(pathStr) ?? 0) - 1;
|
|
2391
|
+
if (watchers > 0) {
|
|
2392
|
+
poller.paths.set(pathStr, watchers);
|
|
2393
|
+
return;
|
|
2394
|
+
}
|
|
2395
|
+
poller.paths.delete(pathStr);
|
|
2396
|
+
this.stopIdlePoller(workspace);
|
|
2397
|
+
}
|
|
2398
|
+
/**
|
|
2399
|
+
* Follow a dataset's content hash without fetching its content; see the
|
|
2400
|
+
* interface doc.
|
|
2401
|
+
*/
|
|
2402
|
+
watchHash(workspace, path2, onHash, intervalMs = HASH_POLL_MS) {
|
|
2403
|
+
var _a2;
|
|
2404
|
+
const pathStr = datasetPathToString(path2);
|
|
2405
|
+
let byPath = this.hashWatches.get(workspace);
|
|
2406
|
+
if (!byPath) {
|
|
2407
|
+
byPath = /* @__PURE__ */ new Map();
|
|
2408
|
+
this.hashWatches.set(workspace, byPath);
|
|
2409
|
+
}
|
|
2410
|
+
let callbacks = byPath.get(pathStr);
|
|
2411
|
+
if (!callbacks) {
|
|
2412
|
+
callbacks = /* @__PURE__ */ new Map();
|
|
2413
|
+
byPath.set(pathStr, callbacks);
|
|
2414
|
+
}
|
|
2415
|
+
callbacks.set(onHash, void 0);
|
|
2416
|
+
const poller = this.workspacePollers.get(workspace);
|
|
2417
|
+
if (!poller) {
|
|
2418
|
+
this.workspacePollers.set(workspace, {
|
|
2419
|
+
intervalMs,
|
|
2420
|
+
paths: /* @__PURE__ */ new Map(),
|
|
2421
|
+
handle: this.clock.setInterval(() => this.pollWorkspaceStatus(workspace), intervalMs)
|
|
2422
|
+
});
|
|
2423
|
+
void this.pollWorkspaceStatus(workspace);
|
|
2424
|
+
} else if (intervalMs < poller.intervalMs) {
|
|
2387
2425
|
(_a2 = poller.handle) == null ? void 0 : _a2.clear();
|
|
2388
|
-
|
|
2426
|
+
poller.intervalMs = intervalMs;
|
|
2427
|
+
poller.handle = this.clock.setInterval(() => this.pollWorkspaceStatus(workspace), intervalMs);
|
|
2389
2428
|
}
|
|
2429
|
+
return () => {
|
|
2430
|
+
const watched = this.hashWatches.get(workspace);
|
|
2431
|
+
const set3 = watched == null ? void 0 : watched.get(pathStr);
|
|
2432
|
+
if (!watched || !set3) return;
|
|
2433
|
+
set3.delete(onHash);
|
|
2434
|
+
if (set3.size === 0) watched.delete(pathStr);
|
|
2435
|
+
if (watched.size === 0) this.hashWatches.delete(workspace);
|
|
2436
|
+
this.stopIdlePoller(workspace);
|
|
2437
|
+
};
|
|
2438
|
+
}
|
|
2439
|
+
/** Stops a workspace's poller once it has no path to reconcile and no hash
|
|
2440
|
+
* to follow — without this, a long-lived session polls forever. */
|
|
2441
|
+
stopIdlePoller(workspace) {
|
|
2442
|
+
var _a2;
|
|
2443
|
+
const poller = this.workspacePollers.get(workspace);
|
|
2444
|
+
if (!poller || poller.paths.size > 0 || this.hashWatches.has(workspace)) return;
|
|
2445
|
+
(_a2 = poller.handle) == null ? void 0 : _a2.clear();
|
|
2446
|
+
this.workspacePollers.delete(workspace);
|
|
2390
2447
|
}
|
|
2391
2448
|
refresh(workspace) {
|
|
2392
2449
|
if (this.destroyed) return Promise.resolve();
|
|
2393
2450
|
if (!this.workspacePollers.has(workspace)) return Promise.resolve();
|
|
2394
|
-
|
|
2451
|
+
const inFlight = this.inFlightPolls.get(workspace);
|
|
2452
|
+
if (inFlight === void 0) return this.pollWorkspaceStatus(workspace);
|
|
2453
|
+
const again = () => this.destroyed || !this.workspacePollers.has(workspace) ? void 0 : this.pollWorkspaceStatus(workspace);
|
|
2454
|
+
return inFlight.then(again, again);
|
|
2395
2455
|
}
|
|
2396
2456
|
/**
|
|
2397
2457
|
* Poll workspace status and reconcile the cache with the server.
|
|
@@ -2407,11 +2467,12 @@ class ReactiveDatasetCache {
|
|
|
2407
2467
|
return promise4;
|
|
2408
2468
|
}
|
|
2409
2469
|
async doPollWorkspaceStatus(workspace) {
|
|
2470
|
+
var _a2;
|
|
2410
2471
|
if (this.destroyed) return;
|
|
2411
2472
|
const poller = this.workspacePollers.get(workspace);
|
|
2412
|
-
if (!poller || poller.paths.size === 0) return;
|
|
2473
|
+
if (!poller || poller.paths.size === 0 && !this.hashWatches.has(workspace)) return;
|
|
2413
2474
|
const epochsAtStart = /* @__PURE__ */ new Map();
|
|
2414
|
-
for (const pathStr of poller.paths) {
|
|
2475
|
+
for (const pathStr of poller.paths.keys()) {
|
|
2415
2476
|
const key = pathStr ? `${workspace}.${pathStr}` : workspace;
|
|
2416
2477
|
epochsAtStart.set(key, this.writeEpochs.get(key) ?? 0);
|
|
2417
2478
|
}
|
|
@@ -2425,15 +2486,28 @@ class ReactiveDatasetCache {
|
|
|
2425
2486
|
if (this.destroyed) return;
|
|
2426
2487
|
const infoByPath = /* @__PURE__ */ new Map();
|
|
2427
2488
|
for (const info of status.datasets) infoByPath.set(info.path, info);
|
|
2489
|
+
for (const [pathStr, callbacks] of this.hashWatches.get(workspace) ?? []) {
|
|
2490
|
+
const info = infoByPath.get(pathStr ? `.${pathStr}` : "");
|
|
2491
|
+
const hash2 = ((_a2 = info == null ? void 0 : info.hash) == null ? void 0 : _a2.type) === "some" ? info.hash.value : null;
|
|
2492
|
+
for (const [onHash, told] of [...callbacks]) {
|
|
2493
|
+
if (told === hash2 || !callbacks.has(onHash)) continue;
|
|
2494
|
+
callbacks.set(onHash, hash2);
|
|
2495
|
+
try {
|
|
2496
|
+
onHash(hash2);
|
|
2497
|
+
} catch (error3) {
|
|
2498
|
+
console.error(`A hash watch on ${workspace}.${pathStr} failed:`, error3);
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2428
2502
|
const pending = [];
|
|
2429
2503
|
this.batch(() => {
|
|
2430
|
-
var
|
|
2431
|
-
for (const pathStr of poller.paths) {
|
|
2504
|
+
var _a3;
|
|
2505
|
+
for (const pathStr of poller.paths.keys()) {
|
|
2432
2506
|
const e3Path = pathStr ? `.${pathStr}` : "";
|
|
2433
2507
|
const info = infoByPath.get(e3Path);
|
|
2434
2508
|
const key = pathStr ? `${workspace}.${pathStr}` : workspace;
|
|
2435
2509
|
const path2 = this.stringToPath(pathStr);
|
|
2436
|
-
const currentHash = ((
|
|
2510
|
+
const currentHash = ((_a3 = info == null ? void 0 : info.hash) == null ? void 0 : _a3.type) === "some" ? info.hash.value : null;
|
|
2437
2511
|
const knownHash = this.knownHashes.get(key);
|
|
2438
2512
|
if (info == null ? void 0 : info.status) {
|
|
2439
2513
|
const previous = this.statuses.get(key);
|
|
@@ -2599,6 +2673,7 @@ class ReactiveDatasetCache {
|
|
|
2599
2673
|
}
|
|
2600
2674
|
this.workspacePollers.clear();
|
|
2601
2675
|
this.inFlightPolls.clear();
|
|
2676
|
+
this.hashWatches.clear();
|
|
2602
2677
|
this.keySubscribers.clear();
|
|
2603
2678
|
this.globalSubscribers.clear();
|
|
2604
2679
|
this.knownHashes.clear();
|
|
@@ -2713,9 +2788,16 @@ class MemoryStagedAdapter {
|
|
|
2713
2788
|
this.map.clear();
|
|
2714
2789
|
}
|
|
2715
2790
|
}
|
|
2791
|
+
const SCOPE_SEPARATOR = "\0";
|
|
2792
|
+
function cacheKeyOf(key) {
|
|
2793
|
+
return key.slice(key.indexOf(SCOPE_SEPARATOR) + 1);
|
|
2794
|
+
}
|
|
2716
2795
|
class StagedStore {
|
|
2717
2796
|
constructor(adapter) {
|
|
2797
|
+
// By scope and `datasetCacheKey`; subscribers and versions go by the
|
|
2798
|
+
// `datasetCacheKey` alone, which is what a reactive view tracks.
|
|
2718
2799
|
__publicField(this, "entries", /* @__PURE__ */ new Map());
|
|
2800
|
+
__publicField(this, "scope", null);
|
|
2719
2801
|
__publicField(this, "subscribers", /* @__PURE__ */ new Map());
|
|
2720
2802
|
__publicField(this, "versions", /* @__PURE__ */ new Map());
|
|
2721
2803
|
__publicField(this, "adapter");
|
|
@@ -2739,25 +2821,25 @@ class StagedStore {
|
|
|
2739
2821
|
}
|
|
2740
2822
|
}
|
|
2741
2823
|
hasPending(workspace, path2) {
|
|
2742
|
-
return this.entries.has(
|
|
2824
|
+
return this.entries.has(this.keyOf(workspace, path2));
|
|
2743
2825
|
}
|
|
2744
2826
|
getBuffered(workspace, path2) {
|
|
2745
2827
|
var _a2;
|
|
2746
|
-
return (_a2 = this.entries.get(
|
|
2828
|
+
return (_a2 = this.entries.get(this.keyOf(workspace, path2))) == null ? void 0 : _a2.buffered;
|
|
2747
2829
|
}
|
|
2748
2830
|
getSnapshot(workspace, path2) {
|
|
2749
2831
|
var _a2;
|
|
2750
|
-
return (_a2 = this.entries.get(
|
|
2832
|
+
return (_a2 = this.entries.get(this.keyOf(workspace, path2))) == null ? void 0 : _a2.snapshot;
|
|
2751
2833
|
}
|
|
2752
2834
|
getEntry(workspace, path2) {
|
|
2753
|
-
return this.entries.get(
|
|
2835
|
+
return this.entries.get(this.keyOf(workspace, path2));
|
|
2754
2836
|
}
|
|
2755
2837
|
write(workspace, path2, snapshotIfNew, buffered) {
|
|
2756
|
-
const key =
|
|
2838
|
+
const key = this.keyOf(workspace, path2);
|
|
2757
2839
|
const existing = this.entries.get(key);
|
|
2758
2840
|
const next2 = existing ? { snapshot: existing.snapshot, buffered } : { snapshot: snapshotIfNew, buffered };
|
|
2759
2841
|
this.entries.set(key, next2);
|
|
2760
|
-
this.notify(
|
|
2842
|
+
this.notify(datasetCacheKey(workspace, path2));
|
|
2761
2843
|
const persisted = {
|
|
2762
2844
|
snapshot: next2.snapshot,
|
|
2763
2845
|
buffered: next2.buffered
|
|
@@ -2765,15 +2847,26 @@ class StagedStore {
|
|
|
2765
2847
|
this.persist(key, () => this.adapter.save(key, persisted));
|
|
2766
2848
|
}
|
|
2767
2849
|
discard(workspace, path2) {
|
|
2768
|
-
const key =
|
|
2850
|
+
const key = this.keyOf(workspace, path2);
|
|
2769
2851
|
if (!this.entries.has(key)) return false;
|
|
2770
2852
|
this.entries.delete(key);
|
|
2771
|
-
this.notify(
|
|
2853
|
+
this.notify(datasetCacheKey(workspace, path2));
|
|
2772
2854
|
this.persist(key, () => this.adapter.remove(key));
|
|
2773
2855
|
return true;
|
|
2774
2856
|
}
|
|
2775
2857
|
listKeys() {
|
|
2776
|
-
|
|
2858
|
+
const prefix2 = `${this.scope ?? ""}${SCOPE_SEPARATOR}`;
|
|
2859
|
+
return [...this.entries.keys()].filter((key) => key.startsWith(prefix2)).map(cacheKeyOf);
|
|
2860
|
+
}
|
|
2861
|
+
setScope(scope) {
|
|
2862
|
+
const before = this.scope;
|
|
2863
|
+
this.scope = scope;
|
|
2864
|
+
this.notifyScopes(before, scope);
|
|
2865
|
+
return () => {
|
|
2866
|
+
if (this.scope !== scope) return;
|
|
2867
|
+
this.scope = null;
|
|
2868
|
+
this.notifyScopes(scope, null);
|
|
2869
|
+
};
|
|
2777
2870
|
}
|
|
2778
2871
|
subscribe(key, callback) {
|
|
2779
2872
|
let set3 = this.subscribers.get(key);
|
|
@@ -2796,15 +2889,29 @@ class StagedStore {
|
|
|
2796
2889
|
this.errorListeners.delete(cb);
|
|
2797
2890
|
};
|
|
2798
2891
|
}
|
|
2799
|
-
/** Test-only: clear in-memory + persisted state. */
|
|
2892
|
+
/** Test-only: clear in-memory + persisted state, in every scope. */
|
|
2800
2893
|
async clear() {
|
|
2801
2894
|
const keys = [...this.entries.keys()];
|
|
2802
2895
|
this.entries.clear();
|
|
2803
|
-
for (const key of keys) this.notify(key);
|
|
2896
|
+
for (const key of new Set(keys.map(cacheKeyOf))) this.notify(key);
|
|
2804
2897
|
await this.flushPending();
|
|
2805
2898
|
await this.adapter.clear();
|
|
2806
2899
|
}
|
|
2807
2900
|
// ----- internals -------------------------------------------------------
|
|
2901
|
+
/** The key a path's entry is held under in the current scope. */
|
|
2902
|
+
keyOf(workspace, path2) {
|
|
2903
|
+
return `${this.scope ?? ""}${SCOPE_SEPARATOR}${datasetCacheKey(workspace, path2)}`;
|
|
2904
|
+
}
|
|
2905
|
+
/** Tells every path with an entry in either scope that what it reads has
|
|
2906
|
+
* changed: the scope's move shows one's entries and hides the other's. */
|
|
2907
|
+
notifyScopes(from2, to) {
|
|
2908
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2909
|
+
for (const key of this.entries.keys()) {
|
|
2910
|
+
const scope = key.slice(0, key.indexOf(SCOPE_SEPARATOR));
|
|
2911
|
+
if (scope === (from2 ?? "") || scope === (to ?? "")) keys.add(cacheKeyOf(key));
|
|
2912
|
+
}
|
|
2913
|
+
for (const key of keys) this.notify(key);
|
|
2914
|
+
}
|
|
2808
2915
|
notify(key) {
|
|
2809
2916
|
this.versions.set(key, (this.versions.get(key) ?? 0) + 1);
|
|
2810
2917
|
const subs = this.subscribers.get(key);
|
|
@@ -2821,7 +2928,7 @@ class StagedStore {
|
|
|
2821
2928
|
const settled = prev2.then(op, op).then(
|
|
2822
2929
|
() => void 0,
|
|
2823
2930
|
(err) => {
|
|
2824
|
-
this.emitPersistError(key, err);
|
|
2931
|
+
this.emitPersistError(cacheKeyOf(key), err);
|
|
2825
2932
|
}
|
|
2826
2933
|
).then(() => {
|
|
2827
2934
|
if (this.saveChains.get(key) === settled) this.saveChains.delete(key);
|
|
@@ -2852,11 +2959,18 @@ class StagedStore {
|
|
|
2852
2959
|
return;
|
|
2853
2960
|
}
|
|
2854
2961
|
for (const [key, p2] of persisted) {
|
|
2962
|
+
if (!key.includes(SCOPE_SEPARATOR)) {
|
|
2963
|
+
this.persist(key, () => this.adapter.remove(key));
|
|
2964
|
+
this.emitPersistError(key, new Error(
|
|
2965
|
+
`a staged edit of ${key} that an older build left names no server or repository, and was dropped`
|
|
2966
|
+
));
|
|
2967
|
+
continue;
|
|
2968
|
+
}
|
|
2855
2969
|
this.entries.set(key, {
|
|
2856
2970
|
snapshot: p2.snapshot,
|
|
2857
2971
|
buffered: p2.buffered
|
|
2858
2972
|
});
|
|
2859
|
-
this.notify(key);
|
|
2973
|
+
this.notify(cacheKeyOf(key));
|
|
2860
2974
|
}
|
|
2861
2975
|
}
|
|
2862
2976
|
}
|
|
@@ -2884,7 +2998,7 @@ function clearStagedStoreSingleton() {
|
|
|
2884
2998
|
}
|
|
2885
2999
|
const UNCHANGED_VARIANT = east.variant("unchanged", null);
|
|
2886
3000
|
const blobEqual = east.equalFor(east.BlobType);
|
|
2887
|
-
const eastTypeEqual$
|
|
3001
|
+
const eastTypeEqual$1 = east.equalFor(internal.EastTypeType);
|
|
2888
3002
|
const helpersCache = new east.SortedMap(
|
|
2889
3003
|
void 0,
|
|
2890
3004
|
east.compareFor(internal.EastTypeType)
|
|
@@ -2973,8 +3087,14 @@ class BindRuntime {
|
|
|
2973
3087
|
}
|
|
2974
3088
|
this.cache = cache3;
|
|
2975
3089
|
}
|
|
2976
|
-
/**
|
|
2977
|
-
|
|
3090
|
+
/**
|
|
3091
|
+
* Clear the active cache and drop any queued writes.
|
|
3092
|
+
*
|
|
3093
|
+
* @param cache - Clear only while this is the active cache, so a provider
|
|
3094
|
+
* tearing down after another installed its own leaves that one in place
|
|
3095
|
+
*/
|
|
3096
|
+
clearCache(cache3) {
|
|
3097
|
+
if (cache3 !== void 0 && this.cache !== cache3) return;
|
|
2978
3098
|
this.cache = null;
|
|
2979
3099
|
this.clearPendingWrites();
|
|
2980
3100
|
this.handleCache.clear();
|
|
@@ -3087,11 +3207,11 @@ class BindRuntime {
|
|
|
3087
3207
|
const key = datasetCacheKey(workspace, sourcePath);
|
|
3088
3208
|
const existing = this.bindingRegistry.get(key);
|
|
3089
3209
|
if (existing) {
|
|
3090
|
-
if (existing.mode === info.mode && existing.hasPatchDataset === info.hasPatchDataset && existing.sourceType
|
|
3210
|
+
if (existing.mode === info.mode && existing.hasPatchDataset === info.hasPatchDataset && Object.is(existing.sourceType, info.sourceType)) {
|
|
3091
3211
|
return;
|
|
3092
3212
|
}
|
|
3093
3213
|
const shapeChanged = existing.mode !== info.mode || existing.hasPatchDataset !== info.hasPatchDataset;
|
|
3094
|
-
const typeChanged = !eastTypeEqual$
|
|
3214
|
+
const typeChanged = !eastTypeEqual$1(existing.sourceType, info.sourceType);
|
|
3095
3215
|
if (!shapeChanged && !typeChanged) {
|
|
3096
3216
|
this.bindingRegistry.set(key, info);
|
|
3097
3217
|
return;
|
|
@@ -3281,7 +3401,7 @@ class BindRuntime {
|
|
|
3281
3401
|
};
|
|
3282
3402
|
const bindingDescriptor = {
|
|
3283
3403
|
source: sourcePath,
|
|
3284
|
-
patch: patchPath ? east.
|
|
3404
|
+
patch: patchPath ? east.some(patchPath) : east.none,
|
|
3285
3405
|
mode: east.variant(mode, null)
|
|
3286
3406
|
};
|
|
3287
3407
|
const writeStaged = (value) => {
|
|
@@ -3299,6 +3419,10 @@ class BindRuntime {
|
|
|
3299
3419
|
this.queueWrite(() => cache3.launchDataflow(ws));
|
|
3300
3420
|
return null;
|
|
3301
3421
|
};
|
|
3422
|
+
const hasSource = () => {
|
|
3423
|
+
this.trackPath(ws, sourcePath);
|
|
3424
|
+
return cache3.has(ws, sourcePath);
|
|
3425
|
+
};
|
|
3302
3426
|
if (mode === "direct" && !patchPath) {
|
|
3303
3427
|
return {
|
|
3304
3428
|
read: () => {
|
|
@@ -3321,7 +3445,7 @@ class BindRuntime {
|
|
|
3321
3445
|
pending: () => false,
|
|
3322
3446
|
commit: () => null,
|
|
3323
3447
|
discard: () => null,
|
|
3324
|
-
has:
|
|
3448
|
+
has: hasSource,
|
|
3325
3449
|
status: () => {
|
|
3326
3450
|
this.trackPath(ws, sourcePath);
|
|
3327
3451
|
return cache3.getStatus(ws, sourcePath);
|
|
@@ -3370,7 +3494,7 @@ class BindRuntime {
|
|
|
3370
3494
|
this.queueWrite(() => cache3.write(ws, pPath2, encodePatch(UNCHANGED_VARIANT)));
|
|
3371
3495
|
return null;
|
|
3372
3496
|
},
|
|
3373
|
-
has:
|
|
3497
|
+
has: hasSource,
|
|
3374
3498
|
status: () => {
|
|
3375
3499
|
this.trackPath(ws, sourcePath);
|
|
3376
3500
|
return cache3.getStatus(ws, sourcePath);
|
|
@@ -3414,7 +3538,7 @@ class BindRuntime {
|
|
|
3414
3538
|
staged.discard(ws, sourcePath);
|
|
3415
3539
|
return null;
|
|
3416
3540
|
},
|
|
3417
|
-
has:
|
|
3541
|
+
has: hasSource,
|
|
3418
3542
|
status: () => {
|
|
3419
3543
|
this.trackPath(ws, sourcePath);
|
|
3420
3544
|
return cache3.getStatus(ws, sourcePath);
|
|
@@ -3461,7 +3585,7 @@ class BindRuntime {
|
|
|
3461
3585
|
staged.discard(ws, sourcePath);
|
|
3462
3586
|
return null;
|
|
3463
3587
|
},
|
|
3464
|
-
has:
|
|
3588
|
+
has: hasSource,
|
|
3465
3589
|
status: () => {
|
|
3466
3590
|
this.trackPath(ws, sourcePath);
|
|
3467
3591
|
return cache3.getStatus(ws, sourcePath);
|
|
@@ -3519,8 +3643,8 @@ function getReactiveDatasetCache() {
|
|
|
3519
3643
|
function initializeReactiveDatasetCache(cache3) {
|
|
3520
3644
|
defaultBindRuntime.initializeCache(cache3);
|
|
3521
3645
|
}
|
|
3522
|
-
function clearReactiveDatasetCache() {
|
|
3523
|
-
defaultBindRuntime.clearCache();
|
|
3646
|
+
function clearReactiveDatasetCache(cache3) {
|
|
3647
|
+
defaultBindRuntime.clearCache(cache3);
|
|
3524
3648
|
}
|
|
3525
3649
|
function enableBindingTracking() {
|
|
3526
3650
|
return defaultBindRuntime.enableTracking();
|
|
@@ -3700,7 +3824,11 @@ class TrackedChannelStore {
|
|
|
3700
3824
|
this.keyVersions.clear();
|
|
3701
3825
|
}
|
|
3702
3826
|
}
|
|
3703
|
-
|
|
3827
|
+
const NO_INDEX = { index: null, join: false };
|
|
3828
|
+
function selectorKey(selector2) {
|
|
3829
|
+
return selector2.index === null ? "" : `@${selector2.index}${selector2.join ? "+join" : ""}`;
|
|
3830
|
+
}
|
|
3831
|
+
function createDefaultPagedApi(apiUrl, repo, getToken, datasets) {
|
|
3704
3832
|
const opts = () => ({ token: getToken() });
|
|
3705
3833
|
return {
|
|
3706
3834
|
async getPage(workspace, path2, window3) {
|
|
@@ -3708,58 +3836,115 @@ function createDefaultPagedApi(apiUrl, repo, getToken) {
|
|
|
3708
3836
|
},
|
|
3709
3837
|
async findKey(workspace, path2, query) {
|
|
3710
3838
|
return e3ApiClient.datasetFindKey(apiUrl, repo, workspace, path2, query, opts());
|
|
3839
|
+
},
|
|
3840
|
+
async getRevision(workspace, path2) {
|
|
3841
|
+
const status = await e3ApiClient.datasetGetStatus(apiUrl, repo, workspace, path2, opts());
|
|
3842
|
+
return status.hash.type === "some" ? status.hash.value : null;
|
|
3843
|
+
},
|
|
3844
|
+
watchRevision(workspace, path2, onChange2) {
|
|
3845
|
+
return datasets.watchHash(workspace, path2, onChange2);
|
|
3711
3846
|
}
|
|
3712
3847
|
};
|
|
3713
3848
|
}
|
|
3714
3849
|
const RETRY_AFTER_MS = 2e3;
|
|
3715
3850
|
const MAX_RETAINED_WINDOWS = 24;
|
|
3716
|
-
const PERMANENT_PAGE_ERRORS = /* @__PURE__ */ new Set([
|
|
3717
|
-
|
|
3851
|
+
const PERMANENT_PAGE_ERRORS = /* @__PURE__ */ new Set([
|
|
3852
|
+
"bad_request",
|
|
3853
|
+
"dataset_not_canonical",
|
|
3854
|
+
"dataset_not_indexed",
|
|
3855
|
+
"dataset_not_pageable",
|
|
3856
|
+
"dataset_not_searchable",
|
|
3857
|
+
"dataset_not_segmented",
|
|
3858
|
+
"index_not_found",
|
|
3859
|
+
"key_parse_error"
|
|
3860
|
+
]);
|
|
3861
|
+
const NO_VALUE_ERRORS = /* @__PURE__ */ new Set(["dataset_unassigned", "dataset_null"]);
|
|
3862
|
+
function toSelector(indexArg, joinArg) {
|
|
3863
|
+
const index2 = indexArg;
|
|
3864
|
+
return {
|
|
3865
|
+
index: index2 !== void 0 && index2.type === "some" ? index2.value : null,
|
|
3866
|
+
join: joinArg === true
|
|
3867
|
+
};
|
|
3868
|
+
}
|
|
3869
|
+
function checkDeclared(allowed, path2) {
|
|
3870
|
+
if (allowed === null) return;
|
|
3871
|
+
const pathStr = datasetPathToString(path2);
|
|
3872
|
+
if (!allowed.has(pathStr)) {
|
|
3873
|
+
throw new Error(
|
|
3874
|
+
`Data.bindPaged: source path "${pathStr}" not declared in manifest — bind it in the task body so derivation records it`
|
|
3875
|
+
);
|
|
3876
|
+
}
|
|
3877
|
+
}
|
|
3878
|
+
function errorCode(err) {
|
|
3718
3879
|
const code = err == null ? void 0 : err.code;
|
|
3719
|
-
return typeof code === "string"
|
|
3880
|
+
return typeof code === "string" ? code : void 0;
|
|
3881
|
+
}
|
|
3882
|
+
function isPermanentPageError(err) {
|
|
3883
|
+
const code = errorCode(err);
|
|
3884
|
+
return code !== void 0 && PERMANENT_PAGE_ERRORS.has(code);
|
|
3885
|
+
}
|
|
3886
|
+
function failureOf(path2, err) {
|
|
3887
|
+
const code = errorCode(err);
|
|
3888
|
+
const details = err == null ? void 0 : err.details;
|
|
3889
|
+
const reason = code === void 0 ? err instanceof Error ? err.message : String(err) : typeof details === "string" && details !== "" ? `${code}: ${details}` : code;
|
|
3890
|
+
return `Data.bindPaged: ${datasetPathToString(path2)}: ${reason}`;
|
|
3720
3891
|
}
|
|
3721
3892
|
function keyTypeOf(sourceType) {
|
|
3722
3893
|
if (sourceType.type === "Dict") return sourceType.value.key;
|
|
3723
3894
|
if (sourceType.type === "Set") return sourceType.value;
|
|
3724
3895
|
return null;
|
|
3725
3896
|
}
|
|
3726
|
-
function buildSeek(sourceType, T2, pathExpr, platform2) {
|
|
3727
|
-
if (keyTypeOf(sourceType) === null) return east.none;
|
|
3897
|
+
function buildSeek(sourceType, T2, pathExpr, indexExpr, joinExpr, selector2, platform2) {
|
|
3898
|
+
if (selector2.index === null && keyTypeOf(sourceType) === null) return east.none;
|
|
3728
3899
|
const { seek } = internal$1.DataPagedPrimitives;
|
|
3729
3900
|
return east.some(east.East.compile(
|
|
3730
3901
|
east.East.function([eastUi.SeekQueryType], east.OptionType(eastUi.SeekRangeType), ($3, query) => {
|
|
3731
|
-
$3.return(seek([T2], pathExpr, query));
|
|
3902
|
+
$3.return(seek([T2], pathExpr, indexExpr, joinExpr, query));
|
|
3732
3903
|
}),
|
|
3733
3904
|
platform2
|
|
3734
3905
|
));
|
|
3735
3906
|
}
|
|
3736
|
-
function
|
|
3737
|
-
return `paged:${workspace}:${datasetPathToString(path2)}
|
|
3907
|
+
function pagedRevisionKey(workspace, path2) {
|
|
3908
|
+
return `paged:${workspace}:${datasetPathToString(path2)}#revision`;
|
|
3909
|
+
}
|
|
3910
|
+
function pagedWindowKey(workspace, path2, revision, offset, limit2, selector2 = NO_INDEX) {
|
|
3911
|
+
return `paged:${workspace}:${datasetPathToString(path2)}${selectorKey(selector2)}@${revision}#${offset}+${limit2}`;
|
|
3738
3912
|
}
|
|
3739
|
-
function pagedTotalKey(workspace, path2) {
|
|
3740
|
-
return `paged:${workspace}:${datasetPathToString(path2)}#total`;
|
|
3913
|
+
function pagedTotalKey(workspace, path2, revision, selector2 = NO_INDEX) {
|
|
3914
|
+
return `paged:${workspace}:${datasetPathToString(path2)}${selectorKey(selector2)}@${revision}#total`;
|
|
3741
3915
|
}
|
|
3742
|
-
function pagedSeekKey(workspace, path2, query) {
|
|
3743
|
-
const q = "key" in query ? `k=${query.key}` : "fields" in query ? `f=${query.fields.join("\0")}|p=${query.prefix ?? ""}` : `p=${query.prefix}`;
|
|
3744
|
-
return `paged:${workspace}:${datasetPathToString(path2)}#seek:${q}`;
|
|
3916
|
+
function pagedSeekKey(workspace, path2, revision, query, selector2 = NO_INDEX) {
|
|
3917
|
+
const q = "key" in query ? `k=${query.key}` : "fields" in query ? `f=${query.fields.join("\0")}|p=${query.prefix ?? ""}` : "prefix" in query ? `p=${query.prefix}` : `r=${(query.from ?? []).join("\0")}|${(query.to ?? []).join("\0")}`;
|
|
3918
|
+
return `paged:${workspace}:${datasetPathToString(path2)}${selectorKey(selector2)}@${revision}#seek:${q}`;
|
|
3745
3919
|
}
|
|
3746
|
-
function toFindQuery(query) {
|
|
3920
|
+
function toFindQuery(query, selector2 = NO_INDEX) {
|
|
3747
3921
|
const q = query;
|
|
3748
|
-
|
|
3749
|
-
if (q.type === "
|
|
3922
|
+
const scope = selector2.index === null ? {} : { index: selector2.index };
|
|
3923
|
+
if (q.type === "key") return { key: q.value, ...scope };
|
|
3924
|
+
if (q.type === "prefix") return { prefix: q.value, ...scope };
|
|
3925
|
+
if (q.type === "range") {
|
|
3926
|
+
const r2 = q.value;
|
|
3927
|
+
const from2 = [...r2.from];
|
|
3928
|
+
const to = [...r2.to];
|
|
3929
|
+
if (from2.length === 0 && to.length === 0) {
|
|
3930
|
+
throw new Error("Data.bindPaged: a range seek names no end — give it a `from`, a `to`, or both");
|
|
3931
|
+
}
|
|
3932
|
+
return from2.length === 0 ? { to, ...scope } : to.length === 0 ? { from: from2, ...scope } : { from: from2, to, ...scope };
|
|
3933
|
+
}
|
|
3750
3934
|
const f2 = q.value;
|
|
3751
3935
|
const fields = [...f2.values];
|
|
3752
|
-
return f2.prefix.type === "some" ? { fields, prefix: f2.prefix.value } : { fields };
|
|
3936
|
+
return f2.prefix.type === "some" ? { fields, prefix: f2.prefix.value, ...scope } : { fields, ...scope };
|
|
3753
3937
|
}
|
|
3754
3938
|
class PagedRuntime extends TrackedChannelStore {
|
|
3755
3939
|
constructor() {
|
|
3756
3940
|
super(...arguments);
|
|
3757
3941
|
__publicField(this, "api", null);
|
|
3758
3942
|
__publicField(this, "workspace", null);
|
|
3759
|
-
// Compiled-handle cache (issue #106 perf): buildHandle compiles
|
|
3943
|
+
// Compiled-handle cache (issue #106 perf): buildHandle compiles several
|
|
3760
3944
|
// East.functions per bind, and binds re-run every reactive frame. The
|
|
3761
|
-
// method IR is a pure function of (sourceType,
|
|
3762
|
-
// resolve api/workspace LIVE, so a cached handle still
|
|
3945
|
+
// method IR is a pure function of (sourceType, path, selector, shape), and
|
|
3946
|
+
// the methods resolve api/workspace LIVE, so a cached handle still
|
|
3947
|
+
// re-binds.
|
|
3763
3948
|
//
|
|
3764
3949
|
// Keyed by TYPE first, then path — never by path alone. The window decoder
|
|
3765
3950
|
// is baked from `sourceType`, so a path re-bound at a different type (a
|
|
@@ -3774,6 +3959,10 @@ class PagedRuntime extends TrackedChannelStore {
|
|
|
3774
3959
|
/** Loaded window keys in least-recently-READ order (a Map preserves
|
|
3775
3960
|
* insertion order; a read re-inserts). Bounds the decoded-window cache. */
|
|
3776
3961
|
__publicField(this, "loadedWindows", /* @__PURE__ */ new Map());
|
|
3962
|
+
/** Each dataset's snapshot, by workspace and path. */
|
|
3963
|
+
__publicField(this, "snapshots", /* @__PURE__ */ new Map());
|
|
3964
|
+
/** Fetches launched so far — the source of every channel's `launchSeq`. */
|
|
3965
|
+
__publicField(this, "launches", 0);
|
|
3777
3966
|
}
|
|
3778
3967
|
/** Monotonic clock seam so tests can drive the retry gate. */
|
|
3779
3968
|
now() {
|
|
@@ -3784,17 +3973,33 @@ class PagedRuntime extends TrackedChannelStore {
|
|
|
3784
3973
|
}
|
|
3785
3974
|
// ----- wiring ----------------------------------------------------------
|
|
3786
3975
|
/** Install the API adapter + workspace — called by the React provider
|
|
3787
|
-
* (or a test/showcase harness) before any handle is used.
|
|
3976
|
+
* (or a test/showcase harness) before any handle is used. Another adapter
|
|
3977
|
+
* or workspace starts from nothing: no snapshot of the old one's carries
|
|
3978
|
+
* over. */
|
|
3788
3979
|
initialize(api3, workspace) {
|
|
3980
|
+
if (this.api !== api3 || this.workspace !== workspace) this.reset();
|
|
3789
3981
|
this.api = api3;
|
|
3790
3982
|
this.workspace = workspace;
|
|
3791
3983
|
}
|
|
3792
|
-
/**
|
|
3793
|
-
|
|
3984
|
+
/**
|
|
3985
|
+
* Tear down the adapter and all window state.
|
|
3986
|
+
*
|
|
3987
|
+
* @param api - Clear only while this is the installed adapter, so a
|
|
3988
|
+
* provider tearing down after another installed its own leaves that one
|
|
3989
|
+
* in place
|
|
3990
|
+
*/
|
|
3991
|
+
clear(api3) {
|
|
3992
|
+
if (api3 !== void 0 && this.api !== api3) return;
|
|
3794
3993
|
this.api = null;
|
|
3795
3994
|
this.workspace = null;
|
|
3796
|
-
this.
|
|
3995
|
+
this.reset();
|
|
3797
3996
|
this.handleCache.clear();
|
|
3997
|
+
}
|
|
3998
|
+
/** Stop following every dataset, and drop what every snapshot delivered. */
|
|
3999
|
+
reset() {
|
|
4000
|
+
for (const snapshot of this.snapshots.values()) snapshot.unwatch();
|
|
4001
|
+
this.snapshots.clear();
|
|
4002
|
+
this.clearChannels();
|
|
3798
4003
|
this.loadedWindows.clear();
|
|
3799
4004
|
}
|
|
3800
4005
|
resolveWorkspace() {
|
|
@@ -3805,7 +4010,178 @@ class PagedRuntime extends TrackedChannelStore {
|
|
|
3805
4010
|
}
|
|
3806
4011
|
return this.workspace;
|
|
3807
4012
|
}
|
|
3808
|
-
// -----
|
|
4013
|
+
// ----- snapshots -------------------------------------------------------
|
|
4014
|
+
/** A dataset's snapshot, followed from its first read until the runtime
|
|
4015
|
+
* is cleared. */
|
|
4016
|
+
snapshotOf(workspace, path2) {
|
|
4017
|
+
const key = `${workspace}:${datasetPathToString(path2)}`;
|
|
4018
|
+
const existing = this.snapshots.get(key);
|
|
4019
|
+
if (existing !== void 0) return existing;
|
|
4020
|
+
const snapshot = {
|
|
4021
|
+
key,
|
|
4022
|
+
revision: void 0,
|
|
4023
|
+
moves: 0,
|
|
4024
|
+
findSeq: 0,
|
|
4025
|
+
finding: false,
|
|
4026
|
+
channels: /* @__PURE__ */ new Set(),
|
|
4027
|
+
unwatch: () => {
|
|
4028
|
+
}
|
|
4029
|
+
};
|
|
4030
|
+
this.snapshots.set(key, snapshot);
|
|
4031
|
+
if (this.api !== null) {
|
|
4032
|
+
snapshot.unwatch = this.api.watchRevision(workspace, path2, (hash2) => this.moveTo(workspace, path2, snapshot, hash2));
|
|
4033
|
+
}
|
|
4034
|
+
return snapshot;
|
|
4035
|
+
}
|
|
4036
|
+
/** Whether a snapshot is still the runtime's, rather than one a clear or a
|
|
4037
|
+
* re-initialization dropped. */
|
|
4038
|
+
isLive(snapshot) {
|
|
4039
|
+
return this.snapshots.get(snapshot.key) === snapshot;
|
|
4040
|
+
}
|
|
4041
|
+
/** Whether a live snapshot is still pinned to `revision`. */
|
|
4042
|
+
pinnedTo(snapshot, revision) {
|
|
4043
|
+
return this.isLive(snapshot) && snapshot.revision === revision;
|
|
4044
|
+
}
|
|
4045
|
+
/**
|
|
4046
|
+
* The revision a read of `path` is pinned to — a hash, `null` while the
|
|
4047
|
+
* dataset has no value, or `undefined` while it is being found — tracked so
|
|
4048
|
+
* the read re-fires when the source moves.
|
|
4049
|
+
*
|
|
4050
|
+
* @throws The failed lookup's reason, until a read after the retry gap
|
|
4051
|
+
* looks again
|
|
4052
|
+
*/
|
|
4053
|
+
revisionFor(workspace, path2) {
|
|
4054
|
+
this.track(pagedRevisionKey(workspace, path2));
|
|
4055
|
+
const snapshot = this.snapshotOf(workspace, path2);
|
|
4056
|
+
if (snapshot.revision !== void 0 || snapshot.finding) return snapshot.revision;
|
|
4057
|
+
if (snapshot.findError !== void 0 && this.now() - (snapshot.findFailedAtMs ?? 0) < RETRY_AFTER_MS) {
|
|
4058
|
+
throw new Error(snapshot.findError);
|
|
4059
|
+
}
|
|
4060
|
+
this.find(workspace, path2, snapshot);
|
|
4061
|
+
return void 0;
|
|
4062
|
+
}
|
|
4063
|
+
/**
|
|
4064
|
+
* Ask the server which content the dataset holds, and move there — unless
|
|
4065
|
+
* a move lands first, which came from something no older than the answer.
|
|
4066
|
+
*/
|
|
4067
|
+
find(workspace, path2, snapshot) {
|
|
4068
|
+
const seq = ++snapshot.findSeq;
|
|
4069
|
+
const moves = snapshot.moves;
|
|
4070
|
+
snapshot.finding = true;
|
|
4071
|
+
const api3 = this.api;
|
|
4072
|
+
void (async () => {
|
|
4073
|
+
let revision;
|
|
4074
|
+
try {
|
|
4075
|
+
if (api3 === null) throw new Error("no PagedApi installed");
|
|
4076
|
+
revision = await api3.getRevision(workspace, path2);
|
|
4077
|
+
} catch (err) {
|
|
4078
|
+
if (!this.isLive(snapshot) || snapshot.findSeq !== seq) return;
|
|
4079
|
+
snapshot.finding = false;
|
|
4080
|
+
if (snapshot.revision !== void 0) return;
|
|
4081
|
+
snapshot.findError = failureOf(path2, err);
|
|
4082
|
+
snapshot.findFailedAtMs = this.now();
|
|
4083
|
+
console.error(`Data.bindPaged: could not find which content ${datasetPathToString(path2)} holds:`, err);
|
|
4084
|
+
this.notify(pagedRevisionKey(workspace, path2));
|
|
4085
|
+
return;
|
|
4086
|
+
}
|
|
4087
|
+
if (!this.isLive(snapshot) || snapshot.findSeq !== seq) return;
|
|
4088
|
+
snapshot.finding = false;
|
|
4089
|
+
if (snapshot.moves !== moves) return;
|
|
4090
|
+
this.moveTo(workspace, path2, snapshot, revision);
|
|
4091
|
+
})();
|
|
4092
|
+
}
|
|
4093
|
+
/**
|
|
4094
|
+
* Move a dataset's source to `revision`: drop what the old snapshot
|
|
4095
|
+
* delivered and re-fire every read of the dataset, so the windows and
|
|
4096
|
+
* searches still in use are fetched again, pinned to the new one. A move to
|
|
4097
|
+
* the revision the source already has changes nothing.
|
|
4098
|
+
*/
|
|
4099
|
+
moveTo(workspace, path2, snapshot, revision) {
|
|
4100
|
+
if (!this.isLive(snapshot) || snapshot.revision === revision) return;
|
|
4101
|
+
snapshot.revision = revision;
|
|
4102
|
+
snapshot.moves += 1;
|
|
4103
|
+
delete snapshot.findError;
|
|
4104
|
+
delete snapshot.findFailedAtMs;
|
|
4105
|
+
for (const key of snapshot.channels) {
|
|
4106
|
+
this.entries.delete(key);
|
|
4107
|
+
this.loadedWindows.delete(key);
|
|
4108
|
+
}
|
|
4109
|
+
snapshot.channels.clear();
|
|
4110
|
+
this.notify(pagedRevisionKey(workspace, path2));
|
|
4111
|
+
}
|
|
4112
|
+
/**
|
|
4113
|
+
* Handle what a pinned fetch threw when it is not the read's failure: a
|
|
4114
|
+
* refusal naming other content moves the source there, and "no value"
|
|
4115
|
+
* moves it to no snapshot. Returns whether the error was one of those, or
|
|
4116
|
+
* arrived after the source had already moved on.
|
|
4117
|
+
*/
|
|
4118
|
+
followed(workspace, path2, snapshot, revision, err) {
|
|
4119
|
+
if (!this.pinnedTo(snapshot, revision)) return true;
|
|
4120
|
+
if (err instanceof e3ApiClient.DatasetHashMismatchError) {
|
|
4121
|
+
if (err.currentHash !== null && err.currentHash !== revision) {
|
|
4122
|
+
this.moveTo(workspace, path2, snapshot, err.currentHash);
|
|
4123
|
+
return true;
|
|
4124
|
+
}
|
|
4125
|
+
this.find(workspace, path2, snapshot);
|
|
4126
|
+
return false;
|
|
4127
|
+
}
|
|
4128
|
+
const code = errorCode(err);
|
|
4129
|
+
if (code !== void 0 && NO_VALUE_ERRORS.has(code)) {
|
|
4130
|
+
this.moveTo(workspace, path2, snapshot, null);
|
|
4131
|
+
return true;
|
|
4132
|
+
}
|
|
4133
|
+
return false;
|
|
4134
|
+
}
|
|
4135
|
+
// ----- channels ----------------------------------------------------------
|
|
4136
|
+
/** A channel of the snapshot's current revision, dropped when it moves. */
|
|
4137
|
+
channel(snapshot, key) {
|
|
4138
|
+
snapshot.channels.add(key);
|
|
4139
|
+
return this.entry(key);
|
|
4140
|
+
}
|
|
4141
|
+
/** Whether a channel is due a fetch: never fetched, evicted, or failed
|
|
4142
|
+
* for a reason a retry can fix, longer ago than the retry gap. */
|
|
4143
|
+
due(entry) {
|
|
4144
|
+
if (entry.status === "idle") return true;
|
|
4145
|
+
if (entry.status !== "failed" || entry.permanent === true) return false;
|
|
4146
|
+
return this.now() - (entry.failedAtMs ?? 0) >= RETRY_AFTER_MS;
|
|
4147
|
+
}
|
|
4148
|
+
/**
|
|
4149
|
+
* Mark a channel's fetch as started, returning the fetch's sequence number.
|
|
4150
|
+
*
|
|
4151
|
+
* Deliberately does NOT notify — the read that triggers it runs inside a
|
|
4152
|
+
* render pass, and notifying there would re-enter the renderer. Only the
|
|
4153
|
+
* settle notifies.
|
|
4154
|
+
*/
|
|
4155
|
+
launch(entry) {
|
|
4156
|
+
entry.status = "running";
|
|
4157
|
+
entry.launchSeq = ++this.launches;
|
|
4158
|
+
return entry.launchSeq;
|
|
4159
|
+
}
|
|
4160
|
+
/** Apply a fetch's outcome if the channel still waits on it, re-firing the
|
|
4161
|
+
* channel's reads. Returns whether it applied. */
|
|
4162
|
+
settle(key, seq, mutate) {
|
|
4163
|
+
const entry = this.entries.get(key);
|
|
4164
|
+
if (entry === void 0 || entry.launchSeq !== seq) return false;
|
|
4165
|
+
mutate(entry);
|
|
4166
|
+
this.notify(key);
|
|
4167
|
+
return true;
|
|
4168
|
+
}
|
|
4169
|
+
/** Settle a fetch as failed, with the reason a read will throw. */
|
|
4170
|
+
fail(key, seq, reason, permanent) {
|
|
4171
|
+
this.settle(key, seq, (e3) => {
|
|
4172
|
+
e3.status = "failed";
|
|
4173
|
+
e3.error = reason;
|
|
4174
|
+
e3.failedAtMs = this.now();
|
|
4175
|
+
e3.permanent = permanent;
|
|
4176
|
+
});
|
|
4177
|
+
}
|
|
4178
|
+
/** What a read of a channel answers: its value once loaded, `none` while
|
|
4179
|
+
* in flight, or its failure, thrown. */
|
|
4180
|
+
answer(entry, value) {
|
|
4181
|
+
if (entry.status === "loaded" && value !== void 0) return east.some(value);
|
|
4182
|
+
if (entry.status === "failed") throw new Error(entry.error ?? "Data.bindPaged: the read failed");
|
|
4183
|
+
return east.none;
|
|
4184
|
+
}
|
|
3809
4185
|
/** Note a window as most-recently-read, and drop the coldest decoded
|
|
3810
4186
|
* windows once the cache exceeds its cap. An evicted window returns to
|
|
3811
4187
|
* `idle`, so the next read refetches it rather than reading a hole. */
|
|
@@ -3823,131 +4199,83 @@ class PagedRuntime extends TrackedChannelStore {
|
|
|
3823
4199
|
delete entry.window;
|
|
3824
4200
|
}
|
|
3825
4201
|
}
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
*
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
ensureWindow(sourceType, workspace, path2, offset, limit2) {
|
|
3834
|
-
const key = pagedWindowKey(workspace, path2, offset, limit2);
|
|
3835
|
-
const entry = this.entry(key);
|
|
3836
|
-
if (entry.status === "running" || entry.status === "loaded") return;
|
|
3837
|
-
if (entry.status === "failed") {
|
|
3838
|
-
if (entry.permanent) return;
|
|
3839
|
-
const since = this.now() - (entry.failedAtMs ?? 0);
|
|
3840
|
-
if (since < RETRY_AFTER_MS) return;
|
|
3841
|
-
}
|
|
3842
|
-
entry.status = "running";
|
|
3843
|
-
entry.launchSeq += 1;
|
|
3844
|
-
const mySeq = entry.launchSeq;
|
|
4202
|
+
// ----- window loading --------------------------------------------------
|
|
4203
|
+
/** Start the pinned fetch for a window if it is due one, returning its
|
|
4204
|
+
* channel. */
|
|
4205
|
+
ensureWindow(sourceType, workspace, path2, snapshot, revision, offset, limit2, selector2, key) {
|
|
4206
|
+
const entry = this.channel(snapshot, key);
|
|
4207
|
+
if (!this.due(entry)) return entry;
|
|
4208
|
+
const seq = this.launch(entry);
|
|
3845
4209
|
const api3 = this.api;
|
|
3846
4210
|
void (async () => {
|
|
3847
|
-
const settle = (mutate) => {
|
|
3848
|
-
const current = this.entries.get(key);
|
|
3849
|
-
if (!current || current.launchSeq !== mySeq) return;
|
|
3850
|
-
mutate(current);
|
|
3851
|
-
this.notify(key);
|
|
3852
|
-
};
|
|
3853
|
-
if (!api3) {
|
|
3854
|
-
settle((e3) => {
|
|
3855
|
-
e3.status = "failed";
|
|
3856
|
-
e3.failedAtMs = this.now();
|
|
3857
|
-
});
|
|
3858
|
-
console.error("Data.bindPaged: no PagedApi installed");
|
|
3859
|
-
return;
|
|
3860
|
-
}
|
|
3861
4211
|
let page;
|
|
3862
4212
|
try {
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
e3.permanent = permanent;
|
|
4213
|
+
if (api3 === null) throw new Error("no PagedApi installed");
|
|
4214
|
+
page = await api3.getPage(workspace, path2, {
|
|
4215
|
+
offset,
|
|
4216
|
+
limit: limit2,
|
|
4217
|
+
hash: revision,
|
|
4218
|
+
...selector2.index !== null && { index: selector2.index, join: selector2.join }
|
|
3870
4219
|
});
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
);
|
|
4220
|
+
} catch (err) {
|
|
4221
|
+
if (this.followed(workspace, path2, snapshot, revision, err)) return;
|
|
4222
|
+
this.fail(key, seq, failureOf(path2, err), isPermanentPageError(err));
|
|
4223
|
+
console.error(`Data.bindPaged: fetch failed for ${key}:`, err);
|
|
3875
4224
|
return;
|
|
3876
4225
|
}
|
|
4226
|
+
if (!this.pinnedTo(snapshot, revision)) return;
|
|
3877
4227
|
let decoded;
|
|
3878
4228
|
try {
|
|
3879
4229
|
decoded = east.decodeBeast2For(sourceType)(page.data);
|
|
3880
4230
|
} catch (err) {
|
|
3881
|
-
|
|
3882
|
-
e3.status = "failed";
|
|
3883
|
-
e3.failedAtMs = this.now();
|
|
3884
|
-
});
|
|
4231
|
+
this.fail(key, seq, `${failureOf(path2, err)} (the window does not decode as the source's type)`, true);
|
|
3885
4232
|
console.error(`Data.bindPaged: decode failed for ${key}:`, err);
|
|
3886
4233
|
return;
|
|
3887
4234
|
}
|
|
3888
|
-
settle((e3) => {
|
|
4235
|
+
const landed = this.settle(key, seq, (e3) => {
|
|
3889
4236
|
e3.status = "loaded";
|
|
3890
4237
|
e3.window = decoded;
|
|
3891
4238
|
e3.total = page.totalElements;
|
|
4239
|
+
delete e3.error;
|
|
3892
4240
|
});
|
|
4241
|
+
if (!landed) return;
|
|
3893
4242
|
this.touchWindow(key);
|
|
3894
|
-
const totalKey = pagedTotalKey(workspace, path2);
|
|
3895
|
-
const totalEntry = this.
|
|
4243
|
+
const totalKey = pagedTotalKey(workspace, path2, revision, selector2);
|
|
4244
|
+
const totalEntry = this.channel(snapshot, totalKey);
|
|
3896
4245
|
if (totalEntry.total !== page.totalElements) {
|
|
3897
4246
|
totalEntry.total = page.totalElements;
|
|
3898
4247
|
totalEntry.status = "loaded";
|
|
3899
4248
|
this.notify(totalKey);
|
|
3900
4249
|
}
|
|
3901
4250
|
})();
|
|
4251
|
+
return entry;
|
|
3902
4252
|
}
|
|
3903
|
-
/**
|
|
3904
|
-
*
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
const entry = this.entry(key);
|
|
3910
|
-
if (entry.status === "running" || entry.status === "loaded") return;
|
|
3911
|
-
if (entry.status === "failed") {
|
|
3912
|
-
if (entry.permanent) return;
|
|
3913
|
-
const since = this.now() - (entry.failedAtMs ?? 0);
|
|
3914
|
-
if (since < RETRY_AFTER_MS) return;
|
|
3915
|
-
}
|
|
3916
|
-
entry.status = "running";
|
|
3917
|
-
entry.launchSeq += 1;
|
|
3918
|
-
const mySeq = entry.launchSeq;
|
|
4253
|
+
/** Start the pinned fence search for one key query if it is due one,
|
|
4254
|
+
* returning its channel — the seek sibling of {@link ensureWindow}. */
|
|
4255
|
+
ensureSeek(workspace, path2, snapshot, revision, query, key) {
|
|
4256
|
+
const entry = this.channel(snapshot, key);
|
|
4257
|
+
if (!this.due(entry)) return entry;
|
|
4258
|
+
const seq = this.launch(entry);
|
|
3919
4259
|
const api3 = this.api;
|
|
3920
4260
|
void (async () => {
|
|
3921
|
-
|
|
3922
|
-
const current = this.entries.get(key);
|
|
3923
|
-
if (!current || current.launchSeq !== mySeq) return;
|
|
3924
|
-
mutate(current);
|
|
3925
|
-
this.notify(key);
|
|
3926
|
-
};
|
|
3927
|
-
if (!api3) {
|
|
3928
|
-
settle((e3) => {
|
|
3929
|
-
e3.status = "failed";
|
|
3930
|
-
e3.failedAtMs = this.now();
|
|
3931
|
-
});
|
|
3932
|
-
console.error("Data.bindPaged: no PagedApi installed");
|
|
3933
|
-
return;
|
|
3934
|
-
}
|
|
4261
|
+
let range;
|
|
3935
4262
|
try {
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
e3.status = "loaded";
|
|
3939
|
-
e3.range = range;
|
|
3940
|
-
});
|
|
4263
|
+
if (api3 === null) throw new Error("no PagedApi installed");
|
|
4264
|
+
range = await api3.findKey(workspace, path2, { ...query, hash: revision });
|
|
3941
4265
|
} catch (err) {
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
e3.status = "failed";
|
|
3945
|
-
e3.failedAtMs = this.now();
|
|
3946
|
-
e3.permanent = permanent;
|
|
3947
|
-
});
|
|
4266
|
+
if (this.followed(workspace, path2, snapshot, revision, err)) return;
|
|
4267
|
+
this.fail(key, seq, failureOf(path2, err), isPermanentPageError(err));
|
|
3948
4268
|
console.error(`Data.bindPaged: key search failed for ${key}:`, err);
|
|
4269
|
+
return;
|
|
3949
4270
|
}
|
|
4271
|
+
if (!this.pinnedTo(snapshot, revision)) return;
|
|
4272
|
+
this.settle(key, seq, (e3) => {
|
|
4273
|
+
e3.status = "loaded";
|
|
4274
|
+
e3.range = range;
|
|
4275
|
+
delete e3.error;
|
|
4276
|
+
});
|
|
3950
4277
|
})();
|
|
4278
|
+
return entry;
|
|
3951
4279
|
}
|
|
3952
4280
|
/**
|
|
3953
4281
|
* The low-level primitives backing handle methods, bound to THIS runtime.
|
|
@@ -3957,53 +4285,92 @@ class PagedRuntime extends TrackedChannelStore {
|
|
|
3957
4285
|
*/
|
|
3958
4286
|
buildPrimitives() {
|
|
3959
4287
|
return [
|
|
3960
|
-
internal$1.DataPagedPrimitives.page.implement((sourceType) => (pathArg, offsetArg, limitArg) => {
|
|
4288
|
+
internal$1.DataPagedPrimitives.page.implement((sourceType) => (pathArg, indexArg, joinArg, offsetArg, limitArg) => {
|
|
3961
4289
|
const workspace = this.resolveWorkspace();
|
|
3962
4290
|
const path2 = pathArg;
|
|
4291
|
+
const revision = this.revisionFor(workspace, path2);
|
|
4292
|
+
if (typeof revision !== "string") return east.none;
|
|
4293
|
+
const selector2 = toSelector(indexArg, joinArg);
|
|
3963
4294
|
const offset = Number(offsetArg);
|
|
3964
4295
|
const limit2 = Number(limitArg);
|
|
3965
|
-
const key = pagedWindowKey(workspace, path2, offset, limit2);
|
|
4296
|
+
const key = pagedWindowKey(workspace, path2, revision, offset, limit2, selector2);
|
|
3966
4297
|
this.track(key);
|
|
3967
|
-
this.ensureWindow(
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
4298
|
+
const entry = this.ensureWindow(
|
|
4299
|
+
sourceType,
|
|
4300
|
+
workspace,
|
|
4301
|
+
path2,
|
|
4302
|
+
this.snapshotOf(workspace, path2),
|
|
4303
|
+
revision,
|
|
4304
|
+
offset,
|
|
4305
|
+
limit2,
|
|
4306
|
+
selector2,
|
|
4307
|
+
key
|
|
4308
|
+
);
|
|
4309
|
+
if (entry.status === "loaded" && entry.window !== void 0) this.touchWindow(key);
|
|
4310
|
+
return this.answer(entry, entry.window);
|
|
3974
4311
|
}),
|
|
3975
|
-
internal$1.DataPagedPrimitives.total.implement((_sourceType) => (pathArg) => {
|
|
4312
|
+
internal$1.DataPagedPrimitives.total.implement((_sourceType) => (pathArg, indexArg, joinArg) => {
|
|
3976
4313
|
const workspace = this.resolveWorkspace();
|
|
3977
|
-
const
|
|
4314
|
+
const path2 = pathArg;
|
|
4315
|
+
const revision = this.revisionFor(workspace, path2);
|
|
4316
|
+
if (typeof revision !== "string") return east.none;
|
|
4317
|
+
const key = pagedTotalKey(workspace, path2, revision, toSelector(indexArg, joinArg));
|
|
3978
4318
|
this.track(key);
|
|
3979
|
-
const entry = this.
|
|
3980
|
-
return entry.total !== void 0 ? east.
|
|
4319
|
+
const entry = this.channel(this.snapshotOf(workspace, path2), key);
|
|
4320
|
+
return entry.total !== void 0 ? east.some(BigInt(entry.total)) : east.none;
|
|
3981
4321
|
}),
|
|
3982
|
-
internal$1.DataPagedPrimitives.seek.implement((_sourceType) => (pathArg, queryArg) => {
|
|
4322
|
+
internal$1.DataPagedPrimitives.seek.implement((_sourceType) => (pathArg, indexArg, joinArg, queryArg) => {
|
|
3983
4323
|
const workspace = this.resolveWorkspace();
|
|
3984
4324
|
const path2 = pathArg;
|
|
3985
|
-
const
|
|
3986
|
-
|
|
4325
|
+
const revision = this.revisionFor(workspace, path2);
|
|
4326
|
+
if (typeof revision !== "string") return east.none;
|
|
4327
|
+
const selector2 = toSelector(indexArg, joinArg);
|
|
4328
|
+
const query = toFindQuery(queryArg, selector2);
|
|
4329
|
+
const key = pagedSeekKey(workspace, path2, revision, query, selector2);
|
|
3987
4330
|
this.track(key);
|
|
3988
|
-
this.ensureSeek(workspace, path2, query, key);
|
|
3989
|
-
const
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
4331
|
+
const entry = this.ensureSeek(workspace, path2, this.snapshotOf(workspace, path2), revision, query, key);
|
|
4332
|
+
const range = entry.range;
|
|
4333
|
+
return this.answer(entry, range === void 0 ? void 0 : { found: range.found, row: BigInt(range.row), count: BigInt(range.count) });
|
|
4334
|
+
}),
|
|
4335
|
+
internal$1.DataPagedPrimitives.revision.implement((_sourceType) => (pathArg, _indexArg, _joinArg) => {
|
|
4336
|
+
const revision = this.revisionFor(this.resolveWorkspace(), pathArg);
|
|
4337
|
+
return typeof revision === "string" ? east.some(revision) : east.none;
|
|
4338
|
+
}),
|
|
4339
|
+
internal$1.DataPagedPrimitives.refresh.implement((_sourceType) => (pathArg, _indexArg, _joinArg, targetArg) => {
|
|
4340
|
+
const workspace = this.resolveWorkspace();
|
|
4341
|
+
const path2 = pathArg;
|
|
4342
|
+
const target = targetArg;
|
|
4343
|
+
queueMicrotask(() => {
|
|
4344
|
+
if (this.workspace !== workspace) return;
|
|
4345
|
+
const snapshot = this.snapshotOf(workspace, path2);
|
|
4346
|
+
if (target.type === "some") this.moveTo(workspace, path2, snapshot, target.value);
|
|
4347
|
+
else this.find(workspace, path2, snapshot);
|
|
4348
|
+
});
|
|
4349
|
+
return null;
|
|
3993
4350
|
})
|
|
3994
4351
|
];
|
|
3995
4352
|
}
|
|
3996
4353
|
/**
|
|
3997
|
-
* Build the handle value for one
|
|
3998
|
-
*
|
|
3999
|
-
*
|
|
4000
|
-
* type-arg) — so the handle is ordinary serializable East data (issue
|
|
4354
|
+
* Build the handle value for one paged bind. Every method is a thin
|
|
4355
|
+
* IR-bearing `East.function` over {@link buildPrimitives}, capturing only
|
|
4356
|
+
* the plain-data source path and selector (the value type rides as a
|
|
4357
|
+
* type-arg) — so the handle is ordinary serializable East data (issue
|
|
4358
|
+
* #106).
|
|
4359
|
+
*
|
|
4360
|
+
* @param sourceType - The dataset's type, or an index's window type
|
|
4361
|
+
* @param path - The dataset's path
|
|
4362
|
+
* @param selector - The rows the bind serves
|
|
4363
|
+
* @param shape - `released`: the handle `data_bind_paged` returns, without
|
|
4364
|
+
* `revision` or `refresh`; `pinned`: the handle `data_bind_paged_pinned`
|
|
4365
|
+
* returns. Both read through the same snapshot.
|
|
4366
|
+
* @returns The handle
|
|
4001
4367
|
*/
|
|
4002
|
-
buildHandle(sourceType, path2) {
|
|
4003
|
-
const
|
|
4368
|
+
buildHandle(sourceType, path2, selector2, shape) {
|
|
4369
|
+
const id3 = `${datasetPathToString(path2)}${selectorKey(selector2)}`;
|
|
4370
|
+
const cacheKey = `${id3}#${shape}`;
|
|
4004
4371
|
let byPath = this.handleCache.get(sourceType);
|
|
4005
4372
|
if (byPath) {
|
|
4006
|
-
const hit = byPath.get(
|
|
4373
|
+
const hit = byPath.get(cacheKey);
|
|
4007
4374
|
if (hit) return hit;
|
|
4008
4375
|
} else {
|
|
4009
4376
|
byPath = /* @__PURE__ */ new Map();
|
|
@@ -4011,24 +4378,27 @@ class PagedRuntime extends TrackedChannelStore {
|
|
|
4011
4378
|
}
|
|
4012
4379
|
const T2 = east.fromEastTypeValue(sourceType);
|
|
4013
4380
|
const pathExpr = east.East.value(path2, e3Types.TreePathType);
|
|
4381
|
+
const indexExpr = east.East.value(selector2.index === null ? east.none : east.some(selector2.index), east.OptionType(east.StringType));
|
|
4382
|
+
const joinExpr = east.East.value(selector2.join, east.BooleanType);
|
|
4014
4383
|
const platform2 = this.buildPrimitives();
|
|
4015
|
-
const { page, total } = internal$1.DataPagedPrimitives;
|
|
4384
|
+
const { page, total, revision, refresh } = internal$1.DataPagedPrimitives;
|
|
4016
4385
|
const handle = {
|
|
4017
4386
|
// The comparable identity east-ui's `PagedSourceType` requires:
|
|
4018
4387
|
// East compares every function as EQUAL, so a struct of nothing but
|
|
4019
4388
|
// closures is indistinguishable from any other and a memoized
|
|
4020
4389
|
// component would never re-render on a source swap (#567 D4). The
|
|
4021
|
-
// dataset path
|
|
4022
|
-
|
|
4390
|
+
// dataset path and selector are the natural identity — same path,
|
|
4391
|
+
// same rows. The snapshot they serve is `revision`'s, not the id's.
|
|
4392
|
+
id: id3,
|
|
4023
4393
|
page: east.East.compile(
|
|
4024
4394
|
east.East.function([east.IntegerType, east.IntegerType], east.OptionType(T2), ($3, offset, limit2) => {
|
|
4025
|
-
$3.return(page([T2], pathExpr, offset, limit2));
|
|
4395
|
+
$3.return(page([T2], pathExpr, indexExpr, joinExpr, offset, limit2));
|
|
4026
4396
|
}),
|
|
4027
4397
|
platform2
|
|
4028
4398
|
),
|
|
4029
4399
|
total: east.East.compile(
|
|
4030
4400
|
east.East.function([], east.OptionType(east.IntegerType), ($3) => {
|
|
4031
|
-
$3.return(total([T2], pathExpr));
|
|
4401
|
+
$3.return(total([T2], pathExpr, indexExpr, joinExpr));
|
|
4032
4402
|
}),
|
|
4033
4403
|
platform2
|
|
4034
4404
|
),
|
|
@@ -4037,28 +4407,50 @@ class PagedRuntime extends TrackedChannelStore {
|
|
|
4037
4407
|
// segments) against the stored fences; an Array's stream order has
|
|
4038
4408
|
// nothing to search. Resolved at bind time from the dataset's own
|
|
4039
4409
|
// type, so a component renders the affordance only when it works.
|
|
4040
|
-
seek: buildSeek(sourceType, T2, pathExpr, platform2)
|
|
4410
|
+
seek: buildSeek(sourceType, T2, pathExpr, indexExpr, joinExpr, selector2, platform2)
|
|
4041
4411
|
};
|
|
4042
|
-
|
|
4412
|
+
if (shape === "pinned") {
|
|
4413
|
+
handle.revision = east.East.compile(
|
|
4414
|
+
east.East.function([], east.OptionType(east.StringType), ($3) => {
|
|
4415
|
+
$3.return(revision([T2], pathExpr, indexExpr, joinExpr));
|
|
4416
|
+
}),
|
|
4417
|
+
platform2
|
|
4418
|
+
);
|
|
4419
|
+
handle.refresh = east.East.compile(
|
|
4420
|
+
east.East.function([east.OptionType(east.StringType)], east.NullType, ($3, target) => {
|
|
4421
|
+
$3.return(refresh([T2], pathExpr, indexExpr, joinExpr, target));
|
|
4422
|
+
}),
|
|
4423
|
+
platform2
|
|
4424
|
+
);
|
|
4425
|
+
}
|
|
4426
|
+
byPath.set(cacheKey, handle);
|
|
4043
4427
|
return handle;
|
|
4044
4428
|
}
|
|
4045
4429
|
// ----- platform building -------------------------------------------------
|
|
4046
|
-
/** Build
|
|
4047
|
-
*
|
|
4048
|
-
*
|
|
4430
|
+
/** Build the PlatformFunction behind `data_bind_paged` — the bind a UI
|
|
4431
|
+
* exported before pinned reads calls — bound to this runtime. Its handle
|
|
4432
|
+
* has no `revision` or `refresh`, but its reads are pinned, follow the
|
|
4433
|
+
* dataset and fail visibly all the same. Pass `allowed=null` for an
|
|
4434
|
+
* unscoped impl, or a Set of path strings for manifest scoping. */
|
|
4049
4435
|
buildPlatform(allowed) {
|
|
4050
4436
|
return internal$1.bindPagedPlatformFn.implement(
|
|
4051
4437
|
(sourceType) => (pathArg) => {
|
|
4052
4438
|
const path2 = pathArg;
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4439
|
+
checkDeclared(allowed, path2);
|
|
4440
|
+
return this.buildHandle(sourceType, path2, NO_INDEX, "released");
|
|
4441
|
+
}
|
|
4442
|
+
);
|
|
4443
|
+
}
|
|
4444
|
+
/** Build the PlatformFunction behind `data_bind_paged_pinned` — what
|
|
4445
|
+
* `Data.bindPaged` emits, for a dataset's own rows or a record's index —
|
|
4446
|
+
* bound to this runtime and scoped by `allowed` exactly as
|
|
4447
|
+
* {@link buildPlatform} is: an index read is a read of the record's path. */
|
|
4448
|
+
buildPinnedPlatform(allowed) {
|
|
4449
|
+
return internal$1.bindPagedPinnedPlatformFn.implement(
|
|
4450
|
+
(sourceType) => (pathArg, indexArg, joinArg) => {
|
|
4451
|
+
const path2 = pathArg;
|
|
4452
|
+
checkDeclared(allowed, path2);
|
|
4453
|
+
return this.buildHandle(sourceType, path2, toSelector(indexArg, joinArg), "pinned");
|
|
4062
4454
|
}
|
|
4063
4455
|
);
|
|
4064
4456
|
}
|
|
@@ -4067,17 +4459,19 @@ const defaultPagedRuntime = new PagedRuntime();
|
|
|
4067
4459
|
function initializePagedApi(api3, workspace) {
|
|
4068
4460
|
defaultPagedRuntime.initialize(api3, workspace);
|
|
4069
4461
|
}
|
|
4070
|
-
function clearPagedApi() {
|
|
4071
|
-
defaultPagedRuntime.clear();
|
|
4462
|
+
function clearPagedApi(api3) {
|
|
4463
|
+
defaultPagedRuntime.clear(api3);
|
|
4072
4464
|
}
|
|
4073
4465
|
const PagedPlatform = [
|
|
4074
4466
|
defaultPagedRuntime.buildPlatform(null),
|
|
4467
|
+
defaultPagedRuntime.buildPinnedPlatform(null),
|
|
4075
4468
|
...defaultPagedRuntime.buildPrimitives()
|
|
4076
4469
|
];
|
|
4077
4470
|
function createScopedPagedPlatform(pages) {
|
|
4078
4471
|
const allowed = new Set(pages.map((p2) => datasetPathToString(p2)));
|
|
4079
4472
|
return [
|
|
4080
4473
|
defaultPagedRuntime.buildPlatform(allowed),
|
|
4474
|
+
defaultPagedRuntime.buildPinnedPlatform(allowed),
|
|
4081
4475
|
...defaultPagedRuntime.buildPrimitives()
|
|
4082
4476
|
];
|
|
4083
4477
|
}
|
|
@@ -4100,13 +4494,12 @@ function createDefaultFunctionApi(apiUrl, repo, getToken) {
|
|
|
4100
4494
|
async call(workspace, fn3, req) {
|
|
4101
4495
|
return e3ApiClient.workspaceFunctionCall(apiUrl, repo, workspace, fn3, {
|
|
4102
4496
|
args: req.args,
|
|
4103
|
-
runner: east.
|
|
4104
|
-
limits: east.
|
|
4497
|
+
runner: east.none,
|
|
4498
|
+
limits: east.none
|
|
4105
4499
|
}, opts());
|
|
4106
4500
|
}
|
|
4107
4501
|
};
|
|
4108
4502
|
}
|
|
4109
|
-
const eastTypeEqual$1 = east.equalFor(internal.EastTypeType);
|
|
4110
4503
|
function signatureOfFuncHandleType(handleType) {
|
|
4111
4504
|
var _a2, _b2;
|
|
4112
4505
|
if (handleType.type !== "Struct") {
|
|
@@ -4203,8 +4596,15 @@ class FuncRuntime extends TrackedChannelStore {
|
|
|
4203
4596
|
this.api = api3;
|
|
4204
4597
|
this.workspace = workspace;
|
|
4205
4598
|
}
|
|
4206
|
-
/**
|
|
4207
|
-
|
|
4599
|
+
/**
|
|
4600
|
+
* Tear down the adapter and all call state.
|
|
4601
|
+
*
|
|
4602
|
+
* @param api - Clear only while this is the installed adapter, so a
|
|
4603
|
+
* provider tearing down after another installed its own leaves that one
|
|
4604
|
+
* in place
|
|
4605
|
+
*/
|
|
4606
|
+
clear(api3) {
|
|
4607
|
+
if (api3 !== void 0 && this.api !== api3) return;
|
|
4208
4608
|
this.api = null;
|
|
4209
4609
|
this.workspace = null;
|
|
4210
4610
|
this.clearChannels();
|
|
@@ -4243,8 +4643,8 @@ class FuncRuntime extends TrackedChannelStore {
|
|
|
4243
4643
|
stderr: ""
|
|
4244
4644
|
};
|
|
4245
4645
|
}
|
|
4246
|
-
const inputsMatch = deployed.inputTypes.length === sig.inputs.length && deployed.inputTypes.every((t4, i) =>
|
|
4247
|
-
const outputMatches =
|
|
4646
|
+
const inputsMatch = deployed.inputTypes.length === sig.inputs.length && deployed.inputTypes.every((t4, i) => east.isTypeValueEqual(t4, sig.inputs[i]));
|
|
4647
|
+
const outputMatches = east.isTypeValueEqual(deployed.outputType, sig.output);
|
|
4248
4648
|
if (!inputsMatch || !outputMatches) {
|
|
4249
4649
|
const message = `signature mismatch for "${name}": bound (${sig.inputs.length} inputs) disagrees with the deployed package`;
|
|
4250
4650
|
return {
|
|
@@ -4347,7 +4747,7 @@ class FuncRuntime extends TrackedChannelStore {
|
|
|
4347
4747
|
internal$1.FuncBindPrimitives.read.implement((_outputType) => (nameArg) => {
|
|
4348
4748
|
const { key, entry } = channel(nameArg);
|
|
4349
4749
|
runtime.track(key);
|
|
4350
|
-
return entry.result !== void 0 ? east.
|
|
4750
|
+
return entry.result !== void 0 ? east.some(entry.result) : east.none;
|
|
4351
4751
|
}),
|
|
4352
4752
|
internal$1.FuncBindPrimitives.status.implement((nameArg) => {
|
|
4353
4753
|
const { key, entry } = channel(nameArg);
|
|
@@ -4357,7 +4757,7 @@ class FuncRuntime extends TrackedChannelStore {
|
|
|
4357
4757
|
internal$1.FuncBindPrimitives.error.implement((nameArg) => {
|
|
4358
4758
|
const { key, entry } = channel(nameArg);
|
|
4359
4759
|
runtime.track(key);
|
|
4360
|
-
return entry.status === "failed" && entry.error !== void 0 ? east.
|
|
4760
|
+
return entry.status === "failed" && entry.error !== void 0 ? east.some(entry.error) : east.none;
|
|
4361
4761
|
}),
|
|
4362
4762
|
internal$1.FuncBindPrimitives.pending.implement((nameArg) => {
|
|
4363
4763
|
const { key, entry } = channel(nameArg);
|
|
@@ -4437,8 +4837,8 @@ const defaultFuncRuntime = new FuncRuntime();
|
|
|
4437
4837
|
function initializeFunctionApi(api3, workspace) {
|
|
4438
4838
|
defaultFuncRuntime.initialize(api3, workspace);
|
|
4439
4839
|
}
|
|
4440
|
-
function clearFunctionApi() {
|
|
4441
|
-
defaultFuncRuntime.clear();
|
|
4840
|
+
function clearFunctionApi(api3) {
|
|
4841
|
+
defaultFuncRuntime.clear(api3);
|
|
4442
4842
|
}
|
|
4443
4843
|
const FuncPlatform = [
|
|
4444
4844
|
defaultFuncRuntime.buildPlatform(null),
|
|
@@ -8211,12 +8611,6 @@ function errorOfMutationResult(result) {
|
|
|
8211
8611
|
message: `reducer exited with code ${outcome.value.exitCode}`,
|
|
8212
8612
|
stderr: outcome.value.stderr
|
|
8213
8613
|
};
|
|
8214
|
-
case "too_large":
|
|
8215
|
-
return {
|
|
8216
|
-
kind: east.variant("too_large", { bytes: outcome.value.bytes, limit: outcome.value.limit }),
|
|
8217
|
-
message: `new state too large (${outcome.value.bytes} bytes, limit ${outcome.value.limit})`,
|
|
8218
|
-
stderr: outcome.value.stderr
|
|
8219
|
-
};
|
|
8220
8614
|
case "timed_out":
|
|
8221
8615
|
return {
|
|
8222
8616
|
kind: east.variant("timed_out", { ms: outcome.value.ms }),
|
|
@@ -8276,8 +8670,15 @@ class RecordRuntime extends TrackedChannelStore {
|
|
|
8276
8670
|
this.cache = cache3;
|
|
8277
8671
|
this.workspace = workspace;
|
|
8278
8672
|
}
|
|
8279
|
-
/**
|
|
8280
|
-
|
|
8673
|
+
/**
|
|
8674
|
+
* Tear down the adapter and all record state.
|
|
8675
|
+
*
|
|
8676
|
+
* @param api - Clear only while this is the installed adapter, so a
|
|
8677
|
+
* provider tearing down after another installed its own leaves that one
|
|
8678
|
+
* in place
|
|
8679
|
+
*/
|
|
8680
|
+
clear(api3) {
|
|
8681
|
+
if (api3 !== void 0 && this.api !== api3) return;
|
|
8281
8682
|
this.api = null;
|
|
8282
8683
|
this.cache = null;
|
|
8283
8684
|
this.workspace = null;
|
|
@@ -8585,8 +8986,8 @@ const defaultRecordRuntime = new RecordRuntime();
|
|
|
8585
8986
|
function initializeRecordApi(api3, cache3, workspace) {
|
|
8586
8987
|
defaultRecordRuntime.initialize(api3, cache3, workspace);
|
|
8587
8988
|
}
|
|
8588
|
-
function clearRecordApi() {
|
|
8589
|
-
defaultRecordRuntime.clear();
|
|
8989
|
+
function clearRecordApi(api3) {
|
|
8990
|
+
defaultRecordRuntime.clear(api3);
|
|
8590
8991
|
}
|
|
8591
8992
|
const RecordPlatform = [
|
|
8592
8993
|
defaultRecordRuntime.buildPlatform(null),
|
|
@@ -8612,7 +9013,8 @@ function createInMemoryRecordApi(cache3, workspace, defs2) {
|
|
|
8612
9013
|
state: `${def.name}-state-0`.padEnd(64, "0"),
|
|
8613
9014
|
mutation: "$init",
|
|
8614
9015
|
actor: "memory",
|
|
8615
|
-
at: /* @__PURE__ */ new Date(0)
|
|
9016
|
+
at: /* @__PURE__ */ new Date(0),
|
|
9017
|
+
delta: east.none
|
|
8616
9018
|
};
|
|
8617
9019
|
compiled.set(def.name, { stateType, mutations, commits: [genesis], seq: 0 });
|
|
8618
9020
|
void cache3.write(workspace, recordPath(def.name), east.encodeBeast2For(stateType)(def.initial));
|
|
@@ -8644,7 +9046,8 @@ function createInMemoryRecordApi(cache3, workspace, defs2) {
|
|
|
8644
9046
|
state: `${record}-state-${c2.seq}`.padEnd(64, "0"),
|
|
8645
9047
|
mutation,
|
|
8646
9048
|
actor: "memory",
|
|
8647
|
-
at: /* @__PURE__ */ new Date(0)
|
|
9049
|
+
at: /* @__PURE__ */ new Date(0),
|
|
9050
|
+
delta: east.none
|
|
8648
9051
|
});
|
|
8649
9052
|
return { outcome: east.variant("committed", { commitHash: hash2, stateHash: `${record}-state-${c2.seq}`.padEnd(64, "0") }) };
|
|
8650
9053
|
},
|
|
@@ -8693,68 +9096,49 @@ function ReactiveDatasetProvider({
|
|
|
8693
9096
|
children: children2
|
|
8694
9097
|
}) {
|
|
8695
9098
|
const e3 = useE3Config();
|
|
9099
|
+
const { apiUrl, workspace } = e3;
|
|
9100
|
+
const repo = e3.repo ?? "default";
|
|
8696
9101
|
const tokenRef = React.useRef(e3.token ?? null);
|
|
8697
9102
|
tokenRef.current = e3.token ?? null;
|
|
8698
|
-
const
|
|
8699
|
-
() => createDefaultDatasetApi(e3.apiUrl, e3.repo ?? "default", () => tokenRef.current),
|
|
8700
|
-
[e3.apiUrl, e3.repo]
|
|
8701
|
-
);
|
|
8702
|
-
const cache3 = React.useMemo(() => {
|
|
8703
|
-
const cfg = {};
|
|
8704
|
-
if (e3.workspace !== void 0) cfg.workspace = e3.workspace;
|
|
8705
|
-
return new ReactiveDatasetCache(cfg, api3);
|
|
8706
|
-
}, [api3, e3.workspace]);
|
|
8707
|
-
React.useMemo(() => {
|
|
8708
|
-
initializeReactiveDatasetCache(cache3);
|
|
8709
|
-
cache3.setScheduler((notify3) => queueMicrotask(notify3));
|
|
8710
|
-
}, [cache3]);
|
|
8711
|
-
React.useMemo(() => {
|
|
8712
|
-
if (e3.workspace !== void 0) {
|
|
8713
|
-
initializeFunctionApi(
|
|
8714
|
-
createDefaultFunctionApi(e3.apiUrl, e3.repo ?? "default", () => tokenRef.current),
|
|
8715
|
-
e3.workspace
|
|
8716
|
-
);
|
|
8717
|
-
}
|
|
8718
|
-
}, [e3.apiUrl, e3.repo, e3.workspace]);
|
|
8719
|
-
React.useMemo(() => {
|
|
8720
|
-
if (e3.workspace !== void 0) {
|
|
8721
|
-
initializePagedApi(
|
|
8722
|
-
createDefaultPagedApi(e3.apiUrl, e3.repo ?? "default", () => tokenRef.current),
|
|
8723
|
-
e3.workspace
|
|
8724
|
-
);
|
|
8725
|
-
}
|
|
8726
|
-
}, [e3.apiUrl, e3.repo, e3.workspace]);
|
|
8727
|
-
React.useMemo(() => {
|
|
8728
|
-
if (e3.workspace !== void 0) {
|
|
8729
|
-
initializeRecordApi(
|
|
8730
|
-
createDefaultRecordApi(e3.apiUrl, e3.repo ?? "default", () => tokenRef.current),
|
|
8731
|
-
cache3,
|
|
8732
|
-
e3.workspace
|
|
8733
|
-
);
|
|
8734
|
-
}
|
|
8735
|
-
}, [e3.apiUrl, e3.repo, e3.workspace, cache3]);
|
|
9103
|
+
const [installed, setInstalled] = React.useState(null);
|
|
8736
9104
|
React.useEffect(() => {
|
|
9105
|
+
const getToken = () => tokenRef.current;
|
|
9106
|
+
const cache22 = new ReactiveDatasetCache(
|
|
9107
|
+
workspace !== void 0 ? { workspace } : {},
|
|
9108
|
+
createDefaultDatasetApi(apiUrl, repo, getToken)
|
|
9109
|
+
);
|
|
9110
|
+
cache22.setScheduler((notify3) => queueMicrotask(notify3));
|
|
9111
|
+
initializeReactiveDatasetCache(cache22);
|
|
9112
|
+
const functionApi = createDefaultFunctionApi(apiUrl, repo, getToken);
|
|
9113
|
+
const pagedApi = createDefaultPagedApi(apiUrl, repo, getToken, cache22);
|
|
9114
|
+
const recordApi = createDefaultRecordApi(apiUrl, repo, getToken);
|
|
9115
|
+
if (workspace !== void 0) {
|
|
9116
|
+
initializeFunctionApi(functionApi, workspace);
|
|
9117
|
+
initializePagedApi(pagedApi, workspace);
|
|
9118
|
+
initializeRecordApi(recordApi, cache22, workspace);
|
|
9119
|
+
}
|
|
9120
|
+
const unscopeStaged = getStagedStore().setScope(JSON.stringify([apiUrl, repo]));
|
|
9121
|
+
setInstalled({ apiUrl, repo, workspace, cache: cache22 });
|
|
8737
9122
|
return () => {
|
|
8738
|
-
|
|
8739
|
-
|
|
8740
|
-
|
|
8741
|
-
|
|
8742
|
-
|
|
8743
|
-
|
|
8744
|
-
if (
|
|
9123
|
+
clearReactiveDatasetCache(cache22);
|
|
9124
|
+
clearFunctionApi(functionApi);
|
|
9125
|
+
clearPagedApi(pagedApi);
|
|
9126
|
+
clearRecordApi(recordApi);
|
|
9127
|
+
unscopeStaged();
|
|
9128
|
+
cache22.destroy();
|
|
9129
|
+
if (workspace) clearBindingRegistry(workspace);
|
|
8745
9130
|
else clearBindingRegistry();
|
|
8746
9131
|
};
|
|
8747
|
-
}, [
|
|
9132
|
+
}, [apiUrl, repo, workspace]);
|
|
9133
|
+
const cache3 = installed !== null && installed.apiUrl === apiUrl && installed.repo === repo && installed.workspace === workspace ? installed.cache : null;
|
|
8748
9134
|
React.useEffect(() => {
|
|
8749
|
-
if (typeof window
|
|
8750
|
-
|
|
8751
|
-
}
|
|
9135
|
+
if (cache3 === null || typeof window === "undefined") return;
|
|
9136
|
+
window.__EAST_REACTIVE_DATASET_CACHE__ = cache3;
|
|
8752
9137
|
return () => {
|
|
8753
|
-
|
|
8754
|
-
delete window.__EAST_REACTIVE_DATASET_CACHE__;
|
|
8755
|
-
}
|
|
9138
|
+
delete window.__EAST_REACTIVE_DATASET_CACHE__;
|
|
8756
9139
|
};
|
|
8757
9140
|
}, [cache3]);
|
|
9141
|
+
if (cache3 === null) return null;
|
|
8758
9142
|
return /* @__PURE__ */ jsxRuntime.jsx(ReactiveDatasetCacheContext.Provider, { value: cache3, children: children2 });
|
|
8759
9143
|
}
|
|
8760
9144
|
function useReactiveDatasetCache() {
|
|
@@ -8873,12 +9257,11 @@ function collectLeaves(node2, into = []) {
|
|
|
8873
9257
|
else for (const c2 of node2.children) collectLeaves(c2, into);
|
|
8874
9258
|
return into;
|
|
8875
9259
|
}
|
|
9260
|
+
const readString = east.parseFor(east.StringType);
|
|
8876
9261
|
function leafDisplayLabel(seg) {
|
|
8877
|
-
if (seg.kind === "key"
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
} catch {
|
|
8881
|
-
}
|
|
9262
|
+
if (seg.kind === "key") {
|
|
9263
|
+
const read = readString(seg.key);
|
|
9264
|
+
if (read.success) return read.value;
|
|
8882
9265
|
}
|
|
8883
9266
|
return east.pathDisplay(seg);
|
|
8884
9267
|
}
|
|
@@ -8930,57 +9313,28 @@ function walkPatchToTree(typeValue, patch, rootLabel) {
|
|
|
8930
9313
|
return root2;
|
|
8931
9314
|
}
|
|
8932
9315
|
const MAX_INLINE_CHARS = 48;
|
|
8933
|
-
function formatLeafValue(
|
|
8934
|
-
if (
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
case "Null":
|
|
8938
|
-
return "null";
|
|
8939
|
-
case "Boolean":
|
|
8940
|
-
return value ? "true" : "false";
|
|
8941
|
-
case "Integer":
|
|
8942
|
-
return typeof value === "bigint" ? value.toString() : String(value);
|
|
8943
|
-
case "Float":
|
|
8944
|
-
return formatFloat(value);
|
|
8945
|
-
case "String":
|
|
8946
|
-
return value === "" ? '""' : String(value);
|
|
8947
|
-
case "DateTime":
|
|
8948
|
-
return value instanceof Date ? value.toISOString() : String(value);
|
|
8949
|
-
case "Blob":
|
|
8950
|
-
return value instanceof Uint8Array ? `${value.length} bytes` : truncate(east.printFor(typeValue)(value));
|
|
8951
|
-
case "Variant":
|
|
8952
|
-
if (east.isVariant(value)) {
|
|
8953
|
-
const cases = typeValue.value;
|
|
8954
|
-
const sub = cases.find((c2) => c2.name === value.type);
|
|
8955
|
-
if (value.value === null || value.value === void 0 || !sub) return value.type;
|
|
8956
|
-
return `${value.type}(${truncate(east.printFor(sub.type)(value.value))})`;
|
|
8957
|
-
}
|
|
8958
|
-
return "<value>";
|
|
8959
|
-
default:
|
|
8960
|
-
return truncate(east.printFor(typeValue)(value));
|
|
8961
|
-
}
|
|
8962
|
-
}
|
|
8963
|
-
function formatFloat(v3) {
|
|
8964
|
-
if (typeof v3 !== "number") return String(v3);
|
|
8965
|
-
if (Number.isInteger(v3)) return v3.toFixed(1);
|
|
8966
|
-
return Math.abs(v3) >= 1e3 ? v3.toLocaleString("en-US", { maximumFractionDigits: 2 }) : String(Number(v3.toFixed(4)));
|
|
9316
|
+
function formatLeafValue(leafType, value, words = eastUiComponents.formatters()) {
|
|
9317
|
+
if (leafType.type === "Float") return words.float(value);
|
|
9318
|
+
const text = east.printFor(leafType)(value);
|
|
9319
|
+
return leafType.type === "String" ? text : truncate(text);
|
|
8967
9320
|
}
|
|
8968
9321
|
function truncate(s2) {
|
|
8969
9322
|
return s2.length > MAX_INLINE_CHARS ? s2.slice(0, MAX_INLINE_CHARS - 1) + "…" : s2;
|
|
8970
9323
|
}
|
|
8971
|
-
function formatBindingLabel(
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
if (last2.type === "key") return String(last2.value);
|
|
9324
|
+
function formatBindingLabel(path2) {
|
|
9325
|
+
const last2 = path2[path2.length - 1];
|
|
9326
|
+
if (last2 === void 0) return "(root)";
|
|
9327
|
+
switch (last2.type) {
|
|
9328
|
+
case "field":
|
|
9329
|
+
return last2.value;
|
|
8978
9330
|
}
|
|
8979
|
-
return String(last2);
|
|
8980
9331
|
}
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
9332
|
+
const DATETIME_LOCAL = internal.tokenizeDateTimeFormat("YYYY-MM-DDTHH:mm");
|
|
9333
|
+
const readBoolean = east.parseFor(east.BooleanType);
|
|
9334
|
+
const readInteger = east.parseFor(east.IntegerType);
|
|
9335
|
+
const readFloat = east.parseFor(east.FloatType);
|
|
9336
|
+
function isPrimitiveLeafType(leafType) {
|
|
9337
|
+
switch (leafType.type) {
|
|
8984
9338
|
case "Boolean":
|
|
8985
9339
|
case "Integer":
|
|
8986
9340
|
case "Float":
|
|
@@ -8992,49 +9346,46 @@ function isPrimitiveLeafType(t4) {
|
|
|
8992
9346
|
}
|
|
8993
9347
|
}
|
|
8994
9348
|
function formatManualDraft(leafType, value) {
|
|
8995
|
-
if (
|
|
9349
|
+
if (value === void 0) return "";
|
|
8996
9350
|
switch (leafType.type) {
|
|
8997
9351
|
case "Boolean":
|
|
8998
|
-
return value ? "true" : "false";
|
|
8999
9352
|
case "Integer":
|
|
9000
|
-
return typeof value === "bigint" ? value.toString() : String(value);
|
|
9001
9353
|
case "Float":
|
|
9002
|
-
return
|
|
9354
|
+
return east.printFor(leafType)(value);
|
|
9003
9355
|
case "String":
|
|
9004
|
-
return
|
|
9005
|
-
case "DateTime":
|
|
9006
|
-
|
|
9007
|
-
return value.toISOString().slice(0, 16);
|
|
9008
|
-
}
|
|
9356
|
+
return value;
|
|
9357
|
+
case "DateTime":
|
|
9358
|
+
return internal.formatDateTime(value, DATETIME_LOCAL);
|
|
9009
9359
|
default:
|
|
9010
9360
|
return "";
|
|
9011
9361
|
}
|
|
9012
9362
|
}
|
|
9013
9363
|
function parseManualDraft(leafType, draft) {
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
case "Float": {
|
|
9019
|
-
const n2 = Number(draft);
|
|
9020
|
-
if (Number.isNaN(n2)) return { ok: false };
|
|
9021
|
-
return { ok: true, value: n2 };
|
|
9022
|
-
}
|
|
9023
|
-
case "String":
|
|
9024
|
-
return { ok: true, value: draft };
|
|
9025
|
-
case "DateTime": {
|
|
9026
|
-
const d2 = new Date(draft);
|
|
9027
|
-
if (Number.isNaN(d2.getTime())) return { ok: false };
|
|
9028
|
-
return { ok: true, value: d2 };
|
|
9029
|
-
}
|
|
9030
|
-
default:
|
|
9031
|
-
return { ok: false };
|
|
9364
|
+
switch (leafType.type) {
|
|
9365
|
+
case "Boolean": {
|
|
9366
|
+
const read = readBoolean(draft);
|
|
9367
|
+
return read.success ? { ok: true, value: read.value } : { ok: false };
|
|
9032
9368
|
}
|
|
9033
|
-
|
|
9034
|
-
|
|
9369
|
+
case "Integer": {
|
|
9370
|
+
const read = readInteger(draft);
|
|
9371
|
+
return read.success ? { ok: true, value: read.value } : { ok: false };
|
|
9372
|
+
}
|
|
9373
|
+
case "Float": {
|
|
9374
|
+
const read = readFloat(draft);
|
|
9375
|
+
return read.success ? { ok: true, value: read.value } : { ok: false };
|
|
9376
|
+
}
|
|
9377
|
+
case "String":
|
|
9378
|
+
return { ok: true, value: draft };
|
|
9379
|
+
case "DateTime": {
|
|
9380
|
+
const read = internal.parseDateTimeFormatted(draft, DATETIME_LOCAL);
|
|
9381
|
+
return read.success ? { ok: true, value: read.value } : { ok: false };
|
|
9382
|
+
}
|
|
9383
|
+
default:
|
|
9384
|
+
return { ok: false };
|
|
9035
9385
|
}
|
|
9036
9386
|
}
|
|
9037
|
-
const diffValueEqual = east.
|
|
9387
|
+
const diffValueEqual = east.equivalentFor(internal$1.Diff.Component.schema);
|
|
9388
|
+
const diffValueDataEqual = east.equalFor(internal$1.Diff.Component.schema);
|
|
9038
9389
|
function getOpt$1(opt) {
|
|
9039
9390
|
return opt.type === "some" ? opt.value : void 0;
|
|
9040
9391
|
}
|
|
@@ -9260,6 +9611,7 @@ function ActionBtn({
|
|
|
9260
9611
|
);
|
|
9261
9612
|
}
|
|
9262
9613
|
const DiffRow = React.memo(function DiffRow2({ row, depth, bindingPathStr, showActions, onDiscard, annotation, metrics }) {
|
|
9614
|
+
const words = eastUiComponents.useFormatters();
|
|
9263
9615
|
const handleDiscard = React.useCallback(() => onDiscard(bindingPathStr, row.path), [onDiscard, bindingPathStr, row.path]);
|
|
9264
9616
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9265
9617
|
react.Box,
|
|
@@ -9292,7 +9644,7 @@ const DiffRow = React.memo(function DiffRow2({ row, depth, bindingPathStr, showA
|
|
|
9292
9644
|
row.stale && /* @__PURE__ */ jsxRuntime.jsxs(react.Text, { fontSize: "11px", color: "fg.warning", fontWeight: 500, children: [
|
|
9293
9645
|
/* @__PURE__ */ jsxRuntime.jsx(FontAwesomeIcon, { icon: faTriangleExclamation }),
|
|
9294
9646
|
" ",
|
|
9295
|
-
row.stale.actual === void 0 ? "stale — source no longer has this entry" : `stale — source actually has ${formatLeafValue(row.leafType, row.stale.actual)}`
|
|
9647
|
+
row.stale.actual === void 0 ? "stale — source no longer has this entry" : `stale — source actually has ${formatLeafValue(row.leafType, row.stale.actual, words)}`
|
|
9296
9648
|
] }),
|
|
9297
9649
|
annotation && /* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "11px", color: `${annotation.tone}.700`, fontWeight: 500, children: annotation.text })
|
|
9298
9650
|
] }),
|
|
@@ -9301,13 +9653,13 @@ const DiffRow = React.memo(function DiffRow2({ row, depth, bindingPathStr, showA
|
|
|
9301
9653
|
row.before !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(Chip$1, { fontSize: metrics.chipFontSize, children: [
|
|
9302
9654
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", color: "fg.danger", children: /* @__PURE__ */ jsxRuntime.jsx(FontAwesomeIcon, { icon: faMinus }) }),
|
|
9303
9655
|
" ",
|
|
9304
|
-
formatLeafValue(row.leafType, row.before)
|
|
9656
|
+
formatLeafValue(row.leafType, row.before, words)
|
|
9305
9657
|
] }),
|
|
9306
9658
|
row.before !== void 0 && row.after !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", color: "fg.subtle", fontSize: "11px", children: /* @__PURE__ */ jsxRuntime.jsx(FontAwesomeIcon, { icon: faArrowRight }) }),
|
|
9307
9659
|
row.after !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(Chip$1, { fontSize: metrics.chipFontSize, children: [
|
|
9308
9660
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", color: "fg.success", children: /* @__PURE__ */ jsxRuntime.jsx(FontAwesomeIcon, { icon: faPlus }) }),
|
|
9309
9661
|
" ",
|
|
9310
|
-
formatLeafValue(row.leafType, row.after)
|
|
9662
|
+
formatLeafValue(row.leafType, row.after, words)
|
|
9311
9663
|
] })
|
|
9312
9664
|
] }),
|
|
9313
9665
|
showActions && /* @__PURE__ */ jsxRuntime.jsx(ActionBtn, { icon: faXmark, title: "Discard this change", onClick: handleDiscard, size: metrics.actionBtnSize })
|
|
@@ -9316,9 +9668,11 @@ const DiffRow = React.memo(function DiffRow2({ row, depth, bindingPathStr, showA
|
|
|
9316
9668
|
}
|
|
9317
9669
|
);
|
|
9318
9670
|
});
|
|
9671
|
+
const REMOVED = "(removed)";
|
|
9319
9672
|
const ConflictRow = React.memo(function ConflictRow2({ row, depth, bindingPathStr, serverValue, resolution, onResolve, metrics }) {
|
|
9320
|
-
const
|
|
9321
|
-
const
|
|
9673
|
+
const words = eastUiComponents.useFormatters();
|
|
9674
|
+
const yoursStr = row.after === void 0 ? REMOVED : formatLeafValue(row.leafType, row.after, words);
|
|
9675
|
+
const theirsStr = serverValue === void 0 ? REMOVED : formatLeafValue(row.leafType, serverValue, words);
|
|
9322
9676
|
const isYours = (resolution == null ? void 0 : resolution.type) === "keepA";
|
|
9323
9677
|
const isTheirs = (resolution == null ? void 0 : resolution.type) === "keepB";
|
|
9324
9678
|
const isManual = (resolution == null ? void 0 : resolution.type) === "manual";
|
|
@@ -9384,7 +9738,7 @@ const ConflictRow = React.memo(function ConflictRow2({ row, depth, bindingPathSt
|
|
|
9384
9738
|
{
|
|
9385
9739
|
selected: isManual,
|
|
9386
9740
|
leafType: row.leafType,
|
|
9387
|
-
value:
|
|
9741
|
+
value: (resolution == null ? void 0 : resolution.type) === "manual" ? resolution.value : row.after,
|
|
9388
9742
|
onChange: handleManual
|
|
9389
9743
|
}
|
|
9390
9744
|
)
|
|
@@ -9501,9 +9855,8 @@ function ManualEditor({
|
|
|
9501
9855
|
const fire = React.useCallback((parsed) => {
|
|
9502
9856
|
queueMicrotask(() => onChange2(parsed));
|
|
9503
9857
|
}, [onChange2]);
|
|
9504
|
-
if (!leafType) return null;
|
|
9505
9858
|
if (leafType.type === "Boolean") {
|
|
9506
|
-
const checked =
|
|
9859
|
+
const checked = value === true;
|
|
9507
9860
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9508
9861
|
react.Box,
|
|
9509
9862
|
{
|
|
@@ -9685,9 +10038,10 @@ const EastChakraDiff = React.memo(function EastChakraDiff2({ value }) {
|
|
|
9685
10038
|
const [conflicts, setConflicts] = React.useState(null);
|
|
9686
10039
|
const [resolutions, setResolutions] = React.useState(/* @__PURE__ */ new Map());
|
|
9687
10040
|
const [committing, setCommitting] = React.useState(false);
|
|
10041
|
+
const data4 = eastUiComponents.useDataStable(value, diffValueDataEqual);
|
|
9688
10042
|
const irBindings = React.useMemo(
|
|
9689
|
-
() =>
|
|
9690
|
-
[
|
|
10043
|
+
() => data4.bindings ?? [],
|
|
10044
|
+
[data4.bindings]
|
|
9691
10045
|
);
|
|
9692
10046
|
const interactive = !(getOpt$1(value.readonly) ?? false);
|
|
9693
10047
|
const onCommittedFn = getOpt$1(value.onCommitted);
|
|
@@ -9721,7 +10075,7 @@ const EastChakraDiff = React.memo(function EastChakraDiff2({ value }) {
|
|
|
9721
10075
|
React.useEffect(() => {
|
|
9722
10076
|
setConflicts(null);
|
|
9723
10077
|
setResolutions(/* @__PURE__ */ new Map());
|
|
9724
|
-
}, [
|
|
10078
|
+
}, [data4, stagedVersion, datasetVersion]);
|
|
9725
10079
|
const visibleBindings = React.useMemo(
|
|
9726
10080
|
() => bindings.filter((b2) => b2.leaves.length > 0),
|
|
9727
10081
|
[bindings]
|
|
@@ -23100,13 +23454,13 @@ var hashIterableInts = function hashIterableInts2(iterator) {
|
|
|
23100
23454
|
}
|
|
23101
23455
|
return hash2;
|
|
23102
23456
|
};
|
|
23103
|
-
var hashInt = function hashInt2(
|
|
23457
|
+
var hashInt = function hashInt2(num) {
|
|
23104
23458
|
var seed = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_HASH_SEED;
|
|
23105
|
-
return seed * K +
|
|
23459
|
+
return seed * K + num | 0;
|
|
23106
23460
|
};
|
|
23107
|
-
var hashIntAlt = function hashIntAlt2(
|
|
23461
|
+
var hashIntAlt = function hashIntAlt2(num) {
|
|
23108
23462
|
var seed = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_HASH_SEED_ALT;
|
|
23109
|
-
return (seed << 5) + seed +
|
|
23463
|
+
return (seed << 5) + seed + num | 0;
|
|
23110
23464
|
};
|
|
23111
23465
|
var combineHashes = function combineHashes2(hash1, hash2) {
|
|
23112
23466
|
return hash1 * 2097152 + hash2;
|
|
@@ -23136,7 +23490,7 @@ var hashIntsArray = function hashIntsArray2(ints, seed) {
|
|
|
23136
23490
|
};
|
|
23137
23491
|
return hashIterableInts(iterator, seed);
|
|
23138
23492
|
};
|
|
23139
|
-
var hashString
|
|
23493
|
+
var hashString = function hashString2(str, seed) {
|
|
23140
23494
|
var entry = {
|
|
23141
23495
|
value: 0,
|
|
23142
23496
|
done: false
|
|
@@ -23163,9 +23517,9 @@ var hashStringsArray = function hashStringsArray2(strs) {
|
|
|
23163
23517
|
for (var i = 0; i < strs.length; i++) {
|
|
23164
23518
|
var str = strs[i];
|
|
23165
23519
|
if (i === 0) {
|
|
23166
|
-
hash2 = hashString
|
|
23520
|
+
hash2 = hashString(str);
|
|
23167
23521
|
} else {
|
|
23168
|
-
hash2 = hashString
|
|
23522
|
+
hash2 = hashString(str, hash2);
|
|
23169
23523
|
}
|
|
23170
23524
|
}
|
|
23171
23525
|
return hash2;
|
|
@@ -30303,7 +30657,7 @@ var cache = function cache2(fn3, name) {
|
|
|
30303
30657
|
var _p = eles[0]._private;
|
|
30304
30658
|
var tch = _p.traversalCache = _p.traversalCache || {};
|
|
30305
30659
|
var ch = tch[name] = tch[name] || [];
|
|
30306
|
-
var hash2 = hashString
|
|
30660
|
+
var hash2 = hashString(key);
|
|
30307
30661
|
var cacheHit = ch[hash2];
|
|
30308
30662
|
if (cacheHit) {
|
|
30309
30663
|
return cacheHit;
|
|
@@ -32909,13 +33263,13 @@ function styleCache(key, fn3, ele) {
|
|
|
32909
33263
|
}
|
|
32910
33264
|
}
|
|
32911
33265
|
function cacheStyleFunction(key, fn3) {
|
|
32912
|
-
key = hashString
|
|
33266
|
+
key = hashString(key);
|
|
32913
33267
|
return function cachedStyleFunction(ele) {
|
|
32914
33268
|
return styleCache(key, fn3, ele);
|
|
32915
33269
|
};
|
|
32916
33270
|
}
|
|
32917
33271
|
function cachePrototypeStyleFunction(key, fn3) {
|
|
32918
|
-
key = hashString
|
|
33272
|
+
key = hashString(key);
|
|
32919
33273
|
var selfFn = function selfFn2(ele) {
|
|
32920
33274
|
return fn3.call(ele);
|
|
32921
33275
|
};
|
|
@@ -43186,7 +43540,7 @@ BRp$9.applyLabelDimensions = function(ele) {
|
|
|
43186
43540
|
BRp$9.applyPrefixedLabelDimensions = function(ele, prefix2) {
|
|
43187
43541
|
var _p = ele._private;
|
|
43188
43542
|
var text = this.getLabelText(ele, prefix2);
|
|
43189
|
-
var cacheKey = hashString
|
|
43543
|
+
var cacheKey = hashString(text, ele._private.labelDimsKey);
|
|
43190
43544
|
if (getPrefixedProperty(_p.rscratch, "prefixedLabelDimsKey", prefix2) === cacheKey) {
|
|
43191
43545
|
return;
|
|
43192
43546
|
}
|
|
@@ -47582,7 +47936,7 @@ CRp$9.drawArrowShape = function(edge, context, fill, edgeWidth, shape, shapeWidt
|
|
|
47582
47936
|
var shapeImpl = r2.arrowShapes[shape];
|
|
47583
47937
|
if (usePaths) {
|
|
47584
47938
|
var cache3 = r2.arrowPathCache = r2.arrowPathCache || [];
|
|
47585
|
-
var key = hashString
|
|
47939
|
+
var key = hashString(shape);
|
|
47586
47940
|
var cachedPath = cache3[key];
|
|
47587
47941
|
if (cachedPath != null) {
|
|
47588
47942
|
path2 = context = cachedPath;
|
|
@@ -57964,7 +58318,7 @@ function useBindingValue(binding) {
|
|
|
57964
58318
|
try {
|
|
57965
58319
|
return { value: handle.read(), pending: handle.pending(), error: void 0 };
|
|
57966
58320
|
} catch (e3) {
|
|
57967
|
-
console.error(`[Experiment] failed to read binding "${
|
|
58321
|
+
console.error(`[Experiment] failed to read binding "${e3Types.pathToString(sourcePath)}":`, e3);
|
|
57968
58322
|
return { value: null, pending: false, error: e3 };
|
|
57969
58323
|
}
|
|
57970
58324
|
}, [handle, version2]);
|
|
@@ -57980,20 +58334,25 @@ function useBindingValue(binding) {
|
|
|
57980
58334
|
}, [handle]);
|
|
57981
58335
|
return { value, mode, pending, error: error3, mutate, commit, discard };
|
|
57982
58336
|
}
|
|
58337
|
+
function sameType(a2, b2) {
|
|
58338
|
+
return east.isTypeValueEqual(east.toEastTypeValue(a2), east.toEastTypeValue(b2));
|
|
58339
|
+
}
|
|
58340
|
+
function sameSignature(a2, b2) {
|
|
58341
|
+
const ai = a2.inputs;
|
|
58342
|
+
const bi = b2.inputs;
|
|
58343
|
+
return sameType(a2.output, b2.output) && (ai === null || bi === null ? ai === bi : ai.length === bi.length && ai.every((t4, i) => sameType(t4, bi[i])));
|
|
58344
|
+
}
|
|
57983
58345
|
const IDLE = { call: () => {
|
|
57984
58346
|
}, result: null, status: "idle", pending: false, error: null };
|
|
57985
58347
|
function useFuncCall(name, inputs, output2) {
|
|
57986
58348
|
const workspace = getReactiveDatasetCache().getConfig().workspace ?? "";
|
|
57987
58349
|
const ready4 = !!name && !!inputs && workspace !== "";
|
|
57988
|
-
const
|
|
57989
|
-
() => ready4 ? JSON.stringify([inputs.map((t4) => east.toEastTypeValue(t4)), east.toEastTypeValue(output2)]) : "",
|
|
57990
|
-
[ready4, inputs, output2]
|
|
57991
|
-
);
|
|
58350
|
+
const signature = eastUiComponents.useDataStable({ inputs, output: output2 }, sameSignature);
|
|
57992
58351
|
const handle = React.useMemo(() => {
|
|
57993
|
-
if (!ready4) return null;
|
|
57994
|
-
const handleType = east.toEastTypeValue(internal$1.FuncBindHandleType(inputs,
|
|
58352
|
+
if (!ready4 || signature.inputs === null) return null;
|
|
58353
|
+
const handleType = east.toEastTypeValue(internal$1.FuncBindHandleType(signature.inputs, signature.output));
|
|
57995
58354
|
return defaultFuncRuntime.buildHandle(handleType, name);
|
|
57996
|
-
}, [ready4, name, workspace,
|
|
58355
|
+
}, [ready4, name, workspace, signature]);
|
|
57997
58356
|
const channelKey = ready4 ? funcChannelKey(workspace, name) : "";
|
|
57998
58357
|
const version2 = React.useSyncExternalStore(
|
|
57999
58358
|
React.useCallback(
|
|
@@ -58004,7 +58363,6 @@ function useFuncCall(name, inputs, output2) {
|
|
|
58004
58363
|
React.useCallback(() => channelKey ? defaultFuncRuntime.getKeyVersion(channelKey) : 0, [channelKey])
|
|
58005
58364
|
);
|
|
58006
58365
|
return React.useMemo(() => {
|
|
58007
|
-
var _a2;
|
|
58008
58366
|
if (!handle) return IDLE;
|
|
58009
58367
|
let result = null;
|
|
58010
58368
|
let status = "idle";
|
|
@@ -58016,10 +58374,7 @@ function useFuncCall(name, inputs, output2) {
|
|
|
58016
58374
|
status = handle.status().type;
|
|
58017
58375
|
pending = handle.pending();
|
|
58018
58376
|
const err = handle.error();
|
|
58019
|
-
if (err.type === "some")
|
|
58020
|
-
const v3 = err.value;
|
|
58021
|
-
error3 = { kind: ((_a2 = v3.kind) == null ? void 0 : _a2.type) ?? "failed", message: v3.message ?? "", stdout: v3.stdout ?? "", stderr: v3.stderr ?? "" };
|
|
58022
|
-
}
|
|
58377
|
+
if (err.type === "some") error3 = err.value;
|
|
58023
58378
|
} catch {
|
|
58024
58379
|
}
|
|
58025
58380
|
return { call: (...args) => {
|
|
@@ -60637,207 +60992,14 @@ function GuidanceToggle({ on: on3, onToggle }) {
|
|
|
60637
60992
|
}
|
|
60638
60993
|
) });
|
|
60639
60994
|
}
|
|
60640
|
-
function ChartLabel({ x: x2, y: y2, w: w2, align, size: size3, weight: weight8, color: color2, family, help, children: children2 }) {
|
|
60641
|
-
const span = /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: `${size3}px`, fontFamily: family, fontWeight: weight8, color: color2, lineHeight: 1, whiteSpace: "nowrap" }, children: children2 });
|
|
60642
|
-
return /* @__PURE__ */ jsxRuntime.jsx("foreignObject", { x: x2, y: y2, width: w2, height: size3 + 6, style: { overflow: "visible" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: align, fontSize: `${size3}px`, lineHeight: 1 }, children: help ? /* @__PURE__ */ jsxRuntime.jsx(Help, { id: help, children: span }) : span }) });
|
|
60643
|
-
}
|
|
60644
|
-
function svgText(size3, fill, family, weight8) {
|
|
60645
|
-
return { fontSize: `${size3}px`, fill, fontFamily: family, ...weight8 !== void 0 ? { fontWeight: weight8 } : {} };
|
|
60646
|
-
}
|
|
60647
|
-
function useMeasuredWidth() {
|
|
60648
|
-
const ref = React.useRef(null);
|
|
60649
|
-
const [w2, setW] = React.useState(0);
|
|
60650
|
-
React.useLayoutEffect(() => {
|
|
60651
|
-
const el = ref.current;
|
|
60652
|
-
if (!el) return;
|
|
60653
|
-
const update2 = () => setW(el.clientWidth);
|
|
60654
|
-
update2();
|
|
60655
|
-
const ro = new ResizeObserver(update2);
|
|
60656
|
-
ro.observe(el);
|
|
60657
|
-
return () => ro.disconnect();
|
|
60658
|
-
}, []);
|
|
60659
|
-
return [ref, w2];
|
|
60660
|
-
}
|
|
60661
|
-
function useChartTheme() {
|
|
60662
|
-
const system = react.useChakraContext();
|
|
60663
|
-
const tok = (k2, fallback) => system.token(k2, fallback);
|
|
60664
|
-
const tones = {
|
|
60665
|
-
neg: tok("colors.fg.danger", "#b85a4a"),
|
|
60666
|
-
pos: tok("colors.fg.success", "#2f7a5b"),
|
|
60667
|
-
warn: tok("colors.fg.warning", "#b8862d"),
|
|
60668
|
-
muted: tok("colors.fg.muted", "#6b8080"),
|
|
60669
|
-
brand: tok("colors.brand.solid", "#3a7780")
|
|
60670
|
-
};
|
|
60671
|
-
return {
|
|
60672
|
-
mono: tok("fonts.mono", '"JetBrains Mono", ui-monospace, monospace'),
|
|
60673
|
-
body: tok("fonts.body", "system-ui, -apple-system, sans-serif"),
|
|
60674
|
-
ink: tok("colors.fg", "#111b22"),
|
|
60675
|
-
muted: tones.muted,
|
|
60676
|
-
faint: tok("colors.fg.subtle", "#9bb0b0"),
|
|
60677
|
-
rule: tok("colors.border.subtle", "#e2e8e8"),
|
|
60678
|
-
ruleStrong: tok("colors.border.strong", "#cbd5d5"),
|
|
60679
|
-
surface: tok("colors.bg.surface", "#ffffff"),
|
|
60680
|
-
tone: (t4) => tones[t4] ?? tones.brand,
|
|
60681
|
-
labelSize: 10,
|
|
60682
|
-
titleSize: 11,
|
|
60683
|
-
lineWidth: 1.8,
|
|
60684
|
-
barWidth: 2.5,
|
|
60685
|
-
dotRadius: 2.6,
|
|
60686
|
-
scatterRadius: 3.4,
|
|
60687
|
-
areaOpacity: 0.16
|
|
60688
|
-
};
|
|
60689
|
-
}
|
|
60690
|
-
const fmt$2 = (n2) => Number.isInteger(n2) ? String(n2) : n2.toFixed(1);
|
|
60691
|
-
const signed$1 = (n2) => (n2 > 0 ? "+" : "") + fmt$2(n2);
|
|
60692
|
-
const niceCeil = (v3) => {
|
|
60693
|
-
if (v3 <= 1e-9) return 0;
|
|
60694
|
-
const mag = Math.pow(10, Math.floor(Math.log10(v3)));
|
|
60695
|
-
const n2 = v3 / mag;
|
|
60696
|
-
const step3 = n2 <= 1 ? 1 : n2 <= 1.5 ? 1.5 : n2 <= 2 ? 2 : n2 <= 3 ? 3 : n2 <= 4 ? 4 : n2 <= 5 ? 5 : n2 <= 6 ? 6 : n2 <= 8 ? 8 : 10;
|
|
60697
|
-
return step3 * mag;
|
|
60698
|
-
};
|
|
60699
|
-
function ForestPlot({ rows, min: min4, max: max5, unit: unit2, height: height2, rowHelp }) {
|
|
60700
|
-
const t4 = useChartTheme();
|
|
60701
|
-
const [ref, w2] = useMeasuredWidth();
|
|
60702
|
-
const n2 = rows.length;
|
|
60703
|
-
const hPx = height2 ?? 26 + n2 * 38;
|
|
60704
|
-
const padL = 124, padR = 46, padT = 20, padB = 30;
|
|
60705
|
-
const innerW = Math.max(0, w2 - padL - padR);
|
|
60706
|
-
const innerH = hPx - padT - padB;
|
|
60707
|
-
const x2 = createLinearScale({ domain: [min4, max5], range: [0, innerW] });
|
|
60708
|
-
const rowH = innerH / Math.max(1, n2);
|
|
60709
|
-
const zeroX = Math.max(0, Math.min(innerW, x2(0)));
|
|
60710
|
-
const frac = (v3) => max5 > min4 ? (v3 - min4) / (max5 - min4) : 0.5;
|
|
60711
|
-
const anchorAt = (v3) => frac(v3) < 0.06 ? "start" : frac(v3) > 0.94 ? "end" : "middle";
|
|
60712
|
-
const zf = frac(0);
|
|
60713
|
-
const ticks2 = zf > 0.12 && zf < 0.88 ? [min4, 0, max5] : [min4, max5];
|
|
60714
|
-
return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { ref, width: "100%", height: `${hPx}px`, children: w2 > 0 && /* @__PURE__ */ jsxRuntime.jsx("svg", { width: w2, height: hPx, style: { display: "block" }, children: /* @__PURE__ */ jsxRuntime.jsxs(Group, { left: padL, top: padT, children: [
|
|
60715
|
-
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: zeroX, y: -4 }, to: { x: zeroX, y: innerH }, stroke: t4.muted, strokeWidth: 1, strokeDasharray: "3 2" }),
|
|
60716
|
-
/* @__PURE__ */ jsxRuntime.jsx("text", { x: zeroX, y: -6, textAnchor: anchorAt(0), style: svgText(t4.labelSize, t4.muted, t4.mono), children: "no effect" }),
|
|
60717
|
-
rows.map((r2, i) => {
|
|
60718
|
-
const cy = rowH * i + rowH / 2;
|
|
60719
|
-
const col = t4.tone(r2.tone);
|
|
60720
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Group, { top: cy, children: [
|
|
60721
|
-
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: x2(r2.lo), y: 0 }, to: { x: x2(r2.hi), y: 0 }, stroke: col, strokeWidth: t4.barWidth, strokeOpacity: 0.9, strokeLinecap: "round" }),
|
|
60722
|
-
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: x2(r2.lo), y: -4 }, to: { x: x2(r2.lo), y: 4 }, stroke: col, strokeWidth: 1.5 }),
|
|
60723
|
-
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: x2(r2.hi), y: -4 }, to: { x: x2(r2.hi), y: 4 }, stroke: col, strokeWidth: 1.5 }),
|
|
60724
|
-
/* @__PURE__ */ jsxRuntime.jsx(Circle, { cx: x2(r2.est), cy: 0, r: t4.scatterRadius, fill: col, stroke: t4.surface, strokeWidth: 1.8 }),
|
|
60725
|
-
/* @__PURE__ */ jsxRuntime.jsx(ChartLabel, { x: -padL + 2, y: -13, w: padL - 6, align: "left", size: t4.labelSize, weight: 600, color: t4.ink, family: t4.body, ...(rowHelp == null ? void 0 : rowHelp[i]) ? { help: rowHelp[i] } : {}, children: r2.label }),
|
|
60726
|
-
r2.note && /* @__PURE__ */ jsxRuntime.jsx("text", { x: -padL + 2, y: 9, style: svgText(9, t4.faint, t4.body), children: r2.note }),
|
|
60727
|
-
/* @__PURE__ */ jsxRuntime.jsx("text", { x: innerW + padR - 2, y: 4, textAnchor: "end", style: svgText(t4.titleSize, col, t4.mono, 700), children: signed$1(r2.est) })
|
|
60728
|
-
] }, i);
|
|
60729
|
-
}),
|
|
60730
|
-
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: innerH }, to: { x: innerW, y: innerH }, stroke: t4.rule, strokeWidth: 1 }),
|
|
60731
|
-
ticks2.map((tk, i) => /* @__PURE__ */ jsxRuntime.jsxs(Group, { left: Math.max(0, Math.min(innerW, x2(tk))), children: [
|
|
60732
|
-
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: innerH }, to: { x: 0, y: innerH + 4 }, stroke: t4.ruleStrong, strokeWidth: 1 }),
|
|
60733
|
-
/* @__PURE__ */ jsxRuntime.jsx("text", { x: 0, y: innerH + 14, textAnchor: anchorAt(tk), style: svgText(t4.labelSize, t4.muted, t4.mono), children: signed$1(tk) })
|
|
60734
|
-
] }, `t${i}`)),
|
|
60735
|
-
unit2 && /* @__PURE__ */ jsxRuntime.jsx("text", { x: innerW / 2, y: innerH + 26, textAnchor: "middle", style: svgText(t4.labelSize, t4.muted, t4.mono), children: unit2 })
|
|
60736
|
-
] }) }) });
|
|
60737
|
-
}
|
|
60738
|
-
function AreaRange({ lo: lo2, mid, hi, xTicks = [], yTicks = [], zero: zero2, tone: toneName, marks = [], height: height2, yFormat = "signed" }) {
|
|
60739
|
-
const t4 = useChartTheme();
|
|
60740
|
-
const [ref, w2] = useMeasuredWidth();
|
|
60741
|
-
const hPx = height2 ?? 100;
|
|
60742
|
-
const col = t4.tone(toneName ?? "brand");
|
|
60743
|
-
const padL = yTicks.length ? 52 : 6;
|
|
60744
|
-
const padR = 12;
|
|
60745
|
-
const padT = marks.length ? 22 : 8;
|
|
60746
|
-
const padB = xTicks.length ? 22 : 12;
|
|
60747
|
-
const innerW = Math.max(0, w2 - padL - padR);
|
|
60748
|
-
const innerH = hPx - padT - padB;
|
|
60749
|
-
const xScale = createLinearScale({ domain: [0, Math.max(1, mid.length - 1)], range: [0, innerW] });
|
|
60750
|
-
const fin = (x2, fallback) => typeof x2 === "number" && Number.isFinite(x2) ? x2 : fallback;
|
|
60751
|
-
const data4 = mid.map((m2, i) => {
|
|
60752
|
-
const mm = fin(m2, 0);
|
|
60753
|
-
return { i, lo: fin(lo2[i], mm), hi: fin(hi[i], mm), mid: mm };
|
|
60754
|
-
});
|
|
60755
|
-
const dataMin = Math.min(...data4.map((d2) => d2.lo), zero2 ?? Infinity);
|
|
60756
|
-
const dataMax = Math.max(...data4.map((d2) => d2.hi), zero2 ?? -Infinity);
|
|
60757
|
-
const yHiN = niceCeil(Math.max(dataMax, 0));
|
|
60758
|
-
const yLoN = dataMin < -0.08 * yHiN ? -niceCeil(-dataMin) : 0;
|
|
60759
|
-
const yScale = createLinearScale({ domain: [yLoN, yHiN], range: [innerH, 0] });
|
|
60760
|
-
const yfmt = (v3) => yFormat === "percent" ? `${Math.round(v3)}%` : signed$1(v3);
|
|
60761
|
-
const yLabels = [yfmt(yHiN), yfmt((yHiN + yLoN) / 2), yfmt(yLoN)];
|
|
60762
|
-
return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { ref, width: "100%", height: `${hPx}px`, children: w2 > 0 && /* @__PURE__ */ jsxRuntime.jsx("svg", { width: w2, height: hPx, style: { display: "block" }, children: /* @__PURE__ */ jsxRuntime.jsxs(Group, { left: padL, top: padT, children: [
|
|
60763
|
-
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: 0 }, to: { x: 0, y: innerH }, stroke: t4.rule, strokeWidth: 1 }),
|
|
60764
|
-
yTicks.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
60765
|
-
/* @__PURE__ */ jsxRuntime.jsx("text", { x: -8, y: 10, textAnchor: "end", style: svgText(t4.labelSize, t4.muted, t4.mono), children: yLabels[0] }),
|
|
60766
|
-
/* @__PURE__ */ jsxRuntime.jsx("text", { x: -8, y: innerH / 2 + 3, textAnchor: "end", style: svgText(t4.labelSize, t4.muted, t4.mono), children: yLabels[1] }),
|
|
60767
|
-
/* @__PURE__ */ jsxRuntime.jsx("text", { x: -8, y: innerH - 1, textAnchor: "end", style: svgText(t4.labelSize, t4.muted, t4.mono), children: yLabels[2] })
|
|
60768
|
-
] }),
|
|
60769
|
-
zero2 != null && /* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: yScale(zero2) }, to: { x: innerW, y: yScale(zero2) }, stroke: t4.muted, strokeWidth: 1, strokeDasharray: "3 2" }),
|
|
60770
|
-
/* @__PURE__ */ jsxRuntime.jsx(Area, { data: data4, x: (d2) => xScale(d2.i), y0: (d2) => yScale(d2.lo), y1: (d2) => yScale(d2.hi), curve: monotoneX, fill: col, fillOpacity: t4.areaOpacity, stroke: "transparent" }),
|
|
60771
|
-
/* @__PURE__ */ jsxRuntime.jsx(LinePath, { data: data4, x: (d2) => xScale(d2.i), y: (d2) => yScale(d2.mid), curve: monotoneX, stroke: col, strokeWidth: t4.lineWidth }),
|
|
60772
|
-
marks.map((m2, i) => {
|
|
60773
|
-
const mc = t4.tone(m2.tone);
|
|
60774
|
-
const dotY = yScale(fin(mid[m2.at], 0));
|
|
60775
|
-
const labY = Math.max(9, dotY - 9);
|
|
60776
|
-
const atEnd = m2.at >= mid.length - 2;
|
|
60777
|
-
const atStart = m2.at <= 1;
|
|
60778
|
-
const align = atEnd ? "right" : atStart ? "left" : "center";
|
|
60779
|
-
const labW = m2.label.length * 6.5 + 8;
|
|
60780
|
-
const labX = atEnd ? -labW - 5 : atStart ? 5 : -labW / 2;
|
|
60781
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Group, { left: xScale(m2.at), children: [
|
|
60782
|
-
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: -2 }, to: { x: 0, y: innerH }, stroke: mc, strokeWidth: 1, strokeDasharray: "2 3" }),
|
|
60783
|
-
/* @__PURE__ */ jsxRuntime.jsx(Circle, { cx: 0, cy: dotY, r: t4.dotRadius, fill: mc, stroke: t4.surface, strokeWidth: 1.5 }),
|
|
60784
|
-
/* @__PURE__ */ jsxRuntime.jsx(ChartLabel, { x: labX, y: labY - 11, w: labW, align, size: t4.labelSize, weight: 500, color: mc, family: t4.body, ...m2.help ? { help: m2.help } : {}, children: m2.label })
|
|
60785
|
-
] }, `mk${i}`);
|
|
60786
|
-
}),
|
|
60787
|
-
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: innerH }, to: { x: innerW, y: innerH }, stroke: t4.rule, strokeWidth: 1 }),
|
|
60788
|
-
xTicks.map((tk, i) => {
|
|
60789
|
-
const word = Number.isNaN(Number(tk));
|
|
60790
|
-
return /* @__PURE__ */ jsxRuntime.jsx("text", { x: innerW * i / Math.max(1, xTicks.length - 1), y: innerH + 14, textAnchor: i === 0 ? "start" : i === xTicks.length - 1 ? "end" : "middle", style: svgText(word ? 9 : t4.labelSize, word ? t4.faint : t4.muted, word ? t4.body : t4.mono), children: tk }, `x${i}`);
|
|
60791
|
-
})
|
|
60792
|
-
] }) }) });
|
|
60793
|
-
}
|
|
60794
|
-
function OverlapHistogram({ treated, control, domain = [0, 1], supportLabel, positivityOk, height: height2 }) {
|
|
60795
|
-
const t4 = useChartTheme();
|
|
60796
|
-
const [ref, w2] = useMeasuredWidth();
|
|
60797
|
-
const hPx = height2 ?? 150;
|
|
60798
|
-
const padL = 8, padR = 8, padT = 16, padB = 26;
|
|
60799
|
-
const innerW = Math.max(0, w2 - padL - padR);
|
|
60800
|
-
const innerH = hPx - padT - padB;
|
|
60801
|
-
const centerY = innerH / 2;
|
|
60802
|
-
const halfH = centerY - 4;
|
|
60803
|
-
const bins = Math.max(treated.length, control.length);
|
|
60804
|
-
const x2 = createLinearScale({ domain, range: [0, innerW] });
|
|
60805
|
-
const span = domain[1] - domain[0];
|
|
60806
|
-
const binW = bins > 0 ? innerW / bins : innerW;
|
|
60807
|
-
const barW = Math.max(1, binW * 0.78);
|
|
60808
|
-
const maxVal = Math.max(1e-9, ...treated, ...control);
|
|
60809
|
-
const tCol = t4.tone("pos");
|
|
60810
|
-
const cCol = t4.tone("muted");
|
|
60811
|
-
const ticks2 = [domain[0], (domain[0] + domain[1]) / 2, domain[1]];
|
|
60812
|
-
const cx2 = (i) => x2(domain[0] + (i + 0.5) / bins * span);
|
|
60813
|
-
return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { ref, width: "100%", height: `${hPx}px`, children: w2 > 0 && /* @__PURE__ */ jsxRuntime.jsx("svg", { width: w2, height: hPx, style: { display: "block" }, children: /* @__PURE__ */ jsxRuntime.jsxs(Group, { left: padL, top: padT, children: [
|
|
60814
|
-
/* @__PURE__ */ jsxRuntime.jsx("text", { x: 0, y: -4, style: svgText(9, t4.faint, t4.body), children: "treated ↑" }),
|
|
60815
|
-
supportLabel && /* @__PURE__ */ jsxRuntime.jsx("text", { x: innerW, y: -4, textAnchor: "end", style: svgText(t4.labelSize, positivityOk ? t4.tone("pos") : t4.tone("warn"), t4.mono, 600), children: supportLabel }),
|
|
60816
|
-
Array.from({ length: bins }, (_2, i) => {
|
|
60817
|
-
const ht = Number(treated[i] ?? 0) / maxVal * halfH;
|
|
60818
|
-
const hc = Number(control[i] ?? 0) / maxVal * halfH;
|
|
60819
|
-
const left = cx2(i) - barW / 2;
|
|
60820
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Group, { children: [
|
|
60821
|
-
ht > 0 && /* @__PURE__ */ jsxRuntime.jsx("rect", { x: left, y: centerY - ht, width: barW, height: ht, fill: tCol, fillOpacity: 0.85, rx: 0.5 }),
|
|
60822
|
-
hc > 0 && /* @__PURE__ */ jsxRuntime.jsx("rect", { x: left, y: centerY, width: barW, height: hc, fill: cCol, fillOpacity: 0.6, rx: 0.5 })
|
|
60823
|
-
] }, i);
|
|
60824
|
-
}),
|
|
60825
|
-
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: centerY }, to: { x: innerW, y: centerY }, stroke: t4.ruleStrong, strokeWidth: 1 }),
|
|
60826
|
-
/* @__PURE__ */ jsxRuntime.jsx("text", { x: 0, y: innerH + 4, style: svgText(9, t4.faint, t4.body), children: "untreated ↓" }),
|
|
60827
|
-
ticks2.map((tk, i) => /* @__PURE__ */ jsxRuntime.jsx("text", { x: x2(tk), y: innerH + 16, textAnchor: i === 0 ? "start" : i === ticks2.length - 1 ? "end" : "middle", style: svgText(t4.labelSize, t4.muted, t4.mono), children: fmt$2(tk) }, `x${i}`))
|
|
60828
|
-
] }) }) });
|
|
60829
|
-
}
|
|
60830
60995
|
const arr = (v3) => v3 ? Array.from(v3, Number) : [];
|
|
60831
60996
|
const arrI = (v3) => v3 ? Array.from(v3, Number) : [];
|
|
60832
|
-
const
|
|
60833
|
-
|
|
60834
|
-
|
|
60835
|
-
|
|
60836
|
-
const signed = (x2) => {
|
|
60837
|
-
const f2 = fmt$1(x2);
|
|
60838
|
-
return f2 === "0" || f2 === "0.0" || f2.startsWith("-") ? f2 : `+${f2}`;
|
|
60839
|
-
};
|
|
60997
|
+
const ONE_DECIMAL = east.variant("number", { minimumFractionDigits: east.some(1n), maximumFractionDigits: east.some(1n), signDisplay: east.none });
|
|
60998
|
+
const formatOf = (x2) => Number.isInteger(x2) ? void 0 : ONE_DECIMAL;
|
|
60999
|
+
const fmt$1 = (x2, words) => words.value(Math.abs(x2) < 0.05 ? 0 : x2, formatOf(x2));
|
|
61000
|
+
const signed = (x2, words) => words.value(x2, formatOf(x2), true);
|
|
60840
61001
|
const clamp01 = (x2) => x2 < 0 ? 0 : x2 > 1 ? 1 : x2;
|
|
61002
|
+
const compareFloats = east.compareFor(east.FloatType);
|
|
60841
61003
|
function band(absStd) {
|
|
60842
61004
|
if (absStd >= 0.66) return { level: "large gap", tone: "neg" };
|
|
60843
61005
|
if (absStd >= 0.33) return { level: "some", tone: "warn" };
|
|
@@ -60887,7 +61049,7 @@ function treatmentKind(cols, treatment) {
|
|
|
60887
61049
|
return "value";
|
|
60888
61050
|
}
|
|
60889
61051
|
}
|
|
60890
|
-
function deriveSpec(config2, cols, result, meta3, dataLen, subject) {
|
|
61052
|
+
function deriveSpec(config2, cols, result, meta3, dataLen, subject, words) {
|
|
60891
61053
|
const outUnit = unitOf(meta3, config2.outcome);
|
|
60892
61054
|
const balByCol = /* @__PURE__ */ new Map();
|
|
60893
61055
|
for (const b2 of (result == null ? void 0 : result.balance) ?? []) {
|
|
@@ -60925,24 +61087,24 @@ function deriveSpec(config2, cols, result, meta3, dataLen, subject) {
|
|
|
60925
61087
|
// n_total belongs to the Answer-tab counts strip; labelling the header
|
|
60926
61088
|
// with it desyncs from the data after a population edit (and reads
|
|
60927
61089
|
// wrong whenever the two legitimately differ).
|
|
60928
|
-
dataLabel: `${dataLen} ${subject.many}`
|
|
61090
|
+
dataLabel: `${words.number(dataLen)} ${subject.many}`
|
|
60929
61091
|
};
|
|
60930
61092
|
}
|
|
60931
|
-
function balanceDisplay(b2, categorical) {
|
|
61093
|
+
function balanceDisplay(b2, categorical, words) {
|
|
60932
61094
|
const isProp = categorical.has(b2.base_column) && b2.treated_mean >= 0 && b2.treated_mean <= 1 && b2.control_mean >= 0 && b2.control_mean <= 1;
|
|
60933
|
-
return isProp ? `${
|
|
61095
|
+
return isProp ? `${words.percent(b2.treated_mean)} vs ${words.percent(b2.control_mean)}` : `${words.value(b2.treated_mean, ONE_DECIMAL)} vs ${words.value(b2.control_mean, ONE_DECIMAL)}`;
|
|
60934
61096
|
}
|
|
60935
|
-
function deriveAnswer(config2, result, adj, meta3) {
|
|
61097
|
+
function deriveAnswer(config2, result, adj, meta3, words) {
|
|
60936
61098
|
const ci = eastUiComponents.getSomeorUndefined(adj.ci);
|
|
60937
61099
|
const nci = eastUiComponents.getSomeorUndefined(result.naive_ci);
|
|
60938
61100
|
const categorical = new Set(eastUiComponents.getSomeorUndefined(config2.categorical) ?? []);
|
|
60939
|
-
const balance = [...result.balance].sort((a2, b2) => Math.abs(b2.std_diff)
|
|
61101
|
+
const balance = [...result.balance].sort((a2, b2) => compareFloats(Math.abs(b2.std_diff), Math.abs(a2.std_diff))).map((b2) => ({
|
|
60940
61102
|
// One-hot rows are `col=level` — label the BASE confounder, keep the level.
|
|
60941
61103
|
col: b2.column,
|
|
60942
61104
|
label: b2.column === b2.base_column ? labelOf(meta3, b2.base_column) : `${labelOf(meta3, b2.base_column)}${b2.column.startsWith(b2.base_column) ? b2.column.slice(b2.base_column.length) : ` (${b2.column})`}`,
|
|
60943
61105
|
treated: b2.treated_mean,
|
|
60944
61106
|
control: b2.control_mean,
|
|
60945
|
-
display: balanceDisplay(b2, categorical),
|
|
61107
|
+
display: balanceDisplay(b2, categorical, words),
|
|
60946
61108
|
frac: clamp01(Math.abs(b2.std_diff)),
|
|
60947
61109
|
tone: band(Math.abs(b2.std_diff)).tone
|
|
60948
61110
|
}));
|
|
@@ -60973,12 +61135,12 @@ function deriveAnswer(config2, result, adj, meta3) {
|
|
|
60973
61135
|
balance
|
|
60974
61136
|
};
|
|
60975
61137
|
}
|
|
60976
|
-
function deriveNarrative(result, a2, refute, higherBetter, subject) {
|
|
61138
|
+
function deriveNarrative(result, a2, refute, higherBetter, subject, words) {
|
|
60977
61139
|
if (a2 === null) return null;
|
|
60978
61140
|
const unit2 = a2.unit ? ` ${a2.unit}` : "";
|
|
60979
61141
|
const dirUp = a2.effect > 0;
|
|
60980
61142
|
const verb = higherBetter === void 0 ? dirUp ? "raises" : "lowers" : dirUp === higherBetter ? "improves" : "worsens";
|
|
60981
|
-
const range = ` (likely between ${signed(a2.lo)} and ${signed(a2.hi)})`;
|
|
61143
|
+
const range = ` (likely between ${signed(a2.lo, words)} and ${signed(a2.hi, words)})`;
|
|
60982
61144
|
const passed = (refute == null ? void 0 : refute.checks.filter((c2) => c2.passed).length) ?? 0;
|
|
60983
61145
|
const total = (refute == null ? void 0 : refute.checks.length) ?? 0;
|
|
60984
61146
|
const trustClause = total === 0 ? "" : passed === total ? ` It held up against all ${total} ways we tried to break it.` : ` It passed ${passed} of ${total} stress tests — see “Can we trust it?”.`;
|
|
@@ -60989,13 +61151,13 @@ function deriveNarrative(result, a2, refute, higherBetter, subject) {
|
|
|
60989
61151
|
segments: [
|
|
60990
61152
|
{ text: "Yes — ", strong: true },
|
|
60991
61153
|
{ text: `${a2.treatment} genuinely ${verb} ${a2.outcome}: about ` },
|
|
60992
|
-
{ text: `${signed(a2.effect)}${unit2}`, strong: true },
|
|
61154
|
+
{ text: `${signed(a2.effect, words)}${unit2}`, strong: true },
|
|
60993
61155
|
{ text: ` per ${subject.one}${range}.${trustClause}` }
|
|
60994
61156
|
]
|
|
60995
61157
|
};
|
|
60996
61158
|
case "modest": {
|
|
60997
61159
|
const tags = new Set(result.verdict_reasons.map((v3) => v3.type));
|
|
60998
|
-
const why = tags.has("not_material") ? ` — the change (${signed(a2.effect)}${unit2}) is smaller than what would matter here (±${fmt$1(result.materiality_threshold)}${unit2}).` : tags.has("ci_spans_zero") ? ` — the likely range (${signed(a2.lo)} to ${signed(a2.hi)}) includes zero.` : tags.has("thin_support") ? " — too few treated and untreated look-alikes overlap to be confident." : tags.has("low_robustness") ? " — a fairly weak hidden factor could overturn it." : a2.lo <= 0 && a2.hi >= 0 ? ` — the likely range (${signed(a2.lo)} to ${signed(a2.hi)}) includes zero.` : ".";
|
|
61160
|
+
const why = tags.has("not_material") ? ` — the change (${signed(a2.effect, words)}${unit2}) is smaller than what would matter here (±${fmt$1(result.materiality_threshold, words)}${unit2}).` : tags.has("ci_spans_zero") ? ` — the likely range (${signed(a2.lo, words)} to ${signed(a2.hi, words)}) includes zero.` : tags.has("thin_support") ? " — too few treated and untreated look-alikes overlap to be confident." : tags.has("low_robustness") ? " — a fairly weak hidden factor could overturn it." : a2.lo <= 0 && a2.hi >= 0 ? ` — the likely range (${signed(a2.lo, words)} to ${signed(a2.hi, words)}) includes zero.` : ".";
|
|
60999
61161
|
return {
|
|
61000
61162
|
tone: "warn",
|
|
61001
61163
|
segments: [
|
|
@@ -61010,14 +61172,14 @@ function deriveNarrative(result, a2, refute, higherBetter, subject) {
|
|
|
61010
61172
|
tone: "warn",
|
|
61011
61173
|
segments: [
|
|
61012
61174
|
{ text: "Don’t act on this yet — ", strong: true },
|
|
61013
|
-
{ text: `we got a number (${signed(a2.effect)}${unit2}), but a stress test failed: something we didn’t adjust for may still be driving it.` }
|
|
61175
|
+
{ text: `we got a number (${signed(a2.effect, words)}${unit2}), but a stress test failed: something we didn’t adjust for may still be driving it.` }
|
|
61014
61176
|
]
|
|
61015
61177
|
};
|
|
61016
61178
|
default:
|
|
61017
61179
|
return null;
|
|
61018
61180
|
}
|
|
61019
61181
|
}
|
|
61020
|
-
function deriveRefusal(config2, result, meta3, subject) {
|
|
61182
|
+
function deriveRefusal(config2, result, meta3, subject, words) {
|
|
61021
61183
|
const nT = Number(result.n_treated), nC = Number(result.n_control), nTot = Number(result.n_total);
|
|
61022
61184
|
const treatment = labelOf(meta3, config2.treatment);
|
|
61023
61185
|
if (result.verdict.type === "not_estimable") {
|
|
@@ -61027,22 +61189,22 @@ function deriveRefusal(config2, result, meta3, subject) {
|
|
|
61027
61189
|
title: `Can’t estimate the effect of ${treatment}`,
|
|
61028
61190
|
body: reason,
|
|
61029
61191
|
evidence: [
|
|
61030
|
-
{ label: "treated", value:
|
|
61031
|
-
{ label: "untreated", value:
|
|
61032
|
-
{ label: subject.many, value:
|
|
61192
|
+
{ label: "treated", value: words.number(nT) },
|
|
61193
|
+
{ label: "untreated", value: words.number(nC) },
|
|
61194
|
+
{ label: subject.many, value: words.number(nTot) }
|
|
61033
61195
|
]
|
|
61034
61196
|
};
|
|
61035
61197
|
}
|
|
61036
61198
|
if (result.verdict.type === "non_identifiable_positivity") {
|
|
61037
|
-
const pct =
|
|
61199
|
+
const pct = words.percent(result.overlap.common_support_frac);
|
|
61038
61200
|
return {
|
|
61039
61201
|
kind: "positivity",
|
|
61040
61202
|
title: "No like-for-like comparison exists",
|
|
61041
|
-
body: `The treated and untreated groups barely overlap on the confounders — only ${pct}
|
|
61203
|
+
body: `The treated and untreated groups barely overlap on the confounders — only ${pct} sit in a range where both occur — so there is no fair comparison to adjust toward.`,
|
|
61042
61204
|
evidence: [
|
|
61043
|
-
{ label: "common support", value:
|
|
61044
|
-
{ label: "treated", value:
|
|
61045
|
-
{ label: "untreated", value:
|
|
61205
|
+
{ label: "common support", value: pct },
|
|
61206
|
+
{ label: "treated", value: words.number(nT) },
|
|
61207
|
+
{ label: "untreated", value: words.number(nC) }
|
|
61046
61208
|
]
|
|
61047
61209
|
};
|
|
61048
61210
|
}
|
|
@@ -61051,20 +61213,19 @@ function deriveRefusal(config2, result, meta3, subject) {
|
|
|
61051
61213
|
title: `Can’t estimate the effect of ${treatment}`,
|
|
61052
61214
|
body: "The engine could not produce a like-for-like estimate for this configuration.",
|
|
61053
61215
|
evidence: [
|
|
61054
|
-
{ label: "treated", value:
|
|
61055
|
-
{ label: "untreated", value:
|
|
61056
|
-
{ label: subject.many, value:
|
|
61216
|
+
{ label: "treated", value: words.number(nT) },
|
|
61217
|
+
{ label: "untreated", value: words.number(nC) },
|
|
61218
|
+
{ label: subject.many, value: words.number(nTot) }
|
|
61057
61219
|
]
|
|
61058
61220
|
};
|
|
61059
61221
|
}
|
|
61060
|
-
function deriveOverlap(o2) {
|
|
61061
|
-
const pct = Math.round(o2.common_support_frac * 100);
|
|
61222
|
+
function deriveOverlap(o2, words) {
|
|
61062
61223
|
return {
|
|
61063
61224
|
treated: arr(o2.treated_propensity),
|
|
61064
61225
|
control: arr(o2.control_propensity),
|
|
61065
61226
|
commonSupportFrac: o2.common_support_frac,
|
|
61066
61227
|
positivityOk: o2.positivity_ok,
|
|
61067
|
-
supportLabel: `${
|
|
61228
|
+
supportLabel: `${words.percent(o2.common_support_frac)} common support`
|
|
61068
61229
|
};
|
|
61069
61230
|
}
|
|
61070
61231
|
function zeroCrossing(xs, ys) {
|
|
@@ -61077,7 +61238,7 @@ function zeroCrossing(xs, ys) {
|
|
|
61077
61238
|
}
|
|
61078
61239
|
return null;
|
|
61079
61240
|
}
|
|
61080
|
-
function deriveRefute(r2, adj, meta3) {
|
|
61241
|
+
function deriveRefute(r2, adj, meta3, words) {
|
|
61081
61242
|
const checks = [];
|
|
61082
61243
|
const est = (adj == null ? void 0 : adj.effect) ?? 0;
|
|
61083
61244
|
const placeboEffect = eastUiComponents.getSomeorUndefined(r2.placebo_effect);
|
|
@@ -61090,7 +61251,7 @@ function deriveRefute(r2, adj, meta3) {
|
|
|
61090
61251
|
desc: "Shuffle which rows were treated; a real effect should collapse to zero.",
|
|
61091
61252
|
// Speak the outcome, not the statistic: on fake labels the effect
|
|
61092
61253
|
// should VANISH — say whether it did.
|
|
61093
|
-
value: placeboEffect !== void 0 ? passed ? `vanished (${signed(placeboEffect)})` : `didn’t vanish (${signed(placeboEffect)})` : passed ? "vanished" : "didn’t vanish",
|
|
61254
|
+
value: placeboEffect !== void 0 ? passed ? `vanished (${signed(placeboEffect, words)})` : `didn’t vanish (${signed(placeboEffect, words)})` : passed ? "vanished" : "didn’t vanish",
|
|
61094
61255
|
passed,
|
|
61095
61256
|
tip: east.some("Randomly re-label which rows were treated. A genuine effect should vanish."),
|
|
61096
61257
|
help: "check_shuffle"
|
|
@@ -61104,7 +61265,7 @@ function deriveRefute(r2, adj, meta3) {
|
|
|
61104
61265
|
name: "Drop-some test",
|
|
61105
61266
|
short: "drop-some",
|
|
61106
61267
|
desc: "Re-estimate on random subsamples; a trustworthy effect stays put.",
|
|
61107
|
-
value: passed ? `stayed at ${signed(ds)} ± ${fmt$1(dstd)}` : `moved to ${signed(ds)} ± ${fmt$1(dstd)}`,
|
|
61268
|
+
value: passed ? `stayed at ${signed(ds, words)} ± ${fmt$1(dstd, words)}` : `moved to ${signed(ds, words)} ± ${fmt$1(dstd, words)}`,
|
|
61108
61269
|
passed,
|
|
61109
61270
|
tip: east.none,
|
|
61110
61271
|
help: "check_dropsome"
|
|
@@ -61124,14 +61285,14 @@ function deriveRefute(r2, adj, meta3) {
|
|
|
61124
61285
|
}
|
|
61125
61286
|
const sens = eastUiComponents.getSomeorUndefined(r2.sensitivity);
|
|
61126
61287
|
const evalue = eastUiComponents.getSomeorUndefined(r2.robustness_value);
|
|
61127
|
-
const benchmarks = sens ? [...sens.benchmarks].sort((a2, b2) => b2.strength
|
|
61288
|
+
const benchmarks = sens ? [...sens.benchmarks].sort((a2, b2) => compareFloats(b2.strength, a2.strength)) : [];
|
|
61128
61289
|
if (sens !== void 0 || evalue !== void 0) {
|
|
61129
61290
|
const strengths = sens ? arr(sens.strengths) : [];
|
|
61130
61291
|
const effects = sens ? arr(sens.effects) : [];
|
|
61131
61292
|
const tip = sens ? zeroCrossing(strengths, effects) : null;
|
|
61132
61293
|
const strongest = benchmarks[0];
|
|
61133
|
-
const value = tip !== null ? strongest !== void 0 ? tip > strongest.strength ? `flips only beyond ${labelOf(meta3, strongest.column)}` : `a cause weaker than ${labelOf(meta3, strongest.column)} could flip it` : `would flip at ${fmt$1(tip)}` : evalue !== void 0 ? `holds (E-value ${fmt$1(evalue)})` : "holds throughout";
|
|
61134
|
-
const scaleNote = strongest !== void 0 ? ` For scale, your strongest known factor (${labelOf(meta3, strongest.column)}) sits at ${fmt$1(strongest.strength)} on this axis.` : "";
|
|
61294
|
+
const value = tip !== null ? strongest !== void 0 ? tip > strongest.strength ? `flips only beyond ${labelOf(meta3, strongest.column)}` : `a cause weaker than ${labelOf(meta3, strongest.column)} could flip it` : `would flip at ${fmt$1(tip, words)}` : evalue !== void 0 ? `holds (E-value ${fmt$1(evalue, words)})` : "holds throughout";
|
|
61295
|
+
const scaleNote = strongest !== void 0 ? ` For scale, your strongest known factor (${labelOf(meta3, strongest.column)}) sits at ${fmt$1(strongest.strength, words)} on this axis.` : "";
|
|
61135
61296
|
checks.push({
|
|
61136
61297
|
name: "Hidden cause",
|
|
61137
61298
|
short: "hidden cause",
|
|
@@ -61167,12 +61328,12 @@ function deriveRefute(r2, adj, meta3) {
|
|
|
61167
61328
|
const at = atOf(b2.strength);
|
|
61168
61329
|
return at === null ? [] : [{ at, label: `as strong as ${labelOf(meta3, b2.column)}`, tone: "muted", help: "sensitivity" }];
|
|
61169
61330
|
});
|
|
61170
|
-
sensVM = { lo: lo2, mid, hi, xTicks: ["none", "", "stronger"], yTicks: [fmt$1(yLo), fmt$1((yLo + yHi) / 2), fmt$1(yHi)], marks };
|
|
61331
|
+
sensVM = { lo: lo2, mid, hi, xTicks: ["none", "", "stronger"], yTicks: [fmt$1(yLo, words), fmt$1((yLo + yHi) / 2, words), fmt$1(yHi, words)], marks };
|
|
61171
61332
|
}
|
|
61172
61333
|
}
|
|
61173
61334
|
return { checks, sens: sensVM };
|
|
61174
61335
|
}
|
|
61175
|
-
function deriveDose(dose, config2, meta3) {
|
|
61336
|
+
function deriveDose(dose, config2, meta3, words) {
|
|
61176
61337
|
const grid = arr(dose.grid);
|
|
61177
61338
|
const mid = arr(dose.effect);
|
|
61178
61339
|
const lo2 = eastUiComponents.getSomeorUndefined(dose.lower) ? arr(eastUiComponents.getSomeorUndefined(dose.lower)) : mid.slice();
|
|
@@ -61190,17 +61351,17 @@ function deriveDose(dose, config2, meta3) {
|
|
|
61190
61351
|
}
|
|
61191
61352
|
}
|
|
61192
61353
|
const xi = grid.length ? [0, Math.floor(grid.length / 2), grid.length - 1] : [];
|
|
61193
|
-
const xTicks = xi.map((i) => fmt$1(grid[i]));
|
|
61354
|
+
const xTicks = xi.map((i) => fmt$1(grid[i], words));
|
|
61194
61355
|
const yLo = Math.min(0, ...lo2), yHi = Math.max(...hi, 0);
|
|
61195
|
-
const yTicks = [fmt$1(yLo), fmt$1((yLo + yHi) / 2), fmt$1(yHi)];
|
|
61356
|
+
const yTicks = [fmt$1(yLo, words), fmt$1((yLo + yHi) / 2, words), fmt$1(yHi, words)];
|
|
61196
61357
|
const margSteps = marg.slice(1);
|
|
61197
61358
|
let lastStep = margSteps.length - 1;
|
|
61198
61359
|
while (lastStep > 0 && Math.abs(margSteps[lastStep]) < 0.12 * maxMarg) lastStep--;
|
|
61199
|
-
const marginal = margSteps.slice(0, lastStep + 1).map((v3, i) => ({ label:
|
|
61360
|
+
const marginal = margSteps.slice(0, lastStep + 1).map((v3, i) => ({ label: fmt$1(grid[i + 1], words), value: v3, frac: clamp01(Math.abs(v3) / maxMarg) }));
|
|
61200
61361
|
const stepFrom = here < sweet ? here : Math.max(0, sweet - 1);
|
|
61201
61362
|
const gainToSweet = (mid[sweet] ?? 0) - (mid[stepFrom] ?? 0);
|
|
61202
61363
|
const nextGain = sweet + 1 < mid.length ? mid[sweet + 1] - mid[sweet] : 0;
|
|
61203
|
-
const tradeoff = `Going from ${fmt$1(grid[stepFrom] ?? 0)} to ${fmt$1(grid[sweet] ?? 0)} adds ${signed(gainToSweet)}; the next step adds only ${signed(nextGain)}.`;
|
|
61364
|
+
const tradeoff = `Going from ${fmt$1(grid[stepFrom] ?? 0, words)} to ${fmt$1(grid[sweet] ?? 0, words)} adds ${signed(gainToSweet, words)}; the next step adds only ${signed(nextGain, words)}.`;
|
|
61204
61365
|
const marks = [];
|
|
61205
61366
|
if (sizes.length) marks.push({ at: here, label: "you are here", tone: "muted", help: "dose_here" });
|
|
61206
61367
|
marks.push({ at: sweet, label: "sweet spot", tone: "pos", help: "dose_sweet" });
|
|
@@ -61217,7 +61378,7 @@ function deriveDose(dose, config2, meta3) {
|
|
|
61217
61378
|
marks,
|
|
61218
61379
|
// Name the feature in the recommendation — a bare "≈ 5.5" doesn't say
|
|
61219
61380
|
// 5.5 of WHAT.
|
|
61220
|
-
recoLabel: `aim for ${featureLabel} ≈ ${fmt$1(grid[sweet] ?? 0)}${featureUnit ? " " + featureUnit : ""}`,
|
|
61381
|
+
recoLabel: `aim for ${featureLabel} ≈ ${fmt$1(grid[sweet] ?? 0, words)}${featureUnit ? " " + featureUnit : ""}`,
|
|
61221
61382
|
recoEffect: mid[sweet] ?? 0,
|
|
61222
61383
|
recoLo: lo2[sweet] ?? 0,
|
|
61223
61384
|
recoHi: hi[sweet] ?? 0,
|
|
@@ -61226,11 +61387,11 @@ function deriveDose(dose, config2, meta3) {
|
|
|
61226
61387
|
framing: `A different question from the headline: how ${outcomeLabel} responds as ${featureLabel} itself moves.`
|
|
61227
61388
|
};
|
|
61228
61389
|
}
|
|
61229
|
-
function relTime(d2, now2) {
|
|
61390
|
+
function relTime(d2, now2, words) {
|
|
61230
61391
|
const days = Math.floor((now2.getTime() - d2.getTime()) / 864e5);
|
|
61231
61392
|
if (days <= 0) return "today";
|
|
61232
61393
|
if (days === 1) return "yesterday";
|
|
61233
|
-
if (days < 7) return
|
|
61394
|
+
if (days < 7) return words.weekday(d2);
|
|
61234
61395
|
return "last wk";
|
|
61235
61396
|
}
|
|
61236
61397
|
const VERDICT_WORD = {
|
|
@@ -61240,43 +61401,43 @@ const VERDICT_WORD = {
|
|
|
61240
61401
|
non_identifiable_positivity: "no overlap",
|
|
61241
61402
|
not_estimable: "n/a"
|
|
61242
61403
|
};
|
|
61243
|
-
function deriveJournalRow(row, now2, meta3) {
|
|
61404
|
+
function deriveJournalRow(row, now2, meta3, words) {
|
|
61244
61405
|
const adj = eastUiComponents.getSomeorUndefined(row.adjusted);
|
|
61245
61406
|
return {
|
|
61246
61407
|
treatment: labelOf(meta3, row.config.treatment),
|
|
61247
61408
|
outcome: labelOf(meta3, row.config.outcome),
|
|
61248
61409
|
confounders: row.config.common_causes.map((c2) => labelOf(meta3, c2)).join(", "),
|
|
61249
|
-
effect: adj !== void 0 ? signed(adj) : signed(row.naive),
|
|
61410
|
+
effect: adj !== void 0 ? signed(adj, words) : signed(row.naive, words),
|
|
61250
61411
|
verdict: VERDICT_WORD[row.verdict.type],
|
|
61251
61412
|
verdictTone: VERDICT_TONE[row.verdict.type],
|
|
61252
61413
|
who: row.committed_by,
|
|
61253
|
-
when: relTime(row.committed_at, now2),
|
|
61414
|
+
when: relTime(row.committed_at, now2, words),
|
|
61254
61415
|
// The originating preset id (resolved to a label by the surface); `none` for a
|
|
61255
61416
|
// free-form / pre-presets row.
|
|
61256
61417
|
preset: row.preset
|
|
61257
61418
|
};
|
|
61258
61419
|
}
|
|
61259
|
-
function deriveView(config2, ranConfig, cols, result, journal, meta3, dataLen, now2, subject = { one: "record", many: "records" }) {
|
|
61420
|
+
function deriveView(config2, ranConfig, cols, result, journal, meta3, dataLen, now2, subject = { one: "record", many: "records" }, words = eastUiComponents.formatters()) {
|
|
61260
61421
|
var _a2;
|
|
61261
61422
|
const adj = result ? eastUiComponents.getSomeorUndefined(result.adjusted) : void 0;
|
|
61262
61423
|
const refutation = result ? eastUiComponents.getSomeorUndefined(result.refutation) : void 0;
|
|
61263
61424
|
const doseR = result ? eastUiComponents.getSomeorUndefined(result.dose_response) : void 0;
|
|
61264
|
-
const answer = result && adj ? deriveAnswer(ranConfig, result, adj, meta3) : null;
|
|
61265
|
-
const refute = refutation ? deriveRefute(refutation, adj, meta3) : null;
|
|
61425
|
+
const answer = result && adj ? deriveAnswer(ranConfig, result, adj, meta3, words) : null;
|
|
61426
|
+
const refute = refutation ? deriveRefute(refutation, adj, meta3, words) : null;
|
|
61266
61427
|
const higherBetter = eastUiComponents.getSomeorUndefined((_a2 = colMeta(meta3, ranConfig.outcome)) == null ? void 0 : _a2.higherIsBetter);
|
|
61267
61428
|
return {
|
|
61268
61429
|
// The set-up rail reflects the LIVE config (the editor); the result deck
|
|
61269
61430
|
// reflects RANCONFIG — the config that produced `result` — so the result
|
|
61270
61431
|
// strings never drift ahead of the numbers on a live picker edit.
|
|
61271
|
-
spec: deriveSpec(config2, cols, result, meta3, dataLen, subject),
|
|
61432
|
+
spec: deriveSpec(config2, cols, result, meta3, dataLen, subject, words),
|
|
61272
61433
|
verdict: result ? deriveVerdict(result.verdict) : null,
|
|
61273
|
-
narrative: result ? deriveNarrative(result, answer, refute, higherBetter, subject) : null,
|
|
61434
|
+
narrative: result ? deriveNarrative(result, answer, refute, higherBetter, subject, words) : null,
|
|
61274
61435
|
answer,
|
|
61275
|
-
refusal: result && !adj ? deriveRefusal(ranConfig, result, meta3, subject) : null,
|
|
61276
|
-
overlap: result ? deriveOverlap(result.overlap) : null,
|
|
61436
|
+
refusal: result && !adj ? deriveRefusal(ranConfig, result, meta3, subject, words) : null,
|
|
61437
|
+
overlap: result ? deriveOverlap(result.overlap, words) : null,
|
|
61277
61438
|
refute,
|
|
61278
|
-
dose: doseR && doseR.effect.length ? deriveDose(doseR, ranConfig, meta3) : null,
|
|
61279
|
-
journal: journal ? journal.map((r2) => deriveJournalRow(r2, now2, meta3)) : null
|
|
61439
|
+
dose: doseR && doseR.effect.length ? deriveDose(doseR, ranConfig, meta3, words) : null,
|
|
61440
|
+
journal: journal ? journal.map((r2) => deriveJournalRow(r2, now2, meta3, words)) : null
|
|
61280
61441
|
};
|
|
61281
61442
|
}
|
|
61282
61443
|
const DESIGN_HEADLINE = {
|
|
@@ -61295,7 +61456,7 @@ function deriveDesignOption(o2) {
|
|
|
61295
61456
|
treatedShare: o2.treated_share
|
|
61296
61457
|
};
|
|
61297
61458
|
}
|
|
61298
|
-
function deriveDesign(d2, result, ranConfig, meta3) {
|
|
61459
|
+
function deriveDesign(d2, result, ranConfig, meta3, words = eastUiComponents.formatters()) {
|
|
61299
61460
|
const basis = d2.basis.type;
|
|
61300
61461
|
const outcome = ranConfig.outcome;
|
|
61301
61462
|
const unit2 = unitOf(meta3, outcome);
|
|
@@ -61327,9 +61488,9 @@ function deriveDesign(d2, result, ranConfig, meta3) {
|
|
|
61327
61488
|
}
|
|
61328
61489
|
return bi;
|
|
61329
61490
|
};
|
|
61330
|
-
const xTicks = len ? [
|
|
61491
|
+
const xTicks = len ? [words.number(ns[0]), words.number(ns[Math.floor((len - 1) / 2)]), words.number(ns[len - 1])] : [];
|
|
61331
61492
|
const marks = [];
|
|
61332
|
-
if (len) marks.push({ at: nearest(primary.nTotal), label: `target ${(d2.target_power
|
|
61493
|
+
if (len) marks.push({ at: nearest(primary.nTotal), label: `target ${words.percent(d2.target_power)}`, tone: "pos", help: "validate_power" });
|
|
61333
61494
|
const cp = eastUiComponents.getSomeorUndefined(d2.current_power);
|
|
61334
61495
|
if (cp !== void 0 && len) {
|
|
61335
61496
|
const curN = result ? Number(result.n_total) : 0;
|
|
@@ -61337,7 +61498,7 @@ function deriveDesign(d2, result, ranConfig, meta3) {
|
|
|
61337
61498
|
const offScale = curN >= (ns[len - 1] ?? 0);
|
|
61338
61499
|
marks.push({
|
|
61339
61500
|
at: offScale ? len - 1 : nearest(curN),
|
|
61340
|
-
label: offScale ? `you’re here · ${(cp
|
|
61501
|
+
label: offScale ? `you’re here · ${words.percent(cp)} (off-scale)` : `you’re here ${words.percent(cp)}`,
|
|
61341
61502
|
tone: "muted",
|
|
61342
61503
|
help: "validate_power"
|
|
61343
61504
|
});
|
|
@@ -61351,13 +61512,204 @@ function deriveDesign(d2, result, ranConfig, meta3) {
|
|
|
61351
61512
|
alternates: options2.slice(1),
|
|
61352
61513
|
matchOn,
|
|
61353
61514
|
curve: { mid: powers.slice(0, len).map((p2) => p2 * 100), xTicks, marks },
|
|
61354
|
-
targetLabel: `${signed(d2.target_effect)}${unit2 ? ` ${unit2}` : ""}`,
|
|
61355
|
-
targetPctLabel:
|
|
61515
|
+
targetLabel: `${signed(d2.target_effect, words)}${unit2 ? ` ${unit2}` : ""}`,
|
|
61516
|
+
targetPctLabel: words.percent(d2.target_power),
|
|
61356
61517
|
holdback: basis === "create_control",
|
|
61357
61518
|
showOverlap: basis === "restrict_to_overlap",
|
|
61358
61519
|
faint
|
|
61359
61520
|
};
|
|
61360
61521
|
}
|
|
61522
|
+
function ChartLabel({ x: x2, y: y2, w: w2, align, size: size3, weight: weight8, color: color2, family, help, children: children2 }) {
|
|
61523
|
+
const span = /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: `${size3}px`, fontFamily: family, fontWeight: weight8, color: color2, lineHeight: 1, whiteSpace: "nowrap" }, children: children2 });
|
|
61524
|
+
return /* @__PURE__ */ jsxRuntime.jsx("foreignObject", { x: x2, y: y2, width: w2, height: size3 + 6, style: { overflow: "visible" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: align, fontSize: `${size3}px`, lineHeight: 1 }, children: help ? /* @__PURE__ */ jsxRuntime.jsx(Help, { id: help, children: span }) : span }) });
|
|
61525
|
+
}
|
|
61526
|
+
function svgText(size3, fill, family, weight8) {
|
|
61527
|
+
return { fontSize: `${size3}px`, fill, fontFamily: family, ...weight8 !== void 0 ? { fontWeight: weight8 } : {} };
|
|
61528
|
+
}
|
|
61529
|
+
function useMeasuredWidth() {
|
|
61530
|
+
const ref = React.useRef(null);
|
|
61531
|
+
const [w2, setW] = React.useState(0);
|
|
61532
|
+
React.useLayoutEffect(() => {
|
|
61533
|
+
const el = ref.current;
|
|
61534
|
+
if (!el) return;
|
|
61535
|
+
const update2 = () => setW(el.clientWidth);
|
|
61536
|
+
update2();
|
|
61537
|
+
const ro = new ResizeObserver(update2);
|
|
61538
|
+
ro.observe(el);
|
|
61539
|
+
return () => ro.disconnect();
|
|
61540
|
+
}, []);
|
|
61541
|
+
return [ref, w2];
|
|
61542
|
+
}
|
|
61543
|
+
function useChartTheme() {
|
|
61544
|
+
const system = react.useChakraContext();
|
|
61545
|
+
const tok = (k2, fallback) => system.token(k2, fallback);
|
|
61546
|
+
const tones = {
|
|
61547
|
+
neg: tok("colors.fg.danger", "#b85a4a"),
|
|
61548
|
+
pos: tok("colors.fg.success", "#2f7a5b"),
|
|
61549
|
+
warn: tok("colors.fg.warning", "#b8862d"),
|
|
61550
|
+
muted: tok("colors.fg.muted", "#6b8080"),
|
|
61551
|
+
brand: tok("colors.brand.solid", "#3a7780")
|
|
61552
|
+
};
|
|
61553
|
+
return {
|
|
61554
|
+
mono: tok("fonts.mono", '"JetBrains Mono", ui-monospace, monospace'),
|
|
61555
|
+
body: tok("fonts.body", "system-ui, -apple-system, sans-serif"),
|
|
61556
|
+
ink: tok("colors.fg", "#111b22"),
|
|
61557
|
+
muted: tones.muted,
|
|
61558
|
+
faint: tok("colors.fg.subtle", "#9bb0b0"),
|
|
61559
|
+
rule: tok("colors.border.subtle", "#e2e8e8"),
|
|
61560
|
+
ruleStrong: tok("colors.border.strong", "#cbd5d5"),
|
|
61561
|
+
surface: tok("colors.bg.surface", "#ffffff"),
|
|
61562
|
+
tone: (t4) => tones[t4] ?? tones.brand,
|
|
61563
|
+
labelSize: 10,
|
|
61564
|
+
titleSize: 11,
|
|
61565
|
+
lineWidth: 1.8,
|
|
61566
|
+
barWidth: 2.5,
|
|
61567
|
+
dotRadius: 2.6,
|
|
61568
|
+
scatterRadius: 3.4,
|
|
61569
|
+
areaOpacity: 0.16
|
|
61570
|
+
};
|
|
61571
|
+
}
|
|
61572
|
+
const niceCeil = (v3) => {
|
|
61573
|
+
if (v3 <= 1e-9) return 0;
|
|
61574
|
+
const mag = Math.pow(10, Math.floor(Math.log10(v3)));
|
|
61575
|
+
const n2 = v3 / mag;
|
|
61576
|
+
const step3 = n2 <= 1 ? 1 : n2 <= 1.5 ? 1.5 : n2 <= 2 ? 2 : n2 <= 3 ? 3 : n2 <= 4 ? 4 : n2 <= 5 ? 5 : n2 <= 6 ? 6 : n2 <= 8 ? 8 : 10;
|
|
61577
|
+
return step3 * mag;
|
|
61578
|
+
};
|
|
61579
|
+
function ForestPlot({ rows, min: min4, max: max5, unit: unit2, height: height2, rowHelp }) {
|
|
61580
|
+
const t4 = useChartTheme();
|
|
61581
|
+
const words = eastUiComponents.useFormatters();
|
|
61582
|
+
const [ref, w2] = useMeasuredWidth();
|
|
61583
|
+
const n2 = rows.length;
|
|
61584
|
+
const hPx = height2 ?? 26 + n2 * 38;
|
|
61585
|
+
const padL = 124, padR = 46, padT = 20, padB = 30;
|
|
61586
|
+
const innerW = Math.max(0, w2 - padL - padR);
|
|
61587
|
+
const innerH = hPx - padT - padB;
|
|
61588
|
+
const x2 = createLinearScale({ domain: [min4, max5], range: [0, innerW] });
|
|
61589
|
+
const rowH = innerH / Math.max(1, n2);
|
|
61590
|
+
const zeroX = Math.max(0, Math.min(innerW, x2(0)));
|
|
61591
|
+
const frac = (v3) => max5 > min4 ? (v3 - min4) / (max5 - min4) : 0.5;
|
|
61592
|
+
const anchorAt = (v3) => frac(v3) < 0.06 ? "start" : frac(v3) > 0.94 ? "end" : "middle";
|
|
61593
|
+
const zf = frac(0);
|
|
61594
|
+
const ticks2 = zf > 0.12 && zf < 0.88 ? [min4, 0, max5] : [min4, max5];
|
|
61595
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { ref, width: "100%", height: `${hPx}px`, children: w2 > 0 && /* @__PURE__ */ jsxRuntime.jsx("svg", { width: w2, height: hPx, style: { display: "block" }, children: /* @__PURE__ */ jsxRuntime.jsxs(Group, { left: padL, top: padT, children: [
|
|
61596
|
+
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: zeroX, y: -4 }, to: { x: zeroX, y: innerH }, stroke: t4.muted, strokeWidth: 1, strokeDasharray: "3 2" }),
|
|
61597
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: zeroX, y: -6, textAnchor: anchorAt(0), style: svgText(t4.labelSize, t4.muted, t4.mono), children: "no effect" }),
|
|
61598
|
+
rows.map((r2, i) => {
|
|
61599
|
+
const cy = rowH * i + rowH / 2;
|
|
61600
|
+
const col = t4.tone(r2.tone);
|
|
61601
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Group, { top: cy, children: [
|
|
61602
|
+
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: x2(r2.lo), y: 0 }, to: { x: x2(r2.hi), y: 0 }, stroke: col, strokeWidth: t4.barWidth, strokeOpacity: 0.9, strokeLinecap: "round" }),
|
|
61603
|
+
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: x2(r2.lo), y: -4 }, to: { x: x2(r2.lo), y: 4 }, stroke: col, strokeWidth: 1.5 }),
|
|
61604
|
+
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: x2(r2.hi), y: -4 }, to: { x: x2(r2.hi), y: 4 }, stroke: col, strokeWidth: 1.5 }),
|
|
61605
|
+
/* @__PURE__ */ jsxRuntime.jsx(Circle, { cx: x2(r2.est), cy: 0, r: t4.scatterRadius, fill: col, stroke: t4.surface, strokeWidth: 1.8 }),
|
|
61606
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChartLabel, { x: -padL + 2, y: -13, w: padL - 6, align: "left", size: t4.labelSize, weight: 600, color: t4.ink, family: t4.body, ...(rowHelp == null ? void 0 : rowHelp[i]) ? { help: rowHelp[i] } : {}, children: r2.label }),
|
|
61607
|
+
r2.note && /* @__PURE__ */ jsxRuntime.jsx("text", { x: -padL + 2, y: 9, style: svgText(9, t4.faint, t4.body), children: r2.note }),
|
|
61608
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: innerW + padR - 2, y: 4, textAnchor: "end", style: svgText(t4.titleSize, col, t4.mono, 700), children: signed(r2.est, words) })
|
|
61609
|
+
] }, i);
|
|
61610
|
+
}),
|
|
61611
|
+
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: innerH }, to: { x: innerW, y: innerH }, stroke: t4.rule, strokeWidth: 1 }),
|
|
61612
|
+
ticks2.map((tk, i) => /* @__PURE__ */ jsxRuntime.jsxs(Group, { left: Math.max(0, Math.min(innerW, x2(tk))), children: [
|
|
61613
|
+
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: innerH }, to: { x: 0, y: innerH + 4 }, stroke: t4.ruleStrong, strokeWidth: 1 }),
|
|
61614
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: 0, y: innerH + 14, textAnchor: anchorAt(tk), style: svgText(t4.labelSize, t4.muted, t4.mono), children: signed(tk, words) })
|
|
61615
|
+
] }, `t${i}`)),
|
|
61616
|
+
unit2 && /* @__PURE__ */ jsxRuntime.jsx("text", { x: innerW / 2, y: innerH + 26, textAnchor: "middle", style: svgText(t4.labelSize, t4.muted, t4.mono), children: unit2 })
|
|
61617
|
+
] }) }) });
|
|
61618
|
+
}
|
|
61619
|
+
function AreaRange({ lo: lo2, mid, hi, xTicks = [], xTickWords = false, yTicks = [], zero: zero2, tone: toneName, marks = [], height: height2, yFormat = "signed" }) {
|
|
61620
|
+
const t4 = useChartTheme();
|
|
61621
|
+
const words = eastUiComponents.useFormatters();
|
|
61622
|
+
const [ref, w2] = useMeasuredWidth();
|
|
61623
|
+
const hPx = height2 ?? 100;
|
|
61624
|
+
const col = t4.tone(toneName ?? "brand");
|
|
61625
|
+
const padL = yTicks.length ? 52 : 6;
|
|
61626
|
+
const padR = 12;
|
|
61627
|
+
const padT = marks.length ? 22 : 8;
|
|
61628
|
+
const padB = xTicks.length ? 22 : 12;
|
|
61629
|
+
const innerW = Math.max(0, w2 - padL - padR);
|
|
61630
|
+
const innerH = hPx - padT - padB;
|
|
61631
|
+
const xScale = createLinearScale({ domain: [0, Math.max(1, mid.length - 1)], range: [0, innerW] });
|
|
61632
|
+
const fin = (x2, fallback) => typeof x2 === "number" && Number.isFinite(x2) ? x2 : fallback;
|
|
61633
|
+
const data4 = mid.map((m2, i) => {
|
|
61634
|
+
const mm = fin(m2, 0);
|
|
61635
|
+
return { i, lo: fin(lo2[i], mm), hi: fin(hi[i], mm), mid: mm };
|
|
61636
|
+
});
|
|
61637
|
+
const dataMin = Math.min(...data4.map((d2) => d2.lo), zero2 ?? Infinity);
|
|
61638
|
+
const dataMax = Math.max(...data4.map((d2) => d2.hi), zero2 ?? -Infinity);
|
|
61639
|
+
const yHiN = niceCeil(Math.max(dataMax, 0));
|
|
61640
|
+
const yLoN = dataMin < -0.08 * yHiN ? -niceCeil(-dataMin) : 0;
|
|
61641
|
+
const yScale = createLinearScale({ domain: [yLoN, yHiN], range: [innerH, 0] });
|
|
61642
|
+
const yfmt = (v3) => yFormat === "percent" ? words.percent(v3 / 100) : signed(v3, words);
|
|
61643
|
+
const yLabels = [yfmt(yHiN), yfmt((yHiN + yLoN) / 2), yfmt(yLoN)];
|
|
61644
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { ref, width: "100%", height: `${hPx}px`, children: w2 > 0 && /* @__PURE__ */ jsxRuntime.jsx("svg", { width: w2, height: hPx, style: { display: "block" }, children: /* @__PURE__ */ jsxRuntime.jsxs(Group, { left: padL, top: padT, children: [
|
|
61645
|
+
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: 0 }, to: { x: 0, y: innerH }, stroke: t4.rule, strokeWidth: 1 }),
|
|
61646
|
+
yTicks.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
61647
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: -8, y: 10, textAnchor: "end", style: svgText(t4.labelSize, t4.muted, t4.mono), children: yLabels[0] }),
|
|
61648
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: -8, y: innerH / 2 + 3, textAnchor: "end", style: svgText(t4.labelSize, t4.muted, t4.mono), children: yLabels[1] }),
|
|
61649
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: -8, y: innerH - 1, textAnchor: "end", style: svgText(t4.labelSize, t4.muted, t4.mono), children: yLabels[2] })
|
|
61650
|
+
] }),
|
|
61651
|
+
zero2 != null && /* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: yScale(zero2) }, to: { x: innerW, y: yScale(zero2) }, stroke: t4.muted, strokeWidth: 1, strokeDasharray: "3 2" }),
|
|
61652
|
+
/* @__PURE__ */ jsxRuntime.jsx(Area, { data: data4, x: (d2) => xScale(d2.i), y0: (d2) => yScale(d2.lo), y1: (d2) => yScale(d2.hi), curve: monotoneX, fill: col, fillOpacity: t4.areaOpacity, stroke: "transparent" }),
|
|
61653
|
+
/* @__PURE__ */ jsxRuntime.jsx(LinePath, { data: data4, x: (d2) => xScale(d2.i), y: (d2) => yScale(d2.mid), curve: monotoneX, stroke: col, strokeWidth: t4.lineWidth }),
|
|
61654
|
+
marks.map((m2, i) => {
|
|
61655
|
+
const mc = t4.tone(m2.tone);
|
|
61656
|
+
const dotY = yScale(fin(mid[m2.at], 0));
|
|
61657
|
+
const labY = Math.max(9, dotY - 9);
|
|
61658
|
+
const atEnd = m2.at >= mid.length - 2;
|
|
61659
|
+
const atStart = m2.at <= 1;
|
|
61660
|
+
const align = atEnd ? "right" : atStart ? "left" : "center";
|
|
61661
|
+
const labW = m2.label.length * 6.5 + 8;
|
|
61662
|
+
const labX = atEnd ? -labW - 5 : atStart ? 5 : -labW / 2;
|
|
61663
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Group, { left: xScale(m2.at), children: [
|
|
61664
|
+
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: -2 }, to: { x: 0, y: innerH }, stroke: mc, strokeWidth: 1, strokeDasharray: "2 3" }),
|
|
61665
|
+
/* @__PURE__ */ jsxRuntime.jsx(Circle, { cx: 0, cy: dotY, r: t4.dotRadius, fill: mc, stroke: t4.surface, strokeWidth: 1.5 }),
|
|
61666
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChartLabel, { x: labX, y: labY - 11, w: labW, align, size: t4.labelSize, weight: 500, color: mc, family: t4.body, ...m2.help ? { help: m2.help } : {}, children: m2.label })
|
|
61667
|
+
] }, `mk${i}`);
|
|
61668
|
+
}),
|
|
61669
|
+
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: innerH }, to: { x: innerW, y: innerH }, stroke: t4.rule, strokeWidth: 1 }),
|
|
61670
|
+
xTicks.map((tk, i) => {
|
|
61671
|
+
const word = xTickWords;
|
|
61672
|
+
return /* @__PURE__ */ jsxRuntime.jsx("text", { x: innerW * i / Math.max(1, xTicks.length - 1), y: innerH + 14, textAnchor: i === 0 ? "start" : i === xTicks.length - 1 ? "end" : "middle", style: svgText(word ? 9 : t4.labelSize, word ? t4.faint : t4.muted, word ? t4.body : t4.mono), children: tk }, `x${i}`);
|
|
61673
|
+
})
|
|
61674
|
+
] }) }) });
|
|
61675
|
+
}
|
|
61676
|
+
function OverlapHistogram({ treated, control, domain = [0, 1], supportLabel, positivityOk, height: height2 }) {
|
|
61677
|
+
const t4 = useChartTheme();
|
|
61678
|
+
const words = eastUiComponents.useFormatters();
|
|
61679
|
+
const [ref, w2] = useMeasuredWidth();
|
|
61680
|
+
const hPx = height2 ?? 150;
|
|
61681
|
+
const padL = 8, padR = 8, padT = 16, padB = 26;
|
|
61682
|
+
const innerW = Math.max(0, w2 - padL - padR);
|
|
61683
|
+
const innerH = hPx - padT - padB;
|
|
61684
|
+
const centerY = innerH / 2;
|
|
61685
|
+
const halfH = centerY - 4;
|
|
61686
|
+
const bins = Math.max(treated.length, control.length);
|
|
61687
|
+
const x2 = createLinearScale({ domain, range: [0, innerW] });
|
|
61688
|
+
const span = domain[1] - domain[0];
|
|
61689
|
+
const binW = bins > 0 ? innerW / bins : innerW;
|
|
61690
|
+
const barW = Math.max(1, binW * 0.78);
|
|
61691
|
+
const maxVal = Math.max(1e-9, ...treated, ...control);
|
|
61692
|
+
const tCol = t4.tone("pos");
|
|
61693
|
+
const cCol = t4.tone("muted");
|
|
61694
|
+
const ticks2 = [domain[0], (domain[0] + domain[1]) / 2, domain[1]];
|
|
61695
|
+
const cx2 = (i) => x2(domain[0] + (i + 0.5) / bins * span);
|
|
61696
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { ref, width: "100%", height: `${hPx}px`, children: w2 > 0 && /* @__PURE__ */ jsxRuntime.jsx("svg", { width: w2, height: hPx, style: { display: "block" }, children: /* @__PURE__ */ jsxRuntime.jsxs(Group, { left: padL, top: padT, children: [
|
|
61697
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: 0, y: -4, style: svgText(9, t4.faint, t4.body), children: "treated ↑" }),
|
|
61698
|
+
supportLabel && /* @__PURE__ */ jsxRuntime.jsx("text", { x: innerW, y: -4, textAnchor: "end", style: svgText(t4.labelSize, positivityOk ? t4.tone("pos") : t4.tone("warn"), t4.mono, 600), children: supportLabel }),
|
|
61699
|
+
Array.from({ length: bins }, (_2, i) => {
|
|
61700
|
+
const ht = Number(treated[i] ?? 0) / maxVal * halfH;
|
|
61701
|
+
const hc = Number(control[i] ?? 0) / maxVal * halfH;
|
|
61702
|
+
const left = cx2(i) - barW / 2;
|
|
61703
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Group, { children: [
|
|
61704
|
+
ht > 0 && /* @__PURE__ */ jsxRuntime.jsx("rect", { x: left, y: centerY - ht, width: barW, height: ht, fill: tCol, fillOpacity: 0.85, rx: 0.5 }),
|
|
61705
|
+
hc > 0 && /* @__PURE__ */ jsxRuntime.jsx("rect", { x: left, y: centerY, width: barW, height: hc, fill: cCol, fillOpacity: 0.6, rx: 0.5 })
|
|
61706
|
+
] }, i);
|
|
61707
|
+
}),
|
|
61708
|
+
/* @__PURE__ */ jsxRuntime.jsx(Line, { from: { x: 0, y: centerY }, to: { x: innerW, y: centerY }, stroke: t4.ruleStrong, strokeWidth: 1 }),
|
|
61709
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: 0, y: innerH + 4, style: svgText(9, t4.faint, t4.body), children: "untreated ↓" }),
|
|
61710
|
+
ticks2.map((tk, i) => /* @__PURE__ */ jsxRuntime.jsx("text", { x: x2(tk), y: innerH + 16, textAnchor: i === 0 ? "start" : i === ticks2.length - 1 ? "end" : "middle", style: svgText(t4.labelSize, t4.muted, t4.mono), children: fmt$1(tk, words) }, `x${i}`))
|
|
61711
|
+
] }) }) });
|
|
61712
|
+
}
|
|
61361
61713
|
const SUBJECT_DEFAULT = { one: "record", many: "records" };
|
|
61362
61714
|
const AUTORUN_MAX_ROWS = 5e4;
|
|
61363
61715
|
const TONE_TOKEN = {
|
|
@@ -61385,7 +61737,7 @@ function kindOfTypeValue(t4) {
|
|
|
61385
61737
|
}
|
|
61386
61738
|
}
|
|
61387
61739
|
function useColumns(workspace, source) {
|
|
61388
|
-
const types =
|
|
61740
|
+
const types = getBindingTypes(workspace, source);
|
|
61389
61741
|
return React.useMemo(() => {
|
|
61390
61742
|
const st = types == null ? void 0 : types.sourceType;
|
|
61391
61743
|
if (!st || st.type !== "Array") return { columns: [], rowArrayType: null };
|
|
@@ -61397,35 +61749,9 @@ function useColumns(workspace, source) {
|
|
|
61397
61749
|
};
|
|
61398
61750
|
}, [types == null ? void 0 : types.sourceType]);
|
|
61399
61751
|
}
|
|
61400
|
-
function
|
|
61401
|
-
return
|
|
61402
|
-
const { fieldId, op } = p2.value;
|
|
61403
|
-
const v3 = row[fieldId];
|
|
61404
|
-
const ov = op.value;
|
|
61405
|
-
switch (op.type) {
|
|
61406
|
-
case "eq":
|
|
61407
|
-
case "is":
|
|
61408
|
-
return v3 === ov;
|
|
61409
|
-
case "neq":
|
|
61410
|
-
return v3 !== ov;
|
|
61411
|
-
case "lt":
|
|
61412
|
-
return num(v3) != null && num(ov) != null ? num(v3) < num(ov) : true;
|
|
61413
|
-
case "lte":
|
|
61414
|
-
return num(v3) != null && num(ov) != null ? num(v3) <= num(ov) : true;
|
|
61415
|
-
case "gt":
|
|
61416
|
-
return num(v3) != null && num(ov) != null ? num(v3) > num(ov) : true;
|
|
61417
|
-
case "gte":
|
|
61418
|
-
return num(v3) != null && num(ov) != null ? num(v3) >= num(ov) : true;
|
|
61419
|
-
case "in":
|
|
61420
|
-
return east.isEastSet(ov) ? ov.has(v3) : true;
|
|
61421
|
-
case "notIn":
|
|
61422
|
-
return east.isEastSet(ov) ? !ov.has(v3) : true;
|
|
61423
|
-
default:
|
|
61424
|
-
return true;
|
|
61425
|
-
}
|
|
61426
|
-
});
|
|
61752
|
+
function inPopulation(row, population) {
|
|
61753
|
+
return population.every((p2) => eastUi.slicePredicateMatches(p2, row));
|
|
61427
61754
|
}
|
|
61428
|
-
const num = (x2) => typeof x2 === "number" ? x2 : typeof x2 === "bigint" ? Number(x2) : null;
|
|
61429
61755
|
function Cap({ children: children2, help }) {
|
|
61430
61756
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
61431
61757
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "caption.eyebrow", fontSize: "9px", mb: "2.5", children: help ? /* @__PURE__ */ jsxRuntime.jsx(Help, { id: help, children: children2 }) : children2 }),
|
|
@@ -61538,7 +61864,7 @@ function LoadingSkeleton() {
|
|
|
61538
61864
|
] })
|
|
61539
61865
|
] });
|
|
61540
61866
|
}
|
|
61541
|
-
const experimentValueEqual = east.
|
|
61867
|
+
const experimentValueEqual = east.equivalentFor(internal$1.Experiment.Component.schema);
|
|
61542
61868
|
const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }) {
|
|
61543
61869
|
var _a2, _b2, _c2;
|
|
61544
61870
|
const v3 = value;
|
|
@@ -61548,6 +61874,7 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
61548
61874
|
const bs = react.useSlotRecipe({ key: "barStrip" })({});
|
|
61549
61875
|
const statusR = react.useSlotRecipe({ key: "status" });
|
|
61550
61876
|
const es = react.useSlotRecipe({ key: "eyebrowRow" })({});
|
|
61877
|
+
const words = eastUiComponents.useFormatters();
|
|
61551
61878
|
const workspace = getReactiveDatasetCache().getConfig().workspace ?? "";
|
|
61552
61879
|
const data4 = useBindingValue(v3.data);
|
|
61553
61880
|
const journalBind = useBindingValue(v3.journal.type === "some" ? v3.journal.value : null);
|
|
@@ -61595,7 +61922,7 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
61595
61922
|
const population = localPop;
|
|
61596
61923
|
const filteredRows = React.useMemo(() => {
|
|
61597
61924
|
if (!data4.value) return null;
|
|
61598
|
-
return population.length ? data4.value.filter((r2) =>
|
|
61925
|
+
return population.length ? data4.value.filter((r2) => inPopulation(r2, population)) : data4.value;
|
|
61599
61926
|
}, [data4.value, population]);
|
|
61600
61927
|
const fields = React.useMemo(
|
|
61601
61928
|
() => columns.filter((c2) => c2.kind !== "other").map((c2) => {
|
|
@@ -61697,8 +62024,8 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
61697
62024
|
}, [ranConfig, config2, meta3, subject]);
|
|
61698
62025
|
const view = React.useMemo(() => {
|
|
61699
62026
|
if (!config2) return null;
|
|
61700
|
-
return deriveView(config2, ranConfig ?? config2, columns, shownResult, journalBind.value, meta3, nRows, now2, subject);
|
|
61701
|
-
}, [config2, ranConfig, columns, shownResult, journalBind.value, meta3, nRows, now2, subject]);
|
|
62027
|
+
return deriveView(config2, ranConfig ?? config2, columns, shownResult, journalBind.value, meta3, nRows, now2, subject, words);
|
|
62028
|
+
}, [config2, ranConfig, columns, shownResult, journalBind.value, meta3, nRows, now2, subject, words]);
|
|
61702
62029
|
const designConfigValue = React.useMemo(() => ({
|
|
61703
62030
|
alpha: east.none,
|
|
61704
62031
|
target_power: east.none,
|
|
@@ -61711,15 +62038,15 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
61711
62038
|
var _a3;
|
|
61712
62039
|
if (tab !== "validate" || !hasDesign || design.pending || precomputedDesign !== null) return;
|
|
61713
62040
|
if (!filteredRows || !config2 || !shownResult) return;
|
|
61714
|
-
if (((_a3 = designSnapRef.current) == null ? void 0 : _a3.result
|
|
62041
|
+
if (Object.is((_a3 = designSnapRef.current) == null ? void 0 : _a3.result, shownResult)) return;
|
|
61715
62042
|
designSnapRef.current = { result: shownResult, config: ranConfig ?? config2 };
|
|
61716
62043
|
design.call(filteredRows, ranConfig ?? config2, shownResult, designConfigValue);
|
|
61717
62044
|
}, [tab, hasDesign, precomputedDesign, filteredRows, config2, ranConfig, shownResult, design, designConfigValue]);
|
|
61718
62045
|
const vmDesign = React.useMemo(() => {
|
|
61719
|
-
if (precomputedDesign !== null && shownResult !== null && config2) return deriveDesign(precomputedDesign, shownResult, ranConfig ?? config2, meta3);
|
|
61720
|
-
return design.result && designSnapRef.current ? deriveDesign(design.result, designSnapRef.current.result, designSnapRef.current.config, meta3) : null;
|
|
61721
|
-
}, [precomputedDesign, shownResult, config2, ranConfig, design.result, meta3]);
|
|
61722
|
-
const designFresh = precomputedDesign !== null && shownResult !== null || design.result !== null && ((_b2 = designSnapRef.current) == null ? void 0 : _b2.result
|
|
62046
|
+
if (precomputedDesign !== null && shownResult !== null && config2) return deriveDesign(precomputedDesign, shownResult, ranConfig ?? config2, meta3, words);
|
|
62047
|
+
return design.result && designSnapRef.current ? deriveDesign(design.result, designSnapRef.current.result, designSnapRef.current.config, meta3, words) : null;
|
|
62048
|
+
}, [precomputedDesign, shownResult, config2, ranConfig, design.result, meta3, words]);
|
|
62049
|
+
const designFresh = precomputedDesign !== null && shownResult !== null || design.result !== null && Object.is((_b2 = designSnapRef.current) == null ? void 0 : _b2.result, shownResult) && !design.pending;
|
|
61723
62050
|
if (!config2 || !view) {
|
|
61724
62051
|
const failed2 = experiment.status === "failed";
|
|
61725
62052
|
const noConfigs = !configsBind.error && configs.length === 0;
|
|
@@ -61787,7 +62114,7 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
61787
62114
|
readonly && /* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", css: badge({ variant: "plain", size: "sm" }), textTransform: "none", letterSpacing: "normal", children: "View only" }),
|
|
61788
62115
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { as: "span", css: dataStatus.root, children: [
|
|
61789
62116
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", css: dataStatus.indicator }),
|
|
61790
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", css: dataStatus.label, children: stale ? `${nRows} rows` : vs.dataLabel })
|
|
62117
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", css: dataStatus.label, children: stale ? `${words.number(nRows)} rows` : vs.dataLabel })
|
|
61791
62118
|
] }),
|
|
61792
62119
|
/* @__PURE__ */ jsxRuntime.jsx(GuidanceToggle, { on: guidance, onToggle: () => setGuidance((g2) => !g2) }),
|
|
61793
62120
|
canRun && /* @__PURE__ */ jsxRuntime.jsx(ActionButton, { button, variant: "solid", label: "Run", onClick: onRun, disabled: runDisabled, pulse: stale }),
|
|
@@ -61820,7 +62147,7 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
61820
62147
|
"add another"
|
|
61821
62148
|
] }) })
|
|
61822
62149
|
] }) }),
|
|
61823
|
-
/* @__PURE__ */ jsxRuntime.jsx(Step, { n: 4, title: `Which ${subject.many}?`, help: "step_population", children: /* @__PURE__ */ jsxRuntime.jsx(FilterRail, { fields, population, onChange: editPopulation, chip, button, readonly, subjectMany: subject.many }) }),
|
|
62150
|
+
/* @__PURE__ */ jsxRuntime.jsx(Step, { n: 4, title: `Which ${subject.many}?`, help: "step_population", children: /* @__PURE__ */ jsxRuntime.jsx(FilterRail, { fields, population, onChange: editPopulation, chip, button, readonly, subjectMany: subject.many, words }) }),
|
|
61824
62151
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { as: "details", borderTopWidth: "1px", borderColor: "border.subtle", children: [
|
|
61825
62152
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
61826
62153
|
react.Box,
|
|
@@ -61938,10 +62265,11 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
61938
62265
|
subjectMany: subject.many,
|
|
61939
62266
|
higherBetter,
|
|
61940
62267
|
badge,
|
|
61941
|
-
barList
|
|
62268
|
+
barList,
|
|
62269
|
+
words
|
|
61942
62270
|
}
|
|
61943
62271
|
),
|
|
61944
|
-
activeTab === "answer" && !a2 && ref && /* @__PURE__ */ jsxRuntime.jsx(RefusalZone, { refusal: ref, overlap: ov, naiveValue: (shownResult == null ? void 0 : shownResult.naive) ?? 0, outcome: vs.outcomeLabel }),
|
|
62272
|
+
activeTab === "answer" && !a2 && ref && /* @__PURE__ */ jsxRuntime.jsx(RefusalZone, { refusal: ref, overlap: ov, naiveValue: (shownResult == null ? void 0 : shownResult.naive) ?? 0, outcome: vs.outcomeLabel, words }),
|
|
61945
62273
|
activeTab === "trust" && vr && /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { p: "4.5", children: [
|
|
61946
62274
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "body.sm", color: "fg.muted", mb: "3.5", children: /* @__PURE__ */ jsxRuntime.jsx(Help, { id: "trust_intro", children: "Before trusting the answer we tried to break it — colour shows pass / caution." }) }),
|
|
61947
62275
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { layerStyle: "frame.flat", children: vr.checks.map((c2, i) => {
|
|
@@ -61969,6 +62297,7 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
61969
62297
|
zero: 0,
|
|
61970
62298
|
tone: "brand",
|
|
61971
62299
|
xTicks: vr.sens.xTicks,
|
|
62300
|
+
xTickWords: true,
|
|
61972
62301
|
yTicks: vr.sens.yTicks,
|
|
61973
62302
|
marks: vr.sens.marks,
|
|
61974
62303
|
height: vr.sens.marks.length ? 148 : 132
|
|
@@ -62014,13 +62343,13 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
62014
62343
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", flexDirection: "column", gap: "0.5", children: [
|
|
62015
62344
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "caption.eyebrow", children: vd.recoLabel }),
|
|
62016
62345
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", alignItems: "baseline", gap: "2", children: [
|
|
62017
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "mono-kpi", fontFamily: "heading", color: "brand.solid", children: signed(vd.recoEffect) }),
|
|
62346
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "mono-kpi", fontFamily: "heading", color: "brand.solid", children: signed(vd.recoEffect, words) }),
|
|
62018
62347
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Text, { textStyle: "mono.sm", color: "fg.muted", children: [
|
|
62019
62348
|
vd.outcome,
|
|
62020
62349
|
" · ",
|
|
62021
|
-
signed(vd.recoLo),
|
|
62350
|
+
signed(vd.recoLo, words),
|
|
62022
62351
|
" … ",
|
|
62023
|
-
signed(vd.recoHi)
|
|
62352
|
+
signed(vd.recoHi, words)
|
|
62024
62353
|
] })
|
|
62025
62354
|
] })
|
|
62026
62355
|
] }),
|
|
@@ -62032,7 +62361,7 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
62032
62361
|
vd.outcome,
|
|
62033
62362
|
" per step"
|
|
62034
62363
|
] }),
|
|
62035
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { py: "0.5", maxH: "200px", overflowY: "auto", children: barList(vd.marginal.map((m2, i) => ({ label: m2.label, frac: m2.frac, tone: i < 2 ? "brand" : "muted", value: signed(m2.value) }))) })
|
|
62364
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { py: "0.5", maxH: "200px", overflowY: "auto", children: barList(vd.marginal.map((m2, i) => ({ label: m2.label, frac: m2.frac, tone: i < 2 ? "brand" : "muted", value: signed(m2.value, words) }))) })
|
|
62036
62365
|
] })
|
|
62037
62366
|
] })
|
|
62038
62367
|
] }),
|
|
@@ -62050,7 +62379,7 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
62050
62379
|
" tab for why)."
|
|
62051
62380
|
] })
|
|
62052
62381
|
] }),
|
|
62053
|
-
activeTab === "validate" && (design.status === "failed" && design.error ? /* @__PURE__ */ jsxRuntime.jsx(react.Box, { px: "4.5", pt: "4.5", children: /* @__PURE__ */ jsxRuntime.jsx(RunError, { error: design.error }) }) : designFresh && vmDesign ? /* @__PURE__ */ jsxRuntime.jsx(ValidatePanel, { vm: vmDesign, barList }) : !hasDesign && precomputedDesign === null ? /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { p: "4.5", children: [
|
|
62382
|
+
activeTab === "validate" && (design.status === "failed" && design.error ? /* @__PURE__ */ jsxRuntime.jsx(react.Box, { px: "4.5", pt: "4.5", children: /* @__PURE__ */ jsxRuntime.jsx(RunError, { error: design.error }) }) : designFresh && vmDesign ? /* @__PURE__ */ jsxRuntime.jsx(ValidatePanel, { vm: vmDesign, barList, words }) : !hasDesign && precomputedDesign === null ? /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { p: "4.5", children: [
|
|
62054
62383
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "inline-flex", alignItems: "center", gap: "2", mb: "2", color: "fg.muted", children: [
|
|
62055
62384
|
/* @__PURE__ */ jsxRuntime.jsx(FontAwesomeIcon, { icon: faTriangleExclamation, style: { fontSize: "13px" } }),
|
|
62056
62385
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "body.sm", fontWeight: "semibold", color: "fg.default", children: "No trial recipe for this question" })
|
|
@@ -62067,7 +62396,7 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
62067
62396
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: es.root, bg: "bg.canvas", borderTopWidth: "1px", borderColor: "border.subtle", children: [
|
|
62068
62397
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: es.lbl, children: /* @__PURE__ */ jsxRuntime.jsx(Help, { id: "journal", children: "Committed experiments" }) }),
|
|
62069
62398
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: es.meta, children: /* @__PURE__ */ jsxRuntime.jsxs(react.Text, { as: "span", children: [
|
|
62070
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "fg.default", fontWeight: "semibold", children: journal.length }),
|
|
62399
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "fg.default", fontWeight: "semibold", children: words.number(journal.length) }),
|
|
62071
62400
|
" on record",
|
|
62072
62401
|
journal.length > 50 ? " · showing newest 50" : ""
|
|
62073
62402
|
] }) })
|
|
@@ -62109,7 +62438,7 @@ const EastChakraExperiment = React.memo(function EastChakraExperiment2({ value }
|
|
|
62109
62438
|
] })
|
|
62110
62439
|
] }) });
|
|
62111
62440
|
}, (prev2, next2) => experimentValueEqual(prev2.value, next2.value) && prev2.storageKey === next2.storageKey);
|
|
62112
|
-
function AnswerNumeric({ a: a2, verdict, narrative, checks, onGoTrust, subjectMany, higherBetter, badge, barList }) {
|
|
62441
|
+
function AnswerNumeric({ a: a2, verdict, narrative, checks, onGoTrust, subjectMany, higherBetter, badge, barList, words }) {
|
|
62113
62442
|
const dirUp = a2.effect > 0;
|
|
62114
62443
|
const statusWord = higherBetter === void 0 ? dirUp ? "Higher" : "Lower" : dirUp === higherBetter ? "Better" : "Worse";
|
|
62115
62444
|
const lowerWord = a2.naive < 0 ? "lower" : "higher";
|
|
@@ -62124,7 +62453,7 @@ function AnswerNumeric({ a: a2, verdict, narrative, checks, onGoTrust, subjectMa
|
|
|
62124
62453
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "mono.sm", color: "fg.muted", children: a2.outcome }),
|
|
62125
62454
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", alignItems: "baseline", gap: "2.5", children: [
|
|
62126
62455
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "mono-kpi", fontFamily: "heading", fontSize: "32px", color: kpiColor, children: /* @__PURE__ */ jsxRuntime.jsxs(Help, { id: "answer_effect", children: [
|
|
62127
|
-
signed(a2.effect),
|
|
62456
|
+
signed(a2.effect, words),
|
|
62128
62457
|
a2.unit ? /* @__PURE__ */ jsxRuntime.jsxs(react.Text, { as: "span", fontSize: "16px", color: "fg.muted", children: [
|
|
62129
62458
|
" ",
|
|
62130
62459
|
a2.unit
|
|
@@ -62132,9 +62461,9 @@ function AnswerNumeric({ a: a2, verdict, narrative, checks, onGoTrust, subjectMa
|
|
|
62132
62461
|
] }) }),
|
|
62133
62462
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "mono.sm", color: "fg.muted", children: /* @__PURE__ */ jsxRuntime.jsxs(Help, { id: "answer_ci", children: [
|
|
62134
62463
|
"likely between ",
|
|
62135
|
-
signed(a2.lo),
|
|
62464
|
+
signed(a2.lo, words),
|
|
62136
62465
|
" and ",
|
|
62137
|
-
signed(a2.hi)
|
|
62466
|
+
signed(a2.hi, words)
|
|
62138
62467
|
] }) })
|
|
62139
62468
|
] })
|
|
62140
62469
|
] }),
|
|
@@ -62198,7 +62527,7 @@ function AnswerNumeric({ a: a2, verdict, narrative, checks, onGoTrust, subjectMa
|
|
|
62198
62527
|
" on ",
|
|
62199
62528
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontWeight: "semibold", children: a2.outcome }),
|
|
62200
62529
|
" (",
|
|
62201
|
-
signed(a2.naive),
|
|
62530
|
+
signed(a2.naive, words),
|
|
62202
62531
|
") — but they also differ most on ",
|
|
62203
62532
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontWeight: "semibold", children: top.label }),
|
|
62204
62533
|
" (",
|
|
@@ -62257,13 +62586,13 @@ function AnswerNumeric({ a: a2, verdict, narrative, checks, onGoTrust, subjectMa
|
|
|
62257
62586
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { px: "3.5", pb: "3.5", py: "0.5", maxH: "208px", overflowY: "auto", children: barList(a2.balance.map((b2) => ({ label: b2.label, frac: b2.frac, tone: b2.tone, value: b2.display }))) })
|
|
62258
62587
|
] }),
|
|
62259
62588
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { mt: "3.5", children: /* @__PURE__ */ jsxRuntime.jsx(Help, { id: "counts", display: "inline-flex", gap: "4", children: [[a2.nTotal, subjectMany], [a2.nCompared, "compared like-for-like"], [a2.nDropped, "had no fair match"]].map(([n2, label], i) => /* @__PURE__ */ jsxRuntime.jsxs(react.Text, { textStyle: "mono.sm", color: "fg.muted", children: [
|
|
62260
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "fg.default", fontWeight: "semibold", children:
|
|
62589
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "fg.default", fontWeight: "semibold", children: words.number(n2) }),
|
|
62261
62590
|
" ",
|
|
62262
62591
|
label
|
|
62263
62592
|
] }, i)) }) })
|
|
62264
62593
|
] });
|
|
62265
62594
|
}
|
|
62266
|
-
function RefusalZone({ refusal, overlap, naiveValue, outcome }) {
|
|
62595
|
+
function RefusalZone({ refusal, overlap, naiveValue, outcome, words }) {
|
|
62267
62596
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { p: "4.5", children: [
|
|
62268
62597
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "inline-flex", alignItems: "center", gap: "2", mb: "2", color: "fg.warning", children: [
|
|
62269
62598
|
/* @__PURE__ */ jsxRuntime.jsx(FontAwesomeIcon, { icon: faTriangleExclamation, style: { fontSize: "14px" } }),
|
|
@@ -62286,11 +62615,11 @@ function RefusalZone({ refusal, overlap, naiveValue, outcome }) {
|
|
|
62286
62615
|
"Raw average difference in ",
|
|
62287
62616
|
outcome,
|
|
62288
62617
|
" (context only, not an answer): ",
|
|
62289
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontFamily: "mono", color: "fg.muted", children: signed(naiveValue) })
|
|
62618
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontFamily: "mono", color: "fg.muted", children: signed(naiveValue, words) })
|
|
62290
62619
|
] })
|
|
62291
62620
|
] });
|
|
62292
62621
|
}
|
|
62293
|
-
function ValidatePanel({ vm, barList }) {
|
|
62622
|
+
function ValidatePanel({ vm, barList, words }) {
|
|
62294
62623
|
const stat = react.useSlotRecipe({ key: "stat" })({ size: "lg" });
|
|
62295
62624
|
const meter = react.useSlotRecipe({ key: "segmentedMeter" })({});
|
|
62296
62625
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { p: "4.5", children: [
|
|
@@ -62298,7 +62627,7 @@ function ValidatePanel({ vm, barList }) {
|
|
|
62298
62627
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", alignItems: "flex-end", gap: "5", flexWrap: "wrap", children: [
|
|
62299
62628
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: stat.root, children: [
|
|
62300
62629
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { css: stat.label, children: /* @__PURE__ */ jsxRuntime.jsx(Help, { id: "validate_size", children: vm.holdback ? "to hold back from" : "to run" }) }),
|
|
62301
|
-
vm.faint ? /* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "body.sm", fontWeight: "semibold", color: "fg.warning", maxW: "220px", children: "Effect too faint to size — set a materiality threshold to size a trial." }) : /* @__PURE__ */ jsxRuntime.jsx(react.Text, { css: stat.valueText, color: "brand.solid", children: vm.primary.nTotal
|
|
62630
|
+
vm.faint ? /* @__PURE__ */ jsxRuntime.jsx(react.Text, { textStyle: "body.sm", fontWeight: "semibold", color: "fg.warning", maxW: "220px", children: "Effect too faint to size — set a materiality threshold to size a trial." }) : /* @__PURE__ */ jsxRuntime.jsx(react.Text, { css: stat.valueText, color: "brand.solid", children: words.number(vm.primary.nTotal) })
|
|
62302
62631
|
] }),
|
|
62303
62632
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: meter.root, flex: "1", minW: "220px", children: [
|
|
62304
62633
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { css: meter.label, children: /* @__PURE__ */ jsxRuntime.jsx(Help, { id: "validate_split", children: vm.holdback ? "Hold-back split" : "Split" }) }),
|
|
@@ -62310,7 +62639,7 @@ function ValidatePanel({ vm, barList }) {
|
|
|
62310
62639
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: meter.keyItem, children: [
|
|
62311
62640
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: meter.keyDot, bg: "brand.solid" }),
|
|
62312
62641
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
62313
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", css: meter.valueText, children: vm.primary.nTreated
|
|
62642
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", css: meter.valueText, children: words.number(vm.primary.nTreated) }),
|
|
62314
62643
|
" ",
|
|
62315
62644
|
vm.holdback ? "treated" : "get it"
|
|
62316
62645
|
] })
|
|
@@ -62318,7 +62647,7 @@ function ValidatePanel({ vm, barList }) {
|
|
|
62318
62647
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: meter.keyItem, children: [
|
|
62319
62648
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: meter.keyDot, bg: "bg.emphasized" }),
|
|
62320
62649
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
62321
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", css: meter.valueText, children: vm.primary.nControl
|
|
62650
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", css: meter.valueText, children: words.number(vm.primary.nControl) }),
|
|
62322
62651
|
" ",
|
|
62323
62652
|
vm.holdback ? "held back" : "left alone"
|
|
62324
62653
|
] })
|
|
@@ -62351,16 +62680,16 @@ function ValidatePanel({ vm, barList }) {
|
|
|
62351
62680
|
vm.alternates.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(react.Box, { display: "flex", flexDirection: "column", gap: "1.5", mt: "3", pt: "3", borderTopWidth: "1px", borderColor: "border.subtle", children: vm.alternates.map((o2, i) => /* @__PURE__ */ jsxRuntime.jsxs(react.Text, { textStyle: "caption", color: "fg.muted", children: [
|
|
62352
62681
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontWeight: "semibold", color: "fg.default", children: o2.label }),
|
|
62353
62682
|
" · ",
|
|
62354
|
-
o2.nTotal
|
|
62683
|
+
words.number(o2.nTotal),
|
|
62355
62684
|
" total (",
|
|
62356
|
-
o2.nTreated
|
|
62685
|
+
words.number(o2.nTreated),
|
|
62357
62686
|
" / ",
|
|
62358
|
-
o2.nControl
|
|
62687
|
+
words.number(o2.nControl),
|
|
62359
62688
|
")"
|
|
62360
62689
|
] }, i)) })
|
|
62361
62690
|
] });
|
|
62362
62691
|
}
|
|
62363
|
-
function FilterRail({ fields, population, onChange: onChange2, chip, button, readonly, subjectMany }) {
|
|
62692
|
+
function FilterRail({ fields, population, onChange: onChange2, chip, button, readonly, subjectMany, words }) {
|
|
62364
62693
|
const [open, setOpen] = React.useState(null);
|
|
62365
62694
|
const replaceAt = (i, p2) => onChange2(population.map((f2, j2) => j2 === i ? p2 : f2));
|
|
62366
62695
|
const removeAt = (i) => onChange2(population.filter((_2, j2) => j2 !== i));
|
|
@@ -62369,7 +62698,7 @@ function FilterRail({ fields, population, onChange: onChange2, chip, button, rea
|
|
|
62369
62698
|
return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { display: "flex", flexWrap: "wrap", gap: "1.5", alignItems: "center", children: population.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: chip({ tone: "plain", numeric: true, shape: "rounded" }), children: [
|
|
62370
62699
|
"all ",
|
|
62371
62700
|
subjectMany
|
|
62372
|
-
] }) : population.map((pred, i) => /* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: chip({ tone: "brand", numeric: true, shape: "rounded" }), flexShrink: 0, children: /* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", whiteSpace: "nowrap", children: eastUiComponents.formatPredicate(pred) }) }, i)) });
|
|
62701
|
+
] }) : population.map((pred, i) => /* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: chip({ tone: "brand", numeric: true, shape: "rounded" }), flexShrink: 0, children: /* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", whiteSpace: "nowrap", children: eastUiComponents.formatPredicate(pred, words) }) }, i)) });
|
|
62373
62702
|
}
|
|
62374
62703
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", flexWrap: "wrap", gap: "1.5", alignItems: "center", children: [
|
|
62375
62704
|
population.map((pred, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -62383,7 +62712,7 @@ function FilterRail({ fields, population, onChange: onChange2, chip, button, rea
|
|
|
62383
62712
|
] }),
|
|
62384
62713
|
footActions: done,
|
|
62385
62714
|
trigger: /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: chip({ tone: "brand", numeric: true, shape: "rounded" }), cursor: "pointer", flexShrink: 0, children: [
|
|
62386
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", whiteSpace: "nowrap", children: eastUiComponents.formatPredicate(pred) }),
|
|
62715
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", whiteSpace: "nowrap", children: eastUiComponents.formatPredicate(pred, words) }),
|
|
62387
62716
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "button", display: "inline-flex", alignItems: "center", cursor: "pointer", color: "brand.fg", flexShrink: "0", fontSize: "10px", onClick: (e3) => {
|
|
62388
62717
|
e3.stopPropagation();
|
|
62389
62718
|
removeAt(i);
|
|
@@ -62509,20 +62838,8 @@ function viewFor(binding) {
|
|
|
62509
62838
|
const patch = binding.patch.type === "some" ? binding.patch.value : void 0;
|
|
62510
62839
|
return defaultBindRuntime.buildBindHandle(types.sourceType, source, patch, binding.mode.type);
|
|
62511
62840
|
}
|
|
62512
|
-
|
|
62513
|
-
|
|
62514
|
-
if (typeof x2 === "bigint") return `${x2}n`;
|
|
62515
|
-
if (x2 instanceof Date) return x2.toISOString();
|
|
62516
|
-
if (east.isEastSet(x2)) return [...x2].sort();
|
|
62517
|
-
if (east.isEastDict(x2)) return [...x2.entries()].sort((a2, b2) => String(a2[0]).localeCompare(String(b2[0])));
|
|
62518
|
-
return x2;
|
|
62519
|
-
});
|
|
62520
|
-
}
|
|
62521
|
-
function hashString2(s2) {
|
|
62522
|
-
let h2 = 5381;
|
|
62523
|
-
for (let i = 0; i < s2.length; i++) h2 = (h2 << 5) + h2 + s2.charCodeAt(i) | 0;
|
|
62524
|
-
return (h2 >>> 0).toString(36);
|
|
62525
|
-
}
|
|
62841
|
+
const printDescriptors = east.printFor(east.StructType({ decisions: east.ArrayType(internal$1.DiffBindingType), judgements: internal$1.DiffBindingType }));
|
|
62842
|
+
const printTypeValue = east.printFor(east.EastTypeValueType);
|
|
62526
62843
|
function readSelectionAt(selectionKey) {
|
|
62527
62844
|
platform.StateRuntime.trackKey(selectionKey);
|
|
62528
62845
|
const bytes = platform.StateRuntime.getStore().read(selectionKey);
|
|
@@ -62564,16 +62881,6 @@ function removeFromOwningView(decisions, caseId) {
|
|
|
62564
62881
|
}
|
|
62565
62882
|
}
|
|
62566
62883
|
const decisionHandleCache = /* @__PURE__ */ new Map();
|
|
62567
|
-
function typeToken(tv) {
|
|
62568
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
62569
|
-
return JSON.stringify(tv, (_k, v3) => {
|
|
62570
|
-
if (typeof v3 === "object" && v3 !== null) {
|
|
62571
|
-
if (seen.has(v3)) return "<cyc>";
|
|
62572
|
-
seen.add(v3);
|
|
62573
|
-
}
|
|
62574
|
-
return typeof v3 === "bigint" ? `${v3}n` : v3;
|
|
62575
|
-
});
|
|
62576
|
-
}
|
|
62577
62884
|
function compileDecisionMethods(constraintType, decisions, judgements, selectionKey) {
|
|
62578
62885
|
const platform$1 = platform.getRegisteredPlatformImplementations();
|
|
62579
62886
|
const c2 = east.fromEastTypeValue(constraintType);
|
|
@@ -62641,7 +62948,7 @@ function buildDecisionHandle(decisions, judgements, constraintType) {
|
|
|
62641
62948
|
const at = (j2) => j2.resolvedAt.type === "some" ? j2.resolvedAt.value.getTime() : 0;
|
|
62642
62949
|
return entries.sort((a2, b2) => at(b2) - at(a2));
|
|
62643
62950
|
};
|
|
62644
|
-
const cacheKey = `${
|
|
62951
|
+
const cacheKey = `${printDescriptors({ decisions, judgements })}|${printTypeValue(east.canonicalTypeValue(cType))}`;
|
|
62645
62952
|
let methods = decisionHandleCache.get(cacheKey);
|
|
62646
62953
|
if (methods === void 0) {
|
|
62647
62954
|
methods = compileDecisionMethods(cType, decisions, judgements, selectionKey);
|
|
@@ -62831,91 +63138,71 @@ const OP_WORDS = {
|
|
|
62831
63138
|
notIn: "not in",
|
|
62832
63139
|
is: "is"
|
|
62833
63140
|
};
|
|
62834
|
-
|
|
62835
|
-
|
|
62836
|
-
|
|
62837
|
-
|
|
62838
|
-
|
|
62839
|
-
|
|
63141
|
+
const PRINTERS = /* @__PURE__ */ new WeakMap();
|
|
63142
|
+
function printerOf(contract) {
|
|
63143
|
+
let printer = PRINTERS.get(contract);
|
|
63144
|
+
if (printer === void 0) {
|
|
63145
|
+
const context = /* @__PURE__ */ new Map();
|
|
63146
|
+
east.printFor(contract.type, context);
|
|
63147
|
+
printer = (type) => east.printFor(type, context);
|
|
63148
|
+
PRINTERS.set(contract, printer);
|
|
62840
63149
|
}
|
|
62841
|
-
|
|
62842
|
-
return Object.entries(v3).map(([k2, x2]) => `${k2} ${formatScalar(x2)}`).join(" · ");
|
|
62843
|
-
}
|
|
62844
|
-
return String(v3);
|
|
63150
|
+
return printer;
|
|
62845
63151
|
}
|
|
62846
|
-
function
|
|
62847
|
-
|
|
62848
|
-
|
|
62849
|
-
|
|
62850
|
-
|
|
62851
|
-
|
|
62852
|
-
|
|
62853
|
-
|
|
62854
|
-
|
|
62855
|
-
const
|
|
62856
|
-
|
|
62857
|
-
return { lever, op: word, value: `${formatScalar(r2.min)} – ${formatScalar(r2.max)}` };
|
|
62858
|
-
}
|
|
63152
|
+
function formatValue(value, type, words, print) {
|
|
63153
|
+
switch (type.type) {
|
|
63154
|
+
case "DateTime":
|
|
63155
|
+
return words.monthDay(value);
|
|
63156
|
+
case "Float":
|
|
63157
|
+
return words.float(value);
|
|
63158
|
+
case "String":
|
|
63159
|
+
return value;
|
|
63160
|
+
case "Set": {
|
|
63161
|
+
const member = type.value;
|
|
63162
|
+
return `{${[...value].map((m2) => formatValue(m2, member, words, print)).join(", ")}}`;
|
|
62859
63163
|
}
|
|
62860
|
-
return { lever, op: word, value: formatScalar(op.value) };
|
|
62861
|
-
}
|
|
62862
|
-
return { lever, op: "·", value: formatScalar(c2.value) };
|
|
62863
|
-
}
|
|
62864
|
-
const PRIMITIVES = /* @__PURE__ */ new Set(["String", "Integer", "Float", "DateTime", "Boolean"]);
|
|
62865
|
-
function normalizeTypeValue(tv) {
|
|
62866
|
-
var _a2;
|
|
62867
|
-
const n2 = tv;
|
|
62868
|
-
if (n2.cases !== void 0 || n2.fields !== void 0) {
|
|
62869
|
-
const out = { type: n2.type };
|
|
62870
|
-
if (n2.cases) out.cases = Object.fromEntries(Object.entries(n2.cases).map(([k2, v3]) => [k2, normalizeTypeValue(v3)]));
|
|
62871
|
-
if (n2.fields) out.fields = Object.fromEntries(Object.entries(n2.fields).map(([k2, v3]) => [k2, normalizeTypeValue(v3)]));
|
|
62872
|
-
if (n2.key) out.key = normalizeTypeValue(n2.key);
|
|
62873
|
-
if (n2.value !== void 0 && (n2.type === "Array" || n2.type === "Dict")) out.value = normalizeTypeValue(n2.value);
|
|
62874
|
-
return out;
|
|
62875
|
-
}
|
|
62876
|
-
switch (n2.type) {
|
|
62877
63164
|
case "Struct":
|
|
62878
|
-
return
|
|
62879
|
-
case "Variant":
|
|
62880
|
-
return { type: "Variant", cases: Object.fromEntries(n2.value.map((f2) => [f2.name, normalizeTypeValue(f2.type)])) };
|
|
62881
|
-
case "Array":
|
|
62882
|
-
return { type: "Array", value: normalizeTypeValue(n2.value) };
|
|
62883
|
-
case "Dict": {
|
|
62884
|
-
const d2 = n2.value;
|
|
62885
|
-
return { type: "Dict", key: normalizeTypeValue(d2.key), value: normalizeTypeValue(d2.value) };
|
|
62886
|
-
}
|
|
62887
|
-
case "Recursive": {
|
|
62888
|
-
const w2 = n2.value;
|
|
62889
|
-
if ((w2 == null ? void 0 : w2.type) === "wrapper" && ((_a2 = w2.value) == null ? void 0 : _a2.inner)) return normalizeTypeValue(w2.value.inner);
|
|
62890
|
-
return { type: n2.type };
|
|
62891
|
-
}
|
|
63165
|
+
return type.value.map((f2) => `${f2.name} ${formatValue(value[f2.name], f2.type, words, print)}`).join(" · ");
|
|
62892
63166
|
default:
|
|
62893
|
-
return
|
|
63167
|
+
return print(type)(value);
|
|
62894
63168
|
}
|
|
62895
63169
|
}
|
|
62896
|
-
function
|
|
62897
|
-
|
|
62898
|
-
|
|
62899
|
-
|
|
62900
|
-
|
|
62901
|
-
|
|
62902
|
-
|
|
62903
|
-
|
|
62904
|
-
|
|
62905
|
-
|
|
62906
|
-
|
|
62907
|
-
|
|
62908
|
-
|
|
62909
|
-
|
|
62910
|
-
|
|
62911
|
-
|
|
63170
|
+
function formatConstraint(constraint, contract, levers, words = eastUiComponents.formatters()) {
|
|
63171
|
+
var _a2;
|
|
63172
|
+
const lever = ((_a2 = levers == null ? void 0 : levers.find((l2) => l2.case === constraint.type)) == null ? void 0 : _a2.label) ?? constraint.type;
|
|
63173
|
+
const payload = contract == null ? void 0 : contract.payloads.get(constraint.type);
|
|
63174
|
+
if (contract === void 0 || payload === void 0) return { lever, op: "·", value: "" };
|
|
63175
|
+
const print = printerOf(contract);
|
|
63176
|
+
if (payload.type === "Variant") {
|
|
63177
|
+
const op = constraint.value;
|
|
63178
|
+
const word = OP_WORDS[op.type] ?? op.type;
|
|
63179
|
+
const opType = payload.value.find((c2) => c2.name === op.type).type;
|
|
63180
|
+
if (opType.type === "Struct") {
|
|
63181
|
+
const fields = opType.value;
|
|
63182
|
+
const min4 = fields.find((f2) => f2.name === "min");
|
|
63183
|
+
const max5 = fields.find((f2) => f2.name === "max");
|
|
63184
|
+
if (min4 !== void 0 && max5 !== void 0) {
|
|
63185
|
+
const range = op.value;
|
|
63186
|
+
return { lever, op: word, value: `${formatValue(range.min, min4.type, words, print)} – ${formatValue(range.max, max5.type, words, print)}` };
|
|
63187
|
+
}
|
|
63188
|
+
}
|
|
63189
|
+
return { lever, op: word, value: formatValue(op.value, opType, words, print) };
|
|
62912
63190
|
}
|
|
63191
|
+
return { lever, op: "·", value: formatValue(constraint.value, payload, words, print) };
|
|
62913
63192
|
}
|
|
62914
|
-
|
|
62915
|
-
|
|
62916
|
-
|
|
62917
|
-
if (
|
|
62918
|
-
if (
|
|
63193
|
+
const PRIMITIVES = /* @__PURE__ */ new Set(["String", "Integer", "Float", "DateTime", "Boolean"]);
|
|
63194
|
+
const NULL_TYPE = east.toEastTypeValue(east.NullType);
|
|
63195
|
+
function emptyFor(type) {
|
|
63196
|
+
if (type.type === "DateTime") return /* @__PURE__ */ new Date();
|
|
63197
|
+
if (type.type === "Struct") return Object.fromEntries(type.value.map((f2) => [f2.name, emptyFor(f2.type)]));
|
|
63198
|
+
return east.defaultValue(type);
|
|
63199
|
+
}
|
|
63200
|
+
function leverPayloadEditable(payload) {
|
|
63201
|
+
if (payload === void 0) return false;
|
|
63202
|
+
const primitive = (t4) => PRIMITIVES.has(t4.type);
|
|
63203
|
+
const structOfPrimitives = (t4) => t4.type === "Struct" && t4.value.every((f2) => primitive(f2.type));
|
|
63204
|
+
if (primitive(payload) || structOfPrimitives(payload)) return true;
|
|
63205
|
+
if (payload.type === "Variant") return payload.value.every((c2) => primitive(c2.type) || structOfPrimitives(c2.type));
|
|
62919
63206
|
return false;
|
|
62920
63207
|
}
|
|
62921
63208
|
const inputStyle = east.some({ size: east.some(east.variant("sm", null)) });
|
|
@@ -62923,17 +63210,17 @@ function LeverEditor({ leverCase, payload, onInject }) {
|
|
|
62923
63210
|
var _a2;
|
|
62924
63211
|
const button = react.useRecipe({ key: "button" });
|
|
62925
63212
|
const isOpVariant = payload.type === "Variant";
|
|
62926
|
-
const ops = React.useMemo(() =>
|
|
63213
|
+
const ops = React.useMemo(() => payload.type === "Variant" ? payload.value.map((c2) => c2.name) : [], [payload]);
|
|
62927
63214
|
const [opTag, setOpTag] = React.useState(ops[0] ?? "");
|
|
62928
|
-
const active =
|
|
63215
|
+
const active = payload.type === "Variant" ? ((_a2 = payload.value.find((c2) => c2.name === opTag)) == null ? void 0 : _a2.type) ?? NULL_TYPE : payload;
|
|
62929
63216
|
const valRef = React.useRef(emptyFor(active));
|
|
62930
63217
|
const keyRef = React.useRef(`${leverCase}:${opTag}`);
|
|
62931
63218
|
if (keyRef.current !== `${leverCase}:${opTag}`) {
|
|
62932
63219
|
keyRef.current = `${leverCase}:${opTag}`;
|
|
62933
63220
|
valRef.current = emptyFor(active);
|
|
62934
63221
|
}
|
|
62935
|
-
const primitiveInput = (
|
|
62936
|
-
switch (
|
|
63222
|
+
const primitiveInput = (type, key, get3, set3) => {
|
|
63223
|
+
switch (type.type) {
|
|
62937
63224
|
case "Integer":
|
|
62938
63225
|
return /* @__PURE__ */ jsxRuntime.jsx(eastUiComponents.EastChakraIntegerInput, { value: { value: get3(), onChange: east.some(set3), style: inputStyle } }, key);
|
|
62939
63226
|
case "Float":
|
|
@@ -62946,7 +63233,7 @@ function LeverEditor({ leverCase, payload, onInject }) {
|
|
|
62946
63233
|
{
|
|
62947
63234
|
ariaLabel: key,
|
|
62948
63235
|
value: {
|
|
62949
|
-
value: east.some(
|
|
63236
|
+
value: east.some(get3() === true ? "true" : "false"),
|
|
62950
63237
|
items: [{ value: "true", label: "true", disabled: east.none }, { value: "false", label: "false", disabled: east.none }],
|
|
62951
63238
|
placeholder: east.none,
|
|
62952
63239
|
multiple: east.none,
|
|
@@ -62959,17 +63246,19 @@ function LeverEditor({ leverCase, payload, onInject }) {
|
|
|
62959
63246
|
},
|
|
62960
63247
|
key
|
|
62961
63248
|
);
|
|
63249
|
+
case "String":
|
|
63250
|
+
return /* @__PURE__ */ jsxRuntime.jsx(eastUiComponents.EastChakraStringInput, { value: { value: get3(), onChange: east.some(set3), style: inputStyle } }, key);
|
|
62962
63251
|
default:
|
|
62963
|
-
return
|
|
63252
|
+
return null;
|
|
62964
63253
|
}
|
|
62965
63254
|
};
|
|
62966
63255
|
const valueControls = React.useMemo(() => {
|
|
62967
63256
|
const k2 = keyRef.current;
|
|
62968
63257
|
if (active.type === "Struct") {
|
|
62969
|
-
return
|
|
63258
|
+
return active.value.map(({ name: field, type }) => /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", alignItems: "center", gap: "6px", minW: 0, children: [
|
|
62970
63259
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", textStyle: "caption.eyebrow", color: "fg.subtle", flexShrink: 0, children: field }),
|
|
62971
63260
|
primitiveInput(
|
|
62972
|
-
|
|
63261
|
+
type,
|
|
62973
63262
|
`${k2}.${field}.in`,
|
|
62974
63263
|
() => valRef.current[field],
|
|
62975
63264
|
(v3) => {
|
|
@@ -63025,11 +63314,12 @@ function LeverEditor({ leverCase, payload, onInject }) {
|
|
|
63025
63314
|
}
|
|
63026
63315
|
);
|
|
63027
63316
|
}
|
|
63028
|
-
function fmt(d2, n2, showSign = false) {
|
|
63029
|
-
return
|
|
63317
|
+
function fmt(words, d2, n2, showSign = false) {
|
|
63318
|
+
return words.value(n2, eastUiComponents.getSomeorUndefined(d2.format), showSign);
|
|
63030
63319
|
}
|
|
63031
63320
|
const caption = { textStyle: "caption.eyebrow", color: "fg.muted" };
|
|
63032
63321
|
const EvidenceFacet = React.memo(function EvidenceFacet2({ decision, children: children2 }) {
|
|
63322
|
+
const words = eastUiComponents.useFormatters();
|
|
63033
63323
|
const stakes = eastUiComponents.getSomeorUndefined(decision.stakes);
|
|
63034
63324
|
const downside = eastUiComponents.getSomeorUndefined(decision.downside);
|
|
63035
63325
|
const confidence = eastUiComponents.getSomeorUndefined(decision.confidence);
|
|
@@ -63045,15 +63335,12 @@ const EvidenceFacet = React.memo(function EvidenceFacet2({ decision, children: c
|
|
|
63045
63335
|
] }),
|
|
63046
63336
|
downside !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63047
63337
|
"if wrong ",
|
|
63048
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontFamily: "mono", fontWeight: "semibold", color: "fg.danger", children: fmt(decision, downside, true) }),
|
|
63338
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontFamily: "mono", fontWeight: "semibold", color: "fg.danger", children: fmt(words, decision, downside, true) }),
|
|
63049
63339
|
" · "
|
|
63050
63340
|
] }),
|
|
63051
63341
|
confidence !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63052
63342
|
"confidence ",
|
|
63053
|
-
/* @__PURE__ */ jsxRuntime.
|
|
63054
|
-
Math.round(confidence * 100),
|
|
63055
|
-
"%"
|
|
63056
|
-
] })
|
|
63343
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontFamily: "mono", fontWeight: "semibold", children: words.percent(confidence) })
|
|
63057
63344
|
] })
|
|
63058
63345
|
] })
|
|
63059
63346
|
] }),
|
|
@@ -63069,8 +63356,9 @@ const EvidenceFacet = React.memo(function EvidenceFacet2({ decision, children: c
|
|
|
63069
63356
|
children2
|
|
63070
63357
|
] });
|
|
63071
63358
|
});
|
|
63359
|
+
const compareValues$1 = east.compareFor(east.FloatType);
|
|
63072
63360
|
function rankOptions(d2) {
|
|
63073
|
-
const alternatives = [...d2.alternatives].sort((a2, b2) => b2.value
|
|
63361
|
+
const alternatives = [...d2.alternatives].sort((a2, b2) => compareValues$1(b2.value, a2.value)).map((a2) => ({
|
|
63074
63362
|
label: a2.label,
|
|
63075
63363
|
value: a2.value,
|
|
63076
63364
|
downside: eastUiComponents.getSomeorUndefined(a2.downside),
|
|
@@ -63090,14 +63378,15 @@ function rankOptions(d2) {
|
|
|
63090
63378
|
...alternatives
|
|
63091
63379
|
].map((o2, i) => ({ ...o2, rank: i + 1 }));
|
|
63092
63380
|
}
|
|
63093
|
-
function metaLine(o2) {
|
|
63381
|
+
function metaLine(o2, words) {
|
|
63094
63382
|
const parts = [];
|
|
63095
63383
|
if (o2.recommended) parts.push("recommended");
|
|
63096
|
-
if (o2.confidence !== void 0) parts.push(`${
|
|
63384
|
+
if (o2.confidence !== void 0) parts.push(`${words.percent(o2.confidence)} conf`);
|
|
63097
63385
|
if (!o2.recommended && o2.note !== void 0) parts.push(o2.note);
|
|
63098
63386
|
return parts.join(" · ");
|
|
63099
63387
|
}
|
|
63100
63388
|
const OptionsFacet = React.memo(function OptionsFacet2({ decision, narrow }) {
|
|
63389
|
+
const words = eastUiComponents.useFormatters();
|
|
63101
63390
|
const options2 = rankOptions(decision);
|
|
63102
63391
|
const maxUp = Math.max(...options2.map((o2) => Math.max(o2.value, 0)), 1e-9);
|
|
63103
63392
|
const maxDown = Math.max(...options2.map((o2) => Math.abs(o2.downside ?? 0)), 1e-9);
|
|
@@ -63113,7 +63402,7 @@ const OptionsFacet = React.memo(function OptionsFacet2({ decision, narrow }) {
|
|
|
63113
63402
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", flexDirection: "column", gap: "10px", children: [
|
|
63114
63403
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Text, { ...caption, color: "fg", children: [
|
|
63115
63404
|
"Options · ",
|
|
63116
|
-
options2.length,
|
|
63405
|
+
words.number(options2.length),
|
|
63117
63406
|
" evaluated"
|
|
63118
63407
|
] }),
|
|
63119
63408
|
options2.map((o2) => /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", flexDirection: "column", gap: "4px", pl: "8px", ...o2.recommended ? { boxShadow: "inset 2px 0 0 var(--chakra-colors-accent-brand)" } : {}, children: [
|
|
@@ -63122,8 +63411,8 @@ const OptionsFacet = React.memo(function OptionsFacet2({ decision, narrow }) {
|
|
|
63122
63411
|
" ",
|
|
63123
63412
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontWeight: o2.recommended ? "semibold" : "normal", children: o2.label })
|
|
63124
63413
|
] }),
|
|
63125
|
-
meter(upLabel, o2.value / maxUp, fmt(decision, o2.value, signed2), signed2 ? "success" : "neutral"),
|
|
63126
|
-
meter("If wrong", (o2.downside ?? 0) / maxDown, o2.downside !== void 0 ? fmt(decision, o2.downside, true) : "—", "danger")
|
|
63414
|
+
meter(upLabel, o2.value / maxUp, fmt(words, decision, o2.value, signed2), signed2 ? "success" : "neutral"),
|
|
63415
|
+
meter("If wrong", (o2.downside ?? 0) / maxDown, o2.downside !== void 0 ? fmt(words, decision, o2.downside, true) : "—", "danger")
|
|
63127
63416
|
] }, o2.rank))
|
|
63128
63417
|
] });
|
|
63129
63418
|
}
|
|
@@ -63131,7 +63420,7 @@ const OptionsFacet = React.memo(function OptionsFacet2({ decision, narrow }) {
|
|
|
63131
63420
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "grid", gridTemplateColumns: "minmax(180px, 1.1fr) 1fr 1fr", alignItems: "baseline", gap: "8px", children: [
|
|
63132
63421
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Text, { ...caption, color: "fg", children: [
|
|
63133
63422
|
"Options · ",
|
|
63134
|
-
options2.length,
|
|
63423
|
+
words.number(options2.length),
|
|
63135
63424
|
" evaluated"
|
|
63136
63425
|
] }),
|
|
63137
63426
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { ...caption, textAlign: "center", children: "If wrong" }),
|
|
@@ -63153,15 +63442,15 @@ const OptionsFacet = React.memo(function OptionsFacet2({ decision, narrow }) {
|
|
|
63153
63442
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { minW: 0, pl: o2.recommended ? "6px" : "0", display: "flex", alignItems: "baseline", gap: "6px", children: [
|
|
63154
63443
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontFamily: "mono", fontSize: "11px", color: "fg.subtle", flexShrink: 0, children: o2.rank }),
|
|
63155
63444
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontSize: "12.5px", fontWeight: o2.recommended ? "semibold" : "normal", flexShrink: 0, children: o2.label }),
|
|
63156
|
-
metaLine(o2) !== "" && /* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontFamily: "mono", fontSize: "10.5px", color: "fg.muted", minW: 0, truncate: true, children: metaLine(o2) })
|
|
63445
|
+
metaLine(o2, words) !== "" && /* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontFamily: "mono", fontSize: "10.5px", color: "fg.muted", minW: 0, truncate: true, children: metaLine(o2, words) })
|
|
63157
63446
|
] }),
|
|
63158
63447
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { display: "flex", justifyContent: "flex-end", alignItems: "center", gap: "6px", height: "16px", children: o2.downside !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63159
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "10.5px", fontFamily: "mono", color: "fg.danger", flexShrink: 0, children: fmt(decision, o2.downside, true) }),
|
|
63448
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "10.5px", fontFamily: "mono", color: "fg.danger", flexShrink: 0, children: fmt(words, decision, o2.downside, true) }),
|
|
63160
63449
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { height: "12px", width: `${Math.round(downFrac * 100)}%`, bg: "fg.danger", opacity: 0.55 })
|
|
63161
63450
|
] }) }),
|
|
63162
63451
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { display: "flex", alignItems: "center", gap: "6px", height: "16px", borderLeftWidth: "1px", borderColor: "border.strong", children: o2.value > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63163
63452
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { height: "12px", width: `${Math.round(upFrac * 100)}%`, bg: signed2 ? "fg.success" : "fg.subtle", opacity: 0.6 }),
|
|
63164
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "10.5px", fontFamily: "mono", color: signed2 ? "fg.success" : "fg.muted", flexShrink: 0, children: fmt(decision, o2.value, signed2) })
|
|
63453
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "10.5px", fontFamily: "mono", color: signed2 ? "fg.success" : "fg.muted", flexShrink: 0, children: fmt(words, decision, o2.value, signed2) })
|
|
63165
63454
|
] }) })
|
|
63166
63455
|
]
|
|
63167
63456
|
},
|
|
@@ -63175,8 +63464,9 @@ const ANSWERS = [
|
|
|
63175
63464
|
{ literal: "no", label: "No" },
|
|
63176
63465
|
{ literal: "unknown", label: "Don't know" }
|
|
63177
63466
|
];
|
|
63178
|
-
const JudgementFacet = React.memo(function JudgementFacet2({ decision, handle,
|
|
63467
|
+
const JudgementFacet = React.memo(function JudgementFacet2({ decision, handle, contract }) {
|
|
63179
63468
|
var _a2;
|
|
63469
|
+
const words = eastUiComponents.useFormatters();
|
|
63180
63470
|
const button = react.useRecipe({ key: "button" });
|
|
63181
63471
|
const input = react.useRecipe({ key: "input" });
|
|
63182
63472
|
const judgement = handle.judgementFor(decision.id);
|
|
@@ -63189,11 +63479,12 @@ const JudgementFacet = React.memo(function JudgementFacet2({ decision, handle, l
|
|
|
63189
63479
|
if (knowledge !== stagedKnowledge) handle.addKnowledge(decision.id, knowledge);
|
|
63190
63480
|
}, [knowledge, stagedKnowledge, handle, decision.id]);
|
|
63191
63481
|
const levers = React.useMemo(
|
|
63192
|
-
() => decision.levers.filter((l2) => leverPayloadEditable(
|
|
63193
|
-
[decision.levers,
|
|
63482
|
+
() => decision.levers.filter((l2) => leverPayloadEditable(contract == null ? void 0 : contract.payloads.get(l2.case))),
|
|
63483
|
+
[decision.levers, contract]
|
|
63194
63484
|
);
|
|
63195
63485
|
const [leverCase, setLeverCase] = React.useState(((_a2 = levers[0]) == null ? void 0 : _a2.case) ?? "");
|
|
63196
63486
|
const activeLever = levers.find((l2) => l2.case === leverCase) ?? levers[0];
|
|
63487
|
+
const activePayload = activeLever === void 0 ? void 0 : contract == null ? void 0 : contract.payloads.get(activeLever.case);
|
|
63197
63488
|
const gate = handle.commitStateFor(decision.id);
|
|
63198
63489
|
const gateHint = (gate == null ? void 0 : gate.type) === "gated" ? gate.value === 1n ? "Answer the judgement question to enable apply" : `Answer the ${gate.value} judgement questions to enable apply` : (gate == null ? void 0 : gate.type) === "blocked" ? "Commit blocked — an answer contradicts the recommendation" : (gate == null ? void 0 : gate.type) === "handoff" ? "Awaiting handoff — an answer was don't know" : null;
|
|
63199
63490
|
const onInject = React.useCallback((constraint) => {
|
|
@@ -63239,8 +63530,7 @@ const JudgementFacet = React.memo(function JudgementFacet2({ decision, handle, l
|
|
|
63239
63530
|
(levers.length > 0 || judgement.constraints.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", flexDirection: "column", gap: "6px", children: [
|
|
63240
63531
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { ...caption, children: "Inject constraint · next run folds it in" }),
|
|
63241
63532
|
judgement.constraints.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(react.Box, { display: "flex", gap: "12px", flexWrap: "wrap", children: judgement.constraints.map((c2, i) => {
|
|
63242
|
-
const
|
|
63243
|
-
const f2 = formatConstraint(c2, leverPayloads[tag], decision.levers);
|
|
63533
|
+
const f2 = formatConstraint(c2, contract, decision.levers, words);
|
|
63244
63534
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Text, { as: "span", fontFamily: "mono", fontSize: "11px", children: [
|
|
63245
63535
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "accent.brand", fontWeight: "semibold", children: f2.lever }),
|
|
63246
63536
|
" ",
|
|
@@ -63249,7 +63539,7 @@ const JudgementFacet = React.memo(function JudgementFacet2({ decision, handle, l
|
|
|
63249
63539
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontWeight: "semibold", children: f2.value })
|
|
63250
63540
|
] }, i);
|
|
63251
63541
|
}) }),
|
|
63252
|
-
activeLever !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", alignItems: "center", gap: "8px", flexWrap: "wrap", children: [
|
|
63542
|
+
activeLever !== void 0 && activePayload !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", alignItems: "center", gap: "8px", flexWrap: "wrap", children: [
|
|
63253
63543
|
levers.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(react.Box, { flexShrink: 0, css: { "& [data-scope=select][data-part=root]": { width: "auto", minWidth: "160px" } }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
63254
63544
|
eastUiComponents.EastChakraSelect,
|
|
63255
63545
|
{
|
|
@@ -63271,7 +63561,7 @@ const JudgementFacet = React.memo(function JudgementFacet2({ decision, handle, l
|
|
|
63271
63561
|
LeverEditor,
|
|
63272
63562
|
{
|
|
63273
63563
|
leverCase: activeLever.case,
|
|
63274
|
-
payload:
|
|
63564
|
+
payload: activePayload,
|
|
63275
63565
|
onInject
|
|
63276
63566
|
},
|
|
63277
63567
|
activeLever.case
|
|
@@ -63294,11 +63584,54 @@ const JudgementFacet = React.memo(function JudgementFacet2({ decision, handle, l
|
|
|
63294
63584
|
] })
|
|
63295
63585
|
] });
|
|
63296
63586
|
});
|
|
63587
|
+
function body(type) {
|
|
63588
|
+
return type.type === "Recursive" && type.value.type === "wrapper" ? type.value.value.inner : type;
|
|
63589
|
+
}
|
|
63590
|
+
function constraintContractOf(judgementsType) {
|
|
63591
|
+
const dict = body(judgementsType);
|
|
63592
|
+
if (dict.type !== "Dict") return void 0;
|
|
63593
|
+
const record = body(dict.value.value);
|
|
63594
|
+
if (record.type !== "Struct") return void 0;
|
|
63595
|
+
const field = record.value.find((f2) => f2.name === "constraints");
|
|
63596
|
+
if (field === void 0) return void 0;
|
|
63597
|
+
const constraints = body(field.type);
|
|
63598
|
+
if (constraints.type !== "Array") return void 0;
|
|
63599
|
+
const contract = constraints.value;
|
|
63600
|
+
const cases = body(contract);
|
|
63601
|
+
if (cases.type !== "Variant") return void 0;
|
|
63602
|
+
return {
|
|
63603
|
+
type: contract,
|
|
63604
|
+
payloads: new Map(cases.value.map((c2) => [c2.name, c2.type]))
|
|
63605
|
+
};
|
|
63606
|
+
}
|
|
63607
|
+
function useConstraintContract(ref) {
|
|
63608
|
+
const workspace = getReactiveDatasetCache().getConfig().workspace ?? "";
|
|
63609
|
+
return React.useMemo(() => {
|
|
63610
|
+
if (ref === null) return void 0;
|
|
63611
|
+
const judgements = getBindingTypes(workspace, ref.judgements.source);
|
|
63612
|
+
return judgements === void 0 ? void 0 : constraintContractOf(judgements.sourceType);
|
|
63613
|
+
}, [ref, workspace]);
|
|
63614
|
+
}
|
|
63297
63615
|
const URGENCY_RANK = {
|
|
63298
63616
|
overdue: 0,
|
|
63299
63617
|
due: 1,
|
|
63300
63618
|
routine: 2
|
|
63301
63619
|
};
|
|
63620
|
+
const compareInstants = east.compareFor(east.DateTimeType);
|
|
63621
|
+
const compareValues = east.compareFor(east.FloatType);
|
|
63622
|
+
function compareByUrgency(a2, b2) {
|
|
63623
|
+
const rank = URGENCY_RANK[a2.urgency.type] - URGENCY_RANK[b2.urgency.type];
|
|
63624
|
+
if (rank !== 0) return rank;
|
|
63625
|
+
const da = a2.deadline.type === "some" ? a2.deadline.value : void 0;
|
|
63626
|
+
const db = b2.deadline.type === "some" ? b2.deadline.value : void 0;
|
|
63627
|
+
if (da !== void 0 && db !== void 0) {
|
|
63628
|
+
const byDeadline = compareInstants(da, db);
|
|
63629
|
+
if (byDeadline !== 0) return byDeadline;
|
|
63630
|
+
} else if (da !== db) {
|
|
63631
|
+
return da === void 0 ? 1 : -1;
|
|
63632
|
+
}
|
|
63633
|
+
return compareValues(b2.value, a2.value);
|
|
63634
|
+
}
|
|
63302
63635
|
const URGENCY_GROUP_LABEL = {
|
|
63303
63636
|
overdue: "Overdue",
|
|
63304
63637
|
due: "Due today",
|
|
@@ -63345,10 +63678,10 @@ const URGENCY_TONE = {
|
|
|
63345
63678
|
};
|
|
63346
63679
|
const EXIT_MS = 560;
|
|
63347
63680
|
const NARROW_PX = 560;
|
|
63348
|
-
function decisionValue(d2, n2, showSign = false) {
|
|
63349
|
-
return
|
|
63681
|
+
function decisionValue(words, d2, n2, showSign = false) {
|
|
63682
|
+
return words.value(n2, eastUiComponents.getSomeorUndefined(d2.format), showSign);
|
|
63350
63683
|
}
|
|
63351
|
-
function deadlineSuffix(d2) {
|
|
63684
|
+
function deadlineSuffix(d2, words) {
|
|
63352
63685
|
const deadline = eastUiComponents.getSomeorUndefined(d2.deadline);
|
|
63353
63686
|
if (deadline === void 0) return "";
|
|
63354
63687
|
if (d2.urgency.type === "overdue") {
|
|
@@ -63357,34 +63690,16 @@ function deadlineSuffix(d2) {
|
|
|
63357
63690
|
if (hours < 48) return ` ${hours}h`;
|
|
63358
63691
|
return ` ${Math.round(hours / 24)}d`;
|
|
63359
63692
|
}
|
|
63360
|
-
if (d2.urgency.type === "due") {
|
|
63361
|
-
const h2 = deadline.getHours();
|
|
63362
|
-
const m2 = deadline.getMinutes();
|
|
63363
|
-
const meridiem = h2 >= 12 ? "pm" : "am";
|
|
63364
|
-
const clock2 = h2 % 12 === 0 ? 12 : h2 % 12;
|
|
63365
|
-
return m2 === 0 ? ` ${clock2}${meridiem}` : ` ${clock2}:${String(m2).padStart(2, "0")}${meridiem}`;
|
|
63366
|
-
}
|
|
63693
|
+
if (d2.urgency.type === "due") return ` ${words.time(deadline)}`;
|
|
63367
63694
|
return "";
|
|
63368
63695
|
}
|
|
63369
|
-
function
|
|
63370
|
-
const cache3 = getReactiveDatasetCache();
|
|
63371
|
-
const workspace = cache3.getConfig().workspace ?? "";
|
|
63372
|
-
return React.useMemo(() => {
|
|
63373
|
-
var _a2, _b2, _c2;
|
|
63374
|
-
if (!ref) return {};
|
|
63375
|
-
const judgements = getBindingTypes(workspace, ref.judgements.source);
|
|
63376
|
-
if (!(judgements == null ? void 0 : judgements.sourceType)) return {};
|
|
63377
|
-
const root2 = normalizeTypeValue(judgements.sourceType);
|
|
63378
|
-
const constraint = (_c2 = (_b2 = (_a2 = root2.value) == null ? void 0 : _a2.fields) == null ? void 0 : _b2["constraints"]) == null ? void 0 : _c2.value;
|
|
63379
|
-
return (constraint == null ? void 0 : constraint.type) === "Variant" ? constraint.cases ?? {} : {};
|
|
63380
|
-
}, [ref, workspace]);
|
|
63381
|
-
}
|
|
63382
|
-
const Row = React.memo(function Row2({ decision, handle, selected: selected2, narrow, leverPayloads, modify, evidence, defaultFacet, facetInclude, apply: apply2, reject: reject2, leaving, storageKey }) {
|
|
63696
|
+
const Row = React.memo(function Row2({ decision, handle, selected: selected2, narrow, contract, modify, evidence, defaultFacet, facetInclude, apply: apply2, reject: reject2, leaving, storageKey }) {
|
|
63383
63697
|
var _a2, _b2;
|
|
63384
63698
|
const dq = react.useSlotRecipe({ key: "decisionQueue" });
|
|
63385
63699
|
const status = react.useSlotRecipe({ key: "status" });
|
|
63386
63700
|
const tabs = react.useSlotRecipe({ key: "facetTabs" });
|
|
63387
63701
|
const button = react.useRecipe({ key: "button" });
|
|
63702
|
+
const words = eastUiComponents.useFormatters();
|
|
63388
63703
|
const rs = dq({});
|
|
63389
63704
|
const ts = tabs({});
|
|
63390
63705
|
const st = status({ status: URGENCY_TONE[decision.urgency.type], size: "md" });
|
|
@@ -63410,10 +63725,15 @@ const Row = React.memo(function Row2({ decision, handle, selected: selected2, na
|
|
|
63410
63725
|
const handleReject = React.useCallback(() => {
|
|
63411
63726
|
reject2(decision);
|
|
63412
63727
|
}, [reject2, decision]);
|
|
63728
|
+
const stageUpdate = handle.update;
|
|
63729
|
+
const updateDecision = React.useCallback((next2) => {
|
|
63730
|
+
stageUpdate(next2);
|
|
63731
|
+
return null;
|
|
63732
|
+
}, [stageUpdate]);
|
|
63413
63733
|
const probe = React.useMemo(() => {
|
|
63414
63734
|
if (!selected2 || facet !== "modify" || !modify) return null;
|
|
63415
|
-
return modify(decision,
|
|
63416
|
-
}, [selected2, facet, modify, decision,
|
|
63735
|
+
return modify(decision, updateDecision);
|
|
63736
|
+
}, [selected2, facet, modify, decision, updateDecision]);
|
|
63417
63737
|
const canvas = React.useMemo(() => {
|
|
63418
63738
|
if (!selected2 || facet !== "evidence" || !evidence) return null;
|
|
63419
63739
|
return evidence(decision);
|
|
@@ -63462,11 +63782,11 @@ const Row = React.memo(function Row2({ decision, handle, selected: selected2, na
|
|
|
63462
63782
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", css: st.indicator }),
|
|
63463
63783
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { as: "span", css: st.label, children: [
|
|
63464
63784
|
decision.urgency.type,
|
|
63465
|
-
deadlineSuffix(decision)
|
|
63785
|
+
deadlineSuffix(decision, words)
|
|
63466
63786
|
] })
|
|
63467
63787
|
] });
|
|
63468
63788
|
const valueSigned = ((_b2 = eastUiComponents.getSomeorUndefined(decision.valueAxis)) == null ? void 0 : _b2.signed) ?? true;
|
|
63469
|
-
const valueText = /* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontFamily: "mono", fontWeight: "semibold", textAlign: "right", ...valueSigned && decision.value >= 0 && selected2 ? { color: "fg.success" } : {}, children: decisionValue(decision, decision.value, valueSigned && selected2) });
|
|
63789
|
+
const valueText = /* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontFamily: "mono", fontWeight: "semibold", textAlign: "right", ...valueSigned && decision.value >= 0 && selected2 ? { color: "fg.success" } : {}, children: decisionValue(words, decision, decision.value, valueSigned && selected2) });
|
|
63470
63790
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: rs.rowShell, ...leaving ? { "data-leaving": leaving } : {}, children: [
|
|
63471
63791
|
narrow ? /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { px: "14px", py: "10px", children: [
|
|
63472
63792
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { display: "flex", justifyContent: "space-between", alignItems: "baseline", children: [
|
|
@@ -63490,7 +63810,7 @@ const Row = React.memo(function Row2({ decision, handle, selected: selected2, na
|
|
|
63490
63810
|
selected2 && /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { px: narrow ? "14px" : "18px", py: "12px", borderTopWidth: "1px", borderColor: "border.subtle", bg: "bg.canvas", children: [
|
|
63491
63811
|
facet === "evidence" && /* @__PURE__ */ jsxRuntime.jsx(EvidenceFacet, { decision, children: canvas != null && /* @__PURE__ */ jsxRuntime.jsx(eastUiComponents.EastChakraComponent, { value: canvas, storageKey: `${storageKey}-evidence-${decision.id}` }) }),
|
|
63492
63812
|
facet === "options" && /* @__PURE__ */ jsxRuntime.jsx(OptionsFacet, { decision, narrow }),
|
|
63493
|
-
facet === "judgement" && /* @__PURE__ */ jsxRuntime.jsx(JudgementFacet, { decision, handle,
|
|
63813
|
+
facet === "judgement" && /* @__PURE__ */ jsxRuntime.jsx(JudgementFacet, { decision, handle, contract }),
|
|
63494
63814
|
facet === "modify" && probe != null && /* @__PURE__ */ jsxRuntime.jsx(eastUiComponents.EastChakraComponent, { value: probe, storageKey: `${storageKey}-modify-${decision.id}` })
|
|
63495
63815
|
] })
|
|
63496
63816
|
] });
|
|
@@ -63499,6 +63819,7 @@ const RoutineGroup = React.memo(function RoutineGroup2({ routine, acceptAll, lea
|
|
|
63499
63819
|
const dq = react.useSlotRecipe({ key: "decisionQueue" });
|
|
63500
63820
|
const status = react.useSlotRecipe({ key: "status" });
|
|
63501
63821
|
const button = react.useRecipe({ key: "button" });
|
|
63822
|
+
const words = eastUiComponents.useFormatters();
|
|
63502
63823
|
const rs = dq({});
|
|
63503
63824
|
const st = status({ status: "neutral", size: "md" });
|
|
63504
63825
|
const total = React.useMemo(() => routine.reduce((acc, d2) => acc + d2.value, 0), [routine]);
|
|
@@ -63520,15 +63841,15 @@ const RoutineGroup = React.memo(function RoutineGroup2({ routine, acceptAll, lea
|
|
|
63520
63841
|
d2.kind
|
|
63521
63842
|
] })
|
|
63522
63843
|
] }),
|
|
63523
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: rs.routineValue, children: decisionValue(d2, d2.value) })
|
|
63844
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: rs.routineValue, children: decisionValue(words, d2, d2.value) })
|
|
63524
63845
|
] }) }, d2.id)),
|
|
63525
63846
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: rs.summary, ...narrow ? { marginLeft: "0", flexWrap: "wrap" } : {}, children: [
|
|
63526
63847
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { as: "span", css: rs.summaryCap, children: [
|
|
63527
|
-
routine.length,
|
|
63848
|
+
words.number(routine.length),
|
|
63528
63849
|
" routine"
|
|
63529
63850
|
] }),
|
|
63530
63851
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "fg.subtle", children: "·" }),
|
|
63531
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontFamily: "mono", fontWeight: "semibold", children:
|
|
63852
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", fontFamily: "mono", fontWeight: "semibold", children: words.value(total, format2) }),
|
|
63532
63853
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "fg.muted", children: "total" }),
|
|
63533
63854
|
acceptAll && /* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "button", css: button({ variant: "solid", size: "xs" }), ml: "auto", onClick: handleAcceptAll, children: "Accept all" })
|
|
63534
63855
|
] })
|
|
@@ -63537,6 +63858,7 @@ const RoutineGroup = React.memo(function RoutineGroup2({ routine, acceptAll, lea
|
|
|
63537
63858
|
const GroupHead = React.memo(function GroupHead2({ group: group2, collapsible, collapsed, onToggle, acceptAll }) {
|
|
63538
63859
|
const dq = react.useSlotRecipe({ key: "decisionQueue" });
|
|
63539
63860
|
const button = react.useRecipe({ key: "button" });
|
|
63861
|
+
const words = eastUiComponents.useFormatters();
|
|
63540
63862
|
const rs = dq({});
|
|
63541
63863
|
const format2 = group2.decisions[0] ? eastUiComponents.getSomeorUndefined(group2.decisions[0].format) : void 0;
|
|
63542
63864
|
const handleToggle = React.useCallback(() => {
|
|
@@ -63551,11 +63873,11 @@ const GroupHead = React.memo(function GroupHead2({ group: group2, collapsible, c
|
|
|
63551
63873
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { as: "span", css: rs.groupLabel, children: [
|
|
63552
63874
|
group2.label,
|
|
63553
63875
|
" · ",
|
|
63554
|
-
group2.decisions.length
|
|
63876
|
+
words.number(group2.decisions.length)
|
|
63555
63877
|
] }),
|
|
63556
63878
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { as: "span", css: rs.groupSummary, children: [
|
|
63557
|
-
|
|
63558
|
-
group2.pastSla > 0 ? ` · ${group2.pastSla} past SLA` : ""
|
|
63879
|
+
words.value(group2.total, format2),
|
|
63880
|
+
group2.pastSla > 0 ? ` · ${words.number(group2.pastSla)} past SLA` : ""
|
|
63559
63881
|
] }),
|
|
63560
63882
|
acceptAll && /* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "button", css: button({ variant: "solid", size: "xs" }), onClick: handleAcceptAll, children: "Accept all" })
|
|
63561
63883
|
] });
|
|
@@ -63567,10 +63889,11 @@ const EastChakraDecisionQueue = React.memo(function EastChakraDecisionQueue2({ v
|
|
|
63567
63889
|
const dq = react.useSlotRecipe({ key: "decisionQueue" });
|
|
63568
63890
|
const qs = dq({});
|
|
63569
63891
|
const chip = react.useRecipe({ key: "chip" });
|
|
63892
|
+
const words = eastUiComponents.useFormatters();
|
|
63570
63893
|
const handleRef = value.handle;
|
|
63571
63894
|
const handle = useDecisionHandle(handleRef);
|
|
63572
63895
|
const decisions = handle.decisions;
|
|
63573
|
-
const
|
|
63896
|
+
const contract = useConstraintContract(handleRef);
|
|
63574
63897
|
const railAffordances = eastUiComponents.getSomeorUndefined(value.affordances);
|
|
63575
63898
|
const sliceHandle = eastUiComponents.getSomeorUndefined(value.slice) ?? null;
|
|
63576
63899
|
eastUiComponents.useSliceReactivity(sliceHandle == null ? void 0 : sliceHandle.key);
|
|
@@ -63610,14 +63933,8 @@ const EastChakraDecisionQueue = React.memo(function EastChakraDecisionQueue2({ v
|
|
|
63610
63933
|
const heading = eastUiComponents.getSomeorUndefined(value.heading) ?? "Decisions waiting";
|
|
63611
63934
|
const onApply = React.useMemo(() => eastUiComponents.getSomeorUndefined(value.onApply), [value.onApply]);
|
|
63612
63935
|
const onReject = React.useMemo(() => eastUiComponents.getSomeorUndefined(value.onReject), [value.onReject]);
|
|
63613
|
-
const modify = React.useMemo(
|
|
63614
|
-
|
|
63615
|
-
[value.modify]
|
|
63616
|
-
);
|
|
63617
|
-
const evidence = React.useMemo(
|
|
63618
|
-
() => eastUiComponents.getSomeorUndefined(value.evidence),
|
|
63619
|
-
[value.evidence]
|
|
63620
|
-
);
|
|
63936
|
+
const modify = React.useMemo(() => eastUiComponents.getSomeorUndefined(value.modify), [value.modify]);
|
|
63937
|
+
const evidence = React.useMemo(() => eastUiComponents.getSomeorUndefined(value.evidence), [value.evidence]);
|
|
63621
63938
|
const defaultFacet = ((_a2 = eastUiComponents.getSomeorUndefined(value.defaultFacet)) == null ? void 0 : _a2.type) ?? "evidence";
|
|
63622
63939
|
const facetInclude = React.useMemo(() => {
|
|
63623
63940
|
const facets = eastUiComponents.getSomeorUndefined(value.facets);
|
|
@@ -63666,15 +63983,7 @@ const EastChakraDecisionQueue = React.memo(function EastChakraDecisionQueue2({ v
|
|
|
63666
63983
|
for (const { decision } of exiting.values()) {
|
|
63667
63984
|
if (!merged2.some((d2) => d2.id === decision.id)) merged2.push(decision);
|
|
63668
63985
|
}
|
|
63669
|
-
merged2.sort(
|
|
63670
|
-
var _a3, _b2;
|
|
63671
|
-
const r2 = URGENCY_RANK[a2.urgency.type] - URGENCY_RANK[b2.urgency.type];
|
|
63672
|
-
if (r2 !== 0) return r2;
|
|
63673
|
-
const da = ((_a3 = eastUiComponents.getSomeorUndefined(a2.deadline)) == null ? void 0 : _a3.getTime()) ?? Infinity;
|
|
63674
|
-
const db = ((_b2 = eastUiComponents.getSomeorUndefined(b2.deadline)) == null ? void 0 : _b2.getTime()) ?? Infinity;
|
|
63675
|
-
if (da !== db) return da - db;
|
|
63676
|
-
return b2.value - a2.value;
|
|
63677
|
-
});
|
|
63986
|
+
merged2.sort(compareByUrgency);
|
|
63678
63987
|
return {
|
|
63679
63988
|
merged: merged2,
|
|
63680
63989
|
active: merged2.filter((d2) => d2.urgency.type !== "routine"),
|
|
@@ -63713,7 +64022,7 @@ const EastChakraDecisionQueue = React.memo(function EastChakraDecisionQueue2({ v
|
|
|
63713
64022
|
handle,
|
|
63714
64023
|
selected: selectedId === d2.id,
|
|
63715
64024
|
narrow,
|
|
63716
|
-
|
|
64025
|
+
contract,
|
|
63717
64026
|
modify,
|
|
63718
64027
|
evidence,
|
|
63719
64028
|
defaultFacet,
|
|
@@ -63740,13 +64049,13 @@ const EastChakraDecisionQueue = React.memo(function EastChakraDecisionQueue2({ v
|
|
|
63740
64049
|
) }),
|
|
63741
64050
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: es.meta, gap: "10px", children: [
|
|
63742
64051
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { as: "span", children: [
|
|
63743
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "fg", fontWeight: "semibold", children: visible }),
|
|
64052
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "fg", fontWeight: "semibold", children: words.number(visible) }),
|
|
63744
64053
|
narrow ? "" : " decisions"
|
|
63745
64054
|
] }),
|
|
63746
64055
|
pastSla > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63747
64056
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { as: "span", css: es.sep, children: "·" }),
|
|
63748
64057
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { as: "span", children: [
|
|
63749
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "fg.danger", fontWeight: "semibold", children: pastSla }),
|
|
64058
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { as: "span", color: "fg.danger", fontWeight: "semibold", children: words.number(pastSla) }),
|
|
63750
64059
|
narrow ? " SLA" : " past SLA"
|
|
63751
64060
|
] })
|
|
63752
64061
|
] })
|
|
@@ -63808,34 +64117,24 @@ function verdictPresentation(verdict) {
|
|
|
63808
64117
|
return { tone: "warning", verb: "handed off", detail: verdict.value !== "" ? verdict.value : null };
|
|
63809
64118
|
}
|
|
63810
64119
|
}
|
|
63811
|
-
function formatResolvedAt(j2) {
|
|
64120
|
+
function formatResolvedAt(j2, words) {
|
|
63812
64121
|
if (j2.resolvedAt.type !== "some") return null;
|
|
63813
64122
|
const d2 = j2.resolvedAt.value;
|
|
63814
|
-
|
|
63815
|
-
const time2 = `${String(d2.getHours()).padStart(2, "0")}:${String(d2.getMinutes()).padStart(2, "0")}`;
|
|
63816
|
-
return `${month} ${d2.getDate()} · ${time2}`;
|
|
64123
|
+
return `${words.monthDay(d2)} · ${words.time(d2)}`;
|
|
63817
64124
|
}
|
|
63818
64125
|
const EastChakraDecisionJournal = React.memo(function EastChakraDecisionJournal2({ value }) {
|
|
63819
64126
|
const eyebrow = react.useSlotRecipe({ key: "eyebrowRow" });
|
|
63820
64127
|
const status = react.useSlotRecipe({ key: "status" });
|
|
63821
64128
|
const es = eyebrow({});
|
|
64129
|
+
const words = eastUiComponents.useFormatters();
|
|
63822
64130
|
const handle = useDecisionHandle(value.handle);
|
|
63823
64131
|
const heading = eastUiComponents.getSomeorUndefined(value.heading) ?? "Decision journal";
|
|
63824
|
-
const
|
|
63825
|
-
const workspace = cache3.getConfig().workspace ?? "";
|
|
63826
|
-
const leverPayloads = React.useMemo(() => {
|
|
63827
|
-
var _a2, _b2, _c2;
|
|
63828
|
-
const judgements = getBindingTypes(workspace, value.handle.judgements.source);
|
|
63829
|
-
if (!(judgements == null ? void 0 : judgements.sourceType)) return {};
|
|
63830
|
-
const root2 = normalizeTypeValue(judgements.sourceType);
|
|
63831
|
-
const constraint = (_c2 = (_b2 = (_a2 = root2.value) == null ? void 0 : _a2.fields) == null ? void 0 : _b2["constraints"]) == null ? void 0 : _c2.value;
|
|
63832
|
-
return (constraint == null ? void 0 : constraint.type) === "Variant" ? constraint.cases ?? {} : {};
|
|
63833
|
-
}, [workspace, value.handle]);
|
|
64132
|
+
const contract = useConstraintContract(value.handle);
|
|
63834
64133
|
const entries = React.useMemo(() => handle.journal ?? [], [handle.journal]);
|
|
63835
64134
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { borderWidth: "1px", borderColor: "border.strong", borderRadius: "6px", background: "bg.canvas", overflow: "hidden", children: [
|
|
63836
64135
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Box, { css: es.root, children: [
|
|
63837
64136
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: es.lbl, children: heading }),
|
|
63838
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: es.meta, children: entries.length === 1 ? "1 entry" : `${entries.length} entries` })
|
|
64137
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { css: es.meta, children: entries.length === 1 ? "1 entry" : `${words.number(entries.length)} entries` })
|
|
63839
64138
|
] }),
|
|
63840
64139
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
63841
64140
|
react.Box,
|
|
@@ -63847,7 +64146,7 @@ const EastChakraDecisionJournal = React.memo(function EastChakraDecisionJournal2
|
|
|
63847
64146
|
if (!verdict) return null;
|
|
63848
64147
|
const { tone, verb, detail } = verdictPresentation(verdict);
|
|
63849
64148
|
const st = status({ status: tone, size: "md" });
|
|
63850
|
-
const when = formatResolvedAt(j2);
|
|
64149
|
+
const when = formatResolvedAt(j2, words);
|
|
63851
64150
|
const knowledge = j2.knowledge.type === "some" && j2.knowledge.value !== "" ? j2.knowledge.value : null;
|
|
63852
64151
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
63853
64152
|
react.Box,
|
|
@@ -63886,8 +64185,7 @@ const EastChakraDecisionJournal = React.memo(function EastChakraDecisionJournal2
|
|
|
63886
64185
|
}
|
|
63887
64186
|
),
|
|
63888
64187
|
j2.constraints.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(react.Box, { display: "flex", gap: "12px", flexWrap: "wrap", children: j2.constraints.map((c2, k2) => {
|
|
63889
|
-
const
|
|
63890
|
-
const f2 = formatConstraint(c2, leverPayloads[tag]);
|
|
64188
|
+
const f2 = formatConstraint(c2, contract, void 0, words);
|
|
63891
64189
|
return /* @__PURE__ */ jsxRuntime.jsx(eastUiComponents.ClauseChip, { field: f2.lever, op: f2.op, value: f2.value }, k2);
|
|
63892
64190
|
}) })
|
|
63893
64191
|
]
|
|
@@ -64206,6 +64504,7 @@ function useDatasetValue(apiUrl, repo, workspace, datasetPath, options2) {
|
|
|
64206
64504
|
const { requestOptions, queryOverrides, enabled = true, hash: hash2, platforms, type } = options2;
|
|
64207
64505
|
const platformImpls = platforms ?? defaultPlatformImplementations;
|
|
64208
64506
|
const reqOpts = requestOptions ?? { token: null };
|
|
64507
|
+
const queryClient = reactQuery.useQueryClient();
|
|
64209
64508
|
const pathParts = React.useMemo(
|
|
64210
64509
|
() => (datasetPath == null ? void 0 : datasetPath.split(".").filter(Boolean).map((v3) => east.variant("field", v3))) ?? [],
|
|
64211
64510
|
[datasetPath]
|
|
@@ -64215,8 +64514,14 @@ function useDatasetValue(apiUrl, repo, workspace, datasetPath, options2) {
|
|
|
64215
64514
|
queryFn: async () => {
|
|
64216
64515
|
const result = await e3ApiClient.datasetGet(apiUrl, repo, workspace, pathParts, reqOpts);
|
|
64217
64516
|
const decoded = east.decodeBeast2For(type, { platform: platformImpls })(result.data);
|
|
64218
|
-
|
|
64517
|
+
const value = { decoded, sizeBytes: result.data.length, hash: result.hash ?? hash2 ?? null };
|
|
64518
|
+
if (value.hash !== hash2) {
|
|
64519
|
+
queryClient.setQueryData(["datasetValue", apiUrl, repo, workspace, datasetPath, value.hash], value);
|
|
64520
|
+
void queryClient.invalidateQueries({ queryKey: ["datasetStatus", apiUrl, repo, workspace, datasetPath] });
|
|
64521
|
+
}
|
|
64522
|
+
return value;
|
|
64219
64523
|
},
|
|
64524
|
+
select: (value) => value.hash === (hash2 ?? null) ? value : void 0,
|
|
64220
64525
|
enabled: enabled && !!workspace && !!datasetPath && hash2 != null,
|
|
64221
64526
|
...queryOverrides
|
|
64222
64527
|
});
|
|
@@ -64282,14 +64587,6 @@ function useTaskDetails(apiUrl, repo, workspace, taskName, options2) {
|
|
|
64282
64587
|
...options2 == null ? void 0 : options2.queryOverrides
|
|
64283
64588
|
});
|
|
64284
64589
|
}
|
|
64285
|
-
function getTaskKind(details) {
|
|
64286
|
-
var _a2;
|
|
64287
|
-
return ((_a2 = details.kind) == null ? void 0 : _a2.type) === "some" ? details.kind.value : null;
|
|
64288
|
-
}
|
|
64289
|
-
function getTaskMetadata(details) {
|
|
64290
|
-
var _a2;
|
|
64291
|
-
return ((_a2 = details.metadata) == null ? void 0 : _a2.type) === "some" ? details.metadata.value : null;
|
|
64292
|
-
}
|
|
64293
64590
|
const variantStyles = {
|
|
64294
64591
|
// Mode-aware semantic tokens (the raw `red.50` / `gray.50` washes rendered
|
|
64295
64592
|
// as bright light boxes in dark mode — #362).
|
|
@@ -64427,6 +64724,10 @@ function pagingDebug(...args) {
|
|
|
64427
64724
|
console.info("[e3-paging]", ...args);
|
|
64428
64725
|
}
|
|
64429
64726
|
const PAGE_SIZE = 500;
|
|
64727
|
+
function servedPageSize(requested, page) {
|
|
64728
|
+
const trimmed = page.count < requested && page.offset + page.count < page.totalElements;
|
|
64729
|
+
return trimmed ? Math.max(1, page.count) : requested;
|
|
64730
|
+
}
|
|
64430
64731
|
const MAX_RETAINED_PAGES = 8;
|
|
64431
64732
|
function pageRows(type, decoded, offset) {
|
|
64432
64733
|
if (type.type === "Array") {
|
|
@@ -64466,6 +64767,7 @@ const PagedDatasetPreview = React.memo(function PagedDatasetPreview2({
|
|
|
64466
64767
|
onDownload,
|
|
64467
64768
|
onNotIndexed
|
|
64468
64769
|
}) {
|
|
64770
|
+
const words = eastUiComponents.useFormatters();
|
|
64469
64771
|
const queryClient = reactQuery.useQueryClient();
|
|
64470
64772
|
const [pages, setPages] = React.useState(/* @__PURE__ */ new Map());
|
|
64471
64773
|
const [totals, setTotals] = React.useState(null);
|
|
@@ -64473,48 +64775,69 @@ const PagedDatasetPreview = React.memo(function PagedDatasetPreview2({
|
|
|
64473
64775
|
const [error3, setError] = React.useState(null);
|
|
64474
64776
|
const [jumpRow, setJumpRow] = React.useState(void 0);
|
|
64475
64777
|
const inflightRef = React.useRef(/* @__PURE__ */ new Set());
|
|
64778
|
+
const shownRef = React.useRef({ path: path2, hash: hash2 });
|
|
64779
|
+
const [pageSize, setPageSize] = React.useState(PAGE_SIZE);
|
|
64780
|
+
const pageSizeRef = React.useRef(PAGE_SIZE);
|
|
64476
64781
|
React.useEffect(() => {
|
|
64477
64782
|
pagingDebug(`reset (path=${path2}, hash=${hash2.slice(0, 8)})`);
|
|
64783
|
+
shownRef.current = { path: path2, hash: hash2 };
|
|
64478
64784
|
setPages(/* @__PURE__ */ new Map());
|
|
64479
64785
|
setTotals(null);
|
|
64480
64786
|
setError(null);
|
|
64481
64787
|
setJumpRow(void 0);
|
|
64482
|
-
inflightRef.current
|
|
64788
|
+
inflightRef.current = /* @__PURE__ */ new Set();
|
|
64789
|
+
pageSizeRef.current = PAGE_SIZE;
|
|
64790
|
+
setPageSize(PAGE_SIZE);
|
|
64483
64791
|
}, [path2, hash2]);
|
|
64484
64792
|
const loadPage = React.useCallback((pageIdx) => {
|
|
64485
|
-
|
|
64486
|
-
|
|
64793
|
+
const inflight = inflightRef.current;
|
|
64794
|
+
if (inflight.has(pageIdx)) return;
|
|
64795
|
+
inflight.add(pageIdx);
|
|
64796
|
+
const current = () => shownRef.current.path === path2 && shownRef.current.hash === hash2;
|
|
64797
|
+
const size3 = pageSizeRef.current;
|
|
64487
64798
|
setLoadingCount((n2) => n2 + 1);
|
|
64488
|
-
pagingDebug(`fetch p${pageIdx} (offset=${pageIdx *
|
|
64799
|
+
pagingDebug(`fetch p${pageIdx} (offset=${pageIdx * size3}, limit=${size3}, hash=${hash2.slice(0, 8)})`);
|
|
64489
64800
|
const pathParts2 = path2.split(".").filter(Boolean).map((v3) => east.variant("field", v3));
|
|
64490
64801
|
const reqOpts = requestOptions ?? { token: null };
|
|
64491
64802
|
queryClient.fetchQuery({
|
|
64492
|
-
queryKey: ["datasetPage", apiUrl, repo, workspace, path2, hash2, `p${pageIdx}`],
|
|
64803
|
+
queryKey: ["datasetPage", apiUrl, repo, workspace, path2, hash2, `p${pageIdx}@${size3}`],
|
|
64493
64804
|
// Hash-pinned: the URL is a pure function of the bytes, so any
|
|
64494
64805
|
// HTTP cache between here and the server can hold it immutably.
|
|
64495
|
-
queryFn: () => e3ApiClient.datasetGetPage(apiUrl, repo, workspace, pathParts2, { offset: pageIdx *
|
|
64806
|
+
queryFn: () => e3ApiClient.datasetGetPage(apiUrl, repo, workspace, pathParts2, { offset: pageIdx * size3, limit: size3, hash: hash2 }, reqOpts),
|
|
64496
64807
|
staleTime: Infinity
|
|
64497
64808
|
// pages of one content hash are immutable
|
|
64498
64809
|
}).then((page) => {
|
|
64810
|
+
if (!current()) return;
|
|
64811
|
+
if (size3 !== pageSizeRef.current) return;
|
|
64499
64812
|
const decoded = east.decodeBeast2For(type)(page.data);
|
|
64500
64813
|
const rows = pageRows(type, decoded, page.offset);
|
|
64501
64814
|
pagingDebug(
|
|
64502
64815
|
`p${pageIdx} ok: count=${page.count} rows=${rows.length} offset=${page.offset} total=${page.totalElements} segs=${page.segmentCount}`,
|
|
64503
64816
|
rows.length > 0 ? `first=${JSON.stringify(rows[0].label ?? "(derived)")}` : "(empty)"
|
|
64504
64817
|
);
|
|
64505
|
-
if (page.count < PAGE_SIZE && page.offset + page.count < page.totalElements) {
|
|
64506
|
-
pagingDebug(`p${pageIdx} SHORT page: server clamped ${PAGE_SIZE} → ${page.count}`);
|
|
64507
|
-
}
|
|
64508
64818
|
setTotals({ elements: page.totalElements, bytes: page.totalBytes });
|
|
64509
|
-
|
|
64819
|
+
const served = servedPageSize(size3, page);
|
|
64820
|
+
if (served === size3) {
|
|
64821
|
+
setPages((prev2) => new Map(prev2).set(pageIdx, rows));
|
|
64822
|
+
return;
|
|
64823
|
+
}
|
|
64824
|
+
pagingDebug(`p${pageIdx} SHORT page: served ${page.count} of ${size3} — addressing pages by ${served}`);
|
|
64825
|
+
pageSizeRef.current = served;
|
|
64826
|
+
setPageSize(served);
|
|
64827
|
+
setPages(pageIdx === 0 ? /* @__PURE__ */ new Map([[0, rows]]) : /* @__PURE__ */ new Map());
|
|
64510
64828
|
}).catch((err) => {
|
|
64511
64829
|
pagingDebug(`p${pageIdx} FAILED:`, err);
|
|
64830
|
+
if (!current()) return;
|
|
64831
|
+
if (err instanceof e3ApiClient.DatasetHashMismatchError) {
|
|
64832
|
+
void queryClient.invalidateQueries({ queryKey: ["datasetStatus", apiUrl, repo, workspace, path2] });
|
|
64833
|
+
return;
|
|
64834
|
+
}
|
|
64512
64835
|
if (err instanceof e3ApiClient.ApiError && err.code === "dataset_not_indexed") {
|
|
64513
64836
|
onNotIndexed == null ? void 0 : onNotIndexed();
|
|
64514
64837
|
}
|
|
64515
64838
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
64516
64839
|
}).finally(() => {
|
|
64517
|
-
|
|
64840
|
+
inflight.delete(pageIdx);
|
|
64518
64841
|
setLoadingCount((n2) => n2 - 1);
|
|
64519
64842
|
});
|
|
64520
64843
|
}, [queryClient, apiUrl, repo, workspace, path2, hash2, requestOptions, type, onNotIndexed]);
|
|
@@ -64522,8 +64845,8 @@ const PagedDatasetPreview = React.memo(function PagedDatasetPreview2({
|
|
|
64522
64845
|
if (totals === null && error3 === null) loadPage(0);
|
|
64523
64846
|
}, [totals, error3, loadPage]);
|
|
64524
64847
|
const onNeedRows = React.useCallback((startRow, endRow) => {
|
|
64525
|
-
const first2 = Math.max(0, Math.floor(startRow /
|
|
64526
|
-
const last2 = Math.max(first2, Math.ceil(endRow /
|
|
64848
|
+
const first2 = Math.max(0, Math.floor(startRow / pageSize));
|
|
64849
|
+
const last2 = Math.max(first2, Math.ceil(endRow / pageSize) - 1);
|
|
64527
64850
|
const missing = [];
|
|
64528
64851
|
for (let p2 = first2; p2 <= last2; p2++) {
|
|
64529
64852
|
if (!pages.has(p2)) missing.push(p2);
|
|
@@ -64531,7 +64854,7 @@ const PagedDatasetPreview = React.memo(function PagedDatasetPreview2({
|
|
|
64531
64854
|
pagingDebug(`need rows [${startRow}, ${endRow}) → pages ${first2}..${last2}, missing=[${missing.join(",")}], inflight=[${[...inflightRef.current].join(",")}]`);
|
|
64532
64855
|
setPages((prev2) => internal$2.pruneRetainedPages(prev2, first2, last2, MAX_RETAINED_PAGES));
|
|
64533
64856
|
for (const p2 of missing) loadPage(p2);
|
|
64534
|
-
}, [pages, loadPage]);
|
|
64857
|
+
}, [pages, loadPage, pageSize]);
|
|
64535
64858
|
const keyType = React.useMemo(() => type.type === "Dict" ? type.value.key : type.type === "Set" ? type.value : null, [type]);
|
|
64536
64859
|
const pathParts = React.useMemo(() => path2.split(".").filter(Boolean).map((v3) => east.variant("field", v3)), [path2]);
|
|
64537
64860
|
const onFindKey = React.useCallback(async (query) => {
|
|
@@ -64568,11 +64891,11 @@ const PagedDatasetPreview = React.memo(function PagedDatasetPreview2({
|
|
|
64568
64891
|
}), [type]);
|
|
64569
64892
|
const paging = React.useMemo(() => totals === null ? null : {
|
|
64570
64893
|
totalRows: totals.elements,
|
|
64571
|
-
pageSize
|
|
64894
|
+
pageSize,
|
|
64572
64895
|
pages,
|
|
64573
64896
|
onNeedRows,
|
|
64574
64897
|
scrollToRow: jumpRow
|
|
64575
|
-
}, [totals, pages, onNeedRows, jumpRow]);
|
|
64898
|
+
}, [totals, pageSize, pages, onNeedRows, jumpRow]);
|
|
64576
64899
|
if (error3 !== null) {
|
|
64577
64900
|
if (error3 instanceof e3ApiClient.ApiError && error3.code === "dataset_too_large") {
|
|
64578
64901
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Flex, { height: "100%", direction: "column", align: "center", justify: "center", gap: 3, p: 6, children: [
|
|
@@ -64590,11 +64913,11 @@ const PagedDatasetPreview = React.memo(function PagedDatasetPreview2({
|
|
|
64590
64913
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Flex, { direction: "column", height: "100%", overflow: "hidden", children: [
|
|
64591
64914
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Flex, { px: 4, py: 2, gap: 2, align: "center", flexShrink: 0, borderBottom: "1px solid", borderColor: "border.subtle", children: [
|
|
64592
64915
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Text, { fontSize: "xs", color: "fg.muted", whiteSpace: "nowrap", children: [
|
|
64593
|
-
totals.elements
|
|
64916
|
+
words.number(totals.elements),
|
|
64594
64917
|
" ",
|
|
64595
64918
|
itemNoun,
|
|
64596
64919
|
" · ",
|
|
64597
|
-
formatSize(totals.bytes > 0 ? totals.bytes : sizeBytes)
|
|
64920
|
+
formatSize(totals.bytes > 0 ? totals.bytes : sizeBytes, words)
|
|
64598
64921
|
] }),
|
|
64599
64922
|
loadingCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", children: "Loading…" }),
|
|
64600
64923
|
keyType !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -64611,12 +64934,17 @@ const PagedDatasetPreview = React.memo(function PagedDatasetPreview2({
|
|
|
64611
64934
|
] }),
|
|
64612
64935
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { flex: 1, minHeight: 0, overflow: "hidden", children: /* @__PURE__ */ jsxRuntime.jsx(eastUiComponents.EastChakraValueTree, { value: treeValue, storageKey: `${path2}:page`, paging }) })
|
|
64613
64936
|
] });
|
|
64614
|
-
}, (prev2, next2) =>
|
|
64937
|
+
}, (prev2, next2) => {
|
|
64938
|
+
var _a2, _b2;
|
|
64939
|
+
return prev2.apiUrl === next2.apiUrl && prev2.repo === next2.repo && prev2.workspace === next2.workspace && prev2.path === next2.path && prev2.hash === next2.hash && prev2.sizeBytes === next2.sizeBytes && ((_a2 = prev2.requestOptions) == null ? void 0 : _a2.token) === ((_b2 = next2.requestOptions) == null ? void 0 : _b2.token);
|
|
64940
|
+
});
|
|
64615
64941
|
const DEFAULT_SIZE_LIMIT = 200 * 1024;
|
|
64616
|
-
|
|
64617
|
-
|
|
64618
|
-
|
|
64619
|
-
|
|
64942
|
+
const KB_FORMAT = east.variant("number", { minimumFractionDigits: east.some(1n), maximumFractionDigits: east.some(1n), signDisplay: east.none });
|
|
64943
|
+
const MB_FORMAT = east.variant("number", { minimumFractionDigits: east.some(2n), maximumFractionDigits: east.some(2n), signDisplay: east.none });
|
|
64944
|
+
function formatSize(bytes, words = eastUiComponents.formatters()) {
|
|
64945
|
+
if (bytes < 1024) return `${words.number(bytes)} B`;
|
|
64946
|
+
if (bytes < 1024 * 1024) return `${words.value(bytes / 1024, KB_FORMAT)} KB`;
|
|
64947
|
+
return `${words.value(bytes / 1024 / 1024, MB_FORMAT)} MB`;
|
|
64620
64948
|
}
|
|
64621
64949
|
function DownloadButton({ onClick, label }) {
|
|
64622
64950
|
const [downloading, setDownloading] = React.useState(false);
|
|
@@ -64644,6 +64972,7 @@ const DatasetPreview = React.memo(function DatasetPreview2({
|
|
|
64644
64972
|
editable = false
|
|
64645
64973
|
}) {
|
|
64646
64974
|
var _a2;
|
|
64975
|
+
const words = eastUiComponents.useFormatters();
|
|
64647
64976
|
const statusQuery = useDatasetStatus(apiUrl, repo, workspace, path2, {
|
|
64648
64977
|
...requestOptions != null && { requestOptions },
|
|
64649
64978
|
...pollInterval !== void 0 && { pollInterval }
|
|
@@ -64671,12 +65000,29 @@ const DatasetPreview = React.memo(function DatasetPreview2({
|
|
|
64671
65000
|
const setMutation = useDatasetSet(apiUrl, repo, workspace, requestOptions);
|
|
64672
65001
|
const queryClient = reactQuery.useQueryClient();
|
|
64673
65002
|
const decoded = (_a2 = valueQuery.data) == null ? void 0 : _a2.decoded;
|
|
64674
|
-
const
|
|
64675
|
-
|
|
65003
|
+
const edited = React.useRef(null);
|
|
65004
|
+
const writing = React.useRef(0);
|
|
65005
|
+
const writes = React.useRef(Promise.resolve());
|
|
65006
|
+
React.useEffect(() => {
|
|
65007
|
+
if (writing.current === 0) edited.current = null;
|
|
65008
|
+
}, [decoded]);
|
|
65009
|
+
const write = React.useCallback((next2) => {
|
|
65010
|
+
if (workspace == null || path2 == null || type === void 0) return Promise.resolve();
|
|
64676
65011
|
const treePath = path2.split(".").filter(Boolean).map((p2) => east.variant("field", p2));
|
|
64677
65012
|
const data4 = east.encodeBeast2For(type)(next2);
|
|
64678
|
-
|
|
64679
|
-
|
|
65013
|
+
edited.current = { value: next2 };
|
|
65014
|
+
writing.current++;
|
|
65015
|
+
const run = writes.current.then(async () => {
|
|
65016
|
+
await setMutation.mutateAsync({ path: treePath, data: data4 });
|
|
65017
|
+
await queryClient.invalidateQueries({ queryKey: ["datasetStatus", apiUrl, repo, workspace, path2] });
|
|
65018
|
+
});
|
|
65019
|
+
writes.current = run.catch(() => void 0);
|
|
65020
|
+
return run.catch((err) => {
|
|
65021
|
+
edited.current = null;
|
|
65022
|
+
throw err;
|
|
65023
|
+
}).finally(() => {
|
|
65024
|
+
writing.current--;
|
|
65025
|
+
});
|
|
64680
65026
|
}, [apiUrl, repo, workspace, path2, type, setMutation, queryClient]);
|
|
64681
65027
|
const keyType = React.useMemo(() => type === void 0 ? null : type.type === "Dict" ? type.value.key : type.type === "Set" ? type.value : null, [type]);
|
|
64682
65028
|
const inlineKeys = React.useMemo(() => decoded === void 0 || type === void 0 ? null : type.type === "Dict" ? [...decoded.keys()] : type.type === "Set" ? [...decoded.values()] : null, [type, decoded]);
|
|
@@ -64712,11 +65058,12 @@ const DatasetPreview = React.memo(function DatasetPreview2({
|
|
|
64712
65058
|
const treeValue = React.useMemo(() => {
|
|
64713
65059
|
if (type === void 0 || decoded === void 0) return null;
|
|
64714
65060
|
const root2 = eastUi.ValueTree.materialize(type, decoded);
|
|
65061
|
+
const base = () => edited.current !== null ? edited.current.value : decoded;
|
|
64715
65062
|
const wire = editable ? {
|
|
64716
|
-
onEdit: east.some((p2, leaf) => write(eastUi.ValueTree.applyEdit(type,
|
|
64717
|
-
onInsert: east.some((p2) => write(eastUi.ValueTree.applyEdit(type,
|
|
64718
|
-
onRemove: east.some((p2) => write(eastUi.ValueTree.applyEdit(type,
|
|
64719
|
-
onTag: east.some((p2, tag) => write(eastUi.ValueTree.applyEdit(type,
|
|
65063
|
+
onEdit: east.some((p2, leaf) => write(eastUi.ValueTree.applyEdit(type, base(), p2, { kind: "edit", leaf }))),
|
|
65064
|
+
onInsert: east.some((p2) => write(eastUi.ValueTree.applyEdit(type, base(), p2, { kind: "insert" }))),
|
|
65065
|
+
onRemove: east.some((p2) => write(eastUi.ValueTree.applyEdit(type, base(), p2, { kind: "remove" }))),
|
|
65066
|
+
onTag: east.some((p2, tag) => write(eastUi.ValueTree.applyEdit(type, base(), p2, { kind: "tag", tag })))
|
|
64720
65067
|
} : { onEdit: east.none, onInsert: east.none, onRemove: east.none, onTag: east.none };
|
|
64721
65068
|
return { root: root2, ...wire, style: east.some({ height: east.some("100%"), maxHeight: east.none, openDepth: east.none, toolbar: east.some(true) }) };
|
|
64722
65069
|
}, [type, decoded, editable, write]);
|
|
@@ -64750,18 +65097,21 @@ const DatasetPreview = React.memo(function DatasetPreview2({
|
|
|
64750
65097
|
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "lg", color: "fg.warning", fontWeight: "bold", children: "Value too large to display" }),
|
|
64751
65098
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Text, { color: "fg.muted", fontSize: "sm", children: [
|
|
64752
65099
|
"The data is ",
|
|
64753
|
-
formatSize(sizeBytes),
|
|
65100
|
+
formatSize(sizeBytes, words),
|
|
64754
65101
|
", which exceeds the ",
|
|
64755
|
-
formatSize(sizeLimit),
|
|
65102
|
+
formatSize(sizeLimit, words),
|
|
64756
65103
|
" display limit."
|
|
64757
65104
|
] }),
|
|
64758
65105
|
/* @__PURE__ */ jsxRuntime.jsx(DownloadButton, { onClick: download, label: "Download value" })
|
|
64759
65106
|
] });
|
|
64760
65107
|
}
|
|
65108
|
+
if (valueQuery.error) {
|
|
65109
|
+
const { message, details } = formatApiError(valueQuery.error);
|
|
65110
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Load failed", message, details: details ?? formatError(valueQuery.error) });
|
|
65111
|
+
}
|
|
64761
65112
|
if (valueQuery.isLoading || !valueQuery.data) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "loading", title: "Loading..." });
|
|
64762
|
-
if (valueQuery.error) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Decode failed", message: valueQuery.error.message });
|
|
64763
65113
|
const count = type === void 0 || decoded === void 0 ? null : type.type === "Array" ? decoded.length : type.type === "Set" || type.type === "Dict" ? decoded.size : null;
|
|
64764
|
-
const countText = count === null ? "" : `${
|
|
65114
|
+
const countText = count === null ? "" : `${words.number(count)} ${(type == null ? void 0 : type.type) === "Dict" ? "entries" : "items"} · `;
|
|
64765
65115
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Flex, { direction: "column", height: "100%", overflow: "hidden", children: [
|
|
64766
65116
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Flex, { px: 4, py: 2, gap: 2, align: "center", flexShrink: 0, borderBottom: "1px solid", borderColor: "border.subtle", children: [
|
|
64767
65117
|
keyType !== null && inlineKeys !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -64777,7 +65127,7 @@ const DatasetPreview = React.memo(function DatasetPreview2({
|
|
|
64777
65127
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Flex, { flex: 1, justify: "flex-end", align: "center", gap: 2, children: [
|
|
64778
65128
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Text, { fontSize: "xs", color: "fg.muted", children: [
|
|
64779
65129
|
countText,
|
|
64780
|
-
formatSize(sizeBytes)
|
|
65130
|
+
formatSize(sizeBytes, words)
|
|
64781
65131
|
] }),
|
|
64782
65132
|
/* @__PURE__ */ jsxRuntime.jsx(DownloadButton, { onClick: download })
|
|
64783
65133
|
] })
|
|
@@ -64830,19 +65180,15 @@ const UITaskPreview = React.memo(function UITaskPreview2({
|
|
|
64830
65180
|
const workspace = (config2 == null ? void 0 : config2.workspace) ?? (e3 == null ? void 0 : e3.workspace) ?? null;
|
|
64831
65181
|
const token2 = (config2 == null ? void 0 : config2.token) ?? (e3 == null ? void 0 : e3.token) ?? null;
|
|
64832
65182
|
const requestOptions = { token: token2 };
|
|
65183
|
+
const bound3 = cache3 == null ? void 0 : cache3.getConfig().workspace;
|
|
65184
|
+
const foreign = (config2 == null ? void 0 : config2.workspace) !== void 0 && bound3 !== void 0 && config2.workspace !== bound3;
|
|
64833
65185
|
const detailsQuery = useTaskDetails(apiUrl ?? "", repo, workspace, task, { requestOptions });
|
|
64834
65186
|
const details = detailsQuery.data;
|
|
64835
|
-
const
|
|
64836
|
-
const
|
|
64837
|
-
const manifest = React.useMemo(() => {
|
|
64838
|
-
if (!details || !isUI) return null;
|
|
64839
|
-
const meta3 = getTaskMetadata(details);
|
|
64840
|
-
return meta3 ? internal$1.decodeManifest(meta3) : { paths: [], functions: [], records: [], pages: [] };
|
|
64841
|
-
}, [details, isUI]);
|
|
64842
|
-
const outputPath = details ? treePathToString$1(details.output) : null;
|
|
65187
|
+
const manifest = React.useMemo(() => (details == null ? void 0 : details.role.type) === "ui" ? details.role.value : null, [details]);
|
|
65188
|
+
const outputPath = details ? treePathToString$1(details.output.path) : null;
|
|
64843
65189
|
const preloads = React.useMemo(
|
|
64844
|
-
() => manifest && workspace ? manifest.paths.map((path2) => ({ workspace, path: path2 })) : [],
|
|
64845
|
-
[manifest, workspace]
|
|
65190
|
+
() => manifest && workspace && !foreign ? manifest.paths.map((path2) => ({ workspace, path: path2 })) : [],
|
|
65191
|
+
[manifest, workspace, foreign]
|
|
64846
65192
|
);
|
|
64847
65193
|
const { loading: preloading, error: preloadError } = usePreloadReactiveDatasets(preloads);
|
|
64848
65194
|
const scopedPlatforms = React.useMemo(
|
|
@@ -64868,7 +65214,7 @@ const UITaskPreview = React.memo(function UITaskPreview2({
|
|
|
64868
65214
|
[manifest]
|
|
64869
65215
|
);
|
|
64870
65216
|
React.useEffect(() => {
|
|
64871
|
-
if (!cache3 || !manifest || !workspace) return;
|
|
65217
|
+
if (!cache3 || !manifest || !workspace || foreign) return;
|
|
64872
65218
|
for (const path2 of manifest.paths) {
|
|
64873
65219
|
cache3.setRefetchInterval(workspace, path2, pollInterval);
|
|
64874
65220
|
}
|
|
@@ -64877,7 +65223,7 @@ const UITaskPreview = React.memo(function UITaskPreview2({
|
|
|
64877
65223
|
cache3.clearRefetchInterval(workspace, path2);
|
|
64878
65224
|
}
|
|
64879
65225
|
};
|
|
64880
|
-
}, [cache3, manifest, workspace, pollInterval]);
|
|
65226
|
+
}, [cache3, manifest, workspace, pollInterval, foreign]);
|
|
64881
65227
|
const statusQuery = useDatasetStatus(apiUrl ?? "", repo, workspace, outputPath, { requestOptions });
|
|
64882
65228
|
const valueQuery = useDatasetValue(apiUrl ?? "", repo, workspace, outputPath, {
|
|
64883
65229
|
requestOptions,
|
|
@@ -64887,16 +65233,20 @@ const UITaskPreview = React.memo(function UITaskPreview2({
|
|
|
64887
65233
|
});
|
|
64888
65234
|
const store = React.useMemo(() => eastUiComponents.createUIStore(), [task]);
|
|
64889
65235
|
if (!apiUrl) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Configuration error", message: "No apiUrl available — render UITaskPreview inside an <E3Provider> or pass a config prop." });
|
|
65236
|
+
if (foreign) {
|
|
65237
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Workspace mismatch", message: `config names workspace "${config2 == null ? void 0 : config2.workspace}", and the data bindings read workspace "${bound3}", the one the surrounding <ReactiveDatasetProvider> serves: a page previews one workspace.` });
|
|
65238
|
+
}
|
|
64890
65239
|
if (detailsQuery.isLoading) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "loading", title: "Loading task..." });
|
|
64891
65240
|
if (detailsQuery.error) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Error", message: detailsQuery.error.message });
|
|
64892
65241
|
if (!details) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "info", title: "No task", message: `Task "${task}" not found` });
|
|
64893
|
-
if (!
|
|
65242
|
+
if (!manifest) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Not a UI task", message: `Task "${task}" is a ${details.role.type} task` });
|
|
64894
65243
|
if (preloadError) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Preload failed", message: preloadError.message });
|
|
64895
65244
|
if (preloading) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "loading", title: "Loading datasets..." });
|
|
65245
|
+
if (statusQuery.error) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Error", message: statusQuery.error.message });
|
|
64896
65246
|
if (statusQuery.isLoading || !statusQuery.data) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "loading", title: "Loading..." });
|
|
64897
65247
|
if (statusQuery.data.refType !== "value") return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "info", title: "No output yet", message: "Task has not produced a value" });
|
|
65248
|
+
if (valueQuery.error) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Load failed", message: valueQuery.error.message });
|
|
64898
65249
|
if (valueQuery.isLoading || !valueQuery.data) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "loading", title: "Loading..." });
|
|
64899
|
-
if (valueQuery.error) return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Decode failed", message: valueQuery.error.message });
|
|
64900
65250
|
return /* @__PURE__ */ jsxRuntime.jsx(eastUiComponents.UIStoreProvider, { store, children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(react.Box, { height: "100%", overflow: bare ? void 0 : "auto", p: bare ? void 0 : "4", minH: bare ? 0 : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
64901
65251
|
eastUiComponents.EastChakraComponent,
|
|
64902
65252
|
{
|
|
@@ -65353,7 +65703,7 @@ const DataTaskPreview = React.memo(function DataTaskPreview2({
|
|
|
65353
65703
|
const detailsQuery = useTaskDetails(apiUrl, repo, workspace, task, {
|
|
65354
65704
|
...requestOptions != null && { requestOptions }
|
|
65355
65705
|
});
|
|
65356
|
-
const outputPath = detailsQuery.data ? treePathToString(detailsQuery.data.output) : null;
|
|
65706
|
+
const outputPath = detailsQuery.data ? treePathToString(detailsQuery.data.output.path) : null;
|
|
65357
65707
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { height: "100%", display: "flex", flexDirection: "column", overflow: "hidden", children: [
|
|
65358
65708
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
65359
65709
|
react.Flex,
|
|
@@ -65417,13 +65767,14 @@ const TaskPreview = React.memo(function TaskPreview2({
|
|
|
65417
65767
|
requestOptions,
|
|
65418
65768
|
bare = false
|
|
65419
65769
|
}) {
|
|
65770
|
+
var _a2;
|
|
65420
65771
|
const detailsQuery = useTaskDetails(apiUrl, repo, workspace, task, {
|
|
65421
65772
|
...requestOptions != null && { requestOptions }
|
|
65422
65773
|
});
|
|
65423
|
-
const
|
|
65774
|
+
const isUI = ((_a2 = detailsQuery.data) == null ? void 0 : _a2.role.type) === "ui";
|
|
65424
65775
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { height: "100%", display: "flex", flexDirection: "column", overflow: "hidden", children: [
|
|
65425
65776
|
!bare && /* @__PURE__ */ jsxRuntime.jsx(react.Flex, { px: 4, py: 2, borderBottom: "1px solid", borderColor: "border.subtle", bg: "bg.surface", align: "center", flexShrink: 0, children: /* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "sm", fontWeight: "medium", color: "fg", children: task }) }),
|
|
65426
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { flex: 1, overflow: "hidden", minHeight: 0, children: detailsQuery.isLoading ? /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "loading", title: "Loading task..." }) : detailsQuery.error ? /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Error", message: detailsQuery.error.message }) :
|
|
65777
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { flex: 1, overflow: "hidden", minHeight: 0, children: detailsQuery.isLoading ? /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "loading", title: "Loading task..." }) : detailsQuery.error ? /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Error", message: detailsQuery.error.message }) : isUI ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
65427
65778
|
UITaskPreview,
|
|
65428
65779
|
{
|
|
65429
65780
|
task,
|
|
@@ -65441,33 +65792,16 @@ const TaskPreview = React.memo(function TaskPreview2({
|
|
|
65441
65792
|
}
|
|
65442
65793
|
) })
|
|
65443
65794
|
] });
|
|
65444
|
-
}, (prev2, next2) =>
|
|
65795
|
+
}, (prev2, next2) => {
|
|
65796
|
+
var _a2, _b2;
|
|
65797
|
+
return prev2.task === next2.task && prev2.apiUrl === next2.apiUrl && prev2.repo === next2.repo && prev2.workspace === next2.workspace && prev2.bare === next2.bare && ((_a2 = prev2.requestOptions) == null ? void 0 : _a2.token) === ((_b2 = next2.requestOptions) == null ? void 0 : _b2.token);
|
|
65798
|
+
});
|
|
65445
65799
|
function formatPrimitive(type, value) {
|
|
65446
|
-
|
|
65447
|
-
|
|
65448
|
-
return "null";
|
|
65449
|
-
case "Boolean":
|
|
65450
|
-
return value ? "true" : "false";
|
|
65451
|
-
case "Integer":
|
|
65452
|
-
return String(value);
|
|
65453
|
-
case "Float": {
|
|
65454
|
-
const num2 = value;
|
|
65455
|
-
if (Number.isNaN(num2)) return "NaN";
|
|
65456
|
-
if (!Number.isFinite(num2)) return num2 > 0 ? "Infinity" : "-Infinity";
|
|
65457
|
-
return String(num2);
|
|
65458
|
-
}
|
|
65459
|
-
case "String":
|
|
65460
|
-
return `"${value}"`;
|
|
65461
|
-
case "DateTime":
|
|
65462
|
-
return value.toISOString();
|
|
65463
|
-
case "Blob":
|
|
65464
|
-
return `Blob[${value.length} bytes]`;
|
|
65465
|
-
default:
|
|
65466
|
-
return String(value);
|
|
65467
|
-
}
|
|
65800
|
+
if (type.type === "Blob") return `Blob[${value.length} bytes]`;
|
|
65801
|
+
return east.printFor(type)(value);
|
|
65468
65802
|
}
|
|
65469
65803
|
function isPrimitive(type) {
|
|
65470
|
-
return ["Null", "Boolean", "Integer", "Float", "String", "DateTime", "Blob"
|
|
65804
|
+
return ["Null", "Boolean", "Integer", "Float", "String", "DateTime", "Blob"].includes(type.type);
|
|
65471
65805
|
}
|
|
65472
65806
|
function getTypeLabel(type, value) {
|
|
65473
65807
|
switch (type.type) {
|
|
@@ -65589,8 +65923,8 @@ function ValueNode({
|
|
|
65589
65923
|
}
|
|
65590
65924
|
if (type.type === "Variant") {
|
|
65591
65925
|
const cases = type.value;
|
|
65592
|
-
const
|
|
65593
|
-
const activeCase = cases.find((c2) => c2.name ===
|
|
65926
|
+
const chosen = value;
|
|
65927
|
+
const activeCase = cases.find((c2) => c2.name === chosen.type);
|
|
65594
65928
|
if (!activeCase) {
|
|
65595
65929
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { py: 0.5, display: "flex", alignItems: "center", gap: 2, children: [
|
|
65596
65930
|
label && /* @__PURE__ */ jsxRuntime.jsxs(react.Text, { as: "span", color: "accent.purple", fontWeight: "medium", children: [
|
|
@@ -65599,7 +65933,7 @@ function ValueNode({
|
|
|
65599
65933
|
] }),
|
|
65600
65934
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Text, { as: "span", color: "fg.danger", children: [
|
|
65601
65935
|
"Unknown variant: ",
|
|
65602
|
-
|
|
65936
|
+
chosen.type
|
|
65603
65937
|
] })
|
|
65604
65938
|
] });
|
|
65605
65939
|
}
|
|
@@ -65611,7 +65945,7 @@ function ValueNode({
|
|
|
65611
65945
|
] }),
|
|
65612
65946
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Badge, { size: "xs", colorPalette: "brand", variant: "subtle", children: [
|
|
65613
65947
|
".",
|
|
65614
|
-
|
|
65948
|
+
chosen.type
|
|
65615
65949
|
] })
|
|
65616
65950
|
] });
|
|
65617
65951
|
}
|
|
@@ -65623,14 +65957,14 @@ function ValueNode({
|
|
|
65623
65957
|
] }),
|
|
65624
65958
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Badge, { size: "xs", colorPalette: "brand", variant: "subtle", children: [
|
|
65625
65959
|
".",
|
|
65626
|
-
|
|
65960
|
+
chosen.type
|
|
65627
65961
|
] })
|
|
65628
65962
|
] }),
|
|
65629
65963
|
/* @__PURE__ */ jsxRuntime.jsx(react.Box, { pl: 4, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
65630
65964
|
ValueNode,
|
|
65631
65965
|
{
|
|
65632
65966
|
type: activeCase.type,
|
|
65633
|
-
value:
|
|
65967
|
+
value: chosen.value,
|
|
65634
65968
|
depth: depth + 1
|
|
65635
65969
|
}
|
|
65636
65970
|
) })
|
|
@@ -65838,8 +66172,6 @@ exports.funcChannelKey = funcChannelKey;
|
|
|
65838
66172
|
exports.getBindingTypes = getBindingTypes;
|
|
65839
66173
|
exports.getReactiveDatasetCache = getReactiveDatasetCache;
|
|
65840
66174
|
exports.getStagedStore = getStagedStore;
|
|
65841
|
-
exports.getTaskKind = getTaskKind;
|
|
65842
|
-
exports.getTaskMetadata = getTaskMetadata;
|
|
65843
66175
|
exports.initializeFunctionApi = initializeFunctionApi;
|
|
65844
66176
|
exports.initializePagedApi = initializePagedApi;
|
|
65845
66177
|
exports.initializeReactiveDatasetCache = initializeReactiveDatasetCache;
|
|
@@ -65847,6 +66179,7 @@ exports.initializeRecordApi = initializeRecordApi;
|
|
|
65847
66179
|
exports.initializeStagedStore = initializeStagedStore;
|
|
65848
66180
|
exports.isBindingTracking = isBindingTracking;
|
|
65849
66181
|
exports.onWriteError = onWriteError;
|
|
66182
|
+
exports.pagedRevisionKey = pagedRevisionKey;
|
|
65850
66183
|
exports.pagedTotalKey = pagedTotalKey;
|
|
65851
66184
|
exports.pagedWindowKey = pagedWindowKey;
|
|
65852
66185
|
exports.preloadReactiveDatasetList = preloadReactiveDatasetList;
|