@pierre/diffs 1.3.0-beta.2 → 1.3.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/dist/components/CodeView.d.ts +4 -0
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +38 -0
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +2 -2
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +13 -13
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +7 -4
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +57 -47
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  14. package/dist/components/UnresolvedFile.js +1 -1
  15. package/dist/components/VirtualizedFile.d.ts +1 -1
  16. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  17. package/dist/components/VirtualizedFile.js +13 -4
  18. package/dist/components/VirtualizedFile.js.map +1 -1
  19. package/dist/components/VirtualizedFileDiff.d.ts +2 -1
  20. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  21. package/dist/components/VirtualizedFileDiff.js +36 -42
  22. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  23. package/dist/components/Virtualizer.js +5 -3
  24. package/dist/components/Virtualizer.js.map +1 -1
  25. package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
  26. package/dist/editor/editStack.d.ts +1 -1
  27. package/dist/editor/editor.d.ts +14 -6
  28. package/dist/editor/editor.d.ts.map +1 -1
  29. package/dist/editor/editor.js +745 -553
  30. package/dist/editor/editor.js.map +1 -1
  31. package/dist/editor/editor2.js +6 -0
  32. package/dist/editor/editor2.js.map +1 -0
  33. package/dist/editor/lineAnnotations.d.ts +2 -1
  34. package/dist/editor/lineAnnotations.d.ts.map +1 -1
  35. package/dist/editor/lineAnnotations.js +111 -1
  36. package/dist/editor/lineAnnotations.js.map +1 -1
  37. package/dist/editor/marker.d.ts +33 -0
  38. package/dist/editor/marker.d.ts.map +1 -0
  39. package/dist/editor/marker.js +185 -0
  40. package/dist/editor/marker.js.map +1 -0
  41. package/dist/editor/pieceTable.d.ts +3 -3
  42. package/dist/editor/pieceTable.d.ts.map +1 -1
  43. package/dist/editor/pieceTable.js +44 -33
  44. package/dist/editor/pieceTable.js.map +1 -1
  45. package/dist/editor/searchPanel.d.ts +6 -7
  46. package/dist/editor/searchPanel.d.ts.map +1 -1
  47. package/dist/editor/searchPanel.js +103 -138
  48. package/dist/editor/searchPanel.js.map +1 -1
  49. package/dist/editor/selection.d.ts +19 -3
  50. package/dist/editor/selection.d.ts.map +1 -1
  51. package/dist/editor/selection.js +196 -39
  52. package/dist/editor/selection.js.map +1 -1
  53. package/dist/editor/{quickEdit.d.ts → selectionAction.d.ts} +8 -8
  54. package/dist/editor/selectionAction.d.ts.map +1 -0
  55. package/dist/editor/{quickEdit.js → selectionAction.js} +19 -21
  56. package/dist/editor/selectionAction.js.map +1 -0
  57. package/dist/editor/sprite.d.ts +8 -0
  58. package/dist/editor/sprite.d.ts.map +1 -0
  59. package/dist/editor/sprite.js +45 -0
  60. package/dist/editor/sprite.js.map +1 -0
  61. package/dist/editor/textDocument.d.ts +5 -5
  62. package/dist/editor/textDocument.d.ts.map +1 -1
  63. package/dist/editor/textDocument.js +9 -9
  64. package/dist/editor/textDocument.js.map +1 -1
  65. package/dist/editor/textMeasure.js +3 -3
  66. package/dist/editor/textMeasure.js.map +1 -1
  67. package/dist/editor/tokenzier.d.ts +6 -2
  68. package/dist/editor/tokenzier.d.ts.map +1 -1
  69. package/dist/editor/tokenzier.js +135 -85
  70. package/dist/editor/tokenzier.js.map +1 -1
  71. package/dist/editor/utils.d.ts +3 -1
  72. package/dist/editor/utils.d.ts.map +1 -1
  73. package/dist/editor/utils.js +16 -1
  74. package/dist/editor/utils.js.map +1 -1
  75. package/dist/highlighter/shared_highlighter.js +3 -29
  76. package/dist/highlighter/shared_highlighter.js.map +1 -1
  77. package/dist/highlighter/themes/attachResolvedThemes.js +4 -3
  78. package/dist/highlighter/themes/attachResolvedThemes.js.map +1 -1
  79. package/dist/highlighter/themes/cleanUpResolvedThemes.js +3 -2
  80. package/dist/highlighter/themes/cleanUpResolvedThemes.js.map +1 -1
  81. package/dist/highlighter/themes/constants.d.ts +1 -7
  82. package/dist/highlighter/themes/constants.d.ts.map +1 -1
  83. package/dist/highlighter/themes/constants.js +1 -4
  84. package/dist/highlighter/themes/constants.js.map +1 -1
  85. package/dist/highlighter/themes/getResolvedOrResolveTheme.js +2 -2
  86. package/dist/highlighter/themes/getResolvedOrResolveTheme.js.map +1 -1
  87. package/dist/highlighter/themes/getResolvedThemes.js +2 -8
  88. package/dist/highlighter/themes/getResolvedThemes.js.map +1 -1
  89. package/dist/highlighter/themes/hasResolvedThemes.js +2 -3
  90. package/dist/highlighter/themes/hasResolvedThemes.js.map +1 -1
  91. package/dist/highlighter/themes/registerCustomCSSVariableTheme.js +1 -1
  92. package/dist/highlighter/themes/registerCustomTheme.d.ts +5 -3
  93. package/dist/highlighter/themes/registerCustomTheme.d.ts.map +1 -1
  94. package/dist/highlighter/themes/registerCustomTheme.js +15 -5
  95. package/dist/highlighter/themes/registerCustomTheme.js.map +1 -1
  96. package/dist/highlighter/themes/resolveTheme.js +6 -27
  97. package/dist/highlighter/themes/resolveTheme.js.map +1 -1
  98. package/dist/highlighter/themes/resolveThemes.js +5 -12
  99. package/dist/highlighter/themes/resolveThemes.js.map +1 -1
  100. package/dist/highlighter/themes/themeResolution.d.ts +8 -0
  101. package/dist/highlighter/themes/themeResolution.d.ts.map +1 -0
  102. package/dist/highlighter/themes/themeResolution.js +22 -0
  103. package/dist/highlighter/themes/themeResolution.js.map +1 -0
  104. package/dist/highlighter/themes/themeResolver.d.ts +8 -0
  105. package/dist/highlighter/themes/themeResolver.d.ts.map +1 -0
  106. package/dist/highlighter/themes/themeResolver.js +8 -0
  107. package/dist/highlighter/themes/themeResolver.js.map +1 -0
  108. package/dist/index.d.ts +4 -4
  109. package/dist/index.js +3 -3
  110. package/dist/react/index.d.ts +2 -2
  111. package/dist/react/jsx.d.ts.map +1 -1
  112. package/dist/react/utils/useFileDiffInstance.js +1 -0
  113. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  114. package/dist/renderers/DiffHunksRenderer.d.ts +4 -1
  115. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  116. package/dist/renderers/DiffHunksRenderer.js +139 -19
  117. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  118. package/dist/renderers/FileRenderer.d.ts +2 -2
  119. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  120. package/dist/renderers/FileRenderer.js +5 -5
  121. package/dist/renderers/FileRenderer.js.map +1 -1
  122. package/dist/ssr/index.d.ts +2 -2
  123. package/dist/style.js +1 -1
  124. package/dist/style.js.map +1 -1
  125. package/dist/types.d.ts +19 -16
  126. package/dist/types.d.ts.map +1 -1
  127. package/dist/utils/computeEstimatedDiffHeights.js +9 -20
  128. package/dist/utils/computeEstimatedDiffHeights.js.map +1 -1
  129. package/dist/utils/getHighlighterThemeStyles.js +16 -12
  130. package/dist/utils/getHighlighterThemeStyles.js.map +1 -1
  131. package/dist/utils/iterateOverDiff.js +147 -182
  132. package/dist/utils/iterateOverDiff.js.map +1 -1
  133. package/dist/utils/parsePatchFiles.js +93 -4
  134. package/dist/utils/parsePatchFiles.js.map +1 -1
  135. package/dist/utils/updateDiffHunks.d.ts +13 -0
  136. package/dist/utils/updateDiffHunks.d.ts.map +1 -0
  137. package/dist/utils/updateDiffHunks.js +171 -0
  138. package/dist/utils/updateDiffHunks.js.map +1 -0
  139. package/dist/utils/virtualDiffLayout.d.ts +24 -2
  140. package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
  141. package/dist/utils/virtualDiffLayout.js +49 -1
  142. package/dist/utils/virtualDiffLayout.js.map +1 -1
  143. package/dist/worker/WorkerPoolManager.js +1 -1
  144. package/dist/worker/WorkerPoolManager.js.map +1 -1
  145. package/dist/worker/{wasm-D4DU5jgR.js → wasm-BaDzIkIn.js} +2 -2
  146. package/dist/worker/wasm-BaDzIkIn.js.map +1 -0
  147. package/dist/worker/worker-portable.js +1021 -314
  148. package/dist/worker/worker-portable.js.map +1 -1
  149. package/dist/worker/worker.js +202 -196
  150. package/dist/worker/worker.js.map +1 -1
  151. package/package.json +4 -2
  152. package/dist/editor/css.d.ts +0 -6
  153. package/dist/editor/css.d.ts.map +0 -1
  154. package/dist/editor/css.js +0 -218
  155. package/dist/editor/css.js.map +0 -1
  156. package/dist/editor/quickEdit.d.ts.map +0 -1
  157. package/dist/editor/quickEdit.js.map +0 -1
  158. package/dist/worker/wasm-D4DU5jgR.js.map +0 -1
