dsh-diff-approval 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js
CHANGED
|
@@ -712,6 +712,111 @@ window.__ModuleLoader__.load({
|
|
|
712
712
|
return (text.endsWith("\n") ? text.slice(0, -1) : text).split("\n");
|
|
713
713
|
}
|
|
714
714
|
//#endregion
|
|
715
|
+
//#region lib/types/client/split-diff.js
|
|
716
|
+
/**
|
|
717
|
+
* Side-by-side (split) diff model: the unified whole-file diff rows are
|
|
718
|
+
* regrouped into line-aligned pairs for a two-column "before | current" view.
|
|
719
|
+
* Pure derivation; the view owns rendering. A context row becomes a pair with
|
|
720
|
+
* both sides, a deletion a left-only pair, an addition a right-only pair, and
|
|
721
|
+
* an adjacent deletion/addition run is paired line-by-line into a single
|
|
722
|
+
* replacement pair so the two columns line up.
|
|
723
|
+
* @module dsh-diff-approval/client/split-diff
|
|
724
|
+
*/
|
|
725
|
+
/** One whole-file diff row → its visible left side text. */
|
|
726
|
+
function leftSideOf(row) {
|
|
727
|
+
if (row.kind === "add") return void 0;
|
|
728
|
+
return {
|
|
729
|
+
text: row.text,
|
|
730
|
+
line: row.oldLine
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
/** One whole-file diff row → its visible right side text. */
|
|
734
|
+
function rightSideOf(row) {
|
|
735
|
+
if (row.kind === "del") return void 0;
|
|
736
|
+
return {
|
|
737
|
+
text: row.text,
|
|
738
|
+
line: row.newLine
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Regroup the whole-file rows into aligned split pairs, pairing a deletion run
|
|
743
|
+
* with a following addition run line-by-line (so a replaced line is one pair),
|
|
744
|
+
* and leaving a stray deletion or addition as a one-sided pair.
|
|
745
|
+
* @param rows - the whole-file diff rows.
|
|
746
|
+
* @returns the split pairs plus the row→pair index map.
|
|
747
|
+
*/
|
|
748
|
+
function computeSideBySideDiff(rows) {
|
|
749
|
+
const pairs = [];
|
|
750
|
+
const pairOfRow = /* @__PURE__ */ new Map();
|
|
751
|
+
const pendingDel = [];
|
|
752
|
+
const push = (pair, rows) => {
|
|
753
|
+
const index = pairs.length;
|
|
754
|
+
pairs.push(pair);
|
|
755
|
+
for (const r of rows) pairOfRow.set(r, index);
|
|
756
|
+
};
|
|
757
|
+
const flushPending = () => {
|
|
758
|
+
for (const { index, row } of pendingDel) push({
|
|
759
|
+
kind: "del",
|
|
760
|
+
left: leftSideOf(row),
|
|
761
|
+
right: void 0
|
|
762
|
+
}, [index]);
|
|
763
|
+
pendingDel.length = 0;
|
|
764
|
+
};
|
|
765
|
+
for (let i = 0; i < rows.length; i++) {
|
|
766
|
+
const row = rows[i];
|
|
767
|
+
if (row.kind === "context") {
|
|
768
|
+
flushPending();
|
|
769
|
+
push({
|
|
770
|
+
kind: "context",
|
|
771
|
+
left: leftSideOf(row),
|
|
772
|
+
right: rightSideOf(row)
|
|
773
|
+
}, [i]);
|
|
774
|
+
} else if (row.kind === "del") pendingDel.push({
|
|
775
|
+
index: i,
|
|
776
|
+
row
|
|
777
|
+
});
|
|
778
|
+
else {
|
|
779
|
+
const del = pendingDel.shift();
|
|
780
|
+
if (del !== void 0) push({
|
|
781
|
+
kind: "replace",
|
|
782
|
+
left: leftSideOf(del.row),
|
|
783
|
+
right: rightSideOf(row)
|
|
784
|
+
}, [del.index, i]);
|
|
785
|
+
else push({
|
|
786
|
+
kind: "add",
|
|
787
|
+
left: void 0,
|
|
788
|
+
right: rightSideOf(row)
|
|
789
|
+
}, [i]);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
flushPending();
|
|
793
|
+
return {
|
|
794
|
+
pairs,
|
|
795
|
+
pairOfRow
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Pair indices whose left or right text contains the query (case-insensitive).
|
|
800
|
+
* A pair counts once however many times the query appears, so split search
|
|
801
|
+
* highlights the whole pair on both columns and a single "current" pair is
|
|
802
|
+
* stepped through — not each individual left/right occurrence.
|
|
803
|
+
* @param pairs - the split pairs.
|
|
804
|
+
* @param query - the query text; an empty query matches nothing.
|
|
805
|
+
* @returns matching pair indices, in file order.
|
|
806
|
+
*/
|
|
807
|
+
function searchPairs(pairs, query) {
|
|
808
|
+
if (query === "") return [];
|
|
809
|
+
const lower = query.toLowerCase();
|
|
810
|
+
const matches = [];
|
|
811
|
+
for (let index = 0; index < pairs.length; index++) {
|
|
812
|
+
const p = pairs[index];
|
|
813
|
+
if (p === void 0) continue;
|
|
814
|
+
if (p.left !== void 0 && p.left.text.toLowerCase().includes(lower)) matches.push(index);
|
|
815
|
+
else if (p.right !== void 0 && p.right.text.toLowerCase().includes(lower)) matches.push(index);
|
|
816
|
+
}
|
|
817
|
+
return matches;
|
|
818
|
+
}
|
|
819
|
+
//#endregion
|
|
715
820
|
//#region node_modules/.pnpm/@shikijs+types@4.4.3/node_modules/@shikijs/types/dist/index.mjs
|
|
716
821
|
var ShikiError = class extends Error {
|
|
717
822
|
constructor(message) {
|
|
@@ -11631,6 +11736,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11631
11736
|
const PASTE_ON_COPY_KEY = "diff-approval:paste-on-copy";
|
|
11632
11737
|
const IMPORT_UNTRACKED_KEY = "diff-approval:import-untracked";
|
|
11633
11738
|
const TAB_WIDTH_KEY = "diff-approval:tab-size";
|
|
11739
|
+
const SPLIT_MODE_KEY = "diff-approval:split-mode";
|
|
11634
11740
|
const WRAP_PREFIX = "diff-approval:wrap:";
|
|
11635
11741
|
/**
|
|
11636
11742
|
* Whether copying a reference should also paste it into the chat input and
|
|
@@ -11686,9 +11792,22 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11686
11792
|
function setTabWidth(value) {
|
|
11687
11793
|
localStorage.setItem(TAB_WIDTH_KEY, String(value));
|
|
11688
11794
|
}
|
|
11795
|
+
/**
|
|
11796
|
+
* Whether the whole-file diff view uses the two-column (side-by-side) layout.
|
|
11797
|
+
* Default off (single column): the unified diff. Only an explicit `'1'` enables
|
|
11798
|
+
* split mode.
|
|
11799
|
+
* @returns whether the split (two-column) diff view is used.
|
|
11800
|
+
*/
|
|
11801
|
+
function splitMode() {
|
|
11802
|
+
return localStorage.getItem(SPLIT_MODE_KEY) === "1";
|
|
11803
|
+
}
|
|
11804
|
+
/** Persist the split-view preference. */
|
|
11805
|
+
function setSplitMode(value) {
|
|
11806
|
+
localStorage.setItem(SPLIT_MODE_KEY, value ? "1" : "0");
|
|
11807
|
+
}
|
|
11689
11808
|
//#endregion
|
|
11690
11809
|
//#region \0dsh-css:/home/runner/work/dsh-diff-approval/dsh-diff-approval/src/client/PendingPanel.module.css.mjs
|
|
11691
|
-
const css = ".F1KBNa_layer{box-sizing:border-box;flex:none;align-items:center;width:calc(100% + 4px);height:42px;margin:4px -2px;display:flex;position:relative}.F1KBNa_footerButtons{align-items:center;width:100%;display:flex}.F1KBNa_badge{box-sizing:border-box;width:100%;height:42px;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}.F1KBNa_badge:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_badge[data-active]{background:var(--dsw-alias-interactive-bg-hover-solid)}.F1KBNa_badge:disabled{color:var(--dsw-alias-label-tertiary);cursor:default;background:0 0}.F1KBNa_badgeLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.F1KBNa_badgeCount{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;margin-left:auto;font-size:12px;line-height:16px}.F1KBNa_layer.F1KBNa_rail{width:36px;height:36px;margin:8px 0 10px}.F1KBNa_rail .F1KBNa_badge{border-radius:50%;justify-content:center;gap:0;width:36px;height:36px;padding:0}.F1KBNa_rail .F1KBNa_badgeLabel{display:none}.F1KBNa_rail .F1KBNa_badgeCount{box-sizing:border-box;background:var(--dsw-alias-state-business-primary);min-width:18px;height:18px;color:var(--dsw-alias-label-primary-foreground);font-variant-numeric:tabular-nums;border-radius:9px;justify-content:center;align-items:center;padding:0 4px;font-size:11px;line-height:18px;display:flex;position:absolute;top:-3px;right:-7px}.F1KBNa_fullscreenBackdrop{z-index:29;background:var(--dsw-specific-sidebar-fill);position:fixed;inset:0}.F1KBNa_panel{z-index:30;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:auto;max-width:none;box-shadow:var(--dsw-shadow-lv2);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:12px;flex-direction:column;display:flex;position:fixed;inset:8px 8px 128px;overflow:hidden}.F1KBNa_header{box-sizing:border-box;border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);flex:none;justify-content:space-between;align-items:center;min-height:44px;padding:10px 12px;display:flex}.F1KBNa_headerActions{align-items:center;gap:2px;display:flex}.F1KBNa_settingsPage{padding:8px 12px}.F1KBNa_settingsRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:16px 0;display:flex}.F1KBNa_settingsRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}.F1KBNa_settingsRowTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}.F1KBNa_settingsRowDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}.F1KBNa_settingsSelector{background:var(--dsw-alias-bg-module-platform);height:36px;font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:18px;align-items:center;gap:12px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.F1KBNa_settingsSelector:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_settingsSelectorChevron{flex:none}.F1KBNa_states{flex-direction:column;flex:1;min-height:0;padding:4px 12px 12px;display:flex;overflow-y:auto}.F1KBNa_split{flex:1;align-items:stretch;min-height:0;display:flex;position:relative}.F1KBNa_fileListFloat{z-index:40;box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);box-shadow:var(--dsw-shadow-lv2);border-radius:12px;flex-direction:column;padding:6px 8px 10px;display:flex;position:absolute;overflow:hidden}.F1KBNa_fileList{box-sizing:border-box;border-right:1px solid var(--dsw-alias-border-l2);flex-direction:column;flex:none;width:240px;min-height:0;padding:4px 8px 12px;display:flex}.F1KBNa_listScroll{flex:1;min-height:0;overflow-y:auto}.F1KBNa_bulkActions{flex:none;gap:6px;padding-top:8px;display:flex}.F1KBNa_bulkActions .F1KBNa_action{text-align:center;flex:1}.F1KBNa_resizeHandle{cursor:col-resize;background:0 0;flex:none;width:5px;margin:0 -2px}.F1KBNa_resizeHandle:hover{background:var(--dsw-alias-border-l2)}.F1KBNa_detail{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.F1KBNa_detailEmpty{color:var(--dsw-alias-label-tertiary);text-align:center;flex:1;justify-content:center;align-items:center;margin:0;padding:24px;font-size:12px;line-height:18px;display:flex}.F1KBNa_title{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:20px}.F1KBNa_note,.F1KBNa_readError,.F1KBNa_hint{color:var(--dsw-alias-label-tertiary);margin:4px 0;font-size:12px;line-height:18px}.F1KBNa_noteCentered{text-align:center;margin:auto}.F1KBNa_emptyState{flex-direction:column;align-items:center;gap:10px;margin:auto;display:flex}.F1KBNa_importButton{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;padding:5px 14px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_importButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_importButton:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.F1KBNa_importNote{color:var(--dsw-alias-label-tertiary);text-align:center;margin:0;font-size:12px;line-height:18px}.F1KBNa_readError{color:var(--dsw-alias-state-error-primary)}.F1KBNa_group{color:var(--dsw-alias-label-tertiary);margin:8px 0 4px;font-size:12px;font-weight:500;line-height:16px}.F1KBNa_rows{margin:0;padding:0;list-style:none}.F1KBNa_row{border:1px solid #0000;border-radius:10px;margin:2px 0}.F1KBNa_rowHead{width:100%;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:10px;align-items:baseline;gap:8px;padding:6px 8px;display:flex}.F1KBNa_rowHead:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}.F1KBNa_rowHead[data-selected]{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_rowPath{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:var(--dsw-font-markdown-code-block);overflow:hidden}.F1KBNa_kindTag{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);white-space:nowrap;border-radius:6px;flex:none;padding:1px 6px;font-size:11px;line-height:14px}.F1KBNa_kindHint{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px;line-height:16px}.F1KBNa_divergedHint,.F1KBNa_missingHint{border-bottom:1px solid var(--dsw-alias-border-l2);margin:0;padding:6px 8px;font-size:12px;line-height:18px}.F1KBNa_missing{border:1px solid var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-state-warn-label,var(--dsw-alias-state-warn-primary));white-space:nowrap;border-radius:6px;flex:none;padding:1px 6px;font-size:11px;line-height:14px}.F1KBNa_rowFailed{border:1px solid var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary);white-space:nowrap;border-radius:6px;flex:none;padding:1px 6px;font-size:11px;line-height:14px}.F1KBNa_actionError{border-bottom:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;margin:0;padding:6px 8px;font-size:12px;line-height:18px}.F1KBNa_missingHint{color:var(--dsw-alias-state-warn-label,var(--dsw-alias-state-warn-primary))}.F1KBNa_rowMeta{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;gap:6px;margin-left:auto;font-size:12px;line-height:16px;display:inline-flex}.F1KBNa_addCount{color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 60%, var(--dsw-alias-label-primary))}.F1KBNa_delCount{color:color-mix(in srgb, var(--dsw-alias-state-error-primary) 60%, var(--dsw-alias-label-primary))}.F1KBNa_diff{background:var(--dsw-alias-markdown-code-block);flex-direction:column;flex:1;min-height:0;display:flex;position:relative;overflow:hidden}.F1KBNa_diffHeader{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:6px 8px;display:flex}.F1KBNa_diffPath{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary);font:var(--dsw-font-markdown-code-block);flex:1;font-size:12px;line-height:18px;overflow:hidden}.F1KBNa_diffActions{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:6px 8px;display:flex}.F1KBNa_diffStats{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:12px;line-height:16px}.F1KBNa_flexSpacer{flex:1}.F1KBNa_action{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_action:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_action:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.F1KBNa_actionPrimary{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50)}.F1KBNa_actionPrimary:hover:not(:disabled){background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 85%, var(--dsw-static-neutral-bluish-1000))}.F1KBNa_actionPrimary:disabled{background:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50);opacity:.55}.F1KBNa_actionQuietDisabled:disabled{cursor:pointer;color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l1);background:0 0}.F1KBNa_actionPrimary.F1KBNa_actionQuietDisabled:disabled{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50);opacity:1}.F1KBNa_iconAction{justify-content:center;align-items:center;min-height:25px;padding:4px 6px;display:inline-flex}.F1KBNa_close{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:0;display:inline-flex}.F1KBNa_close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.F1KBNa_expand{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:0;display:inline-flex}.F1KBNa_expand:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.F1KBNa_expandExpanded svg{transform:rotate(180deg)}.F1KBNa_diffBodyWrap{flex:1;min-height:0;display:flex;position:relative}.F1KBNa_diffBody{min-width:0;font:var(--dsw-font-markdown-code-block);cursor:text;outline:none;flex:1;padding:0;position:relative;overflow:auto}.F1KBNa_diffBody::-webkit-scrollbar,.F1KBNa_diffBody::-webkit-scrollbar-track,.F1KBNa_diffBody::-webkit-scrollbar-thumb{cursor:default}.F1KBNa_blockActions{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-markdown-code-block);box-shadow:var(--dsw-shadow-lv1);z-index:2;border-radius:10px;align-items:center;gap:9px;padding:5px;display:flex;position:absolute;right:8px}.F1KBNa_blockPosition{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;margin-top:1px;margin-left:7px;font-size:12px;line-height:16px}.F1KBNa_searchBar{z-index:3;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-markdown-code-block);box-shadow:var(--dsw-shadow-lv1);border-radius:10px;align-items:center;gap:4px;padding:4px;display:flex;position:absolute;top:8px;right:8px}.F1KBNa_searchInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);width:150px;color:var(--dsw-alias-label-primary);border-radius:6px;outline:none;padding:3px 8px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_searchInput:focus{border-color:var(--dsw-alias-state-business-primary)}.F1KBNa_searchCount{text-align:center;min-width:34px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12px;line-height:16px}.F1KBNa_diffBody [data-diff-search=hit]{background-image:linear-gradient(#facc1529,#facc1529)}.F1KBNa_diffBody [data-diff-search=current]{background-image:linear-gradient(#facc1552,#facc1552)}.F1KBNa_blockFlash{z-index:1;box-sizing:border-box;border:2px solid var(--dsw-alias-state-business-primary);pointer-events:none;border-radius:4px;animation:1s ease-out forwards F1KBNa_diffFlash;position:absolute;left:0;right:0}@keyframes F1KBNa_diffFlash{0%{opacity:1}to{opacity:0}}.F1KBNa_overviewRuler{pointer-events:none;opacity:.5;width:4px;position:absolute;top:0;bottom:0;right:0}.F1KBNa_overviewMarker{border-radius:2px;width:100%;min-height:2px;position:absolute;right:0}.F1KBNa_markerDel{background-color:var(--dsw-alias-state-error-primary)}.F1KBNa_markerAdd{background-color:var(--dsw-alias-state-success-primary)}.F1KBNa_lines{border-spacing:0;width:max-content;min-width:100%;display:table}.F1KBNa_line{height:22px;line-height:22px;display:table-row}.F1KBNa_vSpacer{display:table-row}.F1KBNa_gutter{box-sizing:border-box;text-align:right;width:44px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;user-select:none;cursor:default;padding-right:10px;display:table-cell}.F1KBNa_code{white-space:pre;display:table-cell}.F1KBNa_context{color:var(--dsw-alias-label-primary)}.F1KBNa_del{background-color:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.F1KBNa_add{background-color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 10%, transparent)}.F1KBNa_statusBar{box-sizing:border-box;border-top:1px solid var(--dsw-alias-border-l2);height:34px;color:var(--dsw-alias-label-tertiary);font-family:var(--dsw-font-markdown-code-block);font-variant-numeric:tabular-nums;flex:none;align-items:center;gap:8px;padding:0 8px;font-size:12px;line-height:18px;display:flex}.F1KBNa_statusAction{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);white-space:nowrap;cursor:pointer;background:0 0;border-radius:8px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_statusAction:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_langSelect{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;flex:none;align-items:center;gap:4px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px;display:inline-flex}.F1KBNa_langSelect:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_langLabel{text-overflow:ellipsis;white-space:nowrap;max-width:140px;overflow:hidden}.F1KBNa_notice{z-index:60;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);max-width:360px;box-shadow:var(--dsw-shadow-lv3);border-radius:10px;align-items:flex-start;gap:12px;padding:12px 14px;display:flex;position:fixed;bottom:24px;right:24px}.F1KBNa_noticeText{font:var(--dsw-font-caption);color:var(--dsw-alias-label-primary);flex:1;margin:0;line-height:1.45}.F1KBNa_noticeButton{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);font:var(--dsw-font-caption);cursor:pointer;border-radius:6px;flex:none;padding:4px 10px}.F1KBNa_noticeButton:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}.F1KBNa_wrap .F1KBNa_line{height:auto;min-height:22px}.F1KBNa_subline{white-space:pre;height:22px;line-height:22px;display:block;overflow:hidden}.F1KBNa_wrapActive{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50)}.F1KBNa_wrapActive:hover{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 85%, var(--dsw-static-neutral-bluish-1000))}";
|
|
11810
|
+
const css = ".F1KBNa_layer{box-sizing:border-box;flex:none;align-items:center;width:calc(100% + 4px);height:42px;margin:4px -2px;display:flex;position:relative}.F1KBNa_footerButtons{align-items:center;width:100%;display:flex}.F1KBNa_badge{box-sizing:border-box;width:100%;height:42px;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}.F1KBNa_badge:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_badge[data-active]{background:var(--dsw-alias-interactive-bg-hover-solid)}.F1KBNa_badge:disabled{color:var(--dsw-alias-label-tertiary);cursor:default;background:0 0}.F1KBNa_badgeLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.F1KBNa_badgeCount{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;margin-left:auto;font-size:12px;line-height:16px}.F1KBNa_layer.F1KBNa_rail{width:36px;height:36px;margin:8px 0 10px}.F1KBNa_rail .F1KBNa_badge{border-radius:50%;justify-content:center;gap:0;width:36px;height:36px;padding:0}.F1KBNa_rail .F1KBNa_badgeLabel{display:none}.F1KBNa_rail .F1KBNa_badgeCount{box-sizing:border-box;background:var(--dsw-alias-state-business-primary);min-width:18px;height:18px;color:var(--dsw-alias-label-primary-foreground);font-variant-numeric:tabular-nums;border-radius:9px;justify-content:center;align-items:center;padding:0 4px;font-size:11px;line-height:18px;display:flex;position:absolute;top:-3px;right:-7px}.F1KBNa_fullscreenBackdrop{z-index:29;background:var(--dsw-specific-sidebar-fill);position:fixed;inset:0}.F1KBNa_panel{z-index:30;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:auto;max-width:none;box-shadow:var(--dsw-shadow-lv2);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:12px;flex-direction:column;display:flex;position:fixed;inset:8px 8px 128px;overflow:hidden}.F1KBNa_header{box-sizing:border-box;border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);flex:none;justify-content:space-between;align-items:center;min-height:44px;padding:10px 12px;display:flex}.F1KBNa_headerActions{align-items:center;gap:2px;display:flex}.F1KBNa_settingsPage{padding:8px 12px}.F1KBNa_settingsRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:16px 0;display:flex}.F1KBNa_settingsRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}.F1KBNa_settingsRowTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}.F1KBNa_settingsRowDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}.F1KBNa_settingsSelector{background:var(--dsw-alias-bg-module-platform);height:36px;font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:18px;align-items:center;gap:12px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.F1KBNa_settingsSelector:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_settingsSelectorChevron{flex:none}.F1KBNa_states{flex-direction:column;flex:1;min-height:0;padding:4px 12px 12px;display:flex;overflow-y:auto}.F1KBNa_split{flex:1;align-items:stretch;min-height:0;display:flex;position:relative}.F1KBNa_fileListFloat{z-index:40;box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);box-shadow:var(--dsw-shadow-lv2);border-radius:12px;flex-direction:column;padding:6px 8px 10px;display:flex;position:absolute;overflow:hidden}.F1KBNa_fileList{box-sizing:border-box;border-right:1px solid var(--dsw-alias-border-l2);flex-direction:column;flex:none;width:240px;min-height:0;padding:4px 8px 12px;display:flex}.F1KBNa_listScroll{flex:1;min-height:0;overflow-y:auto}.F1KBNa_bulkActions{flex:none;gap:6px;padding-top:8px;display:flex}.F1KBNa_bulkActions .F1KBNa_action{text-align:center;flex:1}.F1KBNa_resizeHandle{cursor:col-resize;background:0 0;flex:none;width:5px;margin:0 -2px}.F1KBNa_resizeHandle:hover{background:var(--dsw-alias-border-l2)}.F1KBNa_detail{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.F1KBNa_detailEmpty{color:var(--dsw-alias-label-tertiary);text-align:center;flex:1;justify-content:center;align-items:center;margin:0;padding:24px;font-size:12px;line-height:18px;display:flex}.F1KBNa_title{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:20px}.F1KBNa_note,.F1KBNa_readError,.F1KBNa_hint{color:var(--dsw-alias-label-tertiary);margin:4px 0;font-size:12px;line-height:18px}.F1KBNa_noteCentered{text-align:center;margin:auto}.F1KBNa_emptyState{flex-direction:column;align-items:center;gap:10px;margin:auto;display:flex}.F1KBNa_importButton{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;padding:5px 14px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_importButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_importButton:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.F1KBNa_importNote{color:var(--dsw-alias-label-tertiary);text-align:center;margin:0;font-size:12px;line-height:18px}.F1KBNa_readError{color:var(--dsw-alias-state-error-primary)}.F1KBNa_group{color:var(--dsw-alias-label-tertiary);margin:8px 0 4px;font-size:12px;font-weight:500;line-height:16px}.F1KBNa_rows{margin:0;padding:0;list-style:none}.F1KBNa_row{border:1px solid #0000;border-radius:10px;margin:2px 0}.F1KBNa_rowHead{width:100%;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:10px;align-items:baseline;gap:8px;padding:6px 8px;display:flex}.F1KBNa_rowHead:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}.F1KBNa_rowHead[data-selected]{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_rowPath{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:var(--dsw-font-markdown-code-block);overflow:hidden}.F1KBNa_kindTag{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);white-space:nowrap;border-radius:6px;flex:none;padding:1px 6px;font-size:11px;line-height:14px}.F1KBNa_kindHint{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px;line-height:16px}.F1KBNa_divergedHint,.F1KBNa_missingHint{border-bottom:1px solid var(--dsw-alias-border-l2);margin:0;padding:6px 8px;font-size:12px;line-height:18px}.F1KBNa_missing{border:1px solid var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-state-warn-label,var(--dsw-alias-state-warn-primary));white-space:nowrap;border-radius:6px;flex:none;padding:1px 6px;font-size:11px;line-height:14px}.F1KBNa_rowFailed{border:1px solid var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary);white-space:nowrap;border-radius:6px;flex:none;padding:1px 6px;font-size:11px;line-height:14px}.F1KBNa_actionError{border-bottom:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;margin:0;padding:6px 8px;font-size:12px;line-height:18px}.F1KBNa_missingHint{color:var(--dsw-alias-state-warn-label,var(--dsw-alias-state-warn-primary))}.F1KBNa_rowMeta{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;gap:6px;margin-left:auto;font-size:12px;line-height:16px;display:inline-flex}.F1KBNa_addCount{color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 60%, var(--dsw-alias-label-primary))}.F1KBNa_delCount{color:color-mix(in srgb, var(--dsw-alias-state-error-primary) 60%, var(--dsw-alias-label-primary))}.F1KBNa_diff{background:var(--dsw-alias-markdown-code-block);flex-direction:column;flex:1;min-height:0;display:flex;position:relative;overflow:hidden}.F1KBNa_diffHeader{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:6px 8px;display:flex}.F1KBNa_diffPath{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary);font:var(--dsw-font-markdown-code-block);flex:1;font-size:12px;line-height:18px;overflow:hidden}.F1KBNa_diffActions{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:6px 8px;display:flex}.F1KBNa_diffStats{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:12px;line-height:16px}.F1KBNa_flexSpacer{flex:1}.F1KBNa_action{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_action:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_action:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.F1KBNa_actionPrimary{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50)}.F1KBNa_actionPrimary:hover:not(:disabled){background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 85%, var(--dsw-static-neutral-bluish-1000))}.F1KBNa_actionPrimary:disabled{background:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50);opacity:.55}.F1KBNa_actionQuietDisabled:disabled{cursor:pointer;color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l1);background:0 0}.F1KBNa_actionPrimary.F1KBNa_actionQuietDisabled:disabled{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50);opacity:1}.F1KBNa_iconAction{justify-content:center;align-items:center;min-height:25px;padding:4px 6px;display:inline-flex}.F1KBNa_close{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:0;display:inline-flex}.F1KBNa_close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.F1KBNa_expand{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:0;display:inline-flex}.F1KBNa_expand:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.F1KBNa_expandExpanded svg{transform:rotate(180deg)}.F1KBNa_diffBodyWrap{flex:1;min-height:0;display:flex;position:relative}.F1KBNa_diffBody{min-width:0;font:var(--dsw-font-markdown-code-block);cursor:text;outline:none;flex:1;padding:0;position:relative;overflow:auto}.F1KBNa_diffBody::-webkit-scrollbar,.F1KBNa_diffBody::-webkit-scrollbar-track,.F1KBNa_diffBody::-webkit-scrollbar-thumb{cursor:default}.F1KBNa_blockActions{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-markdown-code-block);box-shadow:var(--dsw-shadow-lv1);z-index:2;border-radius:10px;align-items:center;gap:9px;padding:5px;display:flex;position:absolute;right:8px}.F1KBNa_blockPosition{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;margin-top:1px;margin-left:7px;font-size:12px;line-height:16px}.F1KBNa_searchBar{z-index:3;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-markdown-code-block);box-shadow:var(--dsw-shadow-lv1);border-radius:10px;align-items:center;gap:4px;padding:4px;display:flex;position:absolute;top:8px;right:8px}.F1KBNa_searchInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);width:150px;color:var(--dsw-alias-label-primary);border-radius:6px;outline:none;padding:3px 8px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_searchInput:focus{border-color:var(--dsw-alias-state-business-primary)}.F1KBNa_searchCount{text-align:center;min-width:34px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12px;line-height:16px}.F1KBNa_diffBody [data-diff-search=hit]{background-image:linear-gradient(#facc1529,#facc1529)}.F1KBNa_diffBody [data-diff-search=current]{background-image:linear-gradient(#facc1552,#facc1552)}.F1KBNa_blockFlash{z-index:1;box-sizing:border-box;border:2px solid var(--dsw-alias-state-business-primary);pointer-events:none;border-radius:4px;animation:1s ease-out forwards F1KBNa_diffFlash;position:absolute;left:0;right:0}@keyframes F1KBNa_diffFlash{0%{opacity:1}to{opacity:0}}.F1KBNa_overviewRuler{pointer-events:none;opacity:.5;width:4px;position:absolute;top:0;bottom:0;right:0}.F1KBNa_overviewMarker{border-radius:2px;width:100%;min-height:2px;position:absolute;right:0}.F1KBNa_markerDel{background-color:var(--dsw-alias-state-error-primary)}.F1KBNa_markerAdd{background-color:var(--dsw-alias-state-success-primary)}.F1KBNa_lines{border-spacing:0;width:max-content;min-width:100%;display:table}.F1KBNa_line{height:22px;line-height:22px;display:table-row}.F1KBNa_vSpacer{display:table-row}.F1KBNa_gutter{box-sizing:border-box;text-align:right;width:44px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;user-select:none;cursor:default;padding-right:10px;display:table-cell}.F1KBNa_code{white-space:pre;display:table-cell}.F1KBNa_context{color:var(--dsw-alias-label-primary)}.F1KBNa_del{background-color:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.F1KBNa_add{background-color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 10%, transparent)}.F1KBNa_statusBar{box-sizing:border-box;border-top:1px solid var(--dsw-alias-border-l2);height:34px;color:var(--dsw-alias-label-tertiary);font-family:var(--dsw-font-markdown-code-block);font-variant-numeric:tabular-nums;flex:none;align-items:center;gap:8px;padding:0 8px;font-size:12px;line-height:18px;display:flex}.F1KBNa_statusAction{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);white-space:nowrap;cursor:pointer;background:0 0;border-radius:8px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_statusAction:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_langSelect{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;flex:none;align-items:center;gap:4px;padding:3px 12px;font-family:inherit;font-size:12px;line-height:18px;display:inline-flex}.F1KBNa_langSelect:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_langLabel{text-overflow:ellipsis;white-space:nowrap;max-width:140px;overflow:hidden}.F1KBNa_notice{z-index:60;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);max-width:360px;box-shadow:var(--dsw-shadow-lv3);border-radius:10px;align-items:flex-start;gap:12px;padding:12px 14px;display:flex;position:fixed;bottom:24px;right:24px}.F1KBNa_noticeText{font:var(--dsw-font-caption);color:var(--dsw-alias-label-primary);flex:1;margin:0;line-height:1.45}.F1KBNa_noticeButton{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);font:var(--dsw-font-caption);cursor:pointer;border-radius:6px;flex:none;padding:4px 10px}.F1KBNa_noticeButton:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}.F1KBNa_wrap .F1KBNa_line{height:auto;min-height:22px}.F1KBNa_subline{white-space:pre;height:22px;line-height:22px;display:block;overflow:hidden}.F1KBNa_wrapActive{background:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-static-neutral-bluish-50)}.F1KBNa_wrapActive:hover{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 85%, var(--dsw-static-neutral-bluish-1000))}.F1KBNa_splitRoot{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}.F1KBNa_diffBodySplit{flex:1;min-height:0;overflow-x:hidden}.F1KBNa_splitCols{width:100%;min-width:0;display:flex}.F1KBNa_splitCol{box-sizing:border-box;flex:1 1 0;min-width:0;overflow:hidden}.F1KBNa_splitDivider{background:var(--dsw-alias-border-l2);flex:0 0 1px}.F1KBNa_splitCol .F1KBNa_gutter,.F1KBNa_splitCol .F1KBNa_code{vertical-align:top}.F1KBNa_splitHScrollRow{border-top:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);flex:none;width:100%;min-width:0;display:flex}.F1KBNa_splitHScroll{flex:1 1 0;min-width:0;height:15px;overflow:auto hidden}.F1KBNa_splitHScroll::-webkit-scrollbar{height:15px}.F1KBNa_splitHScroll::-webkit-scrollbar-track{cursor:default}.F1KBNa_splitHScroll::-webkit-scrollbar-thumb{cursor:default}.F1KBNa_splitHScrollFill{height:1px}.F1KBNa_splitLdel{background-color:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.F1KBNa_splitLadd{background-color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 10%, transparent)}.F1KBNa_splitRdel{background-color:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.F1KBNa_splitRadd{background-color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 10%, transparent)}";
|
|
11692
11811
|
const tagId = "dsh-diff-approval/PendingPanel.module.css";
|
|
11693
11812
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
11694
11813
|
const tag = document.createElement("style");
|
|
@@ -11698,99 +11817,111 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
11698
11817
|
document.head.appendChild(tag);
|
|
11699
11818
|
}
|
|
11700
11819
|
var PendingPanel_module_css_default = {
|
|
11701
|
-
"
|
|
11702
|
-
"
|
|
11703
|
-
"
|
|
11704
|
-
"
|
|
11705
|
-
"
|
|
11820
|
+
"layer": "F1KBNa_layer",
|
|
11821
|
+
"rowHead": "F1KBNa_rowHead",
|
|
11822
|
+
"header": "F1KBNa_header",
|
|
11823
|
+
"searchCount": "F1KBNa_searchCount",
|
|
11824
|
+
"splitRdel": "F1KBNa_splitRdel",
|
|
11825
|
+
"blockActions": "F1KBNa_blockActions",
|
|
11826
|
+
"badge": "F1KBNa_badge",
|
|
11827
|
+
"fileList": "F1KBNa_fileList",
|
|
11828
|
+
"badgeLabel": "F1KBNa_badgeLabel",
|
|
11829
|
+
"rows": "F1KBNa_rows",
|
|
11830
|
+
"settingsRowTitle": "F1KBNa_settingsRowTitle",
|
|
11831
|
+
"rail": "F1KBNa_rail",
|
|
11832
|
+
"settingsPage": "F1KBNa_settingsPage",
|
|
11833
|
+
"add": "F1KBNa_add",
|
|
11834
|
+
"splitCols": "F1KBNa_splitCols",
|
|
11835
|
+
"splitHScrollRow": "F1KBNa_splitHScrollRow",
|
|
11836
|
+
"splitHScroll": "F1KBNa_splitHScroll",
|
|
11837
|
+
"diffPath": "F1KBNa_diffPath",
|
|
11838
|
+
"settingsRowText": "F1KBNa_settingsRowText",
|
|
11839
|
+
"detailEmpty": "F1KBNa_detailEmpty",
|
|
11840
|
+
"action": "F1KBNa_action",
|
|
11841
|
+
"notice": "F1KBNa_notice",
|
|
11842
|
+
"splitHScrollFill": "F1KBNa_splitHScrollFill",
|
|
11843
|
+
"splitLdel": "F1KBNa_splitLdel",
|
|
11844
|
+
"diffBodySplit": "F1KBNa_diffBodySplit",
|
|
11845
|
+
"wrap": "F1KBNa_wrap",
|
|
11846
|
+
"row": "F1KBNa_row",
|
|
11847
|
+
"expand": "F1KBNa_expand",
|
|
11848
|
+
"blockFlash": "F1KBNa_blockFlash",
|
|
11849
|
+
"importButton": "F1KBNa_importButton",
|
|
11850
|
+
"del": "F1KBNa_del",
|
|
11851
|
+
"splitRoot": "F1KBNa_splitRoot",
|
|
11852
|
+
"states": "F1KBNa_states",
|
|
11706
11853
|
"note": "F1KBNa_note",
|
|
11707
|
-
"
|
|
11708
|
-
"
|
|
11709
|
-
"
|
|
11854
|
+
"panel": "F1KBNa_panel",
|
|
11855
|
+
"title": "F1KBNa_title",
|
|
11856
|
+
"settingsSelector": "F1KBNa_settingsSelector",
|
|
11857
|
+
"diffBodyWrap": "F1KBNa_diffBodyWrap",
|
|
11858
|
+
"diffBody": "F1KBNa_diffBody",
|
|
11710
11859
|
"readError": "F1KBNa_readError",
|
|
11711
|
-
"
|
|
11712
|
-
"markerAdd": "F1KBNa_markerAdd",
|
|
11713
|
-
"del": "F1KBNa_del",
|
|
11714
|
-
"fileList": "F1KBNa_fileList",
|
|
11860
|
+
"bulkActions": "F1KBNa_bulkActions",
|
|
11715
11861
|
"delCount": "F1KBNa_delCount",
|
|
11716
|
-
"
|
|
11717
|
-
"
|
|
11862
|
+
"addCount": "F1KBNa_addCount",
|
|
11863
|
+
"diffStats": "F1KBNa_diffStats",
|
|
11864
|
+
"close": "F1KBNa_close",
|
|
11865
|
+
"kindHint": "F1KBNa_kindHint",
|
|
11866
|
+
"blockPosition": "F1KBNa_blockPosition",
|
|
11867
|
+
"searchInput": "F1KBNa_searchInput",
|
|
11868
|
+
"overviewRuler": "F1KBNa_overviewRuler",
|
|
11869
|
+
"vSpacer": "F1KBNa_vSpacer",
|
|
11718
11870
|
"context": "F1KBNa_context",
|
|
11719
|
-
"
|
|
11720
|
-
"
|
|
11871
|
+
"fullscreenBackdrop": "F1KBNa_fullscreenBackdrop",
|
|
11872
|
+
"gutter": "F1KBNa_gutter",
|
|
11873
|
+
"iconAction": "F1KBNa_iconAction",
|
|
11874
|
+
"statusBar": "F1KBNa_statusBar",
|
|
11875
|
+
"noticeText": "F1KBNa_noticeText",
|
|
11876
|
+
"wrapActive": "F1KBNa_wrapActive",
|
|
11877
|
+
"splitRadd": "F1KBNa_splitRadd",
|
|
11721
11878
|
"rowMeta": "F1KBNa_rowMeta",
|
|
11722
|
-
"
|
|
11723
|
-
"
|
|
11724
|
-
"expand": "F1KBNa_expand",
|
|
11725
|
-
"lines": "F1KBNa_lines",
|
|
11726
|
-
"missingHint": "F1KBNa_missingHint",
|
|
11879
|
+
"diffHeader": "F1KBNa_diffHeader",
|
|
11880
|
+
"footerButtons": "F1KBNa_footerButtons",
|
|
11727
11881
|
"headerActions": "F1KBNa_headerActions",
|
|
11882
|
+
"actionQuietDisabled": "F1KBNa_actionQuietDisabled",
|
|
11883
|
+
"detail": "F1KBNa_detail",
|
|
11884
|
+
"missing": "F1KBNa_missing",
|
|
11885
|
+
"markerDel": "F1KBNa_markerDel",
|
|
11728
11886
|
"settingsRowDesc": "F1KBNa_settingsRowDesc",
|
|
11729
|
-
"
|
|
11730
|
-
"iconAction": "F1KBNa_iconAction",
|
|
11731
|
-
"rail": "F1KBNa_rail",
|
|
11732
|
-
"wrap": "F1KBNa_wrap",
|
|
11733
|
-
"diffPath": "F1KBNa_diffPath",
|
|
11887
|
+
"langSelect": "F1KBNa_langSelect",
|
|
11734
11888
|
"importNote": "F1KBNa_importNote",
|
|
11735
|
-
"
|
|
11736
|
-
"
|
|
11889
|
+
"listScroll": "F1KBNa_listScroll",
|
|
11890
|
+
"group": "F1KBNa_group",
|
|
11891
|
+
"divergedHint": "F1KBNa_divergedHint",
|
|
11892
|
+
"splitCol": "F1KBNa_splitCol",
|
|
11737
11893
|
"resizeHandle": "F1KBNa_resizeHandle",
|
|
11738
|
-
"
|
|
11739
|
-
"
|
|
11740
|
-
"
|
|
11741
|
-
"
|
|
11742
|
-
"emptyState": "F1KBNa_emptyState",
|
|
11743
|
-
"badgeLabel": "F1KBNa_badgeLabel",
|
|
11744
|
-
"rowFailed": "F1KBNa_rowFailed",
|
|
11745
|
-
"layer": "F1KBNa_layer",
|
|
11746
|
-
"badgeCount": "F1KBNa_badgeCount",
|
|
11894
|
+
"actionPrimary": "F1KBNa_actionPrimary",
|
|
11895
|
+
"diffFlash": "F1KBNa_diffFlash",
|
|
11896
|
+
"subline": "F1KBNa_subline",
|
|
11897
|
+
"statusAction": "F1KBNa_statusAction",
|
|
11747
11898
|
"noteCentered": "F1KBNa_noteCentered",
|
|
11748
|
-
"settingsSelectorChevron": "F1KBNa_settingsSelectorChevron",
|
|
11749
|
-
"importButton": "F1KBNa_importButton",
|
|
11750
|
-
"header": "F1KBNa_header",
|
|
11751
|
-
"action": "F1KBNa_action",
|
|
11752
11899
|
"actionError": "F1KBNa_actionError",
|
|
11753
|
-
"
|
|
11754
|
-
"settingsRowText": "F1KBNa_settingsRowText",
|
|
11755
|
-
"actionQuietDisabled": "F1KBNa_actionQuietDisabled",
|
|
11756
|
-
"blockActions": "F1KBNa_blockActions",
|
|
11757
|
-
"listScroll": "F1KBNa_listScroll",
|
|
11900
|
+
"lines": "F1KBNa_lines",
|
|
11758
11901
|
"hint": "F1KBNa_hint",
|
|
11759
|
-
"
|
|
11760
|
-
"
|
|
11902
|
+
"diff": "F1KBNa_diff",
|
|
11903
|
+
"markerAdd": "F1KBNa_markerAdd",
|
|
11904
|
+
"code": "F1KBNa_code",
|
|
11905
|
+
"emptyState": "F1KBNa_emptyState",
|
|
11761
11906
|
"expandExpanded": "F1KBNa_expandExpanded",
|
|
11762
|
-
"settingsRow": "F1KBNa_settingsRow",
|
|
11763
|
-
"blockPosition": "F1KBNa_blockPosition",
|
|
11764
|
-
"statusAction": "F1KBNa_statusAction",
|
|
11765
|
-
"searchBar": "F1KBNa_searchBar",
|
|
11766
|
-
"searchInput": "F1KBNa_searchInput",
|
|
11767
|
-
"rows": "F1KBNa_rows",
|
|
11768
|
-
"statusBar": "F1KBNa_statusBar",
|
|
11769
|
-
"settingsPage": "F1KBNa_settingsPage",
|
|
11770
|
-
"overviewMarker": "F1KBNa_overviewMarker",
|
|
11771
|
-
"add": "F1KBNa_add",
|
|
11772
11907
|
"langLabel": "F1KBNa_langLabel",
|
|
11773
|
-
"
|
|
11774
|
-
"
|
|
11908
|
+
"searchBar": "F1KBNa_searchBar",
|
|
11909
|
+
"badgeCount": "F1KBNa_badgeCount",
|
|
11910
|
+
"diffActions": "F1KBNa_diffActions",
|
|
11911
|
+
"splitDivider": "F1KBNa_splitDivider",
|
|
11912
|
+
"settingsRow": "F1KBNa_settingsRow",
|
|
11913
|
+
"noticeButton": "F1KBNa_noticeButton",
|
|
11914
|
+
"splitLadd": "F1KBNa_splitLadd",
|
|
11915
|
+
"settingsSelectorChevron": "F1KBNa_settingsSelectorChevron",
|
|
11775
11916
|
"rowPath": "F1KBNa_rowPath",
|
|
11776
|
-
"
|
|
11777
|
-
"
|
|
11778
|
-
"
|
|
11779
|
-
"
|
|
11780
|
-
"
|
|
11781
|
-
"
|
|
11782
|
-
"diffFlash": "F1KBNa_diffFlash",
|
|
11783
|
-
"subline": "F1KBNa_subline",
|
|
11917
|
+
"fileListFloat": "F1KBNa_fileListFloat",
|
|
11918
|
+
"missingHint": "F1KBNa_missingHint",
|
|
11919
|
+
"rowFailed": "F1KBNa_rowFailed",
|
|
11920
|
+
"overviewMarker": "F1KBNa_overviewMarker",
|
|
11921
|
+
"kindTag": "F1KBNa_kindTag",
|
|
11922
|
+
"flexSpacer": "F1KBNa_flexSpacer",
|
|
11784
11923
|
"split": "F1KBNa_split",
|
|
11785
|
-
"
|
|
11786
|
-
"noticeButton": "F1KBNa_noticeButton",
|
|
11787
|
-
"row": "F1KBNa_row",
|
|
11788
|
-
"wrapActive": "F1KBNa_wrapActive",
|
|
11789
|
-
"settingsRowTitle": "F1KBNa_settingsRowTitle",
|
|
11790
|
-
"group": "F1KBNa_group",
|
|
11791
|
-
"rowHead": "F1KBNa_rowHead",
|
|
11792
|
-
"actionPrimary": "F1KBNa_actionPrimary",
|
|
11793
|
-
"noticeText": "F1KBNa_noticeText"
|
|
11924
|
+
"line": "F1KBNa_line"
|
|
11794
11925
|
};
|
|
11795
11926
|
//#endregion
|
|
11796
11927
|
//#region lib/types/client/PendingPanel.js
|
|
@@ -12155,6 +12286,541 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12155
12286
|
});
|
|
12156
12287
|
return blocks;
|
|
12157
12288
|
}
|
|
12289
|
+
/** One side's line-content for the split view: the highlighted runs or plain text. */
|
|
12290
|
+
function splitSideContent(side, wrapped, runs) {
|
|
12291
|
+
if (side === void 0) return "";
|
|
12292
|
+
const highlighted = runs !== void 0 && runs.length > 0;
|
|
12293
|
+
if (wrapped === void 0) return highlighted ? runs.map((span, i) => (0, react_jsx_runtime.jsx)("span", {
|
|
12294
|
+
style: span.style,
|
|
12295
|
+
children: span.text
|
|
12296
|
+
}, i)) : side.text === "" ? "\xA0" : side.text;
|
|
12297
|
+
let offset = 0;
|
|
12298
|
+
return wrapped.map((line, i) => {
|
|
12299
|
+
const start = offset;
|
|
12300
|
+
offset += line.length;
|
|
12301
|
+
const content = highlighted ? clipRuns(runs, start, offset) : line === "" ? "\xA0" : line;
|
|
12302
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
12303
|
+
className: PendingPanel_module_css_default.subline,
|
|
12304
|
+
children: content
|
|
12305
|
+
}, i);
|
|
12306
|
+
});
|
|
12307
|
+
}
|
|
12308
|
+
/**
|
|
12309
|
+
* One side of a split pair row, rendered inside its own column. The two columns
|
|
12310
|
+
* are drawn by two independent `.splitCol` scrollers (each with its own
|
|
12311
|
+
* horizontal scrollbar) that share one vertical scroller, and each row gets the
|
|
12312
|
+
* same fixed `height` (the pair's max of the two sides' wrapped sub-line
|
|
12313
|
+
* counts) so the left/right halves always align on the same Y — no jump when
|
|
12314
|
+
* one side is longer. The gutter and code are top-aligned so sub-lines line up
|
|
12315
|
+
* across the divider.
|
|
12316
|
+
*/
|
|
12317
|
+
function SplitSideRow({ index, side, wrapped, runs, kind, isLeft, height, focused, searchHit, searchCurrent, onHover }) {
|
|
12318
|
+
const tint = isLeft ? kind === "del" || kind === "replace" ? PendingPanel_module_css_default.splitLdel : "" : kind === "add" || kind === "replace" ? PendingPanel_module_css_default.splitRadd : "";
|
|
12319
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
12320
|
+
className: PendingPanel_module_css_default.line,
|
|
12321
|
+
style: { height },
|
|
12322
|
+
"data-diff-split-row": true,
|
|
12323
|
+
"data-diff-split-index": index,
|
|
12324
|
+
"data-diff-split-side": isLeft ? "left" : "right",
|
|
12325
|
+
"data-diff-focused": focused ? "" : void 0,
|
|
12326
|
+
"data-diff-search": searchHit ? searchCurrent ? "current" : "hit" : void 0,
|
|
12327
|
+
onMouseEnter: onHover,
|
|
12328
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
12329
|
+
className: PendingPanel_module_css_default.gutter,
|
|
12330
|
+
children: side?.line ?? ""
|
|
12331
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
12332
|
+
className: `${PendingPanel_module_css_default.code} ${tint}`,
|
|
12333
|
+
"data-diff-code": true,
|
|
12334
|
+
children: splitSideContent(side, wrapped, runs)
|
|
12335
|
+
})]
|
|
12336
|
+
});
|
|
12337
|
+
}
|
|
12338
|
+
/** The two-column (side-by-side) whole-file diff view. */
|
|
12339
|
+
const SplitDiff = (0, react.forwardRef)(function SplitDiff({ file, model, runs, langWrap, tabWidthSpaces, busy, t, onBlockKeep, onBlockRevert }, ref) {
|
|
12340
|
+
const { pairs, pairOfRow } = (0, react.useMemo)(() => computeSideBySideDiff(model.diff.rows), [model]);
|
|
12341
|
+
const pairCount = pairs.length;
|
|
12342
|
+
const bodyRef = (0, react.useRef)(null);
|
|
12343
|
+
const [scrollTop, setScrollTop] = (0, react.useState)(0);
|
|
12344
|
+
const [viewportH, setViewportH] = (0, react.useState)(0);
|
|
12345
|
+
const [bodyWidth, setBodyWidth] = (0, react.useState)(0);
|
|
12346
|
+
const [hoveredBlock, setHoveredBlock] = (0, react.useState)(void 0);
|
|
12347
|
+
const [focus, setFocus] = (0, react.useState)(0);
|
|
12348
|
+
const [flashKey, setFlashKey] = (0, react.useState)(0);
|
|
12349
|
+
const hoveredBlockRef = (0, react.useRef)(void 0);
|
|
12350
|
+
const leftColRef = (0, react.useRef)(null);
|
|
12351
|
+
const rightColRef = (0, react.useRef)(null);
|
|
12352
|
+
const leftHScrollRef = (0, react.useRef)(null);
|
|
12353
|
+
const rightHScrollRef = (0, react.useRef)(null);
|
|
12354
|
+
const [fillWidth, setFillWidth] = (0, react.useState)({
|
|
12355
|
+
left: 0,
|
|
12356
|
+
right: 0
|
|
12357
|
+
});
|
|
12358
|
+
const [searchOpen, setSearchOpen] = (0, react.useState)(false);
|
|
12359
|
+
const [searchQuery, setSearchQuery] = (0, react.useState)("");
|
|
12360
|
+
const [searchIndex, setSearchIndex] = (0, react.useState)(0);
|
|
12361
|
+
const searchInputRef = (0, react.useRef)(null);
|
|
12362
|
+
(0, react.useEffect)(() => {
|
|
12363
|
+
setFocus(0);
|
|
12364
|
+
bodyRef.current?.focus();
|
|
12365
|
+
setFlashKey((k) => k + 1);
|
|
12366
|
+
setHoveredBlock(void 0);
|
|
12367
|
+
setSearchOpen(false);
|
|
12368
|
+
setSearchQuery("");
|
|
12369
|
+
setSearchIndex(0);
|
|
12370
|
+
}, [file.id]);
|
|
12371
|
+
(0, react.useEffect)(() => {
|
|
12372
|
+
const body = bodyRef.current;
|
|
12373
|
+
if (body === null) return;
|
|
12374
|
+
const measure = () => {
|
|
12375
|
+
setViewportH(body.clientHeight);
|
|
12376
|
+
setBodyWidth(body.clientWidth);
|
|
12377
|
+
};
|
|
12378
|
+
measure();
|
|
12379
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
|
|
12380
|
+
observer?.observe(body);
|
|
12381
|
+
return () => {
|
|
12382
|
+
observer?.disconnect();
|
|
12383
|
+
};
|
|
12384
|
+
}, [file.id]);
|
|
12385
|
+
const blockOfPair = (0, react.useMemo)(() => model.blocks.map((block) => ({
|
|
12386
|
+
start: pairOfRow.get(block.start) ?? 0,
|
|
12387
|
+
end: pairOfRow.get(block.end) ?? 0
|
|
12388
|
+
})), [model, pairOfRow]);
|
|
12389
|
+
const blockIndexByPair = (0, react.useMemo)(() => {
|
|
12390
|
+
const map = /* @__PURE__ */ new Map();
|
|
12391
|
+
blockOfPair.forEach((block, bi) => {
|
|
12392
|
+
for (let k = block.start; k <= block.end; k++) map.set(k, bi);
|
|
12393
|
+
});
|
|
12394
|
+
return map;
|
|
12395
|
+
}, [blockOfPair]);
|
|
12396
|
+
const onPairHover = (0, react.useCallback)((k) => {
|
|
12397
|
+
const bi = blockIndexByPair.get(k);
|
|
12398
|
+
setHoveredBlock(bi);
|
|
12399
|
+
if (bi !== void 0) hoveredBlockRef.current = bi;
|
|
12400
|
+
}, [blockIndexByPair]);
|
|
12401
|
+
const colWidth = Math.max(0, (bodyWidth - 1) / 2);
|
|
12402
|
+
const pairWrapped = (0, react.useMemo)(() => {
|
|
12403
|
+
if (!langWrap || bodyWidth === 0) return null;
|
|
12404
|
+
const measure = makeMeasurer(codeFontOf());
|
|
12405
|
+
if (measure === void 0) return null;
|
|
12406
|
+
const charWidth = measure("0");
|
|
12407
|
+
const wrapW = colWidth - WRAP_GUTTERS_PX / 2 - charWidth;
|
|
12408
|
+
const tabPx = tabWidthSpaces * measure(" ");
|
|
12409
|
+
return pairs.map((p) => ({
|
|
12410
|
+
left: p.left === void 0 ? void 0 : wrapInto(p.left.text, wrapW, measure, tabPx),
|
|
12411
|
+
right: p.right === void 0 ? void 0 : wrapInto(p.right.text, wrapW, measure, tabPx)
|
|
12412
|
+
}));
|
|
12413
|
+
}, [
|
|
12414
|
+
pairs,
|
|
12415
|
+
langWrap,
|
|
12416
|
+
bodyWidth,
|
|
12417
|
+
colWidth,
|
|
12418
|
+
tabWidthSpaces
|
|
12419
|
+
]);
|
|
12420
|
+
const pairHeights = (0, react.useMemo)(() => {
|
|
12421
|
+
if (pairWrapped === null) return null;
|
|
12422
|
+
return pairWrapped.map((w) => Math.max(w.left?.length ?? 1, w.right?.length ?? 1) * ROW_HEIGHT_PX);
|
|
12423
|
+
}, [pairWrapped]);
|
|
12424
|
+
const pairOffsets = (0, react.useMemo)(() => {
|
|
12425
|
+
if (pairHeights === null) return null;
|
|
12426
|
+
const offs = new Array(pairHeights.length + 1);
|
|
12427
|
+
offs[0] = 0;
|
|
12428
|
+
for (let i = 0; i < pairHeights.length; i++) offs[i + 1] = offs[i] + pairHeights[i];
|
|
12429
|
+
return offs;
|
|
12430
|
+
}, [pairHeights]);
|
|
12431
|
+
const totalHeight = pairOffsets === null ? pairCount * ROW_HEIGHT_PX : pairOffsets[pairCount] ?? 0;
|
|
12432
|
+
const off = (k) => pairOffsets === null ? k * ROW_HEIGHT_PX : pairOffsets[Math.max(0, Math.min(k, pairCount))] ?? 0;
|
|
12433
|
+
const pairHeightAt = (k) => pairHeights === null ? ROW_HEIGHT_PX : pairHeights[k] ?? ROW_HEIGHT_PX;
|
|
12434
|
+
const widestSide = (0, react.useMemo)(() => {
|
|
12435
|
+
let left = 0;
|
|
12436
|
+
let right = 0;
|
|
12437
|
+
for (const p of pairs) {
|
|
12438
|
+
if (p.left !== void 0) left = Math.max(left, p.left.text.length);
|
|
12439
|
+
if (p.right !== void 0) right = Math.max(right, p.right.text.length);
|
|
12440
|
+
}
|
|
12441
|
+
return {
|
|
12442
|
+
left,
|
|
12443
|
+
right
|
|
12444
|
+
};
|
|
12445
|
+
}, [pairs]);
|
|
12446
|
+
(0, react.useLayoutEffect)(() => {
|
|
12447
|
+
const sync = (side) => {
|
|
12448
|
+
const col = side === "left" ? leftColRef.current : rightColRef.current;
|
|
12449
|
+
const strip = side === "left" ? leftHScrollRef.current : rightHScrollRef.current;
|
|
12450
|
+
if (col === null || strip === null) return;
|
|
12451
|
+
const width = col.scrollWidth;
|
|
12452
|
+
setFillWidth((prev) => prev[side] === width ? prev : {
|
|
12453
|
+
...prev,
|
|
12454
|
+
[side]: width
|
|
12455
|
+
});
|
|
12456
|
+
strip.scrollLeft = col.scrollLeft;
|
|
12457
|
+
};
|
|
12458
|
+
sync("left");
|
|
12459
|
+
sync("right");
|
|
12460
|
+
}, [
|
|
12461
|
+
pairs,
|
|
12462
|
+
langWrap,
|
|
12463
|
+
tabWidthSpaces,
|
|
12464
|
+
bodyWidth
|
|
12465
|
+
]);
|
|
12466
|
+
const onHScroll = (0, react.useCallback)((side) => {
|
|
12467
|
+
const strip = side === "left" ? leftHScrollRef.current : rightHScrollRef.current;
|
|
12468
|
+
const col = side === "left" ? leftColRef.current : rightColRef.current;
|
|
12469
|
+
if (strip === null || col === null) return;
|
|
12470
|
+
col.scrollLeft = strip.scrollLeft;
|
|
12471
|
+
}, []);
|
|
12472
|
+
const searchMatches = (0, react.useMemo)(() => searchPairs(pairs, searchQuery), [pairs, searchQuery]);
|
|
12473
|
+
const searchHitSet = (0, react.useMemo)(() => new Set(searchMatches), [searchMatches]);
|
|
12474
|
+
const currentSearchPair = searchMatches.length === 0 ? void 0 : searchMatches[searchIndex % searchMatches.length];
|
|
12475
|
+
const closeSearch = () => {
|
|
12476
|
+
setSearchOpen(false);
|
|
12477
|
+
setSearchQuery("");
|
|
12478
|
+
setSearchIndex(0);
|
|
12479
|
+
bodyRef.current?.focus();
|
|
12480
|
+
};
|
|
12481
|
+
const openSearch = () => {
|
|
12482
|
+
setSearchOpen(true);
|
|
12483
|
+
requestAnimationFrame(() => {
|
|
12484
|
+
searchInputRef.current?.focus();
|
|
12485
|
+
searchInputRef.current?.select();
|
|
12486
|
+
});
|
|
12487
|
+
};
|
|
12488
|
+
const goSearch = (direction) => {
|
|
12489
|
+
const len = searchMatches.length;
|
|
12490
|
+
if (len === 0) return;
|
|
12491
|
+
const next = (searchIndex + direction + len) % len;
|
|
12492
|
+
setSearchIndex(next);
|
|
12493
|
+
const pairIndex = searchMatches[next];
|
|
12494
|
+
if (pairIndex === void 0) return;
|
|
12495
|
+
const body = bodyRef.current;
|
|
12496
|
+
if (body === null) return;
|
|
12497
|
+
const target = Math.max(0, off(pairIndex) - 44);
|
|
12498
|
+
const clamped = Math.max(0, Math.min(target, body.scrollHeight - body.clientHeight));
|
|
12499
|
+
if (body.scrollTop !== clamped) body.scrollTop = clamped;
|
|
12500
|
+
setScrollTop(clamped);
|
|
12501
|
+
};
|
|
12502
|
+
const handleBlockAction = async (action) => {
|
|
12503
|
+
const operated = hoveredBlock ?? hoveredBlockRef.current;
|
|
12504
|
+
if (operated === void 0) return;
|
|
12505
|
+
const range = blockRanges[operated];
|
|
12506
|
+
if (range === void 0) return;
|
|
12507
|
+
await (action === "keep" ? onBlockKeep(file.sessionId, file.id, range) : onBlockRevert(file.sessionId, file.id, range));
|
|
12508
|
+
const count = model.blocks.length;
|
|
12509
|
+
if (count === 0) return;
|
|
12510
|
+
const next = Math.max(0, Math.min(operated, count - 1));
|
|
12511
|
+
setFocus(next);
|
|
12512
|
+
setHoveredBlock(void 0);
|
|
12513
|
+
setFlashKey((key) => key + 1);
|
|
12514
|
+
};
|
|
12515
|
+
const pairAtY = (y) => {
|
|
12516
|
+
if (pairOffsets === null) return Math.floor(y / ROW_HEIGHT_PX);
|
|
12517
|
+
if (y <= 0) return 0;
|
|
12518
|
+
let lo = 0, hi = pairCount;
|
|
12519
|
+
while (lo < hi) {
|
|
12520
|
+
const mid = lo + hi + 1 >> 1;
|
|
12521
|
+
if ((pairOffsets[mid] ?? 0) <= y) lo = mid;
|
|
12522
|
+
else hi = mid - 1;
|
|
12523
|
+
}
|
|
12524
|
+
return lo;
|
|
12525
|
+
};
|
|
12526
|
+
const viewport = viewportH > 0 ? viewportH : totalHeight;
|
|
12527
|
+
const start = Math.max(0, pairAtY(scrollTop) - OVERSCAN_ROWS);
|
|
12528
|
+
const end = Math.min(pairCount, pairAtY(scrollTop + viewport) + OVERSCAN_ROWS);
|
|
12529
|
+
const visiblePairs = pairs.slice(start, end);
|
|
12530
|
+
const jump = (direction) => {
|
|
12531
|
+
if (blockOfPair.length === 0) return;
|
|
12532
|
+
setFocus((current) => {
|
|
12533
|
+
if (direction === -1) return (current - 1 + blockOfPair.length) % blockOfPair.length;
|
|
12534
|
+
const top = bodyRef.current?.scrollTop ?? 0;
|
|
12535
|
+
for (let index = current + 1; index < blockOfPair.length; index++) if (off(blockOfPair[index].start) >= top) return index;
|
|
12536
|
+
return 0;
|
|
12537
|
+
});
|
|
12538
|
+
setFlashKey((k) => k + 1);
|
|
12539
|
+
};
|
|
12540
|
+
(0, react.useImperativeHandle)(ref, () => ({
|
|
12541
|
+
jump,
|
|
12542
|
+
openSearch
|
|
12543
|
+
}), [jump, openSearch]);
|
|
12544
|
+
(0, react.useLayoutEffect)(() => {
|
|
12545
|
+
if (pairCount === 0) return;
|
|
12546
|
+
const block = blockOfPair[focus];
|
|
12547
|
+
if (block === void 0) return;
|
|
12548
|
+
const body = bodyRef.current;
|
|
12549
|
+
if (body === null) return;
|
|
12550
|
+
const target = off(block.start) - 44;
|
|
12551
|
+
const clamped = Math.max(0, Math.min(target, body.scrollHeight - body.clientHeight));
|
|
12552
|
+
if (body.scrollTop !== clamped) body.scrollTop = clamped;
|
|
12553
|
+
setScrollTop(clamped);
|
|
12554
|
+
}, [
|
|
12555
|
+
model,
|
|
12556
|
+
focus,
|
|
12557
|
+
flashKey,
|
|
12558
|
+
pairCount
|
|
12559
|
+
]);
|
|
12560
|
+
const onScroll = () => {
|
|
12561
|
+
setScrollTop(bodyRef.current?.scrollTop ?? 0);
|
|
12562
|
+
};
|
|
12563
|
+
const inFocused = (k) => {
|
|
12564
|
+
const block = blockOfPair[focus];
|
|
12565
|
+
return block !== void 0 && k >= block.start && k <= block.end;
|
|
12566
|
+
};
|
|
12567
|
+
const blockRanges = (0, react.useMemo)(() => model.blocks.map((block) => blockRangesOf(model.diff.rows, block)), [model]);
|
|
12568
|
+
const focusedBlock = blockOfPair[focus];
|
|
12569
|
+
const flashTop = focusedBlock === void 0 ? 0 : Math.max(0, off(focusedBlock.start) - scrollTop);
|
|
12570
|
+
const flashBottom = focusedBlock === void 0 ? 0 : Math.min(viewportH > 0 ? viewportH : Number.POSITIVE_INFINITY, off(focusedBlock.end + 1) - scrollTop);
|
|
12571
|
+
const flashHeight = Math.max(0, flashBottom - flashTop);
|
|
12572
|
+
const blockActionsTop = hoveredBlock === void 0 || blockOfPair[hoveredBlock] === void 0 ? 0 : Math.max(0, Math.min(off(blockOfPair[hoveredBlock].end + 1) - scrollTop, Math.max(0, viewportH - BLOCK_ACTIONS_FRAME_PX)));
|
|
12573
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
12574
|
+
className: PendingPanel_module_css_default.splitRoot,
|
|
12575
|
+
onMouseLeave: () => setHoveredBlock(void 0),
|
|
12576
|
+
children: [
|
|
12577
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
12578
|
+
className: `${PendingPanel_module_css_default.diffBody} ${PendingPanel_module_css_default.diffBodySplit}`,
|
|
12579
|
+
ref: bodyRef,
|
|
12580
|
+
tabIndex: 0,
|
|
12581
|
+
onScroll,
|
|
12582
|
+
style: { tabSize: tabWidthSpaces },
|
|
12583
|
+
"data-diff-body": true,
|
|
12584
|
+
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
12585
|
+
className: PendingPanel_module_css_default.splitCols,
|
|
12586
|
+
children: [
|
|
12587
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
12588
|
+
className: PendingPanel_module_css_default.splitCol,
|
|
12589
|
+
ref: leftColRef,
|
|
12590
|
+
"data-diff-split-side": "left",
|
|
12591
|
+
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
12592
|
+
className: `${PendingPanel_module_css_default.lines}${langWrap ? " " + PendingPanel_module_css_default.wrap : ""}`,
|
|
12593
|
+
style: langWrap ? void 0 : { minWidth: `max(100%, ${widestSide.left}ch)` },
|
|
12594
|
+
children: [
|
|
12595
|
+
start > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
12596
|
+
className: PendingPanel_module_css_default.vSpacer,
|
|
12597
|
+
style: { height: off(start) },
|
|
12598
|
+
"aria-hidden": "true"
|
|
12599
|
+
}),
|
|
12600
|
+
visiblePairs.map((pair, offset) => {
|
|
12601
|
+
const index = start + offset;
|
|
12602
|
+
const leftRuns = pair.left === void 0 ? void 0 : runs?.oldRuns?.[(pair.left.line ?? 0) - 1];
|
|
12603
|
+
return (0, react_jsx_runtime.jsx)(SplitSideRow, {
|
|
12604
|
+
index,
|
|
12605
|
+
side: pair.left,
|
|
12606
|
+
wrapped: pairWrapped?.[index]?.left,
|
|
12607
|
+
runs: leftRuns,
|
|
12608
|
+
kind: pair.kind,
|
|
12609
|
+
isLeft: true,
|
|
12610
|
+
height: pairHeightAt(index),
|
|
12611
|
+
focused: inFocused(index),
|
|
12612
|
+
searchHit: searchHitSet.has(index),
|
|
12613
|
+
searchCurrent: index === currentSearchPair,
|
|
12614
|
+
onHover: () => onPairHover(index)
|
|
12615
|
+
}, index);
|
|
12616
|
+
}),
|
|
12617
|
+
end < pairCount && (0, react_jsx_runtime.jsx)("div", {
|
|
12618
|
+
className: PendingPanel_module_css_default.vSpacer,
|
|
12619
|
+
style: { height: totalHeight - off(end) },
|
|
12620
|
+
"aria-hidden": "true"
|
|
12621
|
+
})
|
|
12622
|
+
]
|
|
12623
|
+
})
|
|
12624
|
+
}),
|
|
12625
|
+
(0, react_jsx_runtime.jsx)("div", { className: PendingPanel_module_css_default.splitDivider }),
|
|
12626
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
12627
|
+
className: PendingPanel_module_css_default.splitCol,
|
|
12628
|
+
ref: rightColRef,
|
|
12629
|
+
"data-diff-split-side": "right",
|
|
12630
|
+
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
12631
|
+
className: `${PendingPanel_module_css_default.lines}${langWrap ? " " + PendingPanel_module_css_default.wrap : ""}`,
|
|
12632
|
+
style: langWrap ? void 0 : { minWidth: `max(100%, ${widestSide.right}ch)` },
|
|
12633
|
+
children: [
|
|
12634
|
+
start > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
12635
|
+
className: PendingPanel_module_css_default.vSpacer,
|
|
12636
|
+
style: { height: off(start) },
|
|
12637
|
+
"aria-hidden": "true"
|
|
12638
|
+
}),
|
|
12639
|
+
visiblePairs.map((pair, offset) => {
|
|
12640
|
+
const index = start + offset;
|
|
12641
|
+
const rightRuns = pair.right === void 0 ? void 0 : runs?.newRuns?.[(pair.right.line ?? 0) - 1];
|
|
12642
|
+
return (0, react_jsx_runtime.jsx)(SplitSideRow, {
|
|
12643
|
+
index,
|
|
12644
|
+
side: pair.right,
|
|
12645
|
+
wrapped: pairWrapped?.[index]?.right,
|
|
12646
|
+
runs: rightRuns,
|
|
12647
|
+
kind: pair.kind,
|
|
12648
|
+
isLeft: false,
|
|
12649
|
+
height: pairHeightAt(index),
|
|
12650
|
+
focused: inFocused(index),
|
|
12651
|
+
searchHit: searchHitSet.has(index),
|
|
12652
|
+
searchCurrent: index === currentSearchPair,
|
|
12653
|
+
onHover: () => onPairHover(index)
|
|
12654
|
+
}, index);
|
|
12655
|
+
}),
|
|
12656
|
+
end < pairCount && (0, react_jsx_runtime.jsx)("div", {
|
|
12657
|
+
className: PendingPanel_module_css_default.vSpacer,
|
|
12658
|
+
style: { height: totalHeight - off(end) },
|
|
12659
|
+
"aria-hidden": "true"
|
|
12660
|
+
})
|
|
12661
|
+
]
|
|
12662
|
+
})
|
|
12663
|
+
})
|
|
12664
|
+
]
|
|
12665
|
+
})
|
|
12666
|
+
}),
|
|
12667
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
12668
|
+
className: PendingPanel_module_css_default.splitHScrollRow,
|
|
12669
|
+
"data-diff-hscroll-row": true,
|
|
12670
|
+
children: [
|
|
12671
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
12672
|
+
className: PendingPanel_module_css_default.splitHScroll,
|
|
12673
|
+
ref: leftHScrollRef,
|
|
12674
|
+
"data-diff-hscroll": "left",
|
|
12675
|
+
style: {
|
|
12676
|
+
width: colWidth,
|
|
12677
|
+
flex: "none"
|
|
12678
|
+
},
|
|
12679
|
+
onScroll: () => onHScroll("left"),
|
|
12680
|
+
children: (0, react_jsx_runtime.jsx)("div", {
|
|
12681
|
+
className: PendingPanel_module_css_default.splitHScrollFill,
|
|
12682
|
+
style: { width: fillWidth.left || void 0 }
|
|
12683
|
+
})
|
|
12684
|
+
}),
|
|
12685
|
+
(0, react_jsx_runtime.jsx)("div", { className: PendingPanel_module_css_default.splitDivider }),
|
|
12686
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
12687
|
+
className: PendingPanel_module_css_default.splitHScroll,
|
|
12688
|
+
ref: rightHScrollRef,
|
|
12689
|
+
"data-diff-hscroll": "right",
|
|
12690
|
+
style: {
|
|
12691
|
+
width: colWidth,
|
|
12692
|
+
flex: "none"
|
|
12693
|
+
},
|
|
12694
|
+
onScroll: () => onHScroll("right"),
|
|
12695
|
+
children: (0, react_jsx_runtime.jsx)("div", {
|
|
12696
|
+
className: PendingPanel_module_css_default.splitHScrollFill,
|
|
12697
|
+
style: { width: fillWidth.right || void 0 }
|
|
12698
|
+
})
|
|
12699
|
+
})
|
|
12700
|
+
]
|
|
12701
|
+
}),
|
|
12702
|
+
searchOpen && (0, react_jsx_runtime.jsxs)("div", {
|
|
12703
|
+
className: PendingPanel_module_css_default.searchBar,
|
|
12704
|
+
"data-diff-searchbar": true,
|
|
12705
|
+
children: [
|
|
12706
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
12707
|
+
ref: searchInputRef,
|
|
12708
|
+
className: PendingPanel_module_css_default.searchInput,
|
|
12709
|
+
"data-diff-search-input": true,
|
|
12710
|
+
value: searchQuery,
|
|
12711
|
+
placeholder: t("panel.searchPlaceholder"),
|
|
12712
|
+
onChange: (event) => {
|
|
12713
|
+
setSearchQuery(event.target.value);
|
|
12714
|
+
setSearchIndex(0);
|
|
12715
|
+
},
|
|
12716
|
+
onKeyDown: (event) => {
|
|
12717
|
+
if (event.key === "Enter") {
|
|
12718
|
+
event.preventDefault();
|
|
12719
|
+
goSearch(event.shiftKey ? -1 : 1);
|
|
12720
|
+
} else if (event.key === "Escape") closeSearch();
|
|
12721
|
+
}
|
|
12722
|
+
}),
|
|
12723
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
12724
|
+
className: PendingPanel_module_css_default.searchCount,
|
|
12725
|
+
"data-diff-search-count": true,
|
|
12726
|
+
children: searchMatches.length === 0 ? "0/0" : `${searchIndex % searchMatches.length + 1}/${searchMatches.length}`
|
|
12727
|
+
}),
|
|
12728
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
12729
|
+
type: "button",
|
|
12730
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
|
|
12731
|
+
"data-diff-search-prev": true,
|
|
12732
|
+
"aria-label": t("action.prevDiff"),
|
|
12733
|
+
disabled: searchMatches.length === 0,
|
|
12734
|
+
onClick: () => {
|
|
12735
|
+
goSearch(-1);
|
|
12736
|
+
},
|
|
12737
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 14 })
|
|
12738
|
+
}),
|
|
12739
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
12740
|
+
type: "button",
|
|
12741
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
|
|
12742
|
+
"data-diff-search-next": true,
|
|
12743
|
+
"aria-label": t("action.nextDiff"),
|
|
12744
|
+
disabled: searchMatches.length === 0,
|
|
12745
|
+
onClick: () => {
|
|
12746
|
+
goSearch(1);
|
|
12747
|
+
},
|
|
12748
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })
|
|
12749
|
+
}),
|
|
12750
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
12751
|
+
type: "button",
|
|
12752
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
|
|
12753
|
+
"data-diff-search-close": true,
|
|
12754
|
+
"aria-label": t("action.close"),
|
|
12755
|
+
onClick: closeSearch,
|
|
12756
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseOutline16, { size: 14 })
|
|
12757
|
+
})
|
|
12758
|
+
]
|
|
12759
|
+
}),
|
|
12760
|
+
focusedBlock !== void 0 && flashKey > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
12761
|
+
className: PendingPanel_module_css_default.blockFlash,
|
|
12762
|
+
"data-diff-block-flash": true,
|
|
12763
|
+
style: {
|
|
12764
|
+
top: flashTop,
|
|
12765
|
+
height: flashHeight
|
|
12766
|
+
}
|
|
12767
|
+
}, flashKey),
|
|
12768
|
+
hoveredBlock !== void 0 && blockOfPair[hoveredBlock] !== void 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
12769
|
+
className: PendingPanel_module_css_default.blockActions,
|
|
12770
|
+
"data-diff-block-actions": true,
|
|
12771
|
+
style: { top: blockActionsTop },
|
|
12772
|
+
children: [
|
|
12773
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
12774
|
+
className: PendingPanel_module_css_default.blockPosition,
|
|
12775
|
+
"data-diff-block-position": true,
|
|
12776
|
+
children: t("panel.blockPosition", {
|
|
12777
|
+
current: hoveredBlock + 1,
|
|
12778
|
+
total: blockOfPair.length
|
|
12779
|
+
})
|
|
12780
|
+
}),
|
|
12781
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
12782
|
+
type: "button",
|
|
12783
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
|
|
12784
|
+
"data-diff-block-prev": true,
|
|
12785
|
+
"aria-label": t("action.prevDiff"),
|
|
12786
|
+
disabled: busy,
|
|
12787
|
+
onClick: () => jump(-1),
|
|
12788
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 14 })
|
|
12789
|
+
}),
|
|
12790
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
12791
|
+
type: "button",
|
|
12792
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
|
|
12793
|
+
"data-diff-block-next": true,
|
|
12794
|
+
"aria-label": t("action.nextDiff"),
|
|
12795
|
+
disabled: busy,
|
|
12796
|
+
onClick: () => jump(1),
|
|
12797
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })
|
|
12798
|
+
}),
|
|
12799
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
12800
|
+
type: "button",
|
|
12801
|
+
className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary}`,
|
|
12802
|
+
"data-diff-block-keep": true,
|
|
12803
|
+
disabled: busy,
|
|
12804
|
+
onClick: () => {
|
|
12805
|
+
handleBlockAction("keep");
|
|
12806
|
+
},
|
|
12807
|
+
children: t("action.keep")
|
|
12808
|
+
}),
|
|
12809
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
12810
|
+
type: "button",
|
|
12811
|
+
className: `${PendingPanel_module_css_default.action}`,
|
|
12812
|
+
"data-diff-block-revert": true,
|
|
12813
|
+
disabled: busy,
|
|
12814
|
+
onClick: () => {
|
|
12815
|
+
handleBlockAction("revert");
|
|
12816
|
+
},
|
|
12817
|
+
children: t("action.revert")
|
|
12818
|
+
})
|
|
12819
|
+
]
|
|
12820
|
+
})
|
|
12821
|
+
]
|
|
12822
|
+
});
|
|
12823
|
+
});
|
|
12158
12824
|
/** The diff-row index containing a node, or undefined. */
|
|
12159
12825
|
function rowIndexAt(node) {
|
|
12160
12826
|
if (node === null) return void 0;
|
|
@@ -12163,6 +12829,43 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12163
12829
|
const index = Number(row.dataset.diffRow);
|
|
12164
12830
|
return Number.isFinite(index) ? index : void 0;
|
|
12165
12831
|
}
|
|
12832
|
+
/** The split pair index and which side (left=old, right=new) a node sits in, or undefined. */
|
|
12833
|
+
function splitRowInfoAt(node) {
|
|
12834
|
+
if (node === null) return void 0;
|
|
12835
|
+
const row = (node instanceof Element ? node : node.parentElement)?.closest("[data-diff-split-row]");
|
|
12836
|
+
if (row === null || row === void 0) return void 0;
|
|
12837
|
+
const side = row.dataset.diffSplitSide;
|
|
12838
|
+
if (side !== "left" && side !== "right") return void 0;
|
|
12839
|
+
const index = Number(row.dataset.diffSplitIndex);
|
|
12840
|
+
if (!Number.isFinite(index)) return void 0;
|
|
12841
|
+
return {
|
|
12842
|
+
pairIndex: index,
|
|
12843
|
+
side: side === "left" ? "old" : "new"
|
|
12844
|
+
};
|
|
12845
|
+
}
|
|
12846
|
+
/**
|
|
12847
|
+
* Derive the selected split pair range per side (a left-column selection
|
|
12848
|
+
* references the old file, a right-column selection the new file). A selection
|
|
12849
|
+
* spanning the divider (both sides) references two files, so it is rejected.
|
|
12850
|
+
*/
|
|
12851
|
+
function splitRowRangeOf(selection) {
|
|
12852
|
+
if (selection === null || selection.isCollapsed || selection.rangeCount === 0) return void 0;
|
|
12853
|
+
const range = selection.getRangeAt(0);
|
|
12854
|
+
const startInfo = splitRowInfoAt(range.startContainer);
|
|
12855
|
+
const endInfo = splitRowInfoAt(range.endContainer);
|
|
12856
|
+
if (startInfo === void 0 || endInfo === void 0) return void 0;
|
|
12857
|
+
if (startInfo.side !== endInfo.side) return void 0;
|
|
12858
|
+
let start = startInfo.pairIndex;
|
|
12859
|
+
let end = endInfo.pairIndex;
|
|
12860
|
+
if (lineOffsetAt(range.startContainer, range.startOffset) >= lineLengthAt(range.startContainer)) start += 1;
|
|
12861
|
+
if (lineOffsetAt(range.endContainer, range.endOffset) === 0) end -= 1;
|
|
12862
|
+
if (start > end) return void 0;
|
|
12863
|
+
return {
|
|
12864
|
+
start,
|
|
12865
|
+
end,
|
|
12866
|
+
side: startInfo.side
|
|
12867
|
+
};
|
|
12868
|
+
}
|
|
12166
12869
|
/** Character offset of a selection boundary within its line's code text. */
|
|
12167
12870
|
function lineOffsetAt(node, offset) {
|
|
12168
12871
|
const code = (node instanceof Element ? node : node.parentElement)?.closest("[data-diff-code]");
|
|
@@ -12288,6 +12991,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12288
12991
|
setWrapEnabled(wrapKey, next);
|
|
12289
12992
|
};
|
|
12290
12993
|
const [tabWidthSpaces] = (0, react.useState)(() => tabWidth());
|
|
12994
|
+
const splitView = splitMode();
|
|
12995
|
+
const splitDiffRef = (0, react.useRef)(null);
|
|
12291
12996
|
const model = (0, react.useMemo)(() => {
|
|
12292
12997
|
const diff = computeWholeFileDiff(file.oldText, file.newText);
|
|
12293
12998
|
return {
|
|
@@ -12295,6 +13000,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12295
13000
|
blocks: changeBlocksOf(diff)
|
|
12296
13001
|
};
|
|
12297
13002
|
}, [file.oldText, file.newText]);
|
|
13003
|
+
const splitPairs = (0, react.useMemo)(() => splitView ? computeSideBySideDiff(model.diff.rows).pairs : null, [splitView, model]);
|
|
12298
13004
|
const rulerMarkers = (0, react.useMemo)(() => {
|
|
12299
13005
|
const rows = model.diff.rows;
|
|
12300
13006
|
const total = rows.length;
|
|
@@ -12554,6 +13260,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12554
13260
|
setScrollTick((tick) => tick + 1);
|
|
12555
13261
|
setFlashKey((key) => key + 1);
|
|
12556
13262
|
};
|
|
13263
|
+
const jumpBlock = (direction) => {
|
|
13264
|
+
if (splitView) {
|
|
13265
|
+
splitDiffRef.current?.jump(direction);
|
|
13266
|
+
return;
|
|
13267
|
+
}
|
|
13268
|
+
jump(direction);
|
|
13269
|
+
};
|
|
13270
|
+
const jumpBlockRef = (0, react.useRef)(jumpBlock);
|
|
13271
|
+
jumpBlockRef.current = jumpBlock;
|
|
12557
13272
|
const stepBlock = (direction) => {
|
|
12558
13273
|
const count = model.blocks.length;
|
|
12559
13274
|
if (count === 0) return;
|
|
@@ -12563,9 +13278,22 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12563
13278
|
setScrollTick((tick) => tick + 1);
|
|
12564
13279
|
setFlashKey((key) => key + 1);
|
|
12565
13280
|
};
|
|
13281
|
+
const handleBlockAction = async (action) => {
|
|
13282
|
+
if (busy || hoveredBlock === void 0) return;
|
|
13283
|
+
const operated = hoveredBlock;
|
|
13284
|
+
const range = blockRanges[operated];
|
|
13285
|
+
await (action === "keep" ? onBlockKeep(file.sessionId, file.id, range) : onBlockRevert(file.sessionId, file.id, range));
|
|
13286
|
+
const count = model.blocks.length;
|
|
13287
|
+
if (count === 0) return;
|
|
13288
|
+
const next = Math.max(0, Math.min(operated, count - 1));
|
|
13289
|
+
setFocus(next);
|
|
13290
|
+
setHoveredBlock(void 0);
|
|
13291
|
+
setScrollTick((tick) => tick + 1);
|
|
13292
|
+
setFlashKey((key) => key + 1);
|
|
13293
|
+
};
|
|
12566
13294
|
(0, react.useEffect)(() => {
|
|
12567
13295
|
if (jumpSignal === 0) return;
|
|
12568
|
-
|
|
13296
|
+
jumpBlock(1);
|
|
12569
13297
|
}, [jumpSignal]);
|
|
12570
13298
|
const onScroll = () => {
|
|
12571
13299
|
const body = bodyRef.current;
|
|
@@ -12574,15 +13302,27 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12574
13302
|
setViewportHeight(body.clientHeight);
|
|
12575
13303
|
};
|
|
12576
13304
|
(0, react.useEffect)(() => {
|
|
12577
|
-
const update = () => setSelection(rowRangeOf(window.getSelection()));
|
|
13305
|
+
const update = () => setSelection(splitView ? splitRowRangeOf(window.getSelection()) : rowRangeOf(window.getSelection()));
|
|
12578
13306
|
document.addEventListener("selectionchange", update);
|
|
12579
13307
|
update();
|
|
12580
13308
|
return () => {
|
|
12581
13309
|
document.removeEventListener("selectionchange", update);
|
|
12582
13310
|
};
|
|
12583
|
-
}, [file.id]);
|
|
13311
|
+
}, [file.id, splitView]);
|
|
12584
13312
|
const selectionReference = (() => {
|
|
12585
13313
|
if (selection === void 0) return void 0;
|
|
13314
|
+
if (splitView) {
|
|
13315
|
+
if (selection.side === void 0 || splitPairs === null) return void 0;
|
|
13316
|
+
const lineNumbers = [];
|
|
13317
|
+
for (let index = selection.start; index <= selection.end; index++) {
|
|
13318
|
+
const pair = splitPairs[index];
|
|
13319
|
+
if (pair === void 0) continue;
|
|
13320
|
+
const line = selection.side === "old" ? pair.left?.line : pair.right?.line;
|
|
13321
|
+
if (line !== void 0) lineNumbers.push(line);
|
|
13322
|
+
}
|
|
13323
|
+
if (lineNumbers.length === 0) return void 0;
|
|
13324
|
+
return referenceOf(file.path, workspacePath, Math.min(...lineNumbers), Math.max(...lineNumbers));
|
|
13325
|
+
}
|
|
12586
13326
|
const lineNumbers = model.diff.rows.slice(selection.start, selection.end + 1).map((row) => row.newLine).filter((number) => number !== void 0);
|
|
12587
13327
|
if (lineNumbers.length === 0) return void 0;
|
|
12588
13328
|
return referenceOf(file.path, workspacePath, Math.min(...lineNumbers), Math.max(...lineNumbers));
|
|
@@ -12618,6 +13358,10 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12618
13358
|
if (!(event.ctrlKey || event.metaKey) || event.altKey || event.shiftKey) return;
|
|
12619
13359
|
if (event.key.toLowerCase() !== "f") return;
|
|
12620
13360
|
event.preventDefault();
|
|
13361
|
+
if (splitView) {
|
|
13362
|
+
splitDiffRef.current?.openSearch();
|
|
13363
|
+
return;
|
|
13364
|
+
}
|
|
12621
13365
|
setSearchOpen(true);
|
|
12622
13366
|
searchInputRef.current?.focus();
|
|
12623
13367
|
searchInputRef.current?.select();
|
|
@@ -12627,8 +13371,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12627
13371
|
window.removeEventListener("keydown", onKeyDown, true);
|
|
12628
13372
|
};
|
|
12629
13373
|
}, []);
|
|
12630
|
-
const jumpRef = (0, react.useRef)(
|
|
12631
|
-
jumpRef.current =
|
|
13374
|
+
const jumpRef = (0, react.useRef)(jumpBlock);
|
|
13375
|
+
jumpRef.current = jumpBlock;
|
|
12632
13376
|
(0, react.useEffect)(() => {
|
|
12633
13377
|
const onKeyDown = (event) => {
|
|
12634
13378
|
if (!(event.ctrlKey || event.metaKey) || event.altKey || event.shiftKey) return;
|
|
@@ -12736,7 +13480,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12736
13480
|
"aria-label": t("action.prevDiff"),
|
|
12737
13481
|
disabled: busy,
|
|
12738
13482
|
onClick: () => {
|
|
12739
|
-
|
|
13483
|
+
jumpBlock(-1);
|
|
12740
13484
|
},
|
|
12741
13485
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 14 })
|
|
12742
13486
|
})
|
|
@@ -12751,7 +13495,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12751
13495
|
"aria-label": t("action.nextDiff"),
|
|
12752
13496
|
disabled: busy,
|
|
12753
13497
|
onClick: () => {
|
|
12754
|
-
|
|
13498
|
+
jumpBlock(1);
|
|
12755
13499
|
},
|
|
12756
13500
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })
|
|
12757
13501
|
})
|
|
@@ -12801,7 +13545,18 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12801
13545
|
className: PendingPanel_module_css_default.missingHint,
|
|
12802
13546
|
children: t("panel.missingHint")
|
|
12803
13547
|
}),
|
|
12804
|
-
(0, react_jsx_runtime.
|
|
13548
|
+
splitView ? (0, react_jsx_runtime.jsx)(SplitDiff, {
|
|
13549
|
+
ref: splitDiffRef,
|
|
13550
|
+
file,
|
|
13551
|
+
model,
|
|
13552
|
+
runs,
|
|
13553
|
+
langWrap,
|
|
13554
|
+
tabWidthSpaces,
|
|
13555
|
+
busy,
|
|
13556
|
+
t,
|
|
13557
|
+
onBlockKeep,
|
|
13558
|
+
onBlockRevert
|
|
13559
|
+
}) : (0, react_jsx_runtime.jsxs)("div", {
|
|
12805
13560
|
className: PendingPanel_module_css_default.diffBodyWrap,
|
|
12806
13561
|
children: [
|
|
12807
13562
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -12886,7 +13641,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12886
13641
|
"data-diff-block-keep": true,
|
|
12887
13642
|
disabled: busy,
|
|
12888
13643
|
onClick: () => {
|
|
12889
|
-
|
|
13644
|
+
handleBlockAction("keep");
|
|
12890
13645
|
},
|
|
12891
13646
|
children: t("action.keep")
|
|
12892
13647
|
}),
|
|
@@ -12896,7 +13651,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
12896
13651
|
"data-diff-block-revert": true,
|
|
12897
13652
|
disabled: busy,
|
|
12898
13653
|
onClick: () => {
|
|
12899
|
-
|
|
13654
|
+
handleBlockAction("revert");
|
|
12900
13655
|
},
|
|
12901
13656
|
children: t("action.revert")
|
|
12902
13657
|
})
|
|
@@ -13733,6 +14488,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13733
14488
|
const [includeUntrackedOpen, setIncludeUntrackedOpen] = (0, react.useState)(false);
|
|
13734
14489
|
const [tab, setTabState] = (0, react.useState)(tabWidth);
|
|
13735
14490
|
const [tabOpen, setTabOpen] = (0, react.useState)(false);
|
|
14491
|
+
const [split, setSplitState] = (0, react.useState)(splitMode);
|
|
14492
|
+
const [splitOpen, setSplitOpen] = (0, react.useState)(false);
|
|
13736
14493
|
const setPasteOnCopy = (value) => {
|
|
13737
14494
|
setPasteOnCopyState(value);
|
|
13738
14495
|
setPasteOnCopyEnabled(value);
|
|
@@ -13745,6 +14502,10 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13745
14502
|
setTabState(value);
|
|
13746
14503
|
setTabWidth(value);
|
|
13747
14504
|
};
|
|
14505
|
+
const setSplit = (value) => {
|
|
14506
|
+
setSplitState(value);
|
|
14507
|
+
setSplitMode(value);
|
|
14508
|
+
};
|
|
13748
14509
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
13749
14510
|
className: PendingPanel_module_css_default.settingsPage,
|
|
13750
14511
|
"data-diff-settings": true,
|
|
@@ -13777,6 +14538,16 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
13777
14538
|
onOpenChange: setTabOpen,
|
|
13778
14539
|
onSelect: setTab,
|
|
13779
14540
|
dataAttribute: "data-diff-tab-width-select"
|
|
14541
|
+
}),
|
|
14542
|
+
(0, react_jsx_runtime.jsx)(PreferenceRow, {
|
|
14543
|
+
title: t("panel.splitMode"),
|
|
14544
|
+
description: t("panel.splitModeDesc"),
|
|
14545
|
+
value: split,
|
|
14546
|
+
open: splitOpen,
|
|
14547
|
+
onOpenChange: setSplitOpen,
|
|
14548
|
+
onSelect: setSplit,
|
|
14549
|
+
dataAttribute: "data-diff-split-mode-select",
|
|
14550
|
+
t
|
|
13780
14551
|
})
|
|
13781
14552
|
]
|
|
13782
14553
|
});
|
|
@@ -14175,8 +14946,10 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
14175
14946
|
"panel.pasteOnCopyDesc": "开启后,复制的引用会自动填入消息输入框,输入框会获得焦点。",
|
|
14176
14947
|
"panel.importUntracked": "导入未跟踪的文件改动",
|
|
14177
14948
|
"panel.importUntrackedDesc": "开启后,导入工作区改动会包含未跟踪/未版本化的新增文件(Git 未跟踪、SVN 未版本化、Perforce 未版本化)。收集改动需要扫描整个工作区,文件数量大时可能较慢。",
|
|
14178
|
-
"panel.tabWidth": "
|
|
14179
|
-
"panel.tabWidthDesc": "
|
|
14949
|
+
"panel.tabWidth": "制表符宽度",
|
|
14950
|
+
"panel.tabWidthDesc": "差异中制表符的缩进宽度,可选 2 / 4 / 8 个空格(默认 4),同时作用于行宽折行测量。",
|
|
14951
|
+
"panel.splitMode": "双栏对比",
|
|
14952
|
+
"panel.splitModeDesc": "开启后整文件差异用左「改前」|右「当前」双栏、逐行对齐的视图展示,默认关闭使用单栏(合并)视图。",
|
|
14180
14953
|
"settings.tabLabel": "改动审批",
|
|
14181
14954
|
"row.create": "新增文件",
|
|
14182
14955
|
"row.failed": "失败",
|
|
@@ -14239,7 +15012,9 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
|
|
|
14239
15012
|
"panel.importUntracked": "Import changes to untracked files",
|
|
14240
15013
|
"panel.importUntrackedDesc": "When enabled, importing workspace changes includes new/untracked files (Git-untracked, SVN-unversioned, Perforce-unversioned). Collecting changes scans the whole workspace, which can be slow on large trees.",
|
|
14241
15014
|
"panel.tabWidth": "Tab width",
|
|
14242
|
-
"panel.tabWidthDesc": "The indent width of a tab character in the
|
|
15015
|
+
"panel.tabWidthDesc": "The indent width of a tab character in the differences, as 2 / 4 / 8 spaces (default 4). Also drives the wrapped-line measurement.",
|
|
15016
|
+
"panel.splitMode": "Side-by-side view",
|
|
15017
|
+
"panel.splitModeDesc": "When on, the whole-file differences render as a side-by-side (left \"before\" | right \"current\") line-aligned view. Off (default) uses the single-column unified view.",
|
|
14243
15018
|
"settings.tabLabel": "Diff Approval",
|
|
14244
15019
|
"row.create": "New file",
|
|
14245
15020
|
"row.failed": "Failed",
|