dsh-diff-approval 0.19.1 → 0.19.3

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
@@ -5448,6 +5448,51 @@ Please report this to https://github.com/markedjs/marked.`, e) {
5448
5448
  }
5449
5449
  }
5450
5450
  //#endregion
5451
+ //#region lib/types/client/search.js
5452
+ /**
5453
+ * The in-file search matcher, shared by the unified diff and the split view so
5454
+ * both highlight and count the same occurrences.
5455
+ * @module dsh-diff-approval/client/search
5456
+ */
5457
+ /** The plain search: case-insensitive, substring. */
5458
+ const DEFAULT_SEARCH_OPTIONS = {
5459
+ caseSensitive: false,
5460
+ wholeWord: false
5461
+ };
5462
+ /**
5463
+ * Whether `at` holds an identifier character (the ASCII set editors use), or
5464
+ * false outside the string, so a match at either edge counts as a whole word.
5465
+ * @param text - the searched line.
5466
+ * @param at - the character index to test.
5467
+ * @returns whether that position is part of a word.
5468
+ */
5469
+ function isWordCharAt(text, at) {
5470
+ if (at < 0 || at >= text.length) return false;
5471
+ return /[A-Za-z0-9_]/.test(text.charAt(at));
5472
+ }
5473
+ /**
5474
+ * Character ranges of every occurrence of `query` in `text` that the options
5475
+ * accept. Case-insensitive and substring-based unless narrowed.
5476
+ * @param text - the line to search.
5477
+ * @param query - the search text; empty matches nothing.
5478
+ * @param options - case and whole-word narrowing.
5479
+ * @returns `[start, end)` ranges in ascending order.
5480
+ */
5481
+ function matchRangesOf(text, query, options = DEFAULT_SEARCH_OPTIONS) {
5482
+ if (query === "") return [];
5483
+ const haystack = options.caseSensitive ? text : text.toLowerCase();
5484
+ const needle = options.caseSensitive ? query : query.toLowerCase();
5485
+ const out = [];
5486
+ let from = 0;
5487
+ for (;;) {
5488
+ const at = haystack.indexOf(needle, from);
5489
+ if (at === -1) return out;
5490
+ const end = at + needle.length;
5491
+ if (!options.wholeWord || !isWordCharAt(text, at - 1) && !isWordCharAt(text, end)) out.push([at, end]);
5492
+ from = end;
5493
+ }
5494
+ }
5495
+ //#endregion
5451
5496
  //#region lib/types/client/split-diff.js
5452
5497
  /**
5453
5498
  * Side-by-side (split) diff model: the unified whole-file diff rows are
@@ -5553,23 +5598,23 @@ Please report this to https://github.com/markedjs/marked.`, e) {
5553
5598
  };
5554
5599
  }
5555
5600
  /**
5556
- * Pair indices whose left or right text contains the query (case-insensitive).
5557
- * A pair counts once however many times the query appears, so split search
5558
- * highlights the whole pair on both columns and a single "current" pair is
5559
- * stepped through — not each individual left/right occurrence.
5601
+ * Pair indices whose left or right text matches the query. A pair counts once
5602
+ * however many times the query appears, so split search highlights the whole pair
5603
+ * on both columns and a single "current" pair is stepped through — not each
5604
+ * individual left/right occurrence.
5560
5605
  * @param pairs - the split pairs.
5561
5606
  * @param query - the query text; an empty query matches nothing.
5607
+ * @param options - case and whole-word narrowing.
5562
5608
  * @returns matching pair indices, in file order.
5563
5609
  */
5564
- function searchPairs(pairs, query) {
5610
+ function searchPairs(pairs, query, options = DEFAULT_SEARCH_OPTIONS) {
5565
5611
  if (query === "") return [];
5566
- const lower = query.toLowerCase();
5567
5612
  const matches = [];
5568
5613
  for (let index = 0; index < pairs.length; index++) {
5569
5614
  const p = pairs[index];
5570
5615
  if (p === void 0) continue;
5571
- if (p.left !== void 0 && p.left.text.toLowerCase().includes(lower)) matches.push(index);
5572
- else if (p.right !== void 0 && p.right.text.toLowerCase().includes(lower)) matches.push(index);
5616
+ if (p.left !== void 0 && matchRangesOf(p.left.text, query, options).length > 0) matches.push(index);
5617
+ else if (p.right !== void 0 && matchRangesOf(p.right.text, query, options).length > 0) matches.push(index);
5573
5618
  }
5574
5619
  return matches;
5575
5620
  }
@@ -16697,6 +16742,9 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
16697
16742
  /** Client preferences for the review panel, persisted in localStorage. */
16698
16743
  const PASTE_ON_COPY_KEY = "diff-approval:paste-on-copy";
16699
16744
  const IMPORT_UNTRACKED_KEY = "diff-approval:import-untracked";
16745
+ const CONFIRM_FILE_REMOVE_KEY = "diff-approval:confirm-file-remove";
16746
+ const SEARCH_CASE_KEY = "diff-approval:search-case";
16747
+ const SEARCH_WORD_KEY = "diff-approval:search-word";
16700
16748
  const TAB_WIDTH_KEY = "diff-approval:tab-size";
16701
16749
  const SPLIT_MODE_KEY = "diff-approval:split-mode";
16702
16750
  const MD_PREVIEW_KEY = "diff-approval:md-preview";
@@ -16735,6 +16783,43 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
16735
16783
  localStorage.setItem(IMPORT_UNTRACKED_KEY, value ? "1" : "0");
16736
16784
  }