@@ -1,116 +1,111 @@
1
1
  import { isPrimaryModifier } from "./platform.js";
2
2
  import { h } from "./utils.js";
3
+ import { getEditorIconSvg } from "./sprite.js";
3
4
 
4
5
  //#region src/editor/searchPanel.ts
5
6
  var SearchPanelWidget = class {
6
- #textDocument;
7
7
  #container;
8
8
  #inputElement;
9
- #matchesElement;
10
- #searchParams = {
11
- text: "",
12
- replaceText: "",
13
- caseSensitive: false,
14
- wholeWord: false,
15
- regex: false
16
- };
17
- #allMatches = [];
18
9
  constructor(options) {
19
- const { textDocument, containerElement, defaultQuery, initialMatch, postSearch, getCurrentSearchRange, onClose } = options;
20
- const close = () => {
21
- this.cleanup();
22
- onClose();
10
+ const { textDocument, containerElement, defaultQuery, initialMatch, scrollToMatch, onUpdate, onClose } = options;
11
+ const searchParams = {
12
+ text: defaultQuery,
13
+ replaceText: "",
14
+ caseSensitive: false,
15
+ wholeWord: false,
16
+ regex: false
23
17
  };
24
- const updateSearchParam = (key, value) => {
25
- this.#searchParams[key] = value;
26
- updateAllMatches();
27
- this.updateMatches();
18
+ const matches = {
19
+ all: [],
20
+ current: void 0
28
21
  };
29
- const updateAllMatches = () => {
30
- this.#allMatches = this.#searchParams.text !== "" ? this.#textDocument.search("findAll", this.#searchParams) : [];
22
+ const matchResultElement = h("div", { dataset: "matches" });
23
+ const updateMatches = () => {
24
+ matches.all = searchParams.text !== "" ? textDocument.search(searchParams) : [];
31
25
  this.#container.querySelectorAll("[data-disabled]").forEach((element) => {
32
- element.dataset.disabled = String(this.#allMatches.length === 0);
26
+ element.dataset.disabled = String(matches.all.length === 0);
33
27
  });
28
+ if (searchParams.text === "") {
29
+ matchResultElement.textContent = "";
30
+ delete matchResultElement.dataset.noMatches;
31
+ return;
32
+ }
33
+ if (matches.all.length === 0) {
34
+ matchResultElement.textContent = "No results";
35
+ matchResultElement.dataset.noMatches = "";
36
+ } else {
37
+ delete matchResultElement.dataset.noMatches;
38
+ updateCurrentMatch(onUpdate(matches.all));
39
+ return;
40
+ }
41
+ matches.current = void 0;
42
+ onUpdate([]);
34
43
  };
35
- const search = (kind, retainFocus) => {
36
- const matches = this.#textDocument.search(kind, this.#searchParams, getCurrentSearchRange());
37
- if (matches.length === 0) return;
38
- const firstMatch = matches[0];
39
- this.updateMatches(firstMatch);
40
- postSearch(kind, firstMatch, retainFocus);
44
+ const updateCurrentMatch = (currentMatch) => {
45
+ if (currentMatch === void 0) matchResultElement.textContent = `${matches.all.length} results`;
46
+ else {
47
+ const [start, end] = currentMatch;
48
+ matchResultElement.textContent = `${matches.all.findIndex((m) => m[0] === start && m[1] === end) + 1} of ${matches.all.length}`;
49
+ }
50
+ matches.current = currentMatch;
51
+ };
52
+ const updateSearchParam = (key, value) => {
53
+ searchParams[key] = value;
54
+ updateMatches();
41
55
  };
42
- const settingsSwitch = h("div", {
43
- dataset: { icon: "settings" },
44
- title: "Settings",
45
- innerHTML: `<svg width="16" height="16" viewBox="0 0 20 20">
46
- <line x1="3" y1="6" x2="10" y2="6" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
47
- <circle cx="12.5" cy="6" r="2.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></circle>
48
- <line x1="15" y1="6" x2="17" y2="6" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
49
- <line x1="17" y1="14" x2="10" y2="14" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
50
- <circle cx="7.5" cy="14" r="2.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></circle>
51
- <line x1="5" y1="14" x2="3" y2="14" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
52
- </svg>
53
- `,
54
- onclick: () => {
55
- settingsSwitch.replaceWith(settingsPanel);
56
+ const findNextMatch = (findPrevious = false, retainFocus = false) => {
57
+ const allMatches = matches.all;
58
+ let nextMatch = allMatches[0];
59
+ if (allMatches.length > 0) if (findPrevious) {
60
+ const searchOffset = matches.current?.[0] ?? 0;
61
+ nextMatch = allMatches.at(-1);
62
+ for (const m of allMatches) if (m[1] <= searchOffset) nextMatch = m;
63
+ else break;
64
+ } else {
65
+ const searchOffset = matches.current?.[1] ?? 0;
66
+ for (const m of allMatches) if (m[0] >= searchOffset) {
67
+ nextMatch = m;
68
+ break;
69
+ }
56
70
  }
57
- });
58
- const settingsPanel = h("div", {
59
- dataset: "settings",
60
- children: [
61
- h("label", {
62
- dataset: "checkbox",
63
- children: [h("input", {
64
- type: "checkbox",
65
- checked: this.#searchParams.caseSensitive,
66
- onchange: (e) => {
67
- updateSearchParam("caseSensitive", e.target.checked);
68
- }
69
- }), "Match Case"]
70
- }),
71
- h("label", {
72
- dataset: "checkbox",
73
- children: [h("input", {
74
- type: "checkbox",
75
- checked: this.#searchParams.wholeWord,
76
- onchange: (e) => {
77
- updateSearchParam("wholeWord", e.target.checked);
78
- }
79
- }), "Whole Word"]
80
- }),
81
- h("label", {
82
- dataset: "checkbox",
83
- children: [h("input", {
84
- type: "checkbox",
85
- checked: this.#searchParams.regex,
86
- onchange: (e) => {
87
- updateSearchParam("regex", e.target.checked);
88
- }
89
- }), "Regexp"]
90
- })
91
- ],
92
- onmouseleave: () => {
93
- closeSettingsPanelTimeout = setTimeout(() => {
94
- settingsPanel.replaceWith(settingsSwitch);
95
- }, 500);
96
- },
97
- onmouseenter: () => {
98
- clearTimeout(closeSettingsPanelTimeout);
99
- closeSettingsPanelTimeout = void 0;
71
+ if (nextMatch !== void 0) {
72
+ updateCurrentMatch(nextMatch);
73
+ scrollToMatch(nextMatch, retainFocus);
100
74
  }
101
- });
102
- let closeSettingsPanelTimeout;
103
- this.#textDocument = textDocument;
104
- this.#searchParams.text = defaultQuery;
75
+ matches.current = nextMatch;
76
+ };
77
+ const close = () => {
78
+ this.cleanup();
79
+ onClose();
80
+ };
81
+ const makeToggle = (icon, title, key) => {
82
+ const button = h("div", {
83
+ dataset: {
84
+ icon,
85
+ active: String(searchParams[key])
86
+ },
87
+ title,
88
+ innerHTML: getEditorIconSvg(icon),
89
+ onclick: () => {
90
+ const next = !searchParams[key];
91
+ button.dataset.active = String(next);
92
+ updateSearchParam(key, next);
93
+ }
94
+ });
95
+ return button;
96
+ };
97
+ const caseSensitiveToggle = makeToggle("case", "Match Case", "caseSensitive");
98
+ const wholeWordToggle = makeToggle("whole-word", "Whole Word", "wholeWord");
99
+ const regexToggle = makeToggle("regex", "Regexp", "regex");
105
100
  this.#inputElement = h("input", {
106
101
  type: "text",
107
102
  placeholder: "Search",
108
103
  dataset: "search",
109
104
  value: defaultQuery,
110
105
  oninput: (e) => {
111
- this.#searchParams.text = e.target.value;
112
- updateAllMatches();
113
- this.updateMatches();
106
+ searchParams.text = e.target.value;
107
+ matches.current = void 0;
108
+ updateMatches();
114
109
  },
115
110
  onkeydown: (e) => {
116
111
  if (e.key === "Escape") {
@@ -118,38 +113,34 @@ var SearchPanelWidget = class {
118
113
  close();
119
114
  } else if (e.key === "Enter") {
120
115
  e.preventDefault();
121
- search("findNext", true);
116
+ findNextMatch(false, true);
122
117
  } else if (e.key === "f" && isPrimaryModifier(e)) e.preventDefault();
123
118
  }
124
119
  });
125
- this.#matchesElement = h("div", { dataset: "matches" });
126
120
  this.#container = h("div", {
127
- dataset: "searchPanel",
121
+ dataset: ["searchPanel", "editorWidget"],
128
122
  children: [h("div", {
129
123
  dataset: "searchPanelRow",
130
124
  children: [
131
125
  h("div", {
132
126
  dataset: { icon: "search" },
133
- innerHTML: `<svg width="16" height="16" viewBox="0 0 20 20">
134
- <line x1="16.5" y1="16.5" x2="12.0355" y2="12.0355" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
135
- <circle cx="8.5" cy="8.5" r="5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></circle>
136
- </svg>
137
- `
127
+ innerHTML: getEditorIconSvg("search")
138
128
  }),
139
129
  this.#inputElement,
140
- this.#matchesElement,
130
+ matchResultElement,
131
+ caseSensitiveToggle,
132
+ wholeWordToggle,
133
+ regexToggle,
134
+ h("div", { dataset: "divider" }),
141
135
  h("div", {
142
136
  dataset: {
143
137
  icon: "arrow-up",
144
138
  disabled: "true"
145
139
  },
146
140
  title: "Previous",
147
- innerHTML: `<svg width="14" height="14" viewBox="0 0 20 20">
148
- <polyline points="12.5 3.5 6 10 12.5 16.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></polyline>
149
- </svg>
150
- `,
141
+ innerHTML: getEditorIconSvg("arrow-up"),
151
142
  onclick: () => {
152
- search("findPrevious");
143
+ findNextMatch(true);
153
144
  }
154
145
  }),
155
146
  h("div", {
@@ -158,56 +149,30 @@ var SearchPanelWidget = class {
158
149
  disabled: "true"
159
150
  },
160
151
  title: "Next",
161
- innerHTML: `<svg width="14" height="14" viewBox="0 0 20 20">
162
- <polyline points="7.5 16.5 14 10 7.5 3.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></polyline>
163
- </svg>
164
- `,
152
+ innerHTML: getEditorIconSvg("arrow-down"),
165
153
  onclick: () => {
166
- search("findNext");
154
+ findNextMatch();
167
155
  }
168
156
  }),
169
- h("div", { dataset: "spacer" }),
170
- settingsSwitch,
171
157
  h("div", {
172
158
  dataset: { icon: "close" },
173
159
  title: "Close",
174
- innerHTML: `<svg width="16" height="16" viewBox="0 0 20 20">
175
- <line x1="5" y1="5" x2="15" y2="15" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
176
- <line x1="5" y1="15" x2="15" y2="5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line>
177
- </svg>
178
- `,
160
+ innerHTML: getEditorIconSvg("close"),
179
161
  onclick: close
180
162
  })
181
163
  ]
182
164
  })]
183
165
  });
166
+ matches.current = initialMatch;
184
167
  containerElement.before(this.#container);
185
168
  requestAnimationFrame(() => {
186
- if (initialMatch !== void 0) {
187
- updateAllMatches();
188
- this.updateMatches(initialMatch);
189
- }
169
+ if (initialMatch !== void 0) updateMatches();
170
+ else onUpdate([]);
190
171
  this.#inputElement.select();
191
172
  });
192
173
  }
193
- updateMatches(currentMatch = this.#allMatches[0]) {
194
- const allMatches = this.#allMatches;
195
- if (this.#searchParams.text === "") {
196
- this.#matchesElement.textContent = "";
197
- delete this.#matchesElement.dataset.noMatches;
198
- return;
199
- }
200
- if (allMatches.length === 0) {
201
- this.#matchesElement.textContent = "No results";
202
- this.#matchesElement.dataset.noMatches = "";
203
- } else {
204
- delete this.#matchesElement.dataset.noMatches;
205
- const index = allMatches.findIndex((m) => m[0] === currentMatch[0] && m[1] === currentMatch[1]);
206
- this.#matchesElement.textContent = index !== -1 ? `${index + 1} of ${allMatches.length}` : "No results";
207
- }
208
- }
209
174
  focus() {
210
- this.#inputElement.select();
175
+ this.#inputElement.focus();
211
176
  }
212
177
  cleanup() {
213
178
  this.#container.remove();
@@ -1 +1 @@
1
- {"version":3,"file":"searchPanel.js","names":["#searchParams","#allMatches","#textDocument","#container","closeSettingsPanelTimeout: ReturnType<typeof setTimeout> | undefined","#inputElement","#matchesElement"],"sources":["../../src/editor/searchPanel.ts"],"sourcesContent":["import { isPrimaryModifier } from './platform';\nimport type { Range, TextDocument } from './textDocument';\nimport { h } from './utils';\n\nexport type SearchKind =\n | 'findNext'\n | 'findPrevious'\n | 'findAll'\n | 'replace'\n | 'replaceAll';\n\nexport interface SearchParams {\n text: string;\n replaceText: string;\n caseSensitive: boolean;\n wholeWord: boolean;\n regex: boolean;\n}\n\nexport interface SearchPanelOptions {\n textDocument: TextDocument<unknown>;\n containerElement: HTMLElement;\n defaultQuery: string;\n initialMatch?: [number, number];\n postSearch: (\n kind: SearchKind,\n match: [number, number],\n retainFocus?: boolean\n ) => void;\n getCurrentSearchRange: () => Range | undefined;\n onClose: () => void;\n}\n\nexport class SearchPanelWidget {\n #textDocument: TextDocument<unknown>;\n #container: HTMLDivElement;\n #inputElement: HTMLInputElement;\n #matchesElement: HTMLDivElement;\n #searchParams: SearchParams = {\n text: '',\n replaceText: '',\n caseSensitive: false,\n wholeWord: false,\n regex: false,\n };\n #allMatches: [number, number][] = [];\n\n constructor(options: SearchPanelOptions) {\n const {\n textDocument,\n containerElement,\n defaultQuery,\n initialMatch,\n postSearch,\n getCurrentSearchRange,\n onClose,\n } = options;\n\n const close = () => {\n this.cleanup();\n onClose();\n };\n\n const updateSearchParam = <K extends keyof SearchParams>(\n key: K,\n value: SearchParams[K]\n ) => {\n this.#searchParams[key] = value;\n updateAllMatches();\n this.updateMatches();\n };\n\n const updateAllMatches = () => {\n this.#allMatches =\n this.#searchParams.text !== ''\n ? this.#textDocument.search('findAll', this.#searchParams)\n : [];\n this.#container\n .querySelectorAll<HTMLElement>('[data-disabled]')\n .forEach((element) => {\n element.dataset.disabled = String(this.#allMatches.length === 0);\n });\n };\n\n const search = (kind: SearchKind, retainFocus?: boolean) => {\n const matches = this.#textDocument.search(\n kind,\n this.#searchParams,\n getCurrentSearchRange()\n );\n if (matches.length === 0) {\n return;\n }\n const firstMatch = matches[0];\n this.updateMatches(firstMatch);\n postSearch(kind, firstMatch, retainFocus);\n };\n\n const settingsSwitch = h('div', {\n dataset: { icon: 'settings' },\n title: 'Settings',\n innerHTML: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 20 20\">\n <line x1=\"3\" y1=\"6\" x2=\"10\" y2=\"6\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n <circle cx=\"12.5\" cy=\"6\" r=\"2.5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></circle>\n <line x1=\"15\" y1=\"6\" x2=\"17\" y2=\"6\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n <line x1=\"17\" y1=\"14\" x2=\"10\" y2=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n <circle cx=\"7.5\" cy=\"14\" r=\"2.5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></circle>\n <line x1=\"5\" y1=\"14\" x2=\"3\" y2=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n </svg>\n `,\n onclick: () => {\n settingsSwitch.replaceWith(settingsPanel);\n },\n });\n const settingsPanel = h('div', {\n dataset: 'settings',\n children: [\n h('label', {\n dataset: 'checkbox',\n children: [\n h('input', {\n type: 'checkbox',\n checked: this.#searchParams.caseSensitive,\n onchange: (e: Event) => {\n updateSearchParam(\n 'caseSensitive',\n (e.target as HTMLInputElement).checked\n );\n },\n }),\n 'Match Case',\n ],\n }),\n h('label', {\n dataset: 'checkbox',\n children: [\n h('input', {\n type: 'checkbox',\n checked: this.#searchParams.wholeWord,\n onchange: (e: Event) => {\n updateSearchParam(\n 'wholeWord',\n (e.target as HTMLInputElement).checked\n );\n },\n }),\n 'Whole Word',\n ],\n }),\n h('label', {\n dataset: 'checkbox',\n children: [\n h('input', {\n type: 'checkbox',\n checked: this.#searchParams.regex,\n onchange: (e: Event) => {\n updateSearchParam(\n 'regex',\n (e.target as HTMLInputElement).checked\n );\n },\n }),\n 'Regexp',\n ],\n }),\n ],\n onmouseleave: () => {\n closeSettingsPanelTimeout = setTimeout(() => {\n settingsPanel.replaceWith(settingsSwitch);\n }, 500);\n },\n onmouseenter: () => {\n clearTimeout(closeSettingsPanelTimeout);\n closeSettingsPanelTimeout = undefined;\n },\n });\n\n let closeSettingsPanelTimeout: ReturnType<typeof setTimeout> | undefined;\n\n this.#textDocument = textDocument;\n this.#searchParams.text = defaultQuery;\n\n this.#inputElement = h('input', {\n type: 'text',\n placeholder: 'Search',\n dataset: 'search',\n value: defaultQuery,\n oninput: (e: Event) => {\n this.#searchParams.text = (e.target as HTMLInputElement).value;\n updateAllMatches();\n this.updateMatches();\n },\n onkeydown: (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n close();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n search('findNext', true);\n } else if (e.key === 'f' && isPrimaryModifier(e)) {\n // prevent the default browser search panel open behavior\n e.preventDefault();\n }\n },\n });\n this.#matchesElement = h('div', { dataset: 'matches' });\n this.#container = h('div', {\n dataset: 'searchPanel',\n children: [\n h('div', {\n dataset: 'searchPanelRow',\n children: [\n h('div', {\n dataset: { icon: 'search' },\n innerHTML: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 20 20\">\n <line x1=\"16.5\" y1=\"16.5\" x2=\"12.0355\" y2=\"12.0355\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n <circle cx=\"8.5\" cy=\"8.5\" r=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></circle>\n </svg>\n `,\n }),\n this.#inputElement,\n this.#matchesElement,\n h('div', {\n dataset: { icon: 'arrow-up', disabled: 'true' },\n title: 'Previous',\n innerHTML: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\">\n <polyline points=\"12.5 3.5 6 10 12.5 16.5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></polyline>\n </svg>\n `,\n onclick: () => {\n search('findPrevious');\n },\n }),\n h('div', {\n dataset: { icon: 'arrow-down', disabled: 'true' },\n title: 'Next',\n innerHTML: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 20 20\">\n <polyline points=\"7.5 16.5 14 10 7.5 3.5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></polyline>\n </svg>\n `,\n onclick: () => {\n search('findNext');\n },\n }),\n h('div', { dataset: 'spacer' }),\n settingsSwitch,\n h('div', {\n dataset: { icon: 'close' },\n title: 'Close',\n innerHTML: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 20 20\">\n <line x1=\"5\" y1=\"5\" x2=\"15\" y2=\"15\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n <line x1=\"5\" y1=\"15\" x2=\"15\" y2=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"></line>\n </svg>\n `,\n onclick: close,\n }),\n ],\n }),\n ],\n });\n containerElement.before(this.#container);\n\n requestAnimationFrame(() => {\n if (initialMatch !== undefined) {\n updateAllMatches();\n this.updateMatches(initialMatch);\n }\n this.#inputElement.select();\n });\n }\n\n updateMatches(currentMatch: [number, number] = this.#allMatches[0]): void {\n const allMatches = this.#allMatches;\n const searchText = this.#searchParams.text;\n\n if (searchText === '') {\n this.#matchesElement.textContent = '';\n delete this.#matchesElement.dataset.noMatches;\n return;\n }\n\n if (allMatches.length === 0) {\n this.#matchesElement.textContent = 'No results';\n this.#matchesElement.dataset.noMatches = '';\n } else {\n delete this.#matchesElement.dataset.noMatches;\n const index = allMatches.findIndex(\n (m) => m[0] === currentMatch[0] && m[1] === currentMatch[1]\n );\n this.#matchesElement.textContent =\n index !== -1 ? `${index + 1} of ${allMatches.length}` : 'No results';\n }\n }\n\n focus(): void {\n this.#inputElement.select();\n }\n\n cleanup(): void {\n this.#container.remove();\n }\n}\n"],"mappings":";;;;AAiCA,IAAa,oBAAb,MAA+B;CAC7B;CACA;CACA;CACA;CACA,gBAA8B;EAC5B,MAAM;EACN,aAAa;EACb,eAAe;EACf,WAAW;EACX,OAAO;EACR;CACD,cAAkC,EAAE;CAEpC,YAAY,SAA6B;EACvC,MAAM,EACJ,cACA,kBACA,cACA,cACA,YACA,uBACA,YACE;EAEJ,MAAM,cAAc;AAClB,QAAK,SAAS;AACd,YAAS;;EAGX,MAAM,qBACJ,KACA,UACG;AACH,SAAKA,aAAc,OAAO;AAC1B,qBAAkB;AAClB,QAAK,eAAe;;EAGtB,MAAM,yBAAyB;AAC7B,SAAKC,aACH,MAAKD,aAAc,SAAS,KACxB,MAAKE,aAAc,OAAO,WAAW,MAAKF,aAAc,GACxD,EAAE;AACR,SAAKG,UACF,iBAA8B,kBAAkB,CAChD,SAAS,YAAY;AACpB,YAAQ,QAAQ,WAAW,OAAO,MAAKF,WAAY,WAAW,EAAE;KAChE;;EAGN,MAAM,UAAU,MAAkB,gBAA0B;GAC1D,MAAM,UAAU,MAAKC,aAAc,OACjC,MACA,MAAKF,cACL,uBAAuB,CACxB;AACD,OAAI,QAAQ,WAAW,EACrB;GAEF,MAAM,aAAa,QAAQ;AAC3B,QAAK,cAAc,WAAW;AAC9B,cAAW,MAAM,YAAY,YAAY;;EAG3C,MAAM,iBAAiB,EAAE,OAAO;GAC9B,SAAS,EAAE,MAAM,YAAY;GAC7B,OAAO;GACP,WAAW;;;;;;;;;GASX,eAAe;AACb,mBAAe,YAAY,cAAc;;GAE5C,CAAC;EACF,MAAM,gBAAgB,EAAE,OAAO;GAC7B,SAAS;GACT,UAAU;IACR,EAAE,SAAS;KACT,SAAS;KACT,UAAU,CACR,EAAE,SAAS;MACT,MAAM;MACN,SAAS,MAAKA,aAAc;MAC5B,WAAW,MAAa;AACtB,yBACE,iBACC,EAAE,OAA4B,QAChC;;MAEJ,CAAC,EACF,aACD;KACF,CAAC;IACF,EAAE,SAAS;KACT,SAAS;KACT,UAAU,CACR,EAAE,SAAS;MACT,MAAM;MACN,SAAS,MAAKA,aAAc;MAC5B,WAAW,MAAa;AACtB,yBACE,aACC,EAAE,OAA4B,QAChC;;MAEJ,CAAC,EACF,aACD;KACF,CAAC;IACF,EAAE,SAAS;KACT,SAAS;KACT,UAAU,CACR,EAAE,SAAS;MACT,MAAM;MACN,SAAS,MAAKA,aAAc;MAC5B,WAAW,MAAa;AACtB,yBACE,SACC,EAAE,OAA4B,QAChC;;MAEJ,CAAC,EACF,SACD;KACF,CAAC;IACH;GACD,oBAAoB;AAClB,gCAA4B,iBAAiB;AAC3C,mBAAc,YAAY,eAAe;OACxC,IAAI;;GAET,oBAAoB;AAClB,iBAAa,0BAA0B;AACvC,gCAA4B;;GAE/B,CAAC;EAEF,IAAII;AAEJ,QAAKF,eAAgB;AACrB,QAAKF,aAAc,OAAO;AAE1B,QAAKK,eAAgB,EAAE,SAAS;GAC9B,MAAM;GACN,aAAa;GACb,SAAS;GACT,OAAO;GACP,UAAU,MAAa;AACrB,UAAKL,aAAc,OAAQ,EAAE,OAA4B;AACzD,sBAAkB;AAClB,SAAK,eAAe;;GAEtB,YAAY,MAAqB;AAC/B,QAAI,EAAE,QAAQ,UAAU;AACtB,OAAE,gBAAgB;AAClB,YAAO;eACE,EAAE,QAAQ,SAAS;AAC5B,OAAE,gBAAgB;AAClB,YAAO,YAAY,KAAK;eACf,EAAE,QAAQ,OAAO,kBAAkB,EAAE,CAE9C,GAAE,gBAAgB;;GAGvB,CAAC;AACF,QAAKM,iBAAkB,EAAE,OAAO,EAAE,SAAS,WAAW,CAAC;AACvD,QAAKH,YAAa,EAAE,OAAO;GACzB,SAAS;GACT,UAAU,CACR,EAAE,OAAO;IACP,SAAS;IACT,UAAU;KACR,EAAE,OAAO;MACP,SAAS,EAAE,MAAM,UAAU;MAC3B,WAAW;;;;;MAKZ,CAAC;KACF,MAAKE;KACL,MAAKC;KACL,EAAE,OAAO;MACP,SAAS;OAAE,MAAM;OAAY,UAAU;OAAQ;MAC/C,OAAO;MACP,WAAW;;;;MAIX,eAAe;AACb,cAAO,eAAe;;MAEzB,CAAC;KACF,EAAE,OAAO;MACP,SAAS;OAAE,MAAM;OAAc,UAAU;OAAQ;MACjD,OAAO;MACP,WAAW;;;;MAIX,eAAe;AACb,cAAO,WAAW;;MAErB,CAAC;KACF,EAAE,OAAO,EAAE,SAAS,UAAU,CAAC;KAC/B;KACA,EAAE,OAAO;MACP,SAAS,EAAE,MAAM,SAAS;MAC1B,OAAO;MACP,WAAW;;;;;MAKX,SAAS;MACV,CAAC;KACH;IACF,CAAC,CACH;GACF,CAAC;AACF,mBAAiB,OAAO,MAAKH,UAAW;AAExC,8BAA4B;AAC1B,OAAI,iBAAiB,QAAW;AAC9B,sBAAkB;AAClB,SAAK,cAAc,aAAa;;AAElC,SAAKE,aAAc,QAAQ;IAC3B;;CAGJ,cAAc,eAAiC,MAAKJ,WAAY,IAAU;EACxE,MAAM,aAAa,MAAKA;AAGxB,MAFmB,MAAKD,aAAc,SAEnB,IAAI;AACrB,SAAKM,eAAgB,cAAc;AACnC,UAAO,MAAKA,eAAgB,QAAQ;AACpC;;AAGF,MAAI,WAAW,WAAW,GAAG;AAC3B,SAAKA,eAAgB,cAAc;AACnC,SAAKA,eAAgB,QAAQ,YAAY;SACpC;AACL,UAAO,MAAKA,eAAgB,QAAQ;GACpC,MAAM,QAAQ,WAAW,WACtB,MAAM,EAAE,OAAO,aAAa,MAAM,EAAE,OAAO,aAAa,GAC1D;AACD,SAAKA,eAAgB,cACnB,UAAU,KAAK,GAAG,QAAQ,EAAE,MAAM,WAAW,WAAW;;;CAI9D,QAAc;AACZ,QAAKD,aAAc,QAAQ;;CAG7B,UAAgB;AACd,QAAKF,UAAW,QAAQ"}
1
+ {"version":3,"file":"searchPanel.js","names":["searchParams: SearchParams","#container","nextMatch: MatchRange | undefined","#inputElement"],"sources":["../../src/editor/searchPanel.ts"],"sourcesContent":["import { isPrimaryModifier } from './platform';\nimport { getEditorIconSvg, type SVGSpriteNames } from './sprite';\nimport type { TextDocument } from './textDocument';\nimport { h } from './utils';\n\nexport type MatchRange = [startOffset: number, endOffset: number];\n\nexport interface SearchParams {\n text: string;\n replaceText: string;\n caseSensitive: boolean;\n wholeWord: boolean;\n regex: boolean;\n}\n\nexport interface SearchPanelOptions {\n textDocument: TextDocument<unknown>;\n containerElement: HTMLElement;\n defaultQuery: string;\n initialMatch?: MatchRange;\n scrollToMatch: (nextMatch: MatchRange, retainFocus: boolean) => void;\n onUpdate: (matches: MatchRange[]) => MatchRange | undefined;\n onClose: () => void;\n}\n\nexport class SearchPanelWidget {\n #container: HTMLDivElement;\n #inputElement: HTMLInputElement;\n\n constructor(options: SearchPanelOptions) {\n const {\n textDocument,\n containerElement,\n defaultQuery,\n initialMatch,\n scrollToMatch,\n onUpdate,\n onClose,\n } = options;\n\n const searchParams: SearchParams = {\n text: defaultQuery,\n replaceText: '',\n caseSensitive: false,\n wholeWord: false,\n regex: false,\n };\n\n const matches = {\n all: [] as MatchRange[],\n current: undefined as MatchRange | undefined,\n };\n\n const matchResultElement = h('div', { dataset: 'matches' });\n const updateMatches = () => {\n matches.all =\n searchParams.text !== '' ? textDocument.search(searchParams) : [];\n this.#container\n .querySelectorAll<HTMLElement>('[data-disabled]')\n .forEach((element) => {\n element.dataset.disabled = String(matches.all.length === 0);\n });\n\n if (searchParams.text === '') {\n matchResultElement.textContent = '';\n delete matchResultElement.dataset.noMatches;\n return;\n }\n\n if (matches.all.length === 0) {\n matchResultElement.textContent = 'No results';\n matchResultElement.dataset.noMatches = '';\n } else {\n delete matchResultElement.dataset.noMatches;\n updateCurrentMatch(onUpdate(matches.all));\n return;\n }\n\n matches.current = undefined;\n onUpdate([]);\n };\n\n const updateCurrentMatch = (currentMatch: MatchRange | undefined) => {\n if (currentMatch === undefined) {\n matchResultElement.textContent = `${matches.all.length} results`;\n } else {\n const [start, end] = currentMatch;\n const index = matches.all.findIndex(\n (m) => m[0] === start && m[1] === end\n );\n matchResultElement.textContent = `${index + 1} of ${matches.all.length}`;\n }\n matches.current = currentMatch;\n };\n\n const updateSearchParam = <K extends keyof SearchParams>(\n key: K,\n value: SearchParams[K]\n ) => {\n searchParams[key] = value;\n updateMatches();\n };\n\n const findNextMatch = (\n findPrevious: boolean = false,\n retainFocus: boolean = false\n ) => {\n const allMatches = matches.all;\n let nextMatch: MatchRange | undefined = allMatches[0];\n if (allMatches.length > 0) {\n if (findPrevious) {\n const searchOffset = matches.current?.[0] ?? 0;\n nextMatch = allMatches.at(-1);\n for (const m of allMatches) {\n if (m[1] <= searchOffset) {\n nextMatch = m;\n } else {\n break;\n }\n }\n } else {\n const searchOffset = matches.current?.[1] ?? 0;\n for (const m of allMatches) {\n if (m[0] >= searchOffset) {\n nextMatch = m;\n break;\n }\n }\n }\n }\n if (nextMatch !== undefined) {\n updateCurrentMatch(nextMatch);\n scrollToMatch(nextMatch, retainFocus);\n }\n matches.current = nextMatch;\n };\n\n const close = () => {\n this.cleanup();\n onClose();\n };\n\n // Builds an always-visible icon button that toggles one boolean search\n // option (case/whole-word/regex). The button reflects its on/off state via\n // the `data-active` attribute so the stylesheet can highlight it.\n const makeToggle = (\n icon: SVGSpriteNames,\n title: string,\n key: 'caseSensitive' | 'wholeWord' | 'regex'\n ) => {\n const button = h('div', {\n dataset: { icon, active: String(searchParams[key]) },\n title,\n innerHTML: getEditorIconSvg(icon),\n onclick: () => {\n const next = !searchParams[key];\n button.dataset.active = String(next);\n updateSearchParam(key, next);\n },\n });\n return button;\n };\n\n const caseSensitiveToggle = makeToggle(\n 'case',\n 'Match Case',\n 'caseSensitive'\n );\n const wholeWordToggle = makeToggle('whole-word', 'Whole Word', 'wholeWord');\n const regexToggle = makeToggle('regex', 'Regexp', 'regex');\n\n this.#inputElement = h('input', {\n type: 'text',\n placeholder: 'Search',\n dataset: 'search',\n value: defaultQuery,\n oninput: (e: Event) => {\n searchParams.text = (e.target as HTMLInputElement).value;\n matches.current = undefined;\n updateMatches();\n },\n onkeydown: (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n close();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n findNextMatch(false, true);\n } else if (e.key === 'f' && isPrimaryModifier(e)) {\n // prevent the default browser search panel open behavior\n e.preventDefault();\n }\n },\n });\n\n this.#container = h('div', {\n dataset: ['searchPanel', 'editorWidget'],\n children: [\n h('div', {\n dataset: 'searchPanelRow',\n children: [\n h('div', {\n dataset: { icon: 'search' },\n innerHTML: getEditorIconSvg('search'),\n }),\n this.#inputElement,\n matchResultElement,\n caseSensitiveToggle,\n wholeWordToggle,\n regexToggle,\n h('div', { dataset: 'divider' }),\n h('div', {\n dataset: { icon: 'arrow-up', disabled: 'true' },\n title: 'Previous',\n innerHTML: getEditorIconSvg('arrow-up'),\n onclick: () => {\n findNextMatch(true);\n },\n }),\n h('div', {\n dataset: { icon: 'arrow-down', disabled: 'true' },\n title: 'Next',\n innerHTML: getEditorIconSvg('arrow-down'),\n onclick: () => {\n findNextMatch();\n },\n }),\n h('div', {\n dataset: { icon: 'close' },\n title: 'Close',\n innerHTML: getEditorIconSvg('close'),\n onclick: close,\n }),\n ],\n }),\n ],\n });\n\n matches.current = initialMatch;\n containerElement.before(this.#container);\n\n requestAnimationFrame(() => {\n if (initialMatch !== undefined) {\n updateMatches();\n } else {\n onUpdate([]);\n }\n this.#inputElement.select();\n });\n }\n\n focus(): void {\n this.#inputElement.focus();\n }\n\n cleanup(): void {\n this.#container.remove();\n }\n}\n"],"mappings":"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"}
@@ -56,10 +56,26 @@ declare function applyDeleteHardLineForwardToSelections<LAnnotation>(textDocumen
56
56
  nextSelections: EditorSelection[];
57
57
  change?: TextDocumentChange;
58
58
  };
59
+ /**
60
+ * Deletes from each selection back to the start of its soft (visual) line.
61
+ * Non-collapsed selections delete their selected text instead.
62
+ */
63
+ declare function applyDeleteSoftLineBackwardToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], getSoftLineStart?: (line: number, character: number) => number, lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): {
64
+ nextSelections: EditorSelection[];
65
+ change?: TextDocumentChange;
66
+ };
67
+ /**
68
+ * Deletes the word or separator group immediately before each selection.
69
+ * Non-collapsed selections delete their selected text instead.
70
+ */
71
+ declare function applyDeleteWordBackwardToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): {
72
+ nextSelections: EditorSelection[];
73
+ change?: TextDocumentChange;
74
+ };
59
75
  /**
60
76
  * Checks if a selection is collapsed.
61
77
  */
62
- declare function isCollapsedSelection(selection: EditorSelection): boolean;
78
+ declare function isCollapsedSelection(selection: EditorSelection | Range): boolean;
63
79
  /**
64
80
  * Returns the caret (focus) position for a selection.
65
81
  */
@@ -71,7 +87,7 @@ declare function isLineEditable(lineType: string): boolean;
71
87
  /**
72
88
  * Checks whether selections `a` and `b` intersect.
73
89
  */
74
- declare function selectionIntersects(a: EditorSelection, b: EditorSelection): boolean;
90
+ declare function selectionIntersects(a: EditorSelection | Range, b: EditorSelection | Range): boolean;
75
91
  /**
76
92
  * Compares two positions.
77
93
  */
@@ -122,5 +138,5 @@ declare function getSelectionAnchor(lineElement: HTMLElement, character: number)
122
138
  */
123
139
  declare function expandCollapsedSelectionToWord(textDocument: TextDocument<unknown>, selection: EditorSelection): EditorSelection;
124
140
  //#endregion
125
- export { DirectionBackward, DirectionForward, DirectionNone, EditorSelection, SelectionDirection, applyDeleteHardLineForwardToSelections, applyTextChangeToSelections, applyTextReplaceToSelections, applyTransposeToSelections, comparePosition, convertSelection, createSelectionFrom, createSelectionFromAnchorAndFocusOffsets, expandCollapsedSelectionToWord, extendSelection, extendSelections, findNexMatch, getCaretPosition, getDocumentBoundarySelection, getDocumentFullSelection, getSelectionAnchor, getSelectionText, isCollapsedSelection, isLineEditable, mapCursorMove, mapSelectionShift, mergeOverlappingSelections, resolveIndentEdits, selectionIntersects };
141
+ export { DirectionBackward, DirectionForward, DirectionNone, EditorSelection, SelectionDirection, applyDeleteHardLineForwardToSelections, applyDeleteSoftLineBackwardToSelections, applyDeleteWordBackwardToSelections, applyTextChangeToSelections, applyTextReplaceToSelections, applyTransposeToSelections, comparePosition, convertSelection, createSelectionFrom, createSelectionFromAnchorAndFocusOffsets, expandCollapsedSelectionToWord, extendSelection, extendSelections, findNexMatch, getCaretPosition, getDocumentBoundarySelection, getDocumentFullSelection, getSelectionAnchor, getSelectionText, isCollapsedSelection, isLineEditable, mapCursorMove, mapSelectionShift, mergeOverlappingSelections, resolveIndentEdits, selectionIntersects };
126
142
  //# sourceMappingURL=selection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"selection.d.ts","names":["DiffLineAnnotation","Position","Range","ResolvedTextEdit","TextDocument","TextDocumentChange","TextEdit","DirectionBackward","DirectionNone","DirectionForward","SelectionDirection","EditorSelection","convertSelection","StaticRange","resolveIndentEdits","mapCursorMove","mapSelectionShift","applyTextChangeToSelections","LAnnotation","applyTextReplaceToSelections","applyTransposeToSelections","applyDeleteHardLineForwardToSelections","isCollapsedSelection","getCaretPosition","isLineEditable","selectionIntersects","comparePosition","createSelectionFromAnchorAndFocusOffsets","createSelectionFrom","extendSelection","extendSelections","mergeOverlappingSelections","findNexMatch","getDocumentFullSelection","getDocumentBoundarySelection","getSelectionText","getSelectionAnchor","HTMLElement","Node","expandCollapsedSelectionToWord"],"sources":["../../src/editor/selection.d.ts"],"sourcesContent":["import type { DiffLineAnnotation } from '../types';\nimport type { Position, Range, ResolvedTextEdit, TextDocument, TextDocumentChange, TextEdit } from './textDocument';\nexport declare const DirectionBackward = -1;\nexport declare const DirectionNone = 0;\nexport declare const DirectionForward = 1;\nexport type SelectionDirection = typeof DirectionBackward | typeof DirectionNone | typeof DirectionForward;\nexport interface EditorSelection extends Range {\n direction: SelectionDirection;\n}\n/**\n * Converts a selection from a web selection to an editor selection.\n */\nexport declare function convertSelection(range: StaticRange, direction?: SelectionDirection): EditorSelection | undefined;\n/**\n * Resolves the indent edits for a selection.\n */\nexport declare function resolveIndentEdits(textDocument: TextDocument<unknown>, selection: EditorSelection, tabSize: number, outdent: boolean): [edits: TextEdit[], nextSelection: EditorSelection];\n/**\n * Maps the cursor move to all selections.\n */\nexport declare function mapCursorMove(textDocument: TextDocument<unknown>, selections: EditorSelection[], shortcut: 'textStart' | 'start' | 'end' | 'up' | 'down' | 'left' | 'right'): EditorSelection[];\n/**\n * Same as mapCursorMove, but with shift key pressed.\n */\nexport declare function mapSelectionShift(textDocument: TextDocument<unknown>, selections: EditorSelection[], shortcut: 'textStart' | 'start' | 'end' | 'up' | 'down' | 'left' | 'right'): EditorSelection[];\n/**\n * Applies a text change to the given text document\n */\nexport declare function applyTextChangeToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], edit: ResolvedTextEdit, lineAnnotations?: DiffLineAnnotation<LAnnotation>[], tabSize?: number): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n};\n/**\n * Applies a text replace to multiple selections.\n */\nexport declare function applyTextReplaceToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], texts: string[], lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n};\n/**\n * Swaps the two characters adjacent to a collapsed selection, matching browser\n * insertTranspose (Ctrl+T) behavior.\n */\nexport declare function applyTransposeToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n};\n/**\n * Deletes from each selection to the end of its line, including the line break\n * when the caret is already at the end of a non-final line. Non-collapsed\n * selections delete their selected text instead.\n */\nexport declare function applyDeleteHardLineForwardToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n};\n/**\n * Checks if a selection is collapsed.\n */\nexport declare function isCollapsedSelection(selection: EditorSelection): boolean;\n/**\n * Returns the caret (focus) position for a selection.\n */\nexport declare function getCaretPosition(selection: EditorSelection): Position;\n/**\n * Checks if a line is editable.\n */\nexport declare function isLineEditable(lineType: string): boolean;\n/**\n * Checks whether selections `a` and `b` intersect.\n */\nexport declare function selectionIntersects(a: EditorSelection, b: EditorSelection): boolean;\n/**\n * Compares two positions.\n */\nexport declare function comparePosition(a: Position, b: Position): number;\n/**\n * Creates a selection from anchor and focus offsets.\n */\nexport declare function createSelectionFromAnchorAndFocusOffsets(textDocument: TextDocument<unknown>, anchorOffset: number, focusOffset: number): EditorSelection;\n/**\n * Creates a selection from a anchor and focus selection.\n */\nexport declare function createSelectionFrom(anchorSelection: EditorSelection, focusSelection: EditorSelection): EditorSelection;\n/**\n * Extends or shrinks the selection `original` using the endpoints of `target`, \\\n * matching contenteditable shift + click extend behavior.\n */\nexport declare function extendSelection(original: EditorSelection, target: EditorSelection): EditorSelection;\n/**\n * Extends multiple selections.\n */\nexport declare function extendSelections(selections: EditorSelection[], target: EditorSelection): EditorSelection[];\n/**\n * Merges overlapping selections.\n */\nexport declare function mergeOverlappingSelections(selections: EditorSelection[]): EditorSelection[];\n/**\n * Finds the next matching word and updates the selections.\n */\nexport declare function findNexMatch(textDocument: TextDocument<unknown>, selections: EditorSelection[]): EditorSelection[] | undefined;\n/**\n * Get the full selection of the document.\n */\nexport declare function getDocumentFullSelection(textDocument: TextDocument<unknown>): EditorSelection;\n/**\n * Get the boundary selection of the document.\n */\nexport declare function getDocumentBoundarySelection(textDocument: TextDocument<unknown>, atEnd: boolean): EditorSelection;\n/**\n * Get the text of the selections for the given text document.\n */\nexport declare function getSelectionText(textDocument: TextDocument<unknown>, selections: EditorSelection[]): string;\n/**\n * Get the anchor node and offset for a selection.\n */\nexport declare function getSelectionAnchor(lineElement: HTMLElement, character: number): [Node, number];\n/**\n * Expands a zero-width selection to the word-like segment that contains the caret.\n */\nexport declare function expandCollapsedSelectionToWord(textDocument: TextDocument<unknown>, selection: EditorSelection): EditorSelection;\n//# sourceMappingURL=selection.d.ts.map"],"mappings":"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"}
1
+ {"version":3,"file":"selection.d.ts","names":["DiffLineAnnotation","Position","Range","ResolvedTextEdit","TextDocument","TextDocumentChange","TextEdit","DirectionBackward","DirectionNone","DirectionForward","SelectionDirection","EditorSelection","convertSelection","StaticRange","resolveIndentEdits","mapCursorMove","mapSelectionShift","applyTextChangeToSelections","LAnnotation","applyTextReplaceToSelections","applyTransposeToSelections","applyDeleteHardLineForwardToSelections","applyDeleteSoftLineBackwardToSelections","applyDeleteWordBackwardToSelections","isCollapsedSelection","getCaretPosition","isLineEditable","selectionIntersects","comparePosition","createSelectionFromAnchorAndFocusOffsets","createSelectionFrom","extendSelection","extendSelections","mergeOverlappingSelections","findNexMatch","getDocumentFullSelection","getDocumentBoundarySelection","getSelectionText","getSelectionAnchor","HTMLElement","Node","expandCollapsedSelectionToWord"],"sources":["../../src/editor/selection.d.ts"],"sourcesContent":["import type { DiffLineAnnotation } from '../types';\nimport type { Position, Range, ResolvedTextEdit, TextDocument, TextDocumentChange, TextEdit } from './textDocument';\nexport declare const DirectionBackward = -1;\nexport declare const DirectionNone = 0;\nexport declare const DirectionForward = 1;\nexport type SelectionDirection = typeof DirectionBackward | typeof DirectionNone | typeof DirectionForward;\nexport interface EditorSelection extends Range {\n direction: SelectionDirection;\n}\n/**\n * Converts a selection from a web selection to an editor selection.\n */\nexport declare function convertSelection(range: StaticRange, direction?: SelectionDirection): EditorSelection | undefined;\n/**\n * Resolves the indent edits for a selection.\n */\nexport declare function resolveIndentEdits(textDocument: TextDocument<unknown>, selection: EditorSelection, tabSize: number, outdent: boolean): [edits: TextEdit[], nextSelection: EditorSelection];\n/**\n * Maps the cursor move to all selections.\n */\nexport declare function mapCursorMove(textDocument: TextDocument<unknown>, selections: EditorSelection[], shortcut: 'textStart' | 'start' | 'end' | 'up' | 'down' | 'left' | 'right'): EditorSelection[];\n/**\n * Same as mapCursorMove, but with shift key pressed.\n */\nexport declare function mapSelectionShift(textDocument: TextDocument<unknown>, selections: EditorSelection[], shortcut: 'textStart' | 'start' | 'end' | 'up' | 'down' | 'left' | 'right'): EditorSelection[];\n/**\n * Applies a text change to the given text document\n */\nexport declare function applyTextChangeToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], edit: ResolvedTextEdit, lineAnnotations?: DiffLineAnnotation<LAnnotation>[], tabSize?: number): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n};\n/**\n * Applies a text replace to multiple selections.\n */\nexport declare function applyTextReplaceToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], texts: string[], lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n};\n/**\n * Swaps the two characters adjacent to a collapsed selection, matching browser\n * insertTranspose (Ctrl+T) behavior.\n */\nexport declare function applyTransposeToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n};\n/**\n * Deletes from each selection to the end of its line, including the line break\n * when the caret is already at the end of a non-final line. Non-collapsed\n * selections delete their selected text instead.\n */\nexport declare function applyDeleteHardLineForwardToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n};\n/**\n * Deletes from each selection back to the start of its soft (visual) line.\n * Non-collapsed selections delete their selected text instead.\n */\nexport declare function applyDeleteSoftLineBackwardToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], getSoftLineStart?: (line: number, character: number) => number, lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n};\n/**\n * Deletes the word or separator group immediately before each selection.\n * Non-collapsed selections delete their selected text instead.\n */\nexport declare function applyDeleteWordBackwardToSelections<LAnnotation>(textDocument: TextDocument<LAnnotation>, selections: EditorSelection[], lineAnnotations?: DiffLineAnnotation<LAnnotation>[]): {\n nextSelections: EditorSelection[];\n change?: TextDocumentChange;\n};\n/**\n * Checks if a selection is collapsed.\n */\nexport declare function isCollapsedSelection(selection: EditorSelection | Range): boolean;\n/**\n * Returns the caret (focus) position for a selection.\n */\nexport declare function getCaretPosition(selection: EditorSelection): Position;\n/**\n * Checks if a line is editable.\n */\nexport declare function isLineEditable(lineType: string): boolean;\n/**\n * Checks whether selections `a` and `b` intersect.\n */\nexport declare function selectionIntersects(a: EditorSelection | Range, b: EditorSelection | Range): boolean;\n/**\n * Compares two positions.\n */\nexport declare function comparePosition(a: Position, b: Position): number;\n/**\n * Creates a selection from anchor and focus offsets.\n */\nexport declare function createSelectionFromAnchorAndFocusOffsets(textDocument: TextDocument<unknown>, anchorOffset: number, focusOffset: number): EditorSelection;\n/**\n * Creates a selection from a anchor and focus selection.\n */\nexport declare function createSelectionFrom(anchorSelection: EditorSelection, focusSelection: EditorSelection): EditorSelection;\n/**\n * Extends or shrinks the selection `original` using the endpoints of `target`, \\\n * matching contenteditable shift + click extend behavior.\n */\nexport declare function extendSelection(original: EditorSelection, target: EditorSelection): EditorSelection;\n/**\n * Extends multiple selections.\n */\nexport declare function extendSelections(selections: EditorSelection[], target: EditorSelection): EditorSelection[];\n/**\n * Merges overlapping selections.\n */\nexport declare function mergeOverlappingSelections(selections: EditorSelection[]): EditorSelection[];\n/**\n * Finds the next matching word and updates the selections.\n */\nexport declare function findNexMatch(textDocument: TextDocument<unknown>, selections: EditorSelection[]): EditorSelection[] | undefined;\n/**\n * Get the full selection of the document.\n */\nexport declare function getDocumentFullSelection(textDocument: TextDocument<unknown>): EditorSelection;\n/**\n * Get the boundary selection of the document.\n */\nexport declare function getDocumentBoundarySelection(textDocument: TextDocument<unknown>, atEnd: boolean): EditorSelection;\n/**\n * Get the text of the selections for the given text document.\n */\nexport declare function getSelectionText(textDocument: TextDocument<unknown>, selections: EditorSelection[]): string;\n/**\n * Get the anchor node and offset for a selection.\n */\nexport declare function getSelectionAnchor(lineElement: HTMLElement, character: number): [Node, number];\n/**\n * Expands a zero-width selection to the word-like segment that contains the caret.\n */\nexport declare function expandCollapsedSelectionToWord(textDocument: TextDocument<unknown>, selection: EditorSelection): EditorSelection;\n//# sourceMappingURL=selection.d.ts.map"],"mappings":"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"}