dsh-diff-approval 0.14.1 → 0.15.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
@@ -535,7 +535,10 @@ window.__ModuleLoader__.load({
535
535
  return value;
536
536
  }
537
537
  };
538
- new ArrayDiff();
538
+ const arrayDiff = new ArrayDiff();
539
+ function diffArrays(oldArr, newArr, options) {
540
+ return arrayDiff.diff(oldArr, newArr, options);
541
+ }
539
542
  //#endregion
540
543
  //#region node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/patch/create.js
541
544
  function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
@@ -722,6 +725,246 @@ window.__ModuleLoader__.load({
722
725
  added
723
726
  };
724
727
  }
728
+ /** Minimum similarity for a del/add pair to receive an intra-line diff. */
729
+ const INTRA_SIMILARITY_THRESHOLD = .4;
730
+ /** Lines longer than this are skipped (a single pathological line would make the
731
+ * token-diff O(n²) and only ever show a noise floor). Mirrors the highlighting
732
+ * cap so a review stays bounded. */
733
+ const INTRA_MAX_LINE_LENGTH = 2e3;
734
+ /** A similarity-alignment block larger than this many cell-and-compare pairs
735
+ * falls back to by-order pairing: the O(n·m) scan and DP would stall on a
736
+ * whole-file rewrite for no benefit. */
737
+ const INTRA_MAX_ALIGN_CELLS = 8192;
738
+ const WORD_CHAR_RE = /[\p{L}\p{N}_]/u;
739
+ /** CJK characters — Chinese han, Japanese kana, CJK fullwidth forms. Each is an
740
+ * independent unit (there is no whitespace word boundary), so one token each. */
741
+ function isCJKCode$1(cp) {
742
+ return cp >= 12352 && cp <= 12543 || cp >= 13312 && cp <= 19903 || cp >= 19968 && cp <= 40959 || cp >= 63744 && cp <= 64255 || cp >= 65072 && cp <= 65103 || cp >= 65280 && cp <= 65519 || cp >= 131072 && cp <= 195103;
743
+ }
744
+ /** Space, tab, or the ideographic space — whitespace is a break opportunity. */
745
+ function isSpaceCode$1(cp) {
746
+ return cp === 32 || cp === 9 || cp === 12288;
747
+ }
748
+ /**
749
+ * Tokenize a line for an intra-line diff, into a lossless array of tokens whose
750
+ * concatenation equals the input. Word-based for space-delimited scripts: a
751
+ * maximal run of letters/numbers/underscore (any script except CJK) is one
752
+ * token, so a whole edited word stays a single run instead of per-character.
753
+ * Each CJK character is its own token (there is no word boundary), as is each
754
+ * punctuation/symbol character (a run of different punctuation carries no
755
+ * meaning, so it diffs atomically), while a maximal whitespace run stays one
756
+ * token as a natural break. This yields clean word-level highlights for English
757
+ * and per-character precision for CJK and punctuation.
758
+ * @param text - the line's content.
759
+ * @returns the tokens.
760
+ */
761
+ function tokenizeLine(text) {
762
+ const tokens = [];
763
+ let cur = "";
764
+ let runKind;
765
+ const flush = () => {
766
+ if (cur !== "") {
767
+ tokens.push(cur);
768
+ cur = "";
769
+ }
770
+ };
771
+ for (const ch of text) {
772
+ const cp = ch.codePointAt(0) ?? 0;
773
+ const word = WORD_CHAR_RE.test(ch);
774
+ if (isCJKCode$1(cp) || !word && !isSpaceCode$1(cp)) {
775
+ flush();
776
+ runKind = void 0;
777
+ tokens.push(ch);
778
+ continue;
779
+ }
780
+ const kind = word ? "word" : "space";
781
+ if (kind !== runKind) {
782
+ flush();
783
+ runKind = kind;
784
+ }
785
+ cur += ch;
786
+ }
787
+ flush();
788
+ return tokens;
789
+ }
790
+ /**
791
+ * Raw similarity of a del/add line pair in `[0, 1]`, or `-1` when the pair
792
+ * cannot be meaningfully compared (identical lines, either side empty, or over
793
+ * the length cap). Used both by the intra-line gate and by the similarity
794
+ * alignment, so the two always agree on what counts as "changed".
795
+ * @param oldText - the removed side's line text.
796
+ * @param newText - the added side's line text.
797
+ * @returns the similarity ratio, or `-1` when incomparable.
798
+ */
799
+ function lineSimilarity(oldText, newText) {
800
+ if (oldText === newText || oldText === "" || newText === "") return -1;
801
+ if (oldText.length > INTRA_MAX_LINE_LENGTH || newText.length > INTRA_MAX_LINE_LENGTH) return -1;
802
+ return 2 * diffArrays(tokenizeLine(oldText), tokenizeLine(newText)).reduce((sum, change) => change.removed || change.added ? sum : sum + change.value.join("").length, 0) / (oldText.length + newText.length);
803
+ }
804
+ /**
805
+ * Compute the intra-line runs for one del/add line pair, or `undefined` when
806
+ * the pair should not be annotated: identical lines (no internal change) or
807
+ * lines too dissimilar to be a modification (a rewrite, not an edit).
808
+ * Word-based via the `diff` package's `diffArrays` over `tokenizeLine`'s
809
+ * tokens, so an English edit highlights whole changed words and a CJK edit
810
+ * highlights the individual changed characters.
811
+ * @param oldText - the removed side's line text.
812
+ * @param newText - the added side's line text.
813
+ * @returns the del-side and add-side runs, or `undefined` to skip annotation.
814
+ */
815
+ function intraRunsOf(oldText, newText) {
816
+ if (lineSimilarity(oldText, newText) < INTRA_SIMILARITY_THRESHOLD) return void 0;
817
+ const changes = diffArrays(tokenizeLine(oldText), tokenizeLine(newText));
818
+ const del = [];
819
+ const add = [];
820
+ for (const change of changes) {
821
+ const text = change.value.join("");
822
+ if (change.removed) del.push({
823
+ text,
824
+ kind: "del"
825
+ });
826
+ else if (change.added) add.push({
827
+ text,
828
+ kind: "add"
829
+ });
830
+ else {
831
+ del.push({
832
+ text,
833
+ kind: "same"
834
+ });
835
+ add.push({
836
+ text,
837
+ kind: "same"
838
+ });
839
+ }
840
+ }
841
+ if (!del.some((run) => run.kind === "del") && !add.some((run) => run.kind === "add")) return void 0;
842
+ return {
843
+ del,
844
+ add
845
+ };
846
+ }
847
+ /**
848
+ * Align a del run with the following add run. By order (the baseline) pairs
849
+ * `del[i]`↔`add[i]`. With similarity alignment, an order-preserving best match
850
+ * pairs each del with the add that maximises total similarity, keeping a pair
851
+ * only when it clears the similarity threshold — so a lone insert or delete in
852
+ * a mixed block stays unaligned instead of being forced onto a wrong line.
853
+ * @param delRows - the run's del rows (index + text).
854
+ * @param addRows - the run's add rows (index + text).
855
+ * @param alignBySimilarity - whether to use the similarity-based matching.
856
+ * @returns the aligned pairs and the unmatched sides.
857
+ */
858
+ function alignChangedBlock(delRows, addRows, alignBySimilarity) {
859
+ const byOrder = () => {
860
+ const min = Math.min(delRows.length, addRows.length);
861
+ const pairs = [];
862
+ for (let i = 0; i < min; i++) pairs.push({
863
+ delIndex: delRows[i].index,
864
+ addIndex: addRows[i].index
865
+ });
866
+ return {
867
+ pairs,
868
+ delOnly: delRows.slice(min).map((row) => row.index),
869
+ addOnly: addRows.slice(min).map((row) => row.index),
870
+ usedSimilarity: false
871
+ };
872
+ };
873
+ if (!alignBySimilarity) return byOrder();
874
+ const n = delRows.length;
875
+ const m = addRows.length;
876
+ if (n * m > INTRA_MAX_ALIGN_CELLS) return byOrder();
877
+ const sim = [];
878
+ for (let i = 0; i < n; i++) {
879
+ const row = [];
880
+ for (let j = 0; j < m; j++) row.push(lineSimilarity(delRows[i].text, addRows[j].text));
881
+ sim.push(row);
882
+ }
883
+ const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
884
+ for (let i = 1; i <= n; i++) for (let j = 1; j <= m; j++) {
885
+ const skipDel = dp[i - 1][j];
886
+ const skipAdd = dp[i][j - 1];
887
+ const s = sim[i - 1][j - 1];
888
+ const pair = s >= INTRA_SIMILARITY_THRESHOLD ? dp[i - 1][j - 1] + s : Number.NEGATIVE_INFINITY;
889
+ dp[i][j] = Math.max(skipDel, skipAdd, pair);
890
+ }
891
+ const pairs = [];
892
+ const delOnly = [];
893
+ const addOnly = [];
894
+ let i = n;
895
+ let j = m;
896
+ while (i > 0 || j > 0) {
897
+ const s = i > 0 && j > 0 ? sim[i - 1][j - 1] : Number.NEGATIVE_INFINITY;
898
+ if (i > 0 && j > 0 && s >= INTRA_SIMILARITY_THRESHOLD && dp[i][j] === dp[i - 1][j - 1] + s) {
899
+ pairs.push({
900
+ delIndex: delRows[i - 1].index,
901
+ addIndex: addRows[j - 1].index
902
+ });
903
+ i--;
904
+ j--;
905
+ } else if (i > 0 && dp[i][j] === dp[i - 1][j]) {
906
+ delOnly.push(delRows[i - 1].index);
907
+ i--;
908
+ } else if (j > 0) {
909
+ addOnly.push(addRows[j - 1].index);
910
+ j--;
911
+ } else break;
912
+ }
913
+ pairs.reverse();
914
+ delOnly.reverse();
915
+ addOnly.reverse();
916
+ return {
917
+ pairs,
918
+ delOnly,
919
+ addOnly,
920
+ usedSimilarity: true
921
+ };
922
+ }
923
+ /**
924
+ * Derive intra-line runs for a whole-file row list. Each del/add block is
925
+ * aligned (by order, or by similarity when `alignBySimilarity`), and each
926
+ * matched pair is compared by `intraRunsOf`. Returns a map keyed by the row's
927
+ * index in `rows`, present only for rows that carry a highlight.
928
+ * @param rows - the unified `WholeFileDiff` row list.
929
+ * @param alignBySimilarity - align blocks by similarity instead of by order.
930
+ * @returns per-row-index intra-line runs for annotated del/add rows.
931
+ */
932
+ function computeIntraLineDiff(rows, alignBySimilarity = false) {
933
+ const result = /* @__PURE__ */ new Map();
934
+ let i = 0;
935
+ while (i < rows.length) {
936
+ if (rows[i].kind !== "del") {
937
+ i++;
938
+ continue;
939
+ }
940
+ const delIndices = [];
941
+ while (i < rows.length && rows[i].kind === "del") {
942
+ delIndices.push(i);
943
+ i++;
944
+ }
945
+ const addIndices = [];
946
+ while (i < rows.length && rows[i].kind === "add") {
947
+ addIndices.push(i);
948
+ i++;
949
+ }
950
+ const alignment = alignChangedBlock(delIndices.map((index) => ({
951
+ index,
952
+ text: rows[index].text
953
+ })), addIndices.map((index) => ({
954
+ index,
955
+ text: rows[index].text
956
+ })), alignBySimilarity);
957
+ if (alignBySimilarity && !alignment.usedSimilarity) continue;
958
+ for (const pair of alignment.pairs) {
959
+ const intra = intraRunsOf(rows[pair.delIndex].text, rows[pair.addIndex].text);
960
+ if (intra !== void 0) {
961
+ result.set(pair.delIndex, intra.del);
962
+ result.set(pair.addIndex, intra.add);
963
+ }
964
+ }
965
+ }
966
+ return result;
967
+ }
725
968
  /**
726
969
  * Split a side's text into its content lines, with the diff card's terminator
727
970
  * rule: empty text is zero lines, and a single trailing newline is a line
@@ -761,57 +1004,78 @@ window.__ModuleLoader__.load({
761
1004
  };
762
1005
  }
763
1006
  /**
764
- * Regroup the whole-file rows into aligned split pairs, pairing a deletion run
765
- * with a following addition run line-by-line (so a replaced line is one pair),
766
- * and leaving a stray deletion or addition as a one-sided pair.
1007
+ * Regroup the whole-file rows into aligned split pairs. By order, a deletion
1008
+ * run pairs line-by-line with a following addition run; with similarity
1009
+ * alignment, each deletion pairs with its most-similar addition (order
1010
+ * preserved, threshold-bounded) so a mixed insert/delete block does not force a
1011
+ * wrong line together. A stray deletion or addition stays a one-sided pair.
767
1012
  * @param rows - the whole-file diff rows.
1013
+ * @param alignBySimilarity - align a change block by similarity instead of order.
768
1014
  * @returns the split pairs plus the row→pair index map.
769
1015
  */