16737
16785
  /**
16786
+ * Whether a whole-file keep/revert asks before dropping the resolved file from
16787
+ * the list. Defaults to on; only an explicit `'0'` disables it, which then
16788
+ * removes the file straight away.
16789
+ * @returns whether the remove prompt is enabled.
16790
+ */
16791
+ function confirmFileRemoveEnabled() {
16792
+ return localStorage.getItem(CONFIRM_FILE_REMOVE_KEY) !== "0";
16793
+ }
16794
+ /** Persist the whole-file remove-prompt preference. */
16795
+ function setConfirmFileRemoveEnabled(value) {
16796
+ localStorage.setItem(CONFIRM_FILE_REMOVE_KEY, value ? "1" : "0");
16797
+ }
16798
+ /**
16799
+ * Whether the in-file search matches letter case exactly. Defaults to off, so a
16800
+ * plain query keeps matching either case; only an explicit `'1'` turns it on.
16801
+ * @returns whether the search is case-sensitive.
16802
+ */
16803
+ function searchCaseSensitive() {
16804
+ return localStorage.getItem(SEARCH_CASE_KEY) === "1";
16805
+ }
16806
+ /** Persist the search case-sensitivity preference. */
16807
+ function setSearchCaseSensitive(value) {
16808
+ localStorage.setItem(SEARCH_CASE_KEY, value ? "1" : "0");
16809
+ }
16810
+ /**
16811
+ * Whether the in-file search only matches whole words. Defaults to off; only an
16812
+ * explicit `'1'` enables it.
16813
+ * @returns whether the search matches whole words only.
16814
+ */
16815
+ function searchWholeWord() {
16816
+ return localStorage.getItem(SEARCH_WORD_KEY) === "1";
16817
+ }
16818
+ /** Persist the search whole-word preference. */
16819
+ function setSearchWholeWord(value) {
16820
+ localStorage.setItem(SEARCH_WORD_KEY, value ? "1" : "0");
16821
+ }
16822
+ /**
16738
16823
  * Whether lines wrap (auto-wrap) in the diff for one highlight language.
16739
16824
  * Defaults to off; only an explicit `'1'` enables it. Stored per language, so
16740
16825
  * a language's preference never leaks into another's.
@@ -16903,6 +16988,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
16903
16988
  openSearch: "Ctrl+F",
16904
16989
  searchNext: "F3",
16905
16990
  searchPrev: "Shift+F3",
16991
+ matchCase: "Alt+C",
16992
+ matchWholeWord: "Alt+W",
16906
16993
  undo: "Ctrl+Z",
16907
16994
  redo: "Ctrl+Shift+Z",
16908
16995
  cycleNext: "Ctrl+Tab",
@@ -16938,7 +17025,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
16938
17025
  }
16939
17026
  //#endregion
16940
17027
  //#region \0dsh-css:/home/runner/work/dsh-diff-approval/dsh-diff-approval/src/client/PendingPanel.module.css.mjs
16941
- 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_settingsGroup{border-bottom:1px solid var(--dsw-alias-border-l2);margin-top:8px}.F1KBNa_settingsGroupHeader{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:8px;padding:12px 0;display:flex}.F1KBNa_settingsGroupText{text-align:left;flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.F1KBNa_settingsGroupTitle{font-size:14px;font-weight:400;line-height:22px}.F1KBNa_settingsGroupDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}.F1KBNa_settingsGroupChevron{margin-left:auto;transition:transform .15s}.F1KBNa_settingsGroup[data-open] .F1KBNa_settingsGroupChevron{transform:rotate(180deg)}.F1KBNa_settingsGroup[data-open] .F1KBNa_settingsGroupHeader{border-bottom:1px solid var(--dsw-alias-border-l2)}.F1KBNa_settingsGroupBody{flex-direction:column;display:flex}.F1KBNa_settingsGroupBody .F1KBNa_settingsRow{padding-left:16px}.F1KBNa_settingsGroupBody .F1KBNa_settingsRow:last-child,.F1KBNa_settingsPage>.F1KBNa_settingsRow:last-child{border-bottom:none}.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_colorPicker{position:relative}.F1KBNa_colorPickerTrigger{background:var(--dsw-alias-bg-module-platform);width:120px;height:36px;font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:18px;align-items:center;gap:8px;padding:0 8px;font-size:12px;line-height:18px;display:inline-flex}.F1KBNa_colorPickerTrigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_colorSwatch{border:1px solid var(--dsw-alias-border-l2);border-radius:50%;flex:none;width:24px;height:24px}.F1KBNa_colorValue{text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;flex:1;min-width:0;overflow:hidden}.F1KBNa_colorPickerChevron{flex:none}.F1KBNa_colorBackdrop{z-index:40;position:fixed;inset:0}.F1KBNa_colorPickerPopover{z-index:41;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);box-shadow:var(--dsw-shadow-lv2);border-radius:10px;padding:10px;position:absolute;top:calc(100% + 6px);right:0}.F1KBNa_colorPickerPanel{flex-direction:column;gap:8px;display:flex}.F1KBNa_colorPickerInputRow{align-items:center;gap:8px;display:flex}.F1KBNa_colorPickerPreview{border:1px solid var(--dsw-alias-border-l2);border-radius:6px;flex:none;width:22px;height:22px}.F1KBNa_colorPickerInput{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-module-platform);min-width:0;height:30px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;flex:1;padding:0 8px;font-size:12px;line-height:28px}.F1KBNa_colorPickerInput:focus{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-1px}.F1KBNa_colorSv{border:1px solid var(--dsw-alias-border-l1);cursor:crosshair;touch-action:none;border-radius:8px;height:140px;position:relative}.F1KBNa_colorSvCursor{pointer-events:none;border:2px solid #fff;border-radius:50%;width:14px;height:14px;position:absolute;transform:translate(-50%,-50%);box-shadow:0 0 0 1px #00000080}.F1KBNa_colorHue{border:1px solid var(--dsw-alias-border-l1);cursor:pointer;touch-action:none;border-radius:7px;height:14px;position:relative}.F1KBNa_colorHueCursor{pointer-events:none;border:2px solid #fff;border-radius:50%;width:16px;height:16px;position:absolute;top:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 1px #00000080}.F1KBNa_diffPreview{z-index:2;border:1px solid var(--dsw-alias-border-l1);font:var(--dsw-font-markdown-code-block);background:var(--dsw-alias-markdown-code-block);border-radius:8px;margin-bottom:8px;padding:8px;position:sticky;top:0;overflow:hidden}.F1KBNa_diffPreviewTitle{color:var(--dsw-alias-label-tertiary);margin-bottom:6px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_diffPreviewScroll{height:132px;overflow-y:auto}.F1KBNa_mdPreviewWrap{flex:1;min-width:0;min-height:0;display:flex;position:relative}.F1KBNa_mdPreviewBody{min-width:0;min-height:0;color:var(--dsw-alias-label-primary);flex:1;padding:12px 16px;position:relative;overflow:auto}.F1KBNa_mdPreviewContent{width:100%;min-width:0;margin:0 auto}.F1KBNa_mdPreviewSingle{display:block}.F1KBNa_mdPreviewDouble{display:flex}.F1KBNa_mdPreviewBody .mdBlock{border-radius:4px;margin-bottom:12px;padding:2px 6px}.F1KBNa_mdPreviewBody .mdAdd{background-color:color-mix(in srgb, var(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 10%, transparent)}.F1KBNa_mdPreviewBody .mdDel{background-color:color-mix(in srgb, var(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 12%, transparent)}.F1KBNa_mdPreviewBody .mdWordDel{background-color:color-mix(in srgb, var(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 34%, transparent);border-radius:2px;padding:0 1px}.F1KBNa_mdPreviewBody .mdWordAdd{background-color:color-mix(in srgb, var(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 34%, transparent);border-radius:2px;padding:0 1px}.F1KBNa_mdPreviewBody .mdDouble{flex-direction:column;width:100%;min-width:0;display:flex}.F1KBNa_mdPreviewBody .mdDoubleRow{align-items:flex-start;width:100%;min-width:0;display:flex}.F1KBNa_mdPreviewBody .mdDoubleCol{flex:1;min-width:0}.F1KBNa_mdPreviewBody .mdDoubleRule{background:var(--dsw-alias-border-l2);flex:none;align-self:stretch;width:1px;margin:0 12px}.F1KBNa_mdPreviewFallback{font-family:var(--dsw-font-markdown-code-block);color:var(--dsw-alias-label-tertiary);padding:12px 16px;font-size:12px;line-height:18px}.F1KBNa_mdPreviewBody{word-break:break-word;font-size:13px;line-height:20px}.F1KBNa_mdPreviewBody>:first-child{margin-top:0}.F1KBNa_mdPreviewBody>:last-child{margin-bottom:0}.F1KBNa_mdPreviewBody h1,.F1KBNa_mdPreviewBody h2,.F1KBNa_mdPreviewBody h3,.F1KBNa_mdPreviewBody h4,.F1KBNa_mdPreviewBody h5,.F1KBNa_mdPreviewBody h6{margin:16px 0 8px;font-weight:600;line-height:1.3}.F1KBNa_mdPreviewBody h1{font-size:22px}.F1KBNa_mdPreviewBody h2{font-size:19px}.F1KBNa_mdPreviewBody h3{font-size:16px}.F1KBNa_mdPreviewBody h4{font-size:15px}.F1KBNa_mdPreviewBody h5{font-size:14px}.F1KBNa_mdPreviewBody h6{font-size:13px}.F1KBNa_mdPreviewBody p{margin:8px 0}.F1KBNa_mdPreviewBody ul,.F1KBNa_mdPreviewBody ol{margin:8px 0;padding-left:22px}.F1KBNa_mdPreviewBody li{margin:2px 0}.F1KBNa_mdPreviewBody a{color:var(--dsw-alias-state-business-primary);text-decoration:none}.F1KBNa_mdPreviewBody a:hover{text-decoration:underline}.F1KBNa_mdPreviewBody code{font-family:var(--dsw-font-markdown-code-block);background:#9e9e9e40;border-radius:4px;padding:1px 5px;font-size:12.5px}.F1KBNa_mdPreviewBody pre{border:1px solid var(--dsw-alias-border-l1);font-family:var(--dsw-font-markdown-code-block);background:#9e9e9e40;border-radius:8px;margin:8px 0;padding:10px 12px;font-size:12.5px;line-height:18px;overflow:auto}.F1KBNa_mdPreviewBody pre code{background:0 0;padding:0}.F1KBNa_mdPreviewBody blockquote{border-left:3px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);margin:8px 0;padding:0 12px}.F1KBNa_mdPreviewBody hr{background:var(--dsw-alias-border-l1);border:none;height:1px;margin:16px 0}.F1KBNa_mdPreviewBody table{border-collapse:collapse;margin:8px 0}.F1KBNa_mdPreviewBody th,.F1KBNa_mdPreviewBody td{border:1px solid var(--dsw-alias-border-l1);padding:4px 10px}.F1KBNa_mdPreviewBody img{max-width:100%}.F1KBNa_mdPreviewBody .mdImageFallback{border:1px dashed var(--dsw-alias-border-l2);background:color-mix(in srgb, var(--dsw-alias-markdown-code-block) 45%, transparent);width:100%;min-height:120px;color:var(--dsw-alias-label-secondary);font-family:var(--dsw-font-markdown-code-block);text-align:center;white-space:pre-wrap;word-break:break-all;border-radius:4px;justify-content:center;align-items:center;margin:0 auto;padding:8px 12px;font-size:12px;line-height:16px;display:flex}.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);cursor:pointer;border-radius:8px;padding:0;position:relative}.F1KBNa_stepperButton:before,.F1KBNa_stepperButton:after{content:\"\";background:currentColor;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.F1KBNa_stepperButton:before{width:10px;height:1px}.F1KBNa_stepperButton:after{width:1px;height:10px;display:none}.F1KBNa_stepperButtonUp:after{display:block}.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(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 60%, var(--dsw-alias-label-primary))}.F1KBNa_delCount{color:color-mix(in srgb, var(--dsh-diff-del-color,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_divider{background:var(--dsw-alias-border-l1);align-self:stretch;width:1px;margin:2px 0}.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_searchMatch{background-color:#facc1542;border-radius:2px}.F1KBNa_searchMatchCurrent{background-color:#facc1599;border-radius:2px}.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_diffFlashFade;position:absolute;left:0;right:0}.F1KBNa_blockFlashShake{animation:.7s ease-out forwards F1KBNa_diffFlashShake}@keyframes F1KBNa_diffFlashFade{0%{opacity:1}to{opacity:0}}@keyframes F1KBNa_diffFlashShake{0%{opacity:1;transform:translateY(0)}10%{transform:translateY(1px)}20%{transform:translateY(-1px)}30%{transform:translateY(1px)}40%{transform:translateY(-1px)}50%{transform:translateY(1px)}60%{transform:translateY(-1px)}70%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(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%;font-size:calc(1em * var(--dsh-diff-font-scale,1));display:table}.F1KBNa_line{height:var(--dsh-diff-line-height,22px);line-height:var(--dsh-diff-line-height,22px);-webkit-user-select:none;user-select:none;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(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 12%, transparent)}.F1KBNa_add{background-color:color-mix(in srgb, var(--dsh-diff-add-color,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:var(--dsh-diff-line-height,22px)}.F1KBNa_subline{height:var(--dsh-diff-line-height,22px);line-height:var(--dsh-diff-line-height,22px);white-space:pre;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(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 12%, transparent)}.F1KBNa_splitLadd{background-color:color-mix(in srgb, var(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 10%, transparent)}.F1KBNa_splitRdel{background-color:color-mix(in srgb, var(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 12%, transparent)}.F1KBNa_splitRadd{background-color:color-mix(in srgb, var(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 10%, transparent)}.F1KBNa_intraDel{background-color:color-mix(in srgb, var(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 26%, transparent);text-decoration:line-through}.F1KBNa_intraAdd{background-color:color-mix(in srgb, var(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 24%, transparent)}";
17028
+ 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_settingsGroup{border-bottom:1px solid var(--dsw-alias-border-l2);margin-top:8px}.F1KBNa_settingsGroupHeader{width:100%;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:8px;padding:12px 0;display:flex}.F1KBNa_settingsGroupText{text-align:left;flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.F1KBNa_settingsGroupTitle{font-size:14px;font-weight:400;line-height:22px}.F1KBNa_settingsGroupDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}.F1KBNa_settingsGroupChevron{margin-left:auto;transition:transform .15s}.F1KBNa_settingsGroup[data-open] .F1KBNa_settingsGroupChevron{transform:rotate(180deg)}.F1KBNa_settingsGroup[data-open] .F1KBNa_settingsGroupHeader{border-bottom:1px solid var(--dsw-alias-border-l2)}.F1KBNa_settingsGroupBody{flex-direction:column;display:flex}.F1KBNa_settingsGroupBody .F1KBNa_settingsRow{padding-left:16px}.F1KBNa_settingsGroupBody .F1KBNa_settingsRow:last-child,.F1KBNa_settingsPage>.F1KBNa_settingsRow:last-child{border-bottom:none}.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_colorPicker{position:relative}.F1KBNa_colorPickerTrigger{background:var(--dsw-alias-bg-module-platform);width:120px;height:36px;font:inherit;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:18px;align-items:center;gap:8px;padding:0 8px;font-size:12px;line-height:18px;display:inline-flex}.F1KBNa_colorPickerTrigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_colorSwatch{border:1px solid var(--dsw-alias-border-l2);border-radius:50%;flex:none;width:24px;height:24px}.F1KBNa_colorValue{text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;flex:1;min-width:0;overflow:hidden}.F1KBNa_colorPickerChevron{flex:none}.F1KBNa_colorBackdrop{z-index:40;position:fixed;inset:0}.F1KBNa_colorPickerPopover{z-index:41;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);box-shadow:var(--dsw-shadow-lv2);border-radius:10px;padding:10px;position:absolute;top:calc(100% + 6px);right:0}.F1KBNa_colorPickerPanel{flex-direction:column;gap:8px;display:flex}.F1KBNa_colorPickerInputRow{align-items:center;gap:8px;display:flex}.F1KBNa_colorPickerPreview{border:1px solid var(--dsw-alias-border-l2);border-radius:6px;flex:none;width:22px;height:22px}.F1KBNa_colorPickerInput{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-module-platform);min-width:0;height:30px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;flex:1;padding:0 8px;font-size:12px;line-height:28px}.F1KBNa_colorPickerInput:focus{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-1px}.F1KBNa_colorSv{border:1px solid var(--dsw-alias-border-l1);cursor:crosshair;touch-action:none;border-radius:8px;height:140px;position:relative}.F1KBNa_colorSvCursor{pointer-events:none;border:2px solid #fff;border-radius:50%;width:14px;height:14px;position:absolute;transform:translate(-50%,-50%);box-shadow:0 0 0 1px #00000080}.F1KBNa_colorHue{border:1px solid var(--dsw-alias-border-l1);cursor:pointer;touch-action:none;border-radius:7px;height:14px;position:relative}.F1KBNa_colorHueCursor{pointer-events:none;border:2px solid #fff;border-radius:50%;width:16px;height:16px;position:absolute;top:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 1px #00000080}.F1KBNa_diffPreview{z-index:2;border:1px solid var(--dsw-alias-border-l1);font:var(--dsw-font-markdown-code-block);background:var(--dsw-alias-markdown-code-block);border-radius:8px;margin-bottom:8px;padding:8px;position:sticky;top:0;overflow:hidden}.F1KBNa_diffPreviewTitle{color:var(--dsw-alias-label-tertiary);margin-bottom:6px;font-family:inherit;font-size:12px;line-height:18px}.F1KBNa_diffPreviewScroll{height:132px;overflow-y:auto}.F1KBNa_mdPreviewWrap{flex:1;min-width:0;min-height:0;display:flex;position:relative}.F1KBNa_mdPreviewBody{min-width:0;min-height:0;color:var(--dsw-alias-label-primary);flex:1;padding:12px 16px;position:relative;overflow:auto}.F1KBNa_mdPreviewContent{width:100%;min-width:0;margin:0 auto}.F1KBNa_mdPreviewSingle{display:block}.F1KBNa_mdPreviewDouble{display:flex}.F1KBNa_mdPreviewBody .mdBlock{border-radius:4px;margin-bottom:12px;padding:2px 6px}.F1KBNa_mdPreviewBody .mdAdd{background-color:color-mix(in srgb, var(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 10%, transparent)}.F1KBNa_mdPreviewBody .mdDel{background-color:color-mix(in srgb, var(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 12%, transparent)}.F1KBNa_mdPreviewBody .mdWordDel{background-color:color-mix(in srgb, var(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 34%, transparent);border-radius:2px;padding:0 1px}.F1KBNa_mdPreviewBody .mdWordAdd{background-color:color-mix(in srgb, var(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 34%, transparent);border-radius:2px;padding:0 1px}.F1KBNa_mdPreviewBody .mdDouble{flex-direction:column;width:100%;min-width:0;display:flex}.F1KBNa_mdPreviewBody .mdDoubleRow{align-items:flex-start;width:100%;min-width:0;display:flex}.F1KBNa_mdPreviewBody .mdDoubleCol{flex:1;min-width:0}.F1KBNa_mdPreviewBody .mdDoubleRule{background:var(--dsw-alias-border-l2);flex:none;align-self:stretch;width:1px;margin:0 12px}.F1KBNa_mdPreviewFallback{font-family:var(--dsw-font-markdown-code-block);color:var(--dsw-alias-label-tertiary);padding:12px 16px;font-size:12px;line-height:18px}.F1KBNa_mdPreviewBody{word-break:break-word;font-size:13px;line-height:20px}.F1KBNa_mdPreviewBody>:first-child{margin-top:0}.F1KBNa_mdPreviewBody>:last-child{margin-bottom:0}.F1KBNa_mdPreviewBody h1,.F1KBNa_mdPreviewBody h2,.F1KBNa_mdPreviewBody h3,.F1KBNa_mdPreviewBody h4,.F1KBNa_mdPreviewBody h5,.F1KBNa_mdPreviewBody h6{margin:16px 0 8px;font-weight:600;line-height:1.3}.F1KBNa_mdPreviewBody h1{font-size:22px}.F1KBNa_mdPreviewBody h2{font-size:19px}.F1KBNa_mdPreviewBody h3{font-size:16px}.F1KBNa_mdPreviewBody h4{font-size:15px}.F1KBNa_mdPreviewBody h5{font-size:14px}.F1KBNa_mdPreviewBody h6{font-size:13px}.F1KBNa_mdPreviewBody p{margin:8px 0}.F1KBNa_mdPreviewBody ul,.F1KBNa_mdPreviewBody ol{margin:8px 0;padding-left:22px}.F1KBNa_mdPreviewBody li{margin:2px 0}.F1KBNa_mdPreviewBody a{color:var(--dsw-alias-state-business-primary);text-decoration:none}.F1KBNa_mdPreviewBody a:hover{text-decoration:underline}.F1KBNa_mdPreviewBody code{font-family:var(--dsw-font-markdown-code-block);background:#9e9e9e40;border-radius:4px;padding:1px 5px;font-size:12.5px}.F1KBNa_mdPreviewBody pre{border:1px solid var(--dsw-alias-border-l1);font-family:var(--dsw-font-markdown-code-block);background:#9e9e9e40;border-radius:8px;margin:8px 0;padding:10px 12px;font-size:12.5px;line-height:18px;overflow:auto}.F1KBNa_mdPreviewBody pre code{background:0 0;padding:0}.F1KBNa_mdPreviewBody blockquote{border-left:3px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);margin:8px 0;padding:0 12px}.F1KBNa_mdPreviewBody hr{background:var(--dsw-alias-border-l1);border:none;height:1px;margin:16px 0}.F1KBNa_mdPreviewBody table{border-collapse:collapse;margin:8px 0}.F1KBNa_mdPreviewBody th,.F1KBNa_mdPreviewBody td{border:1px solid var(--dsw-alias-border-l1);padding:4px 10px}.F1KBNa_mdPreviewBody img{max-width:100%}.F1KBNa_mdPreviewBody .mdImageFallback{border:1px dashed var(--dsw-alias-border-l2);background:color-mix(in srgb, var(--dsw-alias-markdown-code-block) 45%, transparent);width:100%;min-height:120px;color:var(--dsw-alias-label-secondary);font-family:var(--dsw-font-markdown-code-block);text-align:center;white-space:pre-wrap;word-break:break-all;border-radius:4px;justify-content:center;align-items:center;margin:0 auto;padding:8px 12px;font-size:12px;line-height:16px;display:flex}.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);cursor:pointer;border-radius:8px;padding:0;position:relative}.F1KBNa_stepperButton:before,.F1KBNa_stepperButton:after{content:\"\";background:currentColor;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.F1KBNa_stepperButton:before{width:10px;height:1px}.F1KBNa_stepperButton:after{width:1px;height:10px;display:none}.F1KBNa_stepperButtonUp:after{display:block}.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(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 60%, var(--dsw-alias-label-primary))}.F1KBNa_delCount{color:color-mix(in srgb, var(--dsh-diff-del-color,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_divider{background:var(--dsw-alias-border-l1);align-self:stretch;width:1px;margin:2px 0}.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_searchToggle{border:1px solid var(--dsw-alias-border-l1);min-height:25px;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border-radius:8px;justify-content:center;align-items:center;padding:4px 6px;display:inline-flex}.F1KBNa_searchToggle:hover{background:var(--dsw-alias-interactive-bg-hover)}.F1KBNa_searchToggleOn{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-state-business-primary)}.F1KBNa_searchMatch{background-color:#facc1542;border-radius:2px}.F1KBNa_searchMatchCurrent{background-color:#facc1599;border-radius:2px}.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_diffFlashFade;position:absolute;left:0;right:0}.F1KBNa_blockFlashShake{animation:.7s ease-out forwards F1KBNa_diffFlashShake}@keyframes F1KBNa_diffFlashFade{0%{opacity:1}to{opacity:0}}@keyframes F1KBNa_diffFlashShake{0%{opacity:1;transform:translateY(0)}10%{transform:translateY(1px)}20%{transform:translateY(-1px)}30%{transform:translateY(1px)}40%{transform:translateY(-1px)}50%{transform:translateY(1px)}60%{transform:translateY(-1px)}70%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(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%;font-size:calc(1em * var(--dsh-diff-font-scale,1));display:table}.F1KBNa_line{height:var(--dsh-diff-line-height,22px);line-height:var(--dsh-diff-line-height,22px);-webkit-user-select:none;user-select:none;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(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 12%, transparent)}.F1KBNa_add{background-color:color-mix(in srgb, var(--dsh-diff-add-color,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:var(--dsh-diff-line-height,22px)}.F1KBNa_subline{height:var(--dsh-diff-line-height,22px);line-height:var(--dsh-diff-line-height,22px);white-space:pre;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(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 12%, transparent)}.F1KBNa_splitLadd{background-color:color-mix(in srgb, var(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 10%, transparent)}.F1KBNa_splitRdel{background-color:color-mix(in srgb, var(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 12%, transparent)}.F1KBNa_splitRadd{background-color:color-mix(in srgb, var(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 10%, transparent)}.F1KBNa_intraDel{background-color:color-mix(in srgb, var(--dsh-diff-del-color,var(--dsw-alias-state-error-primary)) 26%, transparent);text-decoration:line-through}.F1KBNa_intraAdd{background-color:color-mix(in srgb, var(--dsh-diff-add-color,var(--dsw-alias-state-success-primary)) 24%, transparent)}";
16942
17029
  const tagId = "dsh-diff-approval/PendingPanel.module.css";
16943
17030
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
16944
17031
  const tag = document.createElement("style");
@@ -16948,160 +17035,162 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
16948
17035
  document.head.appendChild(tag);
16949
17036
  }
16950
17037
  var PendingPanel_module_css_default = {
16951
- "settingsGroupChevron": "F1KBNa_settingsGroupChevron",
16952
- "noteCentered": "F1KBNa_noteCentered",
16953
- "splitRadd": "F1KBNa_splitRadd",
16954
- "colorPickerPreview": "F1KBNa_colorPickerPreview",
16955
- "colorSv": "F1KBNa_colorSv",
16956
- "splitRdel": "F1KBNa_splitRdel",
16957
- "settingsGroupHeader": "F1KBNa_settingsGroupHeader",
16958
- "toggleOn": "F1KBNa_toggleOn",
16959
- "toggleThumb": "F1KBNa_toggleThumb",
16960
- "statusBar": "F1KBNa_statusBar",
16961
- "mdPreviewWrap": "F1KBNa_mdPreviewWrap",
16962
- "intraAdd": "F1KBNa_intraAdd",
16963
- "colorPickerInputRow": "F1KBNa_colorPickerInputRow",
16964
- "divider": "F1KBNa_divider",
16965
- "rowPath": "F1KBNa_rowPath",
16966
- "splitCol": "F1KBNa_splitCol",
16967
- "notice": "F1KBNa_notice",
16968
- "colorPickerChevron": "F1KBNa_colorPickerChevron",
16969
- "overviewMarker": "F1KBNa_overviewMarker",
16970
- "colorHueCursor": "F1KBNa_colorHueCursor",
16971
- "headerActions": "F1KBNa_headerActions",
16972
- "diffBodyWrap": "F1KBNa_diffBodyWrap",
16973
- "settingsPage": "F1KBNa_settingsPage",
17038
+ "blockFlashShake": "F1KBNa_blockFlashShake",
16974
17039
  "del": "F1KBNa_del",
16975
- "settingsSelector": "F1KBNa_settingsSelector",
16976
- "colorPickerInput": "F1KBNa_colorPickerInput",
16977
- "flexSpacer": "F1KBNa_flexSpacer",
16978
- "colorValue": "F1KBNa_colorValue",
16979
- "colorPickerPanel": "F1KBNa_colorPickerPanel",
16980
- "actionPrimary": "F1KBNa_actionPrimary",
16981
- "searchCount": "F1KBNa_searchCount",
16982
- "vSpacer": "F1KBNa_vSpacer",
16983
- "badge": "F1KBNa_badge",
17040
+ "noticeButton": "F1KBNa_noticeButton",
17041
+ "settingsGroupBody": "F1KBNa_settingsGroupBody",
16984
17042
  "colorSwatch": "F1KBNa_colorSwatch",
16985
- "badgeLabel": "F1KBNa_badgeLabel",
16986
- "settingsRowText": "F1KBNa_settingsRowText",
16987
- "stepperButtonUp": "F1KBNa_stepperButtonUp",
16988
- "header": "F1KBNa_header",
16989
- "settingsRowDesc": "F1KBNa_settingsRowDesc",
16990
- "actionQuietDisabled": "F1KBNa_actionQuietDisabled",
16991
- "splitRoot": "F1KBNa_splitRoot",
16992
- "diffFlashFade": "F1KBNa_diffFlashFade",
16993
- "blockActions": "F1KBNa_blockActions",
16994
- "mdPreviewSingle": "F1KBNa_mdPreviewSingle",
17043
+ "fullscreenBackdrop": "F1KBNa_fullscreenBackdrop",
17044
+ "confirmText": "F1KBNa_confirmText",
17045
+ "diffActions": "F1KBNa_diffActions",
17046
+ "splitLdel": "F1KBNa_splitLdel",
17047
+ "toggle": "F1KBNa_toggle",
17048
+ "importButton": "F1KBNa_importButton",
17049
+ "diffPreview": "F1KBNa_diffPreview",
17050
+ "delCount": "F1KBNa_delCount",
17051
+ "addCount": "F1KBNa_addCount",
17052
+ "settingsGroupChevron": "F1KBNa_settingsGroupChevron",
17053
+ "searchToggleOn": "F1KBNa_searchToggleOn",
17054
+ "settingsGroup": "F1KBNa_settingsGroup",
17055
+ "colorHue": "F1KBNa_colorHue",
17056
+ "searchCount": "F1KBNa_searchCount",
17057
+ "searchMatchCurrent": "F1KBNa_searchMatchCurrent",
16995
17058
  "lines": "F1KBNa_lines",
16996
- "mdPreviewFallback": "F1KBNa_mdPreviewFallback",
16997
- "divergedHint": "F1KBNa_divergedHint",
16998
- "badgeCount": "F1KBNa_badgeCount",
17059
+ "mdPreviewContent": "F1KBNa_mdPreviewContent",
17060
+ "rowMeta": "F1KBNa_rowMeta",
17061
+ "expandExpanded": "F1KBNa_expandExpanded",
17062
+ "listScroll": "F1KBNa_listScroll",
17063
+ "kindHint": "F1KBNa_kindHint",
16999
17064
  "fileList": "F1KBNa_fileList",
17000
- "noticeText": "F1KBNa_noticeText",
17001
- "action": "F1KBNa_action",
17002
- "diffStats": "F1KBNa_diffStats",
17065
+ "settingsGroupHeader": "F1KBNa_settingsGroupHeader",
17066
+ "divergedHint": "F1KBNa_divergedHint",
17067
+ "actionQuietDisabled": "F1KBNa_actionQuietDisabled",
17068
+ "colorPickerPopover": "F1KBNa_colorPickerPopover",
17003
17069
  "context": "F1KBNa_context",
17070
+ "confirmActions": "F1KBNa_confirmActions",
17071
+ "markerAdd": "F1KBNa_markerAdd",
17004
17072
  "searchInput": "F1KBNa_searchInput",
17005
- "rowFailed": "F1KBNa_rowFailed",
17006
- "detail": "F1KBNa_detail",
17007
- "hint": "F1KBNa_hint",
17073
+ "toggleOn": "F1KBNa_toggleOn",
17074
+ "header": "F1KBNa_header",
17075
+ "colorValue": "F1KBNa_colorValue",
17076
+ "split": "F1KBNa_split",
17077
+ "colorBackdrop": "F1KBNa_colorBackdrop",
17078
+ "settingsRowTitle": "F1KBNa_settingsRowTitle",
17079
+ "diffPath": "F1KBNa_diffPath",
17080
+ "statusBar": "F1KBNa_statusBar",
17008
17081
  "group": "F1KBNa_group",
17009
- "rowMeta": "F1KBNa_rowMeta",
17010
- "expand": "F1KBNa_expand",
17011
- "searchMatch": "F1KBNa_searchMatch",
17012
- "markerDel": "F1KBNa_markerDel",
17013
- "diffPreviewScroll": "F1KBNa_diffPreviewScroll",
17014
- "langSelect": "F1KBNa_langSelect",
17015
- "settingsGroupBody": "F1KBNa_settingsGroupBody",
17016
- "delCount": "F1KBNa_delCount",
17017
- "listScroll": "F1KBNa_listScroll",
17082
+ "colorSv": "F1KBNa_colorSv",
17083
+ "diffFlashFade": "F1KBNa_diffFlashFade",
17084
+ "detailEmpty": "F1KBNa_detailEmpty",
17085
+ "confirmCard": "F1KBNa_confirmCard",
17086
+ "badge": "F1KBNa_badge",
17087
+ "splitRdel": "F1KBNa_splitRdel",
17018
17088
  "line": "F1KBNa_line",
17019
- "actionError": "F1KBNa_actionError",
17020
- "splitCols": "F1KBNa_splitCols",
17021
- "toggle": "F1KBNa_toggle",
17022
- "confirmBackdrop": "F1KBNa_confirmBackdrop",
17023
- "kindHint": "F1KBNa_kindHint",
17024
- "states": "F1KBNa_states",
17025
- "add": "F1KBNa_add",
17026
- "readError": "F1KBNa_readError",
17027
- "row": "F1KBNa_row",
17028
- "statusAction": "F1KBNa_statusAction",
17029
- "diffBodySplit": "F1KBNa_diffBodySplit",
17089
+ "diffBody": "F1KBNa_diffBody",
17090
+ "stepperValue": "F1KBNa_stepperValue",
17091
+ "stepperButton": "F1KBNa_stepperButton",
17092
+ "settingsSelector": "F1KBNa_settingsSelector",
17093
+ "colorHueCursor": "F1KBNa_colorHueCursor",
17094
+ "badgeLabel": "F1KBNa_badgeLabel",
17030
17095
  "panel": "F1KBNa_panel",
17031
- "colorPicker": "F1KBNa_colorPicker",
17032
- "searchBar": "F1KBNa_searchBar",
17096
+ "diffPreviewScroll": "F1KBNa_diffPreviewScroll",
17097
+ "fileListFloat": "F1KBNa_fileListFloat",
17033
17098
  "note": "F1KBNa_note",
17034
- "settingsGroupDesc": "F1KBNa_settingsGroupDesc",
17035
- "subline": "F1KBNa_subline",
17036
- "wrapActive": "F1KBNa_wrapActive",
17037
- "settingsGroupText": "F1KBNa_settingsGroupText",
17038
- "stepperValue": "F1KBNa_stepperValue",
17039
- "diffPreview": "F1KBNa_diffPreview",
17040
- "detailEmpty": "F1KBNa_detailEmpty",
17041
- "confirmCard": "F1KBNa_confirmCard",
17042
- "emptyState": "F1KBNa_emptyState",
17043
- "settingsSelectorChevron": "F1KBNa_settingsSelectorChevron",
17044
- "settingsRowTitle": "F1KBNa_settingsRowTitle",
17045
- "resizeHandle": "F1KBNa_resizeHandle",
17046
- "colorBackdrop": "F1KBNa_colorBackdrop",
17099
+ "diff": "F1KBNa_diff",
17100
+ "mdPreviewWrap": "F1KBNa_mdPreviewWrap",
17101
+ "blockFlash": "F1KBNa_blockFlash",
17102
+ "vSpacer": "F1KBNa_vSpacer",
17103
+ "hint": "F1KBNa_hint",
17104
+ "settingsRowDesc": "F1KBNa_settingsRowDesc",
17105
+ "gutter": "F1KBNa_gutter",
17106
+ "intraAdd": "F1KBNa_intraAdd",
17047
17107
  "colorPickerTrigger": "F1KBNa_colorPickerTrigger",
17048
- "confirmText": "F1KBNa_confirmText",
17108
+ "splitCol": "F1KBNa_splitCol",
17109
+ "resizeHandle": "F1KBNa_resizeHandle",
17110
+ "detail": "F1KBNa_detail",
17111
+ "diffBodySplit": "F1KBNa_diffBodySplit",
17049
17112
  "missing": "F1KBNa_missing",
17050
- "splitLadd": "F1KBNa_splitLadd",
17051
- "kindTag": "F1KBNa_kindTag",
17052
- "colorPickerPopover": "F1KBNa_colorPickerPopover",
17053
- "split": "F1KBNa_split",
17054
- "colorHue": "F1KBNa_colorHue",
17055
- "importNote": "F1KBNa_importNote",
17056
- "rowHead": "F1KBNa_rowHead",
17057
- "splitLdel": "F1KBNa_splitLdel",
17113
+ "bulkActions": "F1KBNa_bulkActions",
17114
+ "close": "F1KBNa_close",
17115
+ "colorPickerChevron": "F1KBNa_colorPickerChevron",
17116
+ "diffStats": "F1KBNa_diffStats",
17117
+ "badgeCount": "F1KBNa_badgeCount",
17118
+ "colorPickerPreview": "F1KBNa_colorPickerPreview",
17119
+ "divider": "F1KBNa_divider",
17058
17120
  "stepper": "F1KBNa_stepper",
17059
- "mdPreviewDouble": "F1KBNa_mdPreviewDouble",
17060
- "gutter": "F1KBNa_gutter",
17061
- "diffHeader": "F1KBNa_diffHeader",
17062
- "blockFlash": "F1KBNa_blockFlash",
17121
+ "splitDivider": "F1KBNa_splitDivider",
17122
+ "readError": "F1KBNa_readError",
17123
+ "title": "F1KBNa_title",
17124
+ "overviewMarker": "F1KBNa_overviewMarker",
17125
+ "statusAction": "F1KBNa_statusAction",
17126
+ "mdPreviewFallback": "F1KBNa_mdPreviewFallback",
17063
17127
  "code": "F1KBNa_code",
17064
- "footerButtons": "F1KBNa_footerButtons",
17128
+ "settingsRowText": "F1KBNa_settingsRowText",
17129
+ "splitLadd": "F1KBNa_splitLadd",
17130
+ "toggleThumb": "F1KBNa_toggleThumb",
17131
+ "missingHint": "F1KBNa_missingHint",
17065
17132
  "blockPosition": "F1KBNa_blockPosition",
17066
- "diffFlashShake": "F1KBNa_diffFlashShake",
17067
- "diffPreviewTitle": "F1KBNa_diffPreviewTitle",
17068
- "fileListFloat": "F1KBNa_fileListFloat",
17069
- "rows": "F1KBNa_rows",
17070
- "addCount": "F1KBNa_addCount",
17071
- "expandExpanded": "F1KBNa_expandExpanded",
17072
- "diffBody": "F1KBNa_diffBody",
17073
- "colorSvCursor": "F1KBNa_colorSvCursor",
17074
- "langLabel": "F1KBNa_langLabel",
17075
- "blockFlashShake": "F1KBNa_blockFlashShake",
17076
- "searchMatchCurrent": "F1KBNa_searchMatchCurrent",
17077
- "overviewRuler": "F1KBNa_overviewRuler",
17133
+ "settingsSelectorChevron": "F1KBNa_settingsSelectorChevron",
17134
+ "settingsGroupText": "F1KBNa_settingsGroupText",
17135
+ "colorPickerInputRow": "F1KBNa_colorPickerInputRow",
17136
+ "diffBodyWrap": "F1KBNa_diffBodyWrap",
17078
17137
  "rail": "F1KBNa_rail",
17138
+ "colorPicker": "F1KBNa_colorPicker",
17079
17139
  "mdPreviewBody": "F1KBNa_mdPreviewBody",
17140
+ "action": "F1KBNa_action",
17141
+ "expand": "F1KBNa_expand",
17142
+ "markerDel": "F1KBNa_markerDel",
17143
+ "splitHScrollFill": "F1KBNa_splitHScrollFill",
17144
+ "langLabel": "F1KBNa_langLabel",
17145
+ "importNote": "F1KBNa_importNote",
17080
17146
  "wrap": "F1KBNa_wrap",
17147
+ "subline": "F1KBNa_subline",
17148
+ "colorPickerInput": "F1KBNa_colorPickerInput",
17149
+ "colorPickerPanel": "F1KBNa_colorPickerPanel",
17150
+ "mdPreviewDouble": "F1KBNa_mdPreviewDouble",
17151
+ "settingsRow": "F1KBNa_settingsRow",
17152
+ "noteCentered": "F1KBNa_noteCentered",
17153
+ "add": "F1KBNa_add",
17154
+ "notice": "F1KBNa_notice",
17155
+ "emptyState": "F1KBNa_emptyState",
17156
+ "kindTag": "F1KBNa_kindTag",
17157
+ "diffFlashShake": "F1KBNa_diffFlashShake",
17158
+ "splitCols": "F1KBNa_splitCols",
17159
+ "searchBar": "F1KBNa_searchBar",
17160
+ "confirmBackdrop": "F1KBNa_confirmBackdrop",
17161
+ "searchToggle": "F1KBNa_searchToggle",
17162
+ "noticeText": "F1KBNa_noticeText",
17163
+ "splitRoot": "F1KBNa_splitRoot",
17081
17164
  "intraDel": "F1KBNa_intraDel",
17082
- "bulkActions": "F1KBNa_bulkActions",
17083
- "stepperButton": "F1KBNa_stepperButton",
17084
- "splitHScrollFill": "F1KBNa_splitHScrollFill",
17085
- "splitHScroll": "F1KBNa_splitHScroll",
17165
+ "rows": "F1KBNa_rows",
17166
+ "mdPreviewSingle": "F1KBNa_mdPreviewSingle",
17167
+ "colorSvCursor": "F1KBNa_colorSvCursor",
17168
+ "wrapActive": "F1KBNa_wrapActive",
17169
+ "states": "F1KBNa_states",
17086
17170
  "settingsGroupTitle": "F1KBNa_settingsGroupTitle",
17087
- "iconAction": "F1KBNa_iconAction",
17088
- "close": "F1KBNa_close",
17089
- "importButton": "F1KBNa_importButton",
17090
- "title": "F1KBNa_title",
17091
- "fullscreenBackdrop": "F1KBNa_fullscreenBackdrop",
17092
- "settingsRow": "F1KBNa_settingsRow",
17093
- "confirmActions": "F1KBNa_confirmActions",
17171
+ "footerButtons": "F1KBNa_footerButtons",
17172
+ "rowFailed": "F1KBNa_rowFailed",
17173
+ "searchMatch": "F1KBNa_searchMatch",
17174
+ "splitHScroll": "F1KBNa_splitHScroll",
17175
+ "actionPrimary": "F1KBNa_actionPrimary",
17176
+ "diffHeader": "F1KBNa_diffHeader",
17177
+ "settingsGroupDesc": "F1KBNa_settingsGroupDesc",
17178
+ "splitRadd": "F1KBNa_splitRadd",
17179
+ "settingsPage": "F1KBNa_settingsPage",
17180
+ "stepperButtonUp": "F1KBNa_stepperButtonUp",
17181
+ "rowHead": "F1KBNa_rowHead",
17094
17182
  "splitHScrollRow": "F1KBNa_splitHScrollRow",
17095
- "mdPreviewContent": "F1KBNa_mdPreviewContent",
17183
+ "diffPreviewTitle": "F1KBNa_diffPreviewTitle",
17184
+ "blockActions": "F1KBNa_blockActions",
17185
+ "rowPath": "F1KBNa_rowPath",
17186
+ "actionError": "F1KBNa_actionError",
17187
+ "flexSpacer": "F1KBNa_flexSpacer",
17188
+ "iconAction": "F1KBNa_iconAction",
17189
+ "overviewRuler": "F1KBNa_overviewRuler",
17190
+ "langSelect": "F1KBNa_langSelect",
17191
+ "headerActions": "F1KBNa_headerActions",
17096
17192
  "layer": "F1KBNa_layer",
17097
- "missingHint": "F1KBNa_missingHint",
17098
- "diff": "F1KBNa_diff",
17099
- "diffPath": "F1KBNa_diffPath",
17100
- "markerAdd": "F1KBNa_markerAdd",
17101
- "noticeButton": "F1KBNa_noticeButton",
17102
- "splitDivider": "F1KBNa_splitDivider",
17103
- "diffActions": "F1KBNa_diffActions",
17104
- "settingsGroup": "F1KBNa_settingsGroup"
17193
+ "row": "F1KBNa_row"
17105
17194
  };
17106
17195
  //#endregion
17107
17196
  //#region lib/types/client/PendingPanel.js
@@ -17431,6 +17520,29 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
17431
17520
  Array.from(document.querySelectorAll("button")).find((button) => button.textContent?.trim() === sectionLabel)?.click();
17432
17521
  });
17433
17522
  }
17523
+ /**
17524
+ * Search narrowing glyphs, taken from VS Code's Codicons so the two find-widget
17525
+ * toggles read exactly as they do in that editor: `case-sensitive` (an upper- and
17526
+ * lower-case letter pair) and `whole-word` (the same letter pair over a bar that
17527
+ * marks the word boundary). Inline SVG because the icon library ships neither.
17528
+ * @param props.kind - which glyph to draw.
17529
+ * @returns the 16px-grid glyph.
17530
+ */
17531
+ function SearchOptionIcon({ kind }) {
17532
+ return (0, react_jsx_runtime.jsx)("svg", {
17533
+ width: 16,
17534
+ height: 16,
17535
+ viewBox: "0 0 16 16",
17536
+ fill: "none",
17537
+ xmlns: "http://www.w3.org/2000/svg",
17538
+ children: (0, react_jsx_runtime.jsx)("path", {
17539
+ fill: "currentColor",
17540
+ fillRule: "evenodd",
17541
+ clipRule: "evenodd",
17542
+ d: kind === "case" ? `M4.02602 3.34176C4.16218 2.93404 4.83818 2.93398 4.97426 3.34176L6.97426 9.34274C6.97526 9.34674 6.97817 9.35544 6.97817 9.35544L7.97426 12.3427C8.06126 12.6047 7.91984 12.8875 7.65786 12.9756C7.60486 12.9926 7.55165 13.0009 7.49965 13.0009C7.29082 13.0008 7.09602 12.868 7.02602 12.6591L6.14028 10.0009H2.86L1.97426 12.6591C1.88728 12.919 1.60634 13.0634 1.34243 12.9746C1.08043 12.8866 0.93902 12.6038 1.02602 12.3418L2.02211 9.35544C2.02311 9.35144 2.02602 9.34274 2.02602 9.34274L4.02602 3.34176ZM3.19399 8.99997H5.80629L4.49965 5.08102L3.19399 8.99997ZM11.8581 6.66794C13.165 6.73296 13.9427 7.48427 13.9967 8.69626L13.9997 8.83297V12.5078C13.9957 12.7568 13.809 12.9621 13.568 12.9951L13.4997 13C13.2469 12.9998 13.0376 12.8121 13.0045 12.5683L12.9997 12.5V12.4297C12.3407 12.8066 11.7316 13 11.1666 13C9.94081 12.9998 8.99965 12.1369 8.99965 10.833C8.99967 9.68299 9.79211 8.82889 11.1061 8.66989C11.7279 8.59493 12.3589 8.64164 12.9987 8.80954C12.9915 8.07194 12.6279 7.70704 11.8082 7.66598C11.1672 7.63398 10.7158 7.72415 10.4518 7.90915C10.2258 8.06799 9.91347 8.01301 9.75551 7.78708C9.59671 7.56115 9.65178 7.24878 9.87758 7.09079C10.3165 6.78283 10.9138 6.64715 11.6666 6.6611L11.8581 6.66794ZM12.7965 9.8154C12.2587 9.66749 11.7361 9.62551 11.2262 9.68747C10.4042 9.78747 9.99868 10.2244 9.99868 10.8574C9.99884 11.5881 10.474 12.0242 11.1657 12.0244C11.6196 12.0244 12.1777 11.8137 12.8336 11.3818L12.9987 11.2695V9.87594L12.7965 9.8154Z` : `M4.8584 5.6709C6.16516 5.73603 6.94308 6.48734 6.99707 7.69922L7 7.83594V11.5107C6.996 11.7596 6.80919 11.9649 6.56836 11.998L6.5 12.0029C6.24709 12.0029 6.038 11.8152 6.00488 11.5713L6 11.5029V11.4326C5.341 11.8096 4.73199 12.0029 4.16699 12.0029C2.941 12.0029 2 11.1399 2 9.83594C2.00003 8.68597 2.79247 7.83185 4.10645 7.67285C4.7283 7.59793 5.35918 7.64552 5.99902 7.81348C5.99202 7.07548 5.62762 6.70995 4.80762 6.66895C4.16686 6.637 3.7161 6.72717 3.45215 6.91211C3.22615 7.07111 2.91386 7.01604 2.75586 6.79004C2.5969 6.56404 2.65194 6.25174 2.87793 6.09375C3.31692 5.78579 3.91404 5.65006 4.66699 5.66406L4.8584 5.6709ZM5.79688 8.81836C5.25888 8.67037 4.73558 8.62843 4.22559 8.69043C3.40389 8.79054 2.99902 9.22747 2.99902 9.86035C2.99917 10.5911 3.47413 11.0273 4.16602 11.0273C4.62001 11.0273 5.17799 10.8168 5.83398 10.3848L5.99902 10.2725V8.87891L5.79688 8.81836ZM9.55078 2.00586C9.78578 2.02986 9.97307 2.21715 9.99707 2.45215C10 2.46907 10 2.48601 10 2.50293V6.60254C10.418 6.22566 10.9371 6.00293 11.5 6.00293C12.881 6.00293 14 7.34596 14 9.00293C14 10.6599 12.881 12.0029 11.5 12.0029C10.9371 12.0029 10.418 11.7802 10 11.4033V11.5029C10 11.7619 9.80278 11.974 9.55078 12C9.53385 12.003 9.51693 12.0029 9.5 12.0029C9.224 12.0029 9 11.7789 9 11.5029V2.50293C9 2.486 9.00095 2.46907 9.00293 2.45215C9.02793 2.20015 9.241 2.00293 9.5 2.00293C9.51692 2.00293 9.53386 2.00388 9.55078 2.00586ZM11.4355 7.00391C11.0307 7.03208 10.5769 7.31545 10.29 7.82227C10.1232 8.12611 10.018 8.49479 10.002 8.89453C9.99995 8.92952 10 8.96597 10 9.00195C10 9.03795 10.001 9.07438 10.002 9.10938C10.018 9.50814 10.1222 9.87582 10.2891 10.1797C10.576 10.6875 11.0307 10.9728 11.4355 11C11.4565 11.002 11.478 11.002 11.5 11.002C11.522 11.002 11.5435 11.001 11.5645 11C11.9693 10.9728 12.424 10.6875 12.7109 10.1797C12.8778 9.87582 12.982 9.50814 12.998 9.10938C13 9.07438 13 9.03795 13 9.00195C13 8.96597 12.999 8.92952 12.998 8.89453C12.982 8.49479 12.8768 8.12611 12.71 7.82227C12.4231 7.31545 11.9693 7.03109 11.5645 7.00391C11.5435 7.00191 11.522 7.00195 11.5 7.00195C11.478 7.00195 11.4565 7.00291 11.4355 7.00391ZM15.5 12.5C15.776 12.5 16 12.724 16 13V13.5C16 14.327 15.327 15 14.5 15H1.5C0.673 15 0 14.327 0 13.5V13C0 12.724 0.224 12.5 0.5 12.5C0.776 12.5 1 12.724 1 13V13.5C1 13.775 1.224 14 1.5 14H14.5C14.776 14 15 13.775 15 13.5V13C15 12.724 15.224 12.5 15.5 12.5Z`
17543
+ })
17544
+ });
17545
+ }
17434
17546
  /** The diff body's row class per line kind. */
