@elaraai/e3-ui-components 1.0.68 → 1.0.69
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/dist/components/UITaskPreview.d.ts.map +1 -1
- package/dist/diff/index.d.ts.map +1 -1
- package/dist/hooks/useDatasetValue.d.ts.map +1 -1
- package/dist/index.cjs +431 -273
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +430 -274
- package/dist/index.js.map +1 -1
- package/dist/platform/dataset-hooks.d.ts.map +1 -1
- package/dist/platform/index.d.ts +1 -0
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/paged-runtime.d.ts +146 -0
- package/dist/platform/paged-runtime.d.ts.map +1 -0
- package/dist/platform/tracked-channel.d.ts +5 -0
- package/dist/platform/tracked-channel.d.ts.map +1 -1
- package/package.json +13 -13
- package/dist/components/DatasetKeySearch.d.ts +0 -84
- package/dist/components/DatasetKeySearch.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -18,21 +18,22 @@ var __privateWrapper = (obj, member, setter, getter) => ({
|
|
|
18
18
|
}
|
|
19
19
|
});
|
|
20
20
|
var _focused, _cleanup, _setup, _a, _provider, _providerCalled, _b, _online, _cleanup2, _setup2, _c, _gcTimeout, _d, _initialState, _revertState, _cache, _client, _retryer, _defaultOptions, _abortSignalConsumed, _Query_instances, isInitialPausedFetch_fn, dispatch_fn, _e, _client2, _observers, _mutationCache, _retryer2, _Mutation_instances, dispatch_fn2, _f, _mutations, _scopes, _mutationId, _g, _queries, _h, _queryCache, _mutationCache2, _defaultOptions2, _queryDefaults, _mutationDefaults, _mountCount, _unsubscribeFocus, _unsubscribeOnline, _i, _j;
|
|
21
|
-
import { variant, SortedMap, compareFor, EastError, fromEastTypeValue, East, none as none$1, some, OptionType, BooleanType, NullType, ConflictError, equalFor, toEastTypeValue, PatchType, diffFor, applyFor, encodeBeast2For, decodeBeast2For, BlobType, StructType, StringType, walkPatch, pathToString, pathDisplay, printFor, isVariant, prunePatchFor, detectConflictsFor, mergeWithResolutionsFor, validatePatchFor, isEastSet, isEastDict, ArrayType, parseFor } from "@elaraai/east";
|
|
21
|
+
import { variant, SortedMap, compareFor, EastError, fromEastTypeValue, East, none as none$1, some, OptionType, BooleanType, NullType, ConflictError, equalFor, toEastTypeValue, PatchType, diffFor, applyFor, encodeBeast2For, decodeBeast2For, BlobType, IntegerType, StructType, StringType, walkPatch, pathToString, pathDisplay, printFor, isVariant, prunePatchFor, detectConflictsFor, mergeWithResolutionsFor, validatePatchFor, isEastSet, isEastDict, ArrayType, parseFor } from "@elaraai/east";
|
|
22
22
|
import { EastTypeType } from "@elaraai/east/internal";
|
|
23
|
-
import { DataBindModeType, DataBindPrimitives, bindPlatformFn, FuncBindPrimitives, FuncErrorType, FuncStatusType, funcBindPlatformFn, RecordBindPrimitives, recordBindPlatformFn, Diff, Ontology, FuncBindHandleType, Experiment, decisionBindPlatformFn, DecisionBindPrimitives, DecisionConstraintType, DiffBindingType, CommitStateType, VerdictType, AnswerType, judgementInputType, DecisionType, DecisionQueue, DecisionJournal, decodeManifest } from "@elaraai/e3-ui/internal";
|
|
23
|
+
import { DataBindModeType, DataBindPrimitives, bindPlatformFn, DataPagedPrimitives, bindPagedPlatformFn, FuncBindPrimitives, FuncErrorType, FuncStatusType, funcBindPlatformFn, RecordBindPrimitives, recordBindPlatformFn, Diff, Ontology, FuncBindHandleType, Experiment, decisionBindPlatformFn, DecisionBindPrimitives, DecisionConstraintType, DiffBindingType, CommitStateType, VerdictType, AnswerType, judgementInputType, DecisionType, DecisionQueue, DecisionJournal, decodeManifest } from "@elaraai/e3-ui/internal";
|
|
24
24
|
import { registerReactiveTracker, registerPlatformImplementation, StateRuntime, getRegisteredPlatformImplementations, boundSliceConfig } from "@elaraai/east-ui-components/platform";
|
|
25
25
|
import { TreePathType, DatasetStatusType } from "@elaraai/e3-types";
|
|
26
|
-
import { workspaceStatus, datasetListAt, datasetList, dataflowExecuteLaunch, datasetSet, datasetGet, ApiError, workspaceFunctionCall, workspaceFunctionList, workspaceRecordHistory, workspaceRecordMutate, workspaceRecordDescribe, repoCreate, repoGc, repoGcStart, repoGcStatus, repoList, repoRemove, repoStatus, packageExport, packageGet, packageImport, packageList, packageRemove, workspaceCreate, workspaceDeploy, workspaceExport, workspaceGet, workspaceList, workspaceRemove, datasetGetStatus, datasetListRecursive, datasetListRecursivePaths, datasetListWithStatus, taskExecutionList, taskGet, taskList, dataflowCancel, dataflowExecute, dataflowExecutePoll, dataflowGraph, taskLogs
|
|
26
|
+
import { workspaceStatus, datasetListAt, datasetList, dataflowExecuteLaunch, datasetSet, datasetGet, ApiError, datasetFindKey, datasetGetPage, workspaceFunctionCall, workspaceFunctionList, workspaceRecordHistory, workspaceRecordMutate, workspaceRecordDescribe, repoCreate, repoGc, repoGcStart, repoGcStatus, repoList, repoRemove, repoStatus, packageExport, packageGet, packageImport, packageList, packageRemove, workspaceCreate, workspaceDeploy, workspaceExport, workspaceGet, workspaceList, workspaceRemove, datasetGetStatus, datasetListRecursive, datasetListRecursivePaths, datasetListWithStatus, taskExecutionList, taskGet, taskList, dataflowCancel, dataflowExecute, dataflowExecutePoll, dataflowGraph, taskLogs } from "@elaraai/e3-api-client";
|
|
27
|
+
import { SeekQueryType, SeekRangeType, ValueTree } from "@elaraai/east-ui";
|
|
27
28
|
import { jsx as jsx$1, Fragment, jsxs } from "react/jsx-runtime";
|
|
28
29
|
import * as React from "react";
|
|
29
30
|
import React__default, { useId, useMemo, useContext, createContext, useRef, useEffect, useState, useCallback, useSyncExternalStore, memo, forwardRef, useLayoutEffect, Fragment as Fragment$1, Component } from "react";
|
|
30
31
|
import { Box, Flex, Text, HStack, Input, useSlotRecipe, useRecipe, VStack, useToken, Drawer, Portal, Field, NativeSelect, Textarea, chakra, Tooltip, SegmentGroup, Menu, HoverCard, useChakraContext, Spinner, Code, Clipboard, IconButton, Button, Tabs, Badge, useTabs } from "@chakra-ui/react";
|
|
31
|
-
import { implementUIComponent, getSomeorUndefined, formatPredicate, SliceEditPopover, SlicePredicateBuilder, EastChakraSelect, EastChakraStringInput, EastChakraDateTimeInput, EastChakraFloatInput, EastChakraIntegerInput, formatTick, useSliceReactivity, useContainerBelow, usePersistedState, SliceRailCluster, EastChakraComponent, ClauseChip, StateImpl, NavImpl, SliceImpl, SliceApplyImpl, OverlayImpl, ClipboardImpl, DownloadImpl, ShareImpl, LoadingIcon,
|
|
32
|
+
import { implementUIComponent, getSomeorUndefined, formatPredicate, SliceEditPopover, SlicePredicateBuilder, EastChakraSelect, EastChakraStringInput, EastChakraDateTimeInput, EastChakraFloatInput, EastChakraIntegerInput, formatTick, useSliceReactivity, useContainerBelow, usePersistedState, SliceRailCluster, EastChakraComponent, ClauseChip, StateImpl, NavImpl, SliceImpl, SliceApplyImpl, OverlayImpl, ClipboardImpl, DownloadImpl, ShareImpl, LoadingIcon, DatasetKeySearch, EastChakraValueTree, keyRangePredicates, createUIStore, UIStoreProvider } from "@elaraai/east-ui-components";
|
|
33
|
+
import { DatasetKeySearch as DatasetKeySearch2 } from "@elaraai/east-ui-components";
|
|
32
34
|
import { createPortal } from "react-dom";
|
|
33
35
|
import { sliceMatches } from "@elaraai/east-ui/internal";
|
|
34
36
|
import { QueryClient as QueryClient$1, QueryClientProvider, useMutation, useQuery, keepPreviousData, useQueryClient } from "@tanstack/react-query";
|
|
35
|
-
import { ValueTree } from "@elaraai/east-ui";
|
|
36
37
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
37
38
|
var Subscribable = class {
|
|
38
39
|
constructor() {
|
|
@@ -3593,6 +3594,14 @@ class TrackedChannelStore {
|
|
|
3593
3594
|
isTracking() {
|
|
3594
3595
|
return this.trackingContext !== null;
|
|
3595
3596
|
}
|
|
3597
|
+
/** Whether the CURRENT evaluation has already read this channel. A cache
|
|
3598
|
+
* that evicts by least-recently-read must never drop one of these: a read
|
|
3599
|
+
* pass longer than the cache would otherwise evict its own head, and the
|
|
3600
|
+
* next pass would find it gone (#581). */
|
|
3601
|
+
isTracked(key) {
|
|
3602
|
+
var _a2;
|
|
3603
|
+
return ((_a2 = this.trackingContext) == null ? void 0 : _a2.has(key)) ?? false;
|
|
3604
|
+
}
|
|
3596
3605
|
/** Record a channel-key dependency for the current render (no-op when not
|
|
3597
3606
|
* tracking). */
|
|
3598
3607
|
track(key) {
|
|
@@ -3674,6 +3683,397 @@ class TrackedChannelStore {
|
|
|
3674
3683
|
this.keyVersions.clear();
|
|
3675
3684
|
}
|
|
3676
3685
|
}
|
|
3686
|
+
function createDefaultPagedApi(apiUrl, repo, getToken) {
|
|
3687
|
+
const opts = () => ({ token: getToken() });
|
|
3688
|
+
return {
|
|
3689
|
+
async getPage(workspace, path2, window3) {
|
|
3690
|
+
return datasetGetPage(apiUrl, repo, workspace, path2, window3, opts());
|
|
3691
|
+
},
|
|
3692
|
+
async findKey(workspace, path2, query) {
|
|
3693
|
+
return datasetFindKey(apiUrl, repo, workspace, path2, query, opts());
|
|
3694
|
+
}
|
|
3695
|
+
};
|
|
3696
|
+
}
|
|
3697
|
+
const RETRY_AFTER_MS = 2e3;
|
|
3698
|
+
const MAX_RETAINED_WINDOWS = 24;
|
|
3699
|
+
const PERMANENT_PAGE_ERRORS = /* @__PURE__ */ new Set(["dataset_not_pageable"]);
|
|
3700
|
+
function isPermanentPageError(err) {
|
|
3701
|
+
const code = err == null ? void 0 : err.code;
|
|
3702
|
+
return typeof code === "string" && PERMANENT_PAGE_ERRORS.has(code);
|
|
3703
|
+
}
|
|
3704
|
+
function keyTypeOf(sourceType) {
|
|
3705
|
+
if (sourceType.type === "Dict") return sourceType.value.key;
|
|
3706
|
+
if (sourceType.type === "Set") return sourceType.value;
|
|
3707
|
+
return null;
|
|
3708
|
+
}
|
|
3709
|
+
function buildSeek(sourceType, T2, pathExpr, platform) {
|
|
3710
|
+
if (keyTypeOf(sourceType) === null) return none$1;
|
|
3711
|
+
const { seek } = DataPagedPrimitives;
|
|
3712
|
+
return some(East.compile(
|
|
3713
|
+
East.function([SeekQueryType], OptionType(SeekRangeType), ($3, query) => {
|
|
3714
|
+
$3.return(seek([T2], pathExpr, query));
|
|
3715
|
+
}),
|
|
3716
|
+
platform
|
|
3717
|
+
));
|
|
3718
|
+
}
|
|
3719
|
+
function pagedWindowKey(workspace, path2, offset, limit2) {
|
|
3720
|
+
return `paged:${workspace}:${datasetPathToString(path2)}#${offset}+${limit2}`;
|
|
3721
|
+
}
|
|
3722
|
+
function pagedTotalKey(workspace, path2) {
|
|
3723
|
+
return `paged:${workspace}:${datasetPathToString(path2)}#total`;
|
|
3724
|
+
}
|
|
3725
|
+
function pagedSeekKey(workspace, path2, query) {
|
|
3726
|
+
const q = "key" in query ? `k=${query.key}` : "fields" in query ? `f=${query.fields.join("\0")}|p=${query.prefix ?? ""}` : `p=${query.prefix}`;
|
|
3727
|
+
return `paged:${workspace}:${datasetPathToString(path2)}#seek:${q}`;
|
|
3728
|
+
}
|
|
3729
|
+
function toFindQuery(query) {
|
|
3730
|
+
const q = query;
|
|
3731
|
+
if (q.type === "key") return { key: q.value };
|
|
3732
|
+
if (q.type === "prefix") return { prefix: q.value };
|
|
3733
|
+
const f2 = q.value;
|
|
3734
|
+
const fields = [...f2.values];
|
|
3735
|
+
return f2.prefix.type === "some" ? { fields, prefix: f2.prefix.value } : { fields };
|
|
3736
|
+
}
|
|
3737
|
+
class PagedRuntime extends TrackedChannelStore {
|
|
3738
|
+
constructor() {
|
|
3739
|
+
super(...arguments);
|
|
3740
|
+
__publicField(this, "api", null);
|
|
3741
|
+
__publicField(this, "workspace", null);
|
|
3742
|
+
// Compiled-handle cache (issue #106 perf): buildHandle compiles 2
|
|
3743
|
+
// East.functions per bind, and binds re-run every reactive frame. The
|
|
3744
|
+
// method IR is a pure function of (sourceType, sourcePath), and the methods
|
|
3745
|
+
// resolve api/workspace LIVE, so a cached handle still re-binds.
|
|
3746
|
+
//
|
|
3747
|
+
// Keyed by TYPE first, then path — never by path alone. The window decoder
|
|
3748
|
+
// is baked from `sourceType`, so a path re-bound at a different type (a
|
|
3749
|
+
// redeployed dataset whose schema changed, inside a live session) must not
|
|
3750
|
+
// hand back the handle compiled against the old type. Structural key for
|
|
3751
|
+
// the same reason `bind-runtime` uses one: every bind builds a fresh
|
|
3752
|
+
// `EastTypeValue` from IR, so a by-identity cache would miss every render.
|
|
3753
|
+
__publicField(this, "handleCache", new SortedMap(
|
|
3754
|
+
void 0,
|
|
3755
|
+
compareFor(EastTypeType)
|
|
3756
|
+
));
|
|
3757
|
+
/** Loaded window keys in least-recently-READ order (a Map preserves
|
|
3758
|
+
* insertion order; a read re-inserts). Bounds the decoded-window cache. */
|
|
3759
|
+
__publicField(this, "loadedWindows", /* @__PURE__ */ new Map());
|
|
3760
|
+
}
|
|
3761
|
+
/** Monotonic clock seam so tests can drive the retry gate. */
|
|
3762
|
+
now() {
|
|
3763
|
+
return Date.now();
|
|
3764
|
+
}
|
|
3765
|
+
createEntry() {
|
|
3766
|
+
return { status: "idle", launchSeq: 0 };
|
|
3767
|
+
}
|
|
3768
|
+
// ----- wiring ----------------------------------------------------------
|
|
3769
|
+
/** Install the API adapter + workspace — called by the React provider
|
|
3770
|
+
* (or a test/showcase harness) before any handle is used. */
|
|
3771
|
+
initialize(api3, workspace) {
|
|
3772
|
+
this.api = api3;
|
|
3773
|
+
this.workspace = workspace;
|
|
3774
|
+
}
|
|
3775
|
+
/** Tear down the adapter and all window state. */
|
|
3776
|
+
clear() {
|
|
3777
|
+
this.api = null;
|
|
3778
|
+
this.workspace = null;
|
|
3779
|
+
this.clearChannels();
|
|
3780
|
+
this.handleCache.clear();
|
|
3781
|
+
this.loadedWindows.clear();
|
|
3782
|
+
}
|
|
3783
|
+
resolveWorkspace() {
|
|
3784
|
+
if (!this.workspace) {
|
|
3785
|
+
throw new Error(
|
|
3786
|
+
"Data.bindPaged: no paging service — a paged source is served BY THE SERVER (datasetGetPage), so it resolves only inside a live workspace. Render this component against a deployed workspace, or bind the whole value with Data.bind."
|
|
3787
|
+
);
|
|
3788
|
+
}
|
|
3789
|
+
return this.workspace;
|
|
3790
|
+
}
|
|
3791
|
+
// ----- window loading --------------------------------------------------
|
|
3792
|
+
/** Note a window as most-recently-read, and drop the coldest decoded
|
|
3793
|
+
* windows once the cache exceeds its cap. An evicted window returns to
|
|
3794
|
+
* `idle`, so the next read refetches it rather than reading a hole. */
|
|
3795
|
+
touchWindow(key) {
|
|
3796
|
+
this.loadedWindows.delete(key);
|
|
3797
|
+
this.loadedWindows.set(key, true);
|
|
3798
|
+
if (this.loadedWindows.size <= MAX_RETAINED_WINDOWS) return;
|
|
3799
|
+
for (const candidate of [...this.loadedWindows.keys()]) {
|
|
3800
|
+
if (this.loadedWindows.size <= MAX_RETAINED_WINDOWS) break;
|
|
3801
|
+
if (this.isTracked(candidate)) continue;
|
|
3802
|
+
const entry = this.entries.get(candidate);
|
|
3803
|
+
if (entry === void 0 || entry.status !== "loaded") continue;
|
|
3804
|
+
this.loadedWindows.delete(candidate);
|
|
3805
|
+
entry.status = "idle";
|
|
3806
|
+
delete entry.window;
|
|
3807
|
+
}
|
|
3808
|
+
}
|
|
3809
|
+
/**
|
|
3810
|
+
* Start the fetch for a window if it isn't loaded or already in flight.
|
|
3811
|
+
*
|
|
3812
|
+
* Deliberately does NOT notify on launch — the read that triggers it runs
|
|
3813
|
+
* inside a render pass, and notifying there would re-enter the renderer.
|
|
3814
|
+
* Only the settle notifies.
|
|
3815
|
+
*/
|
|
3816
|
+
ensureWindow(sourceType, workspace, path2, offset, limit2) {
|
|
3817
|
+
const key = pagedWindowKey(workspace, path2, offset, limit2);
|
|
3818
|
+
const entry = this.entry(key);
|
|
3819
|
+
if (entry.status === "running" || entry.status === "loaded") return;
|
|
3820
|
+
if (entry.status === "failed") {
|
|
3821
|
+
if (entry.permanent) return;
|
|
3822
|
+
const since = this.now() - (entry.failedAtMs ?? 0);
|
|
3823
|
+
if (since < RETRY_AFTER_MS) return;
|
|
3824
|
+
}
|
|
3825
|
+
entry.status = "running";
|
|
3826
|
+
entry.launchSeq += 1;
|
|
3827
|
+
const mySeq = entry.launchSeq;
|
|
3828
|
+
const api3 = this.api;
|
|
3829
|
+
void (async () => {
|
|
3830
|
+
const settle = (mutate) => {
|
|
3831
|
+
const current = this.entries.get(key);
|
|
3832
|
+
if (!current || current.launchSeq !== mySeq) return;
|
|
3833
|
+
mutate(current);
|
|
3834
|
+
this.notify(key);
|
|
3835
|
+
};
|
|
3836
|
+
if (!api3) {
|
|
3837
|
+
settle((e3) => {
|
|
3838
|
+
e3.status = "failed";
|
|
3839
|
+
e3.failedAtMs = this.now();
|
|
3840
|
+
});
|
|
3841
|
+
console.error("Data.bindPaged: no PagedApi installed");
|
|
3842
|
+
return;
|
|
3843
|
+
}
|
|
3844
|
+
let page;
|
|
3845
|
+
try {
|
|
3846
|
+
page = await api3.getPage(workspace, path2, { offset, limit: limit2 });
|
|
3847
|
+
} catch (err) {
|
|
3848
|
+
const permanent = isPermanentPageError(err);
|
|
3849
|
+
settle((e3) => {
|
|
3850
|
+
e3.status = "failed";
|
|
3851
|
+
e3.failedAtMs = this.now();
|
|
3852
|
+
e3.permanent = permanent;
|
|
3853
|
+
});
|
|
3854
|
+
console.error(
|
|
3855
|
+
permanent ? `Data.bindPaged: ${datasetPathToString(path2)} is not a pageable dataset — bind a collection (Array / Set / Dict), or use Data.bind for a whole value:` : `Data.bindPaged: fetch failed for ${key}:`,
|
|
3856
|
+
err
|
|
3857
|
+
);
|
|
3858
|
+
return;
|
|
3859
|
+
}
|
|
3860
|
+
let decoded;
|
|
3861
|
+
try {
|
|
3862
|
+
decoded = decodeBeast2For(sourceType)(page.data);
|
|
3863
|
+
} catch (err) {
|
|
3864
|
+
settle((e3) => {
|
|
3865
|
+
e3.status = "failed";
|
|
3866
|
+
e3.failedAtMs = this.now();
|
|
3867
|
+
});
|
|
3868
|
+
console.error(`Data.bindPaged: decode failed for ${key}:`, err);
|
|
3869
|
+
return;
|
|
3870
|
+
}
|
|
3871
|
+
settle((e3) => {
|
|
3872
|
+
e3.status = "loaded";
|
|
3873
|
+
e3.window = decoded;
|
|
3874
|
+
e3.total = page.totalElements;
|
|
3875
|
+
});
|
|
3876
|
+
this.touchWindow(key);
|
|
3877
|
+
const totalKey = pagedTotalKey(workspace, path2);
|
|
3878
|
+
const totalEntry = this.entry(totalKey);
|
|
3879
|
+
if (totalEntry.total !== page.totalElements) {
|
|
3880
|
+
totalEntry.total = page.totalElements;
|
|
3881
|
+
totalEntry.status = "loaded";
|
|
3882
|
+
this.notify(totalKey);
|
|
3883
|
+
}
|
|
3884
|
+
})();
|
|
3885
|
+
}
|
|
3886
|
+
/**
|
|
3887
|
+
* Start the fence search for one key query if it isn't answered or already
|
|
3888
|
+
* in flight — the seek sibling of {@link ensureWindow}, with the same
|
|
3889
|
+
* launch-does-not-notify rule (the read runs inside a render pass).
|
|
3890
|
+
*/
|
|
3891
|
+
ensureSeek(workspace, path2, query, key) {
|
|
3892
|
+
const entry = this.entry(key);
|
|
3893
|
+
if (entry.status === "running" || entry.status === "loaded") return;
|
|
3894
|
+
if (entry.status === "failed") {
|
|
3895
|
+
if (entry.permanent) return;
|
|
3896
|
+
const since = this.now() - (entry.failedAtMs ?? 0);
|
|
3897
|
+
if (since < RETRY_AFTER_MS) return;
|
|
3898
|
+
}
|
|
3899
|
+
entry.status = "running";
|
|
3900
|
+
entry.launchSeq += 1;
|
|
3901
|
+
const mySeq = entry.launchSeq;
|
|
3902
|
+
const api3 = this.api;
|
|
3903
|
+
void (async () => {
|
|
3904
|
+
const settle = (mutate) => {
|
|
3905
|
+
const current = this.entries.get(key);
|
|
3906
|
+
if (!current || current.launchSeq !== mySeq) return;
|
|
3907
|
+
mutate(current);
|
|
3908
|
+
this.notify(key);
|
|
3909
|
+
};
|
|
3910
|
+
if (!api3) {
|
|
3911
|
+
settle((e3) => {
|
|
3912
|
+
e3.status = "failed";
|
|
3913
|
+
e3.failedAtMs = this.now();
|
|
3914
|
+
});
|
|
3915
|
+
console.error("Data.bindPaged: no PagedApi installed");
|
|
3916
|
+
return;
|
|
3917
|
+
}
|
|
3918
|
+
try {
|
|
3919
|
+
const range = await api3.findKey(workspace, path2, query);
|
|
3920
|
+
settle((e3) => {
|
|
3921
|
+
e3.status = "loaded";
|
|
3922
|
+
e3.range = range;
|
|
3923
|
+
});
|
|
3924
|
+
} catch (err) {
|
|
3925
|
+
const permanent = isPermanentPageError(err);
|
|
3926
|
+
settle((e3) => {
|
|
3927
|
+
e3.status = "failed";
|
|
3928
|
+
e3.failedAtMs = this.now();
|
|
3929
|
+
e3.permanent = permanent;
|
|
3930
|
+
});
|
|
3931
|
+
console.error(`Data.bindPaged: key search failed for ${key}:`, err);
|
|
3932
|
+
}
|
|
3933
|
+
})();
|
|
3934
|
+
}
|
|
3935
|
+
/**
|
|
3936
|
+
* The low-level primitives backing handle methods, bound to THIS runtime.
|
|
3937
|
+
* Registered globally (extension registry) and included by the scoped
|
|
3938
|
+
* platform (e3 `ui()` tasks) so a decoded handle re-binds to whatever
|
|
3939
|
+
* runtime resolves the primitives on the decode side.
|
|
3940
|
+
*/
|
|
3941
|
+
buildPrimitives() {
|
|
3942
|
+
return [
|
|
3943
|
+
DataPagedPrimitives.page.implement((sourceType) => (pathArg, offsetArg, limitArg) => {
|
|
3944
|
+
const workspace = this.resolveWorkspace();
|
|
3945
|
+
const path2 = pathArg;
|
|
3946
|
+
const offset = Number(offsetArg);
|
|
3947
|
+
const limit2 = Number(limitArg);
|
|
3948
|
+
const key = pagedWindowKey(workspace, path2, offset, limit2);
|
|
3949
|
+
this.track(key);
|
|
3950
|
+
this.ensureWindow(sourceType, workspace, path2, offset, limit2);
|
|
3951
|
+
const entry = this.entry(key);
|
|
3952
|
+
if (entry.status === "loaded" && entry.window !== void 0) {
|
|
3953
|
+
this.touchWindow(key);
|
|
3954
|
+
return variant("some", entry.window);
|
|
3955
|
+
}
|
|
3956
|
+
return variant("none", null);
|
|
3957
|
+
}),
|
|
3958
|
+
DataPagedPrimitives.total.implement((_sourceType) => (pathArg) => {
|
|
3959
|
+
const workspace = this.resolveWorkspace();
|
|
3960
|
+
const key = pagedTotalKey(workspace, pathArg);
|
|
3961
|
+
this.track(key);
|
|
3962
|
+
const entry = this.entry(key);
|
|
3963
|
+
return entry.total !== void 0 ? variant("some", BigInt(entry.total)) : variant("none", null);
|
|
3964
|
+
}),
|
|
3965
|
+
DataPagedPrimitives.seek.implement((_sourceType) => (pathArg, queryArg) => {
|
|
3966
|
+
const workspace = this.resolveWorkspace();
|
|
3967
|
+
const path2 = pathArg;
|
|
3968
|
+
const query = toFindQuery(queryArg);
|
|
3969
|
+
const key = pagedSeekKey(workspace, path2, query);
|
|
3970
|
+
this.track(key);
|
|
3971
|
+
this.ensureSeek(workspace, path2, query, key);
|
|
3972
|
+
const entry = this.entry(key);
|
|
3973
|
+
if (entry.status !== "loaded" || entry.range === void 0) return none$1;
|
|
3974
|
+
const r2 = entry.range;
|
|
3975
|
+
return some({ found: r2.found, row: BigInt(r2.row), count: BigInt(r2.count) });
|
|
3976
|
+
})
|
|
3977
|
+
];
|
|
3978
|
+
}
|
|
3979
|
+
/**
|
|
3980
|
+
* Build the handle value for one `Data.bindPaged` evaluation. Both methods
|
|
3981
|
+
* are thin IR-bearing `East.function`s over {@link buildPrimitives},
|
|
3982
|
+
* capturing only the plain-data source path (the value type rides as a
|
|
3983
|
+
* type-arg) — so the handle is ordinary serializable East data (issue #106).
|
|
3984
|
+
*/
|
|
3985
|
+
buildHandle(sourceType, path2) {
|
|
3986
|
+
const pathKey = datasetPathToString(path2);
|
|
3987
|
+
let byPath = this.handleCache.get(sourceType);
|
|
3988
|
+
if (byPath) {
|
|
3989
|
+
const hit = byPath.get(pathKey);
|
|
3990
|
+
if (hit) return hit;
|
|
3991
|
+
} else {
|
|
3992
|
+
byPath = /* @__PURE__ */ new Map();
|
|
3993
|
+
this.handleCache.set(sourceType, byPath);
|
|
3994
|
+
}
|
|
3995
|
+
const T2 = fromEastTypeValue(sourceType);
|
|
3996
|
+
const pathExpr = East.value(path2, TreePathType);
|
|
3997
|
+
const platform = this.buildPrimitives();
|
|
3998
|
+
const { page, total } = DataPagedPrimitives;
|
|
3999
|
+
const handle = {
|
|
4000
|
+
// The comparable identity east-ui's `PagedSourceType` requires:
|
|
4001
|
+
// East compares every function as EQUAL, so a struct of nothing but
|
|
4002
|
+
// closures is indistinguishable from any other and a memoized
|
|
4003
|
+
// component would never re-render on a source swap (#567 D4). The
|
|
4004
|
+
// dataset path is the natural identity — same path, same rows.
|
|
4005
|
+
id: pathKey,
|
|
4006
|
+
page: East.compile(
|
|
4007
|
+
East.function([IntegerType, IntegerType], OptionType(T2), ($3, offset, limit2) => {
|
|
4008
|
+
$3.return(page([T2], pathExpr, offset, limit2));
|
|
4009
|
+
}),
|
|
4010
|
+
platform
|
|
4011
|
+
),
|
|
4012
|
+
total: East.compile(
|
|
4013
|
+
East.function([], OptionType(IntegerType), ($3) => {
|
|
4014
|
+
$3.return(total([T2], pathExpr));
|
|
4015
|
+
}),
|
|
4016
|
+
platform
|
|
4017
|
+
),
|
|
4018
|
+
// Key search is a KEY-ORDER capability: Set/Dict element windows
|
|
4019
|
+
// ride the canonical East key order, so a key locates in O(log
|
|
4020
|
+
// segments) against the stored fences; an Array's stream order has
|
|
4021
|
+
// nothing to search. Resolved at bind time from the dataset's own
|
|
4022
|
+
// type, so a component renders the affordance only when it works.
|
|
4023
|
+
seek: buildSeek(sourceType, T2, pathExpr, platform)
|
|
4024
|
+
};
|
|
4025
|
+
byPath.set(pathKey, handle);
|
|
4026
|
+
return handle;
|
|
4027
|
+
}
|
|
4028
|
+
// ----- platform building -------------------------------------------------
|
|
4029
|
+
/** Build a `Data.bindPaged` PlatformFunction bound to this runtime. Pass
|
|
4030
|
+
* `allowed=null` for an unscoped impl; pass a Set of path strings for
|
|
4031
|
+
* manifest scoping. */
|
|
4032
|
+
buildPlatform(allowed) {
|
|
4033
|
+
return bindPagedPlatformFn.implement(
|
|
4034
|
+
(sourceType) => (pathArg) => {
|
|
4035
|
+
const path2 = pathArg;
|
|
4036
|
+
if (allowed) {
|
|
4037
|
+
const pathStr = datasetPathToString(path2);
|
|
4038
|
+
if (!allowed.has(pathStr)) {
|
|
4039
|
+
throw new Error(
|
|
4040
|
+
`Data.bindPaged: source path "${pathStr}" not declared in manifest — bind it in the task body so derivation records it`
|
|
4041
|
+
);
|
|
4042
|
+
}
|
|
4043
|
+
}
|
|
4044
|
+
return this.buildHandle(sourceType, path2);
|
|
4045
|
+
}
|
|
4046
|
+
);
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
const defaultPagedRuntime = new PagedRuntime();
|
|
4050
|
+
function initializePagedApi(api3, workspace) {
|
|
4051
|
+
defaultPagedRuntime.initialize(api3, workspace);
|
|
4052
|
+
}
|
|
4053
|
+
function clearPagedApi() {
|
|
4054
|
+
defaultPagedRuntime.clear();
|
|
4055
|
+
}
|
|
4056
|
+
const PagedPlatform = [
|
|
4057
|
+
defaultPagedRuntime.buildPlatform(null),
|
|
4058
|
+
...defaultPagedRuntime.buildPrimitives()
|
|
4059
|
+
];
|
|
4060
|
+
function createScopedPagedPlatform(pages) {
|
|
4061
|
+
const allowed = new Set(pages.map((p2) => datasetPathToString(p2)));
|
|
4062
|
+
return [
|
|
4063
|
+
defaultPagedRuntime.buildPlatform(allowed),
|
|
4064
|
+
...defaultPagedRuntime.buildPrimitives()
|
|
4065
|
+
];
|
|
4066
|
+
}
|
|
4067
|
+
registerReactiveTracker({
|
|
4068
|
+
id: "data-bind-paged",
|
|
4069
|
+
enableTracking: () => defaultPagedRuntime.enableTracking(),
|
|
4070
|
+
disableTracking: () => defaultPagedRuntime.disableTracking(),
|
|
4071
|
+
getStore: () => ({
|
|
4072
|
+
subscribe: (key, cb) => defaultPagedRuntime.subscribe(key, cb),
|
|
4073
|
+
getKeyVersion: (key) => defaultPagedRuntime.getKeyVersion(key)
|
|
4074
|
+
})
|
|
4075
|
+
});
|
|
4076
|
+
registerPlatformImplementation(PagedPlatform);
|
|
3677
4077
|
function createDefaultFunctionApi(apiUrl, repo, getToken) {
|
|
3678
4078
|
const opts = () => ({ token: getToken() });
|
|
3679
4079
|
return {
|
|
@@ -8299,6 +8699,14 @@ function ReactiveDatasetProvider({
|
|
|
8299
8699
|
);
|
|
8300
8700
|
}
|
|
8301
8701
|
}, [e3.apiUrl, e3.repo, e3.workspace]);
|
|
8702
|
+
useMemo(() => {
|
|
8703
|
+
if (e3.workspace !== void 0) {
|
|
8704
|
+
initializePagedApi(
|
|
8705
|
+
createDefaultPagedApi(e3.apiUrl, e3.repo ?? "default", () => tokenRef.current),
|
|
8706
|
+
e3.workspace
|
|
8707
|
+
);
|
|
8708
|
+
}
|
|
8709
|
+
}, [e3.apiUrl, e3.repo, e3.workspace]);
|
|
8302
8710
|
useMemo(() => {
|
|
8303
8711
|
if (e3.workspace !== void 0) {
|
|
8304
8712
|
initializeRecordApi(
|
|
@@ -8313,6 +8721,7 @@ function ReactiveDatasetProvider({
|
|
|
8313
8721
|
const ws = cache3.getConfig().workspace;
|
|
8314
8722
|
clearReactiveDatasetCache();
|
|
8315
8723
|
clearFunctionApi();
|
|
8724
|
+
clearPagedApi();
|
|
8316
8725
|
clearRecordApi();
|
|
8317
8726
|
cache3.destroy();
|
|
8318
8727
|
if (ws) clearBindingRegistry(ws);
|
|
@@ -9272,6 +9681,7 @@ const EastChakraDiff = memo(function EastChakraDiff2({ value }) {
|
|
|
9272
9681
|
const es = eyebrow({});
|
|
9273
9682
|
const commit = useSlotRecipe({ key: "commitBar" });
|
|
9274
9683
|
const cs = commit({});
|
|
9684
|
+
const btn = useRecipe({ key: "button" });
|
|
9275
9685
|
const allDatasetPaths = useMemo(() => {
|
|
9276
9686
|
const paths = [];
|
|
9277
9687
|
for (const b2 of irBindings) {
|
|
@@ -9573,12 +9983,12 @@ const EastChakraDiff = memo(function EastChakraDiff2({ value }) {
|
|
|
9573
9983
|
" · clean merge"
|
|
9574
9984
|
] }) }),
|
|
9575
9985
|
/* @__PURE__ */ jsxs(Box, { css: cs.btnRow, children: [
|
|
9576
|
-
/* @__PURE__ */ jsx$1(Box, { as: "button", css:
|
|
9986
|
+
/* @__PURE__ */ jsx$1(Box, { as: "button", css: btn({ variant: "danger", size: "md" }), onClick: onDiscardAll, children: "Discard all" }),
|
|
9577
9987
|
/* @__PURE__ */ jsx$1(
|
|
9578
9988
|
Box,
|
|
9579
9989
|
{
|
|
9580
9990
|
as: "button",
|
|
9581
|
-
css:
|
|
9991
|
+
css: btn({ variant: "solid", size: "md" }),
|
|
9582
9992
|
"aria-disabled": applyDisabled,
|
|
9583
9993
|
onClick: applyDisabled ? void 0 : onApply,
|
|
9584
9994
|
title: hasStaleLeaves ? "Discard or re-edit the stale changes before applying." : void 0,
|
|
@@ -63771,6 +64181,7 @@ const defaultPlatformImplementations = [
|
|
|
63771
64181
|
...ShareImpl,
|
|
63772
64182
|
...DecisionBindPlatform,
|
|
63773
64183
|
...BindPlatform,
|
|
64184
|
+
...PagedPlatform,
|
|
63774
64185
|
...FuncPlatform,
|
|
63775
64186
|
...RecordPlatform
|
|
63776
64187
|
];
|
|
@@ -63988,271 +64399,6 @@ class ErrorBoundary extends Component {
|
|
|
63988
64399
|
return this.props.children;
|
|
63989
64400
|
}
|
|
63990
64401
|
}
|
|
63991
|
-
const FIND_DEBOUNCE_MS = 250;
|
|
63992
|
-
const POPUP_LIMIT = 20;
|
|
63993
|
-
function structFields(keyType) {
|
|
63994
|
-
if (keyType.type !== "Struct") return null;
|
|
63995
|
-
const fields = keyType.value;
|
|
63996
|
-
return fields.length > 0 ? fields : null;
|
|
63997
|
-
}
|
|
63998
|
-
function splitTopLevel(text) {
|
|
63999
|
-
const parts = [];
|
|
64000
|
-
let current = "";
|
|
64001
|
-
let inString = false;
|
|
64002
|
-
let depth = 0;
|
|
64003
|
-
for (let i = 0; i < text.length; i++) {
|
|
64004
|
-
const ch = text[i];
|
|
64005
|
-
if (inString) {
|
|
64006
|
-
current += ch;
|
|
64007
|
-
if (ch === "\\" && i + 1 < text.length) {
|
|
64008
|
-
current += text[i + 1];
|
|
64009
|
-
i++;
|
|
64010
|
-
} else if (ch === '"') {
|
|
64011
|
-
inString = false;
|
|
64012
|
-
}
|
|
64013
|
-
continue;
|
|
64014
|
-
}
|
|
64015
|
-
if (ch === '"') {
|
|
64016
|
-
inString = true;
|
|
64017
|
-
current += ch;
|
|
64018
|
-
} else if (ch === "(" || ch === "[" || ch === "{") {
|
|
64019
|
-
depth++;
|
|
64020
|
-
current += ch;
|
|
64021
|
-
} else if (ch === ")" || ch === "]" || ch === "}") {
|
|
64022
|
-
depth--;
|
|
64023
|
-
current += ch;
|
|
64024
|
-
} else if (ch === "," && depth === 0) {
|
|
64025
|
-
parts.push(current);
|
|
64026
|
-
current = "";
|
|
64027
|
-
} else {
|
|
64028
|
-
current += ch;
|
|
64029
|
-
}
|
|
64030
|
-
}
|
|
64031
|
-
parts.push(current);
|
|
64032
|
-
return parts;
|
|
64033
|
-
}
|
|
64034
|
-
function keySignature(keyType) {
|
|
64035
|
-
const fields = structFields(keyType);
|
|
64036
|
-
if (fields === null) return keyType.type;
|
|
64037
|
-
return `(${fields.map((f2) => `${f2.name}: ${f2.type.type}`).join(", ")})`;
|
|
64038
|
-
}
|
|
64039
|
-
function parseKeyInput(keyType, text) {
|
|
64040
|
-
const fields = structFields(keyType);
|
|
64041
|
-
if (fields === null) {
|
|
64042
|
-
if (keyType.type === "String") return { kind: "query", query: { prefix: text } };
|
|
64043
|
-
const parsed = parseFor(keyType)(text);
|
|
64044
|
-
if (!parsed.success) return { kind: "hint", hint: `Key is ${keyType.type}` };
|
|
64045
|
-
return { kind: "query", query: { key: printFor(keyType)(parsed.value) } };
|
|
64046
|
-
}
|
|
64047
|
-
if (text.trimStart().startsWith("(")) {
|
|
64048
|
-
const parsed = parseFor(keyType)(text);
|
|
64049
|
-
if (!parsed.success) return { kind: "hint", hint: `Key is ${keySignature(keyType)}` };
|
|
64050
|
-
return { kind: "query", query: { key: printFor(keyType)(parsed.value) } };
|
|
64051
|
-
}
|
|
64052
|
-
const segments = splitTopLevel(text);
|
|
64053
|
-
if (segments.length > fields.length) {
|
|
64054
|
-
return { kind: "hint", hint: `Key is ${keySignature(keyType)}` };
|
|
64055
|
-
}
|
|
64056
|
-
const exact = [];
|
|
64057
|
-
for (let i = 0; i < segments.length; i++) {
|
|
64058
|
-
const field = fields[i];
|
|
64059
|
-
const raw = segments[i].trim();
|
|
64060
|
-
const isLast = i === segments.length - 1;
|
|
64061
|
-
if (isLast && raw === "" && i > 0) {
|
|
64062
|
-
return { kind: "query", query: { fields: exact } };
|
|
64063
|
-
}
|
|
64064
|
-
if (field.type.type === "String" && !raw.startsWith('"')) {
|
|
64065
|
-
if (isLast) {
|
|
64066
|
-
return exact.length === 0 ? { kind: "query", query: { prefix: raw } } : { kind: "query", query: { fields: exact, prefix: raw } };
|
|
64067
|
-
}
|
|
64068
|
-
exact.push(printFor(StringType)(raw));
|
|
64069
|
-
continue;
|
|
64070
|
-
}
|
|
64071
|
-
const parsed = parseFor(field.type)(raw);
|
|
64072
|
-
if (!parsed.success) {
|
|
64073
|
-
return { kind: "hint", hint: `${field.name} is ${field.type.type} — key is ${keySignature(keyType)}` };
|
|
64074
|
-
}
|
|
64075
|
-
exact.push(printFor(field.type)(parsed.value));
|
|
64076
|
-
}
|
|
64077
|
-
return { kind: "query", query: { fields: exact } };
|
|
64078
|
-
}
|
|
64079
|
-
const MATCH_NOTHING = { lower: () => false, upper: () => false };
|
|
64080
|
-
function keyRangePredicates(keyType, query) {
|
|
64081
|
-
if ("key" in query) return null;
|
|
64082
|
-
if (keyType.type === "Struct") {
|
|
64083
|
-
const meta3 = keyType.value;
|
|
64084
|
-
const literals = "fields" in query ? query.fields : [];
|
|
64085
|
-
if (literals.length > meta3.length) return MATCH_NOTHING;
|
|
64086
|
-
const values = [];
|
|
64087
|
-
for (let j2 = 0; j2 < literals.length; j2++) {
|
|
64088
|
-
const parsed = parseFor(meta3[j2].type)(literals[j2]);
|
|
64089
|
-
if (!parsed.success) return MATCH_NOTHING;
|
|
64090
|
-
values.push(parsed.value);
|
|
64091
|
-
}
|
|
64092
|
-
const cmps = meta3.map((f2) => compareFor(f2.type));
|
|
64093
|
-
const lead = (k2) => {
|
|
64094
|
-
for (let j2 = 0; j2 < values.length; j2++) {
|
|
64095
|
-
const c2 = cmps[j2](k2[meta3[j2].name], values[j2]);
|
|
64096
|
-
if (c2 !== 0) return c2;
|
|
64097
|
-
}
|
|
64098
|
-
return 0;
|
|
64099
|
-
};
|
|
64100
|
-
const prefix22 = query.prefix;
|
|
64101
|
-
if (prefix22 === void 0) {
|
|
64102
|
-
return { lower: (k2) => lead(k2) >= 0, upper: (k2) => lead(k2) > 0 };
|
|
64103
|
-
}
|
|
64104
|
-
const prefixIdx = values.length;
|
|
64105
|
-
if (prefixIdx >= meta3.length || meta3[prefixIdx].type.type !== "String") return MATCH_NOTHING;
|
|
64106
|
-
const prefixName = meta3[prefixIdx].name;
|
|
64107
|
-
const prefixCmp = cmps[prefixIdx];
|
|
64108
|
-
return {
|
|
64109
|
-
lower: (k2) => {
|
|
64110
|
-
const c2 = lead(k2);
|
|
64111
|
-
return c2 !== 0 ? c2 > 0 : prefixCmp(k2[prefixName], prefix22) >= 0;
|
|
64112
|
-
},
|
|
64113
|
-
upper: (k2) => {
|
|
64114
|
-
const c2 = lead(k2);
|
|
64115
|
-
if (c2 !== 0) return c2 > 0;
|
|
64116
|
-
const field = k2[prefixName];
|
|
64117
|
-
return prefixCmp(field, prefix22) > 0 && !field.startsWith(prefix22);
|
|
64118
|
-
}
|
|
64119
|
-
};
|
|
64120
|
-
}
|
|
64121
|
-
if (!("prefix" in query) || query.prefix === void 0 || keyType.type !== "String") return MATCH_NOTHING;
|
|
64122
|
-
const prefix2 = query.prefix;
|
|
64123
|
-
const cmp = compareFor(keyType);
|
|
64124
|
-
return {
|
|
64125
|
-
lower: (k2) => cmp(k2, prefix2) >= 0,
|
|
64126
|
-
upper: (k2) => cmp(k2, prefix2) > 0 && !k2.startsWith(prefix2)
|
|
64127
|
-
};
|
|
64128
|
-
}
|
|
64129
|
-
const DatasetKeySearch = memo(function DatasetKeySearch2({ keyType, onFind, onListRange, onJump, onClear }) {
|
|
64130
|
-
const [range, setRange] = useState(null);
|
|
64131
|
-
const [items, setItems] = useState([]);
|
|
64132
|
-
const [activeIdx, setActiveIdx] = useState(-1);
|
|
64133
|
-
const [hint, setHint] = useState(null);
|
|
64134
|
-
const [resetSeq, setResetSeq] = useState(0);
|
|
64135
|
-
const debounceRef = useRef(void 0);
|
|
64136
|
-
const findSeqRef = useRef(0);
|
|
64137
|
-
useEffect(() => () => clearTimeout(debounceRef.current), []);
|
|
64138
|
-
const runFind = useCallback((query) => {
|
|
64139
|
-
const seq = ++findSeqRef.current;
|
|
64140
|
-
void (async () => {
|
|
64141
|
-
try {
|
|
64142
|
-
const result = await onFind(query);
|
|
64143
|
-
if (seq !== findSeqRef.current) return;
|
|
64144
|
-
setRange(result);
|
|
64145
|
-
setActiveIdx(-1);
|
|
64146
|
-
if (result.found) {
|
|
64147
|
-
const labels = await onListRange(result.row, Math.min(POPUP_LIMIT, result.count));
|
|
64148
|
-
if (seq !== findSeqRef.current) return;
|
|
64149
|
-
setItems(labels.map((label, i) => ({ row: result.row + i, label })));
|
|
64150
|
-
} else {
|
|
64151
|
-
setItems([]);
|
|
64152
|
-
}
|
|
64153
|
-
} catch {
|
|
64154
|
-
if (seq !== findSeqRef.current) return;
|
|
64155
|
-
setRange(null);
|
|
64156
|
-
setItems([]);
|
|
64157
|
-
}
|
|
64158
|
-
})();
|
|
64159
|
-
}, [onFind, onListRange]);
|
|
64160
|
-
const resetQueryState = useCallback(() => {
|
|
64161
|
-
clearTimeout(debounceRef.current);
|
|
64162
|
-
findSeqRef.current++;
|
|
64163
|
-
setRange(null);
|
|
64164
|
-
setItems([]);
|
|
64165
|
-
setActiveIdx(-1);
|
|
64166
|
-
setHint(null);
|
|
64167
|
-
}, []);
|
|
64168
|
-
const handleInput = useCallback((text) => {
|
|
64169
|
-
clearTimeout(debounceRef.current);
|
|
64170
|
-
if (text === "") {
|
|
64171
|
-
resetQueryState();
|
|
64172
|
-
onClear == null ? void 0 : onClear();
|
|
64173
|
-
return;
|
|
64174
|
-
}
|
|
64175
|
-
const parsed = parseKeyInput(keyType, text);
|
|
64176
|
-
if (parsed.kind === "hint") {
|
|
64177
|
-
findSeqRef.current++;
|
|
64178
|
-
setRange(null);
|
|
64179
|
-
setItems([]);
|
|
64180
|
-
setActiveIdx(-1);
|
|
64181
|
-
setHint(parsed.hint);
|
|
64182
|
-
return;
|
|
64183
|
-
}
|
|
64184
|
-
setHint(null);
|
|
64185
|
-
debounceRef.current = setTimeout(() => runFind(parsed.query), FIND_DEBOUNCE_MS);
|
|
64186
|
-
}, [keyType, runFind, resetQueryState, onClear]);
|
|
64187
|
-
const clearSearch = useCallback(() => {
|
|
64188
|
-
resetQueryState();
|
|
64189
|
-
setResetSeq((s2) => s2 + 1);
|
|
64190
|
-
onClear == null ? void 0 : onClear();
|
|
64191
|
-
}, [resetQueryState, onClear]);
|
|
64192
|
-
const commit = useCallback((row) => {
|
|
64193
|
-
onJump(row);
|
|
64194
|
-
if (range !== null) setActiveIdx(row - range.row);
|
|
64195
|
-
}, [onJump, range]);
|
|
64196
|
-
const step3 = useCallback((delta) => {
|
|
64197
|
-
if (range === null || !range.found) return;
|
|
64198
|
-
const next2 = Math.max(0, Math.min(range.count - 1, (activeIdx === -1 ? 0 : activeIdx) + delta));
|
|
64199
|
-
commit(range.row + next2);
|
|
64200
|
-
}, [range, activeIdx, commit]);
|
|
64201
|
-
const onKeyDownCapture = useCallback((e3) => {
|
|
64202
|
-
if (e3.key !== "Enter" || range === null || !range.found) return;
|
|
64203
|
-
if (document.querySelector('[data-scope="combobox"][data-part="content"] [data-highlighted]') !== null) return;
|
|
64204
|
-
commit(range.row + Math.max(0, activeIdx));
|
|
64205
|
-
}, [range, activeIdx, commit]);
|
|
64206
|
-
const placeholder = useMemo(() => {
|
|
64207
|
-
const fields = structFields(keyType);
|
|
64208
|
-
if (fields !== null) return `Search keys (${fields.map((f2) => f2.name).join(", ")})`;
|
|
64209
|
-
return keyType.type === "String" ? "Search keys" : `Find key (${keyType.type})`;
|
|
64210
|
-
}, [keyType]);
|
|
64211
|
-
const payload = useMemo(() => ({
|
|
64212
|
-
value: none$1,
|
|
64213
|
-
items: items.map((it) => ({ value: String(it.row), label: it.label, disabled: none$1 })),
|
|
64214
|
-
placeholder: some(placeholder),
|
|
64215
|
-
multiple: none$1,
|
|
64216
|
-
disabled: none$1,
|
|
64217
|
-
allowCustomValue: some(true),
|
|
64218
|
-
onChange: some((v3) => commit(Number(v3))),
|
|
64219
|
-
onChangeMultiple: none$1,
|
|
64220
|
-
onInputValueChange: some(handleInput),
|
|
64221
|
-
onOpenChange: none$1,
|
|
64222
|
-
style: some({ size: some(variant("xs", null)), color: none$1, background: none$1, borderColor: none$1 })
|
|
64223
|
-
}), [items, placeholder, commit, handleInput]);
|
|
64224
|
-
const status = hint !== null ? hint : range === null ? null : !range.found ? "No matches" : activeIdx === -1 ? `${range.count.toLocaleString()} ${range.count === 1 ? "match" : "matches"}` : `${(activeIdx + 1).toLocaleString()} of ${range.count.toLocaleString()}`;
|
|
64225
|
-
const canStep = range !== null && range.found && range.count > 1;
|
|
64226
|
-
return /* @__PURE__ */ jsxs(Flex, { gap: 1, align: "center", minW: "0", onKeyDownCapture, "data-part": "dataset-key-search", children: [
|
|
64227
|
-
/* @__PURE__ */ jsx$1(Flex, { width: `min(${placeholder.length + 10}ch, 40rem)`, minW: "12rem", flexShrink: 1, children: /* @__PURE__ */ jsx$1(EastChakraCombobox, { value: payload, selectionBehavior: "preserve" }, resetSeq) }),
|
|
64228
|
-
status !== null && /* @__PURE__ */ jsx$1(Text, { fontSize: "xs", color: "fg.muted", whiteSpace: "nowrap", children: status }),
|
|
64229
|
-
canStep && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
64230
|
-
/* @__PURE__ */ jsx$1(
|
|
64231
|
-
IconButton,
|
|
64232
|
-
{
|
|
64233
|
-
"aria-label": "Previous match",
|
|
64234
|
-
size: "2xs",
|
|
64235
|
-
variant: "ghost",
|
|
64236
|
-
disabled: activeIdx <= 0,
|
|
64237
|
-
onClick: () => step3(-1),
|
|
64238
|
-
children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faChevronUp })
|
|
64239
|
-
}
|
|
64240
|
-
),
|
|
64241
|
-
/* @__PURE__ */ jsx$1(
|
|
64242
|
-
IconButton,
|
|
64243
|
-
{
|
|
64244
|
-
"aria-label": "Next match",
|
|
64245
|
-
size: "2xs",
|
|
64246
|
-
variant: "ghost",
|
|
64247
|
-
disabled: activeIdx >= range.count - 1,
|
|
64248
|
-
onClick: () => step3(1),
|
|
64249
|
-
children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faChevronDown })
|
|
64250
|
-
}
|
|
64251
|
-
)
|
|
64252
|
-
] }),
|
|
64253
|
-
(range !== null || hint !== null) && /* @__PURE__ */ jsx$1(IconButton, { "aria-label": "Clear search", size: "2xs", variant: "ghost", onClick: clearSearch, children: /* @__PURE__ */ jsx$1(FontAwesomeIcon, { icon: faXmark }) })
|
|
64254
|
-
] });
|
|
64255
|
-
});
|
|
64256
64402
|
function pagingDebug(...args) {
|
|
64257
64403
|
try {
|
|
64258
64404
|
if (typeof localStorage === "undefined") return;
|
|
@@ -64684,7 +64830,7 @@ const UITaskPreview = memo(function UITaskPreview2({
|
|
|
64684
64830
|
const manifest = useMemo(() => {
|
|
64685
64831
|
if (!details || !isUI) return null;
|
|
64686
64832
|
const meta3 = getTaskMetadata(details);
|
|
64687
|
-
return meta3 ? decodeManifest(meta3) : { paths: [], functions: [], records: [] };
|
|
64833
|
+
return meta3 ? decodeManifest(meta3) : { paths: [], functions: [], records: [], pages: [] };
|
|
64688
64834
|
}, [details, isUI]);
|
|
64689
64835
|
const outputPath = details ? treePathToString$1(details.output) : null;
|
|
64690
64836
|
const preloads = useMemo(
|
|
@@ -64708,6 +64854,7 @@ const UITaskPreview = memo(function UITaskPreview2({
|
|
|
64708
64854
|
...ShareImpl,
|
|
64709
64855
|
...DecisionBindPlatform,
|
|
64710
64856
|
...createScopedBindPlatform(manifest),
|
|
64857
|
+
...createScopedPagedPlatform(manifest.pages),
|
|
64711
64858
|
...createScopedFuncPlatform(manifest.functions),
|
|
64712
64859
|
...createScopedRecordPlatform(manifest.records)
|
|
64713
64860
|
] : void 0,
|
|
@@ -65621,7 +65768,7 @@ export {
|
|
|
65621
65768
|
BindPlatform,
|
|
65622
65769
|
BindRuntime,
|
|
65623
65770
|
DataTaskPreview,
|
|
65624
|
-
DatasetKeySearch,
|
|
65771
|
+
DatasetKeySearch2 as DatasetKeySearch,
|
|
65625
65772
|
DatasetPreview,
|
|
65626
65773
|
E3Provider,
|
|
65627
65774
|
EastChakraDecisionJournal,
|
|
@@ -65636,6 +65783,8 @@ export {
|
|
|
65636
65783
|
IndexedDBStagedAdapter,
|
|
65637
65784
|
InputPreview,
|
|
65638
65785
|
MemoryStagedAdapter,
|
|
65786
|
+
PagedPlatform,
|
|
65787
|
+
PagedRuntime,
|
|
65639
65788
|
ReactiveDatasetCache,
|
|
65640
65789
|
ReactiveDatasetLoader,
|
|
65641
65790
|
ReactiveDatasetProvider,
|
|
@@ -65649,6 +65798,7 @@ export {
|
|
|
65649
65798
|
awaitPendingWrites,
|
|
65650
65799
|
clearBindingRegistry,
|
|
65651
65800
|
clearFunctionApi,
|
|
65801
|
+
clearPagedApi,
|
|
65652
65802
|
clearPendingWrites,
|
|
65653
65803
|
clearReactiveDatasetCache,
|
|
65654
65804
|
clearReactiveDatasetListCache,
|
|
@@ -65656,17 +65806,20 @@ export {
|
|
|
65656
65806
|
clearStagedStoreSingleton,
|
|
65657
65807
|
createDefaultDatasetApi,
|
|
65658
65808
|
createDefaultFunctionApi,
|
|
65809
|
+
createDefaultPagedApi,
|
|
65659
65810
|
createDefaultRecordApi,
|
|
65660
65811
|
createInMemoryFunctionApi,
|
|
65661
65812
|
createInMemoryRecordApi,
|
|
65662
65813
|
createReactiveDatasetCache,
|
|
65663
65814
|
createScopedBindPlatform,
|
|
65664
65815
|
createScopedFuncPlatform,
|
|
65816
|
+
createScopedPagedPlatform,
|
|
65665
65817
|
createScopedRecordPlatform,
|
|
65666
65818
|
datasetCacheKey,
|
|
65667
65819
|
datasetPathToString,
|
|
65668
65820
|
defaultBindRuntime,
|
|
65669
65821
|
defaultFuncRuntime,
|
|
65822
|
+
defaultPagedRuntime,
|
|
65670
65823
|
defaultRecordRuntime,
|
|
65671
65824
|
disableBindingTracking,
|
|
65672
65825
|
enableBindingTracking,
|
|
@@ -65679,11 +65832,14 @@ export {
|
|
|
65679
65832
|
getTaskKind,
|
|
65680
65833
|
getTaskMetadata,
|
|
65681
65834
|
initializeFunctionApi,
|
|
65835
|
+
initializePagedApi,
|
|
65682
65836
|
initializeReactiveDatasetCache,
|
|
65683
65837
|
initializeRecordApi,
|
|
65684
65838
|
initializeStagedStore,
|
|
65685
65839
|
isBindingTracking,
|
|
65686
65840
|
onWriteError,
|
|
65841
|
+
pagedTotalKey,
|
|
65842
|
+
pagedWindowKey,
|
|
65687
65843
|
preloadReactiveDatasetList,
|
|
65688
65844
|
realClock,
|
|
65689
65845
|
recordChannelKey,
|