@fusion.dev/helix-headless 0.219.0 → 0.221.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,11 @@
1
- import { AriaForwardController, HelixFormElement, ListedController } from '@fusion.dev/helix-core';
1
+ import { AriaForwardController, findRanges, HelixFormElement, ListedController } from '@fusion.dev/helix-core';
2
2
  import { nothing, type PropertyValues, type TemplateResult } from 'lit';
3
3
  import '../../button/index.js';
4
+ import '../../find/index.js';
4
5
  import '../../icon-button/index.js';
5
6
  import '../../toolbar/index.js';
6
7
  /** A problem in the text, from a linter or a language server, by where it is. */
7
- export interface EditorDiagnostic {
8
+ export interface CodeEditorDiagnostic {
8
9
  /** Where it starts and ends, as offsets into the value. */
9
10
  from: number;
10
11
  message: string;
@@ -13,8 +14,8 @@ export interface EditorDiagnostic {
13
14
  tone?: 'danger' | 'info' | 'warning';
14
15
  }
15
16
  /** What an editor shows, which an engine draws. */
16
- export interface EditorEngineState {
17
- diagnostics: readonly EditorDiagnostic[];
17
+ export interface CodeEditorEngineState {
18
+ diagnostics: readonly CodeEditorDiagnostic[];
18
19
  /** The editor's name, for the engine's text area. */
19
20
  label: string;
20
21
  /** The language to highlight, such as `ts`, `css`, `md` or `rust`. Empty is plain text. */
@@ -26,14 +27,14 @@ export interface EditorEngineState {
26
27
  wrap: boolean;
27
28
  }
28
29
  /** What the editor tells the engine, which the engine calls as the reader works. */
29
- export interface EditorEngineListeners {
30
+ export interface CodeEditorEngineListeners {
30
31
  /** The caret or selection moved, as offsets into the value. */
31
32
  caret?(from: number, to: number): void;
32
33
  /** The reader changed the text. Returns whether the change stands, so the engine can refuse one the page refused. */
33
34
  change(value: string): boolean;
34
35
  }
35
36
  /** What the find bar asks an engine to look for. */
36
- export interface EditorFindQuery {
37
+ export interface CodeEditorFindQuery {
37
38
  caseSensitive: boolean;
38
39
  regex: boolean;
39
40
  /** What Replace puts in place of a match. */
@@ -42,12 +43,12 @@ export interface EditorFindQuery {
42
43
  wholeWord: boolean;
43
44
  }
44
45
  /** Where a search stands: how many matches, and which is selected, counting from 0, or -1 for none. */
45
- export interface EditorFindResult {
46
+ export interface CodeEditorFindResult {
46
47
  count: number;
47
48
  index: number;
48
49
  }
49
50
  /** An engine drawing one editor, which the editor drives. */
50
- export interface EditorEngineView {
51
+ export interface CodeEditorEngineView {
51
52
  /** Takes the engine out of the page. */
52
53
  destroy(): void;
53
54
  /**
@@ -55,34 +56,34 @@ export interface EditorEngineView {
55
56
  * or previous from the selected one. Marks every match while the find bar
56
57
  * is open.
57
58
  */
58
- find?(query: EditorFindQuery, direction: 'first' | 'next' | 'previous'): EditorFindResult;
59
+ find?(query: CodeEditorFindQuery, direction: 'first' | 'next' | 'previous'): CodeEditorFindResult;
59
60
  /** Takes the marks a search drew away, as the find bar closes. */
60
61
  findEnd?(): void;
61
62
  /** Puts the caret in the engine's text area. */
62
63
  focus?(): void;
63
64
  /** Replaces the selected match, or every match, and returns where the search stands after. */
64
- replace?(query: EditorFindQuery, all: boolean): EditorFindResult;
65
+ replace?(query: CodeEditorFindQuery, all: boolean): CodeEditorFindResult;
65
66
  /** Selects a range, scrolls it into view and puts the caret there. */
66
67
  select?(from: number, to: number): void;
67
68
  /** Shows a new state: a value set from outside, a language, diagnostics. */
68
- update(state: EditorEngineState): void;
69
+ update(state: CodeEditorEngineState): void;
69
70
  }
70
71
  /**
71
72
  * Something that draws a code editor, such as CodeMirror through
72
- * `@fusion.dev/helix-editor`. The editor hands it an element to draw in.
73
+ * `@fusion.dev/helix-code-editor`. The editor hands it an element to draw in.
73
74
  */
74
- export interface EditorEngine {
75
- mount(parent: HTMLElement, state: EditorEngineState, listeners: EditorEngineListeners): EditorEngineView;
75
+ export interface CodeEditorEngine {
76
+ mount(parent: HTMLElement, state: CodeEditorEngineState, listeners: CodeEditorEngineListeners): CodeEditorEngineView;
76
77
  }
77
78
  /** Each diagnostic's line, counted from 1, by its start, from one pass over the value. */
78
- export declare const diagnosticLines: (value: string, diagnostics: readonly EditorDiagnostic[]) => number[];
79
+ export declare const diagnosticLines: (value: string, diagnostics: readonly CodeEditorDiagnostic[]) => number[];
79
80
  /** The line and column an offset is at, each counted from 1. */
80
81
  export declare const positionOf: (value: string, at: number) => {
81
82
  column: number;
82
83
  line: number;
83
84
  };
84
- /** Where a query matches in a text, as `[from, to]` offsets, with no empty match. */
85
- export declare const findRanges: (text: string, query: EditorFindQuery) => Array<[number, number]>;
85
+ /** Where a query matches in a text, as `[from, to]` offsets, with no empty match. Find's own, from core. */
86
+ export { findRanges };
86
87
  declare const HelixHeadlessCodeEditor_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinFieldInterface) & typeof HelixFormElement;
87
88
  /**
88
89
  * @summary An editor for a file of code, drawn by a code editor you connect.
@@ -91,8 +92,8 @@ declare const HelixHeadlessCodeEditor_base: (new (...args: any[]) => import("@fu
91
92
  * A pane for working on a file: a header with its name, its language and the
92
93
  * page's own actions, the code, the problems in it, and a status line that
93
94
  * says where the caret is. On its own the code is a `<textarea>` in the code
94
- * face. Connect an engine and it draws the code instead: `connectEditor` from
95
- * `@fusion.dev/helix-editor` connects CodeMirror, with highlighting in your
95
+ * face. Connect an engine and it draws the code instead: `connectCodeEditor` from
96
+ * `@fusion.dev/helix-code-editor` connects CodeMirror, with highlighting in your
96
97
  * theme's syntax colors, line numbers, folding, bracket matching and history.
97
98
  * The value, the form, validation and the events stay the editor's, so a page
98
99
  * reads and writes it the same either way.
@@ -118,7 +119,7 @@ declare const HelixHeadlessCodeEditor_base: (new (...args: any[]) => import("@fu
118
119
  *
119
120
  * @since 0.216.0
120
121
  * @status experimental
121
- * @category inputs
122
+ * @category editors
122
123
  * @aliases Code editor, CodeMirror, File editor, IDE, Monaco
123
124
  * @documentation https://fusion.dev/helix/components/code-editor
124
125
  *
@@ -128,6 +129,7 @@ declare const HelixHeadlessCodeEditor_base: (new (...args: any[]) => import("@fu
128
129
  *
129
130
  * @event {Event} change - The reader finished an edit and focus left the code, in the engine or the plain field.
130
131
  * @event {HelixBeforeChangeEvent} helix-before-change - The text is about to change. Cancelable: cancel it to keep the current text.
132
+ * @event {HelixFoundEvent} helix-found - The find bar searched or moved among the matches, with `count` and the selected match's `index`, counting from 0, or -1 for none.
131
133
  * @event {Event} input - Fired after the text changes.
132
134
  *
133
135
  * @csspart body - The box the code is drawn in, between the header and the problems.
@@ -142,9 +144,9 @@ declare const HelixHeadlessCodeEditor_base: (new (...args: any[]) => import("@fu
142
144
  * @csspart diagnostics - The list of problems under the code, while there are any.
143
145
  * @csspart feedback - The message that says what is wrong.
144
146
  * @csspart field - The frame around the header, the code, the problems and the status line.
145
- * @csspart find - The button in the header that opens the find bar.
146
- * @csspart find-bar - The find bar under the header, while it is open.
147
- * @csspart find-button - The Find button's inner button.
147
+ * @csspart find - The find bar under the header, where the reader searches the code: a Find of its own.
148
+ * @csspart find-actions - The find bar's `actions` slot, which the editor fills with nothing.
149
+ * @csspart find-bar - The find bar's strip: the replace toggle, the field, the count, the toolbar, and the replace row while it shows.
148
150
  * @csspart find-close - The button that closes the find bar.
149
151
  * @csspart find-close-button - The close button's inner button.
150
152
  * @csspart find-close-live - The close button's live region, which speaks while the button is pending.
@@ -154,10 +156,11 @@ declare const HelixHeadlessCodeEditor_base: (new (...args: any[]) => import("@fu
154
156
  * @csspart find-controls-toolbar - The box inside the find bar's toolbar that lays its buttons out.
155
157
  * @csspart find-count - Which match is selected, of how many.
156
158
  * @csspart find-field - The field the search is typed in.
157
- * @csspart find-live - The Find button's live region, which speaks while the button is pending.
159
+ * @csspart find-live - The find bar's live region, which says the count as it changes.
158
160
  * @csspart find-match-case - The option that finds only the same case. Pressed while it applies.
159
161
  * @csspart find-match-case-button - The match case button's inner button.
160
162
  * @csspart find-match-case-live - The match case button's live region, which speaks while the button is pending.
163
+ * @csspart find-match-case-pressed - The match case option while it applies, beside `find-match-case`.
161
164
  * @csspart find-match-case-spinner - The ring the match case button turns while it is pending.
162
165
  * @csspart find-match-case-text - The box the match case button's icon sits in.
163
166
  * @csspart find-next - The button that selects the next match.
@@ -173,18 +176,34 @@ declare const HelixHeadlessCodeEditor_base: (new (...args: any[]) => import("@fu
173
176
  * @csspart find-regex - The option that reads the search as a regular expression. Pressed while it applies.
174
177
  * @csspart find-regex-button - The regular expression button's inner button.
175
178
  * @csspart find-regex-live - The regular expression button's live region, which speaks while the button is pending.
179
+ * @csspart find-regex-pressed - The regular expression option while it applies, beside `find-regex`.
176
180
  * @csspart find-regex-spinner - The ring the regular expression button turns while it is pending.
177
181
  * @csspart find-regex-text - The box the regular expression button's icon sits in.
178
- * @csspart find-replace - The button that shows the replace field under the find field. Expanded while it shows.
179
- * @csspart find-replace-button - The find and replace button's inner button.
180
- * @csspart find-replace-live - The find and replace button's live region, which speaks while the button is pending.
181
- * @csspart find-replace-spinner - The ring the find and replace button turns while it is pending.
182
- * @csspart find-replace-text - The box the find and replace button's icon sits in.
183
- * @csspart find-spinner - The ring the Find button turns while it is pending.
184
- * @csspart find-text - The box the Find button's icon sits in.
182
+ * @csspart find-replace - The button that replaces the selected match.
183
+ * @csspart find-replace-all - The button that replaces every match.
184
+ * @csspart find-replace-all-button - The Replace all button's inner button.
185
+ * @csspart find-replace-all-live - The Replace all button's live region, which speaks while the button is pending.
186
+ * @csspart find-replace-all-spinner - The ring the Replace all button turns while it is pending.
187
+ * @csspart find-replace-all-text - The box the Replace all button's words sits in.
188
+ * @csspart find-replace-button - The Replace button's inner button.
189
+ * @csspart find-replace-field - The field the replacement is typed in.
190
+ * @csspart find-replace-live - The Replace button's live region, which speaks while the button is pending.
191
+ * @csspart find-replace-spinner - The ring the Replace button turns while it is pending.
192
+ * @csspart find-replace-text - The box the Replace button's words sits in.
193
+ * @csspart find-replace-toggle - The button that shows the replace field under the find field. Expanded while it shows. Not drawn while `readonly`.
194
+ * @csspart find-replace-toggle-button - The find and replace button's inner button.
195
+ * @csspart find-replace-toggle-live - The find and replace button's live region, which speaks while the button is pending.
196
+ * @csspart find-replace-toggle-spinner - The ring the find and replace button turns while it is pending.
197
+ * @csspart find-replace-toggle-text - The box the find and replace button's icon sits in.
198
+ * @csspart find-toggle - The button in the header that opens and closes the find bar. Expanded while it is open.
199
+ * @csspart find-toggle-button - The Find button's inner button.
200
+ * @csspart find-toggle-live - The Find button's live region, which speaks while the button is pending.
201
+ * @csspart find-toggle-spinner - The ring the Find button turns while it is pending.
202
+ * @csspart find-toggle-text - The box the Find button's icon sits in.
185
203
  * @csspart find-whole-word - The option that finds only whole words. Pressed while it applies.
186
204
  * @csspart find-whole-word-button - The whole word button's inner button.
187
205
  * @csspart find-whole-word-live - The whole word button's live region, which speaks while the button is pending.
206
+ * @csspart find-whole-word-pressed - The whole word option while it applies, beside `find-whole-word`.
188
207
  * @csspart find-whole-word-spinner - The ring the whole word button turns while it is pending.
189
208
  * @csspart find-whole-word-text - The box the whole word button's icon sits in.
190
209
  * @csspart header - The strip above the code: the name, the language, and the controls.
@@ -193,27 +212,14 @@ declare const HelixHeadlessCodeEditor_base: (new (...args: any[]) => import("@fu
193
212
  * @csspart language - The language's name in the header.
194
213
  * @csspart position - The caret's line and column, in the status line.
195
214
  * @csspart problem-count - How many problems there are, in the status line.
196
- * @csspart replace - The button that replaces the selected match.
197
- * @csspart replace-all - The button that replaces every match.
198
- * @csspart replace-all-button - The Replace all button's inner button.
199
- * @csspart replace-all-live - The Replace all button's live region, which speaks while the button is pending.
200
- * @csspart replace-all-spinner - The ring the Replace all button turns while it is pending.
201
- * @csspart replace-all-text - The box the Replace all button's words sit in.
202
- * @csspart replace-button - The Replace button's inner button.
203
- * @csspart replace-field - The field the replacement is typed in.
204
- * @csspart replace-live - The Replace button's live region, which speaks while the button is pending.
205
- * @csspart replace-spinner - The ring the Replace button turns while it is pending.
206
- * @csspart replace-text - The box the Replace button's words sit in.
207
215
  * @csspart status - The strip under the code.
208
216
  * @csspart view - Where an engine draws, while one is connected.
209
217
  *
210
218
  * @cssstate connected - An engine draws the editor.
211
219
  * @cssstate find-open - The find bar is open.
212
220
  * @cssstate invalid - The editor has an error to show, from `required` or your `feedback`.
213
- * @cssstate replace-open - The replace field shows under the find field.
214
221
  */
215
222
  export declare class HelixHeadlessCodeEditor extends HelixHeadlessCodeEditor_base {
216
- protected static markRules: string[];
217
223
  /**
218
224
  * The key this family's words are registered under, its styled tag:
219
225
  * `registerWords('de', { 'helix-code-editor': { findLabel: 'Suchen' } })`.
@@ -229,14 +235,14 @@ export declare class HelixHeadlessCodeEditor extends HelixHeadlessCodeEditor_bas
229
235
  /** How one problem in the list reads. `{line}` is its line and `{message}` what it says. */
230
236
  diagnosticLabel: string;
231
237
  /** The problems in the text, each underlined and listed under the editor. */
232
- diagnostics: readonly EditorDiagnostic[];
238
+ diagnostics: readonly CodeEditorDiagnostic[];
233
239
  /** The list of problems' name. */
234
240
  diagnosticsLabel: string;
235
241
  /**
236
242
  * What draws the editor, such as `codeMirrorEngine()` from
237
- * `@fusion.dev/helix-editor`. Absent, the editor is a plain text field.
243
+ * `@fusion.dev/helix-code-editor`. Absent, the editor is a plain text field.
238
244
  */
239
- engine: EditorEngine | undefined;
245
+ engine: CodeEditorEngine | undefined;
240
246
  /** The name of the find bar's Close button. */
241
247
  findCloseLabel: string;
242
248
  /** The name of the find bar's toolbar, read by screen readers. */
@@ -286,13 +292,10 @@ export declare class HelixHeadlessCodeEditor extends HelixHeadlessCodeEditor_bas
286
292
  wrap: boolean;
287
293
  /** Where the caret is, as an offset into the value. */
288
294
  private caret;
289
- /** Whether the find bar is open. */
295
+ /** Whether the find bar is open, as it last said. */
290
296
  private findOpen;
291
- /** Where the search stands, or nothing before one. */
292
- private found;
293
- /** Whether the replace field shows under the find field. */
294
- private replaceOpen;
295
- private query;
297
+ /** The find bar drawn now, and how a search is reported to it. */
298
+ private find;
296
299
  private view;
297
300
  /** Whether Escape came just before, which lets Tab leave the plain field. */
298
301
  private escaped;
@@ -303,8 +306,6 @@ export declare class HelixHeadlessCodeEditor extends HelixHeadlessCodeEditor_bas
303
306
  /** The textarea, which the form's validity is read from either way. */
304
307
  private get control();
305
308
  private get engineState();
306
- /** Whether the search can be read, which a regular expression may not be. */
307
- private get readable();
308
309
  /** Puts the caret in the editor, as a label pointing at it would. */
309
310
  focus(options?: FocusOptions): void;
310
311
  /** Selects a range of the code and puts the caret there, in the engine or the plain field. */
@@ -319,19 +320,18 @@ export declare class HelixHeadlessCodeEditor extends HelixHeadlessCodeEditor_bas
319
320
  private readonly handleViewFocusOut;
320
321
  /** Opens the find bar, with the selection as the search where one is selected, and puts focus in its field. */
321
322
  private openFind;
322
- /** Closes the find bar, takes the marks away, and puts focus back in the code. */
323
- private closeFind;
323
+ /** Hands the find bar drawn now the editor to search through, once per bar. */
324
+ private attachFind;
325
+ /** The editor, as the find bar searches through it: the engine, or the plain field. */
326
+ private readonly finder;
324
327
  /** Finds the search and selects a match, in the engine or the plain field. */
325
- private search;
326
- /** Replaces the selected match, or every match, through `requestValue`. */
327
- private replace;
328
- /** Turns one of the find bar's options on or off, and searches again with it. */
329
- private toggleOption;
328
+ private findIn;
329
+ /** Replaces the selected match, or every match, through `requestValue`, and finds the next. */
330
+ private replaceIn;
331
+ /** The find bar opened or closed, which the Find button shows. */
332
+ private readonly handleFindToggle;
330
333
  /** The find key opens the find bar from anywhere in the editor, ahead of the browser's own. */
331
334
  private readonly handleKeys;
332
- private readonly handleFindInput;
333
- private readonly handleReplaceInput;
334
- private readonly handleFindKeys;
335
335
  /** An edit in the textarea, which has taken the character already: put back where it is refused. */
336
336
  private readonly handleInput;
337
337
  /** Relayed, because `change` does not cross a shadow boundary on its own. */
@@ -343,14 +343,12 @@ export declare class HelixHeadlessCodeEditor extends HelixHeadlessCodeEditor_bas
343
343
  * Escape came just before it, which lets the reader leave.
344
344
  */
345
345
  private readonly handleKeydown;
346
- /** The words the find bar's count says, or its regular expression's fault. */
347
- private get countText();
348
346
  /** The header: the name, the language, and the toolbar of the page's actions and Find. */
349
347
  protected renderHeader(): TemplateResult;
350
348
  /**
351
- * The find bar, kept in the tree while closed so its fields keep what was
352
- * typed. The fields stand outside the toolbar, which leaves the arrows to a
353
- * text field.
349
+ * The find bar, a Find of the editor's own that searches the engine or the
350
+ * plain field, kept in the tree while closed so its fields keep what was
351
+ * typed. The editor takes the find key itself, so the bar takes none.
354
352
  */
355
353
  protected renderFind(): TemplateResult;
356
354
  /** The problems, each a button that moves the caret to it, in its tone. */
@@ -364,4 +362,3 @@ declare global {
364
362
  'helix-headless-code-editor': HelixHeadlessCodeEditor;
365
363
  }
366
364
  }
367
- export {};