17435
17547
  const ROW_CLASS = {
17436
17548
  context: PendingPanel_module_css_default.context,
@@ -17509,27 +17621,13 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
17509
17621
  }, i);
17510
17622
  });
17511
17623
  }
17512
- /** Character ranges of each case-insensitive occurrence of `query` in `text`. */
17513
- function matchRangesOf(text, query) {
17514
- if (query === "") return [];
17515
- const lower = text.toLowerCase();
17516
- const q = query.toLowerCase();
17517
- const out = [];
17518
- let from = 0;
17519
- for (;;) {
17520
- const at = lower.indexOf(q, from);
17521
- if (at === -1) return out;
17522
- out.push([at, at + query.length]);
17523
- from = at + query.length;
17524
- }
17525
- }
17526
17624
  /** Render `text[segStart, segEnd)` with every `query` match wrapped in a search
17527
17625
  * highlight, keeping the syntax highlight and intra-line chips on the non-match
17528
17626
  * parts. When no match is present it renders exactly as before (syntax / intra /
17529
17627
  * plain). `segStart`/`segEnd` let the caller render a wrapped sub-line range. */
17530
- function textWithSearch(text, runs, intra, query, segStart = 0, segEnd = text.length, current = false) {
17628
+ function textWithSearch(text, runs, intra, options, query, segStart = 0, segEnd = text.length, current = false) {
17531
17629
  const segText = text.slice(segStart, segEnd);
17532
- const ranges = matchRangesOf(segText, query);
17630
+ const ranges = matchRangesOf(segText, query, options);
17533
17631
  if (ranges.length === 0) return intra !== void 0 && intra.length > 0 ? renderIntra(runs, intra, segStart, segEnd) : runs !== void 0 && runs.length > 0 ? clipRuns(runs, segStart, segEnd) : segText === "" ? "\xA0" : segText;
17534
17632
  const nodes = [];
17535
17633
  const push = (absStart, absEnd, isMatch) => {
@@ -17556,6 +17654,96 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
17556
17654
  if (cursor < segEnd) push(cursor, segEnd, false);
17557
17655
  return nodes;
17558
17656
  }
17657
+ /** Arrow keys render as arrows in a tooltip hint (`Ctrl+↑`, not `Ctrl+ArrowUp`). */
17658
+ const CHORD_KEY_GLYPHS = {
17659
+ ArrowUp: "↑",
17660
+ ArrowDown: "↓",
17661
+ ArrowLeft: "←",
17662
+ ArrowRight: "→"
17663
+ };
17664
+ /**
17665
+ * A tooltip label with the action's configured chord appended. The hint states
17666
+ * the binding the user actually has — including one rebound in Settings — rather
17667
+ * than a default baked into the label.
17668
+ * @param label - the translated action label.
17669
+ * @param action - the keybinding action id (see `DEFAULT_KEYBINDINGS`).
17670
+ * @returns the label, with ` (chord)` appended when one is configured.
17671
+ */
17672
+ function withChord(label, action) {
17673
+ const chord = keybindingOf(action);
17674
+ if (chord === "") return label;
17675
+ return `${label} (${chord.split("+").map((part) => CHORD_KEY_GLYPHS[part] ?? part).join("+")})`;
17676
+ }
17677
+ /**
17678
+ * Whether a key event's target is one of the panel's search query boxes. The
17679
+ * bar's own chords (step, narrow) are scoped this way: the caret has to be in
17680
+ * the box, so an open bar is not enough — the same chord must stay free for
17681
+ * whatever else happens to have focus (the chat composer above all), and a mouse
17682
+ * click on a bar button hands the focus straight back to the box.
17683
+ * @param event - the keydown event.
17684
+ * @returns whether the event came from a search query box.
17685
+ */
17686
+ function isSearchInputEvent(event) {
17687
+ const target = event.target;
17688
+ return target instanceof HTMLInputElement && target.hasAttribute("data-diff-search-input");
17689
+ }
17690
+ /**
17691
+ * Whether a key event came from inside the plugin's own panel. Esc is split along
17692
+ * that line: a press inside the panel is the panel's to dismiss (its search bar
17693
+ * first, otherwise the panel itself), while anything outside it — the chat
17694
+ * composer above all — dismisses the panel and keeps its own Esc besides.
17695
+ * @param event - the keydown event.
17696
+ * @returns whether the event came from inside the panel.
17697
+ */
17698
+ function isInPanelEvent(event) {
17699
+ const target = event.target;
17700
+ return target instanceof Element && target.closest("[data-diff-approval-panel]") !== null;
17701
+ }
17702
+ /**
17703
+ * Whether a key event came from a text field that owns its own keys (`Esc`,
17704
+ * cursor moves). The chat composer is the one that matters: the panel leaves it
17705
+ * alone even while its own search bar is open.
17706
+ * @param event - the keydown event.
17707
+ * @returns whether the event came from a text field.
17708
+ */
17709
+ function isTextFieldEvent(event) {
17710
+ const target = event.target;
17711
+ return target instanceof Element && target.closest("input, textarea, [contenteditable=\"true\"]") !== null;
17712
+ }
17713
+ /**
17714
+ * The in-file search's narrowing toggles. The persisted preference is the
17715
+ * source of truth, so the choice survives a reopen and the two views cannot
17716
+ * disagree: each bar owns one of these, and it re-reads the stored flags with
17717
+ * {@link sync} whenever its bar opens. The options object is memoized so the
17718
+ * memoized rows only re-render when a toggle changes.
17719
+ * @returns the options, their current values, the two toggles, and the re-read.
17720
+ */
17721
+ function useSearchOptions() {
17722
+ const [caseSensitive, setCase] = (0, react.useState)(searchCaseSensitive);
17723
+ const [wholeWord, setWord] = (0, react.useState)(searchWholeWord);
17724
+ return {
17725
+ options: (0, react.useMemo)(() => ({
17726
+ caseSensitive,
17727
+ wholeWord
17728
+ }), [caseSensitive, wholeWord]),
17729
+ caseSensitive,
17730
+ wholeWord,
17731
+ toggleCase: (0, react.useCallback)(() => {
17732
+ const next = !searchCaseSensitive();
17733
+ setSearchCaseSensitive(next);
17734
+ setCase(next);
17735
+ }, []),
17736
+ toggleWord: (0, react.useCallback)(() => {
17737
+ const next = !searchWholeWord();
17738
+ setSearchWholeWord(next);
17739
+ setWord(next);
17740
+ }, []),
17741
+ sync: (0, react.useCallback)(() => {
17742
+ setCase(searchCaseSensitive());
17743
+ setWord(searchWholeWord());
17744
+ }, [])
17745
+ };
17746
+ }
17559
17747
  /**
17560
17748
  * One rendered diff row, memoized so a poll or an unrelated state change
17561
17749
  * does not re-render rows whose content, highlight, and focus are unchanged.
@@ -17564,18 +17752,18 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
17564
17752
  * is `wrappedLines.length * 22` by construction.
17565
17753
  */
17566
17754
  const DiffRow = (0, react.memo)(function DiffRow(props) {
17567
- const { index, row, runs, focused, searchHit, searchCurrent, searchQuery, onRowHover, wrappedLines } = props;
17755
+ const { index, row, runs, focused, searchHit, searchCurrent, searchQuery, searchOptions, onRowHover, wrappedLines } = props;
17568
17756
  const lineNumber = row.kind === "del" ? row.oldLine : row.newLine;
17569
17757
  const sideRuns = row.kind === "del" ? runs?.oldRuns : runs?.newRuns;
17570
17758
  const lineRuns = lineNumber === void 0 ? void 0 : sideRuns?.[lineNumber - 1];
17571
17759
  let code;
17572
- if (wrappedLines === void 0) code = textWithSearch(row.text, lineRuns, void 0, searchQuery, 0, row.text.length, searchCurrent);
17760
+ if (wrappedLines === void 0) code = textWithSearch(row.text, lineRuns, void 0, searchOptions, searchQuery, 0, row.text.length, searchCurrent);
17573
17761
  else {
17574
17762
  let offset = 0;
17575
17763
  code = wrappedLines.map((line, lineIndex) => {
17576
17764
  const start = offset;
17577
17765
  offset += line.length;
17578
- const content = textWithSearch(row.text, lineRuns, void 0, searchQuery, start, offset, searchCurrent);
17766
+ const content = textWithSearch(row.text, lineRuns, void 0, searchOptions, searchQuery, start, offset, searchCurrent);
17579
17767
  return (0, react_jsx_runtime.jsx)("div", {
17580
17768
  className: PendingPanel_module_css_default.subline,
17581
17769
  children: content
@@ -17695,23 +17883,24 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
17695
17883
  }
17696
17884
  return block.oldStart <= oldMin && block.oldEnd >= oldMax && block.newStart <= newMin && block.newEnd >= newMax;
17697
17885
  }
17698
- /** Row indices whose text contains `query` (case-insensitive); empty for ''. */
17699
- function matchingRows(rows, query) {
17886
+ /** Row indices whose text matches `query` under the options; empty for ''. Counted
17887
+ * through the same matcher the highlights use, so the tally can never disagree
17888
+ * with what is drawn. */
17889
+ function matchingRows(rows, query, options) {
17700
17890
  if (query === "") return [];
17701
- const lower = query.toLowerCase();
17702
17891
  const out = [];
17703
- for (let i = 0; i < rows.length; i++) if (rows[i].text.toLowerCase().includes(lower)) out.push(i);
17892
+ for (let i = 0; i < rows.length; i++) if (matchRangesOf(rows[i].text, query, options).length > 0) out.push(i);
17704
17893
  return out;
17705
17894
  }
17706
17895
  /** One side's line-content for the split view: the highlighted runs or plain text. */
17707
- function splitSideContent(side, wrapped, runs, intra, query, current) {
17896
+ function splitSideContent(side, wrapped, runs, intra, options, query, current) {
17708
17897
  if (side === void 0) return "";
17709
- if (wrapped === void 0) return textWithSearch(side.text, runs, intra, query, 0, side.text.length, current);
17898
+ if (wrapped === void 0) return textWithSearch(side.text, runs, intra, options, query, 0, side.text.length, current);
17710
17899
  let offset = 0;
17711
17900
  return wrapped.map((line, i) => {
17712
17901
  const start = offset;
17713
17902
  offset += line.length;
17714
- const content = textWithSearch(side.text, runs, intra, query, start, offset, current);
17903
+ const content = textWithSearch(side.text, runs, intra, options, query, start, offset, current);
17715
17904
  return (0, react_jsx_runtime.jsx)("div", {
17716
17905
  className: PendingPanel_module_css_default.subline,
17717
17906
  children: content
@@ -17727,7 +17916,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
17727
17916
  * one side is longer. The gutter and code are top-aligned so sub-lines line up
17728
17917
  * across the divider.
17729
17918
  */
17730
- function SplitSideRow({ index, side, wrapped, runs, kind, isLeft, height, focused, searchHit, searchCurrent, searchQuery, onHover, intra }) {
17919
+ function SplitSideRow({ index, side, wrapped, runs, kind, isLeft, height, focused, searchHit, searchCurrent, searchQuery, searchOptions, onHover, intra }) {
17731
17920
  const tint = isLeft ? kind === "del" || kind === "replace" ? PendingPanel_module_css_default.splitLdel : "" : kind === "add" || kind === "replace" ? PendingPanel_module_css_default.splitRadd : "";
17732
17921
  return (0, react_jsx_runtime.jsxs)("div", {
17733
17922
  className: PendingPanel_module_css_default.line,
@@ -17746,7 +17935,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
17746
17935
  className: `${PendingPanel_module_css_default.code} ${tint}`,
17747
17936
  "data-diff-code": true,
17748
17937
  "data-diff-code-side": isLeft ? "left" : "right",
17749
- children: splitSideContent(side, wrapped, runs, intra, searchQuery, searchCurrent)
17938
+ children: splitSideContent(side, wrapped, runs, intra, searchOptions, searchQuery, searchCurrent)
17750
17939
  })]
17751
17940
  });
17752
17941
  }
@@ -17791,6 +17980,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
17791
17980
  });
17792
17981
  const [searchOpen, setSearchOpen] = (0, react.useState)(false);
17793
17982
  const [searchQuery, setSearchQuery] = (0, react.useState)("");
17983
+ const search = useSearchOptions();
17794
17984
  const [searchIndex, setSearchIndex] = (0, react.useState)(0);
17795
17985
  const searchInputRef = (0, react.useRef)(null);
17796
17986
  (0, react.useEffect)(() => {
@@ -17916,14 +18106,43 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
17916
18106
  if (strip === null || col === null) return;
17917
18107
  col.scrollLeft = strip.scrollLeft;
17918
18108
  }, []);
17919
- const searchMatches = (0, react.useMemo)(() => searchPairs(pairs, searchQuery), [pairs, searchQuery]);
18109
+ const searchMatches = (0, react.useMemo)(() => searchPairs(pairs, searchQuery, search.options), [
18110
+ pairs,
18111
+ searchQuery,
18112
+ search.options
18113
+ ]);
17920
18114
  const searchHitSet = (0, react.useMemo)(() => new Set(searchMatches), [searchMatches]);
17921
18115
  const currentSearchPair = searchMatches.length === 0 ? void 0 : searchMatches[searchIndex % searchMatches.length];
17922
18116
  const closeSearch = () => {
18117
+ if (!searchOpen) return false;
17923
18118
  setSearchOpen(false);
17924
18119
  setSearchQuery("");
17925
18120
  setSearchIndex(0);
17926
18121
  bodyRef.current?.focus();
18122
+ return true;
18123
+ };
18124
+ /** Run one bar control's action, then hand the focus back to the query box:
18125
+ * the bar's chords are scoped to the box (its Esc to the bar), so a mouse
18126
+ * click on a bar button must not leave them dead on the button it landed on. */
18127
+ const andRefocus = (action) => {
18128
+ action();
18129
+ searchInputRef.current?.focus();
18130
+ };
18131
+ /** The shared toolbar's search button: the split view owns its own bar, so the
18132
+ * button has to toggle this one rather than the single-column state. */
18133
+ const toggleSearch = () => {
18134
+ if (searchOpen) closeSearch();
18135
+ else openSearch();
18136
+ };
18137
+ const toggleMatchCase = () => {
18138
+ if (!searchOpen) return false;
18139
+ search.toggleCase();
18140
+ return true;
18141
+ };
18142
+ const toggleMatchWholeWord = () => {
18143
+ if (!searchOpen) return false;
18144
+ search.toggleWord();
18145
+ return true;
17927
18146
  };
17928
18147
  const openSearch = () => {
17929
18148
  if (searchOpen) {
@@ -17931,13 +18150,14 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
17931
18150
  searchInputRef.current?.select();
17932
18151
  return;
17933
18152
  }
18153
+ search.sync();
17934
18154
  const live = window.getSelection();
17935
18155
  const liveRange = splitRowRangeOf(live);
17936
18156
  const range = liveRange !== void 0 ? liveRange : selection;
17937
18157
  const liveText = (live?.toString() ?? "").trim();
17938
18158
  const value = liveText !== "" && !liveText.includes("\n") ? liveText : "";
17939
18159
  setSearchQuery(value);
17940
- const matches = value === "" ? [] : searchPairs(pairs, value);
18160
+ const matches = value === "" ? [] : searchPairs(pairs, value, search.options);
17941
18161
  let index = 0;
17942
18162
  if (matches.length > 0) {
17943
18163
  const inSel = range === void 0 ? -1 : matches.findIndex((i) => i >= range.start && i <= range.end);
@@ -18051,11 +18271,19 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18051
18271
  (0, react.useImperativeHandle)(ref, () => ({
18052
18272
  jump,
18053
18273
  openSearch,
18054
- searchNext
18274
+ toggleSearch,
18275
+ closeSearch,
18276
+ searchNext,
18277
+ toggleMatchCase,
18278
+ toggleMatchWholeWord
18055
18279
  }), [
18056
18280
  jump,
18057
18281
  openSearch,
18058
- searchNext
18282
+ toggleSearch,
18283
+ closeSearch,
18284
+ searchNext,
18285
+ toggleMatchCase,
18286
+ toggleMatchWholeWord
18059
18287
  ]);
18060
18288
  (0, react.useLayoutEffect)(() => {
18061
18289
  if (pairCount === 0) return;
@@ -18139,6 +18367,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18139
18367
  searchHit: searchHitSet.has(index),
18140
18368
  searchCurrent: index === currentSearchPair,
18141
18369
  searchQuery,
18370
+ searchOptions: search.options,
18142
18371
  onHover: () => onPairHover(index),
18143
18372
  intra: sideIndex?.left === void 0 ? void 0 : model.intra.get(sideIndex.left)
18144
18373
  }, index);
@@ -18181,6 +18410,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18181
18410
  searchHit: searchHitSet.has(index),
18182
18411
  searchCurrent: index === currentSearchPair,
18183
18412
  searchQuery,
18413
+ searchOptions: search.options,
18184
18414
  onHover: () => onPairHover(index),
18185
18415
  intra: sideIndex?.right === void 0 ? void 0 : model.intra.get(sideIndex.right)
18186
18416
  }, index);
@@ -18246,7 +18476,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18246
18476
  setSearchQuery(value);
18247
18477
  if (value !== "") {
18248
18478
  const body = bodyRef.current;
18249
- const matches = searchPairs(pairs, value);
18479
+ const matches = searchPairs(pairs, value, search.options);
18250
18480
  const anchor = currentSearchPair ?? (body === null ? 0 : pairAtY(body.scrollTop));
18251
18481
  const at = matches.findIndex((index) => index >= anchor);
18252
18482
  setSearchIndex(at === -1 ? 0 : at);
@@ -18256,7 +18486,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18256
18486
  if (event.key === "Enter") {
18257
18487
  event.preventDefault();
18258
18488
  goSearch(event.shiftKey ? -1 : 1);
18259
- } else if (event.key === "Escape") closeSearch();
18489
+ }
18260
18490
  }
18261
18491
  }),
18262
18492
  (0, react_jsx_runtime.jsx)("span", {
@@ -18265,7 +18495,45 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18265
18495
  children: searchMatches.length === 0 ? "0/0" : `${searchIndex % searchMatches.length + 1}/${searchMatches.length}`
18266
18496
  }),
18267
18497
  (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
18268
- label: `${t("action.prevDiff")} (Shift+F3)`,
18498
+ label: withChord(t("action.matchCase"), "matchCase"),
18499
+ side: "bottom",
18500
+ delayMs: 500,
18501
+ children: (0, react_jsx_runtime.jsx)("button", {
18502
+ type: "button",
18503
+ className: search.caseSensitive ? `${PendingPanel_module_css_default.searchToggle} ${PendingPanel_module_css_default.searchToggleOn}` : PendingPanel_module_css_default.searchToggle,
18504
+ "data-diff-search-case": true,
18505
+ "data-on": search.caseSensitive ? "" : void 0,
18506
+ "aria-label": t("action.matchCase"),
18507
+ "aria-pressed": search.caseSensitive,
18508
+ onClick: () => {
18509
+ andRefocus(() => {
18510
+ search.toggleCase();
18511
+ });
18512
+ },
18513
+ children: (0, react_jsx_runtime.jsx)(SearchOptionIcon, { kind: "case" })
18514
+ })
18515
+ }),
18516
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
18517
+ label: withChord(t("action.matchWholeWord"), "matchWholeWord"),
18518
+ side: "bottom",
18519
+ delayMs: 500,
18520
+ children: (0, react_jsx_runtime.jsx)("button", {
18521
+ type: "button",
18522
+ className: search.wholeWord ? `${PendingPanel_module_css_default.searchToggle} ${PendingPanel_module_css_default.searchToggleOn}` : PendingPanel_module_css_default.searchToggle,
18523
+ "data-diff-search-word": true,
18524
+ "data-on": search.wholeWord ? "" : void 0,
18525
+ "aria-label": t("action.matchWholeWord"),
18526
+ "aria-pressed": search.wholeWord,
18527
+ onClick: () => {
18528
+ andRefocus(() => {
18529
+ search.toggleWord();
18530
+ });
18531
+ },
18532
+ children: (0, react_jsx_runtime.jsx)(SearchOptionIcon, { kind: "word" })
18533
+ })
18534
+ }),
18535
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
18536
+ label: withChord(t("action.prevDiff"), "searchPrev"),
18269
18537
  side: "bottom",
18270
18538
  delayMs: 500,
18271
18539
  children: (0, react_jsx_runtime.jsx)("button", {
@@ -18275,13 +18543,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18275
18543
  "aria-label": t("action.prevDiff"),
18276
18544
  disabled: searchMatches.length === 0,
18277
18545
  onClick: () => {
18278
- goSearch(-1);
18546
+ andRefocus(() => {
18547
+ goSearch(-1);
18548
+ });
18279
18549
  },
18280
18550
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 14 })
18281
18551
  })
18282
18552
  }),