770
- function computeSideBySideDiff(rows) {
1016
+ function computeSideBySideDiff(rows, alignBySimilarity = false) {
771
1017
  const pairs = [];
772
1018
  const pairOfRow = /* @__PURE__ */ new Map();
773
- const pendingDel = [];
774
- const push = (pair, rows) => {
1019
+ const push = (pair, pairRows) => {
775
1020
  const index = pairs.length;
776
1021
  pairs.push(pair);
777
- for (const r of rows) pairOfRow.set(r, index);
778
- };
779
- const flushPending = () => {
780
- for (const { index, row } of pendingDel) push({
781
- kind: "del",
782
- left: leftSideOf(row),
783
- right: void 0
784
- }, [index]);
785
- pendingDel.length = 0;
1022
+ for (const r of pairRows) pairOfRow.set(r, index);
786
1023
  };
787
- for (let i = 0; i < rows.length; i++) {
1024
+ let i = 0;
1025
+ while (i < rows.length) {
788
1026
  const row = rows[i];
789
1027
  if (row.kind === "context") {
790
- flushPending();
791
1028
  push({
792
1029
  kind: "context",
793
1030
  left: leftSideOf(row),
794
1031
  right: rightSideOf(row)
795
1032
  }, [i]);
796
- } else if (row.kind === "del") pendingDel.push({
797
- index: i,
798
- row
799
- });
800
- else {
801
- const del = pendingDel.shift();
802
- if (del !== void 0) push({
1033
+ i++;
1034
+ continue;
1035
+ }
1036
+ const delRows = [];
1037
+ const addRows = [];
1038
+ if (row.kind === "del") while (i < rows.length && rows[i].kind === "del") {
1039
+ delRows.push({
1040
+ index: i,
1041
+ row: rows[i]
1042
+ });
1043
+ i++;
1044
+ }
1045
+ while (i < rows.length && rows[i].kind === "add") {
1046
+ addRows.push({
1047
+ index: i,
1048
+ row: rows[i]
1049
+ });
1050
+ i++;
1051
+ }
1052
+ const alignment = alignChangedBlock(delRows.map((d) => ({
1053
+ index: d.index,
1054
+ text: d.row.text
1055
+ })), addRows.map((a) => ({
1056
+ index: a.index,
1057
+ text: a.row.text
1058
+ })), alignBySimilarity);
1059
+ for (const p of alignment.pairs) {
1060
+ const del = delRows.find((d) => d.index === p.delIndex);
1061
+ const add = addRows.find((a) => a.index === p.addIndex);
1062
+ push({
803
1063
  kind: "replace",
804
1064
  left: leftSideOf(del.row),
805
- right: rightSideOf(row)
806
- }, [del.index, i]);
807
- else push({
808
- kind: "add",
809
- left: void 0,
810
- right: rightSideOf(row)
811
- }, [i]);
1065
+ right: rightSideOf(add.row)
1066
+ }, [p.delIndex, p.addIndex]);
812
1067
  }
1068
+ for (const d of alignment.delOnly) push({
1069
+ kind: "del",
1070
+ left: leftSideOf(delRows.find((x) => x.index === d).row),
1071
+ right: void 0
1072
+ }, [d]);
1073
+ for (const a of alignment.addOnly) push({
1074
+ kind: "add",
1075
+ left: void 0,
1076
+ right: rightSideOf(addRows.find((x) => x.index === a).row)
1077
+ }, [a]);
813
1078
  }
814
- flushPending();
815
1079
  return {
816
1080
  pairs,
817
1081
  pairOfRow
@@ -11833,6 +12097,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
11833
12097
  const IMPORT_UNTRACKED_KEY = "diff-approval:import-untracked";
11834
12098
  const TAB_WIDTH_KEY = "diff-approval:tab-size";
11835
12099
  const SPLIT_MODE_KEY = "diff-approval:split-mode";
12100
+ const NAV_LEAD_KEY = "diff-approval:nav-lead-rows";
11836
12101
  const WRAP_PREFIX = "diff-approval:wrap:";
11837
12102
  /**
11838
12103
  * Whether copying a reference should also paste it into the chat input and
@@ -11901,6 +12166,21 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
11901
12166
  function setSplitMode(value) {
11902
12167
  localStorage.setItem(SPLIT_MODE_KEY, value ? "1" : "0");
11903
12168
  }
12169
+ /**
12170
+ * How many rows of lead the diff block jump leaves above the jumped-to block,
12171
+ * and how far the anchored navigation scans. Defaults to 2; an out-of-range or
12172
+ * non-integer value falls back to the default.
12173
+ * @returns the lead row count.
12174
+ */
12175
+ function navLeadRows() {
12176
+ const raw = Number.parseInt(localStorage.getItem(NAV_LEAD_KEY) ?? "", 10);
12177
+ if (!Number.isInteger(raw)) return 2;
12178
+ return Math.max(0, Math.min(10, raw));
12179
+ }
12180
+ /** Persist the block-jump lead row count. */
12181
+ function setNavLeadRows(value) {
12182
+ localStorage.setItem(NAV_LEAD_KEY, String(Math.max(0, Math.min(10, value))));
12183
+ }
11904
12184
  const QUICK_SUMMON_KEY = "diff-approval:quick-summon-key";
11905
12185
  /**
11906
12186
  * The quick-summon chord. Stored as `Modifier+...+Key`; falls back to
@@ -11936,7 +12216,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
11936
12216
  }
11937
12217
  //#endregion
11938
12218
  //#region \0dsh-css:/home/runner/work/dsh-diff-approval/dsh-diff-approval/src/client/PendingPanel.module.css.mjs
11939
- 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_confirmBackdrop{z-index:5;background:color-mix(in srgb, var(--dsw-alias-bg-base) 55%, transparent);justify-content:center;align-items:center;padding:24px;display:flex;position:absolute;inset:0}.F1KBNa_confirmCard{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);max-width:340px;box-shadow:var(--dsw-shadow-lv3);border-radius:12px;flex-direction:column;gap:12px;padding:16px;display:flex}.F1KBNa_confirmText{font:var(--dsw-font-caption);color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;margin:0;line-height:1.5}.F1KBNa_confirmActions{justify-content:flex-end;gap:8px;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);-webkit-text-size-adjust:100%;text-size-adjust:100%;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{-webkit-user-select:none;user-select:none;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;-webkit-user-select:none;user-select:none;cursor:default;padding-right:10px;display:table-cell}.F1KBNa_code{white-space:pre;-webkit-user-select:text;user-select:text;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)}";
12219
+ 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_toggle{border:1px solid var(--dsw-alias-border-l2);cursor:pointer;background:0 0;border-radius:18px;flex:none;width:60px;height:36px;padding:0;position:relative}.F1KBNa_toggle:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_toggle:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.F1KBNa_toggleOn{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-state-business-primary)}.F1KBNa_toggleOn:hover{background:var(--dsw-alias-state-business-primary)}.F1KBNa_toggleThumb{background:var(--dsw-alias-label-primary);border-radius:50%;width:28px;height:28px;transition:left .12s;position:absolute;top:3px;left:3px}.F1KBNa_toggleOn .F1KBNa_toggleThumb{background:#fff;left:27px}.F1KBNa_stepper{align-items:center;gap:6px;display:inline-flex}.F1KBNa_stepperButton{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);width:32px;height:32px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:8px;font-size:16px;line-height:1}.F1KBNa_stepperButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_stepperButton:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.F1KBNa_stepperValue{text-align:center;min-width:2ch;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;font-size:14px;line-height:22px}.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_confirmBackdrop{z-index:5;background:color-mix(in srgb, var(--dsw-alias-bg-base) 55%, transparent);justify-content:center;align-items:center;padding:24px;display:flex;position:absolute;inset:0}.F1KBNa_confirmCard{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);max-width:340px;box-shadow:var(--dsw-shadow-lv3);border-radius:12px;flex-direction:column;gap:12px;padding:16px;display:flex}.F1KBNa_confirmText{font:var(--dsw-font-caption);color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;margin:0;line-height:1.5}.F1KBNa_confirmActions{justify-content:flex-end;gap:8px;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{white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary);font:var(--dsw-font-markdown-code-block);-webkit-user-select:text;user-select:text;flex:1;font-size:12px;line-height:18px;overflow:auto 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);-webkit-text-size-adjust:100%;text-size-adjust:100%;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{-webkit-user-select:none;user-select:none;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;-webkit-user-select:none;user-select:none;cursor:default;padding-right:10px;display:table-cell}.F1KBNa_code{white-space:pre;-webkit-user-select:text;user-select:text;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)}.F1KBNa_intraDel{background-color:color-mix(in srgb, var(--dsw-alias-state-error-primary) 26%, transparent);text-decoration:line-through}.F1KBNa_intraAdd{background-color:color-mix(in srgb, var(--dsw-alias-state-success-primary) 24%, transparent)}";
11940
12220
  const tagId = "dsh-diff-approval/PendingPanel.module.css";
11941
12221
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
11942
12222
  const tag = document.createElement("style");
@@ -11946,115 +12226,123 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
11946
12226
  document.head.appendChild(tag);
11947
12227
  }
11948
12228
  var PendingPanel_module_css_default = {
11949
- "confirmBackdrop": "F1KBNa_confirmBackdrop",
11950
- "kindHint": "F1KBNa_kindHint",
11951
- "splitRdel": "F1KBNa_splitRdel",
11952
- "missingHint": "F1KBNa_missingHint",
11953
- "expandExpanded": "F1KBNa_expandExpanded",
11954
- "readError": "F1KBNa_readError",
12229
+ "splitLadd": "F1KBNa_splitLadd",
12230
+ "badge": "F1KBNa_badge",
12231
+ "settingsRowTitle": "F1KBNa_settingsRowTitle",
12232
+ "code": "F1KBNa_code",
12233
+ "confirmCard": "F1KBNa_confirmCard",
12234
+ "title": "F1KBNa_title",
11955
12235
  "diffBody": "F1KBNa_diffBody",
11956
- "lines": "F1KBNa_lines",
11957
- "langLabel": "F1KBNa_langLabel",
11958
- "splitCol": "F1KBNa_splitCol",
11959
- "splitRadd": "F1KBNa_splitRadd",
11960
- "diffPath": "F1KBNa_diffPath",
11961
- "diffActions": "F1KBNa_diffActions",
11962
- "rowPath": "F1KBNa_rowPath",
11963
- "listScroll": "F1KBNa_listScroll",
12236
+ "diffFlash": "F1KBNa_diffFlash",
12237
+ "states": "F1KBNa_states",
12238
+ "actionQuietDisabled": "F1KBNa_actionQuietDisabled",
12239
+ "resizeHandle": "F1KBNa_resizeHandle",
12240
+ "addCount": "F1KBNa_addCount",
11964
12241
  "actionPrimary": "F1KBNa_actionPrimary",
12242
+ "splitHScrollFill": "F1KBNa_splitHScrollFill",
11965
12243
  "importButton": "F1KBNa_importButton",
11966
- "rows": "F1KBNa_rows",
11967
- "searchCount": "F1KBNa_searchCount",
11968
- "statusBar": "F1KBNa_statusBar",
11969
- "footerButtons": "F1KBNa_footerButtons",
11970
- "layer": "F1KBNa_layer",
11971
- "badgeLabel": "F1KBNa_badgeLabel",
12244
+ "splitDivider": "F1KBNa_splitDivider",
11972
12245
  "divergedHint": "F1KBNa_divergedHint",
12246
+ "close": "F1KBNa_close",
12247
+ "importNote": "F1KBNa_importNote",
12248
+ "langSelect": "F1KBNa_langSelect",
12249
+ "langLabel": "F1KBNa_langLabel",
12250
+ "vSpacer": "F1KBNa_vSpacer",
12251
+ "emptyState": "F1KBNa_emptyState",
12252
+ "blockFlash": "F1KBNa_blockFlash",
12253
+ "splitCol": "F1KBNa_splitCol",
12254
+ "rail": "F1KBNa_rail",
12255
+ "action": "F1KBNa_action",
12256
+ "group": "F1KBNa_group",
12257
+ "confirmBackdrop": "F1KBNa_confirmBackdrop",
12258
+ "listScroll": "F1KBNa_listScroll",
12259
+ "bulkActions": "F1KBNa_bulkActions",
12260
+ "searchInput": "F1KBNa_searchInput",
12261
+ "splitLdel": "F1KBNa_splitLdel",
12262
+ "diffPath": "F1KBNa_diffPath",
12263
+ "line": "F1KBNa_line",
12264
+ "intraDel": "F1KBNa_intraDel",
12265
+ "settingsRowDesc": "F1KBNa_settingsRowDesc",
11973
12266
  "actionError": "F1KBNa_actionError",
11974
- "code": "F1KBNa_code",
11975
- "splitDivider": "F1KBNa_splitDivider",
11976
- "confirmCard": "F1KBNa_confirmCard",
11977
- "title": "F1KBNa_title",
12267
+ "rows": "F1KBNa_rows",
12268
+ "wrapActive": "F1KBNa_wrapActive",
12269
+ "hint": "F1KBNa_hint",
12270
+ "kindTag": "F1KBNa_kindTag",
11978
12271
  "wrap": "F1KBNa_wrap",
11979
- "statusAction": "F1KBNa_statusAction",
11980
- "noticeButton": "F1KBNa_noticeButton",
11981
- "flexSpacer": "F1KBNa_flexSpacer",
11982
- "confirmActions": "F1KBNa_confirmActions",
11983
- "searchInput": "F1KBNa_searchInput",
11984
- "settingsRowText": "F1KBNa_settingsRowText",
11985
- "header": "F1KBNa_header",
11986
- "diffStats": "F1KBNa_diffStats",
11987
- "settingsRowTitle": "F1KBNa_settingsRowTitle",
11988
- "blockFlash": "F1KBNa_blockFlash",
11989
- "row": "F1KBNa_row",
11990
12272
  "fullscreenBackdrop": "F1KBNa_fullscreenBackdrop",
11991
- "missing": "F1KBNa_missing",
11992
- "actionQuietDisabled": "F1KBNa_actionQuietDisabled",
11993
- "searchBar": "F1KBNa_searchBar",
12273
+ "readError": "F1KBNa_readError",
12274
+ "add": "F1KBNa_add",
11994
12275
  "overviewRuler": "F1KBNa_overviewRuler",
11995
- "notice": "F1KBNa_notice",
11996
- "splitCols": "F1KBNa_splitCols",
11997
- "markerAdd": "F1KBNa_markerAdd",
11998
- "splitRoot": "F1KBNa_splitRoot",
11999
- "blockPosition": "F1KBNa_blockPosition",
12000
- "overviewMarker": "F1KBNa_overviewMarker",
12001
- "noticeText": "F1KBNa_noticeText",
12002
- "iconAction": "F1KBNa_iconAction",
12003
12276
  "splitHScrollRow": "F1KBNa_splitHScrollRow",
12004
- "delCount": "F1KBNa_delCount",
12005
- "splitLadd": "F1KBNa_splitLadd",
12006
- "hint": "F1KBNa_hint",
12007
- "splitHScroll": "F1KBNa_splitHScroll",
12008
- "note": "F1KBNa_note",
12277
+ "splitRadd": "F1KBNa_splitRadd",
12278
+ "detailEmpty": "F1KBNa_detailEmpty",
12279
+ "statusAction": "F1KBNa_statusAction",
12280
+ "diffBodyWrap": "F1KBNa_diffBodyWrap",
12281
+ "toggleOn": "F1KBNa_toggleOn",
12282
+ "badgeCount": "F1KBNa_badgeCount",
12009
12283
  "settingsPage": "F1KBNa_settingsPage",
12010
- "splitLdel": "F1KBNa_splitLdel",
12011
- "rail": "F1KBNa_rail",
12012
- "del": "F1KBNa_del",
12284
+ "missingHint": "F1KBNa_missingHint",
12285
+ "footerButtons": "F1KBNa_footerButtons",
12013
12286
  "noteCentered": "F1KBNa_noteCentered",
12014
- "line": "F1KBNa_line",
12015
- "action": "F1KBNa_action",
12016
- "fileList": "F1KBNa_fileList",
12017
- "rowMeta": "F1KBNa_rowMeta",
12018
- "diffFlash": "F1KBNa_diffFlash",
12019
- "add": "F1KBNa_add",
12020
- "settingsSelector": "F1KBNa_settingsSelector",
12021
- "detailEmpty": "F1KBNa_detailEmpty",
12022
- "langSelect": "F1KBNa_langSelect",
12023
- "fileListFloat": "F1KBNa_fileListFloat",
12024
- "emptyState": "F1KBNa_emptyState",
12025
- "kindTag": "F1KBNa_kindTag",
12026
- "rowFailed": "F1KBNa_rowFailed",
12027
- "addCount": "F1KBNa_addCount",
12028
- "wrapActive": "F1KBNa_wrapActive",
12029
- "close": "F1KBNa_close",
12287
+ "intraAdd": "F1KBNa_intraAdd",
12288
+ "expandExpanded": "F1KBNa_expandExpanded",
12289
+ "headerActions": "F1KBNa_headerActions",
12290
+ "split": "F1KBNa_split",
12030
12291
  "diffHeader": "F1KBNa_diffHeader",
12031
- "badge": "F1KBNa_badge",
12032
- "bulkActions": "F1KBNa_bulkActions",
12033
- "expand": "F1KBNa_expand",
12034
- "group": "F1KBNa_group",
12292
+ "lines": "F1KBNa_lines",
12293
+ "stepperValue": "F1KBNa_stepperValue",
12294
+ "splitRoot": "F1KBNa_splitRoot",
12035
12295
  "rowHead": "F1KBNa_rowHead",
12036
- "settingsSelectorChevron": "F1KBNa_settingsSelectorChevron",
12296
+ "stepperButton": "F1KBNa_stepperButton",
12297
+ "rowMeta": "F1KBNa_rowMeta",
12298
+ "expand": "F1KBNa_expand",
12037
12299
  "settingsRow": "F1KBNa_settingsRow",
12300
+ "diff": "F1KBNa_diff",
12038
12301
  "panel": "F1KBNa_panel",
12302
+ "diffBodySplit": "F1KBNa_diffBodySplit",
12303
+ "note": "F1KBNa_note",
12304
+ "rowPath": "F1KBNa_rowPath",
12039
12305
  "detail": "F1KBNa_detail",
12040
- "split": "F1KBNa_split",
12041
- "importNote": "F1KBNa_importNote",
12042
- "resizeHandle": "F1KBNa_resizeHandle",
12043
- "diff": "F1KBNa_diff",
12306
+ "confirmActions": "F1KBNa_confirmActions",
12307
+ "badgeLabel": "F1KBNa_badgeLabel",
12044
12308
  "blockActions": "F1KBNa_blockActions",
12309
+ "blockPosition": "F1KBNa_blockPosition",
12045
12310
  "confirmText": "F1KBNa_confirmText",
12046
- "vSpacer": "F1KBNa_vSpacer",
12047
- "gutter": "F1KBNa_gutter",
12048
- "states": "F1KBNa_states",
12049
- "markerDel": "F1KBNa_markerDel",
12050
12311
  "context": "F1KBNa_context",
12051
- "diffBodySplit": "F1KBNa_diffBodySplit",
12052
- "diffBodyWrap": "F1KBNa_diffBodyWrap",
12053
12312
  "subline": "F1KBNa_subline",
12054
- "splitHScrollFill": "F1KBNa_splitHScrollFill",
12055
- "settingsRowDesc": "F1KBNa_settingsRowDesc",
12056
- "headerActions": "F1KBNa_headerActions",
12057
- "badgeCount": "F1KBNa_badgeCount"
12313
+ "settingsSelector": "F1KBNa_settingsSelector",
12314
+ "kindHint": "F1KBNa_kindHint",
12315
+ "notice": "F1KBNa_notice",
12316
+ "noticeText": "F1KBNa_noticeText",
12317
+ "markerAdd": "F1KBNa_markerAdd",
12318
+ "flexSpacer": "F1KBNa_flexSpacer",
12319
+ "stepper": "F1KBNa_stepper",
12320
+ "toggle": "F1KBNa_toggle",
12321
+ "settingsSelectorChevron": "F1KBNa_settingsSelectorChevron",
12322
+ "splitHScroll": "F1KBNa_splitHScroll",
12323
+ "noticeButton": "F1KBNa_noticeButton",
12324
+ "header": "F1KBNa_header",
12325
+ "rowFailed": "F1KBNa_rowFailed",
12326
+ "del": "F1KBNa_del",
12327
+ "diffActions": "F1KBNa_diffActions",
12328
+ "settingsRowText": "F1KBNa_settingsRowText",
12329
+ "fileListFloat": "F1KBNa_fileListFloat",
12330
+ "gutter": "F1KBNa_gutter",
12331
+ "layer": "F1KBNa_layer",
12332
+ "fileList": "F1KBNa_fileList",
12333
+ "overviewMarker": "F1KBNa_overviewMarker",
12334
+ "splitCols": "F1KBNa_splitCols",
12335
+ "searchBar": "F1KBNa_searchBar",
12336
+ "splitRdel": "F1KBNa_splitRdel",
12337
+ "missing": "F1KBNa_missing",
12338
+ "statusBar": "F1KBNa_statusBar",
12339
+ "diffStats": "F1KBNa_diffStats",
12340
+ "markerDel": "F1KBNa_markerDel",
12341
+ "delCount": "F1KBNa_delCount",
12342
+ "toggleThumb": "F1KBNa_toggleThumb",
12343
+ "iconAction": "F1KBNa_iconAction",
12344
+ "row": "F1KBNa_row",
12345
+ "searchCount": "F1KBNa_searchCount"
12058
12346
  };
12059
12347
  //#endregion
12060
12348
  //#region lib/types/client/PendingPanel.js
@@ -12090,6 +12378,10 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
12090
12378
  const FLOAT_LIST_MARGIN_PX = 12;
12091
12379
  /** Fixed diff-row height in px; the virtual window and jump math are built on it. */
12092
12380
  const ROW_HEIGHT_PX = 22;
12381
+ /** Tolerance absorbed when comparing a block's offset to the navigation anchor,
12382
+ * so a sub-pixel float error (wrapped row heights, fractional scrollTop) never
12383
+ * mis-classifies the block the view is sitting on. Half a row height. */
12384
+ const NAV_ANCHOR_TOLERANCE_PX = ROW_HEIGHT_PX / 4;
12093
12385
  /** Total width of the two line-number gutters, subtracted from the code width
12094
12386
  * when measuring wrapped line heights. */
12095
12387
  const WRAP_GUTTERS_PX = 88;
@@ -12304,6 +12596,55 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
12304
12596
  }
12305
12597
  return nodes.length === 0 ? "\xA0" : nodes;
12306
12598
  }
12599
+ /** Chip styling for each intra-line run: removed chars and added chars stand out. */
12600
+ const INTRA_CLASS = {
12601
+ same: void 0,
12602
+ del: PendingPanel_module_css_default.intraDel,
12603
+ add: PendingPanel_module_css_default.intraAdd
12604
+ };
12605
+ /** Clip intra-line runs to a character range, renumbering each cut run. */
12606
+ function clipIntra(intra, start, end) {
12607
+ const out = [];
12608
+ let pos = 0;
12609
+ for (const run of intra) {
12610
+ const runStart = pos;
12611
+ const runEnd = pos + run.text.length;
12612
+ pos = runEnd;
12613
+ if (runEnd <= start || runStart >= end) continue;
12614
+ const text = run.text.slice(Math.max(runStart, start) - runStart, Math.min(runEnd, end) - runStart);
12615
+ if (text.length === 0) continue;
12616
+ out.push({
12617
+ text,
12618
+ kind: run.kind
12619
+ });
12620
+ }
12621
+ return out;
12622
+ }
12623
+ /**
12624
+ * Render a character range as intra-line runs, with the syntax color clipped
12625
+ * back onto each run. Context (`same`) runs show no draw; removed/added runs
12626
+ * carry the chip draw. `intra` must cover `[start, end)` — it is clipped and
12627
+ * reassembled per run, so the returned nodes concatenate to that range.
12628
+ * @param runs - the syntax highlight for the whole line, or undefined.
12629
+ * @param intra - the intra-line runs for the whole line.
12630
+ * @param start - the range start (character offset in the line).
12631
+ * @param end - the range end (exclusive).
12632
+ * @returns the merged spans for the range.
12633
+ */
12634
+ function renderIntra(runs, intra, start, end) {
12635
+ const clipped = clipIntra(intra, start, end);
12636
+ let cursor = start;
12637
+ return clipped.map((run, i) => {
12638
+ const runStart = cursor;
12639
+ const runEnd = runStart + run.text.length;
12640
+ cursor = runEnd;
12641
+ const syntax = runs !== void 0 && runs.length > 0 ? clipRuns(runs, runStart, runEnd) : run.text;
12642
+ return (0, react_jsx_runtime.jsx)("span", {
12643
+ className: INTRA_CLASS[run.kind],
12644
+ children: syntax
12645
+ }, i);
12646
+ });
12647
+ }
12307
12648
  /**
12308
12649
  * One rendered diff row, memoized so a poll or an unrelated state change
12309
12650
  * does not re-render rows whose content, highlight, and focus are unchanged.
@@ -12424,10 +12765,11 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
12424
12765
  return blocks;
12425
12766
  }
12426
12767
  /** One side's line-content for the split view: the highlighted runs or plain text. */
12427
- function splitSideContent(side, wrapped, runs) {
12768
+ function splitSideContent(side, wrapped, runs, intra) {
12428
12769
  if (side === void 0) return "";
12429
12770
  const highlighted = runs !== void 0 && runs.length > 0;
12430
- if (wrapped === void 0) return highlighted ? runs.map((span, i) => (0, react_jsx_runtime.jsx)("span", {
12771
+ const hasIntra = intra !== void 0 && intra.length > 0;
12772
+ if (wrapped === void 0) return hasIntra ? renderIntra(runs, intra, 0, side.text.length) : highlighted ? runs.map((span, i) => (0, react_jsx_runtime.jsx)("span", {
12431
12773
  style: span.style,
12432
12774
  children: span.text
12433
12775
  }, i)) : side.text === "" ? "\xA0" : side.text;
@@ -12435,7 +12777,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
12435
12777
  return wrapped.map((line, i) => {
12436
12778
  const start = offset;
12437
12779
  offset += line.length;
12438
- const content = highlighted ? clipRuns(runs, start, offset) : line === "" ? "\xA0" : line;
12780
+ const content = hasIntra ? renderIntra(runs, intra, start, offset) : highlighted ? clipRuns(runs, start, offset) : line === "" ? "\xA0" : line;
12439
12781
  return (0, react_jsx_runtime.jsx)("div", {
12440
12782
  className: PendingPanel_module_css_default.subline,
12441
12783
  children: content
@@ -12451,7 +12793,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
12451
12793
  * one side is longer. The gutter and code are top-aligned so sub-lines line up
12452
12794
  * across the divider.
12453
12795
  */
12454
- function SplitSideRow({ index, side, wrapped, runs, kind, isLeft, height, focused, searchHit, searchCurrent, onHover }) {
12796
+ function SplitSideRow({ index, side, wrapped, runs, kind, isLeft, height, focused, searchHit, searchCurrent, onHover, intra }) {
12455
12797
  const tint = isLeft ? kind === "del" || kind === "replace" ? PendingPanel_module_css_default.splitLdel : "" : kind === "add" || kind === "replace" ? PendingPanel_module_css_default.splitRadd : "";
12456
12798
  return (0, react_jsx_runtime.jsxs)("div", {
12457
12799
  className: PendingPanel_module_css_default.line,
@@ -12468,14 +12810,26 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
12468
12810
  }), (0, react_jsx_runtime.jsx)("span", {
12469
12811
  className: `${PendingPanel_module_css_default.code} ${tint}`,
12470
12812
  "data-diff-code": true,
12471
- children: splitSideContent(side, wrapped, runs)
12813
+ children: splitSideContent(side, wrapped, runs, intra)
12472
12814
  })]
12473
12815
  });
12474
12816
  }
12475
12817
  /** The two-column (side-by-side) whole-file diff view. */
12476
- const SplitDiff = (0, react.forwardRef)(function SplitDiff({ file, model, runs, langWrap, tabWidthSpaces, busy, t, selection, onBlockKeep, onBlockRevert }, ref) {
12477
- const { pairs, pairOfRow } = (0, react.useMemo)(() => computeSideBySideDiff(model.diff.rows), [model]);
12818
+ const SplitDiff = (0, react.forwardRef)(function SplitDiff({ file, model, runs, langWrap, tabWidthSpaces, busy, t, selection, leadRows, onBlockKeep, onBlockRevert }, ref) {
12819
+ const { pairs, pairOfRow } = (0, react.useMemo)(() => computeSideBySideDiff(model.diff.rows, true), [model]);
12478
12820
  const pairCount = pairs.length;
12821
+ const pairRowIndices = (0, react.useMemo)(() => {
12822
+ const map = /* @__PURE__ */ new Map();
12823
+ model.diff.rows.forEach((row, rowIndex) => {
12824
+ const pairIndex = pairOfRow.get(rowIndex);
12825
+ if (pairIndex === void 0) return;
12826
+ const entry = map.get(pairIndex) ?? {};
12827
+ if (row.kind !== "add") entry.left = rowIndex;
12828
+ if (row.kind !== "del") entry.right = rowIndex;
12829
+ map.set(pairIndex, entry);
12830
+ });
12831
+ return map;
12832
+ }, [model, pairOfRow]);
12479
12833
  const bodyRef = (0, react.useRef)(null);
12480
12834
  const [scrollTop, setScrollTop] = (0, react.useState)(0);
12481
12835
  const [viewportH, setViewportH] = (0, react.useState)(0);
@@ -12688,13 +13042,21 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
12688
13042
  if (block === void 0) return;
12689
13043
  const body = bodyRef.current;
12690
13044
  if (body === null) return;
12691
- const target = off(block.start) - 44;
13045
+ const target = off(block.start) - leadRows * ROW_HEIGHT_PX;
12692
13046
  const clamped = Math.max(0, Math.min(target, body.scrollHeight - body.clientHeight));
12693
13047
  if (body.scrollTop !== clamped) body.scrollTop = clamped;
12694
13048
  setScrollTop(clamped);
12695
- }, [focus, flashKey]);
13049
+ }, [flashKey]);
12696
13050
  const onScroll = () => {
12697
- setScrollTop(bodyRef.current?.scrollTop ?? 0);
13051
+ const body = bodyRef.current;
13052
+ if (body === null) return;
13053
+ setScrollTop(body.scrollTop);
13054
+ const count = blockOfPair.length;
13055
+ if (count === 0) return;
13056
+ const anchor = body.scrollTop + leadRows * ROW_HEIGHT_PX;
13057
+ let ref = -1;
13058
+ for (let index = 0; index < count; index++) if (off(blockOfPair[index].start) <= anchor + NAV_ANCHOR_TOLERANCE_PX) ref = index;
13059
+ setFocus(ref === -1 ? 0 : ref);
12698
13060
  };
12699
13061
  const inFocused = (k) => {
12700
13062
  const block = blockOfPair[focus];
@@ -12736,6 +13098,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
12736
13098
  visiblePairs.map((pair, offset) => {
12737
13099
  const index = start + offset;
12738
13100
  const leftRuns = pair.left === void 0 ? void 0 : runs?.oldRuns?.[(pair.left.line ?? 0) - 1];
13101
+ const sideIndex = pairRowIndices.get(index);
12739
13102
  return (0, react_jsx_runtime.jsx)(SplitSideRow, {
12740
13103
  index,
12741
13104
  side: pair.left,
@@ -12747,7 +13110,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
12747
13110
  focused: inFocused(index),
12748
13111
  searchHit: searchHitSet.has(index),
12749
13112
  searchCurrent: index === currentSearchPair,
12750
- onHover: () => onPairHover(index)
13113
+ onHover: () => onPairHover(index),
13114
+ intra: sideIndex?.left === void 0 ? void 0 : model.intra.get(sideIndex.left)
12751
13115
  }, index);
12752
13116
  }),
12753
13117
  end < pairCount && (0, react_jsx_runtime.jsx)("div", {
@@ -12775,6 +13139,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
12775
13139
  visiblePairs.map((pair, offset) => {
12776
13140
  const index = start + offset;
12777
13141
  const rightRuns = pair.right === void 0 ? void 0 : runs?.newRuns?.[(pair.right.line ?? 0) - 1];
13142
+ const sideIndex = pairRowIndices.get(index);
12778
13143
  return (0, react_jsx_runtime.jsx)(SplitSideRow, {
12779
13144
  index,
12780
13145
  side: pair.right,
@@ -12786,7 +13151,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
12786
13151
  focused: inFocused(index),
12787
13152
  searchHit: searchHitSet.has(index),
12788
13153
  searchCurrent: index === currentSearchPair,
12789
- onHover: () => onPairHover(index)
13154
+ onHover: () => onPairHover(index),
13155
+ intra: sideIndex?.right === void 0 ? void 0 : model.intra.get(sideIndex.right)
12790
13156
  }, index);
12791
13157
  }),
12792
13158
  end < pairCount && (0, react_jsx_runtime.jsx)("div", {
@@ -13043,6 +13409,39 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
13043
13409
  return codeCellAt(node)?.textContent?.length ?? 0;
13044
13410
  }
13045
13411
  /**
13412
+ * Reconstruct the plain text of the current selection so auto-wrap's visual
13413
+ * line breaks never leak into the clipboard. A wrapped row renders its code as
13414
+ * several `.subline` block elements, and the browser's default copy inserts a
13415
+ * newline between them; those segments form one logical line, so they are joined
13416
+ * without a newline while the real newline between diff rows is kept.
13417
+ */
13418
+ function selectedPlainText() {
13419
+ const selection = window.getSelection();
13420
+ if (selection === null || selection.rangeCount === 0 || selection.isCollapsed) return void 0;
13421
+ const range = selection.getRangeAt(0);
13422
+ const container = document.createElement("div");
13423
+ container.appendChild(range.cloneContents());
13424
+ const parts = [];
13425
+ let atLineStart = true;
13426
+ const push = (text) => {
13427
+ if (text.length === 0) return;
13428
+ parts.push(text);
13429
+ atLineStart = text.endsWith("\n");
13430
+ };
13431
+ const walk = (node) => {
13432
+ if (node.nodeType === Node.TEXT_NODE) {
13433
+ push(node.textContent ?? "");
13434
+ return;
13435
+ }
13436
+ if (!(node instanceof Element)) return;
13437
+ const el = node;
13438
+ if ((el.dataset.diffRow !== void 0 || el.dataset.diffSplitRow !== void 0 || el.dataset.diffSplitIndex !== void 0) && !atLineStart) push("\n");
13439
+ for (const child of node.childNodes) walk(child);
13440
+ };
13441
+ walk(container);
13442
+ return parts.join("");
13443
+ }
13444
+ /**
13046
13445
  * Derive the selected diff-row range from a native text selection. A
13047
13446
  * boundary sitting exactly at a line edge contributes no content: a start at
13048
13447
  * the line's end skips to the next line, an end at the line's start falls
@@ -13138,15 +13537,22 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
13138
13537
  };
13139
13538
  const [tabWidthSpaces] = (0, react.useState)(() => tabWidth());
13140
13539
  const splitView = splitMode();
13540
+ const leadRows = navLeadRows();
13141
13541
  const splitDiffRef = (0, react.useRef)(null);
13142
13542
  const model = (0, react.useMemo)(() => {
13143
13543
  const diff = computeWholeFileDiff(file.oldText, file.newText);
13544
+ const intra = splitView ? computeIntraLineDiff(diff.rows, true) : /* @__PURE__ */ new Map();
13144
13545
  return {
13145
13546
  diff,
13146
- blocks: changeBlocksOf(diff)
13547
+ blocks: changeBlocksOf(diff),
13548
+ intra
13147
13549
  };
13148
- }, [file.oldText, file.newText]);
13149
- const splitPairs = (0, react.useMemo)(() => splitView ? computeSideBySideDiff(model.diff.rows).pairs : null, [splitView, model]);
13550
+ }, [
13551
+ file.oldText,
13552
+ file.newText,
13553
+ splitView
13554
+ ]);
13555
+ const splitPairs = (0, react.useMemo)(() => splitView ? computeSideBySideDiff(model.diff.rows, true).pairs : null, [splitView, model]);
13150
13556
  const rulerMarkers = (0, react.useMemo)(() => {
13151
13557
  const rows = model.diff.rows;
13152
13558
  const total = rows.length;
@@ -13372,14 +13778,14 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
13372
13778
  }
13373
13779
  const visibleRows = rows.slice(start, end);
13374
13780
  const blockEnd = hoveredBlock === void 0 ? void 0 : model.blocks[hoveredBlock]?.end;
13375
- const blockActionsTop = blockEnd === void 0 ? 0 : Math.min(offsetOf(blockEnd + 1), Math.max(0, totalHeight - BLOCK_ACTIONS_FRAME_PX));
13781
+ const blockActionsTop = blockEnd === void 0 ? 0 : Math.max(0, Math.min(offsetOf(blockEnd + 1) - scrollTop, Math.max(0, viewportHeight - BLOCK_ACTIONS_FRAME_PX)));
13376
13782
  const selectionBlockEnd = (() => {
13377
13783
  if (coveredBlockIndices.length === 0) return void 0;
13378
13784
  const lastIndex = coveredBlockIndices[coveredBlockIndices.length - 1];
13379
13785
  if (lastIndex === void 0) return void 0;
13380
13786
  return model.blocks[lastIndex]?.end;
13381
13787
  })();
13382
- const selectionActionsTop = selectionBlockEnd === void 0 ? 0 : Math.min(offsetOf(selectionBlockEnd + 1), Math.max(0, totalHeight - BLOCK_ACTIONS_FRAME_PX));
13788
+ const selectionActionsTop = selectionBlockEnd === void 0 ? 0 : Math.max(0, Math.min(offsetOf(selectionBlockEnd + 1) - scrollTop, Math.max(0, viewportHeight - BLOCK_ACTIONS_FRAME_PX)));
13383
13789
  const widestLine = (0, react.useMemo)(() => {
13384
13790
  let widest = 0;
13385
13791
  for (const row of model.diff.rows) if (row.text.length > widest) widest = row.text.length;
@@ -13418,15 +13824,11 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
13418
13824
  if (block === void 0) return;
13419
13825
  const body = bodyRef.current;
13420
13826
  if (body === null) return;
13421
- const target = offsetOf(block.start) - 44;
13827
+ const target = offsetOf(block.start) - leadRows * ROW_HEIGHT_PX;
13422
13828
  const clamped = Math.max(0, Math.min(target, body.scrollHeight - body.clientHeight));
13423
13829
  if (body.scrollTop !== clamped) body.scrollTop = clamped;
13424
13830
  setScrollTop(clamped);
13425
- }, [
13426
- focus,
13427
- scrollTick,
13428
- rowOffsets === null
13429
- ]);
13831
+ }, [scrollTick, rowOffsets === null]);
13430
13832
  const jump = (direction) => {
13431
13833
  if (rowCount === 0) return;
13432
13834
  setFocus((current) => {
@@ -13491,6 +13893,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
13491
13893
  if (body === null) return;
13492
13894
  setScrollTop(body.scrollTop);
13493
13895
  setViewportHeight(body.clientHeight);
13896
+ const count = model.blocks.length;
13897
+ if (rowCount === 0 || count === 0) return;
13898
+ const anchor = body.scrollTop + leadRows * ROW_HEIGHT_PX;
13899
+ let ref = -1;
13900
+ for (let index = 0; index < count; index++) {
13901
+ const block = model.blocks[index];
13902
+ if (block !== void 0 && offsetOf(block.start) <= anchor + NAV_ANCHOR_TOLERANCE_PX) ref = index;
13903
+ }
13904
+ setFocus(ref === -1 ? 0 : ref);
13494
13905
  };
13495
13906
  (0, react.useEffect)(() => {
13496
13907
  const update = () => setSelection(splitView ? splitRowRangeOf(window.getSelection()) : rowRangeOf(window.getSelection()));
@@ -13500,6 +13911,20 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
13500
13911
  document.removeEventListener("selectionchange", update);
13501
13912
  };
13502
13913
  }, [file.id, splitView]);
13914
+ (0, react.useEffect)(() => {
13915
+ const onCopy = (event) => {
13916
+ const anchor = window.getSelection()?.anchorNode;
13917
+ if (!((anchor instanceof Element ? anchor : anchor?.parentElement)?.closest("[data-diff-code]") !== null)) return;
13918
+ const text = selectedPlainText();
13919
+ if (text === void 0) return;
13920
+ event.preventDefault();
13921
+ event.clipboardData?.setData("text/plain", text);
13922
+ };
13923
+ document.addEventListener("copy", onCopy);
13924
+ return () => {
13925
+ document.removeEventListener("copy", onCopy);
13926
+ };
13927
+ }, []);
13503
13928
  const selectionReference = (() => {
13504
13929
  if (selection === void 0) return void 0;
13505
13930
  if (splitView) {
@@ -13662,10 +14087,6 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
13662
14087
  removed: model.diff.removed
13663
14088
  })
13664
14089
  }),
13665
- file.kind === "create" && (0, react_jsx_runtime.jsx)("span", {
13666
- className: PendingPanel_module_css_default.kindHint,
13667
- children: t("panel.createHint")
13668
- }),
13669
14090
  model.blocks.length > 0 && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
13670
14091
  label: `${t("action.prevDiff")} (Ctrl+↑)`,
13671
14092
  side: "bottom",
@@ -13729,7 +14150,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
13729
14150
  onClick: () => {
13730
14151
  onRevert(file.sessionId, file.id);
13731
14152
  },
13732
- children: t("action.revert")
14153
+ children: file.kind === "create" ? t("action.delete") : t("action.revert")
13733
14154
  })
13734
14155
  ]
13735
14156
  }),
@@ -13752,22 +14173,23 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
13752
14173
  busy,
13753
14174
  t,
13754
14175
  selection,
14176
+ leadRows,
13755
14177
  onBlockKeep,
13756
14178
  onBlockRevert
13757
14179
  }) : (0, react_jsx_runtime.jsxs)("div", {
13758
14180
  className: PendingPanel_module_css_default.diffBodyWrap,
14181
+ onMouseLeave: () => {
14182
+ setHoveredBlock(void 0);
14183
+ },
13759
14184
  children: [
13760
- (0, react_jsx_runtime.jsxs)("div", {
14185
+ (0, react_jsx_runtime.jsx)("div", {
13761
14186
  className: PendingPanel_module_css_default.diffBody,
13762
14187
  ref: bodyRef,
13763
14188
  tabIndex: 0,
13764
14189
  onScroll,
13765
- onMouseLeave: () => {
13766
- setHoveredBlock(void 0);
13767
- },
13768
14190
  style: { tabSize: tabWidthSpaces },
13769
14191
  "data-diff-body": true,
13770
- children: [(0, react_jsx_runtime.jsxs)("div", {
14192
+ children: (0, react_jsx_runtime.jsxs)("div", {
13771
14193
  className: `${PendingPanel_module_css_default.lines}${langWrap ? " " + PendingPanel_module_css_default.wrap : ""}`,
13772
14194
  style: langWrap ? {
13773
14195
  width: "100%",
@@ -13798,87 +14220,88 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
13798
14220
  "aria-hidden": "true"
13799
14221
  })
13800
14222
  ]
13801
- }), selectionRange !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
13802
- className: PendingPanel_module_css_default.blockActions,
13803
- "data-diff-selection-actions": true,
13804
- style: { top: selectionActionsTop },
13805
- children: [(0, react_jsx_runtime.jsx)("button", {
14223
+ })
14224
+ }),
14225
+ selectionRange !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
14226
+ className: PendingPanel_module_css_default.blockActions,
14227
+ "data-diff-selection-actions": true,
14228
+ style: { top: selectionActionsTop },
14229
+ children: [(0, react_jsx_runtime.jsx)("button", {
14230
+ type: "button",
14231
+ className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary}`,
14232
+ "data-diff-selection-keep": true,
14233
+ disabled: busy,
14234
+ onClick: () => {
14235
+ handleSelectionAction("keep");
14236
+ },
14237
+ children: t("action.keep")
14238
+ }), (0, react_jsx_runtime.jsx)("button", {
14239
+ type: "button",
14240
+ className: PendingPanel_module_css_default.action,
14241
+ "data-diff-selection-revert": true,
14242
+ disabled: busy,
14243
+ onClick: () => {
14244
+ handleSelectionAction("revert");
14245
+ },
14246
+ children: t("action.revert")
14247
+ })]
14248
+ }) : hoveredBlock !== void 0 && model.blocks[hoveredBlock] !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
14249
+ className: PendingPanel_module_css_default.blockActions,
14250
+ "data-diff-block-actions": true,
14251
+ style: { top: blockActionsTop },
14252
+ children: [
14253
+ (0, react_jsx_runtime.jsx)("span", {
14254
+ className: PendingPanel_module_css_default.blockPosition,
14255
+ "data-diff-block-position": true,
14256
+ children: t("panel.blockPosition", {
14257
+ current: hoveredBlock + 1,
14258
+ total: model.blocks.length
14259
+ })
14260
+ }),
14261
+ (0, react_jsx_runtime.jsx)("button", {
14262
+ type: "button",
14263
+ className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
14264
+ "data-diff-block-prev": true,
14265
+ "aria-label": t("action.prevDiff"),
14266
+ disabled: busy,
14267
+ onClick: () => {
14268
+ stepBlock(-1);
14269
+ },
14270
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 14 })
14271
+ }),
14272
+ (0, react_jsx_runtime.jsx)("button", {
14273
+ type: "button",
14274
+ className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
14275
+ "data-diff-block-next": true,
14276
+ "aria-label": t("action.nextDiff"),
14277
+ disabled: busy,
14278
+ onClick: () => {
14279
+ stepBlock(1);
14280
+ },
14281
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })
14282
+ }),
14283
+ (0, react_jsx_runtime.jsx)("button", {
13806
14284
  type: "button",
13807
14285
  className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary}`,
13808
- "data-diff-selection-keep": true,
14286
+ "data-diff-block-keep": true,
13809
14287
  disabled: busy,
13810
14288
  onClick: () => {
13811
- handleSelectionAction("keep");
14289
+ handleBlockAction("keep");
13812
14290
  },
13813
14291
  children: t("action.keep")
13814
- }), (0, react_jsx_runtime.jsx)("button", {
14292
+ }),
14293
+ (0, react_jsx_runtime.jsx)("button", {
13815
14294
  type: "button",
13816
14295
  className: PendingPanel_module_css_default.action,
13817
- "data-diff-selection-revert": true,
14296
+ "data-diff-block-revert": true,
13818
14297
  disabled: busy,
13819
14298
  onClick: () => {
13820
- handleSelectionAction("revert");
14299
+ handleBlockAction("revert");
13821
14300
  },
13822
14301
  children: t("action.revert")
13823
- })]
13824
- }) : hoveredBlock !== void 0 && model.blocks[hoveredBlock] !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
13825
- className: PendingPanel_module_css_default.blockActions,
13826
- "data-diff-block-actions": true,
13827
- style: { top: blockActionsTop },
13828
- children: [
13829
- (0, react_jsx_runtime.jsx)("span", {
13830
- className: PendingPanel_module_css_default.blockPosition,
13831
- "data-diff-block-position": true,
13832
- children: t("panel.blockPosition", {
13833
- current: hoveredBlock + 1,
13834
- total: model.blocks.length
13835
- })
13836
- }),
13837
- (0, react_jsx_runtime.jsx)("button", {
13838
- type: "button",
13839
- className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
13840
- "data-diff-block-prev": true,
13841
- "aria-label": t("action.prevDiff"),
13842
- disabled: busy,
13843
- onClick: () => {
13844
- stepBlock(-1);
13845
- },
13846
- children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 14 })
13847
- }),
13848
- (0, react_jsx_runtime.jsx)("button", {
13849
- type: "button",
13850
- className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
13851
- "data-diff-block-next": true,
13852
- "aria-label": t("action.nextDiff"),
13853
- disabled: busy,
13854
- onClick: () => {
13855
- stepBlock(1);
13856
- },
13857
- children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })
13858
- }),
13859
- (0, react_jsx_runtime.jsx)("button", {
13860
- type: "button",
13861
- className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary}`,
13862
- "data-diff-block-keep": true,
13863
- disabled: busy,
13864
- onClick: () => {
13865
- handleBlockAction("keep");
13866
- },
13867
- children: t("action.keep")
13868
- }),
13869
- (0, react_jsx_runtime.jsx)("button", {
13870
- type: "button",
13871
- className: PendingPanel_module_css_default.action,
13872
- "data-diff-block-revert": true,
13873
- disabled: busy,
13874
- onClick: () => {
13875
- handleBlockAction("revert");
13876
- },
13877
- children: t("action.revert")
13878
- })
13879
- ]
13880
- }) : null]
13881
- }),
14302
+ })
14303
+ ]
14304
+ }) : null,
13882
14305
  focusedBlock !== void 0 && flashKey > 0 && (0, react_jsx_runtime.jsx)("div", {
13883
14306
  className: PendingPanel_module_css_default.blockFlash,
13884
14307
  "data-diff-block-flash": true,
@@ -14699,42 +15122,26 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
14699
15122
  //#endregion
14700
15123
  //#region lib/types/client/SettingsTab.js
14701
15124
  /** DSH Settings top-level section for this plugin's preferences. */
14702
- /** A pill picker offering the two boolean states 打开 / 关闭. */
14703
- function OnOffPicker({ value, open, onOpenChange, onSelect, dataAttribute, t }) {
14704
- return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
14705
- open,
14706
- onClose: () => {
14707
- onOpenChange(false);
14708
- },
14709
- items: [{
14710
- id: "on",
14711
- label: t("action.toggleOn")
14712
- }, {
14713
- id: "off",
14714
- label: t("action.toggleOff")
14715
- }],
14716
- selectedId: value ? "on" : "off",
14717
- onSelect: (id) => {
14718
- onOpenChange(false);
14719
- onSelect(id === "on");
15125
+ /** A toggle switch offering the two boolean states 打开 / 关闭. */
15126
+ function OnOffToggle({ value, onSelect, dataAttribute, t }) {
15127
+ return (0, react_jsx_runtime.jsx)("button", {
15128
+ type: "button",
15129
+ role: "switch",
15130
+ "aria-checked": value,
15131
+ "aria-label": value ? t("action.toggleOn") : t("action.toggleOff"),
15132
+ className: `${PendingPanel_module_css_default.toggle}${value ? " " + PendingPanel_module_css_default.toggleOn : ""}`,
15133
+ [dataAttribute]: true,
15134
+ onClick: () => {
15135
+ onSelect(!value);
14720
15136
  },
14721
- align: "end",
14722
- portal: true,
14723
- anchor: (0, react_jsx_runtime.jsxs)("button", {
14724
- type: "button",
14725
- className: PendingPanel_module_css_default.settingsSelector,
14726
- "aria-haspopup": "menu",
14727
- "aria-expanded": open,
14728
- onClick: () => {
14729
- onOpenChange(!open);
14730
- },
14731
- [dataAttribute]: true,
14732
- children: [value ? t("action.toggleOn") : t("action.toggleOff"), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: PendingPanel_module_css_default.settingsSelectorChevron })]
15137
+ children: (0, react_jsx_runtime.jsx)("span", {
15138
+ className: PendingPanel_module_css_default.toggleThumb,
15139
+ "aria-hidden": "true"
14733
15140
  })
14734
15141
  });
14735
15142
  }
14736
- /** One Agent-preset-style preference row: title + description, pill picker right. */
14737
- function PreferenceRow({ title, description, value, open, onOpenChange, onSelect, dataAttribute, t }) {
15143
+ /** One Agent-preset-style preference row: title + description, toggle right. */
15144
+ function PreferenceRow({ title, description, value, onSelect, dataAttribute, t }) {
14738
15145
  return (0, react_jsx_runtime.jsxs)("div", {
14739
15146
  className: PendingPanel_module_css_default.settingsRow,
14740
15147
  children: [(0, react_jsx_runtime.jsxs)("div", {
@@ -14746,10 +15153,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
14746
15153
  className: PendingPanel_module_css_default.settingsRowDesc,
14747
15154
  children: description
14748
15155
  })]
14749
- }), (0, react_jsx_runtime.jsx)(OnOffPicker, {
15156
+ }), (0, react_jsx_runtime.jsx)(OnOffToggle, {
14750
15157
  value,
14751
- open,
14752
- onOpenChange,
14753
15158
  onSelect,
14754
15159
  dataAttribute,
14755
15160
  t
@@ -14814,6 +15219,53 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
14814
15219
  })]
14815
15220
  });
14816
15221
  }
15222
+ /** A +/- number stepper for an integer preference, clamped to [min, max]. */
15223
+ function StepperRow({ title, description, value, onChange, min, max, dataAttribute, t }) {
15224
+ return (0, react_jsx_runtime.jsxs)("div", {
15225
+ className: PendingPanel_module_css_default.settingsRow,
15226
+ children: [(0, react_jsx_runtime.jsxs)("div", {
15227
+ className: PendingPanel_module_css_default.settingsRowText,
15228
+ children: [(0, react_jsx_runtime.jsx)("div", {
15229
+ className: PendingPanel_module_css_default.settingsRowTitle,
15230
+ children: title
15231
+ }), (0, react_jsx_runtime.jsx)("div", {
15232
+ className: PendingPanel_module_css_default.settingsRowDesc,
15233
+ children: description
15234
+ })]
15235
+ }), (0, react_jsx_runtime.jsxs)("div", {
15236
+ className: PendingPanel_module_css_default.stepper,
15237
+ children: [
15238
+ (0, react_jsx_runtime.jsx)("button", {
15239
+ type: "button",
15240
+ className: PendingPanel_module_css_default.stepperButton,
15241
+ "data-diff-stepper-down": true,
15242
+ "aria-label": t("action.decrease"),
15243
+ disabled: value <= min,
15244
+ onClick: () => {
15245
+ onChange(Math.max(min, value - 1));
15246
+ },
15247
+ children: "−"
15248
+ }),
15249
+ (0, react_jsx_runtime.jsx)("span", {
15250
+ className: PendingPanel_module_css_default.stepperValue,
15251
+ [dataAttribute]: true,
15252
+ children: value
15253
+ }),
15254
+ (0, react_jsx_runtime.jsx)("button", {
15255
+ type: "button",
15256
+ className: PendingPanel_module_css_default.stepperButton,
15257
+ "data-diff-stepper-up": true,
15258
+ "aria-label": t("action.increase"),
15259
+ disabled: value >= max,
15260
+ onClick: () => {
15261
+ onChange(Math.min(max, value + 1));
15262
+ },
15263
+ children: "+"
15264
+ })
15265
+ ]
15266
+ })]
15267
+ });
15268
+ }
14817
15269
  /** Build the `Modifier+...+Key` chord label from a keydown event; a bare
14818
15270
  * modifier key alone returns undefined (wait for the full combo). */
14819
15271
  function chordLabel(event) {
@@ -14886,13 +15338,11 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
14886
15338
  */
14887
15339
  function DiffApprovalSettingsTab({ t }) {
14888
15340
  const [pasteOnCopy, setPasteOnCopyState] = (0, react.useState)(pasteOnCopyEnabled);
14889
- const [pasteOnCopyOpen, setPasteOnCopyOpen] = (0, react.useState)(false);
14890
15341
  const [includeUntracked, setIncludeUntrackedState] = (0, react.useState)(includeUntrackedEnabled);
14891
- const [includeUntrackedOpen, setIncludeUntrackedOpen] = (0, react.useState)(false);
14892
15342
  const [tab, setTabState] = (0, react.useState)(tabWidth);
14893
15343
  const [tabOpen, setTabOpen] = (0, react.useState)(false);
14894
15344
  const [split, setSplitState] = (0, react.useState)(splitMode);
14895
- const [splitOpen, setSplitOpen] = (0, react.useState)(false);
15345
+ const [lead, setLeadState] = (0, react.useState)(navLeadRows);
14896
15346
  const [summon, setSummonState] = (0, react.useState)(quickSummonKey);
14897
15347
  const setSummon = (value) => {
14898
15348
  setSummonState(value);
@@ -14914,6 +15364,10 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
14914
15364
  setSplitState(value);
14915
15365
  setSplitMode(value);
14916
15366
  };
15367
+ const setLead = (value) => {
15368
+ setLeadState(value);
15369
+ setNavLeadRows(value);
15370
+ };
14917
15371
  return (0, react_jsx_runtime.jsxs)("div", {
14918
15372
  className: PendingPanel_module_css_default.settingsPage,
14919
15373
  "data-diff-settings": true,
@@ -14922,8 +15376,6 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
14922
15376
  title: t("panel.pasteOnCopy"),
14923
15377
  description: t("panel.pasteOnCopyDesc"),
14924
15378
  value: pasteOnCopy,
14925
- open: pasteOnCopyOpen,
14926
- onOpenChange: setPasteOnCopyOpen,
14927
15379
  onSelect: setPasteOnCopy,
14928
15380
  dataAttribute: "data-diff-paste-on-copy-select",
14929
15381
  t
@@ -14932,8 +15384,6 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
14932
15384
  title: t("panel.importUntracked"),
14933
15385
  description: t("panel.importUntrackedDesc"),
14934
15386
  value: includeUntracked,
14935
- open: includeUntrackedOpen,
14936
- onOpenChange: setIncludeUntrackedOpen,
14937
15387
  onSelect: setIncludeUntracked,
14938
15388
  dataAttribute: "data-diff-import-untracked-select",
14939
15389
  t
@@ -14951,12 +15401,20 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
14951
15401
  title: t("panel.splitMode"),
14952
15402
  description: t("panel.splitModeDesc"),
14953
15403
  value: split,
14954
- open: splitOpen,
14955
- onOpenChange: setSplitOpen,
14956
15404
  onSelect: setSplit,
14957
15405
  dataAttribute: "data-diff-split-mode-select",
14958
15406
  t
14959
15407
  }),
15408
+ (0, react_jsx_runtime.jsx)(StepperRow, {
15409
+ title: t("panel.navLeadRows"),
15410
+ description: t("panel.navLeadRowsDesc"),
15411
+ value: lead,
15412
+ onChange: setLead,
15413
+ min: 0,
15414
+ max: 10,
15415
+ dataAttribute: "data-diff-nav-lead-rows",
15416
+ t
15417
+ }),
14960
15418
  (0, react_jsx_runtime.jsx)(ShortcutRow, {
14961
15419
  title: t("panel.quickSummon"),
14962
15420
  description: t("panel.quickSummonDesc"),
@@ -15506,7 +15964,6 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
15506
15964
  "panel.missingHint": "该文件已不存在,回退会恢复该文件。",
15507
15965
  "panel.externalChanged": "检测到文件在外部被修改,已更新对比并新建撤销点;重做历史已被重置。",
15508
15966
  "panel.dismiss": "知道了",
15509
- "panel.createHint": "回退会删除该新建的文件。",
15510
15967
  "panel.pasteOnCopy": "复制引用后自动粘贴到消息输入框",
15511
15968
  "panel.pasteOnCopyDesc": "开启后,复制的引用会自动填入消息输入框,输入框会获得焦点。",
15512
15969
  "panel.importUntracked": "导入未跟踪的文件改动",
@@ -15515,8 +15972,10 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
15515
15972
  "panel.tabWidthDesc": "差异中制表符的缩进宽度,可选 2 / 4 / 8 个空格(默认 4),同时作用于行宽折行测量。",
15516
15973
  "panel.splitMode": "双栏对比",
15517
15974
  "panel.splitModeDesc": "开启后整文件差异用左「改前」|右「当前」双栏、逐行对齐的视图展示,默认关闭使用单栏(合并)视图。",
15975
+ "panel.navLeadRows": "差异跳转行距",
15976
+ "panel.navLeadRowsDesc": "按上/下跳转差异时,目标差异上方保留的行数(默认 2)。也用于从当前滚动位置定位上/下一个差异。",
15518
15977
  "panel.quickSummon": "快速呼出",
15519
- "panel.quickSummonDesc": "用键盘快捷键打开/关闭差异面板(默认 Ctrl+D)。点击右侧按钮后按下新的按键组合即可修改,Esc 取消。",
15978
+ "panel.quickSummonDesc": "用键盘快捷键打开/关闭差异面板。点击右侧按钮后按下新的按键组合即可修改。",
15520
15979
  "panel.recordShortcut": "按下快捷键…",
15521
15980
  "settings.tabLabel": "改动审批",
15522
15981
  "row.create": "新增文件",
@@ -15526,6 +15985,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
15526
15985
  "row.removed": "-{removed}",
15527
15986
  "action.keep": "保留",
15528
15987
  "action.revert": "回退",
15988
+ "action.delete": "删除",
15529
15989
  "action.keepAll": "全部保留",
15530
15990
  "action.revertAll": "全部回退",
15531
15991
  "action.openFile": "打开文件",
@@ -15543,6 +16003,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
15543
16003
  "action.wrap": "自动换行",
15544
16004
  "action.toggleOn": "打开",
15545
16005
  "action.toggleOff": "关闭",
16006
+ "action.decrease": "减小",
16007
+ "action.increase": "增大",
15546
16008
  "action.importVcs": "导入工作区改动",
15547
16009
  "action.importVcsBusy": "导入中…",
15548
16010
  "panel.importNone": "没有可导入的改动",
@@ -15577,7 +16039,6 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
15577
16039
  "panel.missingHint": "This file no longer exists; reverting restores it.",
15578
16040
  "panel.externalChanged": "A file changed outside the review. The comparison was updated and a new undo point created; the redo history was reset.",
15579
16041
  "panel.dismiss": "Got it",
15580
- "panel.createHint": "Reverting removes this created file.",
15581
16042
  "panel.pasteOnCopy": "Paste the copied reference into the composer",
15582
16043
  "panel.pasteOnCopyDesc": "When enabled, a copied reference is pasted into the composer, which then receives focus.",
15583
16044
  "panel.importUntracked": "Import changes to untracked files",
@@ -15586,8 +16047,10 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
15586
16047
  "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.",
15587
16048
  "panel.splitMode": "Side-by-side view",
15588
16049
  "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.",
16050
+ "panel.navLeadRows": "Block jump lead rows",
16051
+ "panel.navLeadRowsDesc": "Rows left above the jumped-to diff block on up/down navigation (default 2). Also used to locate the previous/next diff from the current scroll position.",
15589
16052
  "panel.quickSummon": "Quick summon",
15590
- "panel.quickSummonDesc": "Open or close the diff panel with a keyboard shortcut (default Ctrl+D). Click the button and press a new chord to change it; Esc cancels.",
16053
+ "panel.quickSummonDesc": "Open or close the diff panel with a keyboard shortcut. Click the button and press a new chord to change it.",
15591
16054
  "panel.recordShortcut": "Press keys…",
15592
16055
  "settings.tabLabel": "Diff Approval",
15593
16056
  "row.create": "New file",
@@ -15597,6 +16060,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
15597
16060
  "row.removed": "-{removed}",
15598
16061
  "action.keep": "Keep",
15599
16062
  "action.revert": "Revert",
16063
+ "action.delete": "Delete",
15600
16064
  "action.keepAll": "Keep all",
15601
16065
  "action.revertAll": "Revert all",
15602
16066
  "action.openFile": "Open file",
@@ -15614,6 +16078,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
15614
16078
  "action.wrap": "Wrap lines",
15615
16079
  "action.toggleOn": "On",
15616
16080
  "action.toggleOff": "Off",
16081
+ "action.decrease": "Decrease",
16082
+ "action.increase": "Increase",
15617
16083
  "action.importVcs": "Import workspace changes",
15618
16084
  "action.importVcsBusy": "Importing…",
15619
16085
  "panel.importNone": "No changes to import",