dsh-motion-ui 0.5.2 → 0.5.4
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/CHANGELOG.md +16 -0
- package/README.md +44 -2
- package/VERIFICATION.md +24 -0
- package/client.js +444 -257
- package/index.js +24 -9
- package/lib/author-expression.js +3 -2
- package/lib/authoring-guide.js +9 -0
- package/lib/build-info.js +1 -1
- package/lib/canvas-design.js +3 -3
- package/lib/canvas-preview.js +1 -1
- package/lib/canvas-system.js +6 -2
- package/lib/catalog.js +5 -4
- package/lib/components.js +2 -2
- package/lib/export-runtime-bundle.js +1 -1
- package/lib/freeform.js +3 -2
- package/lib/identifiers.js +4 -0
- package/lib/protocol.js +20 -10
- package/lib/quick-examples.js +8 -0
- package/lib/stream.js +2 -1
- package/lib/tool-json.js +21 -2
- package/lib/tool-schema.js +29 -0
- package/lib/ui-intent.js +2 -2
- package/lib/ui-skill.js +2 -1
- package/package.json +1 -1
- package/skills/intelligent-ui/SKILL.md +8 -2
package/client.js
CHANGED
|
@@ -16,9 +16,9 @@ var __export = (target, all) => {
|
|
|
16
16
|
};
|
|
17
17
|
var __copyProps = (to, from, except, desc) => {
|
|
18
18
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
19
|
-
for (let
|
|
20
|
-
if (!__hasOwnProp.call(to,
|
|
21
|
-
__defProp(to,
|
|
19
|
+
for (let key2 of __getOwnPropNames(from))
|
|
20
|
+
if (!__hasOwnProp.call(to, key2) && key2 !== except)
|
|
21
|
+
__defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable });
|
|
22
22
|
}
|
|
23
23
|
return to;
|
|
24
24
|
};
|
|
@@ -504,9 +504,9 @@ var require_react_dom_development = __commonJS({
|
|
|
504
504
|
if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart === "function") {
|
|
505
505
|
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
|
|
506
506
|
}
|
|
507
|
-
var
|
|
507
|
+
var React10 = require("react");
|
|
508
508
|
var Scheduler = require_scheduler();
|
|
509
|
-
var ReactSharedInternals =
|
|
509
|
+
var ReactSharedInternals = React10.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
|
|
510
510
|
var suppressWarning = false;
|
|
511
511
|
function setSuppressWarning(newSuppressWarning) {
|
|
512
512
|
{
|
|
@@ -2113,7 +2113,7 @@ var require_react_dom_development = __commonJS({
|
|
|
2113
2113
|
{
|
|
2114
2114
|
if (props.value == null) {
|
|
2115
2115
|
if (typeof props.children === "object" && props.children !== null) {
|
|
2116
|
-
|
|
2116
|
+
React10.Children.forEach(props.children, function(child) {
|
|
2117
2117
|
if (child == null) {
|
|
2118
2118
|
return;
|
|
2119
2119
|
}
|
|
@@ -2506,8 +2506,8 @@ var require_react_dom_development = __commonJS({
|
|
|
2506
2506
|
strokeOpacity: true,
|
|
2507
2507
|
strokeWidth: true
|
|
2508
2508
|
};
|
|
2509
|
-
function prefixKey(prefix2,
|
|
2510
|
-
return prefix2 +
|
|
2509
|
+
function prefixKey(prefix2, key2) {
|
|
2510
|
+
return prefix2 + key2.charAt(0).toUpperCase() + key2.substring(1);
|
|
2511
2511
|
}
|
|
2512
2512
|
var prefixes = ["Webkit", "ms", "Moz", "O"];
|
|
2513
2513
|
Object.keys(isUnitlessNumber).forEach(function(prop) {
|
|
@@ -2656,10 +2656,10 @@ var require_react_dom_development = __commonJS({
|
|
|
2656
2656
|
}
|
|
2657
2657
|
function expandShorthandMap(styles) {
|
|
2658
2658
|
var expanded = {};
|
|
2659
|
-
for (var
|
|
2660
|
-
var longhands = shorthandToLonghand[
|
|
2659
|
+
for (var key2 in styles) {
|
|
2660
|
+
var longhands = shorthandToLonghand[key2] || [key2];
|
|
2661
2661
|
for (var i = 0; i < longhands.length; i++) {
|
|
2662
|
-
expanded[longhands[i]] =
|
|
2662
|
+
expanded[longhands[i]] = key2;
|
|
2663
2663
|
}
|
|
2664
2664
|
}
|
|
2665
2665
|
return expanded;
|
|
@@ -2672,9 +2672,9 @@ var require_react_dom_development = __commonJS({
|
|
|
2672
2672
|
var expandedUpdates = expandShorthandMap(styleUpdates);
|
|
2673
2673
|
var expandedStyles = expandShorthandMap(nextStyles);
|
|
2674
2674
|
var warnedAbout = {};
|
|
2675
|
-
for (var
|
|
2676
|
-
var originalKey = expandedUpdates[
|
|
2677
|
-
var correctOriginalKey = expandedStyles[
|
|
2675
|
+
for (var key2 in expandedUpdates) {
|
|
2676
|
+
var originalKey = expandedUpdates[key2];
|
|
2677
|
+
var correctOriginalKey = expandedStyles[key2];
|
|
2678
2678
|
if (correctOriginalKey && originalKey !== correctOriginalKey) {
|
|
2679
2679
|
var warningKey = originalKey + "," + correctOriginalKey;
|
|
2680
2680
|
if (warnedAbout[warningKey]) {
|
|
@@ -3345,10 +3345,10 @@ var require_react_dom_development = __commonJS({
|
|
|
3345
3345
|
function warnInvalidARIAProps(type, props) {
|
|
3346
3346
|
{
|
|
3347
3347
|
var invalidProps = [];
|
|
3348
|
-
for (var
|
|
3349
|
-
var isValid = validateProperty(type,
|
|
3348
|
+
for (var key2 in props) {
|
|
3349
|
+
var isValid = validateProperty(type, key2);
|
|
3350
3350
|
if (!isValid) {
|
|
3351
|
-
invalidProps.push(
|
|
3351
|
+
invalidProps.push(key2);
|
|
3352
3352
|
}
|
|
3353
3353
|
}
|
|
3354
3354
|
var unknownPropString = invalidProps.map(function(prop) {
|
|
@@ -3488,10 +3488,10 @@ var require_react_dom_development = __commonJS({
|
|
|
3488
3488
|
var warnUnknownProperties = function(type, props, eventRegistry) {
|
|
3489
3489
|
{
|
|
3490
3490
|
var unknownProps = [];
|
|
3491
|
-
for (var
|
|
3492
|
-
var isValid = validateProperty$1(type,
|
|
3491
|
+
for (var key2 in props) {
|
|
3492
|
+
var isValid = validateProperty$1(type, key2, props[key2], eventRegistry);
|
|
3493
3493
|
if (!isValid) {
|
|
3494
|
-
unknownProps.push(
|
|
3494
|
+
unknownProps.push(key2);
|
|
3495
3495
|
}
|
|
3496
3496
|
}
|
|
3497
3497
|
var unknownPropString = unknownProps.map(function(prop) {
|
|
@@ -3796,14 +3796,14 @@ var require_react_dom_development = __commonJS({
|
|
|
3796
3796
|
throw new Error("clearCaughtError was called but no error was captured. This error is likely caused by a bug in React. Please file an issue.");
|
|
3797
3797
|
}
|
|
3798
3798
|
}
|
|
3799
|
-
function get(
|
|
3800
|
-
return
|
|
3799
|
+
function get(key2) {
|
|
3800
|
+
return key2._reactInternals;
|
|
3801
3801
|
}
|
|
3802
|
-
function has(
|
|
3803
|
-
return
|
|
3802
|
+
function has(key2) {
|
|
3803
|
+
return key2._reactInternals !== void 0;
|
|
3804
3804
|
}
|
|
3805
|
-
function set(
|
|
3806
|
-
|
|
3805
|
+
function set(key2, value) {
|
|
3806
|
+
key2._reactInternals = value;
|
|
3807
3807
|
}
|
|
3808
3808
|
var NoFlags = (
|
|
3809
3809
|
/* */
|
|
@@ -5378,9 +5378,9 @@ var require_react_dom_development = __commonJS({
|
|
|
5378
5378
|
}
|
|
5379
5379
|
return true;
|
|
5380
5380
|
}
|
|
5381
|
-
function attemptReplayContinuousQueuedEventInMap(queuedEvent,
|
|
5381
|
+
function attemptReplayContinuousQueuedEventInMap(queuedEvent, key2, map) {
|
|
5382
5382
|
if (attemptReplayContinuousQueuedEvent(queuedEvent)) {
|
|
5383
|
-
map.delete(
|
|
5383
|
+
map.delete(key2);
|
|
5384
5384
|
}
|
|
5385
5385
|
}
|
|
5386
5386
|
function replayUnblockedEvents() {
|
|
@@ -5976,9 +5976,9 @@ var require_react_dom_development = __commonJS({
|
|
|
5976
5976
|
};
|
|
5977
5977
|
function getEventKey(nativeEvent) {
|
|
5978
5978
|
if (nativeEvent.key) {
|
|
5979
|
-
var
|
|
5980
|
-
if (
|
|
5981
|
-
return
|
|
5979
|
+
var key2 = normalizeKey[nativeEvent.key] || nativeEvent.key;
|
|
5980
|
+
if (key2 !== "Unidentified") {
|
|
5981
|
+
return key2;
|
|
5982
5982
|
}
|
|
5983
5983
|
}
|
|
5984
5984
|
if (nativeEvent.type === "keypress") {
|
|
@@ -9033,8 +9033,8 @@ var require_react_dom_development = __commonJS({
|
|
|
9033
9033
|
return instance.__reactInternalMemoizedMaskedChildContext;
|
|
9034
9034
|
}
|
|
9035
9035
|
var context = {};
|
|
9036
|
-
for (var
|
|
9037
|
-
context[
|
|
9036
|
+
for (var key2 in contextTypes) {
|
|
9037
|
+
context[key2] = unmaskedContext[key2];
|
|
9038
9038
|
}
|
|
9039
9039
|
{
|
|
9040
9040
|
var name = getComponentNameFromFiber(workInProgress2) || "Unknown";
|
|
@@ -10140,9 +10140,9 @@ var require_react_dom_development = __commonJS({
|
|
|
10140
10140
|
return existing;
|
|
10141
10141
|
}
|
|
10142
10142
|
}
|
|
10143
|
-
function updateFragment2(returnFiber, current3, fragment, lanes,
|
|
10143
|
+
function updateFragment2(returnFiber, current3, fragment, lanes, key2) {
|
|
10144
10144
|
if (current3 === null || current3.tag !== Fragment) {
|
|
10145
|
-
var created = createFiberFromFragment(fragment, returnFiber.mode, lanes,
|
|
10145
|
+
var created = createFiberFromFragment(fragment, returnFiber.mode, lanes, key2);
|
|
10146
10146
|
created.return = returnFiber;
|
|
10147
10147
|
return created;
|
|
10148
10148
|
} else {
|
|
@@ -10191,9 +10191,9 @@ var require_react_dom_development = __commonJS({
|
|
|
10191
10191
|
return null;
|
|
10192
10192
|
}
|
|
10193
10193
|
function updateSlot(returnFiber, oldFiber, newChild, lanes) {
|
|
10194
|
-
var
|
|
10194
|
+
var key2 = oldFiber !== null ? oldFiber.key : null;
|
|
10195
10195
|
if (typeof newChild === "string" && newChild !== "" || typeof newChild === "number") {
|
|
10196
|
-
if (
|
|
10196
|
+
if (key2 !== null) {
|
|
10197
10197
|
return null;
|
|
10198
10198
|
}
|
|
10199
10199
|
return updateTextNode(returnFiber, oldFiber, "" + newChild, lanes);
|
|
@@ -10201,14 +10201,14 @@ var require_react_dom_development = __commonJS({
|
|
|
10201
10201
|
if (typeof newChild === "object" && newChild !== null) {
|
|
10202
10202
|
switch (newChild.$$typeof) {
|
|
10203
10203
|
case REACT_ELEMENT_TYPE: {
|
|
10204
|
-
if (newChild.key ===
|
|
10204
|
+
if (newChild.key === key2) {
|
|
10205
10205
|
return updateElement(returnFiber, oldFiber, newChild, lanes);
|
|
10206
10206
|
} else {
|
|
10207
10207
|
return null;
|
|
10208
10208
|
}
|
|
10209
10209
|
}
|
|
10210
10210
|
case REACT_PORTAL_TYPE: {
|
|
10211
|
-
if (newChild.key ===
|
|
10211
|
+
if (newChild.key === key2) {
|
|
10212
10212
|
return updatePortal(returnFiber, oldFiber, newChild, lanes);
|
|
10213
10213
|
} else {
|
|
10214
10214
|
return null;
|
|
@@ -10221,7 +10221,7 @@ var require_react_dom_development = __commonJS({
|
|
|
10221
10221
|
}
|
|
10222
10222
|
}
|
|
10223
10223
|
if (isArray(newChild) || getIteratorFn(newChild)) {
|
|
10224
|
-
if (
|
|
10224
|
+
if (key2 !== null) {
|
|
10225
10225
|
return null;
|
|
10226
10226
|
}
|
|
10227
10227
|
return updateFragment2(returnFiber, oldFiber, newChild, lanes, null);
|
|
@@ -10277,20 +10277,20 @@ var require_react_dom_development = __commonJS({
|
|
|
10277
10277
|
case REACT_ELEMENT_TYPE:
|
|
10278
10278
|
case REACT_PORTAL_TYPE:
|
|
10279
10279
|
warnForMissingKey(child, returnFiber);
|
|
10280
|
-
var
|
|
10281
|
-
if (typeof
|
|
10280
|
+
var key2 = child.key;
|
|
10281
|
+
if (typeof key2 !== "string") {
|
|
10282
10282
|
break;
|
|
10283
10283
|
}
|
|
10284
10284
|
if (knownKeys === null) {
|
|
10285
10285
|
knownKeys = /* @__PURE__ */ new Set();
|
|
10286
|
-
knownKeys.add(
|
|
10286
|
+
knownKeys.add(key2);
|
|
10287
10287
|
break;
|
|
10288
10288
|
}
|
|
10289
|
-
if (!knownKeys.has(
|
|
10290
|
-
knownKeys.add(
|
|
10289
|
+
if (!knownKeys.has(key2)) {
|
|
10290
|
+
knownKeys.add(key2);
|
|
10291
10291
|
break;
|
|
10292
10292
|
}
|
|
10293
|
-
error("Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted \u2014 the behavior is unsupported and could change in a future version.",
|
|
10293
|
+
error("Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted \u2014 the behavior is unsupported and could change in a future version.", key2);
|
|
10294
10294
|
break;
|
|
10295
10295
|
case REACT_LAZY_TYPE:
|
|
10296
10296
|
var payload = child._payload;
|
|
@@ -10538,10 +10538,10 @@ var require_react_dom_development = __commonJS({
|
|
|
10538
10538
|
return created;
|
|
10539
10539
|
}
|
|
10540
10540
|
function reconcileSingleElement(returnFiber, currentFirstChild, element, lanes) {
|
|
10541
|
-
var
|
|
10541
|
+
var key2 = element.key;
|
|
10542
10542
|
var child = currentFirstChild;
|
|
10543
10543
|
while (child !== null) {
|
|
10544
|
-
if (child.key ===
|
|
10544
|
+
if (child.key === key2) {
|
|
10545
10545
|
var elementType = element.type;
|
|
10546
10546
|
if (elementType === REACT_FRAGMENT_TYPE) {
|
|
10547
10547
|
if (child.tag === Fragment) {
|
|
@@ -10591,10 +10591,10 @@ var require_react_dom_development = __commonJS({
|
|
|
10591
10591
|
}
|
|
10592
10592
|
}
|
|
10593
10593
|
function reconcileSinglePortal(returnFiber, currentFirstChild, portal, lanes) {
|
|
10594
|
-
var
|
|
10594
|
+
var key2 = portal.key;
|
|
10595
10595
|
var child = currentFirstChild;
|
|
10596
10596
|
while (child !== null) {
|
|
10597
|
-
if (child.key ===
|
|
10597
|
+
if (child.key === key2) {
|
|
10598
10598
|
if (child.tag === HostPortal && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) {
|
|
10599
10599
|
deleteRemainingChildren(returnFiber, child.sibling);
|
|
10600
10600
|
var existing = useFiber(child, portal.children || []);
|
|
@@ -11929,17 +11929,17 @@ var require_react_dom_development = __commonJS({
|
|
|
11929
11929
|
}
|
|
11930
11930
|
return [newState, dispatch];
|
|
11931
11931
|
}
|
|
11932
|
-
function mountMutableSource(source, getSnapshot,
|
|
11932
|
+
function mountMutableSource(source, getSnapshot, subscribe2) {
|
|
11933
11933
|
{
|
|
11934
11934
|
return void 0;
|
|
11935
11935
|
}
|
|
11936
11936
|
}
|
|
11937
|
-
function updateMutableSource(source, getSnapshot,
|
|
11937
|
+
function updateMutableSource(source, getSnapshot, subscribe2) {
|
|
11938
11938
|
{
|
|
11939
11939
|
return void 0;
|
|
11940
11940
|
}
|
|
11941
11941
|
}
|
|
11942
|
-
function mountSyncExternalStore(
|
|
11942
|
+
function mountSyncExternalStore(subscribe2, getSnapshot, getServerSnapshot) {
|
|
11943
11943
|
var fiber = currentlyRenderingFiber$1;
|
|
11944
11944
|
var hook = mountWorkInProgressHook();
|
|
11945
11945
|
var nextSnapshot;
|
|
@@ -11982,12 +11982,12 @@ var require_react_dom_development = __commonJS({
|
|
|
11982
11982
|
getSnapshot
|
|
11983
11983
|
};
|
|
11984
11984
|
hook.queue = inst;
|
|
11985
|
-
mountEffect(subscribeToStore.bind(null, fiber, inst,
|
|
11985
|
+
mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe2), [subscribe2]);
|
|
11986
11986
|
fiber.flags |= Passive;
|
|
11987
11987
|
pushEffect(HasEffect | Passive$1, updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), void 0, null);
|
|
11988
11988
|
return nextSnapshot;
|
|
11989
11989
|
}
|
|
11990
|
-
function updateSyncExternalStore(
|
|
11990
|
+
function updateSyncExternalStore(subscribe2, getSnapshot, getServerSnapshot) {
|
|
11991
11991
|
var fiber = currentlyRenderingFiber$1;
|
|
11992
11992
|
var hook = updateWorkInProgressHook();
|
|
11993
11993
|
var nextSnapshot = getSnapshot();
|
|
@@ -12007,7 +12007,7 @@ var require_react_dom_development = __commonJS({
|
|
|
12007
12007
|
markWorkInProgressReceivedUpdate();
|
|
12008
12008
|
}
|
|
12009
12009
|
var inst = hook.queue;
|
|
12010
|
-
updateEffect(subscribeToStore.bind(null, fiber, inst,
|
|
12010
|
+
updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe2), [subscribe2]);
|
|
12011
12011
|
if (inst.getSnapshot !== getSnapshot || snapshotChanged || // Check if the susbcribe function changed. We can save some memory by
|
|
12012
12012
|
// checking whether we scheduled a subscription effect above.
|
|
12013
12013
|
workInProgressHook !== null && workInProgressHook.memoizedState.tag & HasEffect) {
|
|
@@ -12050,13 +12050,13 @@ var require_react_dom_development = __commonJS({
|
|
|
12050
12050
|
forceStoreRerender(fiber);
|
|
12051
12051
|
}
|
|
12052
12052
|
}
|
|
12053
|
-
function subscribeToStore(fiber, inst,
|
|
12053
|
+
function subscribeToStore(fiber, inst, subscribe2) {
|
|
12054
12054
|
var handleStoreChange = function() {
|
|
12055
12055
|
if (checkIfSnapshotChanged(inst)) {
|
|
12056
12056
|
forceStoreRerender(fiber);
|
|
12057
12057
|
}
|
|
12058
12058
|
};
|
|
12059
|
-
return
|
|
12059
|
+
return subscribe2(handleStoreChange);
|
|
12060
12060
|
}
|
|
12061
12061
|
function checkIfSnapshotChanged(inst) {
|
|
12062
12062
|
var latestGetSnapshot = inst.getSnapshot;
|
|
@@ -12637,15 +12637,15 @@ var require_react_dom_development = __commonJS({
|
|
|
12637
12637
|
mountHookTypesDev();
|
|
12638
12638
|
return mountTransition();
|
|
12639
12639
|
},
|
|
12640
|
-
useMutableSource: function(source, getSnapshot,
|
|
12640
|
+
useMutableSource: function(source, getSnapshot, subscribe2) {
|
|
12641
12641
|
currentHookNameInDev = "useMutableSource";
|
|
12642
12642
|
mountHookTypesDev();
|
|
12643
12643
|
return mountMutableSource();
|
|
12644
12644
|
},
|
|
12645
|
-
useSyncExternalStore: function(
|
|
12645
|
+
useSyncExternalStore: function(subscribe2, getSnapshot, getServerSnapshot) {
|
|
12646
12646
|
currentHookNameInDev = "useSyncExternalStore";
|
|
12647
12647
|
mountHookTypesDev();
|
|
12648
|
-
return mountSyncExternalStore(
|
|
12648
|
+
return mountSyncExternalStore(subscribe2, getSnapshot, getServerSnapshot);
|
|
12649
12649
|
},
|
|
12650
12650
|
useId: function() {
|
|
12651
12651
|
currentHookNameInDev = "useId";
|
|
@@ -12741,15 +12741,15 @@ var require_react_dom_development = __commonJS({
|
|
|
12741
12741
|
updateHookTypesDev();
|
|
12742
12742
|
return mountTransition();
|
|
12743
12743
|
},
|
|
12744
|
-
useMutableSource: function(source, getSnapshot,
|
|
12744
|
+
useMutableSource: function(source, getSnapshot, subscribe2) {
|
|
12745
12745
|
currentHookNameInDev = "useMutableSource";
|
|
12746
12746
|
updateHookTypesDev();
|
|
12747
12747
|
return mountMutableSource();
|
|
12748
12748
|
},
|
|
12749
|
-
useSyncExternalStore: function(
|
|
12749
|
+
useSyncExternalStore: function(subscribe2, getSnapshot, getServerSnapshot) {
|
|
12750
12750
|
currentHookNameInDev = "useSyncExternalStore";
|
|
12751
12751
|
updateHookTypesDev();
|
|
12752
|
-
return mountSyncExternalStore(
|
|
12752
|
+
return mountSyncExternalStore(subscribe2, getSnapshot, getServerSnapshot);
|
|
12753
12753
|
},
|
|
12754
12754
|
useId: function() {
|
|
12755
12755
|
currentHookNameInDev = "useId";
|
|
@@ -12845,15 +12845,15 @@ var require_react_dom_development = __commonJS({
|
|
|
12845
12845
|
updateHookTypesDev();
|
|
12846
12846
|
return updateTransition();
|
|
12847
12847
|
},
|
|
12848
|
-
useMutableSource: function(source, getSnapshot,
|
|
12848
|
+
useMutableSource: function(source, getSnapshot, subscribe2) {
|
|
12849
12849
|
currentHookNameInDev = "useMutableSource";
|
|
12850
12850
|
updateHookTypesDev();
|
|
12851
12851
|
return updateMutableSource();
|
|
12852
12852
|
},
|
|
12853
|
-
useSyncExternalStore: function(
|
|
12853
|
+
useSyncExternalStore: function(subscribe2, getSnapshot, getServerSnapshot) {
|
|
12854
12854
|
currentHookNameInDev = "useSyncExternalStore";
|
|
12855
12855
|
updateHookTypesDev();
|
|
12856
|
-
return updateSyncExternalStore(
|
|
12856
|
+
return updateSyncExternalStore(subscribe2, getSnapshot);
|
|
12857
12857
|
},
|
|
12858
12858
|
useId: function() {
|
|
12859
12859
|
currentHookNameInDev = "useId";
|
|
@@ -12949,15 +12949,15 @@ var require_react_dom_development = __commonJS({
|
|
|
12949
12949
|
updateHookTypesDev();
|
|
12950
12950
|
return rerenderTransition();
|
|
12951
12951
|
},
|
|
12952
|
-
useMutableSource: function(source, getSnapshot,
|
|
12952
|
+
useMutableSource: function(source, getSnapshot, subscribe2) {
|
|
12953
12953
|
currentHookNameInDev = "useMutableSource";
|
|
12954
12954
|
updateHookTypesDev();
|
|
12955
12955
|
return updateMutableSource();
|
|
12956
12956
|
},
|
|
12957
|
-
useSyncExternalStore: function(
|
|
12957
|
+
useSyncExternalStore: function(subscribe2, getSnapshot, getServerSnapshot) {
|
|
12958
12958
|
currentHookNameInDev = "useSyncExternalStore";
|
|
12959
12959
|
updateHookTypesDev();
|
|
12960
|
-
return updateSyncExternalStore(
|
|
12960
|
+
return updateSyncExternalStore(subscribe2, getSnapshot);
|
|
12961
12961
|
},
|
|
12962
12962
|
useId: function() {
|
|
12963
12963
|
currentHookNameInDev = "useId";
|
|
@@ -13067,17 +13067,17 @@ var require_react_dom_development = __commonJS({
|
|
|
13067
13067
|
mountHookTypesDev();
|
|
13068
13068
|
return mountTransition();
|
|
13069
13069
|
},
|
|
13070
|
-
useMutableSource: function(source, getSnapshot,
|
|
13070
|
+
useMutableSource: function(source, getSnapshot, subscribe2) {
|
|
13071
13071
|
currentHookNameInDev = "useMutableSource";
|
|
13072
13072
|
warnInvalidHookAccess();
|
|
13073
13073
|
mountHookTypesDev();
|
|
13074
13074
|
return mountMutableSource();
|
|
13075
13075
|
},
|
|
13076
|
-
useSyncExternalStore: function(
|
|
13076
|
+
useSyncExternalStore: function(subscribe2, getSnapshot, getServerSnapshot) {
|
|
13077
13077
|
currentHookNameInDev = "useSyncExternalStore";
|
|
13078
13078
|
warnInvalidHookAccess();
|
|
13079
13079
|
mountHookTypesDev();
|
|
13080
|
-
return mountSyncExternalStore(
|
|
13080
|
+
return mountSyncExternalStore(subscribe2, getSnapshot, getServerSnapshot);
|
|
13081
13081
|
},
|
|
13082
13082
|
useId: function() {
|
|
13083
13083
|
currentHookNameInDev = "useId";
|
|
@@ -13188,17 +13188,17 @@ var require_react_dom_development = __commonJS({
|
|
|
13188
13188
|
updateHookTypesDev();
|
|
13189
13189
|
return updateTransition();
|
|
13190
13190
|
},
|
|
13191
|
-
useMutableSource: function(source, getSnapshot,
|
|
13191
|
+
useMutableSource: function(source, getSnapshot, subscribe2) {
|
|
13192
13192
|
currentHookNameInDev = "useMutableSource";
|
|
13193
13193
|
warnInvalidHookAccess();
|
|
13194
13194
|
updateHookTypesDev();
|
|
13195
13195
|
return updateMutableSource();
|
|
13196
13196
|
},
|
|
13197
|
-
useSyncExternalStore: function(
|
|
13197
|
+
useSyncExternalStore: function(subscribe2, getSnapshot, getServerSnapshot) {
|
|
13198
13198
|
currentHookNameInDev = "useSyncExternalStore";
|
|
13199
13199
|
warnInvalidHookAccess();
|
|
13200
13200
|
updateHookTypesDev();
|
|
13201
|
-
return updateSyncExternalStore(
|
|
13201
|
+
return updateSyncExternalStore(subscribe2, getSnapshot);
|
|
13202
13202
|
},
|
|
13203
13203
|
useId: function() {
|
|
13204
13204
|
currentHookNameInDev = "useId";
|
|
@@ -13309,17 +13309,17 @@ var require_react_dom_development = __commonJS({
|
|
|
13309
13309
|
updateHookTypesDev();
|
|
13310
13310
|
return rerenderTransition();
|
|
13311
13311
|
},
|
|
13312
|
-
useMutableSource: function(source, getSnapshot,
|
|
13312
|
+
useMutableSource: function(source, getSnapshot, subscribe2) {
|
|
13313
13313
|
currentHookNameInDev = "useMutableSource";
|
|
13314
13314
|
warnInvalidHookAccess();
|
|
13315
13315
|
updateHookTypesDev();
|
|
13316
13316
|
return updateMutableSource();
|
|
13317
13317
|
},
|
|
13318
|
-
useSyncExternalStore: function(
|
|
13318
|
+
useSyncExternalStore: function(subscribe2, getSnapshot, getServerSnapshot) {
|
|
13319
13319
|
currentHookNameInDev = "useSyncExternalStore";
|
|
13320
13320
|
warnInvalidHookAccess();
|
|
13321
13321
|
updateHookTypesDev();
|
|
13322
|
-
return updateSyncExternalStore(
|
|
13322
|
+
return updateSyncExternalStore(subscribe2, getSnapshot);
|
|
13323
13323
|
},
|
|
13324
13324
|
useId: function() {
|
|
13325
13325
|
currentHookNameInDev = "useId";
|
|
@@ -13479,9 +13479,9 @@ var require_react_dom_development = __commonJS({
|
|
|
13479
13479
|
if (callback === null || typeof callback === "function") {
|
|
13480
13480
|
return;
|
|
13481
13481
|
}
|
|
13482
|
-
var
|
|
13483
|
-
if (!didWarnOnInvalidCallback.has(
|
|
13484
|
-
didWarnOnInvalidCallback.add(
|
|
13482
|
+
var key2 = callerName + "_" + callback;
|
|
13483
|
+
if (!didWarnOnInvalidCallback.has(key2)) {
|
|
13484
|
+
didWarnOnInvalidCallback.add(key2);
|
|
13485
13485
|
error("%s(...): Expected the last optional `callback` argument to be a function. Instead received: %s.", callerName, callback);
|
|
13486
13486
|
}
|
|
13487
13487
|
};
|
|
@@ -16893,15 +16893,15 @@ var require_react_dom_development = __commonJS({
|
|
|
16893
16893
|
}
|
|
16894
16894
|
}
|
|
16895
16895
|
}
|
|
16896
|
-
var
|
|
16896
|
+
var snapshot2 = instance.getSnapshotBeforeUpdate(finishedWork.elementType === finishedWork.type ? prevProps : resolveDefaultProps(finishedWork.type, prevProps), prevState);
|
|
16897
16897
|
{
|
|
16898
16898
|
var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate;
|
|
16899
|
-
if (
|
|
16899
|
+
if (snapshot2 === void 0 && !didWarnSet.has(finishedWork.type)) {
|
|
16900
16900
|
didWarnSet.add(finishedWork.type);
|
|
16901
16901
|
error("%s.getSnapshotBeforeUpdate(): A snapshot value (or null) must be returned. You have returned undefined.", getComponentNameFromFiber(finishedWork));
|
|
16902
16902
|
}
|
|
16903
16903
|
}
|
|
16904
|
-
instance.__reactInternalSnapshotBeforeUpdate =
|
|
16904
|
+
instance.__reactInternalSnapshotBeforeUpdate = snapshot2;
|
|
16905
16905
|
}
|
|
16906
16906
|
break;
|
|
16907
16907
|
}
|
|
@@ -20259,9 +20259,9 @@ var require_react_dom_development = __commonJS({
|
|
|
20259
20259
|
hasBadMapPolyfill = true;
|
|
20260
20260
|
}
|
|
20261
20261
|
}
|
|
20262
|
-
function FiberNode(tag, pendingProps,
|
|
20262
|
+
function FiberNode(tag, pendingProps, key2, mode) {
|
|
20263
20263
|
this.tag = tag;
|
|
20264
|
-
this.key =
|
|
20264
|
+
this.key = key2;
|
|
20265
20265
|
this.elementType = null;
|
|
20266
20266
|
this.type = null;
|
|
20267
20267
|
this.stateNode = null;
|
|
@@ -20302,8 +20302,8 @@ var require_react_dom_development = __commonJS({
|
|
|
20302
20302
|
}
|
|
20303
20303
|
}
|
|
20304
20304
|
}
|
|
20305
|
-
var createFiber = function(tag, pendingProps,
|
|
20306
|
-
return new FiberNode(tag, pendingProps,
|
|
20305
|
+
var createFiber = function(tag, pendingProps, key2, mode) {
|
|
20306
|
+
return new FiberNode(tag, pendingProps, key2, mode);
|
|
20307
20307
|
};
|
|
20308
20308
|
function shouldConstruct$1(Component) {
|
|
20309
20309
|
var prototype = Component.prototype;
|
|
@@ -20445,7 +20445,7 @@ var require_react_dom_development = __commonJS({
|
|
|
20445
20445
|
}
|
|
20446
20446
|
return createFiber(HostRoot, null, null, mode);
|
|
20447
20447
|
}
|
|
20448
|
-
function createFiberFromTypeAndProps(type,
|
|
20448
|
+
function createFiberFromTypeAndProps(type, key2, pendingProps, owner, mode, lanes) {
|
|
20449
20449
|
var fiberTag = IndeterminateComponent;
|
|
20450
20450
|
var resolvedType = type;
|
|
20451
20451
|
if (typeof type === "function") {
|
|
@@ -20464,7 +20464,7 @@ var require_react_dom_development = __commonJS({
|
|
|
20464
20464
|
} else {
|
|
20465
20465
|
getTag: switch (type) {
|
|
20466
20466
|
case REACT_FRAGMENT_TYPE:
|
|
20467
|
-
return createFiberFromFragment(pendingProps.children, mode, lanes,
|
|
20467
|
+
return createFiberFromFragment(pendingProps.children, mode, lanes, key2);
|
|
20468
20468
|
case REACT_STRICT_MODE_TYPE:
|
|
20469
20469
|
fiberTag = Mode;
|
|
20470
20470
|
mode |= StrictLegacyMode;
|
|
@@ -20473,13 +20473,13 @@ var require_react_dom_development = __commonJS({
|
|
|
20473
20473
|
}
|
|
20474
20474
|
break;
|
|
20475
20475
|
case REACT_PROFILER_TYPE:
|
|
20476
|
-
return createFiberFromProfiler(pendingProps, mode, lanes,
|
|
20476
|
+
return createFiberFromProfiler(pendingProps, mode, lanes, key2);
|
|
20477
20477
|
case REACT_SUSPENSE_TYPE:
|
|
20478
|
-
return createFiberFromSuspense(pendingProps, mode, lanes,
|
|
20478
|
+
return createFiberFromSuspense(pendingProps, mode, lanes, key2);
|
|
20479
20479
|
case REACT_SUSPENSE_LIST_TYPE:
|
|
20480
|
-
return createFiberFromSuspenseList(pendingProps, mode, lanes,
|
|
20480
|
+
return createFiberFromSuspenseList(pendingProps, mode, lanes, key2);
|
|
20481
20481
|
case REACT_OFFSCREEN_TYPE:
|
|
20482
|
-
return createFiberFromOffscreen(pendingProps, mode, lanes,
|
|
20482
|
+
return createFiberFromOffscreen(pendingProps, mode, lanes, key2);
|
|
20483
20483
|
case REACT_LEGACY_HIDDEN_TYPE:
|
|
20484
20484
|
// eslint-disable-next-line no-fallthrough
|
|
20485
20485
|
case REACT_SCOPE_TYPE:
|
|
@@ -20528,7 +20528,7 @@ var require_react_dom_development = __commonJS({
|
|
|
20528
20528
|
}
|
|
20529
20529
|
}
|
|
20530
20530
|
}
|
|
20531
|
-
var fiber = createFiber(fiberTag, pendingProps,
|
|
20531
|
+
var fiber = createFiber(fiberTag, pendingProps, key2, mode);
|
|
20532
20532
|
fiber.elementType = type;
|
|
20533
20533
|
fiber.type = resolvedType;
|
|
20534
20534
|
fiber.lanes = lanes;
|
|
@@ -20543,27 +20543,27 @@ var require_react_dom_development = __commonJS({
|
|
|
20543
20543
|
owner = element._owner;
|
|
20544
20544
|
}
|
|
20545
20545
|
var type = element.type;
|
|
20546
|
-
var
|
|
20546
|
+
var key2 = element.key;
|
|
20547
20547
|
var pendingProps = element.props;
|
|
20548
|
-
var fiber = createFiberFromTypeAndProps(type,
|
|
20548
|
+
var fiber = createFiberFromTypeAndProps(type, key2, pendingProps, owner, mode, lanes);
|
|
20549
20549
|
{
|
|
20550
20550
|
fiber._debugSource = element._source;
|
|
20551
20551
|
fiber._debugOwner = element._owner;
|
|
20552
20552
|
}
|
|
20553
20553
|
return fiber;
|
|
20554
20554
|
}
|
|
20555
|
-
function createFiberFromFragment(elements, mode, lanes,
|
|
20556
|
-
var fiber = createFiber(Fragment, elements,
|
|
20555
|
+
function createFiberFromFragment(elements, mode, lanes, key2) {
|
|
20556
|
+
var fiber = createFiber(Fragment, elements, key2, mode);
|
|
20557
20557
|
fiber.lanes = lanes;
|
|
20558
20558
|
return fiber;
|
|
20559
20559
|
}
|
|
20560
|
-
function createFiberFromProfiler(pendingProps, mode, lanes,
|
|
20560
|
+
function createFiberFromProfiler(pendingProps, mode, lanes, key2) {
|
|
20561
20561
|
{
|
|
20562
20562
|
if (typeof pendingProps.id !== "string") {
|
|
20563
20563
|
error('Profiler must specify an "id" of type `string` as a prop. Received the type `%s` instead.', typeof pendingProps.id);
|
|
20564
20564
|
}
|
|
20565
20565
|
}
|
|
20566
|
-
var fiber = createFiber(Profiler, pendingProps,
|
|
20566
|
+
var fiber = createFiber(Profiler, pendingProps, key2, mode | ProfileMode);
|
|
20567
20567
|
fiber.elementType = REACT_PROFILER_TYPE;
|
|
20568
20568
|
fiber.lanes = lanes;
|
|
20569
20569
|
{
|
|
@@ -20574,20 +20574,20 @@ var require_react_dom_development = __commonJS({
|
|
|
20574
20574
|
}
|
|
20575
20575
|
return fiber;
|
|
20576
20576
|
}
|
|
20577
|
-
function createFiberFromSuspense(pendingProps, mode, lanes,
|
|
20578
|
-
var fiber = createFiber(SuspenseComponent, pendingProps,
|
|
20577
|
+
function createFiberFromSuspense(pendingProps, mode, lanes, key2) {
|
|
20578
|
+
var fiber = createFiber(SuspenseComponent, pendingProps, key2, mode);
|
|
20579
20579
|
fiber.elementType = REACT_SUSPENSE_TYPE;
|
|
20580
20580
|
fiber.lanes = lanes;
|
|
20581
20581
|
return fiber;
|
|
20582
20582
|
}
|
|
20583
|
-
function createFiberFromSuspenseList(pendingProps, mode, lanes,
|
|
20584
|
-
var fiber = createFiber(SuspenseListComponent, pendingProps,
|
|
20583
|
+
function createFiberFromSuspenseList(pendingProps, mode, lanes, key2) {
|
|
20584
|
+
var fiber = createFiber(SuspenseListComponent, pendingProps, key2, mode);
|
|
20585
20585
|
fiber.elementType = REACT_SUSPENSE_LIST_TYPE;
|
|
20586
20586
|
fiber.lanes = lanes;
|
|
20587
20587
|
return fiber;
|
|
20588
20588
|
}
|
|
20589
|
-
function createFiberFromOffscreen(pendingProps, mode, lanes,
|
|
20590
|
-
var fiber = createFiber(OffscreenComponent, pendingProps,
|
|
20589
|
+
function createFiberFromOffscreen(pendingProps, mode, lanes, key2) {
|
|
20590
|
+
var fiber = createFiber(OffscreenComponent, pendingProps, key2, mode);
|
|
20591
20591
|
fiber.elementType = REACT_OFFSCREEN_TYPE;
|
|
20592
20592
|
fiber.lanes = lanes;
|
|
20593
20593
|
var primaryChildInstance = {
|
|
@@ -20731,14 +20731,14 @@ var require_react_dom_development = __commonJS({
|
|
|
20731
20731
|
}
|
|
20732
20732
|
var ReactVersion = "18.3.1";
|
|
20733
20733
|
function createPortal2(children, containerInfo, implementation) {
|
|
20734
|
-
var
|
|
20734
|
+
var key2 = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : null;
|
|
20735
20735
|
{
|
|
20736
|
-
checkKeyStringCoercion(
|
|
20736
|
+
checkKeyStringCoercion(key2);
|
|
20737
20737
|
}
|
|
20738
20738
|
return {
|
|
20739
20739
|
// This tag allow us to uniquely identify this as a React Portal
|
|
20740
20740
|
$$typeof: REACT_PORTAL_TYPE,
|
|
20741
|
-
key:
|
|
20741
|
+
key: key2 == null ? null : "" + key2,
|
|
20742
20742
|
children,
|
|
20743
20743
|
containerInfo,
|
|
20744
20744
|
implementation
|
|
@@ -20966,17 +20966,17 @@ var require_react_dom_development = __commonJS({
|
|
|
20966
20966
|
var setSuspenseHandler = null;
|
|
20967
20967
|
{
|
|
20968
20968
|
var copyWithDeleteImpl = function(obj, path, index2) {
|
|
20969
|
-
var
|
|
20969
|
+
var key2 = path[index2];
|
|
20970
20970
|
var updated = isArray(obj) ? obj.slice() : assign({}, obj);
|
|
20971
20971
|
if (index2 + 1 === path.length) {
|
|
20972
20972
|
if (isArray(updated)) {
|
|
20973
|
-
updated.splice(
|
|
20973
|
+
updated.splice(key2, 1);
|
|
20974
20974
|
} else {
|
|
20975
|
-
delete updated[
|
|
20975
|
+
delete updated[key2];
|
|
20976
20976
|
}
|
|
20977
20977
|
return updated;
|
|
20978
20978
|
}
|
|
20979
|
-
updated[
|
|
20979
|
+
updated[key2] = copyWithDeleteImpl(obj[key2], path, index2 + 1);
|
|
20980
20980
|
return updated;
|
|
20981
20981
|
};
|
|
20982
20982
|
var copyWithDelete = function(obj, path) {
|
|
@@ -21022,9 +21022,9 @@ var require_react_dom_development = __commonJS({
|
|
|
21022
21022
|
if (index2 >= path.length) {
|
|
21023
21023
|
return value;
|
|
21024
21024
|
}
|
|
21025
|
-
var
|
|
21025
|
+
var key2 = path[index2];
|
|
21026
21026
|
var updated = isArray(obj) ? obj.slice() : assign({}, obj);
|
|
21027
|
-
updated[
|
|
21027
|
+
updated[key2] = copyWithSetImpl(obj[key2], path, index2 + 1, value);
|
|
21028
21028
|
return updated;
|
|
21029
21029
|
};
|
|
21030
21030
|
var copyWithSet = function(obj, path, value) {
|
|
@@ -21583,11 +21583,11 @@ var require_react_dom_development = __commonJS({
|
|
|
21583
21583
|
setRestoreImplementation(restoreControlledState$3);
|
|
21584
21584
|
setBatchingImplementation(batchedUpdates$1, discreteUpdates, flushSync);
|
|
21585
21585
|
function createPortal$1(children, container) {
|
|
21586
|
-
var
|
|
21586
|
+
var key2 = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : null;
|
|
21587
21587
|
if (!isValidContainer(container)) {
|
|
21588
21588
|
throw new Error("Target container is not a DOM element.");
|
|
21589
21589
|
}
|
|
21590
|
-
return createPortal2(children, container, null,
|
|
21590
|
+
return createPortal2(children, container, null, key2);
|
|
21591
21591
|
}
|
|
21592
21592
|
function renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) {
|
|
21593
21593
|
return unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback);
|
|
@@ -21678,10 +21678,10 @@ __export(client_exports, {
|
|
|
21678
21678
|
inject: () => inject
|
|
21679
21679
|
});
|
|
21680
21680
|
module.exports = __toCommonJS(client_exports);
|
|
21681
|
-
var
|
|
21681
|
+
var import_react14 = __toESM(require("react"), 1);
|
|
21682
21682
|
|
|
21683
21683
|
// src/view.js
|
|
21684
|
-
var
|
|
21684
|
+
var import_react12 = __toESM(require("react"), 1);
|
|
21685
21685
|
|
|
21686
21686
|
// lib/presentation.js
|
|
21687
21687
|
var UI_ICONS = Object.freeze(["sparkles", "sliders", "layers", "chart", "gauge", "cpu", "database", "info", "check", "warning", "arrow", "target"]);
|
|
@@ -21770,11 +21770,14 @@ function formatNumber(value, decimals = 2) {
|
|
|
21770
21770
|
|
|
21771
21771
|
// lib/canvas-system.js
|
|
21772
21772
|
var CANVAS_SYSTEM_CSS = `
|
|
21773
|
-
:root{--canvas-radius:
|
|
21773
|
+
:root{--canvas-radius:20px;--canvas-gap:16px;--canvas-positive:#167456;--canvas-negative:#b13b3b;--canvas-warning:#875b15}
|
|
21774
21774
|
:root[data-canvas-scheme=dark]{--canvas-positive:#78d9b4;--canvas-negative:#ffaaaa;--canvas-warning:#edc87e}
|
|
21775
|
-
html,body{margin:0;min-width:0;background:var(--canvas-bg,#fff);color:var(--canvas-ink,#182537);font:14px/1.6 system-ui,"Microsoft YaHei",sans-serif}*{box-sizing:border-box}svg{max-width:100%;height:auto}button,input,select,textarea{font:inherit;color:inherit}button,input,select,textarea{border:1px solid var(--canvas-line,#ced4df);border-radius:8px;background:var(--canvas-bg,#fff);padding:8px 12px;max-width:100%}button{cursor:pointer}button:disabled{cursor:default;opacity:.55}input[type=range]{padding:0;accent-color:var(--canvas-accent,#3e60d3)}input[type=checkbox],input[type=radio]{accent-color:var(--canvas-accent,#3e60d3)}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--canvas-accent,#3e60d3);outline-offset:3px}
|
|
21775
|
+
#canvas{display:flow-root}html,body{margin:0;min-width:0;background:var(--canvas-bg,#fff);color:var(--canvas-ink,#182537);font:14px/1.6 system-ui,"Microsoft YaHei",sans-serif}*{box-sizing:border-box}svg{max-width:100%;height:auto}button,input,select,textarea{font:inherit;color:inherit}button,input,select,textarea{border:1px solid var(--canvas-line,#ced4df);border-radius:8px;background:var(--canvas-bg,#fff);padding:8px 12px;max-width:100%}button{cursor:pointer}button:disabled{cursor:default;opacity:.55}input[type=range]{padding:0;accent-color:var(--canvas-accent,#3e60d3)}input[type=checkbox],input[type=radio]{accent-color:var(--canvas-accent,#3e60d3)}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--canvas-accent,#3e60d3);outline-offset:3px}
|
|
21776
21776
|
.ui-stack{display:grid;gap:var(--canvas-gap)}.ui-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:var(--canvas-gap)}.ui-surface{padding:20px;border:1px solid var(--canvas-line,#ced4df);border-radius:var(--canvas-radius);background:var(--canvas-soft,#f3f5f8)}.ui-title{margin:0;font-size:clamp(20px,3vw,28px);line-height:1.3;letter-spacing:-.02em}.ui-caption{color:var(--canvas-muted,#526176);margin:8px 0;font-size:14px}.ui-value{font-size:clamp(24px,4vw,36px);font-variant-numeric:tabular-nums;line-height:1.2}.ui-controls{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.ui-field{display:grid;gap:6px;min-width:0}.ui-legend{display:flex;gap:16px;flex-wrap:wrap;font-size:13px}.ui-status{min-height:1.6em}.ui-error{color:var(--canvas-negative)}.ui-primary{background:var(--canvas-accent,#3e60d3);color:var(--canvas-accent-ink,#fff);border-color:transparent}
|
|
21777
21777
|
svg .ui-node{fill:var(--canvas-soft,#f3f5f8);stroke:var(--canvas-line,#ced4df);stroke-width:1}svg .ui-edge{fill:none;stroke:var(--canvas-muted,#526176);stroke-width:1.5}svg .ui-label{fill:var(--canvas-ink,#182537);font:500 14px system-ui,sans-serif}svg .ui-note{fill:var(--canvas-muted,#526176);font:400 13px system-ui,sans-serif}svg .ui-leader{fill:none;stroke:var(--canvas-muted,#526176);stroke-dasharray:3 4}svg .ui-accent{fill:color-mix(in srgb,var(--canvas-accent,#3e60d3) 12%,var(--canvas-bg,#fff));stroke:var(--canvas-accent,#3e60d3)}
|
|
21778
|
+
.ui-flow{display:flex;align-items:center;justify-content:center;gap:16px;padding:24px 8px;flex-wrap:wrap}.ui-step{display:grid;gap:6px;min-width:130px;max-width:240px;padding:16px 20px;border:1px solid var(--canvas-line);border-radius:6px;background:var(--canvas-bg)}.ui-step strong{font-size:16px;font-weight:600}.ui-step span{font-size:14px;color:var(--canvas-muted)}.ui-arrow{color:var(--canvas-muted);font-size:22px}.ui-callout{border-inline-start:3px solid var(--canvas-accent);padding:8px 16px;color:var(--canvas-ink)}
|
|
21779
|
+
.ui-surface,.ui-step{border-radius:var(--canvas-radius);background:linear-gradient(135deg,color-mix(in srgb,var(--canvas-accent,#3e60d3) 9%,var(--canvas-bg,#fff)),var(--canvas-soft,#f3f5f8))}button,input:not([type=checkbox]):not([type=radio]):not([type=range]),select,textarea{border-radius:14px}.ui-primary{background:linear-gradient(120deg,var(--canvas-accent,#3e60d3),color-mix(in srgb,var(--canvas-accent,#3e60d3) 85%,#152647))}.ui-callout{border-radius:14px;background:linear-gradient(120deg,color-mix(in srgb,var(--canvas-accent,#3e60d3) 7%,var(--canvas-bg,#fff)),var(--canvas-bg,#fff))}
|
|
21780
|
+
@media(max-width:480px){.ui-flow{flex-direction:column;padding:16px 8px;gap:12px}.ui-step{width:100%;max-width:none}.ui-arrow{transform:rotate(90deg)}}
|
|
21778
21781
|
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}}`;
|
|
21779
21782
|
|
|
21780
21783
|
// lib/sandbox.js
|
|
@@ -21838,13 +21841,13 @@ var COMPONENTS = Object.freeze({
|
|
|
21838
21841
|
badge: define(["text"], "Short explicit status label", "tone"),
|
|
21839
21842
|
progress: define(["label", "value", "max", "unit"], "Declared numeric progress snapshot", "tone"),
|
|
21840
21843
|
steps: define(["items"], "Ordered declared steps"),
|
|
21841
|
-
metric: define(["label", "value", "unit", "decimals"], "
|
|
21844
|
+
metric: define(["label", "value", "unit", "decimals"], "Number with units, or a literal/bound status string", "tone"),
|
|
21842
21845
|
input: define(["label", "bind"], "String or numeric state input"),
|
|
21843
21846
|
slider: define(["label", "bind"], "Numeric state control"),
|
|
21844
21847
|
select: define(["label", "bind"], "Selection from declared state options"),
|
|
21845
21848
|
toggle: define(["label", "bind"], "Boolean state control"),
|
|
21846
21849
|
button: define(["text", "action"], "Declared Agent follow-up", "icon"),
|
|
21847
|
-
table: define(["rows", "columns"], "
|
|
21850
|
+
table: define(["label", "rows", "columns"], "Supplied or derived values; inline rows or data/derived reference"),
|
|
21848
21851
|
chart: define(["kind", "rows", "labelKey", "valueKey", "label", "unit", "xScale"], "Bar/line comparison with accessible data"),
|
|
21849
21852
|
sandbox: define(["title", "html", "css", "script", "fallback", "height", "stateKeys", "dataKeys", "derivedKeys"], "Freeform isolated HTML/SVG/CSS/JavaScript visualization")
|
|
21850
21853
|
});
|
|
@@ -21853,6 +21856,11 @@ function componentFields(type) {
|
|
|
21853
21856
|
return c && ["id", "type", ...c.fields, ...c.presentation ? ["icon"] : [], ...c.presentation === "tone" ? ["tone"] : []];
|
|
21854
21857
|
}
|
|
21855
21858
|
|
|
21859
|
+
// lib/identifiers.js
|
|
21860
|
+
var IDENTIFIER_SOURCE = "[\\p{L}_][\\p{L}\\p{M}\\p{N}_]{0,63}";
|
|
21861
|
+
var pattern = new RegExp(`^${IDENTIFIER_SOURCE}$`, "u");
|
|
21862
|
+
var validIdentifier = (value) => typeof value === "string" && pattern.test(value) && !["constructor", "prototype", "__proto__"].includes(value);
|
|
21863
|
+
|
|
21856
21864
|
// lib/author-expression.js
|
|
21857
21865
|
function compileExpression(source) {
|
|
21858
21866
|
const fail2 = () => {
|
|
@@ -21861,7 +21869,7 @@ function compileExpression(source) {
|
|
|
21861
21869
|
if (typeof source !== "string" || !source.trim() || source.length > 2048) fail2();
|
|
21862
21870
|
const tokens = [];
|
|
21863
21871
|
let offset = 0;
|
|
21864
|
-
const token =
|
|
21872
|
+
const token = new RegExp(String.raw`\s*(?:(\d+(?:\.\d*)?|\.\d+)([eE][+-]?\d+)?|("(?:[^"\\]|\\.)*")|(${IDENTIFIER_SOURCE}(?:\.${IDENTIFIER_SOURCE})?)|(===|!==|<=|>=|==|!=|[+*/()?,:<>-]))`, "uy");
|
|
21865
21873
|
while (offset < source.length) {
|
|
21866
21874
|
if (!source.slice(offset).trim()) break;
|
|
21867
21875
|
token.lastIndex = offset;
|
|
@@ -21888,7 +21896,7 @@ function compileExpression(source) {
|
|
|
21888
21896
|
} else if (t === "-" || t === "+") {
|
|
21889
21897
|
const arg = parse(5, depth + 1);
|
|
21890
21898
|
out = t === "-" ? { op: "sub", args: [{ const: 0 }, arg] } : arg;
|
|
21891
|
-
} else if (typeof t === "string" &&
|
|
21899
|
+
} else if (typeof t === "string" && t.split(".").length === 2 && ["state", "data", "derived", "item"].includes(t.split(".")[0]) && validIdentifier(t.split(".")[1])) out = { ref: t };
|
|
21892
21900
|
else if (["min", "max", "round", "abs"].includes(t)) {
|
|
21893
21901
|
take("(");
|
|
21894
21902
|
const args = [parse(0, depth + 1)];
|
|
@@ -21947,7 +21955,6 @@ var fail = (message) => {
|
|
|
21947
21955
|
throw new Error(`DSH UI: ${message}`);
|
|
21948
21956
|
};
|
|
21949
21957
|
var object = (x) => x !== null && typeof x === "object" && !Array.isArray(x);
|
|
21950
|
-
var key = (x) => typeof x === "string" && /^[a-zA-Z][a-zA-Z0-9_]{0,63}$/.test(x) && !["constructor", "prototype", "__proto__"].includes(x);
|
|
21951
21958
|
var finite = (x) => typeof x === "number" && Number.isFinite(x);
|
|
21952
21959
|
var scalar = (x) => typeof x === "string" || typeof x === "boolean" || finite(x);
|
|
21953
21960
|
var text = (x, at) => {
|
|
@@ -21994,6 +22001,10 @@ function validateState(doc, state) {
|
|
|
21994
22001
|
if (!finite(v) || v < s.min || v > s.max) fail(`state.${k} is outside its numeric range`);
|
|
21995
22002
|
const offset = (v - s.min) / s.step;
|
|
21996
22003
|
if (Math.abs(offset - Math.round(offset)) > 1e-6) fail(`state.${k} does not match its step`);
|
|
22004
|
+
} else if (s.type === "json") {
|
|
22005
|
+
if (!object(v) && !Array.isArray(v)) fail(`state.${k} must be an array or object for type json`);
|
|
22006
|
+
safeJson(v);
|
|
22007
|
+
if (new TextEncoder().encode(JSON.stringify(v)).length > 16384) fail(`state.${k} JSON exceeds 16 KiB`);
|
|
21997
22008
|
} else if (s.type === "string") text(v, `state.${k}`);
|
|
21998
22009
|
else if (typeof v !== "boolean") fail(`state.${k} must be boolean`);
|
|
21999
22010
|
if (s.options && !s.options.includes(v)) fail(`invalid option for state.${k}`);
|
|
@@ -22003,7 +22014,7 @@ function validateState(doc, state) {
|
|
|
22003
22014
|
}
|
|
22004
22015
|
var ARITY = { add: [1, 8], sub: [2, 2], mul: [1, 8], div: [2, 2], min: [1, 8], max: [1, 8], round: [1, 1], abs: [1, 1], eq: [2, 2], neq: [2, 2], lt: [2, 2], lte: [2, 2], gt: [2, 2], gte: [2, 2], if: [3, 3] };
|
|
22005
22016
|
function reference(doc, ref) {
|
|
22006
|
-
if (typeof ref !== "string" ||
|
|
22017
|
+
if (typeof ref !== "string" || !["state", "data", "derived"].includes(ref.split(".")[0]) || ref.split(".").length !== 2 || !validIdentifier(ref.split(".")[1])) fail(`invalid reference ${JSON.stringify(ref)}; use state.key, data.key or derived.key with a letter/underscore identifier`);
|
|
22007
22018
|
const [group, k] = ref.split(".");
|
|
22008
22019
|
if (!own(doc[group], k)) fail(`unknown reference ${ref}`);
|
|
22009
22020
|
return [group, k];
|
|
@@ -22114,7 +22125,7 @@ function checkViewValues(doc, evaluated) {
|
|
|
22114
22125
|
if (n.type === "chart" && rows.some((r) => !own(r, n.labelKey) || !scalar(r[n.labelKey]) || !own(r, n.valueKey) || !finite(r[n.valueKey]))) fail("chart requires labels and finite numeric values");
|
|
22115
22126
|
if (n.type === "chart" && n.xScale === "linear" && rows.some((r) => !finite(r[n.labelKey]))) fail("linear chart requires numeric x values");
|
|
22116
22127
|
}
|
|
22117
|
-
if (n.type === "metric" && !
|
|
22128
|
+
if (n.type === "metric" && !scalar(evaluated.resolveValue(n.value))) fail(`node.${n.id}.value must resolve to a number, string or boolean; use table for rows or a canvas for structured data`);
|
|
22118
22129
|
if (n.type === "progress") {
|
|
22119
22130
|
const v = evaluated.resolveValue(n.value), max = evaluated.resolveValue(n.max);
|
|
22120
22131
|
if (!finite(v) || !finite(max) || max <= 0 || v < 0 || v > max) fail("progress requires 0 <= value <= positive max");
|
|
@@ -22142,11 +22153,13 @@ function validateDocument(input) {
|
|
|
22142
22153
|
for (const group of ["state", "data", "derived", "actions"]) {
|
|
22143
22154
|
doc[group] ??= {};
|
|
22144
22155
|
if (!object(doc[group]) || Object.keys(doc[group]).length > 64) fail(`invalid ${group}`);
|
|
22145
|
-
for (const k of Object.keys(doc[group])) if (!
|
|
22156
|
+
for (const k of Object.keys(doc[group])) if (!validIdentifier(k)) fail(`invalid key in ${group}: ${JSON.stringify(k)}; use 1..64 letters, numbers or underscores, starting with a letter/underscore (Chinese letters supported); no spaces, dots or hyphens. Put display labels in label/text`);
|
|
22146
22157
|
}
|
|
22147
22158
|
for (const [k, s] of Object.entries(doc.state)) {
|
|
22148
22159
|
fields(s, ["type", "default", "min", "max", "step", "options"], `state.${k}`);
|
|
22149
|
-
if (
|
|
22160
|
+
if (s.type === "string" && (Array.isArray(s.default) || object(s.default)) && !own(s, "options")) s.type = "json";
|
|
22161
|
+
if (!["number", "string", "boolean", "json"].includes(s.type)) fail(`unsupported state type ${k}; use number, string, boolean or json (arrays/objects)`);
|
|
22162
|
+
if (s.type === "json" && own(s, "options")) fail(`state.${k}: json state does not support select options; use scalar options or a canvas`);
|
|
22150
22163
|
if (s.type === "number") {
|
|
22151
22164
|
if (![s.min, s.max, s.step].every(finite) || s.min >= s.max || s.step <= 0) fail(`invalid numeric limits for ${k}`);
|
|
22152
22165
|
if ((s.max - s.min) / s.step > 1e9) fail(`numeric step too small for ${k}`);
|
|
@@ -22169,7 +22182,7 @@ function validateDocument(input) {
|
|
|
22169
22182
|
if (!Array.isArray(rows) || rows.length > LIMITS.rows || !rows.every(object)) fail("map source must be object rows");
|
|
22170
22183
|
if (!object(e.map.fields) || !Object.keys(e.map.fields).length || Object.keys(e.map.fields).length > 16) fail("map requires 1..16 fields");
|
|
22171
22184
|
for (const [k2, value2] of Object.entries(e.map.fields)) {
|
|
22172
|
-
if (!
|
|
22185
|
+
if (!validIdentifier(k2)) fail(`invalid map field ${JSON.stringify(k2).slice(0, 100)}; use a letter/underscore identifier such as powerW or \u529F\u7387, without spaces, dots or hyphens`);
|
|
22173
22186
|
validateExpression(value2, depth + 1, rows);
|
|
22174
22187
|
}
|
|
22175
22188
|
return;
|
|
@@ -22183,7 +22196,7 @@ function validateDocument(input) {
|
|
|
22183
22196
|
fields(e, ["ref"], "expression");
|
|
22184
22197
|
if (typeof e.ref === "string" && e.ref.startsWith("item.")) {
|
|
22185
22198
|
const k = e.ref.slice(5);
|
|
22186
|
-
if (!itemRows || !
|
|
22199
|
+
if (!itemRows || !validIdentifier(k) || itemRows.some((row) => !own(row, k) || !scalar(row[k]))) fail("invalid or unscoped item reference");
|
|
22187
22200
|
} else reference(doc, e.ref);
|
|
22188
22201
|
return;
|
|
22189
22202
|
}
|
|
@@ -22226,9 +22239,10 @@ function validateDocument(input) {
|
|
|
22226
22239
|
if (!Array.isArray(list) || depth > LIMITS.depth) fail("invalid node children or depth");
|
|
22227
22240
|
for (const n of list) {
|
|
22228
22241
|
if (++count > LIMITS.nodes) fail("too many nodes");
|
|
22229
|
-
if (!object(n) || !
|
|
22242
|
+
if (!object(n) || !validIdentifier(n.id) || ids.has(n.id)) fail("node ids must be unique identifiers");
|
|
22230
22243
|
ids.add(n.id);
|
|
22231
22244
|
if (!Object.hasOwn(COMPONENTS, n.type)) fail("unsupported component " + n.type);
|
|
22245
|
+
if (["table", "chart"].includes(n.type) && typeof n.rows === "string" && /^(data|derived)\./.test(n.rows)) n.rows = { ref: n.rows };
|
|
22232
22246
|
switch (n.type) {
|
|
22233
22247
|
case "sandbox": {
|
|
22234
22248
|
text(n.title, "canvas title");
|
|
@@ -22288,6 +22302,7 @@ function validateDocument(input) {
|
|
|
22288
22302
|
const [, k] = reference(doc, n.bind), spec = doc.state[k];
|
|
22289
22303
|
if (n.type === "slider" && spec.type !== "number") fail("slider requires numeric state");
|
|
22290
22304
|
if (n.type === "toggle" && spec.type !== "boolean") fail("toggle requires boolean state");
|
|
22305
|
+
if (["input", "select"].includes(n.type) && spec.type === "json") fail(`node.${n.id}: structured state requires a sandbox with DSHUI.setState; use separate boolean states and toggle nodes for a native checklist`);
|
|
22291
22306
|
if (n.type === "input" && spec.type === "boolean") fail("use toggle for boolean state");
|
|
22292
22307
|
if (n.type === "select" && !spec.options) fail("select requires options");
|
|
22293
22308
|
break;
|
|
@@ -22297,12 +22312,13 @@ function validateDocument(input) {
|
|
|
22297
22312
|
if (!own(doc.actions, n.action)) fail("unknown action");
|
|
22298
22313
|
break;
|
|
22299
22314
|
case "table": {
|
|
22300
|
-
|
|
22315
|
+
if (n.label !== void 0) text(n.label, "table label");
|
|
22316
|
+
if (!Array.isArray(n.rows)) value(n.rows, "table rows");
|
|
22301
22317
|
if (!Array.isArray(n.columns) || !n.columns.length || n.columns.length > 16) fail("invalid table columns");
|
|
22302
22318
|
const cols = /* @__PURE__ */ new Set();
|
|
22303
22319
|
for (const c of n.columns) {
|
|
22304
22320
|
fields(c, ["key", "label", "unit"], "column");
|
|
22305
|
-
if (!
|
|
22321
|
+
if (!validIdentifier(c.key) || cols.has(c.key)) fail("invalid or duplicate column key");
|
|
22306
22322
|
cols.add(c.key);
|
|
22307
22323
|
text(c.label, "column label");
|
|
22308
22324
|
if (c.unit !== void 0) text(c.unit, "column unit");
|
|
@@ -22310,8 +22326,8 @@ function validateDocument(input) {
|
|
|
22310
22326
|
break;
|
|
22311
22327
|
}
|
|
22312
22328
|
case "chart":
|
|
22313
|
-
value(n.rows, "chart rows");
|
|
22314
|
-
if (!["bar", "line"].includes(n.kind) || !
|
|
22329
|
+
if (!Array.isArray(n.rows)) value(n.rows, "chart rows");
|
|
22330
|
+
if (!["bar", "line"].includes(n.kind) || !validIdentifier(n.labelKey) || !validIdentifier(n.valueKey)) fail("invalid chart");
|
|
22315
22331
|
text(n.label, "chart label");
|
|
22316
22332
|
if (n.unit !== void 0) text(n.unit, "chart unit");
|
|
22317
22333
|
if (n.xScale !== void 0 && (!["category", "linear"].includes(n.xScale) || n.xScale === "linear" && n.kind !== "line")) fail("invalid xScale");
|
|
@@ -22375,9 +22391,9 @@ var import_react2 = require("react");
|
|
|
22375
22391
|
|
|
22376
22392
|
// src/state-channel.js
|
|
22377
22393
|
var listeners = /* @__PURE__ */ new Map();
|
|
22378
|
-
var
|
|
22394
|
+
var key = (id, sessionId) => id + "\0" + sessionId;
|
|
22379
22395
|
function subscribeState(id, sessionId, fn) {
|
|
22380
|
-
const k =
|
|
22396
|
+
const k = key(id, sessionId), set = listeners.get(k) ?? /* @__PURE__ */ new Set();
|
|
22381
22397
|
listeners.set(k, set);
|
|
22382
22398
|
set.add(fn);
|
|
22383
22399
|
return () => {
|
|
@@ -22386,7 +22402,7 @@ function subscribeState(id, sessionId, fn) {
|
|
|
22386
22402
|
};
|
|
22387
22403
|
}
|
|
22388
22404
|
function broadcastState(id, sessionId, saved, origin) {
|
|
22389
|
-
for (const fn of listeners.get(
|
|
22405
|
+
for (const fn of listeners.get(key(id, sessionId)) ?? []) if (fn !== origin) fn(saved);
|
|
22390
22406
|
}
|
|
22391
22407
|
|
|
22392
22408
|
// src/saved-state.js
|
|
@@ -22495,10 +22511,10 @@ function useSavedState(record, sessionId, preview = false) {
|
|
|
22495
22511
|
const timer = setTimeout(async () => {
|
|
22496
22512
|
r.saving = true;
|
|
22497
22513
|
if (r.alive) setStatus("\u6B63\u5728\u4FDD\u5B58\u53C2\u6570\u2026");
|
|
22498
|
-
const
|
|
22514
|
+
const revision2 = r.revision;
|
|
22499
22515
|
try {
|
|
22500
|
-
const saved = checked(await request(STATE_URL, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ documentId: record.documentId, sessionId, revision, state }) }));
|
|
22501
|
-
if (saved.revision !==
|
|
22516
|
+
const saved = checked(await request(STATE_URL, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ documentId: record.documentId, sessionId, revision: revision2, state }) }));
|
|
22517
|
+
if (saved.revision !== revision2 + 1 || JSON.stringify(saved.state) !== signature) throw new Error("Unexpected save response");
|
|
22502
22518
|
r.revision = saved.revision;
|
|
22503
22519
|
r.saved = signature;
|
|
22504
22520
|
broadcastState(record.documentId, sessionId, saved, receive.current);
|
|
@@ -22535,6 +22551,40 @@ function useSavedState(record, sessionId, preview = false) {
|
|
|
22535
22551
|
return { state: preview ? initialState(doc) : state, setState, ready: !preview && ready, status: preview ? "\u751F\u6210\u9884\u89C8 \xB7 \u5B8C\u6210\u6821\u9A8C\u540E\u53EF\u64CD\u4F5C" : status, issue, epoch, retry, useRemote: () => load(), keepLocal: () => load(true) };
|
|
22536
22552
|
}
|
|
22537
22553
|
|
|
22554
|
+
// lib/tool-json.js
|
|
22555
|
+
function clean(source) {
|
|
22556
|
+
let input = source.trim().replace(/^\uFEFF/, "");
|
|
22557
|
+
const fence = input.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/i);
|
|
22558
|
+
if (fence) input = fence[1];
|
|
22559
|
+
let output = "", quoted = false, escaped = false;
|
|
22560
|
+
for (let i = 0; i < input.length; i++) {
|
|
22561
|
+
const c = input[i];
|
|
22562
|
+
if (quoted) {
|
|
22563
|
+
output += c;
|
|
22564
|
+
if (escaped) escaped = false;
|
|
22565
|
+
else if (c === "\\") escaped = true;
|
|
22566
|
+
else if (c === '"') quoted = false;
|
|
22567
|
+
continue;
|
|
22568
|
+
}
|
|
22569
|
+
if (c === '"') quoted = true;
|
|
22570
|
+
if (c === "," && /^\s*[}\]]/.test(input.slice(i + 1))) continue;
|
|
22571
|
+
output += c;
|
|
22572
|
+
}
|
|
22573
|
+
return output;
|
|
22574
|
+
}
|
|
22575
|
+
function toolJson(value, field, maxBytes = 131072) {
|
|
22576
|
+
if (typeof value !== "string") return value;
|
|
22577
|
+
if (new TextEncoder().encode(value).length > maxBytes) throw new Error(`DSH UI: ${field} JSON exceeds size limit`);
|
|
22578
|
+
const source = clean(value);
|
|
22579
|
+
try {
|
|
22580
|
+
return JSON.parse(source);
|
|
22581
|
+
} catch (error) {
|
|
22582
|
+
const position = error.message.match(/position (\d+)/)?.[1];
|
|
22583
|
+
const location = position === void 0 ? "" : ` at line ${source.slice(0, Number(position)).split("\n").length}, column ${Number(position) - source.lastIndexOf("\n", Number(position) - 1)}`;
|
|
22584
|
+
throw new Error(`DSH UI: ${field} must contain valid JSON${location}. Pass an object directly, not a manually escaped JSON string. Do not use single-quoted keys or raw newlines inside strings. For HTML/SVG use render_canvas with separate html/css/script fields. No partial document was saved.`);
|
|
22585
|
+
}
|
|
22586
|
+
}
|
|
22587
|
+
|
|
22538
22588
|
// lib/stream.js
|
|
22539
22589
|
function parseToolArguments(raw) {
|
|
22540
22590
|
if (typeof raw !== "string" || raw.length > LIMITS.bytes || new TextEncoder().encode(raw).length > LIMITS.bytes) return null;
|
|
@@ -22626,7 +22676,7 @@ function previewDocument(raw) {
|
|
|
22626
22676
|
const root = parseToolArguments(raw);
|
|
22627
22677
|
if (!root) return null;
|
|
22628
22678
|
const document2 = root.members?.get("document");
|
|
22629
|
-
if (document2?.complete && typeof document2.value === "string" && root.members.size === 1) return validateDocument(
|
|
22679
|
+
if (document2?.complete && typeof document2.value === "string" && root.members.size === 1) return validateDocument(toolJson(document2.value, "document"));
|
|
22630
22680
|
if (!document2?.members) return null;
|
|
22631
22681
|
if ([...root.members.keys()].some((k) => k !== "document")) return null;
|
|
22632
22682
|
const doc = { ...document2.value }, nodes = document2.members.get("nodes");
|
|
@@ -22695,12 +22745,13 @@ function updatePreview(html) {
|
|
|
22695
22745
|
morph(document.getElementById("canvas"), template.content);
|
|
22696
22746
|
}
|
|
22697
22747
|
function previewFrameDocument(channel, nonce) {
|
|
22698
|
-
return `<!doctype html><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none';script-src 'nonce-${nonce}';style-src 'unsafe-inline';img-src data:;base-uri 'none';form-action 'none';frame-src 'none'"><style>${CANVAS_SYSTEM_CSS}</style><style id="custom"></style><style>#canvas,#canvas *,#canvas *::before,#canvas *::after{animation:none!important;transition:none!important}html,body{overflow:hidden}</style><main id="canvas" inert></main><script nonce="${nonce}">const update=${updatePreview.toString()};addEventListener('message',e=>{if(e.source!==parent||e.data?.channel!==${JSON.stringify(channel)})return;document.getElementById('custom').textContent=e.data.css;for(const [k,v] of Object.entries(e.data.theme||{}))document.documentElement.style.setProperty('--canvas-'+k,v);document.documentElement.dataset.canvasScheme=e.data.theme?.scheme||'light';update(e.data.html)});<\/script>`;
|
|
22748
|
+
return `<!doctype html><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none';script-src 'nonce-${nonce}';style-src 'unsafe-inline';img-src data:;base-uri 'none';form-action 'none';frame-src 'none'"><style>${CANVAS_SYSTEM_CSS}</style><style id="custom"></style><style>#canvas,#canvas *,#canvas *::before,#canvas *::after{animation:none!important;transition:none!important}html,body{overflow:hidden}</style><main id="canvas" inert></main><script nonce="${nonce}">const update=${updatePreview.toString()};addEventListener('message',e=>{if(e.source!==parent||e.data?.channel!==${JSON.stringify(channel)})return;document.getElementById('custom').textContent=e.data.css;for(const [k,v] of Object.entries(e.data.theme||{}))document.documentElement.style.setProperty('--canvas-'+k,v);document.documentElement.dataset.canvasScheme=e.data.theme?.scheme||'light';update(e.data.html)});new ResizeObserver(()=>parent.postMessage({channel:${JSON.stringify(channel)},previewHeight:Math.ceil(document.getElementById('canvas').getBoundingClientRect().height)},'*')).observe(document.getElementById('canvas'));<\/script>`;
|
|
22699
22749
|
}
|
|
22700
22750
|
|
|
22701
22751
|
// src/canvas-preview.js
|
|
22702
22752
|
var h2 = import_react3.default.createElement;
|
|
22703
22753
|
function CanvasPreview({ node }) {
|
|
22754
|
+
const [height, setHeight] = (0, import_react3.useState)(node.height ?? 420);
|
|
22704
22755
|
const frame = (0, import_react3.useRef)(null), latest = (0, import_react3.useRef)(node);
|
|
22705
22756
|
latest.current = node;
|
|
22706
22757
|
const config = (0, import_react3.useMemo)(() => {
|
|
@@ -22725,14 +22776,22 @@ function CanvasPreview({ node }) {
|
|
|
22725
22776
|
observer.observe(document.body, { attributes: true });
|
|
22726
22777
|
return () => observer.disconnect();
|
|
22727
22778
|
}, []);
|
|
22728
|
-
|
|
22779
|
+
(0, import_react3.useEffect)(() => {
|
|
22780
|
+
const receive = (event) => {
|
|
22781
|
+
const m = event.data;
|
|
22782
|
+
if (event.source === frame.current?.contentWindow && m?.channel === config.channel && Number.isFinite(m.previewHeight) && m.previewHeight >= 0) setHeight(Math.max(32, Math.min(1e3, Math.ceil(m.previewHeight))));
|
|
22783
|
+
};
|
|
22784
|
+
window.addEventListener("message", receive);
|
|
22785
|
+
return () => window.removeEventListener("message", receive);
|
|
22786
|
+
}, [config]);
|
|
22787
|
+
return h2("section", { className: "dgui-canvas", "data-canvas-phase": "preview", "aria-label": node.title }, h2("p", { className: "dgui-copy", role: "status" }, "\u9759\u6001\u9884\u89C8 \xB7 \u63D0\u4EA4\u6210\u529F\u540E\u542F\u7528\u4EA4\u4E92"), h2("iframe", { ref: frame, title: node.title + "\uFF08\u9759\u6001\u9884\u89C8\uFF09", sandbox: "allow-scripts", referrerPolicy: "no-referrer", srcDoc, onLoad: publish, style: { display: "block", width: "100%", height, border: 0, pointerEvents: "none" } }));
|
|
22729
22788
|
}
|
|
22730
22789
|
|
|
22731
22790
|
// src/sandbox.js
|
|
22732
|
-
var
|
|
22791
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
22733
22792
|
|
|
22734
22793
|
// lib/export-runtime-bundle.js
|
|
22735
|
-
var EXPORT_RUNTIME = '(() => {\n // lib/presentation.js\n var UI_ICONS = Object.freeze(["sparkles", "sliders", "layers", "chart", "gauge", "cpu", "database", "info", "check", "warning", "arrow", "target"]);\n var UI_TONES = Object.freeze(["neutral", "accent", "success", "warning", "danger"]);\n var UI_LAYOUTS = Object.freeze(["dashboard", "workbench", "comparison", "guide", "status", "report"]);\n var UI_ACCENTS = Object.freeze(["blue", "teal", "violet", "amber", "rose"]);\n var UI_SURFACES = Object.freeze(["outline", "soft", "featured"]);\n\n // lib/visual-audit.js\n function measureVisual(root, nodeId = "") {\n const issues = [], seen = /* @__PURE__ */ new Set(), coverage = { nodeId, elements: 0, truncated: false, contrastChecked: 0, contrastUncovered: 0 };\n const add = (code, value, el2) => {\n const id = el2?.closest("[data-ui-node]")?.getAttribute("data-ui-node") ?? nodeId;\n const k = id + ":" + code + ":" + Math.round(value ?? 0);\n if (!seen.has(k) && issues.length < 40) {\n seen.add(k);\n issues.push({ code, nodeId: id, ...value === void 0 ? {} : { value: Number(value.toFixed(2)) } });\n }\n };\n const color = (s) => {\n let m = s.match(/^rgba?\\(([^)]+)\\)/);\n if (m) {\n const a = m[1].split(/[\\s,\\/]+/).map(Number);\n return [a[0] / 255, a[1] / 255, a[2] / 255, a[3] ?? 1];\n }\n m = s.match(/^color\\(srgb ([^)]+)\\)/);\n if (m) {\n const a = m[1].split(/[\\s\\/]+/).map(Number);\n return [a[0], a[1], a[2], a[3] ?? 1];\n }\n return null;\n };\n const luminance = (c) => c.slice(0, 3).map((v) => v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4).reduce((s, v, i) => s + v * [0.2126, 0.7152, 0.0722][i], 0);\n const widthRoot = root.id === "canvas" ? document.documentElement : root;\n if (widthRoot.scrollWidth > widthRoot.clientWidth + 2) add("overflow", widthRoot.scrollWidth - widthRoot.clientWidth);\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);\n let el;\n while (el = walker.nextNode()) {\n if (coverage.elements >= 2e3) {\n coverage.truncated = true;\n break;\n }\n coverage.elements++;\n if (el.matches("[data-canvas-phase=error]")) add("runtimeError", void 0, el);\n const css = getComputedStyle(el), box = el.getBoundingClientRect();\n if (!box.width || !box.height || css.visibility === "hidden" || css.display === "none") continue;\n const text2 = [...el.childNodes].some((n) => n.nodeType === 3 && n.textContent.trim());\n if (text2) {\n let size = parseFloat(css.fontSize);\n if (el instanceof SVGElement && el.getScreenCTM) {\n const m = el.getScreenCTM();\n if (m) size *= Math.hypot(m.c, m.d);\n }\n if (size < 11.9) add("smallText", size, el);\n const fg = color(css.color);\n let ancestor = el, bg = null, depth = 0;\n while (ancestor && depth++ < 64) {\n const style = getComputedStyle(ancestor);\n if (style.backgroundImage !== "none") break;\n const c = color(style.backgroundColor);\n if (c?.[3] === 1) {\n bg = c;\n break;\n }\n if (c?.[3] > 0) break;\n ancestor = ancestor.parentElement;\n }\n if (!(el instanceof SVGElement) && fg?.[3] === 1 && bg) {\n coverage.contrastChecked++;\n const a = luminance(fg), b = luminance(bg), ratio = (Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05);\n if (ratio < (size >= 24 || size >= 18.66 && parseFloat(css.fontWeight) >= 700 ? 3 : 4.5)) add("contrast", ratio, el);\n } else coverage.contrastUncovered++;\n }\n if (el.matches("input:not([type=hidden]),select,textarea,button,[role=button]") && !el.getAttribute("aria-label") && !el.getAttribute("aria-labelledby") && !el.labels?.length && !el.textContent.trim() && !el.getAttribute("title")) add("missingLabel", void 0, el);\n }\n Object.defineProperty(issues, "coverage", { value: coverage });\n return issues;\n }\n\n // lib/format-number.js\n function formatNumber(value, decimals = 2) {\n if (typeof value !== "number" || !Number.isFinite(value)) throw new Error("DSH UI: formatNumber requires a finite number");\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 6) throw new Error("DSH UI: formatNumber decimals must be an integer from 0 to 6");\n return value.toLocaleString("en-US", { minimumFractionDigits: decimals, maximumFractionDigits: decimals });\n }\n\n // lib/canvas-system.js\n var CANVAS_SYSTEM_CSS = `\n:root{--canvas-radius:12px;--canvas-gap:16px;--canvas-positive:#167456;--canvas-negative:#b13b3b;--canvas-warning:#875b15}\n:root[data-canvas-scheme=dark]{--canvas-positive:#78d9b4;--canvas-negative:#ffaaaa;--canvas-warning:#edc87e}\nhtml,body{margin:0;min-width:0;background:var(--canvas-bg,#fff);color:var(--canvas-ink,#182537);font:14px/1.6 system-ui,"Microsoft YaHei",sans-serif}*{box-sizing:border-box}svg{max-width:100%;height:auto}button,input,select,textarea{font:inherit;color:inherit}button,input,select,textarea{border:1px solid var(--canvas-line,#ced4df);border-radius:8px;background:var(--canvas-bg,#fff);padding:8px 12px;max-width:100%}button{cursor:pointer}button:disabled{cursor:default;opacity:.55}input[type=range]{padding:0;accent-color:var(--canvas-accent,#3e60d3)}input[type=checkbox],input[type=radio]{accent-color:var(--canvas-accent,#3e60d3)}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--canvas-accent,#3e60d3);outline-offset:3px}\n.ui-stack{display:grid;gap:var(--canvas-gap)}.ui-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:var(--canvas-gap)}.ui-surface{padding:20px;border:1px solid var(--canvas-line,#ced4df);border-radius:var(--canvas-radius);background:var(--canvas-soft,#f3f5f8)}.ui-title{margin:0;font-size:clamp(20px,3vw,28px);line-height:1.3;letter-spacing:-.02em}.ui-caption{color:var(--canvas-muted,#526176);margin:8px 0;font-size:14px}.ui-value{font-size:clamp(24px,4vw,36px);font-variant-numeric:tabular-nums;line-height:1.2}.ui-controls{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.ui-field{display:grid;gap:6px;min-width:0}.ui-legend{display:flex;gap:16px;flex-wrap:wrap;font-size:13px}.ui-status{min-height:1.6em}.ui-error{color:var(--canvas-negative)}.ui-primary{background:var(--canvas-accent,#3e60d3);color:var(--canvas-accent-ink,#fff);border-color:transparent}\nsvg .ui-node{fill:var(--canvas-soft,#f3f5f8);stroke:var(--canvas-line,#ced4df);stroke-width:1}svg .ui-edge{fill:none;stroke:var(--canvas-muted,#526176);stroke-width:1.5}svg .ui-label{fill:var(--canvas-ink,#182537);font:500 14px system-ui,sans-serif}svg .ui-note{fill:var(--canvas-muted,#526176);font:400 13px system-ui,sans-serif}svg .ui-leader{fill:none;stroke:var(--canvas-muted,#526176);stroke-dasharray:3 4}svg .ui-accent{fill:color-mix(in srgb,var(--canvas-accent,#3e60d3) 12%,var(--canvas-bg,#fff));stroke:var(--canvas-accent,#3e60d3)}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}}`;\n\n // lib/sandbox.js\n var SANDBOX_LIMITS = Object.freeze({ source: 49152, height: 1e3, message: 16384, rate: 30 });\n function canvasSnapshot(node2, state2, data, derived, disabled, theme) {\n const pick = (keys, values) => Object.fromEntries((keys ?? []).map((k) => [k, values[k]]));\n return { state: pick(node2.stateKeys, state2), data: pick(node2.dataKeys, data), derived: pick(node2.derivedKeys, derived), disabled, theme };\n }\n function canvasPatch(message, node2) {\n if (!message || typeof message !== "object" || Array.isArray(message)) throw new Error("Invalid canvas patch");\n const keys = Object.keys(message);\n if (!keys.length || keys.length > 64 || keys.some((k) => !(node2.stateKeys ?? []).includes(k))) throw new Error("Canvas state key is not declared");\n if (JSON.stringify(message).length > SANDBOX_LIMITS.message) throw new Error("Canvas patch is too large");\n return message;\n }\n function sandboxDocument(node2, channel2, nonce2) {\n const json = (value) => JSON.stringify(value).replace(/</g, "\\\\u003c").replace(/\\u2028/g, "\\\\u2028").replace(/\\u2029/g, "\\\\u2029");\n return `<!doctype html><html><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src \'none\'; script-src \'nonce-${nonce2}\'; style-src \'unsafe-inline\'; img-src data:; font-src \'none\'; connect-src \'none\'; media-src \'none\'; object-src \'none\'; frame-src \'none\'; worker-src \'none\'; base-uri \'none\'; form-action \'none\'"><meta name="viewport" content="width=device-width,initial-scale=1"><style>${CANVAS_SYSTEM_CSS}</style></head><body><main id="canvas"></main><script nonce="${nonce2}">(()=>{\n const channel=${json(channel2)}, source=${json({ html: node2.html, css: node2.css ?? "", script: node2.script ?? "" })};\n let snapshot={state:{},data:{},derived:{},disabled:true,theme:{}}, started=false;\n const listeners=new Set(), send=(type,payload)=>parent.postMessage({dshCanvas:1,channel,type,payload},\'*\');\n const report=e=>send(\'error\',String(e?.message??e).slice(0,1000));\n const audit=${measureVisual.toString()};let auditTimer;const scheduleAudit=()=>{clearTimeout(auditTimer);auditTimer=setTimeout(()=>{const issues=audit(document.getElementById(\'canvas\'),${json(node2.id ?? "")});send(\'audit\',{issues,coverage:issues.coverage})},400)};\n addEventListener(\'resize\',scheduleAudit);\n addEventListener(\'error\',e=>report(e.error??e.message));addEventListener(\'unhandledrejection\',e=>report(e.reason));\n const animations=new Set(), motion=matchMedia(\'(prefers-reduced-motion: reduce)\');\n let raf=0,last=0,time=0;\n const visible=()=>snapshot.visible!==false&&!document.hidden;\n const canAnimate=()=>visible()&&!snapshot.disabled&&!motion.matches;\n const draw=delta=>{for(const fn of animations)try{fn({time,delta,reducedMotion:motion.matches,visible:visible()})}catch(e){animations.delete(fn);report(e)}};\n const tick=t=>{raf=0;if(!canAnimate()||!animations.size){last=0;draw(0);return}const delta=last?Math.min(.05,(t-last)/1000):0;last=t;time+=delta;draw(delta);if(animations.size)raf=requestAnimationFrame(tick)};\n const refresh=()=>{draw(0);if(canAnimate()&&animations.size){if(!raf){last=0;raf=requestAnimationFrame(tick)}}else{cancelAnimationFrame(raf);raf=0;last=0}};\n motion.addEventListener(\'change\',refresh);document.addEventListener(\'visibilitychange\',refresh);\n const formatNumber=${formatNumber.toString()};\n const api={formatNumber,get snapshot(){return structuredClone(snapshot)},subscribe(fn){if(typeof fn!==\'function\')throw Error(\'Listener required\');listeners.add(fn);fn(api.snapshot);return()=>listeners.delete(fn)},setState(patch){if(!snapshot.disabled)send(\'patch\',patch)},animate(fn){if(typeof fn!==\'function\')throw Error(\'Animation callback required\');animations.add(fn);refresh();return()=>{animations.delete(fn);if(!animations.size){cancelAnimationFrame(raf);raf=0;last=0}}}};\n Object.defineProperty(window,\'DSHUI\',{value:Object.freeze(api),writable:false});\n for(const type of [\'click\',\'input\',\'change\',\'keydown\',\'pointerdown\'])document.addEventListener(type,e=>{if(snapshot.disabled){e.preventDefault();e.stopImmediatePropagation()}},true);\n addEventListener(\'message\',event=>{\n const m=event.data;if(event.source!==parent||m?.dshCanvas!==1||m.channel!==channel||m.type!==\'snapshot\')return;\n snapshot=m.payload;for(const [k,v] of Object.entries(snapshot.theme??{}))document.documentElement.style.setProperty(\'--canvas-\'+k,v);\n document.documentElement.style.colorScheme=snapshot.theme?.scheme??\'light\';document.documentElement.dataset.canvasScheme=snapshot.theme?.scheme??\'light\';\n const wasStarted=started;\n if(!started){started=true;document.getElementById(\'canvas\').innerHTML=source.html;const style=document.createElement(\'style\');style.textContent=source.css;document.head.append(style);const script=document.createElement(\'script\');script.nonce=${json(nonce2)};script.textContent=source.script;document.body.append(script)}\n if(wasStarted)for(const fn of listeners)try{fn(api.snapshot)}catch(e){report(e)}\n refresh();if(!wasStarted)send(\'mounted\');scheduleAudit();\n });\n let resizePending=false;new ResizeObserver(()=>{if(!started||resizePending)return;resizePending=true;requestAnimationFrame(()=>{resizePending=false;send(\'height\',Math.ceil(document.getElementById(\'canvas\').getBoundingClientRect().height))})}).observe(document.getElementById(\'canvas\'));\n send(\'ready\');\n})();<\\/script></body></html>`;\n }\n\n // lib/components.js\n var define = (fields2, purpose, presentation = "") => Object.freeze({ fields: Object.freeze(fields2), purpose, presentation });\n var COMPONENTS = Object.freeze({\n heading: define(["text"], "Section heading", "tone"),\n text: define(["text"], "Readable explanation or bound text", "tone"),\n row: define(["children"], "Wrapping parallel content"),\n column: define(["children"], "Ordered vertical content"),\n card: define(["title", "children", "surface"], "Meaningful grouped section", "tone"),\n details: define(["title", "children", "open"], "Collapsible supporting content", "tone"),\n badge: define(["text"], "Short explicit status label", "tone"),\n progress: define(["label", "value", "max", "unit"], "Declared numeric progress snapshot", "tone"),\n steps: define(["items"], "Ordered declared steps"),\n metric: define(["label", "value", "unit", "decimals"], "Numeric result with units", "tone"),\n input: define(["label", "bind"], "String or numeric state input"),\n slider: define(["label", "bind"], "Numeric state control"),\n select: define(["label", "bind"], "Selection from declared state options"),\n toggle: define(["label", "bind"], "Boolean state control"),\n button: define(["text", "action"], "Declared Agent follow-up", "icon"),\n table: define(["rows", "columns"], "Exact supplied or derived values"),\n chart: define(["kind", "rows", "labelKey", "valueKey", "label", "unit", "xScale"], "Bar/line comparison with accessible data"),\n sandbox: define(["title", "html", "css", "script", "fallback", "height", "stateKeys", "dataKeys", "derivedKeys"], "Freeform isolated HTML/SVG/CSS/JavaScript visualization")\n });\n function componentFields(type) {\n const c = Object.hasOwn(COMPONENTS, type) ? COMPONENTS[type] : void 0;\n return c && ["id", "type", ...c.fields, ...c.presentation ? ["icon"] : [], ...c.presentation === "tone" ? ["tone"] : []];\n }\n\n // lib/author-expression.js\n function compileExpression(source) {\n const fail2 = () => {\n throw new Error("DSH UI: invalid formula; use state.x, data.x, derived.x, item.x, numbers, strings, + - * /, comparisons, ?: and min/max/round/abs");\n };\n if (typeof source !== "string" || !source.trim() || source.length > 2048) fail2();\n const tokens = [];\n let offset = 0;\n const token2 = /\\s*(?:(\\d+(?:\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?|("(?:[^"\\\\]|\\\\.)*")|([a-zA-Z][a-zA-Z0-9_]*(?:\\.[a-zA-Z][a-zA-Z0-9_]*)?)|(===|!==|<=|>=|==|!=|[+*/()?,:<>-]))/y;\n while (offset < source.length) {\n if (!source.slice(offset).trim()) break;\n token2.lastIndex = offset;\n const m = token2.exec(source);\n if (!m) fail2();\n offset = token2.lastIndex;\n tokens.push(m[1] ? { number: Number(m[1] + (m[2] ?? "")) } : m[3] ? { string: JSON.parse(m[3]) } : m[4] ?? m[5]);\n if (tokens.length > 256) fail2();\n }\n let pos = 0;\n const operators = { "==": ["eq", 1], "===": ["eq", 1], "!=": ["neq", 1], "!==": ["neq", 1], "<": ["lt", 2], "<=": ["lte", 2], ">": ["gt", 2], ">=": ["gte", 2], "+": ["add", 3], "-": ["sub", 3], "*": ["mul", 4], "/": ["div", 4] };\n const take = (t) => {\n if (tokens[pos++] !== t) fail2();\n };\n function parse(min = 0, depth = 0) {\n if (depth > 12) fail2();\n const t = tokens[pos++];\n let out;\n if (t && typeof t === "object") out = { const: Object.hasOwn(t, "number") ? t.number : t.string };\n else if (t === "true" || t === "false") out = { const: t === "true" };\n else if (t === "(") {\n out = parse(0, depth + 1);\n take(")");\n } else if (t === "-" || t === "+") {\n const arg = parse(5, depth + 1);\n out = t === "-" ? { op: "sub", args: [{ const: 0 }, arg] } : arg;\n } else if (typeof t === "string" && /^(state|data|derived|item)\\.[a-zA-Z][a-zA-Z0-9_]*$/.test(t)) out = { ref: t };\n else if (["min", "max", "round", "abs"].includes(t)) {\n take("(");\n const args = [parse(0, depth + 1)];\n while (tokens[pos] === ",") {\n pos++;\n args.push(parse(0, depth + 1));\n if (args.length > 8) fail2();\n }\n take(")");\n out = { op: t, args };\n } else fail2();\n while (typeof tokens[pos] === "string" && Object.hasOwn(operators, tokens[pos]) && operators[tokens[pos]][1] >= min) {\n const [op, precedence] = operators[tokens[pos++]];\n out = { op, args: [out, parse(precedence + 1, depth + 1)] };\n }\n if (min === 0 && tokens[pos] === "?") {\n pos++;\n const yes = parse(0, depth + 1);\n take(":");\n out = { op: "if", args: [out, yes, parse(0, depth + 1)] };\n }\n return out;\n }\n const result = parse();\n if (pos !== tokens.length) fail2();\n return result;\n }\n function expandExpressions(doc2) {\n const expression = (e) => {\n if (!e || typeof e !== "object" || Array.isArray(e)) return e;\n if (Object.hasOwn(e, "expr")) {\n if (Object.keys(e).length !== 1) throw new Error("DSH UI: expr must be the only formula field");\n return compileExpression(e.expr);\n }\n if (Array.isArray(e.args)) e.args = e.args.map(expression);\n if (e.map?.fields) for (const k of Object.keys(e.map.fields)) e.map.fields[k] = expression(e.map.fields[k]);\n return e;\n };\n if (doc2.derived && typeof doc2.derived === "object") for (const k of Object.keys(doc2.derived)) doc2.derived[k] = expression(doc2.derived[k]);\n const walk = (nodes) => {\n if (!Array.isArray(nodes)) return;\n for (const node2 of nodes) {\n if (!node2 || typeof node2 !== "object") continue;\n for (const field of ["text", "value", "max", "rows"]) if (Object.hasOwn(node2, field)) node2[field] = expression(node2[field]);\n walk(node2.children);\n }\n };\n walk(doc2.nodes);\n return doc2;\n }\n\n // lib/protocol.js\n var LIMITS = Object.freeze({ bytes: 131072, nodes: 160, depth: 12, rows: 500, expressions: 128, steps: 4096 });\n var own = (o, k) => Object.hasOwn(o, k);\n var fail = (message) => {\n throw new Error(`DSH UI: ${message}`);\n };\n var object = (x) => x !== null && typeof x === "object" && !Array.isArray(x);\n var key = (x) => typeof x === "string" && /^[a-zA-Z][a-zA-Z0-9_]{0,63}$/.test(x) && !["constructor", "prototype", "__proto__"].includes(x);\n var finite = (x) => typeof x === "number" && Number.isFinite(x);\n var scalar = (x) => typeof x === "string" || typeof x === "boolean" || finite(x);\n var text = (x, at) => {\n if (typeof x !== "string" || x.length > 8192) fail(`${at} must be a string of at most 8192 characters`);\n };\n function fields(value, allowed, at) {\n if (!object(value)) fail(`${at} must be an object`);\n for (const k of Object.keys(value)) if (!allowed.includes(k)) {\n const hint = at === "document" ? " Controls and visual components belong in nodes as registered typed nodes, not extra document fields." : "";\n fail(`unknown field ${at}.${k}; allowed fields at ${at}: ${allowed.join(", ")}.${hint}`);\n }\n }\n function safeJson(value, depth = 0, source = false) {\n if (depth > 48) fail("JSON nesting is too deep");\n if (value === null || typeof value === "boolean") return;\n if (typeof value === "string") {\n if (source) {\n if (value.length > SANDBOX_LIMITS.source) fail("canvas source exceeds 48 Ki characters");\n return;\n }\n return text(value, "value");\n }\n if (typeof value === "number") {\n if (!finite(value)) fail("numbers must be finite");\n return;\n }\n if (typeof value !== "object") fail("only JSON values are accepted");\n if (Array.isArray(value) && value.length > LIMITS.rows) fail("too many array items");\n for (const k of Object.keys(value)) {\n if (["__proto__", "prototype", "constructor"].includes(k)) fail("unsafe property name");\n safeJson(value[k], depth + 1, value.type === "sandbox" && ["html", "css", "script"].includes(k));\n }\n }\n function initialState(doc2) {\n return Object.fromEntries(Object.entries(doc2.state).map(([k, spec]) => [k, spec.default]));\n }\n function validateState(doc2, state2) {\n if (!object(state2) || Object.keys(state2).length !== Object.keys(doc2.state).length) fail("state keys do not match the document");\n const result = {};\n for (const [k, s] of Object.entries(doc2.state)) {\n if (!own(state2, k)) fail(`missing state.${k}`);\n const v = state2[k];\n if (s.type === "number") {\n if (!finite(v) || v < s.min || v > s.max) fail(`state.${k} is outside its numeric range`);\n const offset = (v - s.min) / s.step;\n if (Math.abs(offset - Math.round(offset)) > 1e-6) fail(`state.${k} does not match its step`);\n } else if (s.type === "string") text(v, `state.${k}`);\n else if (typeof v !== "boolean") fail(`state.${k} must be boolean`);\n if (s.options && !s.options.includes(v)) fail(`invalid option for state.${k}`);\n result[k] = v;\n }\n return result;\n }\n var ARITY = { add: [1, 8], sub: [2, 2], mul: [1, 8], div: [2, 2], min: [1, 8], max: [1, 8], round: [1, 1], abs: [1, 1], eq: [2, 2], neq: [2, 2], lt: [2, 2], lte: [2, 2], gt: [2, 2], gte: [2, 2], if: [3, 3] };\n function reference(doc2, ref) {\n if (typeof ref !== "string" || !/^(state|data|derived)\\.[a-zA-Z][a-zA-Z0-9_]{0,63}$/.test(ref)) fail("invalid reference");\n const [group, k] = ref.split(".");\n if (!own(doc2[group], k)) fail(`unknown reference ${ref}`);\n return [group, k];\n }\n function evaluate(doc2, state2) {\n const derived = {}, active = /* @__PURE__ */ new Set();\n let steps = 0, generatedRows = 0;\n const budget = () => {\n if (++steps > LIMITS.steps) fail("calculation budget exceeded");\n };\n const resolve = (ref) => {\n budget();\n const [group, k] = reference(doc2, ref);\n if (group !== "derived") return (group === "state" ? state2 : doc2.data)[k];\n if (own(derived, k)) return derived[k];\n if (active.has(k)) fail(`cyclic calculation ${k}`);\n active.add(k);\n const result2 = expression(doc2.derived[k]);\n active.delete(k);\n derived[k] = result2;\n return result2;\n };\n const expression = (e, item) => {\n budget();\n if (own(e, "map")) {\n const rows = resolve(e.map.source);\n if ((generatedRows += rows.length) > LIMITS.rows) fail("generated row limit exceeded");\n return rows.map((row) => Object.fromEntries(Object.entries(e.map.fields).map(([k, value]) => {\n const out2 = expression(value, row);\n if (!scalar(out2)) fail("generated cells must be scalar");\n return [k, out2];\n })));\n }\n if (own(e, "const")) return e.const;\n if (own(e, "ref")) {\n if (e.ref.startsWith("item.")) {\n const k = e.ref.slice(5);\n if (!item || !own(item, k) || !scalar(item[k])) fail("invalid item reference");\n return item[k];\n }\n return resolve(e.ref);\n }\n if (e.op === "if") {\n const condition = expression(e.args[0], item);\n if (typeof condition !== "boolean") fail("if condition must be boolean");\n return expression(e.args[condition ? 1 : 2], item);\n }\n const a = e.args.map((arg) => expression(arg, item));\n if (e.op === "eq") return a[0] === a[1];\n if (e.op === "neq") return a[0] !== a[1];\n if (!a.every(finite)) fail(`operator ${e.op} requires finite numbers`);\n let out;\n switch (e.op) {\n case "add":\n out = a.reduce((x, y) => x + y, 0);\n break;\n case "sub":\n out = a[0] - a[1];\n break;\n case "mul":\n out = a.reduce((x, y) => x * y, 1);\n break;\n case "div":\n if (a[1] === 0) fail("division by zero");\n out = a[0] / a[1];\n break;\n case "min":\n out = Math.min(...a);\n break;\n case "max":\n out = Math.max(...a);\n break;\n case "round":\n out = Math.round(a[0]);\n break;\n case "abs":\n out = Math.abs(a[0]);\n break;\n case "lt":\n return a[0] < a[1];\n case "lte":\n return a[0] <= a[1];\n case "gt":\n return a[0] > a[1];\n case "gte":\n return a[0] >= a[1];\n default:\n fail(`unsupported operator ${e.op}`);\n }\n if (!finite(out)) fail("non-finite calculation result");\n return out;\n };\n for (const k of Object.keys(doc2.derived)) resolve(`derived.${k}`);\n if (new TextEncoder().encode(JSON.stringify(derived)).length > LIMITS.bytes) fail("derived output exceeds 128 KiB");\n const result = { derived, resolveValue: (value) => {\n if (!object(value)) return value;\n return expression(value);\n } };\n checkViewValues(doc2, result);\n return result;\n }\n function checkViewValues(doc2, evaluated) {\n function walk(list) {\n for (const n of list) {\n if (n.type === "table" || n.type === "chart") {\n const rows = evaluated.resolveValue(n.rows);\n if (!Array.isArray(rows) || rows.length > LIMITS.rows || !rows.every(object)) fail("table/chart rows must reference an array of objects");\n if (n.type === "chart" && rows.some((r) => !own(r, n.labelKey) || !scalar(r[n.labelKey]) || !own(r, n.valueKey) || !finite(r[n.valueKey]))) fail("chart requires labels and finite numeric values");\n if (n.type === "chart" && n.xScale === "linear" && rows.some((r) => !finite(r[n.labelKey]))) fail("linear chart requires numeric x values");\n }\n if (n.type === "metric" && !finite(evaluated.resolveValue(n.value))) fail("metric requires a numeric value");\n if (n.type === "progress") {\n const v = evaluated.resolveValue(n.value), max = evaluated.resolveValue(n.max);\n if (!finite(v) || !finite(max) || max <= 0 || v < 0 || v > max) fail("progress requires 0 <= value <= positive max");\n }\n if (n.children) walk(n.children);\n }\n }\n walk(doc2.nodes);\n }\n function validateDocument(input) {\n safeJson(input);\n const json = JSON.stringify(input);\n if (new TextEncoder().encode(json).length > LIMITS.bytes) fail("document exceeds 128 KiB");\n const doc2 = expandExpressions(JSON.parse(json));\n fields(doc2, ["version", "title", "fallback", "state", "data", "derived", "nodes", "actions", "presentation"], "document");\n if (doc2.presentation !== void 0) {\n fields(doc2.presentation, ["layout", "accent", "density"], "presentation");\n for (const [k, allowed] of Object.entries({ layout: UI_LAYOUTS, accent: UI_ACCENTS, density: ["comfortable", "compact"] }))\n if (doc2.presentation[k] !== void 0 && !allowed.includes(doc2.presentation[k])) fail(`unknown presentation ${k}`);\n }\n if (doc2.version !== 1) fail("unsupported protocol version");\n text(doc2.title, "title");\n text(doc2.fallback, "fallback");\n if (!doc2.title.trim() || !doc2.fallback.trim()) fail("title and fallback cannot be empty");\n for (const group of ["state", "data", "derived", "actions"]) {\n doc2[group] ??= {};\n if (!object(doc2[group]) || Object.keys(doc2[group]).length > 64) fail(`invalid ${group}`);\n for (const k of Object.keys(doc2[group])) if (!key(k)) fail(`invalid key in ${group}`);\n }\n for (const [k, s] of Object.entries(doc2.state)) {\n fields(s, ["type", "default", "min", "max", "step", "options"], `state.${k}`);\n if (!["number", "string", "boolean"].includes(s.type)) fail(`unsupported state type ${k}`);\n if (s.type === "number") {\n if (![s.min, s.max, s.step].every(finite) || s.min >= s.max || s.step <= 0) fail(`invalid numeric limits for ${k}`);\n if ((s.max - s.min) / s.step > 1e9) fail(`numeric step too small for ${k}`);\n } else if (["min", "max", "step"].some((p) => own(s, p))) fail(`numeric limits on non-number ${k}`);\n if (s.options && (!Array.isArray(s.options) || !s.options.length || s.options.length > 64 || !s.options.every(scalar))) fail(`invalid options for ${k}`);\n }\n const defaults = validateState(doc2, initialState(doc2));\n let expressions = 0;\n for (const [k, spec] of Object.entries(doc2.state))\n for (const option of spec.options ?? []) validateState(doc2, { ...defaults, [k]: option });\n function validateExpression(e, depth = 0, itemRows) {\n if (++expressions > LIMITS.expressions || depth > LIMITS.depth) fail("expression limit exceeded");\n if (!object(e)) fail("expression must be an object");\n if (own(e, "map")) {\n if (depth !== 0) fail("map is only allowed at the root of a derived value");\n fields(e, ["map"], "expression");\n fields(e.map, ["source", "fields"], "map");\n if (typeof e.map.source !== "string" || !e.map.source.startsWith("data.")) fail(\'map source must reference static data using a string such as "data.samples"; put object rows in document.data.samples, not inline in map.source\');\n const [, k] = reference(doc2, e.map.source), rows = doc2.data[k];\n if (!Array.isArray(rows) || rows.length > LIMITS.rows || !rows.every(object)) fail("map source must be object rows");\n if (!object(e.map.fields) || !Object.keys(e.map.fields).length || Object.keys(e.map.fields).length > 16) fail("map requires 1..16 fields");\n for (const [k2, value2] of Object.entries(e.map.fields)) {\n if (!key(k2)) fail(`invalid map field ${JSON.stringify(k2).slice(0, 100)}; use an ASCII identifier matching [a-zA-Z][a-zA-Z0-9_]{0,63}, such as powerW. Put Chinese display text in column/chart labels, not internal field keys`);\n validateExpression(value2, depth + 1, rows);\n }\n return;\n }\n if (own(e, "const")) {\n fields(e, ["const"], "expression");\n if (!scalar(e.const)) fail("constant must be scalar");\n return;\n }\n if (own(e, "ref")) {\n fields(e, ["ref"], "expression");\n if (typeof e.ref === "string" && e.ref.startsWith("item.")) {\n const k = e.ref.slice(5);\n if (!itemRows || !key(k) || itemRows.some((row) => !own(row, k) || !scalar(row[k]))) fail("invalid or unscoped item reference");\n } else reference(doc2, e.ref);\n return;\n }\n fields(e, ["op", "args"], "expression");\n const arity = ARITY[e.op];\n if (!arity || !Array.isArray(e.args) || e.args.length < arity[0] || e.args.length > arity[1]) fail("invalid operator or argument count");\n e.args.forEach((a) => validateExpression(a, depth + 1, itemRows));\n }\n Object.values(doc2.derived).forEach((e) => validateExpression(e));\n const visited = /* @__PURE__ */ new Set(), active = /* @__PURE__ */ new Set();\n function visit(k) {\n if (active.has(k)) fail(`cyclic calculation ${k}`);\n if (visited.has(k)) return;\n active.add(k);\n function walk(e) {\n if (e.ref?.startsWith("derived.")) visit(e.ref.split(".")[1]);\n for (const a of e.args ?? []) walk(a);\n for (const value2 of Object.values(e.map?.fields ?? {})) walk(value2);\n }\n walk(doc2.derived[k]);\n active.delete(k);\n visited.add(k);\n }\n Object.keys(doc2.derived).forEach(visit);\n for (const [k, a] of Object.entries(doc2.actions)) {\n fields(a, ["type", "intent", "stateKeys"], `actions.${k}`);\n if (a.type !== "agent.followup") fail("only agent.followup actions are supported");\n text(a.intent, "action intent");\n if (!a.intent.trim() || !Array.isArray(a.stateKeys) || a.stateKeys.length > 64 || new Set(a.stateKeys).size !== a.stateKeys.length || a.stateKeys.some((s) => !own(doc2.state, s))) fail("invalid action stateKeys");\n }\n const ids = /* @__PURE__ */ new Set();\n let count2 = 0;\n const value = (v, at) => {\n if (object(v)) {\n if (own(v, "map")) fail("map belongs in derived");\n validateExpression(v);\n } else if (!scalar(v)) fail(`invalid value at ${at}`);\n };\n function nodes(list, depth = 0) {\n if (!Array.isArray(list) || depth > LIMITS.depth) fail("invalid node children or depth");\n for (const n of list) {\n if (++count2 > LIMITS.nodes) fail("too many nodes");\n if (!object(n) || !key(n.id) || ids.has(n.id)) fail("node ids must be unique identifiers");\n ids.add(n.id);\n if (!Object.hasOwn(COMPONENTS, n.type)) fail("unsupported component " + n.type);\n switch (n.type) {\n case "sandbox": {\n text(n.title, "canvas title");\n text(n.fallback, "canvas fallback");\n if (!n.title.trim() || !n.fallback.trim() || typeof n.html !== "string" || !n.html.trim()) fail("canvas requires title, HTML and fallback");\n for (const field of ["html", "css", "script"]) if (n[field] !== void 0 && (typeof n[field] !== "string" || n[field].length > SANDBOX_LIMITS.source)) fail("canvas source exceeds 48 Ki characters");\n if (n.height !== void 0 && (!Number.isInteger(n.height) || n.height < 160 || n.height > SANDBOX_LIMITS.height)) fail("canvas height must be 160..1000");\n for (const [field, group] of [["stateKeys", "state"], ["dataKeys", "data"], ["derivedKeys", "derived"]]) if (n[field] !== void 0 && (!Array.isArray(n[field]) || n[field].length > 64 || new Set(n[field]).size !== n[field].length || n[field].some((k) => !own(doc2[group], k)))) fail("invalid canvas " + field);\n break;\n }\n case "row":\n case "column":\n break;\n case "card":\n if (n.title !== void 0) text(n.title, "card title");\n if (n.surface !== void 0 && !UI_SURFACES.includes(n.surface)) fail("unknown card surface");\n break;\n case "details":\n text(n.title, "details title");\n if (n.open !== void 0 && typeof n.open !== "boolean") fail("details open must be boolean");\n break;\n case "badge":\n value(n.text, "badge text");\n break;\n case "progress":\n text(n.label, "progress label");\n value(n.value, "progress value");\n value(n.max, "progress max");\n if (n.unit !== void 0) text(n.unit, "progress unit");\n break;\n case "steps": {\n if (!Array.isArray(n.items) || !n.items.length || n.items.length > 12) fail("steps require 1..12 items");\n for (const item of n.items) {\n fields(item, ["title", "description", "status"], "step");\n text(item.title, "step title");\n if (item.description !== void 0) text(item.description, "step description");\n if (!["pending", "active", "done", "error"].includes(item.status)) fail("unknown step status");\n }\n break;\n }\n case "heading":\n case "text":\n value(n.text, "text");\n break;\n case "metric":\n text(n.label, "metric label");\n value(n.value, "metric value");\n if (n.unit !== void 0) text(n.unit, "unit");\n if (n.decimals !== void 0 && (!Number.isInteger(n.decimals) || n.decimals < 0 || n.decimals > 6)) fail("invalid decimals");\n break;\n case "input":\n case "slider":\n case "select":\n case "toggle": {\n text(n.label, "control label");\n if (typeof n.bind !== "string" || !n.bind.startsWith("state.")) fail("controls must bind state");\n const [, k] = reference(doc2, n.bind), spec = doc2.state[k];\n if (n.type === "slider" && spec.type !== "number") fail("slider requires numeric state");\n if (n.type === "toggle" && spec.type !== "boolean") fail("toggle requires boolean state");\n if (n.type === "input" && spec.type === "boolean") fail("use toggle for boolean state");\n if (n.type === "select" && !spec.options) fail("select requires options");\n break;\n }\n case "button":\n text(n.text, "button text");\n if (!own(doc2.actions, n.action)) fail("unknown action");\n break;\n case "table": {\n value(n.rows, "table rows");\n if (!Array.isArray(n.columns) || !n.columns.length || n.columns.length > 16) fail("invalid table columns");\n const cols = /* @__PURE__ */ new Set();\n for (const c of n.columns) {\n fields(c, ["key", "label", "unit"], "column");\n if (!key(c.key) || cols.has(c.key)) fail("invalid or duplicate column key");\n cols.add(c.key);\n text(c.label, "column label");\n if (c.unit !== void 0) text(c.unit, "column unit");\n }\n break;\n }\n case "chart":\n value(n.rows, "chart rows");\n if (!["bar", "line"].includes(n.kind) || !key(n.labelKey) || !key(n.valueKey)) fail("invalid chart");\n text(n.label, "chart label");\n if (n.unit !== void 0) text(n.unit, "chart unit");\n if (n.xScale !== void 0 && (!["category", "linear"].includes(n.xScale) || n.xScale === "linear" && n.kind !== "line")) fail("invalid xScale");\n break;\n default:\n fail(`unsupported component ${n.type}`);\n }\n if (["heading", "text", "card", "metric", "button", "badge", "progress", "details"].includes(n.type)) {\n if (n.icon !== void 0 && !UI_ICONS.includes(n.icon)) fail("unknown UI icon");\n if (n.type !== "button") {\n if (n.tone !== void 0 && !UI_TONES.includes(n.tone)) fail("unknown UI tone");\n }\n }\n fields(n, componentFields(n.type), `node.${n.id}`);\n if (["row", "column", "card", "details"].includes(n.type)) nodes(n.children, depth + 1);\n }\n }\n nodes(doc2.nodes);\n if (!count2) fail("at least one node is required");\n evaluate(doc2, defaults);\n return doc2;\n }\n\n // src/export-runtime.js\n var payload = JSON.parse(document.getElementById("dsh-ui-export").textContent);\n var doc = validateDocument(payload.document);\n var node = doc.nodes.flatMap(function flatten(n) {\n return [n, ...(n.children ?? []).flatMap(flatten)];\n }).find((n) => n.id === payload.nodeId && n.type === "sandbox");\n if (!node) throw Error("\\u5BFC\\u51FA\\u7684\\u753B\\u5E03\\u4E0D\\u5B58\\u5728");\n var state = validateState(doc, payload.state);\n var connected = false;\n var start = Date.now();\n var count = 0;\n var token = () => Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) => b.toString(16).padStart(2, "0")).join("");\n var channel = token();\n var nonce = payload.nonce;\n var frame = document.createElement("iframe");\n frame.title = node.title;\n frame.sandbox = "allow-scripts";\n frame.referrerPolicy = "no-referrer";\n frame.style.cssText = "display:block;width:100%;height:" + (node.height ?? 420) + "px;border:0";\n var status = document.getElementById("status");\n var publish = () => {\n try {\n frame.contentWindow.postMessage({ dshCanvas: 1, channel, type: "snapshot", payload: { ...canvasSnapshot(node, state, doc.data, evaluate(doc, state).derived, false, payload.theme), visible: !document.hidden } }, "*");\n } catch (e) {\n status.textContent = "\\u8BA1\\u7B97\\u5931\\u8D25\\uFF1A" + e.message;\n }\n };\n addEventListener("message", (event) => {\n const m = event.data;\n if (event.source !== frame.contentWindow || m?.channel !== channel || m.dshCanvas !== 1) return;\n if (Date.now() - start > 1e3) {\n start = Date.now();\n count = 0;\n }\n if (++count > SANDBOX_LIMITS.rate) return;\n if (m.type === "ready") {\n connected = true;\n publish();\n } else if (m.type === "patch" && connected) {\n try {\n const next = validateState(doc, { ...state, ...canvasPatch(m.payload, node) });\n evaluate(doc, next);\n state = next;\n status.textContent = "\\u672C\\u5730\\u53C2\\u6570\\u5DF2\\u66F4\\u65B0\\uFF1B\\u5237\\u65B0\\u6587\\u4EF6\\u4F1A\\u56DE\\u5230\\u5BFC\\u51FA\\u65F6\\u7684\\u53C2\\u6570\\u3002";\n } catch (e) {\n status.textContent = "\\u53C2\\u6570\\u65E0\\u6548\\uFF1A" + e.message;\n }\n publish();\n } else if (m.type === "height" && Number.isFinite(m.payload)) frame.style.height = Math.max(160, Math.min(1e3, Math.ceil(m.payload))) + "px";\n else if (m.type === "error") status.textContent = "\\u753B\\u5E03\\u8FD0\\u884C\\u5F02\\u5E38\\uFF1A" + String(m.payload).slice(0, 1e3);\n });\n document.addEventListener("visibilitychange", () => {\n if (connected) publish();\n });\n document.getElementById("surface").append(frame);\n frame.srcdoc = sandboxDocument(node, channel, nonce);\n})();\n';
|
|
22794
|
+
var EXPORT_RUNTIME = '(() => {\n // lib/presentation.js\n var UI_ICONS = Object.freeze(["sparkles", "sliders", "layers", "chart", "gauge", "cpu", "database", "info", "check", "warning", "arrow", "target"]);\n var UI_TONES = Object.freeze(["neutral", "accent", "success", "warning", "danger"]);\n var UI_LAYOUTS = Object.freeze(["dashboard", "workbench", "comparison", "guide", "status", "report"]);\n var UI_ACCENTS = Object.freeze(["blue", "teal", "violet", "amber", "rose"]);\n var UI_SURFACES = Object.freeze(["outline", "soft", "featured"]);\n\n // lib/visual-audit.js\n function measureVisual(root, nodeId = "") {\n const issues = [], seen = /* @__PURE__ */ new Set(), coverage = { nodeId, elements: 0, truncated: false, contrastChecked: 0, contrastUncovered: 0 };\n const add = (code, value, el2) => {\n const id = el2?.closest("[data-ui-node]")?.getAttribute("data-ui-node") ?? nodeId;\n const k = id + ":" + code + ":" + Math.round(value ?? 0);\n if (!seen.has(k) && issues.length < 40) {\n seen.add(k);\n issues.push({ code, nodeId: id, ...value === void 0 ? {} : { value: Number(value.toFixed(2)) } });\n }\n };\n const color = (s) => {\n let m = s.match(/^rgba?\\(([^)]+)\\)/);\n if (m) {\n const a = m[1].split(/[\\s,\\/]+/).map(Number);\n return [a[0] / 255, a[1] / 255, a[2] / 255, a[3] ?? 1];\n }\n m = s.match(/^color\\(srgb ([^)]+)\\)/);\n if (m) {\n const a = m[1].split(/[\\s\\/]+/).map(Number);\n return [a[0], a[1], a[2], a[3] ?? 1];\n }\n return null;\n };\n const luminance = (c) => c.slice(0, 3).map((v) => v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4).reduce((s, v, i) => s + v * [0.2126, 0.7152, 0.0722][i], 0);\n const widthRoot = root.id === "canvas" ? document.documentElement : root;\n if (widthRoot.scrollWidth > widthRoot.clientWidth + 2) add("overflow", widthRoot.scrollWidth - widthRoot.clientWidth);\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);\n let el;\n while (el = walker.nextNode()) {\n if (coverage.elements >= 2e3) {\n coverage.truncated = true;\n break;\n }\n coverage.elements++;\n if (el.matches("[data-canvas-phase=error]")) add("runtimeError", void 0, el);\n const css = getComputedStyle(el), box = el.getBoundingClientRect();\n if (!box.width || !box.height || css.visibility === "hidden" || css.display === "none") continue;\n const text2 = [...el.childNodes].some((n) => n.nodeType === 3 && n.textContent.trim());\n if (text2) {\n let size = parseFloat(css.fontSize);\n if (el instanceof SVGElement && el.getScreenCTM) {\n const m = el.getScreenCTM();\n if (m) size *= Math.hypot(m.c, m.d);\n }\n if (size < 11.9) add("smallText", size, el);\n const fg = color(css.color);\n let ancestor = el, bg = null, depth = 0;\n while (ancestor && depth++ < 64) {\n const style = getComputedStyle(ancestor);\n if (style.backgroundImage !== "none") break;\n const c = color(style.backgroundColor);\n if (c?.[3] === 1) {\n bg = c;\n break;\n }\n if (c?.[3] > 0) break;\n ancestor = ancestor.parentElement;\n }\n if (!(el instanceof SVGElement) && fg?.[3] === 1 && bg) {\n coverage.contrastChecked++;\n const a = luminance(fg), b = luminance(bg), ratio = (Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05);\n if (ratio < (size >= 24 || size >= 18.66 && parseFloat(css.fontWeight) >= 700 ? 3 : 4.5)) add("contrast", ratio, el);\n } else coverage.contrastUncovered++;\n }\n if (el.matches("input:not([type=hidden]),select,textarea,button,[role=button]") && !el.getAttribute("aria-label") && !el.getAttribute("aria-labelledby") && !el.labels?.length && !el.textContent.trim() && !el.getAttribute("title")) add("missingLabel", void 0, el);\n }\n Object.defineProperty(issues, "coverage", { value: coverage });\n return issues;\n }\n\n // lib/format-number.js\n function formatNumber(value, decimals = 2) {\n if (typeof value !== "number" || !Number.isFinite(value)) throw new Error("DSH UI: formatNumber requires a finite number");\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 6) throw new Error("DSH UI: formatNumber decimals must be an integer from 0 to 6");\n return value.toLocaleString("en-US", { minimumFractionDigits: decimals, maximumFractionDigits: decimals });\n }\n\n // lib/canvas-system.js\n var CANVAS_SYSTEM_CSS = `\n:root{--canvas-radius:20px;--canvas-gap:16px;--canvas-positive:#167456;--canvas-negative:#b13b3b;--canvas-warning:#875b15}\n:root[data-canvas-scheme=dark]{--canvas-positive:#78d9b4;--canvas-negative:#ffaaaa;--canvas-warning:#edc87e}\n#canvas{display:flow-root}html,body{margin:0;min-width:0;background:var(--canvas-bg,#fff);color:var(--canvas-ink,#182537);font:14px/1.6 system-ui,"Microsoft YaHei",sans-serif}*{box-sizing:border-box}svg{max-width:100%;height:auto}button,input,select,textarea{font:inherit;color:inherit}button,input,select,textarea{border:1px solid var(--canvas-line,#ced4df);border-radius:8px;background:var(--canvas-bg,#fff);padding:8px 12px;max-width:100%}button{cursor:pointer}button:disabled{cursor:default;opacity:.55}input[type=range]{padding:0;accent-color:var(--canvas-accent,#3e60d3)}input[type=checkbox],input[type=radio]{accent-color:var(--canvas-accent,#3e60d3)}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--canvas-accent,#3e60d3);outline-offset:3px}\n.ui-stack{display:grid;gap:var(--canvas-gap)}.ui-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:var(--canvas-gap)}.ui-surface{padding:20px;border:1px solid var(--canvas-line,#ced4df);border-radius:var(--canvas-radius);background:var(--canvas-soft,#f3f5f8)}.ui-title{margin:0;font-size:clamp(20px,3vw,28px);line-height:1.3;letter-spacing:-.02em}.ui-caption{color:var(--canvas-muted,#526176);margin:8px 0;font-size:14px}.ui-value{font-size:clamp(24px,4vw,36px);font-variant-numeric:tabular-nums;line-height:1.2}.ui-controls{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.ui-field{display:grid;gap:6px;min-width:0}.ui-legend{display:flex;gap:16px;flex-wrap:wrap;font-size:13px}.ui-status{min-height:1.6em}.ui-error{color:var(--canvas-negative)}.ui-primary{background:var(--canvas-accent,#3e60d3);color:var(--canvas-accent-ink,#fff);border-color:transparent}\nsvg .ui-node{fill:var(--canvas-soft,#f3f5f8);stroke:var(--canvas-line,#ced4df);stroke-width:1}svg .ui-edge{fill:none;stroke:var(--canvas-muted,#526176);stroke-width:1.5}svg .ui-label{fill:var(--canvas-ink,#182537);font:500 14px system-ui,sans-serif}svg .ui-note{fill:var(--canvas-muted,#526176);font:400 13px system-ui,sans-serif}svg .ui-leader{fill:none;stroke:var(--canvas-muted,#526176);stroke-dasharray:3 4}svg .ui-accent{fill:color-mix(in srgb,var(--canvas-accent,#3e60d3) 12%,var(--canvas-bg,#fff));stroke:var(--canvas-accent,#3e60d3)}\n.ui-flow{display:flex;align-items:center;justify-content:center;gap:16px;padding:24px 8px;flex-wrap:wrap}.ui-step{display:grid;gap:6px;min-width:130px;max-width:240px;padding:16px 20px;border:1px solid var(--canvas-line);border-radius:6px;background:var(--canvas-bg)}.ui-step strong{font-size:16px;font-weight:600}.ui-step span{font-size:14px;color:var(--canvas-muted)}.ui-arrow{color:var(--canvas-muted);font-size:22px}.ui-callout{border-inline-start:3px solid var(--canvas-accent);padding:8px 16px;color:var(--canvas-ink)}\n.ui-surface,.ui-step{border-radius:var(--canvas-radius);background:linear-gradient(135deg,color-mix(in srgb,var(--canvas-accent,#3e60d3) 9%,var(--canvas-bg,#fff)),var(--canvas-soft,#f3f5f8))}button,input:not([type=checkbox]):not([type=radio]):not([type=range]),select,textarea{border-radius:14px}.ui-primary{background:linear-gradient(120deg,var(--canvas-accent,#3e60d3),color-mix(in srgb,var(--canvas-accent,#3e60d3) 85%,#152647))}.ui-callout{border-radius:14px;background:linear-gradient(120deg,color-mix(in srgb,var(--canvas-accent,#3e60d3) 7%,var(--canvas-bg,#fff)),var(--canvas-bg,#fff))}\n@media(max-width:480px){.ui-flow{flex-direction:column;padding:16px 8px;gap:12px}.ui-step{width:100%;max-width:none}.ui-arrow{transform:rotate(90deg)}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}}`;\n\n // lib/sandbox.js\n var SANDBOX_LIMITS = Object.freeze({ source: 49152, height: 1e3, message: 16384, rate: 30 });\n function canvasSnapshot(node2, state2, data, derived, disabled, theme) {\n const pick = (keys, values) => Object.fromEntries((keys ?? []).map((k) => [k, values[k]]));\n return { state: pick(node2.stateKeys, state2), data: pick(node2.dataKeys, data), derived: pick(node2.derivedKeys, derived), disabled, theme };\n }\n function canvasPatch(message, node2) {\n if (!message || typeof message !== "object" || Array.isArray(message)) throw new Error("Invalid canvas patch");\n const keys = Object.keys(message);\n if (!keys.length || keys.length > 64 || keys.some((k) => !(node2.stateKeys ?? []).includes(k))) throw new Error("Canvas state key is not declared");\n if (JSON.stringify(message).length > SANDBOX_LIMITS.message) throw new Error("Canvas patch is too large");\n return message;\n }\n function sandboxDocument(node2, channel2, nonce2) {\n const json = (value) => JSON.stringify(value).replace(/</g, "\\\\u003c").replace(/\\u2028/g, "\\\\u2028").replace(/\\u2029/g, "\\\\u2029");\n return `<!doctype html><html><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src \'none\'; script-src \'nonce-${nonce2}\'; style-src \'unsafe-inline\'; img-src data:; font-src \'none\'; connect-src \'none\'; media-src \'none\'; object-src \'none\'; frame-src \'none\'; worker-src \'none\'; base-uri \'none\'; form-action \'none\'"><meta name="viewport" content="width=device-width,initial-scale=1"><style>${CANVAS_SYSTEM_CSS}</style></head><body><main id="canvas"></main><script nonce="${nonce2}">(()=>{\n const channel=${json(channel2)}, source=${json({ html: node2.html, css: node2.css ?? "", script: node2.script ?? "" })};\n let snapshot={state:{},data:{},derived:{},disabled:true,theme:{}}, started=false;\n const listeners=new Set(), send=(type,payload)=>parent.postMessage({dshCanvas:1,channel,type,payload},\'*\');\n const report=e=>send(\'error\',String(e?.message??e).slice(0,1000));\n const audit=${measureVisual.toString()};let auditTimer;const scheduleAudit=()=>{clearTimeout(auditTimer);auditTimer=setTimeout(()=>{const issues=audit(document.getElementById(\'canvas\'),${json(node2.id ?? "")});send(\'audit\',{issues,coverage:issues.coverage})},400)};\n addEventListener(\'resize\',scheduleAudit);\n addEventListener(\'error\',e=>report(e.error??e.message));addEventListener(\'unhandledrejection\',e=>report(e.reason));\n const animations=new Set(), motion=matchMedia(\'(prefers-reduced-motion: reduce)\');\n let raf=0,last=0,time=0;\n const visible=()=>snapshot.visible!==false&&!document.hidden;\n const canAnimate=()=>visible()&&!snapshot.disabled&&!motion.matches;\n const draw=delta=>{for(const fn of animations)try{fn({time,delta,reducedMotion:motion.matches,visible:visible()})}catch(e){animations.delete(fn);report(e)}};\n const tick=t=>{raf=0;if(!canAnimate()||!animations.size){last=0;draw(0);return}const delta=last?Math.min(.05,(t-last)/1000):0;last=t;time+=delta;draw(delta);if(animations.size)raf=requestAnimationFrame(tick)};\n const refresh=()=>{draw(0);if(canAnimate()&&animations.size){if(!raf){last=0;raf=requestAnimationFrame(tick)}}else{cancelAnimationFrame(raf);raf=0;last=0}};\n motion.addEventListener(\'change\',refresh);document.addEventListener(\'visibilitychange\',refresh);\n const formatNumber=${formatNumber.toString()};\n const api={formatNumber,get snapshot(){return structuredClone(snapshot)},subscribe(fn){if(typeof fn!==\'function\')throw Error(\'Listener required\');listeners.add(fn);fn(api.snapshot);return()=>listeners.delete(fn)},setState(patch){if(!snapshot.disabled)send(\'patch\',patch)},animate(fn){if(typeof fn!==\'function\')throw Error(\'Animation callback required\');animations.add(fn);refresh();return()=>{animations.delete(fn);if(!animations.size){cancelAnimationFrame(raf);raf=0;last=0}}}};\n Object.defineProperty(window,\'DSHUI\',{value:Object.freeze(api),writable:false});\n for(const type of [\'click\',\'input\',\'change\',\'keydown\',\'pointerdown\'])document.addEventListener(type,e=>{if(snapshot.disabled){e.preventDefault();e.stopImmediatePropagation()}},true);\n addEventListener(\'message\',event=>{\n const m=event.data;if(event.source!==parent||m?.dshCanvas!==1||m.channel!==channel||m.type!==\'snapshot\')return;\n snapshot=m.payload;for(const [k,v] of Object.entries(snapshot.theme??{}))document.documentElement.style.setProperty(\'--canvas-\'+k,v);\n document.documentElement.style.colorScheme=snapshot.theme?.scheme??\'light\';document.documentElement.dataset.canvasScheme=snapshot.theme?.scheme??\'light\';\n const wasStarted=started;\n if(!started){started=true;document.getElementById(\'canvas\').innerHTML=source.html;const style=document.createElement(\'style\');style.textContent=source.css;document.head.append(style);const script=document.createElement(\'script\');script.nonce=${json(nonce2)};script.textContent=source.script;document.body.append(script)}\n if(wasStarted)for(const fn of listeners)try{fn(api.snapshot)}catch(e){report(e)}\n refresh();if(!wasStarted)send(\'mounted\');scheduleAudit();\n });\n let resizePending=false;new ResizeObserver(()=>{if(!started||resizePending)return;resizePending=true;requestAnimationFrame(()=>{resizePending=false;send(\'height\',Math.ceil(document.getElementById(\'canvas\').getBoundingClientRect().height))})}).observe(document.getElementById(\'canvas\'));\n send(\'ready\');\n})();<\\/script></body></html>`;\n }\n\n // lib/components.js\n var define = (fields2, purpose, presentation = "") => Object.freeze({ fields: Object.freeze(fields2), purpose, presentation });\n var COMPONENTS = Object.freeze({\n heading: define(["text"], "Section heading", "tone"),\n text: define(["text"], "Readable explanation or bound text", "tone"),\n row: define(["children"], "Wrapping parallel content"),\n column: define(["children"], "Ordered vertical content"),\n card: define(["title", "children", "surface"], "Meaningful grouped section", "tone"),\n details: define(["title", "children", "open"], "Collapsible supporting content", "tone"),\n badge: define(["text"], "Short explicit status label", "tone"),\n progress: define(["label", "value", "max", "unit"], "Declared numeric progress snapshot", "tone"),\n steps: define(["items"], "Ordered declared steps"),\n metric: define(["label", "value", "unit", "decimals"], "Number with units, or a literal/bound status string", "tone"),\n input: define(["label", "bind"], "String or numeric state input"),\n slider: define(["label", "bind"], "Numeric state control"),\n select: define(["label", "bind"], "Selection from declared state options"),\n toggle: define(["label", "bind"], "Boolean state control"),\n button: define(["text", "action"], "Declared Agent follow-up", "icon"),\n table: define(["label", "rows", "columns"], "Supplied or derived values; inline rows or data/derived reference"),\n chart: define(["kind", "rows", "labelKey", "valueKey", "label", "unit", "xScale"], "Bar/line comparison with accessible data"),\n sandbox: define(["title", "html", "css", "script", "fallback", "height", "stateKeys", "dataKeys", "derivedKeys"], "Freeform isolated HTML/SVG/CSS/JavaScript visualization")\n });\n function componentFields(type) {\n const c = Object.hasOwn(COMPONENTS, type) ? COMPONENTS[type] : void 0;\n return c && ["id", "type", ...c.fields, ...c.presentation ? ["icon"] : [], ...c.presentation === "tone" ? ["tone"] : []];\n }\n\n // lib/identifiers.js\n var IDENTIFIER_SOURCE = "[\\\\p{L}_][\\\\p{L}\\\\p{M}\\\\p{N}_]{0,63}";\n var pattern = new RegExp(`^${IDENTIFIER_SOURCE}$`, "u");\n var validIdentifier = (value) => typeof value === "string" && pattern.test(value) && !["constructor", "prototype", "__proto__"].includes(value);\n\n // lib/author-expression.js\n function compileExpression(source) {\n const fail2 = () => {\n throw new Error("DSH UI: invalid formula; use state.x, data.x, derived.x, item.x, numbers, strings, + - * /, comparisons, ?: and min/max/round/abs");\n };\n if (typeof source !== "string" || !source.trim() || source.length > 2048) fail2();\n const tokens = [];\n let offset = 0;\n const token2 = new RegExp(String.raw`\\s*(?:(\\d+(?:\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?|("(?:[^"\\\\]|\\\\.)*")|(${IDENTIFIER_SOURCE}(?:\\.${IDENTIFIER_SOURCE})?)|(===|!==|<=|>=|==|!=|[+*/()?,:<>-]))`, "uy");\n while (offset < source.length) {\n if (!source.slice(offset).trim()) break;\n token2.lastIndex = offset;\n const m = token2.exec(source);\n if (!m) fail2();\n offset = token2.lastIndex;\n tokens.push(m[1] ? { number: Number(m[1] + (m[2] ?? "")) } : m[3] ? { string: JSON.parse(m[3]) } : m[4] ?? m[5]);\n if (tokens.length > 256) fail2();\n }\n let pos = 0;\n const operators = { "==": ["eq", 1], "===": ["eq", 1], "!=": ["neq", 1], "!==": ["neq", 1], "<": ["lt", 2], "<=": ["lte", 2], ">": ["gt", 2], ">=": ["gte", 2], "+": ["add", 3], "-": ["sub", 3], "*": ["mul", 4], "/": ["div", 4] };\n const take = (t) => {\n if (tokens[pos++] !== t) fail2();\n };\n function parse(min = 0, depth = 0) {\n if (depth > 12) fail2();\n const t = tokens[pos++];\n let out;\n if (t && typeof t === "object") out = { const: Object.hasOwn(t, "number") ? t.number : t.string };\n else if (t === "true" || t === "false") out = { const: t === "true" };\n else if (t === "(") {\n out = parse(0, depth + 1);\n take(")");\n } else if (t === "-" || t === "+") {\n const arg = parse(5, depth + 1);\n out = t === "-" ? { op: "sub", args: [{ const: 0 }, arg] } : arg;\n } else if (typeof t === "string" && t.split(".").length === 2 && ["state", "data", "derived", "item"].includes(t.split(".")[0]) && validIdentifier(t.split(".")[1])) out = { ref: t };\n else if (["min", "max", "round", "abs"].includes(t)) {\n take("(");\n const args = [parse(0, depth + 1)];\n while (tokens[pos] === ",") {\n pos++;\n args.push(parse(0, depth + 1));\n if (args.length > 8) fail2();\n }\n take(")");\n out = { op: t, args };\n } else fail2();\n while (typeof tokens[pos] === "string" && Object.hasOwn(operators, tokens[pos]) && operators[tokens[pos]][1] >= min) {\n const [op, precedence] = operators[tokens[pos++]];\n out = { op, args: [out, parse(precedence + 1, depth + 1)] };\n }\n if (min === 0 && tokens[pos] === "?") {\n pos++;\n const yes = parse(0, depth + 1);\n take(":");\n out = { op: "if", args: [out, yes, parse(0, depth + 1)] };\n }\n return out;\n }\n const result = parse();\n if (pos !== tokens.length) fail2();\n return result;\n }\n function expandExpressions(doc2) {\n const expression = (e) => {\n if (!e || typeof e !== "object" || Array.isArray(e)) return e;\n if (Object.hasOwn(e, "expr")) {\n if (Object.keys(e).length !== 1) throw new Error("DSH UI: expr must be the only formula field");\n return compileExpression(e.expr);\n }\n if (Array.isArray(e.args)) e.args = e.args.map(expression);\n if (e.map?.fields) for (const k of Object.keys(e.map.fields)) e.map.fields[k] = expression(e.map.fields[k]);\n return e;\n };\n if (doc2.derived && typeof doc2.derived === "object") for (const k of Object.keys(doc2.derived)) doc2.derived[k] = expression(doc2.derived[k]);\n const walk = (nodes) => {\n if (!Array.isArray(nodes)) return;\n for (const node2 of nodes) {\n if (!node2 || typeof node2 !== "object") continue;\n for (const field of ["text", "value", "max", "rows"]) if (Object.hasOwn(node2, field)) node2[field] = expression(node2[field]);\n walk(node2.children);\n }\n };\n walk(doc2.nodes);\n return doc2;\n }\n\n // lib/protocol.js\n var LIMITS = Object.freeze({ bytes: 131072, nodes: 160, depth: 12, rows: 500, expressions: 128, steps: 4096 });\n var own = (o, k) => Object.hasOwn(o, k);\n var fail = (message) => {\n throw new Error(`DSH UI: ${message}`);\n };\n var object = (x) => x !== null && typeof x === "object" && !Array.isArray(x);\n var finite = (x) => typeof x === "number" && Number.isFinite(x);\n var scalar = (x) => typeof x === "string" || typeof x === "boolean" || finite(x);\n var text = (x, at) => {\n if (typeof x !== "string" || x.length > 8192) fail(`${at} must be a string of at most 8192 characters`);\n };\n function fields(value, allowed, at) {\n if (!object(value)) fail(`${at} must be an object`);\n for (const k of Object.keys(value)) if (!allowed.includes(k)) {\n const hint = at === "document" ? " Controls and visual components belong in nodes as registered typed nodes, not extra document fields." : "";\n fail(`unknown field ${at}.${k}; allowed fields at ${at}: ${allowed.join(", ")}.${hint}`);\n }\n }\n function safeJson(value, depth = 0, source = false) {\n if (depth > 48) fail("JSON nesting is too deep");\n if (value === null || typeof value === "boolean") return;\n if (typeof value === "string") {\n if (source) {\n if (value.length > SANDBOX_LIMITS.source) fail("canvas source exceeds 48 Ki characters");\n return;\n }\n return text(value, "value");\n }\n if (typeof value === "number") {\n if (!finite(value)) fail("numbers must be finite");\n return;\n }\n if (typeof value !== "object") fail("only JSON values are accepted");\n if (Array.isArray(value) && value.length > LIMITS.rows) fail("too many array items");\n for (const k of Object.keys(value)) {\n if (["__proto__", "prototype", "constructor"].includes(k)) fail("unsafe property name");\n safeJson(value[k], depth + 1, value.type === "sandbox" && ["html", "css", "script"].includes(k));\n }\n }\n function initialState(doc2) {\n return Object.fromEntries(Object.entries(doc2.state).map(([k, spec]) => [k, spec.default]));\n }\n function validateState(doc2, state2) {\n if (!object(state2) || Object.keys(state2).length !== Object.keys(doc2.state).length) fail("state keys do not match the document");\n const result = {};\n for (const [k, s] of Object.entries(doc2.state)) {\n if (!own(state2, k)) fail(`missing state.${k}`);\n const v = state2[k];\n if (s.type === "number") {\n if (!finite(v) || v < s.min || v > s.max) fail(`state.${k} is outside its numeric range`);\n const offset = (v - s.min) / s.step;\n if (Math.abs(offset - Math.round(offset)) > 1e-6) fail(`state.${k} does not match its step`);\n } else if (s.type === "json") {\n if (!object(v) && !Array.isArray(v)) fail(`state.${k} must be an array or object for type json`);\n safeJson(v);\n if (new TextEncoder().encode(JSON.stringify(v)).length > 16384) fail(`state.${k} JSON exceeds 16 KiB`);\n } else if (s.type === "string") text(v, `state.${k}`);\n else if (typeof v !== "boolean") fail(`state.${k} must be boolean`);\n if (s.options && !s.options.includes(v)) fail(`invalid option for state.${k}`);\n result[k] = v;\n }\n return result;\n }\n var ARITY = { add: [1, 8], sub: [2, 2], mul: [1, 8], div: [2, 2], min: [1, 8], max: [1, 8], round: [1, 1], abs: [1, 1], eq: [2, 2], neq: [2, 2], lt: [2, 2], lte: [2, 2], gt: [2, 2], gte: [2, 2], if: [3, 3] };\n function reference(doc2, ref) {\n if (typeof ref !== "string" || !["state", "data", "derived"].includes(ref.split(".")[0]) || ref.split(".").length !== 2 || !validIdentifier(ref.split(".")[1])) fail(`invalid reference ${JSON.stringify(ref)}; use state.key, data.key or derived.key with a letter/underscore identifier`);\n const [group, k] = ref.split(".");\n if (!own(doc2[group], k)) fail(`unknown reference ${ref}`);\n return [group, k];\n }\n function evaluate(doc2, state2) {\n const derived = {}, active = /* @__PURE__ */ new Set();\n let steps = 0, generatedRows = 0;\n const budget = () => {\n if (++steps > LIMITS.steps) fail("calculation budget exceeded");\n };\n const resolve = (ref) => {\n budget();\n const [group, k] = reference(doc2, ref);\n if (group !== "derived") return (group === "state" ? state2 : doc2.data)[k];\n if (own(derived, k)) return derived[k];\n if (active.has(k)) fail(`cyclic calculation ${k}`);\n active.add(k);\n const result2 = expression(doc2.derived[k]);\n active.delete(k);\n derived[k] = result2;\n return result2;\n };\n const expression = (e, item) => {\n budget();\n if (own(e, "map")) {\n const rows = resolve(e.map.source);\n if ((generatedRows += rows.length) > LIMITS.rows) fail("generated row limit exceeded");\n return rows.map((row) => Object.fromEntries(Object.entries(e.map.fields).map(([k, value]) => {\n const out2 = expression(value, row);\n if (!scalar(out2)) fail("generated cells must be scalar");\n return [k, out2];\n })));\n }\n if (own(e, "const")) return e.const;\n if (own(e, "ref")) {\n if (e.ref.startsWith("item.")) {\n const k = e.ref.slice(5);\n if (!item || !own(item, k) || !scalar(item[k])) fail("invalid item reference");\n return item[k];\n }\n return resolve(e.ref);\n }\n if (e.op === "if") {\n const condition = expression(e.args[0], item);\n if (typeof condition !== "boolean") fail("if condition must be boolean");\n return expression(e.args[condition ? 1 : 2], item);\n }\n const a = e.args.map((arg) => expression(arg, item));\n if (e.op === "eq") return a[0] === a[1];\n if (e.op === "neq") return a[0] !== a[1];\n if (!a.every(finite)) fail(`operator ${e.op} requires finite numbers`);\n let out;\n switch (e.op) {\n case "add":\n out = a.reduce((x, y) => x + y, 0);\n break;\n case "sub":\n out = a[0] - a[1];\n break;\n case "mul":\n out = a.reduce((x, y) => x * y, 1);\n break;\n case "div":\n if (a[1] === 0) fail("division by zero");\n out = a[0] / a[1];\n break;\n case "min":\n out = Math.min(...a);\n break;\n case "max":\n out = Math.max(...a);\n break;\n case "round":\n out = Math.round(a[0]);\n break;\n case "abs":\n out = Math.abs(a[0]);\n break;\n case "lt":\n return a[0] < a[1];\n case "lte":\n return a[0] <= a[1];\n case "gt":\n return a[0] > a[1];\n case "gte":\n return a[0] >= a[1];\n default:\n fail(`unsupported operator ${e.op}`);\n }\n if (!finite(out)) fail("non-finite calculation result");\n return out;\n };\n for (const k of Object.keys(doc2.derived)) resolve(`derived.${k}`);\n if (new TextEncoder().encode(JSON.stringify(derived)).length > LIMITS.bytes) fail("derived output exceeds 128 KiB");\n const result = { derived, resolveValue: (value) => {\n if (!object(value)) return value;\n return expression(value);\n } };\n checkViewValues(doc2, result);\n return result;\n }\n function checkViewValues(doc2, evaluated) {\n function walk(list) {\n for (const n of list) {\n if (n.type === "table" || n.type === "chart") {\n const rows = evaluated.resolveValue(n.rows);\n if (!Array.isArray(rows) || rows.length > LIMITS.rows || !rows.every(object)) fail("table/chart rows must reference an array of objects");\n if (n.type === "chart" && rows.some((r) => !own(r, n.labelKey) || !scalar(r[n.labelKey]) || !own(r, n.valueKey) || !finite(r[n.valueKey]))) fail("chart requires labels and finite numeric values");\n if (n.type === "chart" && n.xScale === "linear" && rows.some((r) => !finite(r[n.labelKey]))) fail("linear chart requires numeric x values");\n }\n if (n.type === "metric" && !scalar(evaluated.resolveValue(n.value))) fail(`node.${n.id}.value must resolve to a number, string or boolean; use table for rows or a canvas for structured data`);\n if (n.type === "progress") {\n const v = evaluated.resolveValue(n.value), max = evaluated.resolveValue(n.max);\n if (!finite(v) || !finite(max) || max <= 0 || v < 0 || v > max) fail("progress requires 0 <= value <= positive max");\n }\n if (n.children) walk(n.children);\n }\n }\n walk(doc2.nodes);\n }\n function validateDocument(input) {\n safeJson(input);\n const json = JSON.stringify(input);\n if (new TextEncoder().encode(json).length > LIMITS.bytes) fail("document exceeds 128 KiB");\n const doc2 = expandExpressions(JSON.parse(json));\n fields(doc2, ["version", "title", "fallback", "state", "data", "derived", "nodes", "actions", "presentation"], "document");\n if (doc2.presentation !== void 0) {\n fields(doc2.presentation, ["layout", "accent", "density"], "presentation");\n for (const [k, allowed] of Object.entries({ layout: UI_LAYOUTS, accent: UI_ACCENTS, density: ["comfortable", "compact"] }))\n if (doc2.presentation[k] !== void 0 && !allowed.includes(doc2.presentation[k])) fail(`unknown presentation ${k}`);\n }\n if (doc2.version !== 1) fail("unsupported protocol version");\n text(doc2.title, "title");\n text(doc2.fallback, "fallback");\n if (!doc2.title.trim() || !doc2.fallback.trim()) fail("title and fallback cannot be empty");\n for (const group of ["state", "data", "derived", "actions"]) {\n doc2[group] ??= {};\n if (!object(doc2[group]) || Object.keys(doc2[group]).length > 64) fail(`invalid ${group}`);\n for (const k of Object.keys(doc2[group])) if (!validIdentifier(k)) fail(`invalid key in ${group}: ${JSON.stringify(k)}; use 1..64 letters, numbers or underscores, starting with a letter/underscore (Chinese letters supported); no spaces, dots or hyphens. Put display labels in label/text`);\n }\n for (const [k, s] of Object.entries(doc2.state)) {\n fields(s, ["type", "default", "min", "max", "step", "options"], `state.${k}`);\n if (s.type === "string" && (Array.isArray(s.default) || object(s.default)) && !own(s, "options")) s.type = "json";\n if (!["number", "string", "boolean", "json"].includes(s.type)) fail(`unsupported state type ${k}; use number, string, boolean or json (arrays/objects)`);\n if (s.type === "json" && own(s, "options")) fail(`state.${k}: json state does not support select options; use scalar options or a canvas`);\n if (s.type === "number") {\n if (![s.min, s.max, s.step].every(finite) || s.min >= s.max || s.step <= 0) fail(`invalid numeric limits for ${k}`);\n if ((s.max - s.min) / s.step > 1e9) fail(`numeric step too small for ${k}`);\n } else if (["min", "max", "step"].some((p) => own(s, p))) fail(`numeric limits on non-number ${k}`);\n if (s.options && (!Array.isArray(s.options) || !s.options.length || s.options.length > 64 || !s.options.every(scalar))) fail(`invalid options for ${k}`);\n }\n const defaults = validateState(doc2, initialState(doc2));\n let expressions = 0;\n for (const [k, spec] of Object.entries(doc2.state))\n for (const option of spec.options ?? []) validateState(doc2, { ...defaults, [k]: option });\n function validateExpression(e, depth = 0, itemRows) {\n if (++expressions > LIMITS.expressions || depth > LIMITS.depth) fail("expression limit exceeded");\n if (!object(e)) fail("expression must be an object");\n if (own(e, "map")) {\n if (depth !== 0) fail("map is only allowed at the root of a derived value");\n fields(e, ["map"], "expression");\n fields(e.map, ["source", "fields"], "map");\n if (typeof e.map.source !== "string" || !e.map.source.startsWith("data.")) fail(\'map source must reference static data using a string such as "data.samples"; put object rows in document.data.samples, not inline in map.source\');\n const [, k] = reference(doc2, e.map.source), rows = doc2.data[k];\n if (!Array.isArray(rows) || rows.length > LIMITS.rows || !rows.every(object)) fail("map source must be object rows");\n if (!object(e.map.fields) || !Object.keys(e.map.fields).length || Object.keys(e.map.fields).length > 16) fail("map requires 1..16 fields");\n for (const [k2, value2] of Object.entries(e.map.fields)) {\n if (!validIdentifier(k2)) fail(`invalid map field ${JSON.stringify(k2).slice(0, 100)}; use a letter/underscore identifier such as powerW or \\u529F\\u7387, without spaces, dots or hyphens`);\n validateExpression(value2, depth + 1, rows);\n }\n return;\n }\n if (own(e, "const")) {\n fields(e, ["const"], "expression");\n if (!scalar(e.const)) fail("constant must be scalar");\n return;\n }\n if (own(e, "ref")) {\n fields(e, ["ref"], "expression");\n if (typeof e.ref === "string" && e.ref.startsWith("item.")) {\n const k = e.ref.slice(5);\n if (!itemRows || !validIdentifier(k) || itemRows.some((row) => !own(row, k) || !scalar(row[k]))) fail("invalid or unscoped item reference");\n } else reference(doc2, e.ref);\n return;\n }\n fields(e, ["op", "args"], "expression");\n const arity = ARITY[e.op];\n if (!arity || !Array.isArray(e.args) || e.args.length < arity[0] || e.args.length > arity[1]) fail("invalid operator or argument count");\n e.args.forEach((a) => validateExpression(a, depth + 1, itemRows));\n }\n Object.values(doc2.derived).forEach((e) => validateExpression(e));\n const visited = /* @__PURE__ */ new Set(), active = /* @__PURE__ */ new Set();\n function visit(k) {\n if (active.has(k)) fail(`cyclic calculation ${k}`);\n if (visited.has(k)) return;\n active.add(k);\n function walk(e) {\n if (e.ref?.startsWith("derived.")) visit(e.ref.split(".")[1]);\n for (const a of e.args ?? []) walk(a);\n for (const value2 of Object.values(e.map?.fields ?? {})) walk(value2);\n }\n walk(doc2.derived[k]);\n active.delete(k);\n visited.add(k);\n }\n Object.keys(doc2.derived).forEach(visit);\n for (const [k, a] of Object.entries(doc2.actions)) {\n fields(a, ["type", "intent", "stateKeys"], `actions.${k}`);\n if (a.type !== "agent.followup") fail("only agent.followup actions are supported");\n text(a.intent, "action intent");\n if (!a.intent.trim() || !Array.isArray(a.stateKeys) || a.stateKeys.length > 64 || new Set(a.stateKeys).size !== a.stateKeys.length || a.stateKeys.some((s) => !own(doc2.state, s))) fail("invalid action stateKeys");\n }\n const ids = /* @__PURE__ */ new Set();\n let count2 = 0;\n const value = (v, at) => {\n if (object(v)) {\n if (own(v, "map")) fail("map belongs in derived");\n validateExpression(v);\n } else if (!scalar(v)) fail(`invalid value at ${at}`);\n };\n function nodes(list, depth = 0) {\n if (!Array.isArray(list) || depth > LIMITS.depth) fail("invalid node children or depth");\n for (const n of list) {\n if (++count2 > LIMITS.nodes) fail("too many nodes");\n if (!object(n) || !validIdentifier(n.id) || ids.has(n.id)) fail("node ids must be unique identifiers");\n ids.add(n.id);\n if (!Object.hasOwn(COMPONENTS, n.type)) fail("unsupported component " + n.type);\n if (["table", "chart"].includes(n.type) && typeof n.rows === "string" && /^(data|derived)\\./.test(n.rows)) n.rows = { ref: n.rows };\n switch (n.type) {\n case "sandbox": {\n text(n.title, "canvas title");\n text(n.fallback, "canvas fallback");\n if (!n.title.trim() || !n.fallback.trim() || typeof n.html !== "string" || !n.html.trim()) fail("canvas requires title, HTML and fallback");\n for (const field of ["html", "css", "script"]) if (n[field] !== void 0 && (typeof n[field] !== "string" || n[field].length > SANDBOX_LIMITS.source)) fail("canvas source exceeds 48 Ki characters");\n if (n.height !== void 0 && (!Number.isInteger(n.height) || n.height < 160 || n.height > SANDBOX_LIMITS.height)) fail("canvas height must be 160..1000");\n for (const [field, group] of [["stateKeys", "state"], ["dataKeys", "data"], ["derivedKeys", "derived"]]) if (n[field] !== void 0 && (!Array.isArray(n[field]) || n[field].length > 64 || new Set(n[field]).size !== n[field].length || n[field].some((k) => !own(doc2[group], k)))) fail("invalid canvas " + field);\n break;\n }\n case "row":\n case "column":\n break;\n case "card":\n if (n.title !== void 0) text(n.title, "card title");\n if (n.surface !== void 0 && !UI_SURFACES.includes(n.surface)) fail("unknown card surface");\n break;\n case "details":\n text(n.title, "details title");\n if (n.open !== void 0 && typeof n.open !== "boolean") fail("details open must be boolean");\n break;\n case "badge":\n value(n.text, "badge text");\n break;\n case "progress":\n text(n.label, "progress label");\n value(n.value, "progress value");\n value(n.max, "progress max");\n if (n.unit !== void 0) text(n.unit, "progress unit");\n break;\n case "steps": {\n if (!Array.isArray(n.items) || !n.items.length || n.items.length > 12) fail("steps require 1..12 items");\n for (const item of n.items) {\n fields(item, ["title", "description", "status"], "step");\n text(item.title, "step title");\n if (item.description !== void 0) text(item.description, "step description");\n if (!["pending", "active", "done", "error"].includes(item.status)) fail("unknown step status");\n }\n break;\n }\n case "heading":\n case "text":\n value(n.text, "text");\n break;\n case "metric":\n text(n.label, "metric label");\n value(n.value, "metric value");\n if (n.unit !== void 0) text(n.unit, "unit");\n if (n.decimals !== void 0 && (!Number.isInteger(n.decimals) || n.decimals < 0 || n.decimals > 6)) fail("invalid decimals");\n break;\n case "input":\n case "slider":\n case "select":\n case "toggle": {\n text(n.label, "control label");\n if (typeof n.bind !== "string" || !n.bind.startsWith("state.")) fail("controls must bind state");\n const [, k] = reference(doc2, n.bind), spec = doc2.state[k];\n if (n.type === "slider" && spec.type !== "number") fail("slider requires numeric state");\n if (n.type === "toggle" && spec.type !== "boolean") fail("toggle requires boolean state");\n if (["input", "select"].includes(n.type) && spec.type === "json") fail(`node.${n.id}: structured state requires a sandbox with DSHUI.setState; use separate boolean states and toggle nodes for a native checklist`);\n if (n.type === "input" && spec.type === "boolean") fail("use toggle for boolean state");\n if (n.type === "select" && !spec.options) fail("select requires options");\n break;\n }\n case "button":\n text(n.text, "button text");\n if (!own(doc2.actions, n.action)) fail("unknown action");\n break;\n case "table": {\n if (n.label !== void 0) text(n.label, "table label");\n if (!Array.isArray(n.rows)) value(n.rows, "table rows");\n if (!Array.isArray(n.columns) || !n.columns.length || n.columns.length > 16) fail("invalid table columns");\n const cols = /* @__PURE__ */ new Set();\n for (const c of n.columns) {\n fields(c, ["key", "label", "unit"], "column");\n if (!validIdentifier(c.key) || cols.has(c.key)) fail("invalid or duplicate column key");\n cols.add(c.key);\n text(c.label, "column label");\n if (c.unit !== void 0) text(c.unit, "column unit");\n }\n break;\n }\n case "chart":\n if (!Array.isArray(n.rows)) value(n.rows, "chart rows");\n if (!["bar", "line"].includes(n.kind) || !validIdentifier(n.labelKey) || !validIdentifier(n.valueKey)) fail("invalid chart");\n text(n.label, "chart label");\n if (n.unit !== void 0) text(n.unit, "chart unit");\n if (n.xScale !== void 0 && (!["category", "linear"].includes(n.xScale) || n.xScale === "linear" && n.kind !== "line")) fail("invalid xScale");\n break;\n default:\n fail(`unsupported component ${n.type}`);\n }\n if (["heading", "text", "card", "metric", "button", "badge", "progress", "details"].includes(n.type)) {\n if (n.icon !== void 0 && !UI_ICONS.includes(n.icon)) fail("unknown UI icon");\n if (n.type !== "button") {\n if (n.tone !== void 0 && !UI_TONES.includes(n.tone)) fail("unknown UI tone");\n }\n }\n fields(n, componentFields(n.type), `node.${n.id}`);\n if (["row", "column", "card", "details"].includes(n.type)) nodes(n.children, depth + 1);\n }\n }\n nodes(doc2.nodes);\n if (!count2) fail("at least one node is required");\n evaluate(doc2, defaults);\n return doc2;\n }\n\n // src/export-runtime.js\n var payload = JSON.parse(document.getElementById("dsh-ui-export").textContent);\n var doc = validateDocument(payload.document);\n var node = doc.nodes.flatMap(function flatten(n) {\n return [n, ...(n.children ?? []).flatMap(flatten)];\n }).find((n) => n.id === payload.nodeId && n.type === "sandbox");\n if (!node) throw Error("\\u5BFC\\u51FA\\u7684\\u753B\\u5E03\\u4E0D\\u5B58\\u5728");\n var state = validateState(doc, payload.state);\n var connected = false;\n var start = Date.now();\n var count = 0;\n var token = () => Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) => b.toString(16).padStart(2, "0")).join("");\n var channel = token();\n var nonce = payload.nonce;\n var frame = document.createElement("iframe");\n frame.title = node.title;\n frame.sandbox = "allow-scripts";\n frame.referrerPolicy = "no-referrer";\n frame.style.cssText = "display:block;width:100%;height:" + (node.height ?? 420) + "px;border:0";\n var status = document.getElementById("status");\n var publish = () => {\n try {\n frame.contentWindow.postMessage({ dshCanvas: 1, channel, type: "snapshot", payload: { ...canvasSnapshot(node, state, doc.data, evaluate(doc, state).derived, false, payload.theme), visible: !document.hidden } }, "*");\n } catch (e) {\n status.textContent = "\\u8BA1\\u7B97\\u5931\\u8D25\\uFF1A" + e.message;\n }\n };\n addEventListener("message", (event) => {\n const m = event.data;\n if (event.source !== frame.contentWindow || m?.channel !== channel || m.dshCanvas !== 1) return;\n if (Date.now() - start > 1e3) {\n start = Date.now();\n count = 0;\n }\n if (++count > SANDBOX_LIMITS.rate) return;\n if (m.type === "ready") {\n connected = true;\n publish();\n } else if (m.type === "patch" && connected) {\n try {\n const next = validateState(doc, { ...state, ...canvasPatch(m.payload, node) });\n evaluate(doc, next);\n state = next;\n status.textContent = "\\u672C\\u5730\\u53C2\\u6570\\u5DF2\\u66F4\\u65B0\\uFF1B\\u5237\\u65B0\\u6587\\u4EF6\\u4F1A\\u56DE\\u5230\\u5BFC\\u51FA\\u65F6\\u7684\\u53C2\\u6570\\u3002";\n } catch (e) {\n status.textContent = "\\u53C2\\u6570\\u65E0\\u6548\\uFF1A" + e.message;\n }\n publish();\n } else if (m.type === "height" && Number.isFinite(m.payload) && m.payload >= 0) frame.style.height = Math.max(32, Math.min(1e3, Math.ceil(m.payload))) + "px";\n else if (m.type === "error") status.textContent = "\\u753B\\u5E03\\u8FD0\\u884C\\u5F02\\u5E38\\uFF1A" + String(m.payload).slice(0, 1e3);\n });\n document.addEventListener("visibilitychange", () => {\n if (connected) publish();\n });\n document.getElementById("surface").append(frame);\n frame.srcdoc = sandboxDocument(node, channel, nonce);\n})();\n';
|
|
22736
22795
|
|
|
22737
22796
|
// lib/canvas-export.js
|
|
22738
22797
|
function standaloneCanvas(document2, node, state, theme = {}) {
|
|
@@ -22743,18 +22802,64 @@ function standaloneCanvas(document2, node, state, theme = {}) {
|
|
|
22743
22802
|
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta http-equiv="Content-Security-Policy" content="default-src 'none';script-src 'nonce-${token}';style-src 'unsafe-inline';frame-src 'self';base-uri 'none';form-action 'none'"><title>${escape(node.title)}</title><style>body{margin:0;padding:24px;background:${theme.scheme === "dark" ? "#161b23" : "#f4f6fa"};color:${theme.scheme === "dark" ? "#e6edf6" : "#182537"};font:14px/1.6 system-ui,sans-serif}main{max-width:1100px;margin:auto}h1{font-size:22px}p{overflow-wrap:anywhere}#surface{background:${theme.scheme === "dark" ? "#161b23" : "#fff"};border-radius:12px;overflow:hidden}#status{min-height:1.6em}</style></head><body><main><h1>${escape(node.title)}</h1><p>DSH Motion UI \xB7 \u72EC\u7ACB\u526F\u672C\u3002\u5305\u542B\u5BFC\u51FA\u65F6\u53C2\u6570\uFF0C\u672C\u5730\u4EA4\u4E92\u4E0D\u4F1A\u4FDD\u5B58\u5230 DSH\uFF0C\u4E5F\u4E0D\u4F1A\u8C03\u7528 Agent\u3002</p><div id="surface"></div><p id="status" role="status"></p><details><summary>\u6587\u5B57\u8BF4\u660E</summary><p>${escape(node.fallback)}</p></details></main><script type="application/json" id="dsh-ui-export">${json}<\/script><script nonce="${token}">${EXPORT_RUNTIME.replace(/<\/script/gi, "<\\/script")}<\/script></body></html>`;
|
|
22744
22803
|
}
|
|
22745
22804
|
|
|
22805
|
+
// src/view-settings.js
|
|
22806
|
+
var import_react4 = require("react");
|
|
22807
|
+
var scope;
|
|
22808
|
+
function configureViewSettings(value) {
|
|
22809
|
+
scope = value;
|
|
22810
|
+
}
|
|
22811
|
+
var subscribe = (fn) => scope?.subscribe(fn) ?? (() => {
|
|
22812
|
+
});
|
|
22813
|
+
var snapshot = () => scope?.getSnapshot()?.value?.showDetails === true;
|
|
22814
|
+
function useViewDetails() {
|
|
22815
|
+
return (0, import_react4.useSyncExternalStore)(subscribe, snapshot, () => false);
|
|
22816
|
+
}
|
|
22817
|
+
|
|
22818
|
+
// src/action-menu.js
|
|
22819
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
22820
|
+
function ActionMenu({ label, children }) {
|
|
22821
|
+
const [open, setOpen] = (0, import_react5.useState)(false), root = (0, import_react5.useRef)(null), button = (0, import_react5.useRef)(null);
|
|
22822
|
+
(0, import_react5.useEffect)(() => {
|
|
22823
|
+
if (!open) return;
|
|
22824
|
+
const outside = (e) => {
|
|
22825
|
+
if (!root.current?.contains(e.target)) setOpen(false);
|
|
22826
|
+
};
|
|
22827
|
+
const escape = (e) => {
|
|
22828
|
+
if (e.key === "Escape") {
|
|
22829
|
+
setOpen(false);
|
|
22830
|
+
button.current?.focus();
|
|
22831
|
+
}
|
|
22832
|
+
};
|
|
22833
|
+
document.addEventListener("pointerdown", outside);
|
|
22834
|
+
document.addEventListener("keydown", escape);
|
|
22835
|
+
return () => {
|
|
22836
|
+
document.removeEventListener("pointerdown", outside);
|
|
22837
|
+
document.removeEventListener("keydown", escape);
|
|
22838
|
+
};
|
|
22839
|
+
}, [open]);
|
|
22840
|
+
return import_react5.default.createElement(
|
|
22841
|
+
"div",
|
|
22842
|
+
{ className: "dgui-action-menu", ref: root },
|
|
22843
|
+
import_react5.default.createElement("button", { ref: button, type: "button", className: "dgui-menu-trigger", "aria-label": label, "aria-expanded": open, onClick: () => setOpen(!open) }, "\u22EF"),
|
|
22844
|
+
open && import_react5.default.createElement("div", { className: "dgui-menu-content", "aria-label": label, onClick: (e) => {
|
|
22845
|
+
if (e.target.closest("button")) setOpen(false);
|
|
22846
|
+
} }, children)
|
|
22847
|
+
);
|
|
22848
|
+
}
|
|
22849
|
+
|
|
22746
22850
|
// src/sandbox.js
|
|
22747
|
-
var h3 =
|
|
22851
|
+
var h3 = import_react6.default.createElement;
|
|
22748
22852
|
var randomToken = () => Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
22749
22853
|
function Sandbox({ node, document: doc, state, data, derived, disabled, preview, update, onAudit }) {
|
|
22750
|
-
const
|
|
22751
|
-
const
|
|
22752
|
-
const [
|
|
22753
|
-
const [
|
|
22754
|
-
const [
|
|
22854
|
+
const showDetails = useViewDetails();
|
|
22855
|
+
const frame = (0, import_react6.useRef)(null), latest = (0, import_react6.useRef)(null), connected = (0, import_react6.useRef)(false), loads = (0, import_react6.useRef)(0), visible = (0, import_react6.useRef)(true), errorKind = (0, import_react6.useRef)("");
|
|
22856
|
+
const [error, setError] = (0, import_react6.useState)(""), [stopped, setStopped] = (0, import_react6.useState)(false), [generation, setGeneration] = (0, import_react6.useState)(0);
|
|
22857
|
+
const [height, setHeight] = (0, import_react6.useState)(node.height ?? 420);
|
|
22858
|
+
const [token, setToken] = (0, import_react6.useState)(0);
|
|
22859
|
+
const [mounted, setMounted] = (0, import_react6.useState)(false);
|
|
22755
22860
|
const sourceKey = JSON.stringify(node);
|
|
22756
|
-
const config = (0,
|
|
22757
|
-
const srcDoc = (0,
|
|
22861
|
+
const config = (0, import_react6.useMemo)(() => ({ channel: randomToken(), nonce: randomToken() }), [sourceKey, generation]);
|
|
22862
|
+
const srcDoc = (0, import_react6.useMemo)(() => sandboxDocument(node, config.channel, config.nonce), [sourceKey, config]);
|
|
22758
22863
|
latest.current = { node, state, data, derived, disabled, update, onAudit };
|
|
22759
22864
|
const publish = () => {
|
|
22760
22865
|
const el = frame.current, current2 = latest.current;
|
|
@@ -22764,7 +22869,7 @@ function Sandbox({ node, document: doc, state, data, derived, disabled, preview,
|
|
|
22764
22869
|
theme.scheme = document.body.hasAttribute("data-ds-dark-theme") || el.closest("[data-preview-theme=dark]") ? "dark" : "light";
|
|
22765
22870
|
el.contentWindow?.postMessage({ dshCanvas: 1, channel: config.channel, type: "snapshot", payload: { ...canvasSnapshot(current2.node, current2.state, current2.data, current2.derived, current2.disabled, theme), visible: visible.current && !document.hidden } }, "*");
|
|
22766
22871
|
};
|
|
22767
|
-
(0,
|
|
22872
|
+
(0, import_react6.useEffect)(() => {
|
|
22768
22873
|
if (preview || stopped) return;
|
|
22769
22874
|
connected.current = false;
|
|
22770
22875
|
loads.current = 0;
|
|
@@ -22792,7 +22897,7 @@ function Sandbox({ node, document: doc, state, data, derived, disabled, preview,
|
|
|
22792
22897
|
setToken((t) => t + 1);
|
|
22793
22898
|
} else if (m.type === "mounted" && connected.current) setMounted(true);
|
|
22794
22899
|
else if (m.type === "audit" && connected.current) latest.current.onAudit?.(node.id, m.payload?.issues, m.payload?.coverage);
|
|
22795
|
-
else if (m.type === "height" && connected.current && Number.isFinite(m.payload) && m.payload
|
|
22900
|
+
else if (m.type === "height" && connected.current && Number.isFinite(m.payload) && m.payload >= 0) setHeight(Math.max(32, Math.min(SANDBOX_LIMITS.height, Math.ceil(m.payload))));
|
|
22796
22901
|
else if (m.type === "error") {
|
|
22797
22902
|
errorKind.current = "runtime";
|
|
22798
22903
|
setError(typeof m.payload === "string" ? m.payload.slice(0, 1e3) : "\u753B\u5E03\u8FD0\u884C\u5F02\u5E38");
|
|
@@ -22838,7 +22943,7 @@ function Sandbox({ node, document: doc, state, data, derived, disabled, preview,
|
|
|
22838
22943
|
intersection.disconnect();
|
|
22839
22944
|
};
|
|
22840
22945
|
}, [config, preview, stopped]);
|
|
22841
|
-
(0,
|
|
22946
|
+
(0, import_react6.useEffect)(() => {
|
|
22842
22947
|
publish();
|
|
22843
22948
|
}, [state, data, derived, disabled, config, token]);
|
|
22844
22949
|
const inactive = preview || stopped;
|
|
@@ -22864,6 +22969,13 @@ function Sandbox({ node, document: doc, state, data, derived, disabled, preview,
|
|
|
22864
22969
|
return h3(
|
|
22865
22970
|
"section",
|
|
22866
22971
|
{ className: "dgui-canvas", "data-ui-node": node.id, "data-canvas-phase": inactive ? stopped ? "stopped" : "preview" : error ? "error" : mounted ? "ready" : "loading", "aria-label": node.title },
|
|
22972
|
+
!preview && !showDetails && h3(
|
|
22973
|
+
ActionMenu,
|
|
22974
|
+
{ label: `${node.title}\u64CD\u4F5C` },
|
|
22975
|
+
h3("button", { type: "button", disabled: disabled || !doc || stopped, onClick: download }, "\u5BFC\u51FA\u72EC\u7ACB HTML"),
|
|
22976
|
+
h3("button", { type: "button", disabled, onClick: restart }, stopped ? "\u6062\u590D\u4EA4\u4E92" : "\u91CD\u7F6E\u753B\u5E03"),
|
|
22977
|
+
!stopped && h3("button", { type: "button", onClick: () => setStopped(true) }, "\u505C\u6B62\u753B\u5E03")
|
|
22978
|
+
),
|
|
22867
22979
|
preview ? h3(CanvasPreview, { node }) : inactive ? h3("div", { className: "dgui-canvas-placeholder", role: "status" }, h3("p", null, "\u753B\u5E03\u5DF2\u505C\u6B62\u3002"), stopped && h3("button", { type: "button", className: "dgui-secondary", onClick: restart }, "\u6062\u590D\u4EA4\u4E92")) : h3(
|
|
22868
22980
|
"div",
|
|
22869
22981
|
{ className: "dgui-canvas-stage", style: { minHeight: mounted || error ? void 0 : Math.min(height, 420) } },
|
|
@@ -22876,7 +22988,8 @@ function Sandbox({ node, document: doc, state, data, derived, disabled, preview,
|
|
|
22876
22988
|
}, style: { width: "100%", height, border: 0, display: "block", visibility: mounted || error ? "visible" : "hidden" }, allow: "camera 'none'; microphone 'none'; geolocation 'none'; clipboard-read 'none'; clipboard-write 'none'" })
|
|
22877
22989
|
),
|
|
22878
22990
|
error && h3("div", { className: "dgui-canvas-issue", role: "alert" }, h3("strong", null, "\u4EA4\u4E92\u9047\u5230\u95EE\u9898"), h3("p", null, "\u53EF\u4EE5\u91CD\u65B0\u8F7D\u5165\uFF1B\u5DF2\u4FDD\u5B58\u7684\u53C2\u6570\u4F1A\u4FDD\u7559\u3002"), h3("div", { className: "dgui-recovery" }, h3("button", { type: "button", className: "dgui-secondary", onClick: restart }, "\u91CD\u7F6E\u753B\u5E03"), !stopped && h3("button", { type: "button", className: "dgui-secondary", onClick: () => setStopped(true) }, "\u505C\u6B62\u753B\u5E03")), h3("details", null, h3("summary", null, "\u9519\u8BEF\u8BE6\u60C5"), h3("pre", null, error))),
|
|
22879
|
-
h3(
|
|
22991
|
+
error && !showDetails && h3("p", { className: "dgui-error" }, node.fallback),
|
|
22992
|
+
showDetails && h3(
|
|
22880
22993
|
"details",
|
|
22881
22994
|
{ className: "dgui-canvas-options" },
|
|
22882
22995
|
h3("summary", null, "\u8BF4\u660E\u4E0E\u64CD\u4F5C"),
|
|
@@ -22888,13 +23001,13 @@ function Sandbox({ node, document: doc, state, data, derived, disabled, preview,
|
|
|
22888
23001
|
}
|
|
22889
23002
|
|
|
22890
23003
|
// lib/build-info.js
|
|
22891
|
-
var BUILD_INFO = Object.freeze({ "version": "0.5.
|
|
23004
|
+
var BUILD_INFO = Object.freeze({ "version": "0.5.4", "id": "0.5.4+92e88973eabc", "sourceHash": "92e88973eabc736e169fbb03366db183ca5cd1fbbe0e3a7e44e5742da708d96e" });
|
|
22892
23005
|
|
|
22893
23006
|
// lib/refinement.js
|
|
22894
23007
|
var AUDIT_MESSAGES = Object.freeze({ overflow: "\u5185\u5BB9\u8D85\u51FA\u89C6\u53E3\u5BBD\u5EA6", smallText: "\u6587\u5B57\u5B9E\u9645\u663E\u793A\u5C3A\u5BF8\u5C0F\u4E8E 12px", contrast: "\u6587\u5B57\u4E0E\u80CC\u666F\u5BF9\u6BD4\u5EA6\u504F\u4F4E", missingLabel: "\u4EA4\u4E92\u63A7\u4EF6\u7F3A\u5C11\u53EF\u8BBF\u95EE\u540D\u79F0", runtimeError: "\u753B\u5E03\u62A5\u544A\u8FD0\u884C\u5F02\u5E38" });
|
|
22895
23008
|
|
|
22896
23009
|
// src/current-document.js
|
|
22897
|
-
var
|
|
23010
|
+
var import_react7 = require("react");
|
|
22898
23011
|
var current = /* @__PURE__ */ new Map();
|
|
22899
23012
|
var listeners2 = /* @__PURE__ */ new Set();
|
|
22900
23013
|
function publishDocument(raw) {
|
|
@@ -22905,9 +23018,9 @@ function publishDocument(raw) {
|
|
|
22905
23018
|
listeners2.forEach((fn) => fn());
|
|
22906
23019
|
}
|
|
22907
23020
|
function useCurrentDocument(raw, sessionId) {
|
|
22908
|
-
const [, wake] = (0,
|
|
22909
|
-
const [attempt, retry] = (0,
|
|
22910
|
-
(0,
|
|
23021
|
+
const [, wake] = (0, import_react7.useState)(0);
|
|
23022
|
+
const [attempt, retry] = (0, import_react7.useState)(0), [load, setLoad] = (0, import_react7.useState)({ status: "loading" });
|
|
23023
|
+
(0, import_react7.useEffect)(() => {
|
|
22911
23024
|
if (!raw.documentId || !sessionId) return;
|
|
22912
23025
|
const notify = () => wake((v) => v + 1);
|
|
22913
23026
|
listeners2.add(notify);
|
|
@@ -22933,10 +23046,10 @@ function useCurrentDocument(raw, sessionId) {
|
|
|
22933
23046
|
}
|
|
22934
23047
|
|
|
22935
23048
|
// src/history-view.js
|
|
22936
|
-
var
|
|
22937
|
-
var h4 =
|
|
23049
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
23050
|
+
var h4 = import_react8.default.createElement;
|
|
22938
23051
|
function HistoryView({ record, sessionId }) {
|
|
22939
|
-
const [versions, setVersions] = (0,
|
|
23052
|
+
const [versions, setVersions] = (0, import_react8.useState)(null), [error, setError] = (0, import_react8.useState)(""), [busy, setBusy] = (0, import_react8.useState)(false), [preview, setPreview] = (0, import_react8.useState)(null);
|
|
22940
23053
|
const url = "/api/plugins/dsh-generative-ui/history?" + new URLSearchParams({ documentId: record.documentId, sessionId });
|
|
22941
23054
|
async function request2(options) {
|
|
22942
23055
|
const r = await fetch(url, { credentials: "same-origin", ...options }), value = await r.json();
|
|
@@ -22954,11 +23067,11 @@ function HistoryView({ record, sessionId }) {
|
|
|
22954
23067
|
setBusy(false);
|
|
22955
23068
|
}
|
|
22956
23069
|
}
|
|
22957
|
-
async function restore(
|
|
23070
|
+
async function restore(revision2) {
|
|
22958
23071
|
setBusy(true);
|
|
22959
23072
|
setError("");
|
|
22960
23073
|
try {
|
|
22961
|
-
const next = await request2({ method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ documentRevision: record.documentRevision ?? 0, targetRevision:
|
|
23074
|
+
const next = await request2({ method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ documentRevision: record.documentRevision ?? 0, targetRevision: revision2 }) });
|
|
22962
23075
|
publishDocument(next);
|
|
22963
23076
|
setPreview(null);
|
|
22964
23077
|
setVersions(await request2());
|
|
@@ -22968,11 +23081,11 @@ function HistoryView({ record, sessionId }) {
|
|
|
22968
23081
|
setBusy(false);
|
|
22969
23082
|
}
|
|
22970
23083
|
}
|
|
22971
|
-
async function inspect(
|
|
23084
|
+
async function inspect(revision2) {
|
|
22972
23085
|
setBusy(true);
|
|
22973
23086
|
setError("");
|
|
22974
23087
|
try {
|
|
22975
|
-
const r = await fetch(url + "&revision=" +
|
|
23088
|
+
const r = await fetch(url + "&revision=" + revision2, { credentials: "same-origin" }), v = await r.json();
|
|
22976
23089
|
if (!r.ok) throw new Error(v.error ?? "\u5386\u53F2\u8BFB\u53D6\u5931\u8D25");
|
|
22977
23090
|
setPreview({ ...v, document: validateDocument(v.document) });
|
|
22978
23091
|
} catch (e) {
|
|
@@ -23003,16 +23116,20 @@ function HistoryView({ record, sessionId }) {
|
|
|
23003
23116
|
}
|
|
23004
23117
|
|
|
23005
23118
|
// src/presentation.js
|
|
23006
|
-
var
|
|
23119
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
23007
23120
|
var import_react_dom = __toESM(require_react_dom(), 1);
|
|
23008
23121
|
|
|
23009
23122
|
// src/presentation-store.js
|
|
23010
|
-
var
|
|
23123
|
+
var import_react9 = require("react");
|
|
23011
23124
|
var records = /* @__PURE__ */ new Map();
|
|
23012
23125
|
var listeners3 = /* @__PURE__ */ new Set();
|
|
23013
23126
|
var locations = /* @__PURE__ */ new Map();
|
|
23014
23127
|
var opener;
|
|
23015
|
-
var
|
|
23128
|
+
var revision = 0;
|
|
23129
|
+
var emit = () => {
|
|
23130
|
+
revision++;
|
|
23131
|
+
listeners3.forEach((fn) => fn());
|
|
23132
|
+
};
|
|
23016
23133
|
var notifyUi = emit;
|
|
23017
23134
|
function rememberUi(raw, sessionId, sendPrompt) {
|
|
23018
23135
|
if (raw?.version !== 1 || raw.sessionId !== sessionId) return;
|
|
@@ -23028,8 +23145,7 @@ var subscribeUi = (fn) => {
|
|
|
23028
23145
|
return () => listeners3.delete(fn);
|
|
23029
23146
|
};
|
|
23030
23147
|
function useUiRegistry() {
|
|
23031
|
-
|
|
23032
|
-
(0, import_react7.useEffect)(() => subscribeUi(() => wake((v) => v + 1)), []);
|
|
23148
|
+
(0, import_react9.useSyncExternalStore)(subscribeUi, () => revision, () => 0);
|
|
23033
23149
|
return uiRecords();
|
|
23034
23150
|
}
|
|
23035
23151
|
function setPanelOpener(fn) {
|
|
@@ -23057,10 +23173,10 @@ function removeMarkerLocation(id, host) {
|
|
|
23057
23173
|
}
|
|
23058
23174
|
}
|
|
23059
23175
|
var markerLocation = (id) => locations.get(id);
|
|
23060
|
-
function usePresentation(
|
|
23061
|
-
const [, wake] = (0,
|
|
23062
|
-
(0,
|
|
23063
|
-
return
|
|
23176
|
+
function usePresentation(scope2) {
|
|
23177
|
+
const [, wake] = (0, import_react9.useState)(0);
|
|
23178
|
+
(0, import_react9.useEffect)(() => scope2?.subscribe(() => wake((v) => v + 1)), [scope2]);
|
|
23179
|
+
return scope2?.getSnapshot().value?.displayMode ?? "tail";
|
|
23064
23180
|
}
|
|
23065
23181
|
|
|
23066
23182
|
// src/markers.js
|
|
@@ -23120,16 +23236,59 @@ function startUiMarkers(root, sessionId) {
|
|
|
23120
23236
|
};
|
|
23121
23237
|
}
|
|
23122
23238
|
|
|
23239
|
+
// src/presentation-owner.js
|
|
23240
|
+
var import_react10 = require("react");
|
|
23241
|
+
var roots = /* @__PURE__ */ new WeakMap();
|
|
23242
|
+
function usePresentationOwner(anchor, documentId, sessionId) {
|
|
23243
|
+
const [owner, setOwner] = (0, import_react10.useState)(false);
|
|
23244
|
+
(0, import_react10.useEffect)(() => {
|
|
23245
|
+
const element = anchor.current;
|
|
23246
|
+
if (!element) return;
|
|
23247
|
+
const root = element.closest("[data-conversation-scroll]") ?? element.parentElement;
|
|
23248
|
+
if (!root) return;
|
|
23249
|
+
let documents = roots.get(root);
|
|
23250
|
+
if (!documents) {
|
|
23251
|
+
documents = /* @__PURE__ */ new Map();
|
|
23252
|
+
roots.set(root, documents);
|
|
23253
|
+
}
|
|
23254
|
+
const key2 = sessionId + ":" + documentId;
|
|
23255
|
+
let entries = documents.get(key2);
|
|
23256
|
+
if (!entries) {
|
|
23257
|
+
entries = /* @__PURE__ */ new Set();
|
|
23258
|
+
documents.set(key2, entries);
|
|
23259
|
+
}
|
|
23260
|
+
const entry = { element, update: setOwner };
|
|
23261
|
+
entries.add(entry);
|
|
23262
|
+
const elect = () => {
|
|
23263
|
+
let winner;
|
|
23264
|
+
for (const candidate of entries) {
|
|
23265
|
+
if (!candidate.element.isConnected) continue;
|
|
23266
|
+
if (!winner || winner.element.compareDocumentPosition(candidate.element) & 4) winner = candidate;
|
|
23267
|
+
}
|
|
23268
|
+
for (const candidate of entries) candidate.update(candidate === winner);
|
|
23269
|
+
};
|
|
23270
|
+
elect();
|
|
23271
|
+
return () => {
|
|
23272
|
+
entries.delete(entry);
|
|
23273
|
+
elect();
|
|
23274
|
+
if (!entries.size) documents.delete(key2);
|
|
23275
|
+
};
|
|
23276
|
+
}, [anchor, documentId, sessionId]);
|
|
23277
|
+
return owner;
|
|
23278
|
+
}
|
|
23279
|
+
|
|
23123
23280
|
// src/presentation.js
|
|
23124
|
-
var h5 =
|
|
23281
|
+
var h5 = import_react11.default.createElement;
|
|
23125
23282
|
var scanners = /* @__PURE__ */ new WeakMap();
|
|
23126
23283
|
var focused = /* @__PURE__ */ new Map();
|
|
23127
|
-
function PresentationView({ raw, sessionId, sendPrompt, scope }) {
|
|
23128
|
-
const
|
|
23129
|
-
(0,
|
|
23284
|
+
function PresentationView({ raw, sessionId, sendPrompt, scope: scope2 }) {
|
|
23285
|
+
const showDetails = useViewDetails();
|
|
23286
|
+
const anchor = (0, import_react11.useRef)(null), records2 = useUiRegistry(), mode = usePresentation(scope2), host = markerLocation(raw.documentId);
|
|
23287
|
+
const owner = usePresentationOwner(anchor, raw.documentId, sessionId);
|
|
23288
|
+
(0, import_react11.useEffect)(() => {
|
|
23130
23289
|
rememberUi(raw, sessionId, sendPrompt);
|
|
23131
23290
|
}, [raw, sessionId, sendPrompt]);
|
|
23132
|
-
(0,
|
|
23291
|
+
(0, import_react11.useEffect)(() => {
|
|
23133
23292
|
const root = anchor.current?.closest("[data-conversation-scroll]");
|
|
23134
23293
|
if (!root) return;
|
|
23135
23294
|
let entry = scanners.get(root);
|
|
@@ -23150,31 +23309,31 @@ function PresentationView({ raw, sessionId, sendPrompt, scope }) {
|
|
|
23150
23309
|
}
|
|
23151
23310
|
};
|
|
23152
23311
|
}, [sessionId]);
|
|
23153
|
-
(0,
|
|
23312
|
+
(0, import_react11.useEffect)(() => {
|
|
23154
23313
|
const block = host?.uiMarkerBlock;
|
|
23155
|
-
if (!block) return;
|
|
23314
|
+
if (!block || !owner) return;
|
|
23156
23315
|
const previous = block.style.display;
|
|
23157
23316
|
block.style.display = mode === "inline" ? "none" : previous;
|
|
23158
23317
|
return () => {
|
|
23159
23318
|
block.style.display = previous;
|
|
23160
23319
|
};
|
|
23161
|
-
}, [host, mode]);
|
|
23320
|
+
}, [host, mode, owner]);
|
|
23162
23321
|
const available = panelAvailable();
|
|
23163
|
-
(0,
|
|
23164
|
-
if (mode === "sidebar" && available) openUiPanel(raw.documentId, sessionId);
|
|
23165
|
-
}, [mode, available, sessionId, raw.documentId]);
|
|
23322
|
+
(0, import_react11.useEffect)(() => {
|
|
23323
|
+
if (owner && mode === "sidebar" && available) openUiPanel(raw.documentId, sessionId);
|
|
23324
|
+
}, [mode, available, sessionId, raw.documentId, owner]);
|
|
23166
23325
|
const content = h5(ValidatedView, { raw, fallback: raw.document.fallback, sessionId, sendPrompt });
|
|
23167
23326
|
return h5(
|
|
23168
23327
|
"div",
|
|
23169
23328
|
{ ref: anchor, "data-dgui-presentation": raw.documentId },
|
|
23170
|
-
available && h5("button", { type: "button", className: "dgui-secondary", onClick: () => openUiPanel(raw.documentId, sessionId) }, "\u5728\u4FA7\u680F\u6253\u5F00"),
|
|
23171
|
-
mode === "sidebar" && available ? h5("p", { className: "dgui-copy" }, `${raw.document.title} \xB7 \u5728\u4FA7\u680F\u4E2D\u64CD\u4F5C`) : mode === "inline" && host ? (0, import_react_dom.createPortal)(content, host) : content,
|
|
23172
|
-
mode === "inline" && !host && h5("small", { className: "dgui-copy" }, "\u6B63\u6587\u6807\u8BB0\
|
|
23329
|
+
owner && available && h5("button", { type: "button", className: "dgui-secondary", onClick: () => openUiPanel(raw.documentId, sessionId) }, "\u5728\u4FA7\u680F\u6253\u5F00"),
|
|
23330
|
+
owner && (mode === "sidebar" && available ? h5("p", { className: "dgui-copy" }, `${raw.document.title} \xB7 \u5728\u4FA7\u680F\u4E2D\u64CD\u4F5C`) : mode === "inline" && host ? (0, import_react_dom.createPortal)(content, host) : content),
|
|
23331
|
+
showDetails && owner && mode === "inline" && !host && h5("small", { className: "dgui-copy" }, "\u672A\u63D0\u4F9B\u6B63\u6587\u6807\u8BB0\uFF0C\u754C\u9762\u663E\u793A\u5728\u56DE\u7B54\u4E0B\u65B9\u3002")
|
|
23173
23332
|
);
|
|
23174
23333
|
}
|
|
23175
23334
|
function UiPanel({ sessionId, sendPrompt }) {
|
|
23176
|
-
const records2 = useUiRegistry().filter((r) => r.sessionId === sessionId), [selected, setSelected] = (0,
|
|
23177
|
-
(0,
|
|
23335
|
+
const records2 = useUiRegistry().filter((r) => r.sessionId === sessionId), [selected, setSelected] = (0, import_react11.useState)(focused.get(sessionId));
|
|
23336
|
+
(0, import_react11.useEffect)(() => subscribeUi(() => setSelected(focused.get(sessionId))), [sessionId]);
|
|
23178
23337
|
const record = records2.find((r) => r.raw.documentId === selected) ?? records2.at(-1);
|
|
23179
23338
|
return h5(
|
|
23180
23339
|
"div",
|
|
@@ -23192,11 +23351,11 @@ function focusUi(id, sessionId) {
|
|
|
23192
23351
|
}
|
|
23193
23352
|
|
|
23194
23353
|
// src/view.js
|
|
23195
|
-
var h6 =
|
|
23354
|
+
var h6 = import_react12.default.createElement;
|
|
23196
23355
|
var display = (value) => value === void 0 || value === null ? "\u2014" : typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
23197
23356
|
function NumericInput({ id, spec, value, onChange, invalidChanged, disabled }) {
|
|
23198
|
-
const [draft, setDraft] = (0,
|
|
23199
|
-
(0,
|
|
23357
|
+
const [draft, setDraft] = (0, import_react12.useState)(String(value)), [invalid, setInvalid] = (0, import_react12.useState)(false);
|
|
23358
|
+
(0, import_react12.useEffect)(() => {
|
|
23200
23359
|
setDraft(String(value));
|
|
23201
23360
|
setInvalid(false);
|
|
23202
23361
|
invalidChanged(id, false);
|
|
@@ -23220,15 +23379,17 @@ function NumericInput({ id, spec, value, onChange, invalidChanged, disabled }) {
|
|
|
23220
23379
|
}
|
|
23221
23380
|
});
|
|
23222
23381
|
}
|
|
23223
|
-
function Table({ rows, columns, id }) {
|
|
23382
|
+
function Table({ rows, columns, id, label }) {
|
|
23224
23383
|
return h6("div", { className: "dgui-table-wrap" }, h6(
|
|
23225
23384
|
"table",
|
|
23226
23385
|
{ "data-ui-node": id },
|
|
23386
|
+
label && h6("caption", null, label),
|
|
23227
23387
|
h6("thead", null, h6("tr", null, columns.map((c) => h6("th", { key: c.key, scope: "col" }, c.label, c.unit ? ` (${c.unit})` : "")))),
|
|
23228
23388
|
h6("tbody", null, rows.length ? rows.map((row, i) => h6("tr", { key: i }, columns.map((c) => h6("td", { key: c.key, "data-numeric": typeof row[c.key] === "number" }, display(Object.hasOwn(row, c.key) ? row[c.key] : void 0))))) : h6("tr", null, h6("td", { colSpan: columns.length }, "\u6682\u65E0\u6570\u636E")))
|
|
23229
23389
|
));
|
|
23230
23390
|
}
|
|
23231
23391
|
function Chart({ node, rows }) {
|
|
23392
|
+
const [showData, setShowData] = (0, import_react12.useState)(false);
|
|
23232
23393
|
const data = rows.slice(0, 40), values = data.map((r) => r[node.valueKey]);
|
|
23233
23394
|
const low = node.kind === "line" && values.length ? Math.min(...values) : Math.min(0, ...values);
|
|
23234
23395
|
const high = node.kind === "line" && values.length ? Math.max(...values) : Math.max(0, ...values), range = high - low || 1;
|
|
@@ -23241,7 +23402,7 @@ function Chart({ node, rows }) {
|
|
|
23241
23402
|
return h6(
|
|
23242
23403
|
"figure",
|
|
23243
23404
|
{ className: "dgui-chart", "data-ui-node": node.id },
|
|
23244
|
-
h6("figcaption", null, h6(Icon, { name: "chart" }), node.label, node.unit && h6("span", { className: "dgui-chart-unit" }, `(${node.unit})`)),
|
|
23405
|
+
h6("figcaption", null, h6(Icon, { name: "chart" }), node.label, rows.length > 40 && "\uFF08\u56FE\u793A\u524D 40 \u9879\uFF09", node.unit && h6("span", { className: "dgui-chart-unit" }, `(${node.unit})`), h6("button", { type: "button", className: "dgui-chart-data-button", "aria-expanded": showData, onClick: () => setShowData(!showData) }, "\u56FE\u8868\u6570\u636E")),
|
|
23245
23406
|
h6("div", { className: "dgui-plot", tabIndex: 0, role: "region", "aria-label": `${node.label}\u56FE\u8868\uFF0C\u53EF\u6A2A\u5411\u6EDA\u52A8` }, h6(
|
|
23246
23407
|
"svg",
|
|
23247
23408
|
{ viewBox: `0 0 ${width} 205`, role: "img", "aria-label": `${node.label}\u3002\u5C55\u5F00\u56FE\u8868\u6570\u636E\u53EF\u67E5\u770B\u6BCF\u9879\u6570\u503C\u3002` },
|
|
@@ -23256,16 +23417,15 @@ function Chart({ node, rows }) {
|
|
|
23256
23417
|
(data.length <= 12 || i % Math.ceil(data.length / 12) === 0) && h6("text", { x: x(i), y: 192, textAnchor: "middle", fontSize: 14, fill: "var(--du-muted)" }, String(r[node.labelKey]).slice(0, 12))
|
|
23257
23418
|
))
|
|
23258
23419
|
)),
|
|
23259
|
-
h6("
|
|
23260
|
-
rows.length > 40 && h6("small", null, "\u56FE\u793A\u524D 40 \u9879\uFF0C\u5B8C\u6574\u6570\u503C\u89C1\u4E0B\u65B9\u6570\u636E\u3002"),
|
|
23261
|
-
h6("details", null, h6("summary", null, "\u56FE\u8868\u6570\u636E"), h6(Table, { rows, columns: [{ key: node.labelKey, label: "\u9879\u76EE" }, { key: node.valueKey, label: node.label, unit: node.unit }], id: `${node.id}-data` }))
|
|
23420
|
+
h6("div", { hidden: !showData }, h6(Table, { rows, columns: [{ key: node.labelKey, label: "\u9879\u76EE" }, { key: node.valueKey, label: node.label, unit: node.unit }], id: `${node.id}-data` }))
|
|
23262
23421
|
);
|
|
23263
23422
|
}
|
|
23264
23423
|
function UiView({ record, sessionId, sendPrompt, preview = false }) {
|
|
23424
|
+
const showDetails = useViewDetails();
|
|
23265
23425
|
const doc = record.document;
|
|
23266
|
-
const viewId =
|
|
23267
|
-
const root = (0,
|
|
23268
|
-
const collectAudit =
|
|
23426
|
+
const viewId = import_react12.default.useId();
|
|
23427
|
+
const root = (0, import_react12.useRef)(null), canvasAudits = (0, import_react12.useRef)(/* @__PURE__ */ new Map()), [audit, setAudit] = (0, import_react12.useState)(null), auditPending = (0, import_react12.useRef)(0);
|
|
23428
|
+
const collectAudit = import_react12.default.useCallback(() => {
|
|
23269
23429
|
clearTimeout(auditPending.current);
|
|
23270
23430
|
auditPending.current = setTimeout(() => {
|
|
23271
23431
|
if (!root.current || preview) return;
|
|
@@ -23277,7 +23437,7 @@ function UiView({ record, sessionId, sendPrompt, preview = false }) {
|
|
|
23277
23437
|
});
|
|
23278
23438
|
}, 250);
|
|
23279
23439
|
}, [record.documentId, record.documentRevision, sessionId, preview]);
|
|
23280
|
-
(0,
|
|
23440
|
+
(0, import_react12.useEffect)(() => {
|
|
23281
23441
|
canvasAudits.current.clear();
|
|
23282
23442
|
collectAudit();
|
|
23283
23443
|
window.addEventListener("resize", collectAudit);
|
|
@@ -23295,22 +23455,22 @@ function UiView({ record, sessionId, sendPrompt, preview = false }) {
|
|
|
23295
23455
|
collectAudit();
|
|
23296
23456
|
};
|
|
23297
23457
|
const { state, setState, ready, status, issue, epoch, retry, useRemote, keepLocal } = useSavedState(record, sessionId, preview);
|
|
23298
|
-
const [error, setError] = (0,
|
|
23299
|
-
const [busy, setBusy] = (0,
|
|
23300
|
-
const pending = (0,
|
|
23301
|
-
(0,
|
|
23458
|
+
const [error, setError] = (0, import_react12.useState)(""), [actionStatus, setActionStatus] = (0, import_react12.useState)("");
|
|
23459
|
+
const [busy, setBusy] = (0, import_react12.useState)(false), [invalidFields, setInvalidFields] = (0, import_react12.useState)({});
|
|
23460
|
+
const pending = (0, import_react12.useRef)(false);
|
|
23461
|
+
(0, import_react12.useEffect)(() => {
|
|
23302
23462
|
setInvalidFields({});
|
|
23303
23463
|
}, [epoch]);
|
|
23304
|
-
const invalidChanged =
|
|
23464
|
+
const invalidChanged = import_react12.default.useCallback((id, invalid) => setInvalidFields((previous) => previous[id] === invalid ? previous : { ...previous, [id]: invalid }), []);
|
|
23305
23465
|
let computed;
|
|
23306
23466
|
try {
|
|
23307
23467
|
computed = evaluate(doc, state);
|
|
23308
23468
|
} catch (e) {
|
|
23309
23469
|
computed = { error: e.message };
|
|
23310
23470
|
}
|
|
23311
|
-
const currentState = (0,
|
|
23471
|
+
const currentState = (0, import_react12.useRef)(state);
|
|
23312
23472
|
currentState.current = state;
|
|
23313
|
-
(0,
|
|
23473
|
+
(0, import_react12.useEffect)(() => {
|
|
23314
23474
|
collectAudit();
|
|
23315
23475
|
}, [state, ready, collectAudit]);
|
|
23316
23476
|
const updatePatch = (patch) => {
|
|
@@ -23320,9 +23480,9 @@ function UiView({ record, sessionId, sendPrompt, preview = false }) {
|
|
|
23320
23480
|
setError("");
|
|
23321
23481
|
setActionStatus("");
|
|
23322
23482
|
};
|
|
23323
|
-
const update = (
|
|
23483
|
+
const update = (key2, value) => {
|
|
23324
23484
|
try {
|
|
23325
|
-
updatePatch({ [
|
|
23485
|
+
updatePatch({ [key2]: value });
|
|
23326
23486
|
} catch (e) {
|
|
23327
23487
|
setError(e.message);
|
|
23328
23488
|
}
|
|
@@ -23372,7 +23532,7 @@ function UiView({ record, sessionId, sendPrompt, preview = false }) {
|
|
|
23372
23532
|
return h6("ol", { ...props, className: "dgui-steps" }, n.items.map((item, i) => h6("li", { key: i, "data-step-status": item.status }, h6("span", { className: "dgui-step-dot", "aria-hidden": true }, item.status === "done" ? h6(Icon, { name: "check" }) : item.status === "error" ? h6(Icon, { name: "warning" }) : i + 1), h6("div", null, h6("strong", null, item.title), h6("span", { className: "dgui-step-state" }, { pending: "\u5F85\u8FDB\u884C", active: "\u5F53\u524D\u6B65\u9AA4", done: "\u5DF2\u5B8C\u6210", error: "\u5F02\u5E38" }[item.status]), item.description && h6("p", null, item.description)))));
|
|
23373
23533
|
case "metric": {
|
|
23374
23534
|
const v = resolve(n.value);
|
|
23375
|
-
return h6("div", { ...props, className: "dgui-metric" }, h6("span", { className: "dgui-metric-label" }, h6(Icon, { name: n.icon ?? "gauge" }), n.label), h6("strong", null, typeof v === "number" ? formatNumber(v, n.decimals ?? 2) :
|
|
23535
|
+
return h6("div", { ...props, className: "dgui-metric" }, h6("span", { className: "dgui-metric-label" }, h6(Icon, { name: n.icon ?? "gauge" }), n.label), h6("strong", null, typeof v === "number" ? formatNumber(v, n.decimals ?? 2) : display(v), " ", h6("small", null, n.unit)));
|
|
23376
23536
|
}
|
|
23377
23537
|
case "input":
|
|
23378
23538
|
case "slider":
|
|
@@ -23382,7 +23542,7 @@ function UiView({ record, sessionId, sendPrompt, preview = false }) {
|
|
|
23382
23542
|
let control;
|
|
23383
23543
|
if (n.type === "select") control = h6("select", { id, value: spec.options.indexOf(v), disabled: !ready, onChange: (e) => update(k, spec.options[Number(e.target.value)]) }, spec.options.map((o, i) => h6("option", { key: i, value: i }, display(o))));
|
|
23384
23544
|
else if (n.type === "toggle") control = h6("input", { id, className: "dgui-toggle", type: "checkbox", checked: v, disabled: !ready, onChange: (e) => update(k, e.target.checked) });
|
|
23385
|
-
else if (n.type === "slider") control = h6(
|
|
23545
|
+
else if (n.type === "slider") control = h6(import_react12.default.Fragment, null, h6("input", { id, type: "range", min: spec.min, max: spec.max, step: spec.step, value: v, disabled: !ready, onChange: (e) => update(k, Number(e.target.value)) }), h6("output", { htmlFor: id }, display(v)));
|
|
23386
23546
|
else if (spec.type === "number") control = h6(NumericInput, { id, spec, value: v, disabled: !ready, invalidChanged, onChange: (value) => update(k, value) });
|
|
23387
23547
|
else control = h6("input", { id, type: "text", value: v, maxLength: 8192, disabled: !ready, onChange: (e) => update(k, e.target.value) });
|
|
23388
23548
|
return h6("div", { ...props, className: "dgui-control" }, h6("label", { htmlFor: id }, h6(Icon, { name: n.type === "toggle" ? "layers" : n.type === "select" ? "target" : "sliders" }), h6("span", null, n.label)), control);
|
|
@@ -23390,7 +23550,7 @@ function UiView({ record, sessionId, sendPrompt, preview = false }) {
|
|
|
23390
23550
|
case "button":
|
|
23391
23551
|
return h6("button", { ...props, className: "dgui-button", type: "button", disabled: disabled || !sendPrompt, onClick: () => followup(n.action) }, n.text, h6(Icon, { name: n.icon ?? "arrow" }));
|
|
23392
23552
|
case "table":
|
|
23393
|
-
return computed.error ? null : h6(Table, { key: n.id, id: n.id, rows: resolve(n.rows), columns: n.columns });
|
|
23553
|
+
return computed.error ? null : h6(Table, { key: n.id, id: n.id, label: n.label, rows: resolve(n.rows), columns: n.columns });
|
|
23394
23554
|
case "chart":
|
|
23395
23555
|
return computed.error ? null : h6(Chart, { key: n.id, node: n, rows: resolve(n.rows) });
|
|
23396
23556
|
default:
|
|
@@ -23401,14 +23561,14 @@ function UiView({ record, sessionId, sendPrompt, preview = false }) {
|
|
|
23401
23561
|
return h6(
|
|
23402
23562
|
"section",
|
|
23403
23563
|
{ ref: root, className: "dgui-root", "data-document-revision": record.documentRevision ?? 0, "data-dgui-build": BUILD_INFO.id, "data-dsh-generative-ui": record.documentId, "data-layout": doc.presentation?.layout, "data-accent": doc.presentation?.accent, "data-density": doc.presentation?.density, "data-preview": preview || void 0, "aria-label": doc.title, "aria-busy": preview || void 0 },
|
|
23404
|
-
h6("header", { className: "dgui-header" }, h6("span", { className: "dgui-heading-icon" }, h6(Icon, { name: sceneIcons[doc.presentation?.layout] ?? "sliders" })), h6("strong", { className: "dgui-header-title" }, doc.title), h6("span", { className: "dgui-badge" }, h6(Icon, { name: "sparkles" }), preview ? "\u751F\u6210\u4E2D" : "\
|
|
23564
|
+
h6("header", { className: "dgui-header" }, h6("span", { className: "dgui-heading-icon" }, h6(Icon, { name: sceneIcons[doc.presentation?.layout] ?? (Object.keys(doc.state).length ? "sliders" : "layers") })), h6("strong", { className: "dgui-header-title" }, doc.title), h6("span", { className: "dgui-badge" }, h6(Icon, { name: "sparkles" }), preview ? "\u751F\u6210\u4E2D" : "\u53EF\u89C6\u5316")),
|
|
23405
23565
|
h6("div", { key: epoch, className: "dgui-content" }, doc.nodes.map(renderNode)),
|
|
23406
|
-
h6("div", { className: "dgui-status", role: "status", "data-status": /失败|冲突/.test(status) ? "error" : /正在|等待/.test(status) ? "pending" : "saved" }, h6(Icon, { name: /失败|冲突/.test(status) ? "warning" : /正在|等待/.test(status) ? "database" : "check" }), h6("span", null, status), actionStatus && h6("span", null, ` \xB7 ${actionStatus}`)),
|
|
23566
|
+
(Object.keys(doc.state).length > 0 || issue || actionStatus) && h6("div", { className: showDetails || issue || actionStatus ? "dgui-status" : "dgui-sr-only", role: "status", "data-status": /失败|冲突/.test(status) ? "error" : /正在|等待/.test(status) ? "pending" : "saved" }, h6(Icon, { name: /失败|冲突/.test(status) ? "warning" : /正在|等待/.test(status) ? "database" : "check" }), h6("span", null, status), actionStatus && h6("span", null, ` \xB7 ${actionStatus}`)),
|
|
23407
23567
|
issue && h6(
|
|
23408
23568
|
"div",
|
|
23409
23569
|
{ className: "dgui-recovery" },
|
|
23410
23570
|
issue.kind === "conflict" ? h6(
|
|
23411
|
-
|
|
23571
|
+
import_react12.default.Fragment,
|
|
23412
23572
|
null,
|
|
23413
23573
|
h6("button", { type: "button", className: "dgui-secondary", disabled: status === "\u6B63\u5728\u6062\u590D\u53C2\u6570\u2026", onClick: useRemote }, "\u4F7F\u7528\u5DF2\u4FDD\u5B58\u53C2\u6570"),
|
|
23414
23574
|
h6("button", { type: "button", className: "dgui-secondary", disabled: status === "\u6B63\u5728\u6062\u590D\u53C2\u6570\u2026", onClick: keepLocal }, "\u4FDD\u7559\u672C\u9875\u53C2\u6570\u5E76\u91CD\u8BD5")
|
|
@@ -23416,12 +23576,12 @@ function UiView({ record, sessionId, sendPrompt, preview = false }) {
|
|
|
23416
23576
|
),
|
|
23417
23577
|
(error || computed.error) && h6("p", { className: "dgui-error", role: "alert" }, error || computed.error),
|
|
23418
23578
|
Object.values(invalidFields).some(Boolean) && h6("p", { className: "dgui-error", role: "alert" }, "\u8BF7\u8F93\u5165\u8303\u56F4\u5185\u4E14\u7B26\u5408\u6B65\u957F\u7684\u6570\u503C\u3002"),
|
|
23419
|
-
!preview && audit && h6("details", { className: "dgui-fallback dgui-audit" }, h6("summary", null, "\u663E\u793A\u68C0\u67E5"), h6("p", null, `${audit.width}px \xB7 ${audit.theme === "dark" ? "\u6DF1\u8272" : "\u6D45\u8272"} \xB7 \u542F\u53D1\u5F0F\u89C2\u5BDF\uFF0C\u4E0D\u4EE3\u8868\u5B8C\u6574\u89C6\u89C9\u9A8C\u6536\u3002`), h6("p", null, "\u672A\u8986\u76D6\uFF1A\u590D\u6742\u80CC\u666F\u3001\u906E\u6321\u5173\u7CFB\u53CA SVG \u914D\u8272\uFF1B\u62A5\u544A\u4E0D\u7B49\u4E8E\u5B8C\u6574\u65E0\u969C\u788D\u68C0\u67E5\u3002"), audit.coverage?.some((c) => c.truncated) && h6("p", null, "\u5185\u5BB9\u8F83\u591A\uFF0C\u672C\u6B21\u53EA\u68C0\u67E5\u4E86\u6BCF\u4E2A\u533A\u57DF\u7684\u524D 2000 \u4E2A\u5143\u7D20\u3002"), audit.issues.length ? h6("ul", null, audit.issues.map((i, j) => h6("li", { key: j }, AUDIT_MESSAGES[i.code], i.nodeId ? `\uFF08${i.nodeId}\uFF09` : ""))) : h6("p", null, "\u672C\u6B21\u68C0\u67E5\u672A\u53D1\u73B0\u6240\u8986\u76D6\u7684\u95EE\u9898\u3002")),
|
|
23420
|
-
!preview && h6(HistoryView, { record, sessionId }),
|
|
23421
|
-
h6("details", { className: "dgui-fallback" }, h6("summary", null, Object.keys(doc.state).length ? "\u539F\u59CB\u6587\u5B57\u8BF4\u660E\u4E0E\u521D\u59CB\u53C2\u6570" : "\u539F\u59CB\u6587\u5B57\u8BF4\u660E"), h6("p", null, doc.fallback), Object.keys(doc.state).length > 0 && h6("pre", null, JSON.stringify(initialState(doc), null, 2)))
|
|
23579
|
+
showDetails && !preview && audit && h6("details", { className: "dgui-fallback dgui-audit" }, h6("summary", null, "\u663E\u793A\u68C0\u67E5"), h6("p", null, `${audit.width}px \xB7 ${audit.theme === "dark" ? "\u6DF1\u8272" : "\u6D45\u8272"} \xB7 \u542F\u53D1\u5F0F\u89C2\u5BDF\uFF0C\u4E0D\u4EE3\u8868\u5B8C\u6574\u89C6\u89C9\u9A8C\u6536\u3002`), h6("p", null, "\u672A\u8986\u76D6\uFF1A\u590D\u6742\u80CC\u666F\u3001\u906E\u6321\u5173\u7CFB\u53CA SVG \u914D\u8272\uFF1B\u62A5\u544A\u4E0D\u7B49\u4E8E\u5B8C\u6574\u65E0\u969C\u788D\u68C0\u67E5\u3002"), audit.coverage?.some((c) => c.truncated) && h6("p", null, "\u5185\u5BB9\u8F83\u591A\uFF0C\u672C\u6B21\u53EA\u68C0\u67E5\u4E86\u6BCF\u4E2A\u533A\u57DF\u7684\u524D 2000 \u4E2A\u5143\u7D20\u3002"), audit.issues.length ? h6("ul", null, audit.issues.map((i, j) => h6("li", { key: j }, AUDIT_MESSAGES[i.code], i.nodeId ? `\uFF08${i.nodeId}\uFF09` : ""))) : h6("p", null, "\u672C\u6B21\u68C0\u67E5\u672A\u53D1\u73B0\u6240\u8986\u76D6\u7684\u95EE\u9898\u3002")),
|
|
23580
|
+
showDetails && !preview && h6(HistoryView, { record, sessionId }),
|
|
23581
|
+
showDetails && h6("details", { className: "dgui-fallback" }, h6("summary", null, Object.keys(doc.state).length ? "\u539F\u59CB\u6587\u5B57\u8BF4\u660E\u4E0E\u521D\u59CB\u53C2\u6570" : "\u539F\u59CB\u6587\u5B57\u8BF4\u660E"), h6("p", null, doc.fallback), Object.keys(doc.state).length > 0 && h6("pre", null, JSON.stringify(initialState(doc), null, 2)))
|
|
23422
23582
|
);
|
|
23423
23583
|
}
|
|
23424
|
-
var UiBoundary = class extends
|
|
23584
|
+
var UiBoundary = class extends import_react12.default.Component {
|
|
23425
23585
|
state = { failed: false };
|
|
23426
23586
|
static getDerivedStateFromError() {
|
|
23427
23587
|
return { failed: true };
|
|
@@ -23444,9 +23604,11 @@ function StreamingToolView(props) {
|
|
|
23444
23604
|
return h6(StreamingPreview, { raw, callId: props.callId, sessionId: props.sessionId });
|
|
23445
23605
|
}
|
|
23446
23606
|
function StreamingPreview({ raw, callId = "stream", sessionId }) {
|
|
23447
|
-
const
|
|
23448
|
-
const
|
|
23449
|
-
const
|
|
23607
|
+
const committed = useUiRegistry().some((r) => r.sessionId === sessionId && r.raw.callId === callId);
|
|
23608
|
+
const deferred = import_react12.default.useDeferredValue(raw);
|
|
23609
|
+
const doc = (0, import_react12.useMemo)(() => previewDocument(deferred), [deferred]);
|
|
23610
|
+
const canvas = (0, import_react12.useMemo)(() => doc ? null : previewCanvas(deferred), [doc, deferred]);
|
|
23611
|
+
if (committed) return h6("p", { className: "dgui-copy" }, "\u754C\u9762\u5DF2\u751F\u6210\u3002");
|
|
23450
23612
|
if (canvas) return h6("div", { className: "dgui-root", "data-preview": true }, h6(CanvasPreview, { node: canvas }));
|
|
23451
23613
|
if (!doc) return h6("div", { className: "dgui-pending", role: "status" }, "\u6B63\u5728\u7EC4\u7EC7\u5E76\u6821\u9A8C\u4EA4\u4E92\u754C\u9762\u2026");
|
|
23452
23614
|
return h6(UiBoundary, { key: callId, fallback: doc.fallback }, h6(UiView, { record: { document: doc, documentId: `preview-${callId}` }, sessionId, preview: true }));
|
|
@@ -23455,7 +23617,7 @@ function TurnUiView(props) {
|
|
|
23455
23617
|
return (props.turn.data.get("dshGenerativeUi") ?? []).filter((r) => r.seq < props.seq).map((r) => r.isPatch ? h6(PatchNotice, { key: `patch-${r.seq}`, raw: r.raw }) : h6(PresentationView, { key: r.raw.documentId, ...r, sessionId: props.sessionId, sendPrompt: props.sendPrompt, scope: props.presentationScope }));
|
|
23456
23618
|
}
|
|
23457
23619
|
function PatchNotice({ raw }) {
|
|
23458
|
-
(0,
|
|
23620
|
+
(0, import_react12.useEffect)(() => {
|
|
23459
23621
|
try {
|
|
23460
23622
|
if (raw) publishDocument(raw);
|
|
23461
23623
|
} catch {
|
|
@@ -23465,7 +23627,7 @@ function PatchNotice({ raw }) {
|
|
|
23465
23627
|
}
|
|
23466
23628
|
function ValidatedView({ raw, fallback, sessionId, sendPrompt }) {
|
|
23467
23629
|
const { record: current2, status, retry } = useCurrentDocument(raw ?? {}, sessionId);
|
|
23468
|
-
const result = (0,
|
|
23630
|
+
const result = (0, import_react12.useMemo)(() => {
|
|
23469
23631
|
try {
|
|
23470
23632
|
if (!current2 || current2.version !== 1 || typeof current2.documentId !== "string" || typeof current2.callId !== "string") return null;
|
|
23471
23633
|
return { ...current2, document: validateDocument(current2.document) };
|
|
@@ -23475,7 +23637,7 @@ function ValidatedView({ raw, fallback, sessionId, sendPrompt }) {
|
|
|
23475
23637
|
}, [current2]);
|
|
23476
23638
|
if (!result) return h6("div", { className: "dgui-root" }, h6("p", null, "\u6587\u5B57\u7ED3\u679C\uFF08\u672A\u63D0\u4F9B\u517C\u5BB9\u7684\u754C\u9762\u6570\u636E\uFF09"), h6("pre", null, fallback));
|
|
23477
23639
|
return h6(
|
|
23478
|
-
|
|
23640
|
+
import_react12.default.Fragment,
|
|
23479
23641
|
null,
|
|
23480
23642
|
status === "error" && h6("div", { className: "dgui-root dgui-document-warning", role: "status" }, h6("p", null, "\u672A\u80FD\u786E\u8BA4\u6700\u65B0\u754C\u9762\u7248\u672C\uFF0C\u5F53\u524D\u663E\u793A\u5DF2\u77E5\u7248\u672C\u3002"), h6("button", { type: "button", className: "dgui-secondary", onClick: retry }, "\u91CD\u65B0\u8BFB\u53D6\u6700\u65B0\u754C\u9762")),
|
|
23481
23643
|
status === "loading" && h6("p", { className: "dgui-copy", role: "status" }, "\u6B63\u5728\u8BFB\u53D6\u6700\u65B0\u754C\u9762\u7248\u672C\u2026"),
|
|
@@ -23503,8 +23665,8 @@ var turnUiDefinition = {
|
|
|
23503
23665
|
const fallback = (event.data.message.content ?? []).filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
23504
23666
|
return { ...context.state, records: [...context.state.records, { seq: event.seq, raw, fallback, ...isPatch ? { isPatch: true } : {} }] };
|
|
23505
23667
|
},
|
|
23506
|
-
buildLocationData(context,
|
|
23507
|
-
if (
|
|
23668
|
+
buildLocationData(context, scope2, previous) {
|
|
23669
|
+
if (scope2 !== "turn" || !context.state) return null;
|
|
23508
23670
|
if (previous?.key === "dshGenerativeUi" && previous.value === context.state.records) return previous;
|
|
23509
23671
|
return { kind: "turn", turn: context.state.turn, key: "dshGenerativeUi", value: context.state.records };
|
|
23510
23672
|
}
|
|
@@ -23538,8 +23700,30 @@ var CANVAS_CSS = `
|
|
|
23538
23700
|
.dgui-canvas{min-width:0}.dgui-canvas-stage{position:relative}.dgui-canvas-loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:10px;color:var(--du-muted);font-size:13px;background:var(--du-soft);border-radius:12px}.dgui-canvas-spinner{width:16px;height:16px;border:2px solid var(--du-line);border-top-color:var(--du-accent);border-radius:50%;animation:dgui-spin .9s linear infinite}.dgui-canvas-placeholder{padding:24px 18px;background:var(--du-soft);border:1px dashed var(--du-line);border-radius:12px;color:var(--du-muted);font-size:13px;display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.dgui-canvas-placeholder p{margin:0}.dgui-canvas-options{margin-top:6px}.dgui-root .dgui-canvas-options>summary{font-size:12px;padding:5px 0;color:var(--du-muted);width:fit-content}.dgui-canvas-options[open]{border-top:1px solid var(--du-line);padding-top:8px;margin-top:12px}.dgui-canvas-options>.dgui-copy{padding:8px 0;font-size:12px}.dgui-canvas-issue{border:1px solid color-mix(in srgb,var(--du-amber) 30%,var(--du-line));background:color-mix(in srgb,var(--du-amber) 5%,var(--du-bg));border-radius:10px;padding:14px;margin-top:10px;font-size:12px;color:var(--du-ink)}.dgui-canvas-issue>strong{font-size:13px}.dgui-canvas-issue>p{color:var(--du-muted);margin-top:4px}.dgui-canvas-issue details{margin-top:8px}.dgui-root .dgui-canvas-issue pre{max-height:160px;overflow:auto}.dgui-canvas-options .dgui-secondary{font-size:12px;padding:6px 9px;box-shadow:none}@keyframes dgui-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.dgui-canvas-spinner{animation:none}}@media(forced-colors:active){.dgui-canvas-issue,.dgui-canvas-placeholder{border-color:CanvasText}}
|
|
23539
23701
|
`;
|
|
23540
23702
|
|
|
23703
|
+
// src/soft-styles.js
|
|
23704
|
+
var SOFT_CSS = `
|
|
23705
|
+
.dgui-root{--du-radius:24px;--du-radius-inner:18px;background:linear-gradient(145deg,color-mix(in srgb,var(--du-accent) 4%,var(--du-bg)),var(--du-bg) 42%,color-mix(in srgb,var(--du-violet) 3%,var(--du-bg)));border-radius:var(--du-radius)}
|
|
23706
|
+
.dgui-root .dgui-card,.dgui-root .dgui-metric,.dgui-root .dgui-chart,.dgui-root .dgui-progress,.dgui-root .dgui-details{border-radius:var(--du-radius-inner);background:linear-gradient(135deg,color-mix(in srgb,var(--du-tone) 9%,var(--du-bg)),color-mix(in srgb,var(--du-violet) 4%,var(--du-bg)) 65%,var(--du-bg))}
|
|
23707
|
+
.dgui-root .dgui-card[data-surface=soft]{background:linear-gradient(135deg,var(--du-soft),color-mix(in srgb,var(--du-accent) 7%,var(--du-bg)))}
|
|
23708
|
+
.dgui-root .dgui-card[data-surface=featured]{border-radius:20px;background:linear-gradient(130deg,color-mix(in srgb,var(--du-accent) 14%,var(--du-bg)),color-mix(in srgb,var(--du-violet) 7%,var(--du-bg)));box-shadow:none}
|
|
23709
|
+
.dgui-root[data-layout=dashboard] .dgui-metric{background:linear-gradient(135deg,color-mix(in srgb,var(--du-tone) 11%,var(--du-bg)),var(--du-bg))}
|
|
23710
|
+
.dgui-root[data-layout=report] .dgui-card{padding:16px 18px;border:1px solid var(--du-line);border-radius:18px}
|
|
23711
|
+
.dgui-root .dgui-heading-icon{border-radius:14px;background:linear-gradient(145deg,color-mix(in srgb,var(--du-accent) 14%,var(--du-bg)),color-mix(in srgb,var(--du-violet) 8%,var(--du-bg)))}
|
|
23712
|
+
.dgui-root .dgui-button{border-radius:14px;background:linear-gradient(120deg,var(--du-action,#3e60d3),color-mix(in srgb,var(--du-action,#3e60d3) 85%,#152647))}
|
|
23713
|
+
.dgui-root input:not([type=range]):not([type=checkbox]),.dgui-root select,.dgui-root textarea,.dgui-root .dgui-secondary,.dgui-root .dgui-menu-trigger{border-radius:12px}
|
|
23714
|
+
.dgui-root .dgui-menu-content,.dgui-root .dgui-table-wrap,.dgui-root .dgui-canvas-placeholder,.dgui-root .dgui-canvas-loading,.dgui-root .dgui-canvas-issue{border-radius:18px}
|
|
23715
|
+
.dgui-root .dgui-menu-content button{border-radius:12px}.dgui-root .dgui-badge{border-radius:999px;background:linear-gradient(120deg,var(--du-soft),var(--du-tint))}
|
|
23716
|
+
.dgui-root .dgui-table-wrap caption{text-align:left;padding:12px 14px;font-size:14px;font-weight:600;color:var(--du-ink);background:linear-gradient(120deg,var(--du-tint),var(--du-bg))}
|
|
23717
|
+
.dgui-root[data-layout=status] .dgui-header{border-radius:23px 23px 0 0;background:linear-gradient(120deg,var(--du-tint),var(--du-soft))}
|
|
23718
|
+
.dgui-root[data-layout=dashboard]{background:linear-gradient(145deg,var(--du-tint),var(--du-bg) 45%,color-mix(in srgb,var(--du-violet) 4%,var(--du-bg)))}
|
|
23719
|
+
.dgui-root .dgui-content>:last-child{margin-bottom:0}.dgui-root .dgui-canvas-stage iframe{border-radius:16px}
|
|
23720
|
+
@media(max-width:600px){.dgui-root{--du-radius:22px;--du-radius-inner:18px}}
|
|
23721
|
+
@media(forced-colors:active){.dgui-root,.dgui-root .dgui-card,.dgui-root .dgui-metric,.dgui-root .dgui-chart,.dgui-root .dgui-button{background:Canvas}}
|
|
23722
|
+
`;
|
|
23723
|
+
|
|
23541
23724
|
// src/styles.js
|
|
23542
23725
|
var CSS = `
|
|
23726
|
+
.dgui-chart-data-button{margin-left:auto;border:0;background:transparent;color:var(--du-muted);font:inherit;cursor:pointer;padding:4px 8px}.dgui-chart-data-button:hover{color:var(--du-accent)}.dgui-sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip-path:inset(50%)!important;white-space:nowrap!important;border:0!important}.dgui-canvas{position:relative}.dgui-action-menu{position:absolute;top:6px;right:6px;z-index:2}.dgui-menu-trigger{width:32px;height:32px;border:1px solid var(--du-line);border-radius:8px;background:var(--du-bg);color:var(--du-muted);font-size:24px;line-height:1;cursor:pointer}.dgui-menu-content{position:absolute;top:38px;right:0;display:grid;min-width:156px;padding:5px;border:1px solid var(--du-line);border-radius:10px;background:var(--du-bg);box-shadow:0 6px 20px #0002}.dgui-menu-content button{border:0;border-radius:6px;background:transparent;color:var(--du-ink);padding:9px 12px;text-align:left;font:inherit;white-space:nowrap;cursor:pointer}.dgui-menu-content button:hover{background:var(--du-soft)}.dgui-menu-content button:disabled{opacity:.45;cursor:default}.dgui-action-menu button:focus-visible{outline:2px solid var(--du-accent);outline-offset:2px}
|
|
23543
23727
|
.dgui-root.dgui-settings{border:0;border-radius:0;box-shadow:none;background:transparent;padding:0;margin:0;max-width:720px;display:flex;flex-direction:column;gap:14px;font-size:13px;line-height:1.65}
|
|
23544
23728
|
.dgui-settings h3{font-size:14px;font-weight:600;margin:0}.dgui-settings label{font-weight:500}.dgui-settings p{color:var(--du-muted)}
|
|
23545
23729
|
.dgui-settings select{width:100%;max-width:420px;min-height:40px;border:1px solid var(--du-line);border-radius:6px;padding:9px 12px;background:var(--dsw-alias-bg-layer-3,var(--du-bg));color:inherit;font:inherit}.dgui-settings select:focus-visible{outline:2px solid var(--du-accent);outline-offset:3px}.dgui-settings select:disabled{opacity:.5}
|
|
@@ -23562,29 +23746,29 @@ body[data-ds-dark-theme] .dgui-root,.dgui-root[data-preview-theme=dark]{--du-acc
|
|
|
23562
23746
|
.dgui-panel{padding:16px;min-width:0;overflow:auto;height:100%;box-sizing:border-box}.dgui-panel>.dgui-root{margin-bottom:16px}.dgui-panel label{display:flex;align-items:center;flex-wrap:wrap;gap:10px}.dgui-panel select{max-width:100%;flex:1;min-width:120px;border:1px solid var(--du-line);border-radius:8px;padding:8px;background:var(--du-bg);color:var(--du-ink)}
|
|
23563
23747
|
.dgui-history-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:10px 0;border-bottom:1px solid var(--du-line)}.dgui-history-row>span{flex:1;min-width:140px}.dgui-version-preview{margin-top:14px;border:1px solid var(--du-line);border-radius:12px;padding:12px}.dgui-version-preview .dgui-root{margin-top:12px}
|
|
23564
23748
|
[data-dgui-presentation]>.dgui-secondary{margin:8px 0}[data-dgui-marker]{min-width:0}
|
|
23565
|
-
|
|
23749
|
+
` + SOFT_CSS;
|
|
23566
23750
|
|
|
23567
23751
|
// src/settings.js
|
|
23568
|
-
var
|
|
23569
|
-
var h7 =
|
|
23570
|
-
function ModeSettings({ scope }) {
|
|
23571
|
-
const [
|
|
23572
|
-
(0,
|
|
23573
|
-
const ready =
|
|
23574
|
-
async function change(mode,
|
|
23752
|
+
var import_react13 = __toESM(require("react"), 1);
|
|
23753
|
+
var h7 = import_react13.default.createElement;
|
|
23754
|
+
function ModeSettings({ scope: scope2 }) {
|
|
23755
|
+
const [snapshot2, setSnapshot] = (0, import_react13.useState)(() => scope2.getSnapshot()), [busy, setBusy] = (0, import_react13.useState)(false), [message, setMessage] = (0, import_react13.useState)(""), pending = (0, import_react13.useRef)(false);
|
|
23756
|
+
(0, import_react13.useEffect)(() => scope2.subscribe(() => setSnapshot(scope2.getSnapshot())), [scope2]);
|
|
23757
|
+
const ready = snapshot2.status === "ready" && snapshot2.value !== void 0;
|
|
23758
|
+
async function change(mode, key2 = "designMode") {
|
|
23575
23759
|
if (pending.current || !ready) return;
|
|
23576
23760
|
pending.current = true;
|
|
23577
23761
|
setBusy(true);
|
|
23578
23762
|
setMessage("");
|
|
23579
23763
|
try {
|
|
23580
|
-
await
|
|
23581
|
-
const actual =
|
|
23764
|
+
await scope2.mutate([{ op: "set", path: [key2], value: mode }], scope2.getSnapshot().revision);
|
|
23765
|
+
const actual = scope2.getSnapshot();
|
|
23582
23766
|
setSnapshot(actual);
|
|
23583
|
-
if (actual.status !== "ready" || actual.value?.[
|
|
23584
|
-
setMessage(
|
|
23767
|
+
if (actual.status !== "ready" || actual.value?.[key2] !== mode) throw new Error("\u8BBE\u7F6E\u672A\u4FDD\u5B58\uFF0C\u53EF\u80FD\u53D1\u751F\u914D\u7F6E\u51B2\u7A81\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
23768
|
+
setMessage(key2 === "designMode" ? "\u6A21\u5F0F\u5DF2\u4FDD\u5B58\uFF1B\u4ECE\u4E0B\u4E00\u6B21\u8BF7\u6C42\u5F00\u59CB\u751F\u6548\u3002" : "\u5C55\u793A\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\uFF1B\u6B63\u6587\u5B9A\u4F4D\u6307\u5BFC\u4ECE\u4E0B\u4E00\u6B21\u8BF7\u6C42\u5F00\u59CB\u751F\u6548\u3002");
|
|
23585
23769
|
} catch (e) {
|
|
23586
23770
|
setMessage(e.message ?? "\u6A21\u5F0F\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
23587
|
-
setSnapshot(
|
|
23771
|
+
setSnapshot(scope2.getSnapshot());
|
|
23588
23772
|
} finally {
|
|
23589
23773
|
pending.current = false;
|
|
23590
23774
|
setBusy(false);
|
|
@@ -23595,14 +23779,16 @@ function ModeSettings({ scope }) {
|
|
|
23595
23779
|
{ className: "dgui-root dgui-settings", "aria-label": "DSH Motion UI \u8BBE\u7F6E" },
|
|
23596
23780
|
h7("h3", null, "DSH Motion UI"),
|
|
23597
23781
|
h7("label", { htmlFor: "dgui-design-mode" }, "\u8BBE\u8BA1\u6A21\u5F0F"),
|
|
23598
|
-
h7("select", { id: "dgui-design-mode", value:
|
|
23782
|
+
h7("select", { id: "dgui-design-mode", value: snapshot2.value?.designMode ?? "guided", disabled: !ready || busy, onChange: (e) => change(e.target.value) }, h7("option", { value: "guided" }, "\u5F15\u5BFC\u6A21\u5F0F"), h7("option", { value: "free" }, "\u81EA\u7531\u8BBE\u8BA1\u6A21\u5F0F")),
|
|
23599
23783
|
h7("p", null, "\u5F15\u5BFC\u6A21\u5F0F\u63D0\u4F9B\u8BBE\u8BA1\u6280\u80FD\u3001\u7EC4\u4EF6\u534F\u8BAE\u4E0E\u793A\u4F8B\u3002\u81EA\u7531\u8BBE\u8BA1\u6A21\u5F0F\u53EA\u63D0\u4F9B\u753B\u5E03\u63A5\u53E3\u4E0E\u4EA4\u4E92\u7EA6\u675F\uFF0C\u5E03\u5C40\u3001\u56FE\u5F62\u3001\u914D\u8272\u548C\u52A8\u753B\u7531\u6A21\u578B\u51B3\u5B9A\uFF1B\u4E24\u79CD\u6A21\u5F0F\u7684\u8FD0\u884C\u6743\u9650\u76F8\u540C\u3002"),
|
|
23600
23784
|
h7("p", null, "\u4E24\u79CD\u6A21\u5F0F\u90FD\u4F1A\u6307\u5BFC\u6A21\u578B\u5224\u65AD\u4F55\u65F6\u4E3B\u52A8\u4F7F\u7528 UI\uFF0C\u5E76\u4F18\u5148\u4EA4\u4ED8\u5C0F\u800C\u5B8C\u6574\u7684\u754C\u9762\u3002"),
|
|
23601
23785
|
h7("label", { htmlFor: "dgui-display-mode" }, "\u754C\u9762\u5C55\u793A\u4F4D\u7F6E"),
|
|
23602
|
-
h7("select", { id: "dgui-display-mode", value:
|
|
23786
|
+
h7("select", { id: "dgui-display-mode", value: snapshot2.value?.displayMode ?? "tail", disabled: !ready || busy, onChange: (e) => change(e.target.value, "displayMode") }, h7("option", { value: "tail" }, "\u56DE\u7B54\u4E0B\u65B9"), h7("option", { value: "inline" }, "\u6B63\u6587\u6807\u8BB0\u4F4D\u7F6E"), h7("option", { value: "sidebar" }, "PC \u4FA7\u680F")),
|
|
23603
23787
|
h7("p", null, "\u6B63\u6587\u6A21\u5F0F\u7531\u6A21\u578B\u7528\u6807\u8BB0\u9009\u62E9\u63D2\u5165\u4F4D\u7F6E\uFF0C\u7F3A\u5C11\u6807\u8BB0\u65F6\u663E\u793A\u5728\u56DE\u7B54\u4E0B\u65B9\u3002\u4FA7\u680F\u4E0D\u53EF\u7528\u65F6\u81EA\u52A8\u56DE\u9000\uFF1B\u6B63\u6587\u548C\u4FA7\u680F\u5171\u4EAB\u5DF2\u4FDD\u5B58\u53C2\u6570\u3002"),
|
|
23788
|
+
h7("label", { htmlFor: "dgui-show-details" }, h7("input", { id: "dgui-show-details", type: "checkbox", checked: snapshot2.value?.showDetails === true, disabled: !ready || busy, onChange: (e) => change(e.target.checked, "showDetails") }), " \u663E\u793A\u754C\u9762\u8BE6\u60C5"),
|
|
23789
|
+
h7("p", null, "\u9ED8\u8BA4\u9690\u85CF\u5E95\u90E8\u7684\u53C2\u6570\u72B6\u6001\u3001\u539F\u59CB\u8BF4\u660E\u3001\u663E\u793A\u68C0\u67E5\u548C\u7248\u672C\u5386\u53F2\u3002\u5BFC\u51FA\u4E0E\u91CD\u7F6E\u53EF\u901A\u8FC7\u753B\u5E03\u53F3\u4E0A\u89D2\u64CD\u4F5C\u83DC\u5355\u4F7F\u7528\uFF1B\u9519\u8BEF\u63D0\u793A\u59CB\u7EC8\u4FDD\u7559\u3002"),
|
|
23604
23790
|
h7("p", null, "\u6B64\u8BBE\u7F6E\u5F71\u54CD\u5F53\u524D profile \u540E\u7EED\u8BF7\u6C42\u3002\u5DF2\u6709\u4E0A\u4E0B\u6587\u53EF\u80FD\u4FDD\u7559\u65E7\u6307\u5BFC\uFF0C\u5BF9\u6BD4\u6A21\u5F0F\u65F6\u8BF7\u65B0\u5EFA\u4F1A\u8BDD\u3002"),
|
|
23605
|
-
!ready && h7("p", { role: "status" },
|
|
23791
|
+
!ready && h7("p", { role: "status" }, snapshot2.status === "unavailable" ? "\u63D2\u4EF6\u8BBE\u7F6E\u4E0D\u53EF\u7528\uFF0C\u8BF7\u786E\u8BA4\u5BBF\u4E3B\u5DF2\u52A0\u8F7D\u65B0\u7248\u63D2\u4EF6\u3002" : "\u6B63\u5728\u8BFB\u53D6\u8BBE\u7F6E\u2026"),
|
|
23606
23792
|
message && h7("p", { role: "status" }, message)
|
|
23607
23793
|
);
|
|
23608
23794
|
}
|
|
@@ -23610,13 +23796,14 @@ function ModeSettings({ scope }) {
|
|
|
23610
23796
|
// src/client.jsx
|
|
23611
23797
|
var inject = ["slots", "sessions", "conversation", "uiConversation", "configForms"];
|
|
23612
23798
|
function apply(ctx) {
|
|
23613
|
-
const
|
|
23614
|
-
|
|
23799
|
+
const scope2 = ctx.configForms.get("motion-ui");
|
|
23800
|
+
configureViewSettings(scope2);
|
|
23801
|
+
ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register({ name: "plugins.bundle.config", key: "dsh-motion-ui" }, (props) => import_react14.default.createElement(ModeSettings, { ...props, scope: scope2 })));
|
|
23615
23802
|
ctx.uiConversation.events.register(turnUiDefinition);
|
|
23616
23803
|
ctx.slots.inject("conversation.chat.turnTail", () => ctx.slots.register({
|
|
23617
23804
|
name: "conversation.chat.turnTail",
|
|
23618
23805
|
id: "dsh-generative-ui",
|
|
23619
|
-
inject: (sessionId) => ({ presentationScope:
|
|
23806
|
+
inject: (sessionId) => ({ presentationScope: scope2, sendPrompt: (prompt) => ctx.sessions.scope(sessionId).get("conversation").send(prompt) })
|
|
23620
23807
|
}, TurnUiView));
|
|
23621
23808
|
ctx.effect(() => {
|
|
23622
23809
|
const style = document.createElement("style");
|