18283
18553
  (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
18284
- label: `${t("action.nextDiff")} (F3)`,
18554
+ label: withChord(t("action.nextDiff"), "searchNext"),
18285
18555
  side: "bottom",
18286
18556
  delayMs: 500,
18287
18557
  children: (0, react_jsx_runtime.jsx)("button", {
@@ -18291,7 +18561,9 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18291
18561
  "aria-label": t("action.nextDiff"),
18292
18562
  disabled: searchMatches.length === 0,
18293
18563
  onClick: () => {
18294
- goSearch(1);
18564
+ andRefocus(() => {
18565
+ goSearch(1);
18566
+ });
18295
18567
  },
18296
18568
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })
18297
18569
  })
@@ -18590,7 +18862,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18590
18862
  });
18591
18863
  }
18592
18864
  /** The selected file's diff, actions, jump controls, and copy toolbar. */
18593
- function PendingDiff({ file, busy, workspacePath, jumpSignal, undoFlash, failedMessage, onPasteReference, onToast, t, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen, onPreviewImage, floatMode, floatOpen, onToggleFileList }) {
18865
+ function PendingDiff({ file, busy, workspacePath, jumpSignal, undoFlash, failedMessage, onPasteReference, onToast, t, onKeep, onRevert, onRefreshVcs, onBlockKeep, onBlockRevert, onOpen, onPreviewImage, floatMode, floatOpen, onToggleFileList }) {
18594
18866
  const [langOverride, setLangOverride] = (0, react.useState)(void 0);
18595
18867
  const [langMenuOpen, setLangMenuOpen] = (0, react.useState)(false);
18596
18868
  const langMenuItems = (0, react.useMemo)(() => [{
@@ -18749,6 +19021,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18749
19021
  const [copied, setCopied] = (0, react.useState)(false);
18750
19022
  const [searchOpen, setSearchOpen] = (0, react.useState)(false);
18751
19023
  const [searchQuery, setSearchQuery] = (0, react.useState)("");
19024
+ const search = useSearchOptions();
18752
19025
  const [searchIndex, setSearchIndex] = (0, react.useState)(0);
18753
19026
  const searchInputRef = (0, react.useRef)(null);
18754
19027
  const [flashKey, setFlashKey] = (0, react.useState)(0);
@@ -18806,7 +19079,11 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18806
19079
  end: last.end
18807
19080
  });
18808
19081
  }, [coveredBlockIndices, model]);
18809
- const searchMatches = (0, react.useMemo)(() => matchingRows(model.diff.rows, searchQuery), [model, searchQuery]);
19082
+ const searchMatches = (0, react.useMemo)(() => matchingRows(model.diff.rows, searchQuery, search.options), [
19083
+ model,
19084
+ searchQuery,
19085
+ search.options
19086
+ ]);
18810
19087
  const searchHitSet = (0, react.useMemo)(() => new Set(searchMatches), [searchMatches]);
18811
19088
  const currentSearchRow = searchMatches.length === 0 ? void 0 : searchMatches[searchIndex % searchMatches.length];
18812
19089
  const goSearch = (direction) => {
@@ -18824,7 +19101,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18824
19101
  * start (the "no cursor" fallback).
18825
19102
  */
18826
19103
  const startIndexFor = (value) => {
18827
- const matches = value === "" ? [] : matchingRows(model.diff.rows, value);
19104
+ const matches = value === "" ? [] : matchingRows(model.diff.rows, value, search.options);
18828
19105
  const pos = cursorPosRef.current;
18829
19106
  cursorPosRef.current = void 0;
18830
19107
  if (matches.length === 0) return 0;
@@ -18843,6 +19120,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18843
19120
  searchInputRef.current?.select();
18844
19121
  return;
18845
19122
  }
19123
+ search.sync();
18846
19124
  const live = window.getSelection();
18847
19125
  const liveRange = splitView ? splitRowRangeOf(live) : rowRangeOf(live);
18848
19126
  const pos = liveRange !== void 0 ? liveRange : selection;
@@ -18862,7 +19140,18 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18862
19140
  openSearchRef.current = openSearchWithSelection;
18863
19141
  const searchOpenRef = (0, react.useRef)(searchOpen);
18864
19142
  searchOpenRef.current = searchOpen;
19143
+ /** Run one bar control's action, then hand the focus back to the query box:
19144
+ * the bar's chords are scoped to the box (its Esc to the bar), so a mouse
19145
+ * click on a bar button must not leave them dead on the button it landed on. */
19146
+ const andRefocus = (action) => {
19147
+ action();
19148
+ searchInputRef.current?.focus();
19149
+ };
18865
19150
  const toggleSearch = () => {
19151
+ if (splitView) {
19152
+ splitDiffRef.current?.toggleSearch();
19153
+ return;
19154
+ }
18866
19155
  if (searchOpen) {
18867
19156
  cursorPosRef.current = void 0;
18868
19157
  lastRecordedCursorRef.current = void 0;
@@ -19233,6 +19522,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19233
19522
  }, [searchOpen, splitView]);
19234
19523
  (0, react.useEffect)(() => {
19235
19524
  const onKeyDown = (event) => {
19525
+ if (!isSearchInputEvent(event)) return;
19236
19526
  let direction = 0;
19237
19527
  if (matchesShortcut(event, keybindingOf("searchNext"))) direction = 1;
19238
19528
  else if (matchesShortcut(event, keybindingOf("searchPrev"))) direction = -1;
@@ -19255,6 +19545,52 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19255
19545
  searchMatches,
19256
19546
  splitView
19257
19547
  ]);
19548
+ (0, react.useEffect)(() => {
19549
+ const onKeyDown = (event) => {
19550
+ if (!isSearchInputEvent(event)) return;
19551
+ const option = matchesShortcut(event, keybindingOf("matchCase")) ? "case" : matchesShortcut(event, keybindingOf("matchWholeWord")) ? "word" : void 0;
19552
+ if (option === void 0) return;
19553
+ if (splitView) {
19554
+ const handle = splitDiffRef.current;
19555
+ if (option === "case" ? handle?.toggleMatchCase() === true : handle?.toggleMatchWholeWord() === true) event.preventDefault();
19556
+ return;
19557
+ }
19558
+ if (!searchOpen) return;
19559
+ event.preventDefault();
19560
+ if (option === "case") search.toggleCase();
19561
+ else search.toggleWord();
19562
+ };
19563
+ window.addEventListener("keydown", onKeyDown, true);
19564
+ return () => {
19565
+ window.removeEventListener("keydown", onKeyDown, true);
19566
+ };
19567
+ }, [
19568
+ searchOpen,
19569
+ splitView,
19570
+ search
19571
+ ]);
19572
+ (0, react.useEffect)(() => {
19573
+ const onKeyDown = (event) => {
19574
+ if (event.key !== "Escape" || !isInPanelEvent(event)) return;
19575
+ if (mdPreview && lang === "markdown") return;
19576
+ if (splitView) {
19577
+ if (splitDiffRef.current?.closeSearch() === true) event.preventDefault();
19578
+ return;
19579
+ }
19580
+ if (!searchOpen) return;
19581
+ event.preventDefault();
19582
+ closeSearch();
19583
+ };
19584
+ window.addEventListener("keydown", onKeyDown, true);
19585
+ return () => {
19586
+ window.removeEventListener("keydown", onKeyDown, true);
19587
+ };
19588
+ }, [
19589
+ searchOpen,
19590
+ splitView,
19591
+ mdPreview,
19592
+ lang
19593
+ ]);
19258
19594
  const jumpRef = (0, react.useRef)(jumpBlock);
19259
19595
  jumpRef.current = jumpBlock;
19260
19596
  (0, react.useEffect)(() => {
@@ -19263,8 +19599,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19263
19599
  if (matchesShortcut(event, keybindingOf("jumpUp"))) direction = -1;
19264
19600
  else if (matchesShortcut(event, keybindingOf("jumpDown"))) direction = 1;
19265
19601
  if (direction === 0) return;
19266
- const target = event.target;
19267
- if (target instanceof Element && target.closest("input, textarea, [contenteditable=\"true\"]") !== null) return;
19602
+ if (isTextFieldEvent(event)) return;
19268
19603
  event.preventDefault();
19269
19604
  jumpRef.current(direction, true);
19270
19605
  };
@@ -19352,7 +19687,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19352
19687
  })
19353
19688
  }),
