@lmzhen/dsh-evolution-merge-ui 0.35.0 → 0.36.1
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/lib/client.js +358 -137
- package/lib/types/client/MergeRow.d.ts +11 -4
- package/lib/types/client/MergeStore.d.ts +13 -0
- package/package.json +2 -2
- package/lib/types/client/platform-menu.d.ts +0 -52
package/lib/client.js
CHANGED
|
@@ -291,6 +291,125 @@ window.__ModuleLoader__.load({
|
|
|
291
291
|
return options.seconds === false ? head : head + ":" + pad(date.getSeconds());
|
|
292
292
|
}
|
|
293
293
|
//#endregion
|
|
294
|
+
//#region ../evolution-client-kit/src/notice.ts
|
|
295
|
+
/** One inline state notice: semantic tone plus text, no surface-specific styling. */
|
|
296
|
+
//#endregion
|
|
297
|
+
//#region ../evolution-client-kit/src/presentation/decision-frame.ts
|
|
298
|
+
/** One decision card: title, facts, at most one primary, secondary actions and details. */
|
|
299
|
+
function actionButton(action, role) {
|
|
300
|
+
return (0, react.createElement)("button", {
|
|
301
|
+
key: action.id,
|
|
302
|
+
type: "button",
|
|
303
|
+
"data-role": role === "primary" ? "decision-primary" : "decision-secondary",
|
|
304
|
+
"data-action": action.id,
|
|
305
|
+
"aria-busy": action.busy === true ? "true" : void 0,
|
|
306
|
+
...action.attributes ?? {},
|
|
307
|
+
disabled: action.disabled === true || action.busy === true,
|
|
308
|
+
title: action.title ?? action.label,
|
|
309
|
+
onClick: () => {
|
|
310
|
+
if (action.disabled !== true && action.busy !== true) action.onSelect();
|
|
311
|
+
}
|
|
312
|
+
}, action.label);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Render the one-card decision surface. The model has a singular primary on purpose.
|
|
316
|
+
* @param props - decision model and optional surface class.
|
|
317
|
+
* @returns the decision frame.
|
|
318
|
+
*/
|
|
319
|
+
function DecisionFrame({ decision, className }) {
|
|
320
|
+
const secondary = decision.secondary ?? [];
|
|
321
|
+
return (0, react.createElement)("section", {
|
|
322
|
+
"data-role": "decision-frame",
|
|
323
|
+
...className === void 0 ? {} : { className }
|
|
324
|
+
}, (0, react.createElement)("h2", { "data-role": "decision-title" }, decision.title), decision.summary === void 0 || decision.summary === "" ? null : (0, react.createElement)("p", { "data-role": "decision-summary" }, decision.summary), decision.facts.length === 0 ? null : (0, react.createElement)("dl", { "data-role": "decision-facts" }, decision.facts.map((fact) => (0, react.createElement)("div", {
|
|
325
|
+
key: fact.label,
|
|
326
|
+
"data-role": "decision-fact"
|
|
327
|
+
}, (0, react.createElement)("dt", null, fact.label), (0, react.createElement)("dd", null, fact.value)))), decision.details === void 0 ? null : (0, react.createElement)("div", { "data-role": "decision-details" }, decision.details), decision.primary === void 0 && secondary.length === 0 ? null : (0, react.createElement)("div", { "data-role": "decision-actions" }, decision.primary === void 0 ? null : actionButton(decision.primary, "primary"), secondary.map((action) => actionButton(action, "secondary"))));
|
|
328
|
+
}
|
|
329
|
+
//#endregion
|
|
330
|
+
//#region ../evolution-client-kit/src/presentation/task-banner.ts
|
|
331
|
+
/** A read-only task hint; it deliberately has no primary action. */
|
|
332
|
+
/**
|
|
333
|
+
* Render a task count plus one sentence. The absence of an action prop is the contract.
|
|
334
|
+
* @param props - count, sentence and optional surface class.
|
|
335
|
+
* @returns the banner.
|
|
336
|
+
*/
|
|
337
|
+
function TaskBanner({ count, text, className }) {
|
|
338
|
+
return (0, react.createElement)("div", {
|
|
339
|
+
"data-role": "task-banner",
|
|
340
|
+
"data-count": String(count),
|
|
341
|
+
role: "status",
|
|
342
|
+
...className === void 0 ? {} : { className }
|
|
343
|
+
}, (0, react.createElement)("strong", { "data-role": "task-banner-count" }, String(count)), (0, react.createElement)("span", { "data-role": "task-banner-text" }, text));
|
|
344
|
+
}
|
|
345
|
+
//#endregion
|
|
346
|
+
//#region ../evolution-client-kit/src/presentation/chips.ts
|
|
347
|
+
/** Read-only status chips and toggleable filter chips. */
|
|
348
|
+
//#endregion
|
|
349
|
+
//#region ../evolution-client-kit/src/presentation/empty-state.ts
|
|
350
|
+
/** A compact completed/empty state with at most one primary next step. */
|
|
351
|
+
//#endregion
|
|
352
|
+
//#region ../evolution-client-kit/src/presentation/disclosure-group.ts
|
|
353
|
+
/** A native details group for normal/secondary facts. */
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region ../evolution-client-kit/src/presentation/time-text.ts
|
|
356
|
+
/** The one local-time presentation used by reading surfaces. */
|
|
357
|
+
//#endregion
|
|
358
|
+
//#region ../evolution-client-kit/src/presentation/action-menu.ts
|
|
359
|
+
/**
|
|
360
|
+
* The one seam onto the platform's menu material, plus a small fallback for deployments
|
|
361
|
+
* without the primitive row. No page owns a second menu implementation.
|
|
362
|
+
*/
|
|
363
|
+
const PLATFORM_UI_MODULE$1 = "@deepseek-ai/dsh-client-ui-primitives";
|
|
364
|
+
/**
|
|
365
|
+
* Render the platform menu directly. Kept exported for callers that already own the primitive row.
|
|
366
|
+
* @param primitives - platform MenuSurface/MenuItemButton pair.
|
|
367
|
+
* @param actions - rows in display order.
|
|
368
|
+
* @param label - accessible menu name.
|
|
369
|
+
* @param style - fixed position computed from the pointer.
|
|
370
|
+
* @param className - optional surface class.
|
|
371
|
+
* @returns the menu element.
|
|
372
|
+
*/
|
|
373
|
+
function renderPlatformMenu(primitives, actions, label, style, className) {
|
|
374
|
+
return (0, react.createElement)(primitives.MenuSurface, {
|
|
375
|
+
"data-role": "action-menu",
|
|
376
|
+
"data-platform": "true",
|
|
377
|
+
role: "menu",
|
|
378
|
+
"aria-label": label,
|
|
379
|
+
...className === void 0 ? {} : { className },
|
|
380
|
+
style
|
|
381
|
+
}, actions.map((action) => (0, react.createElement)(primitives.MenuItemButton, {
|
|
382
|
+
key: action.id,
|
|
383
|
+
children: action.label,
|
|
384
|
+
...action.separatorBefore === true ? { separatorBefore: true } : {},
|
|
385
|
+
...action.disabled === true ? { disabled: true } : {},
|
|
386
|
+
...action.danger === true ? { danger: true } : {},
|
|
387
|
+
onSelect: action.onSelect
|
|
388
|
+
})));
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Accept only the two component functions; a namespace row without them is not a menu.
|
|
392
|
+
* @param row - the module row's exports.
|
|
393
|
+
* @returns the two components, or undefined.
|
|
394
|
+
*/
|
|
395
|
+
function menuPrimitivesFrom(row) {
|
|
396
|
+
const surface = row.MenuSurface;
|
|
397
|
+
const item = row.MenuItemButton;
|
|
398
|
+
if (typeof surface !== "function" || typeof item !== "function") return void 0;
|
|
399
|
+
return {
|
|
400
|
+
MenuSurface: surface,
|
|
401
|
+
MenuItemButton: item
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
/** The module-table row, when this deployment carries it. */
|
|
405
|
+
const PLATFORM_MENU = (() => {
|
|
406
|
+
try {
|
|
407
|
+
return menuPrimitivesFrom(require(PLATFORM_UI_MODULE$1));
|
|
408
|
+
} catch {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
})();
|
|
412
|
+
//#endregion
|
|
294
413
|
//#region src/client/api.ts
|
|
295
414
|
/** Read-only merge wire client. Classifies every failure and never writes. */
|
|
296
415
|
const HOST_ROUTES = ROUTES.merge;
|
|
@@ -660,7 +779,8 @@ window.__ModuleLoader__.load({
|
|
|
660
779
|
const NS = "evolution-merge";
|
|
661
780
|
const zh = {
|
|
662
781
|
"entry.label": "技能合并",
|
|
663
|
-
"title": "
|
|
782
|
+
"title": "合并建议",
|
|
783
|
+
"task.pending": "条合并建议待处理",
|
|
664
784
|
"start.scan": "复制扫描命令",
|
|
665
785
|
"start.pair": "复制配对命令模板",
|
|
666
786
|
"degraded": "读模型降级:",
|
|
@@ -670,7 +790,7 @@ window.__ModuleLoader__.load({
|
|
|
670
790
|
"row.noSummary": "无摘要",
|
|
671
791
|
"row.summaryBoth": "双方摘要",
|
|
672
792
|
"overlay.body": "正文",
|
|
673
|
-
"hint": "
|
|
793
|
+
"hint": "先处理需要判断的合并,其他信息按需展开。",
|
|
674
794
|
"history": "历史",
|
|
675
795
|
"close": "关闭",
|
|
676
796
|
"tab.verify": "待判断",
|
|
@@ -713,6 +833,8 @@ window.__ModuleLoader__.load({
|
|
|
713
833
|
"row.noRetry": "不可重试",
|
|
714
834
|
"row.copy": "复制命令",
|
|
715
835
|
"row.more": "更多命令",
|
|
836
|
+
"row.viewBoth": "查看双方",
|
|
837
|
+
"overlay.pair": "查看双方",
|
|
716
838
|
"tab.expired": "已过期",
|
|
717
839
|
"row.targetCreated": "新建",
|
|
718
840
|
"row.verify": "判定状态",
|
|
@@ -869,7 +991,8 @@ window.__ModuleLoader__.load({
|
|
|
869
991
|
});
|
|
870
992
|
const en = {
|
|
871
993
|
"entry.label": "Skill merge",
|
|
872
|
-
"title": "
|
|
994
|
+
"title": "Merge suggestions",
|
|
995
|
+
"task.pending": "merge suggestions need attention",
|
|
873
996
|
"start.scan": "Copy scan command",
|
|
874
997
|
"start.pair": "Copy pair command template",
|
|
875
998
|
"degraded": "Degraded read model:",
|
|
@@ -879,7 +1002,7 @@ window.__ModuleLoader__.load({
|
|
|
879
1002
|
"row.noSummary": "No summary",
|
|
880
1003
|
"row.summaryBoth": "Shared summary",
|
|
881
1004
|
"overlay.body": "Body",
|
|
882
|
-
"hint": "
|
|
1005
|
+
"hint": "Resolve the merges that need a decision first; everything else stays folded.",
|
|
883
1006
|
"history": "History",
|
|
884
1007
|
"close": "Close",
|
|
885
1008
|
"tab.verify": "To judge",
|
|
@@ -922,6 +1045,8 @@ window.__ModuleLoader__.load({
|
|
|
922
1045
|
"row.noRetry": "not retryable",
|
|
923
1046
|
"row.copy": "Copy command",
|
|
924
1047
|
"row.more": "More commands",
|
|
1048
|
+
"row.viewBoth": "View both",
|
|
1049
|
+
"overlay.pair": "View both",
|
|
925
1050
|
"tab.expired": "Expired",
|
|
926
1051
|
"row.targetCreated": "created",
|
|
927
1052
|
"row.verify": "Verify state",
|
|
@@ -1124,6 +1249,30 @@ window.__ModuleLoader__.load({
|
|
|
1124
1249
|
".evolution-merge-panel [data-role=\"title\"] { margin:0; font-size:var(--evo-type-lg); font-weight:600; }",
|
|
1125
1250
|
".evolution-merge-panel [data-role=\"start\"] { display:flex; gap:var(--evo-space-6); flex-wrap:wrap; }",
|
|
1126
1251
|
".evolution-merge-panel [data-role=\"degraded\"] { margin:0; color:var(--dsw-alias-state-warn-primary); font-size:var(--evo-type-xs); }",
|
|
1252
|
+
".evolution-merge-panel [data-role=\"task-banner\"] { display:flex; align-items:baseline; gap:var(--evo-space-6); padding:var(--evo-space-10) var(--evo-space-12); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); background:var(--dsw-alias-bg-layer-1); color:var(--dsw-alias-label-primary); }",
|
|
1253
|
+
".evolution-merge-panel [data-role=\"task-banner-count\"] { font-size:var(--evo-type-lg); font-variant-numeric:tabular-nums; }",
|
|
1254
|
+
".evolution-merge-panel [data-role=\"task-banner-text\"] { color:var(--dsw-alias-label-secondary); font-size:var(--evo-type-sm); }",
|
|
1255
|
+
".evolution-merge-panel .merge-decision { display:flex; flex-direction:column; gap:var(--evo-space-8); padding:var(--evo-space-12); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); background:var(--dsw-alias-bg-layer-1); }",
|
|
1256
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-title\"] { margin:0; font-size:var(--evo-type-sm); font-weight:600; }",
|
|
1257
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-summary\"] { margin:0; color:var(--dsw-alias-label-secondary); font-size:var(--evo-type-xs); }",
|
|
1258
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-facts\"] { display:grid; grid-template-columns:max-content minmax(0,1fr); gap:var(--evo-space-4) var(--evo-space-12); margin:0; font-size:var(--evo-type-xs); }",
|
|
1259
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-fact\"] { display:contents; }",
|
|
1260
|
+
".evolution-merge-panel .merge-decision dt { color:var(--dsw-alias-label-tertiary); }",
|
|
1261
|
+
".evolution-merge-panel .merge-decision dd { margin:0; min-width:0; overflow-wrap:anywhere; }",
|
|
1262
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-actions\"] { display:flex; flex-wrap:wrap; align-items:center; gap:var(--evo-space-8); padding-top:var(--evo-space-8); }",
|
|
1263
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-primary\"], .evolution-merge-panel .merge-decision [data-role=\"decision-secondary\"], .evolution-merge-panel .merge-decision [data-role=\"view-both\"] { padding:var(--evo-space-6) var(--evo-space-12); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); background:var(--dsw-alias-bg-layer-1); color:var(--dsw-alias-label-primary); font-size:var(--evo-type-sm); cursor:pointer; }",
|
|
1264
|
+
".evolution-merge-panel [data-role=\"pair-grid\"] { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--evo-space-12); }",
|
|
1265
|
+
".evolution-merge-panel [data-role=\"body-a\"], .evolution-merge-panel [data-role=\"body-b\"] { min-width:0; }",
|
|
1266
|
+
".evolution-merge-panel [data-role=\"body-a\"] pre, .evolution-merge-panel [data-role=\"body-b\"] pre { max-height:min(52vh,560px); overflow:auto; white-space:pre-wrap; }",
|
|
1267
|
+
"@media (max-width:900px){.evolution-merge-panel [data-role=\"pair-grid\"]{grid-template-columns:minmax(0,1fr)}}",
|
|
1268
|
+
".evo-merge-modal [data-role=\"pair-grid\"]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--evo-space-12)}",
|
|
1269
|
+
".evo-merge-modal [data-role=\"body-a\"],.evo-merge-modal [data-role=\"body-b\"]{min-width:0}",
|
|
1270
|
+
".evo-merge-modal [data-role=\"body-a\"] pre,.evo-merge-modal [data-role=\"body-b\"] pre{max-height:min(52vh,560px);overflow:auto;white-space:pre-wrap}",
|
|
1271
|
+
"@media (max-width:900px){.evo-merge-modal [data-role=\"pair-grid\"]{grid-template-columns:minmax(0,1fr)}}",
|
|
1272
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-primary\"] { background:var(--dsw-alias-label-primary); border-color:transparent; color:var(--dsw-alias-label-primary-foreground); }",
|
|
1273
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-primary\"]:disabled, .evolution-merge-panel .merge-decision [data-role=\"decision-secondary\"]:disabled, .evolution-merge-panel .merge-decision [data-role=\"view-both\"]:disabled { color:var(--dsw-alias-label-dimmed); cursor:default; }",
|
|
1274
|
+
".evolution-merge-panel .merge-decision [data-role=\"decision-details\"] { display:flex; flex-direction:column; gap:var(--evo-space-4); }",
|
|
1275
|
+
".evolution-merge-panel [data-role=\"row-actions\"] { display:flex; align-items:center; justify-content:flex-end; gap:var(--evo-space-8); }",
|
|
1127
1276
|
".evolution-merge-panel [data-role=\"expired-toggle\"] { display:inline-flex; align-items:center; gap:var(--evo-space-4); border:var(--evo-hairline-width) solid var(--dsw-alias-border-secondary); border-radius:var(--evo-radius-control); background:transparent; color:var(--dsw-alias-label-secondary); font:inherit; font-size:var(--evo-type-xs); padding:var(--evo-space-4) var(--evo-space-8); cursor:pointer; }",
|
|
1128
1277
|
".evolution-merge-panel [data-role=\"expired-toggle\"][data-active=\"true\"] { color:var(--dsw-alias-state-warn-primary); border-color:var(--dsw-alias-state-warn-primary); background:transparent; }",
|
|
1129
1278
|
".evolution-merge-panel [data-role=\"failure\"] { display:flex; flex-direction:column; gap:var(--evo-space-6); }",
|
|
@@ -1140,7 +1289,7 @@ window.__ModuleLoader__.load({
|
|
|
1140
1289
|
".evolution-merge-panel [data-role=\"overlay-head\"] { display:flex; align-items:center; justify-content:space-between; gap:var(--evo-space-8); }",
|
|
1141
1290
|
".evolution-merge-panel [data-role=\"overlay-title\"] { margin:0; font-size:var(--evo-type-lg); }",
|
|
1142
1291
|
".evolution-merge-panel [data-role=\"rows\"] { display:flex; flex-direction:column; gap:var(--evo-space-6); }",
|
|
1143
|
-
".evolution-merge-panel [data-role=\"row\"] { display:
|
|
1292
|
+
".evolution-merge-panel [data-role=\"row\"] { display:flex; flex-direction:column; gap:var(--evo-space-6); padding:var(--evo-space-8); border:var(--evo-hairline-width) solid var(--dsw-alias-border-l2); border-radius:var(--evo-radius-control); cursor:grab; }",
|
|
1144
1293
|
".evolution-merge-panel [data-role=\"row\"]:active { cursor:grabbing; }",
|
|
1145
1294
|
".evolution-merge-panel [data-role=\"row-label\"] { font-weight:600; }",
|
|
1146
1295
|
".evolution-merge-panel [data-role=\"row-meta\"] { color:var(--dsw-alias-label-tertiary); font-size:var(--evo-type-xs); }",
|
|
@@ -1180,7 +1329,7 @@ window.__ModuleLoader__.load({
|
|
|
1180
1329
|
].join("\n");
|
|
1181
1330
|
//#endregion
|
|
1182
1331
|
//#region src/client/platform-modal.ts
|
|
1183
|
-
const PLATFORM_UI_MODULE
|
|
1332
|
+
const PLATFORM_UI_MODULE = "@deepseek-ai/dsh-client-ui-primitives";
|
|
1184
1333
|
let cached;
|
|
1185
1334
|
/** The platform Modal, or undefined in a non-browser/SSR render or a deployment without the row. */
|
|
1186
1335
|
function platformModal() {
|
|
@@ -1190,7 +1339,7 @@ window.__ModuleLoader__.load({
|
|
|
1190
1339
|
return;
|
|
1191
1340
|
}
|
|
1192
1341
|
try {
|
|
1193
|
-
const row = require(PLATFORM_UI_MODULE
|
|
1342
|
+
const row = require(PLATFORM_UI_MODULE);
|
|
1194
1343
|
cached = typeof row.Modal === "function" ? row.Modal : null;
|
|
1195
1344
|
} catch {
|
|
1196
1345
|
cached = null;
|
|
@@ -1198,61 +1347,6 @@ window.__ModuleLoader__.load({
|
|
|
1198
1347
|
return cached ?? void 0;
|
|
1199
1348
|
}
|
|
1200
1349
|
//#endregion
|
|
1201
|
-
//#region src/client/platform-menu.ts
|
|
1202
|
-
/**
|
|
1203
|
-
* The one seam onto the platform's menu material and rows.
|
|
1204
|
-
*
|
|
1205
|
-
* The family bundle keeps `@deepseek-ai/*` external, so the platform components are reached through
|
|
1206
|
-
* the loader-provided `require` (the same door the Markdown seam uses). A deployment without the
|
|
1207
|
-
* row gets the panel's own menu fallback; the platform path is not a hard dependency.
|
|
1208
|
-
* @module dsh-evolution-merge-ui/client
|
|
1209
|
-
*/
|
|
1210
|
-
const PLATFORM_UI_MODULE = "@deepseek-ai/dsh-client-ui-primitives";
|
|
1211
|
-
/**
|
|
1212
|
-
* Render the coordinate menu through the platform primitives.
|
|
1213
|
-
* @param primitives - the platform MenuSurface/MenuItemButton pair.
|
|
1214
|
-
* @param actions - rows in display order.
|
|
1215
|
-
* @param label - accessible menu name.
|
|
1216
|
-
* @param style - fixed position computed from the pointer.
|
|
1217
|
-
* @returns the menu element.
|
|
1218
|
-
*/
|
|
1219
|
-
function renderPlatformMenu(primitives, actions, label, style) {
|
|
1220
|
-
return (0, react.createElement)(primitives.MenuSurface, {
|
|
1221
|
-
"data-role": "sort-menu",
|
|
1222
|
-
"data-platform": "true",
|
|
1223
|
-
role: "menu",
|
|
1224
|
-
"aria-label": label,
|
|
1225
|
-
style
|
|
1226
|
-
}, actions.map((action) => (0, react.createElement)(primitives.MenuItemButton, {
|
|
1227
|
-
key: action.id,
|
|
1228
|
-
children: action.label,
|
|
1229
|
-
...action.separatorBefore === true ? { separatorBefore: true } : {},
|
|
1230
|
-
onSelect: action.onSelect
|
|
1231
|
-
})));
|
|
1232
|
-
}
|
|
1233
|
-
/**
|
|
1234
|
-
* Accept only the two component functions; a namespace row without them is not a menu.
|
|
1235
|
-
* @param row - the module row's exports.
|
|
1236
|
-
* @returns the two components, or undefined.
|
|
1237
|
-
*/
|
|
1238
|
-
function menuPrimitivesFrom(row) {
|
|
1239
|
-
const surface = row.MenuSurface;
|
|
1240
|
-
const item = row.MenuItemButton;
|
|
1241
|
-
if (typeof surface !== "function" || typeof item !== "function") return void 0;
|
|
1242
|
-
return {
|
|
1243
|
-
MenuSurface: surface,
|
|
1244
|
-
MenuItemButton: item
|
|
1245
|
-
};
|
|
1246
|
-
}
|
|
1247
|
-
/** The module-table row, when this deployment carries it. */
|
|
1248
|
-
const PLATFORM_MENU = (() => {
|
|
1249
|
-
try {
|
|
1250
|
-
return menuPrimitivesFrom(require(PLATFORM_UI_MODULE));
|
|
1251
|
-
} catch {
|
|
1252
|
-
return;
|
|
1253
|
-
}
|
|
1254
|
-
})();
|
|
1255
|
-
//#endregion
|
|
1256
1350
|
//#region src/client/sorting.ts
|
|
1257
1351
|
/** Workspace scope for one tab. A missing panel workspace is the local scope. */
|
|
1258
1352
|
function resolveWorkspaceId(workspaceId) {
|
|
@@ -1443,7 +1537,7 @@ window.__ModuleLoader__.load({
|
|
|
1443
1537
|
}
|
|
1444
1538
|
//#endregion
|
|
1445
1539
|
//#region src/client/MergeRow.ts
|
|
1446
|
-
/** One merge row: summary, stage, facts, primary
|
|
1540
|
+
/** One merge row: summary, stage, facts, one primary decision and the copy/sort drawer. */
|
|
1447
1541
|
function reasonText$1(t, reasonCode, fallback) {
|
|
1448
1542
|
return reasonCode === void 0 ? fallback : t("history.reason." + reasonCode);
|
|
1449
1543
|
}
|
|
@@ -1469,18 +1563,13 @@ window.__ModuleLoader__.load({
|
|
|
1469
1563
|
}, t("stage.state." + stage.state) + expiry);
|
|
1470
1564
|
}
|
|
1471
1565
|
/**
|
|
1472
|
-
* Render one row.
|
|
1566
|
+
* Render one row as a decision card. The approve action is the only primary; A/B, reject and
|
|
1567
|
+
* auxiliary sort/copy commands cannot borrow that weight.
|
|
1473
1568
|
* @param props - row, translator, copier, sort hooks, body opener and decision callback.
|
|
1474
|
-
* @returns the row
|
|
1569
|
+
* @returns the row with drag/keyboard wiring and a separate more drawer.
|
|
1475
1570
|
*/
|
|
1476
1571
|
function MergeRow(props) {
|
|
1477
|
-
const { row, t, copy, sort,
|
|
1478
|
-
const first = [
|
|
1479
|
-
row.target === void 0 ? void 0 : t("row.target") + " " + row.target,
|
|
1480
|
-
row.failure === void 0 ? void 0 : t("row.failure") + " " + row.failure.code + (row.failure.retryable ? "" : " · " + t("row.noRetry")),
|
|
1481
|
-
row.expired === void 0 ? void 0 : t("row.expired") + " " + t("expired." + row.expired),
|
|
1482
|
-
row.reasonCode === void 0 && row.reason === void 0 ? void 0 : t("row.reason") + " " + reasonText$1(t, row.reasonCode, row.reason ?? "")
|
|
1483
|
-
].filter((value) => value !== void 0).join(" · ");
|
|
1572
|
+
const { row, t, copy, sort, openBoth, onDecide, busy } = props;
|
|
1484
1573
|
const details = [
|
|
1485
1574
|
t("row.id") + " " + row.id,
|
|
1486
1575
|
row.targetActual === void 0 ? void 0 : t("row.actualTarget") + " " + row.targetActual,
|
|
@@ -1489,23 +1578,83 @@ window.__ModuleLoader__.load({
|
|
|
1489
1578
|
row.attempts === void 0 ? void 0 : t("row.attempts") + " " + String(row.attempts),
|
|
1490
1579
|
row.confidence === void 0 ? void 0 : t("row.confidence") + " " + row.confidence.toFixed(2)
|
|
1491
1580
|
].filter((value) => value !== void 0).join(" · ");
|
|
1492
|
-
const
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1581
|
+
const approve = row.actions.find((action) => action.id === "approve");
|
|
1582
|
+
const reject = row.actions.find((action) => action.id === "reject");
|
|
1583
|
+
const bodyA = row.bodies?.find((body) => body.name === row.a);
|
|
1584
|
+
const bodyB = row.bodies?.find((body) => body.name === row.b);
|
|
1585
|
+
const primary = approve === void 0 ? void 0 : {
|
|
1586
|
+
id: "approve",
|
|
1587
|
+
label: t("decision.approve"),
|
|
1588
|
+
disabled: !approve.enabled || busy || onDecide === void 0,
|
|
1589
|
+
...approve.disabledReason === void 0 ? {} : { attributes: { "data-disabled-reason": approve.disabledReason } },
|
|
1590
|
+
onSelect: () => {
|
|
1591
|
+
if (approve.enabled && !busy && onDecide !== void 0) onDecide(row.id, "approve");
|
|
1592
|
+
}
|
|
1593
|
+
};
|
|
1594
|
+
const secondary = [];
|
|
1595
|
+
if (approve !== void 0 && onDecide === void 0) secondary.push({
|
|
1596
|
+
id: "approve",
|
|
1597
|
+
label: t("action.approve"),
|
|
1598
|
+
disabled: !approve.enabled || busy,
|
|
1599
|
+
attributes: { "data-role": "row-action" },
|
|
1600
|
+
onSelect: () => {
|
|
1601
|
+
if (approve.enabled && !busy) copy(approve.command);
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1604
|
+
if (reject !== void 0) secondary.push({
|
|
1605
|
+
id: "reject",
|
|
1606
|
+
label: t("decision.reject"),
|
|
1607
|
+
disabled: !reject.enabled || busy || onDecide === void 0,
|
|
1608
|
+
...reject.disabledReason === void 0 ? {} : { attributes: { "data-disabled-reason": reject.disabledReason } },
|
|
1609
|
+
onSelect: () => {
|
|
1610
|
+
if (reject.enabled && !busy && onDecide !== void 0) onDecide(row.id, "reject");
|
|
1611
|
+
}
|
|
1612
|
+
});
|
|
1613
|
+
if (bodyA !== void 0 && bodyB !== void 0) secondary.push({
|
|
1614
|
+
id: "view-both",
|
|
1615
|
+
label: t("row.viewBoth"),
|
|
1616
|
+
attributes: { "data-role": "view-both" },
|
|
1617
|
+
onSelect: () => {
|
|
1618
|
+
openBoth({
|
|
1619
|
+
name: bodyA.name,
|
|
1620
|
+
side: bodyA.side
|
|
1621
|
+
}, {
|
|
1622
|
+
name: bodyB.name,
|
|
1623
|
+
side: bodyB.side
|
|
1624
|
+
}, bodyA.rowId);
|
|
1625
|
+
}
|
|
1626
|
+
});
|
|
1627
|
+
for (const action of row.actions) {
|
|
1628
|
+
if (action.id === "approve" || action.id === "reject" || action.id === "copy" || action.id === "discard") continue;
|
|
1629
|
+
secondary.push({
|
|
1630
|
+
id: action.id,
|
|
1631
|
+
label: t("action." + action.id),
|
|
1501
1632
|
disabled: !action.enabled || busy,
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
if (
|
|
1505
|
-
else copy(action.command);
|
|
1633
|
+
attributes: { "data-role": "row-action" },
|
|
1634
|
+
onSelect: () => {
|
|
1635
|
+
if (action.enabled && !busy) copy(action.command);
|
|
1506
1636
|
}
|
|
1507
|
-
}
|
|
1508
|
-
}
|
|
1637
|
+
});
|
|
1638
|
+
}
|
|
1639
|
+
const facts = [
|
|
1640
|
+
...row.target === void 0 ? [] : [{
|
|
1641
|
+
label: t("row.target"),
|
|
1642
|
+
value: row.target
|
|
1643
|
+
}],
|
|
1644
|
+
...row.failure === void 0 ? [] : [{
|
|
1645
|
+
label: t("row.failure"),
|
|
1646
|
+
value: row.failure.code + (row.failure.retryable ? "" : " · " + t("row.noRetry"))
|
|
1647
|
+
}],
|
|
1648
|
+
...row.expired === void 0 ? [] : [{
|
|
1649
|
+
label: t("row.expired"),
|
|
1650
|
+
value: t("expired." + row.expired)
|
|
1651
|
+
}],
|
|
1652
|
+
...row.reasonCode === void 0 && row.reason === void 0 ? [] : [{
|
|
1653
|
+
label: t("row.reason"),
|
|
1654
|
+
value: reasonText$1(t, row.reasonCode, row.reason ?? "")
|
|
1655
|
+
}]
|
|
1656
|
+
];
|
|
1657
|
+
const decisionDetails = (0, react.createElement)("div", null, stageNode(row, t), summaryNode(row, t), bodyA === void 0 || bodyB === void 0 ? null : (0, react.createElement)("div", { "data-role": "body-names" }, "A · " + bodyA.name + " · B · " + bodyB.name), (0, react.createElement)("details", { "data-role": "row-details" }, (0, react.createElement)("summary", null, t("row.details")), (0, react.createElement)("p", null, details)));
|
|
1509
1658
|
return (0, react.createElement)("div", {
|
|
1510
1659
|
key: row.id,
|
|
1511
1660
|
"data-role": "row",
|
|
@@ -1545,7 +1694,16 @@ window.__ModuleLoader__.load({
|
|
|
1545
1694
|
event.preventDefault();
|
|
1546
1695
|
sort.menu(row.id, event.clientX, event.clientY);
|
|
1547
1696
|
}
|
|
1548
|
-
}, (0, react.createElement)(
|
|
1697
|
+
}, (0, react.createElement)(DecisionFrame, {
|
|
1698
|
+
className: "merge-decision",
|
|
1699
|
+
decision: {
|
|
1700
|
+
title: row.label,
|
|
1701
|
+
facts,
|
|
1702
|
+
...primary === void 0 ? {} : { primary },
|
|
1703
|
+
...secondary.length === 0 ? {} : { secondary },
|
|
1704
|
+
details: decisionDetails
|
|
1705
|
+
}
|
|
1706
|
+
}), (0, react.createElement)("div", { "data-role": "row-actions" }, (0, react.createElement)("div", { "data-role": "row-meta" }, new Date(row.updatedAt).toLocaleString()), (0, react.createElement)("details", { "data-role": "row-more" }, (0, react.createElement)("summary", null, t("row.more")), (0, react.createElement)("button", {
|
|
1549
1707
|
type: "button",
|
|
1550
1708
|
"data-role": "row-sort",
|
|
1551
1709
|
"aria-haspopup": "menu",
|
|
@@ -1554,29 +1712,7 @@ window.__ModuleLoader__.load({
|
|
|
1554
1712
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
1555
1713
|
sort.menu(row.id, rect.left, rect.bottom);
|
|
1556
1714
|
}
|
|
1557
|
-
}, t("sort.menu")), (() => {
|
|
1558
|
-
const bodyA = row.bodies?.find((body) => body.name === row.a);
|
|
1559
|
-
const bodyB = row.bodies?.find((body) => body.name === row.b);
|
|
1560
|
-
return [bodyA === void 0 ? null : (0, react.createElement)("button", {
|
|
1561
|
-
key: "a",
|
|
1562
|
-
type: "button",
|
|
1563
|
-
"data-role": "body-a",
|
|
1564
|
-
"aria-label": t("body." + bodyA.side) + " " + bodyA.name,
|
|
1565
|
-
title: t("body." + bodyA.side) + " " + bodyA.name,
|
|
1566
|
-
onClick: () => {
|
|
1567
|
-
openBody(bodyA.name, bodyA.side, bodyA.rowId);
|
|
1568
|
-
}
|
|
1569
|
-
}, "A · " + bodyA.name), bodyB === void 0 ? null : (0, react.createElement)("button", {
|
|
1570
|
-
key: "b",
|
|
1571
|
-
type: "button",
|
|
1572
|
-
"data-role": "body-b",
|
|
1573
|
-
"aria-label": t("body." + bodyB.side) + " " + bodyB.name,
|
|
1574
|
-
title: t("body." + bodyB.side) + " " + bodyB.name,
|
|
1575
|
-
onClick: () => {
|
|
1576
|
-
openBody(bodyB.name, bodyB.side, bodyB.rowId);
|
|
1577
|
-
}
|
|
1578
|
-
}, "B · " + bodyB.name)];
|
|
1579
|
-
})(), actions), (0, react.createElement)("details", { "data-role": "row-more" }, (0, react.createElement)("summary", null, t("row.more")), ...row.actions.map((action) => (0, react.createElement)("button", {
|
|
1715
|
+
}, t("sort.menu")), ...row.actions.map((action) => (0, react.createElement)("button", {
|
|
1580
1716
|
key: "copy-" + action.id,
|
|
1581
1717
|
type: "button",
|
|
1582
1718
|
"data-role": "row-copy",
|
|
@@ -1770,6 +1906,39 @@ window.__ModuleLoader__.load({
|
|
|
1770
1906
|
className: "evo-merge-modal"
|
|
1771
1907
|
}, inner);
|
|
1772
1908
|
}
|
|
1909
|
+
function pairNode(overlay, t, onClose) {
|
|
1910
|
+
const Modal = platformModal();
|
|
1911
|
+
const title = t("overlay.pair");
|
|
1912
|
+
const block = (target, body) => (0, react.createElement)("section", {
|
|
1913
|
+
"data-role": target === overlay.a ? "body-a" : "body-b",
|
|
1914
|
+
"data-side": target.side
|
|
1915
|
+
}, (0, react.createElement)("h4", { "data-role": "pair-name" }, target.name + " · " + t("body." + target.side)), body === void 0 ? null : body.truncated ? (0, react.createElement)("p", { "data-role": "body-truncated" }, t("body.truncated")) : null, body === void 0 ? null : body.text === "" ? (0, react.createElement)("p", { "data-role": "body-empty" }, t("body.empty")) : (0, react.createElement)("pre", { "data-role": "body-text" }, body.text));
|
|
1916
|
+
const inner = (0, react.createElement)("section", {
|
|
1917
|
+
"data-role": "overlay",
|
|
1918
|
+
"data-overlay": "pair",
|
|
1919
|
+
"aria-label": title,
|
|
1920
|
+
...Modal === void 0 ? {
|
|
1921
|
+
role: "dialog",
|
|
1922
|
+
"aria-modal": "true",
|
|
1923
|
+
onKeyDown: (event) => {
|
|
1924
|
+
overlayKey(event, onClose);
|
|
1925
|
+
}
|
|
1926
|
+
} : { "data-platform-modal": "true" }
|
|
1927
|
+
}, (0, react.createElement)("div", { "data-role": "overlay-head" }, (0, react.createElement)("h3", { "data-role": "overlay-title" }, title), (0, react.createElement)("button", {
|
|
1928
|
+
type: "button",
|
|
1929
|
+
"data-role": "overlay-close",
|
|
1930
|
+
...Modal === void 0 ? { autoFocus: true } : { "data-modal-autofocus": "true" },
|
|
1931
|
+
onClick: onClose
|
|
1932
|
+
}, t("close"))), overlay.status === "loading" ? (0, react.createElement)("p", { "data-role": "overlay-loading" }, t("loading")) : null, overlay.status === "error" && overlay.failure !== void 0 ? failureNode(t, overlay.failure, [], () => {}) : null, overlay.status === "ready" ? (0, react.createElement)("div", { "data-role": "pair-grid" }, block(overlay.a, overlay.aBody), block(overlay.b, overlay.bBody)) : null);
|
|
1933
|
+
return Modal === void 0 ? inner : (0, react.createElement)(Modal, {
|
|
1934
|
+
open: true,
|
|
1935
|
+
onClose,
|
|
1936
|
+
title,
|
|
1937
|
+
closeLabel: t("close"),
|
|
1938
|
+
headless: true,
|
|
1939
|
+
className: "evo-merge-modal"
|
|
1940
|
+
}, inner);
|
|
1941
|
+
}
|
|
1773
1942
|
function historyNode(overlay, t, onClose) {
|
|
1774
1943
|
const Modal = platformModal();
|
|
1775
1944
|
const title = t("history");
|
|
@@ -1822,9 +1991,9 @@ window.__ModuleLoader__.load({
|
|
|
1822
1991
|
const captureFocus = () => {
|
|
1823
1992
|
returnFocus.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
1824
1993
|
};
|
|
1825
|
-
const
|
|
1994
|
+
const openBoth = (a, b, rowId) => {
|
|
1826
1995
|
captureFocus();
|
|
1827
|
-
store.
|
|
1996
|
+
store.openPair(a, b, rowId);
|
|
1828
1997
|
};
|
|
1829
1998
|
const openHistory = () => {
|
|
1830
1999
|
captureFocus();
|
|
@@ -1992,6 +2161,10 @@ window.__ModuleLoader__.load({
|
|
|
1992
2161
|
"data-role": "decision-notice",
|
|
1993
2162
|
"data-ok": decisionNotice.ok ? "true" : "false"
|
|
1994
2163
|
}, decisionNotice.message);
|
|
2164
|
+
const taskBanner = view.counts.pending > 0 ? (0, react.createElement)(TaskBanner, {
|
|
2165
|
+
count: view.counts.pending,
|
|
2166
|
+
text: t("task.pending")
|
|
2167
|
+
}) : null;
|
|
1995
2168
|
const list = uiState === "ready" && queue.status === "ready" ? (0, react.createElement)("div", {
|
|
1996
2169
|
"data-role": "rows",
|
|
1997
2170
|
id: "merge-rows",
|
|
@@ -2001,7 +2174,7 @@ window.__ModuleLoader__.load({
|
|
|
2001
2174
|
t,
|
|
2002
2175
|
copy,
|
|
2003
2176
|
sort: sortHandlers,
|
|
2004
|
-
|
|
2177
|
+
openBoth,
|
|
2005
2178
|
onDecide: face.decide === void 0 ? void 0 : decideRow,
|
|
2006
2179
|
busy: deciding === row.id
|
|
2007
2180
|
}))) : null;
|
|
@@ -2070,26 +2243,7 @@ window.__ModuleLoader__.load({
|
|
|
2070
2243
|
return (0, react.createElement)("section", {
|
|
2071
2244
|
className: CSS_TAG_ID,
|
|
2072
2245
|
"data-state": uiState
|
|
2073
|
-
}, (0, react.createElement)("h2", { "data-role": "title" }, t("title")), (0, react.createElement)("p", { "data-role": "hint" }, t("hint")), blocked !== void 0 ? failureNode(t, blocked, fallback, copy) : (0, react.createElement)("div", { "data-role": "content" }, (0, react.createElement)("
|
|
2074
|
-
type: "button",
|
|
2075
|
-
"data-role": "start-scan",
|
|
2076
|
-
onClick: () => {
|
|
2077
|
-
copy(view.startCommands.scan);
|
|
2078
|
-
}
|
|
2079
|
-
}, t("start.scan")), (0, react.createElement)("button", {
|
|
2080
|
-
type: "button",
|
|
2081
|
-
"data-role": "start-pair",
|
|
2082
|
-
onClick: () => {
|
|
2083
|
-
copy(view.startCommands.pair);
|
|
2084
|
-
}
|
|
2085
|
-
}, t("start.pair"))), view.degraded ? (0, react.createElement)("p", { "data-role": "degraded" }, t("degraded") + " " + view.notes.join(",")) : null, (0, react.createElement)(MergeSettings, {
|
|
2086
|
-
view,
|
|
2087
|
-
t
|
|
2088
|
-
}), (0, react.createElement)(MergeRunStrips, {
|
|
2089
|
-
view,
|
|
2090
|
-
t,
|
|
2091
|
-
copy
|
|
2092
|
-
}), tabs, expiredToggle, snapshot.viewState === "loading" || queue.status === "loading" ? (0, react.createElement)("p", { "data-role": "note" }, t("loading")) : queue.refreshing === true ? (0, react.createElement)("p", {
|
|
2246
|
+
}, (0, react.createElement)("h2", { "data-role": "title" }, t("title")), (0, react.createElement)("p", { "data-role": "hint" }, t("hint")), blocked !== void 0 ? failureNode(t, blocked, fallback, copy) : (0, react.createElement)("div", { "data-role": "content" }, taskBanner, snapshot.viewState === "loading" || queue.status === "loading" ? (0, react.createElement)("p", { "data-role": "note" }, t("loading")) : queue.refreshing === true ? (0, react.createElement)("p", {
|
|
2093
2247
|
"data-role": "note",
|
|
2094
2248
|
role: "status"
|
|
2095
2249
|
}, t("refreshing")) : null, activeFailure === void 0 ? null : failureNode(t, activeFailure, fallback, copy), copyState.kind === "idle" ? null : copyState.kind === "copied" ? (0, react.createElement)("p", {
|
|
@@ -2104,14 +2258,33 @@ window.__ModuleLoader__.load({
|
|
|
2104
2258
|
onClick: () => {
|
|
2105
2259
|
if (copyState.text !== void 0) copy(copyState.text);
|
|
2106
2260
|
}
|
|
2107
|
-
}, t("copyRetry"))), notice, list, empty, queue.nextCursor === void 0 || uiState !== "ready" ? null : (0, react.createElement)("button", {
|
|
2261
|
+
}, t("copyRetry"))), notice, list, tabs, expiredToggle, empty, queue.nextCursor === void 0 || uiState !== "ready" ? null : (0, react.createElement)("button", {
|
|
2108
2262
|
type: "button",
|
|
2109
2263
|
"data-role": "load-more",
|
|
2110
2264
|
disabled: queue.status === "loading",
|
|
2111
2265
|
onClick: () => {
|
|
2112
2266
|
store.loadMore();
|
|
2113
2267
|
}
|
|
2114
|
-
}, t("loadMore")), (0, react.createElement)(
|
|
2268
|
+
}, t("loadMore")), (0, react.createElement)(MergeSettings, {
|
|
2269
|
+
view,
|
|
2270
|
+
t
|
|
2271
|
+
}), (0, react.createElement)(MergeRunStrips, {
|
|
2272
|
+
view,
|
|
2273
|
+
t,
|
|
2274
|
+
copy
|
|
2275
|
+
}), view.degraded ? (0, react.createElement)("p", { "data-role": "degraded" }, t("degraded") + " " + view.notes.join(",")) : null, (0, react.createElement)("div", { "data-role": "start" }, (0, react.createElement)("button", {
|
|
2276
|
+
type: "button",
|
|
2277
|
+
"data-role": "start-scan",
|
|
2278
|
+
onClick: () => {
|
|
2279
|
+
copy(view.startCommands.scan);
|
|
2280
|
+
}
|
|
2281
|
+
}, t("start.scan")), (0, react.createElement)("button", {
|
|
2282
|
+
type: "button",
|
|
2283
|
+
"data-role": "start-pair",
|
|
2284
|
+
onClick: () => {
|
|
2285
|
+
copy(view.startCommands.pair);
|
|
2286
|
+
}
|
|
2287
|
+
}, t("start.pair"))), (0, react.createElement)("button", {
|
|
2115
2288
|
type: "button",
|
|
2116
2289
|
"data-role": "history",
|
|
2117
2290
|
onClick: () => {
|
|
@@ -2123,7 +2296,7 @@ window.__ModuleLoader__.load({
|
|
|
2123
2296
|
onClick: () => {
|
|
2124
2297
|
copy(doctorCommand);
|
|
2125
2298
|
}
|
|
2126
|
-
}, t("doctor.open")), overlay === void 0 ? null : overlay.kind === "body" ? bodyNode(overlay, t, closeOverlay) : historyNode(overlay, t, closeOverlay), (0, react.createElement)("button", {
|
|
2299
|
+
}, t("doctor.open")), overlay === void 0 ? null : overlay.kind === "body" ? bodyNode(overlay, t, closeOverlay) : overlay.kind === "pair" ? pairNode(overlay, t, closeOverlay) : historyNode(overlay, t, closeOverlay), (0, react.createElement)("button", {
|
|
2127
2300
|
type: "button",
|
|
2128
2301
|
"data-role": "refresh",
|
|
2129
2302
|
onClick: () => {
|
|
@@ -2436,6 +2609,54 @@ window.__ModuleLoader__.load({
|
|
|
2436
2609
|
}
|
|
2437
2610
|
});
|
|
2438
2611
|
}
|
|
2612
|
+
async openPair(a, b, rowId) {
|
|
2613
|
+
const token = ++this.overlayToken;
|
|
2614
|
+
this.set({
|
|
2615
|
+
...this.snapshot,
|
|
2616
|
+
overlay: {
|
|
2617
|
+
kind: "pair",
|
|
2618
|
+
a,
|
|
2619
|
+
b,
|
|
2620
|
+
status: "loading"
|
|
2621
|
+
}
|
|
2622
|
+
});
|
|
2623
|
+
const [left, right] = await Promise.all([this.source.body(a.name, a.side, rowId), this.source.body(b.name, b.side, rowId)]);
|
|
2624
|
+
if (this.disposed || token !== this.overlayToken) return;
|
|
2625
|
+
if (!left.ok || !right.ok) {
|
|
2626
|
+
const failure = !left.ok ? left.failure : !right.ok ? right.failure : void 0;
|
|
2627
|
+
if (failure?.kind === "blocked") {
|
|
2628
|
+
this.set({
|
|
2629
|
+
...this.snapshot,
|
|
2630
|
+
viewState: "blocked",
|
|
2631
|
+
viewFailure: failure,
|
|
2632
|
+
overlay: void 0
|
|
2633
|
+
});
|
|
2634
|
+
return;
|
|
2635
|
+
}
|
|
2636
|
+
this.set({
|
|
2637
|
+
...this.snapshot,
|
|
2638
|
+
overlay: {
|
|
2639
|
+
kind: "pair",
|
|
2640
|
+
a,
|
|
2641
|
+
b,
|
|
2642
|
+
status: "error",
|
|
2643
|
+
...failure === void 0 ? {} : { failure }
|
|
2644
|
+
}
|
|
2645
|
+
});
|
|
2646
|
+
return;
|
|
2647
|
+
}
|
|
2648
|
+
this.set({
|
|
2649
|
+
...this.snapshot,
|
|
2650
|
+
overlay: {
|
|
2651
|
+
kind: "pair",
|
|
2652
|
+
a,
|
|
2653
|
+
b,
|
|
2654
|
+
status: "ready",
|
|
2655
|
+
aBody: left.payload,
|
|
2656
|
+
bBody: right.payload
|
|
2657
|
+
}
|
|
2658
|
+
});
|
|
2659
|
+
}
|
|
2439
2660
|
async openHistory() {
|
|
2440
2661
|
const token = ++this.overlayToken;
|
|
2441
2662
|
this.set({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** One merge row: summary, stage, facts, primary
|
|
1
|
+
/** One merge row: summary, stage, facts, one primary decision and the copy/sort drawer. */
|
|
2
2
|
import { type DragEvent, type ReactNode } from 'react';
|
|
3
3
|
import type { MergeRowView } from './api.ts';
|
|
4
4
|
type Translate = (key: string, values?: Readonly<Record<string, string | number>>) => string;
|
|
@@ -10,16 +10,23 @@ export interface RowSortHandlers {
|
|
|
10
10
|
menu(id: string, x: number, y: number): void;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* Render one row.
|
|
13
|
+
* Render one row as a decision card. The approve action is the only primary; A/B, reject and
|
|
14
|
+
* auxiliary sort/copy commands cannot borrow that weight.
|
|
14
15
|
* @param props - row, translator, copier, sort hooks, body opener and decision callback.
|
|
15
|
-
* @returns the row
|
|
16
|
+
* @returns the row with drag/keyboard wiring and a separate more drawer.
|
|
16
17
|
*/
|
|
17
18
|
export declare function MergeRow(props: {
|
|
18
19
|
row: MergeRowView;
|
|
19
20
|
t: Translate;
|
|
20
21
|
copy: (command: string) => void;
|
|
21
22
|
sort: RowSortHandlers;
|
|
22
|
-
|
|
23
|
+
openBoth: (a: {
|
|
24
|
+
name: string;
|
|
25
|
+
side: 'live' | 'archive';
|
|
26
|
+
}, b: {
|
|
27
|
+
name: string;
|
|
28
|
+
side: 'live' | 'archive';
|
|
29
|
+
}, rowId: string | undefined) => void;
|
|
23
30
|
onDecide: ((rowId: string, verb: 'approve' | 'reject') => void) | undefined;
|
|
24
31
|
busy: boolean;
|
|
25
32
|
}): ReactNode;
|
|
@@ -17,6 +17,10 @@ export interface QueueState {
|
|
|
17
17
|
nextCursor?: string | undefined;
|
|
18
18
|
failure?: MergeFailure | undefined;
|
|
19
19
|
}
|
|
20
|
+
export interface BodyTarget {
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly side: 'live' | 'archive';
|
|
23
|
+
}
|
|
20
24
|
export type OverlayState = {
|
|
21
25
|
kind: 'body';
|
|
22
26
|
name: string;
|
|
@@ -24,6 +28,14 @@ export type OverlayState = {
|
|
|
24
28
|
status: 'loading' | 'ready' | 'error';
|
|
25
29
|
body?: MergeBody;
|
|
26
30
|
failure?: MergeFailure;
|
|
31
|
+
} | {
|
|
32
|
+
kind: 'pair';
|
|
33
|
+
a: BodyTarget;
|
|
34
|
+
b: BodyTarget;
|
|
35
|
+
status: 'loading' | 'ready' | 'error';
|
|
36
|
+
aBody?: MergeBody;
|
|
37
|
+
bBody?: MergeBody;
|
|
38
|
+
failure?: MergeFailure;
|
|
27
39
|
} | {
|
|
28
40
|
kind: 'history';
|
|
29
41
|
status: 'loading' | 'ready' | 'error';
|
|
@@ -71,6 +83,7 @@ export declare class MergeStore {
|
|
|
71
83
|
refresh(): void;
|
|
72
84
|
loadMore(): void;
|
|
73
85
|
openBody(name: string, side: 'live' | 'archive', rowId?: string): Promise<void>;
|
|
86
|
+
openPair(a: BodyTarget, b: BodyTarget, rowId?: string): Promise<void>;
|
|
74
87
|
openHistory(): Promise<void>;
|
|
75
88
|
closeOverlay(): void;
|
|
76
89
|
dispose(): void;
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
]
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
-
"version": "0.
|
|
14
|
+
"version": "0.36.1",
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"react-dom": "^18.2.0"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@lmzhen/dsh-evolution-client-kit": "^0.
|
|
54
|
+
"@lmzhen/dsh-evolution-client-kit": "^0.36.1"
|
|
55
55
|
},
|
|
56
56
|
"engines": {
|
|
57
57
|
"dsh": ">=0.2.1-rc.2 <0.2.2-0"
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The one seam onto the platform's menu material and rows.
|
|
3
|
-
*
|
|
4
|
-
* The family bundle keeps `@deepseek-ai/*` external, so the platform components are reached through
|
|
5
|
-
* the loader-provided `require` (the same door the Markdown seam uses). A deployment without the
|
|
6
|
-
* row gets the panel's own menu fallback; the platform path is not a hard dependency.
|
|
7
|
-
* @module dsh-evolution-merge-ui/client
|
|
8
|
-
*/
|
|
9
|
-
import { type ReactNode } from 'react';
|
|
10
|
-
/** The platform's menu surface: a styled container that accepts div props. */
|
|
11
|
-
export type MenuSurfaceComponent = (props: Record<string, unknown> & {
|
|
12
|
-
children?: ReactNode;
|
|
13
|
-
}) => ReactNode;
|
|
14
|
-
/** The platform's menu row: role=menuitem plus selected/disabled/danger semantics. */
|
|
15
|
-
export type MenuItemButtonComponent = (props: {
|
|
16
|
-
children: ReactNode;
|
|
17
|
-
current?: boolean;
|
|
18
|
-
disabled?: boolean;
|
|
19
|
-
danger?: boolean;
|
|
20
|
-
separatorBefore?: boolean;
|
|
21
|
-
onSelect: () => void;
|
|
22
|
-
}) => ReactNode;
|
|
23
|
-
/** The two components this panel consumes from one platform module row. */
|
|
24
|
-
export interface MenuPrimitives {
|
|
25
|
-
MenuSurface: MenuSurfaceComponent;
|
|
26
|
-
MenuItemButton: MenuItemButtonComponent;
|
|
27
|
-
}
|
|
28
|
-
/** One row of the coordinate menu, independent of the renderer. */
|
|
29
|
-
export interface RowMenuAction {
|
|
30
|
-
readonly id: string;
|
|
31
|
-
readonly label: string;
|
|
32
|
-
readonly onSelect: () => void;
|
|
33
|
-
readonly separatorBefore?: boolean;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Render the coordinate menu through the platform primitives.
|
|
37
|
-
* @param primitives - the platform MenuSurface/MenuItemButton pair.
|
|
38
|
-
* @param actions - rows in display order.
|
|
39
|
-
* @param label - accessible menu name.
|
|
40
|
-
* @param style - fixed position computed from the pointer.
|
|
41
|
-
* @returns the menu element.
|
|
42
|
-
*/
|
|
43
|
-
export declare function renderPlatformMenu(primitives: MenuPrimitives, actions: readonly RowMenuAction[], label: string, style: Record<string, string | number>): ReactNode;
|
|
44
|
-
/**
|
|
45
|
-
* Accept only the two component functions; a namespace row without them is not a menu.
|
|
46
|
-
* @param row - the module row's exports.
|
|
47
|
-
* @returns the two components, or undefined.
|
|
48
|
-
*/
|
|
49
|
-
export declare function menuPrimitivesFrom(row: Record<string, unknown>): MenuPrimitives | undefined;
|
|
50
|
-
/** The module-table row, when this deployment carries it. */
|
|
51
|
-
export declare const PLATFORM_MENU: MenuPrimitives | undefined;
|
|
52
|
-
//# sourceMappingURL=platform-menu.d.ts.map
|