19354
19689
  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, {
19355
- label: `${t("action.prevDiff")} (Ctrl+↑)`,
19690
+ label: withChord(t("action.prevDiff"), "jumpUp"),
19356
19691
  side: "bottom",
19357
19692
  delayMs: 500,
19358
19693
  children: (0, react_jsx_runtime.jsx)("button", {
@@ -19367,7 +19702,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19367
19702
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 14 })
19368
19703
  })
19369
19704
  }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
19370
- label: `${t("action.nextDiff")} (Ctrl+↓)`,
19705
+ label: withChord(t("action.nextDiff"), "jumpDown"),
19371
19706
  side: "bottom",
19372
19707
  delayMs: 500,
19373
19708
  children: (0, react_jsx_runtime.jsx)("button", {
@@ -19383,7 +19718,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19383
19718
  })
19384
19719
  })] }),
19385
19720
  (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
19386
- label: t("action.search"),
19721
+ label: withChord(t("action.search"), "openSearch"),
19387
19722
  side: "bottom",
19388
19723
  delayMs: 500,
19389
19724
  children: (0, react_jsx_runtime.jsx)("button", {
@@ -19426,6 +19761,22 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19426
19761
  children: (0, react_jsx_runtime.jsx)(MarkdownModeIcon, { preview: mdPreview })
19427
19762
  })
19428
19763
  }),
19764
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
19765
+ label: t("action.refreshVcs"),
19766
+ side: "bottom",
19767
+ delayMs: 500,
19768
+ children: (0, react_jsx_runtime.jsx)("button", {
19769
+ type: "button",
19770
+ className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.iconAction}`,
19771
+ "data-diff-refresh-vcs": true,
19772
+ disabled: busy,
19773
+ "aria-label": t("action.refreshVcs"),
19774
+ onClick: () => {
19775
+ onRefreshVcs(file);
19776
+ },
19777
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16, { size: 14 })
19778
+ })
19779
+ }),
19429
19780
  (0, react_jsx_runtime.jsx)("span", { className: PendingPanel_module_css_default.flexSpacer }),
19430
19781
  (0, react_jsx_runtime.jsx)("button", {
19431
19782
  type: "button",
@@ -19539,6 +19890,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19539
19890
  searchHit: searchHitSet.has(index),
19540
19891
  searchCurrent: index === currentSearchRow,
19541
19892
  searchQuery,
19893
+ searchOptions: search.options,
19542
19894
  onRowHover,
19543
19895
  wrappedLines: rowWrapped?.[index]
19544
19896
  }, index);
@@ -19659,7 +20011,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19659
20011
  if (event.key === "Enter") {
19660
20012
  event.preventDefault();
19661
20013
  goSearch(event.shiftKey ? -1 : 1);
19662
- } else if (event.key === "Escape") closeSearch();
20014
+ }
19663
20015
  }
19664
20016
  }),
19665
20017
  (0, react_jsx_runtime.jsx)("span", {
@@ -19668,7 +20020,45 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19668
20020
  children: searchMatches.length === 0 ? "0/0" : `${searchIndex % searchMatches.length + 1}/${searchMatches.length}`
19669
20021
  }),
19670
20022
  (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
19671
- label: `${t("action.prevDiff")} (Shift+F3)`,
20023
+ label: withChord(t("action.matchCase"), "matchCase"),
20024
+ side: "bottom",
20025
+ delayMs: 500,
20026
+ children: (0, react_jsx_runtime.jsx)("button", {
20027
+ type: "button",
20028
+ className: search.caseSensitive ? `${PendingPanel_module_css_default.searchToggle} ${PendingPanel_module_css_default.searchToggleOn}` : PendingPanel_module_css_default.searchToggle,
20029
+ "data-diff-search-case": true,
20030
+ "data-on": search.caseSensitive ? "" : void 0,
20031
+ "aria-label": t("action.matchCase"),
20032
+ "aria-pressed": search.caseSensitive,
20033
+ onClick: () => {
20034
+ andRefocus(() => {
20035
+ search.toggleCase();
20036
+ });
20037
+ },
20038
+ children: (0, react_jsx_runtime.jsx)(SearchOptionIcon, { kind: "case" })
20039
+ })
20040
+ }),
20041
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
20042
+ label: withChord(t("action.matchWholeWord"), "matchWholeWord"),
20043
+ side: "bottom",
20044
+ delayMs: 500,
20045
+ children: (0, react_jsx_runtime.jsx)("button", {
20046
+ type: "button",
20047
+ className: search.wholeWord ? `${PendingPanel_module_css_default.searchToggle} ${PendingPanel_module_css_default.searchToggleOn}` : PendingPanel_module_css_default.searchToggle,
20048
+ "data-diff-search-word": true,
20049
+ "data-on": search.wholeWord ? "" : void 0,
20050
+ "aria-label": t("action.matchWholeWord"),
20051
+ "aria-pressed": search.wholeWord,
20052
+ onClick: () => {
20053
+ andRefocus(() => {
20054
+ search.toggleWord();
20055
+ });
20056
+ },
20057
+ children: (0, react_jsx_runtime.jsx)(SearchOptionIcon, { kind: "word" })
20058
+ })
20059
+ }),
20060
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
20061
+ label: withChord(t("action.prevDiff"), "searchPrev"),
19672
20062
  side: "bottom",
19673
20063
  delayMs: 500,
19674
20064
  children: (0, react_jsx_runtime.jsx)("button", {
@@ -19678,13 +20068,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19678
20068
  "aria-label": t("action.prevDiff"),
19679
20069
  disabled: searchMatches.length === 0,
19680
20070
  onClick: () => {
19681
- goSearch(-1);
20071
+ andRefocus(() => {
20072
+ goSearch(-1);
20073
+ });
19682
20074
  },
19683
20075
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 14 })
19684
20076
  })
19685
20077
  }),
19686
20078
  (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
19687
- label: `${t("action.nextDiff")} (F3)`,
20079
+ label: withChord(t("action.nextDiff"), "searchNext"),
19688
20080
  side: "bottom",
19689
20081
  delayMs: 500,
19690
20082
  children: (0, react_jsx_runtime.jsx)("button", {
@@ -19694,7 +20086,9 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19694
20086
  "aria-label": t("action.nextDiff"),
19695
20087
  disabled: searchMatches.length === 0,
19696
20088
  onClick: () => {
19697
- goSearch(1);
20089
+ andRefocus(() => {
20090
+ goSearch(1);
20091
+ });
19698
20092
  },
19699
20093
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })
19700
20094
  })
@@ -19730,7 +20124,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19730
20124
  "data-diff-status-bar": true,
19731
20125
  children: [
19732
20126
  selectionReference === void 0 ? null : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
19733
- label: copied ? t("action.copied") : `${t("action.copyHint")} (Ctrl+L)`,
20127
+ label: copied ? t("action.copied") : withChord(t("action.copyHint"), "copyRef"),
19734
20128
  side: "top",
19735
20129
  delayMs: 300,
19736
20130
  children: (0, react_jsx_runtime.jsx)("span", {
@@ -19810,7 +20204,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19810
20204
  });
19811
20205
  }
19812
20206
  /** Render the pending-edit review panel and its unified footer action. */
19813
- function PendingPanel({ wide, useSessions, usePending, onRefresh, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen, onPreviewImage, onPasteReference, onUndo, onRedo, onImportVcs, onKeepAll, onRevertAll, onAckRedoCleared, collapseSidebar, t }) {
20207
+ function PendingPanel({ wide, useSessions, usePending, onRefresh, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen, onPreviewImage, onPasteReference, onUndo, onRedo, onImportVcs, onRefreshVcs, onKeepAll, onRevertAll, onAckRedoCleared, collapseSidebar, t }) {
19814
20208
  const current = useSessions((state) => state.current);
19815
20209
  const currentBlank = useSessions((state) => {
19816
20210
  const id = state.current;
@@ -19872,6 +20266,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
19872
20266
  /** A last-block keep/revert awaiting the user's remove-or-keep choice; the
19873
20267
  * choice rides the same block RPC as its `removeWhenResolved` flag. */
19874
20268
  const [blockPrompt, setBlockPrompt] = (0, react.useState)(null);
20269
+ const [filePrompt, setFilePrompt] = (0, react.useState)(null);
19875
20270
  /** Bottom offset tracking the chat composer's top edge so the input stays visible. */
19876
20271
  const [bottomPx, setBottomPx] = (0, react.useState)(FALLBACK_BOTTOM_PX);
19877
20272
  /** Fullscreen expanded: the panel bottom pins to the window edge, ignoring the composer offset. */
@@ -20036,6 +20431,28 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
20036
20431
  }
20037
20432
  return removeWhenResolved === void 0 ? onBlockRevert(sessionId, id, block) : onBlockRevert(sessionId, id, block, removeWhenResolved);
20038
20433
  };
20434
+ const keepWithPrompt = (sessionId, id, keepListed) => {
20435
+ if (keepListed === void 0 && confirmFileRemoveEnabled()) {
20436
+ setFilePrompt({
20437
+ action: "keep",
20438
+ sessionId,
20439
+ id
20440
+ });
20441
+ return Promise.resolve();
20442
+ }
20443
+ return keepListed === void 0 ? onKeep(sessionId, id) : onKeep(sessionId, id, keepListed);
20444
+ };
20445
+ const revertWithPrompt = (sessionId, id, keepListed) => {
20446
+ if (keepListed === void 0 && confirmFileRemoveEnabled()) {
20447
+ setFilePrompt({
20448
+ action: "revert",
20449
+ sessionId,
20450
+ id
20451
+ });
20452
+ return Promise.resolve();
20453
+ }
20454
+ return keepListed === void 0 ? onRevert(sessionId, id) : onRevert(sessionId, id, keepListed);
20455
+ };
20039
20456
  /** Per-file keep/revert failures, surfaced inline on the row and detail. */
20040
20457
  const failed = snapshot.failed ?? EMPTY_FAILED_MAP;
20041
20458
  const failedInitialized = (0, react.useRef)(false);
@@ -20099,6 +20516,40 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
20099
20516
  setBulkBusy(null);
20100
20517
  }
20101
20518
  };
20519
+ /**
20520
+ * Replace one file's diff with its current local VCS change, then report what
20521
+ * the scan found. A scan that sees no change leaves the entry alone, so the
20522
+ * message names the file rather than silently blanking a review in progress.
20523
+ */
20524
+ const runRefreshVcs = async (entry) => {
20525
+ if (current === void 0) return;
20526
+ const includeUntracked = includeUntrackedEnabled();
20527
+ let outcome;
20528
+ try {
20529
+ outcome = (await onRefreshVcs(current, entry.id, includeUntracked)).outcome;
20530
+ } catch (error) {
20531
+ showCopyToast(t("panel.refreshFailed", { message: error instanceof Error ? error.message : String(error) }));
20532
+ return;
20533
+ }
20534
+ if (outcome === "refreshed") {
20535
+ showCopyToast(t("panel.refreshDone"));
20536
+ return;
20537
+ }
20538
+ if (outcome === "unchanged") {
20539
+ showCopyToast(t("panel.refreshUnchanged"));
20540
+ return;
20541
+ }
20542
+ if (outcome === "no-change") {
20543
+ const hint = includeUntracked ? "" : ` ${t("panel.refreshUntrackedHint")}`;
20544
+ showCopyToast(`${t("panel.refreshNone")}${hint}`);
20545
+ return;
20546
+ }
20547
+ if (outcome === "no-vcs") {
20548
+ showCopyToast(t("panel.importNoVcs"));
20549
+ return;
20550
+ }
20551
+ showCopyToast(t("panel.fileNotPending"));
20552
+ };
20102
20553
  const renderEntry = (entry) => (0, react_jsx_runtime.jsx)(PendingFileRow, {
20103
20554
  file: entry,
20104
20555
  selected: selected === entry.id,
@@ -20112,6 +20563,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
20112
20563
  const selectedFile = files.find((file) => file.id === selected);
20113
20564
  /** The file whose removal is being confirmed (a last-block action), if any. */
20114
20565
  const promptFile = blockPrompt === null ? void 0 : files.find((file) => file.id === blockPrompt.id);
20566
+ /** The file whose removal is being confirmed (a whole-file action), if any. */
20567
+ const promptEntry = filePrompt === null ? void 0 : files.find((file) => file.id === filePrompt.id);
20115
20568
  const fileListBody = (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("div", {
20116
20569
  className: PendingPanel_module_css_default.listScroll,
20117
20570
  children: files.length > 0 && (0, react_jsx_runtime.jsxs)("section", { children: [(0, react_jsx_runtime.jsx)("h3", {
@@ -20223,7 +20676,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
20223
20676
  const onKeyDown = (event) => {
20224
20677
  if (event.key !== "Escape") return;
20225
20678
  const target = event.target;
20226
- if (target instanceof Element && target.closest("input, textarea, [contenteditable=\"true\"]") !== null) return;
20679
+ if (target instanceof Node && panelRef.current?.contains(target) === true && document.querySelector("[data-diff-searchbar]") !== null) return;
20227
20680
  event.preventDefault();
20228
20681
  setOpen(false);
20229
20682
  };
@@ -20414,8 +20867,11 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
20414
20867
  onPasteReference,
20415
20868
  onToast: showCopyToast,
20416
20869
  t,
20417
- onKeep,
20418
- onRevert,
20870
+ onKeep: keepWithPrompt,
20871
+ onRevert: revertWithPrompt,
20872
+ onRefreshVcs: (entry) => {
20873
+ runRefreshVcs(entry);
20874
+ },
20419
20875
  onBlockKeep: blockKeepWithPrompt,
20420
20876
  onBlockRevert: blockRevertWithPrompt,
20421
20877
  onOpen,
@@ -20473,6 +20929,42 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
20473
20929
  })]
20474
20930
  })]
20475
20931
  })
20932
+ }),
20933
+ filePrompt !== null && promptEntry !== void 0 && (0, react_jsx_runtime.jsx)("div", {
20934
+ className: PendingPanel_module_css_default.confirmBackdrop,
20935
+ "data-diff-confirm-file": true,
20936
+ children: (0, react_jsx_runtime.jsxs)("div", {
20937
+ className: PendingPanel_module_css_default.confirmCard,
20938
+ role: "dialog",
20939
+ "aria-modal": "true",
20940
+ children: [(0, react_jsx_runtime.jsx)("p", {
20941
+ className: PendingPanel_module_css_default.confirmText,
20942
+ children: t(filePrompt.action === "keep" ? "panel.fileKeptAsk" : "panel.fileRevertedAsk", { file: basenameOf(promptEntry.path) })
20943
+ }), (0, react_jsx_runtime.jsxs)("div", {
20944
+ className: PendingPanel_module_css_default.confirmActions,
20945
+ children: [(0, react_jsx_runtime.jsx)("button", {
20946
+ type: "button",
20947
+ className: `${PendingPanel_module_css_default.action} ${PendingPanel_module_css_default.actionPrimary}`,
20948
+ "data-diff-file-confirm-remove": true,
20949
+ onClick: () => {
20950
+ setFilePrompt(null);
20951
+ const { action, sessionId, id } = filePrompt;
20952
+ action === "keep" ? onKeep(sessionId, id, false) : onRevert(sessionId, id, false);
20953
+ },
20954
+ children: t("row.dismiss")
20955
+ }), (0, react_jsx_runtime.jsx)("button", {
20956
+ type: "button",
20957
+ className: PendingPanel_module_css_default.action,
20958
+ "data-diff-file-confirm-keep": true,
20959
+ onClick: () => {
20960
+ setFilePrompt(null);
20961
+ const { action, sessionId, id } = filePrompt;
20962
+ action === "keep" ? onKeep(sessionId, id, true) : onRevert(sessionId, id, true);
20963
+ },
20964
+ children: t("panel.keepInList")
20965
+ })]
20966
+ })]
20967
+ })
20476
20968
  })
20477
20969
  ]
20478
20970
  })] }), document.body),
@@ -21105,6 +21597,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
21105
21597
  function DiffApprovalSettingsTab({ t }) {
21106
21598
  const [pasteOnCopy, setPasteOnCopyState] = (0, react.useState)(pasteOnCopyEnabled);
21107
21599
  const [includeUntracked, setIncludeUntrackedState] = (0, react.useState)(includeUntrackedEnabled);
21600
+ const [confirmFileRemove, setConfirmFileRemoveState] = (0, react.useState)(confirmFileRemoveEnabled);
21108
21601
  const [tab, setTabState] = (0, react.useState)(tabWidth);
21109
21602
  const [tabOpen, setTabOpen] = (0, react.useState)(false);
21110
21603
  const [split, setSplitState] = (0, react.useState)(splitMode);
@@ -21144,6 +21637,10 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
21144
21637
  setIncludeUntrackedState(value);
21145
21638
  setIncludeUntrackedEnabled(value);
21146
21639
  };
21640
+ const setConfirmFileRemove = (value) => {
21641
+ setConfirmFileRemoveState(value);
21642
+ setConfirmFileRemoveEnabled(value);
21643
+ };
21147
21644
  const setTab = (value) => {
21148
21645
  setTabState(value);
21149
21646
  setTabWidth(value);
@@ -21357,6 +21854,14 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
21357
21854
  onSelect: setIncludeUntracked,
21358
21855
  dataAttribute: "data-diff-import-untracked-select",
21359
21856
  t
21857
+ }),
21858
+ (0, react_jsx_runtime.jsx)(PreferenceRow, {
21859
+ title: t("panel.confirmFileRemove"),
21860
+ description: t("panel.confirmFileRemoveDesc"),
21861
+ value: confirmFileRemove,
21862
+ onSelect: setConfirmFileRemove,
21863
+ dataAttribute: "data-diff-confirm-file-remove-select",
21864
+ t
21360
21865
  })
21361
21866
  ]
21362
21867
  });
@@ -21380,16 +21885,24 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
21380
21885
  async list(sessionId) {
21381
21886
  return listValueOf(await rpc.call(DIFF_APPROVAL_CHANNEL, "list", { sessionId }));
21382
21887
  },
21383
- async keep(sessionId, id) {
21384
- return actionOf(await rpc.call(DIFF_APPROVAL_CHANNEL, "keep", {
21888
+ async keep(sessionId, id, keepListed) {
21889
+ return actionOf(await rpc.call(DIFF_APPROVAL_CHANNEL, "keep", keepListed === void 0 ? {
21385
21890
  sessionId,
21386
21891
  id
21892
+ } : {
21893
+ sessionId,
21894
+ id,
21895
+ keepListed
21387
21896
  }));
21388
21897
  },
21389
- async revert(sessionId, id) {
21390
- return actionOf(await rpc.call(DIFF_APPROVAL_CHANNEL, "revert", {
21898
+ async revert(sessionId, id, keepListed) {
21899
+ return actionOf(await rpc.call(DIFF_APPROVAL_CHANNEL, "revert", keepListed === void 0 ? {
21391
21900
  sessionId,
21392
21901
  id
21902
+ } : {
21903
+ sessionId,
21904
+ id,
21905
+ keepListed
21393
21906
  }));
21394
21907
  },
21395
21908
  async blockKeep(sessionId, id, block, removeWhenResolved) {
@@ -21420,6 +21933,13 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
21420
21933
  includeUntracked
21421
21934
  }));
21422
21935
  },
21936
+ async refreshVcs(sessionId, id, includeUntracked) {
21937
+ return refreshValueOf(await rpc.call(DIFF_APPROVAL_CHANNEL, "vcs-refresh", {
21938
+ sessionId,
21939
+ id,
21940
+ includeUntracked
21941
+ }));
21942
+ },
21423
21943
  async open(sessionId, id, action) {
21424
21944
  return openOf(await rpc.call(DIFF_APPROVAL_CHANNEL, "open", {
21425
21945
  sessionId,
@@ -21519,6 +22039,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
21519
22039
  detected
21520
22040
  };
21521
22041
  }
22042
+ /** Narrow the vcs-refresh endpoint's value; a malformed wire value is a failure. */
22043
+ function refreshValueOf(result) {
22044
+ if (!result.ok) throw new Error(`${result.error.code}: ${result.error.message}`);
22045
+ const value = result.value;
22046
+ if (typeof value !== "object" || value === null) throw new Error("the refresh returned a malformed value");
22047
+ const outcome = value.outcome;
22048
+ if (outcome !== "refreshed" && outcome !== "unchanged" && outcome !== "no-change" && outcome !== "missing" && outcome !== "no-vcs") throw new Error("the refresh returned a malformed outcome");
22049
+ return { outcome };
22050
+ }
21522
22051
  /** Narrow the open endpoint's value; a malformed wire value is an open failure. */
21523
22052
  function openOf(result) {
21524
22053
  if (!result.ok) throw new Error(`${result.error.code}: ${result.error.message}`);
@@ -21633,6 +22162,36 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
21633
22162
  busy: new Set([...snapshot.busy].filter((busy) => busy !== id))
21634
22163
  });
21635
22164
  };
22165
+ /**
22166
+ * Run a whole-file action whose entry STAYS listed (the panel chose "keep in
22167
+ * list"). The local list must not drop it optimistically — that made a kept
22168
+ * file blink out and come back on the next poll — so this takes the block
22169
+ * actions' shape instead: mark busy, run, then re-read so the entry's now-empty
22170
+ * diff shows at once.
22171
+ * @param id - the entry being acted on.
22172
+ * @param refresh - the store's refresh, awaited after a successful action.
22173
+ * @param action - the port call to run.
22174
+ */
22175
+ const withKeptEntry = async (id, refresh, action) => {
22176
+ const { error: _cleared, ...base } = snapshot;
22177
+ publish({
22178
+ ...base,
22179
+ failed: failedOf(snapshot),
22180
+ busy: /* @__PURE__ */ new Set([...snapshot.busy, id])
22181
+ });
22182
+ try {
22183
+ await action();
22184
+ } catch (error) {
22185
+ markFailed(id, error instanceof Error ? error.message : String(error));
22186
+ publish({
22187
+ ...snapshot,
22188
+ busy: new Set([...snapshot.busy].filter((busy) => busy !== id))
22189
+ });
22190
+ return;
22191
+ }
22192
+ clearFailed(id);
22193
+ await refresh();
22194
+ };
21636
22195
  return {
21637
22196
  getSnapshot: () => snapshot,
21638
22197
  subscribe(listener) {
@@ -21672,12 +22231,18 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
21672
22231
  });
21673
22232
  }
21674
22233
  },
21675
- keep(sessionId, id) {
22234
+ keep(sessionId, id, keepListed) {
22235
+ if (keepListed === true) return withKeptEntry(id, () => this.refresh(sessionId), async () => {
22236
+ await port.keep(sessionId, id, true);
22237
+ });
21676
22238
  return withBusy(id, async () => {
21677
22239
  await port.keep(sessionId, id);
21678
22240
  });
21679
22241
  },
21680
- revert(sessionId, id) {
22242
+ revert(sessionId, id, keepListed) {
22243
+ if (keepListed === true) return withKeptEntry(id, () => this.refresh(sessionId), async () => {
22244
+ await port.revert(sessionId, id, true);
22245
+ });
21681
22246
  return withBusy(id, async () => {
21682
22247
  await port.revert(sessionId, id);
21683
22248
  });
@@ -21747,6 +22312,23 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
21747
22312
  await this.refresh(sessionId);
21748
22313
  return value;
21749
22314
  },
22315
+ async refreshVcs(sessionId, id, includeUntracked) {
22316
+ const { error: _cleared, ...base } = snapshot;
22317
+ publish({
22318
+ ...base,
22319
+ busy: /* @__PURE__ */ new Set([...snapshot.busy, id])
22320
+ });
22321
+ try {
22322
+ const value = await port.refreshVcs(sessionId, id, includeUntracked);
22323
+ await this.refresh(sessionId);
22324
+ return value;
22325
+ } finally {
22326
+ publish({
22327
+ ...snapshot,
22328
+ busy: new Set([...snapshot.busy].filter((busy) => busy !== id))
22329
+ });
22330
+ }
22331
+ },
21750
22332
  async open(sessionId, id, action) {
21751
22333
  try {
21752
22334
  await port.open(sessionId, id, action);
@@ -21981,6 +22563,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
21981
22563
  "panel.key.openSearch": "打开差异搜索",
21982
22564
  "panel.key.searchNext": "下一个搜索结果",
21983
22565
  "panel.key.searchPrev": "上一个搜索结果",
22566
+ "panel.key.matchCase": "切换区分大小写",
22567
+ "panel.key.matchWholeWord": "切换全字匹配",
21984
22568
  "panel.key.undo": "撤销",
21985
22569
  "panel.key.redo": "重做",
21986
22570
  "panel.key.cycleNext": "下一个待处理文件",
@@ -22028,7 +22612,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
22028
22612
  "panel.importDone": "已导入 {count} 个改动",
22029
22613
  "panel.importNoVcs": "未检测到版本控制(Git / SVN / Perforce)",
22030
22614
  "panel.importFailed": "导入失败:{message}",
22031
- "action.search": "搜索 (Ctrl+F)",
22615
+ "action.search": "搜索",
22032
22616
  "action.settings": "设置",
22033
22617
  "action.expand": "展开全屏",
22034
22618
  "action.exitFullscreen": "退出全屏",
@@ -22037,7 +22621,19 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
22037
22621
  "status.reverted": "已回退",
22038
22622
  "status.missing": "该改动已不存在",
22039
22623
  "panel.resolvedAsk": "「{file}」的所有改动都已处理,是否从列表移除?",
22040
- "panel.keepInList": "保留在列表"
22624
+ "panel.keepInList": "保留在列表",
22625
+ "panel.fileKeptAsk": "「{file}」的改动已全部保留,是否从列表移除?",
22626
+ "panel.fileRevertedAsk": "「{file}」的改动已全部回退,是否从列表移除?",
22627
+ "panel.confirmFileRemove": "处理整文件后询问是否移出列表",
22628
+ "panel.confirmFileRemoveDesc": "对单个文件执行整文件 Keep/Revert 后,弹窗询问是否把该文件移出列表。关闭后直接移出(不影响批量 Keep All / Revert All)。",
22629
+ "action.refreshVcs": "刷新差异",
22630
+ "action.matchCase": "区分大小写",
22631
+ "action.matchWholeWord": "全字匹配",
22632
+ "panel.refreshDone": "差异已更新",
22633
+ "panel.refreshUnchanged": "差异已是最新",
22634
+ "panel.refreshNone": "未检测到本地 VCS 差异",
22635
+ "panel.refreshUntrackedHint": "(新建/未跟踪文件需要开启「导入未跟踪的文件改动」)",
22636
+ "panel.refreshFailed": "刷新失败:{message}"
22041
22637
  };
22042
22638
  /** English pending-edit review messages. */
22043
22639
  const en = {
@@ -22098,6 +22694,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
22098
22694
  "panel.key.openSearch": "Open diff search",
22099
22695
  "panel.key.searchNext": "Next search result",
22100
22696
  "panel.key.searchPrev": "Previous search result",
22697
+ "panel.key.matchCase": "Toggle match case",
22698
+ "panel.key.matchWholeWord": "Toggle match whole word",
22101
22699
  "panel.key.undo": "Undo",
22102
22700
  "panel.key.redo": "Redo",
22103
22701
  "panel.key.cycleNext": "Next pending file",
@@ -22145,7 +22743,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
22145
22743
  "panel.importDone": "Imported {count} changes",
22146
22744
  "panel.importNoVcs": "No version control detected (Git / SVN / Perforce)",
22147
22745
  "panel.importFailed": "Import failed: {message}",
22148
- "action.search": "Search (Ctrl+F)",
22746
+ "action.search": "Search",
22149
22747
  "action.settings": "Settings",
22150
22748
  "action.expand": "Expand fullscreen",
22151
22749
  "action.exitFullscreen": "Exit fullscreen",
@@ -22154,7 +22752,19 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
22154
22752
  "status.reverted": "Reverted",
22155
22753
  "status.missing": "This change no longer exists",
22156
22754
  "panel.resolvedAsk": "All changes in \"{file}\" are resolved. Remove it from the list?",
22157
- "panel.keepInList": "Keep in list"
22755
+ "panel.keepInList": "Keep in list",
22756
+ "panel.fileKeptAsk": "All changes in \"{file}\" are kept. Remove it from the list?",
22757
+ "panel.fileRevertedAsk": "All changes in \"{file}\" are reverted. Remove it from the list?",
22758
+ "panel.confirmFileRemove": "Ask after a whole-file keep/revert",
22759
+ "panel.confirmFileRemoveDesc": "After a whole-file keep/revert on a single file, ask whether to remove that file from the list. When off, it is removed straight away (Keep All / Revert All are unaffected).",
22760
+ "action.refreshVcs": "Refresh diff",
22761
+ "action.matchCase": "Match case",
22762
+ "action.matchWholeWord": "Match whole word",
22763
+ "panel.refreshDone": "Diff updated",
22764
+ "panel.refreshUnchanged": "Already up to date",
22765
+ "panel.refreshNone": "No local VCS change found",
22766
+ "panel.refreshUntrackedHint": "(new or untracked files need \"Import changes to untracked files\")",
22767
+ "panel.refreshFailed": "Refresh failed: {message}"
22158
22768
  };
22159
22769
  //#endregion
22160
22770
  //#region lib/types/client/index.js
@@ -22269,13 +22879,13 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
22269
22879
  currentSessionId = sessionId;
22270
22880
  store.refresh(sessionId);
22271
22881
  },
22272
- onKeep: (sessionId, path) => store.keep(sessionId, path),
22273
- onRevert: (sessionId, path) => {
22882
+ onKeep: (sessionId, path, keepListed) => store.keep(sessionId, path, keepListed),
22883
+ onRevert: (sessionId, path, keepListed) => {
22274
22884
  const entry = store.getSnapshot().files.find((file) => file.id === path);
22275
22885
  const before = entry?.newText;
22276
22886
  const after = entry?.oldText;
22277
22887
  const filePath = entry?.path;
22278
- return store.revert(sessionId, path).then(() => {
22888
+ return store.revert(sessionId, path, keepListed).then(() => {
22279
22889
  if (filePath !== void 0 && before !== void 0 && after !== void 0) remapFile(filePath, before, after);
22280
22890
  });
22281
22891
  },
@@ -22286,6 +22896,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
22286
22896
  onUndo: (sessionId) => store.undo(sessionId),
22287
22897
  onRedo: (sessionId) => store.redo(sessionId),
22288
22898
  onImportVcs: (sessionId, includeUntracked) => store.importVcs(sessionId, includeUntracked),
22899
+ onRefreshVcs: (sessionId, id, includeUntracked) => store.refreshVcs(sessionId, id, includeUntracked),
22289
22900
  onKeepAll: (sessionId) => store.keepAll(sessionId),
22290
22901
  onRevertAll: (sessionId) => store.revertAll(sessionId),
22291
22902
  onAckRedoCleared: () => store.clearRedoCleared(),