@fusion.dev/helix-headless 0.218.0 → 0.220.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.
Files changed (84) hide show
  1. package/api.json +1 -1
  2. package/custom-elements.json +1 -1
  3. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +13 -2
  4. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +19 -9
  5. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +16 -1
  6. package/dist/breadcrumbs/root/breadcrumbs-root.js +6 -0
  7. package/dist/button/root/button-root.d.ts +33 -0
  8. package/dist/button/root/button-root.js +13 -3
  9. package/dist/canvas/root/canvas-root.d.ts +11 -0
  10. package/dist/canvas/root/canvas-root.js +1 -0
  11. package/dist/chat/composer/chat-composer.d.ts +221 -6
  12. package/dist/chat/composer/chat-composer.js +249 -19
  13. package/dist/chat/message/chat-message.d.ts +7 -0
  14. package/dist/chat/message/chat-message.js +2 -1
  15. package/dist/chat/root/chat-root.d.ts +1 -0
  16. package/dist/chat/root/chat-root.js +1 -1
  17. package/dist/code-editor/root/code-editor-root.d.ts +48 -51
  18. package/dist/code-editor/root/code-editor-root.js +67 -249
  19. package/dist/copy-button/root/copy-button-root.js +3 -3
  20. package/dist/device-screen/root/device-screen-root.d.ts +11 -0
  21. package/dist/device-screen/root/device-screen-root.js +22 -10
  22. package/dist/dialog/root/dialog-root.js +6 -1
  23. package/dist/drilldown/item/drilldown-item.js +1 -1
  24. package/dist/element-events.generated.js +4 -1
  25. package/dist/filter-input/root/filter-input-root.d.ts +4 -3
  26. package/dist/filter-input/root/filter-input-root.js +1 -20
  27. package/dist/find/index.d.ts +1 -0
  28. package/dist/find/index.js +1 -0
  29. package/dist/find/root/find-root.d.ts +314 -0
  30. package/dist/find/root/find-root.js +577 -0
  31. package/dist/graph/root/graph-root.d.ts +11 -0
  32. package/dist/graph/root/graph-root.js +4 -1
  33. package/dist/index.d.ts +1 -0
  34. package/dist/index.js +1 -0
  35. package/dist/input/root/input-root.d.ts +6 -0
  36. package/dist/input/root/input-root.js +7 -0
  37. package/dist/lightbox/root/lightbox-root.d.ts +4 -1
  38. package/dist/lightbox/root/lightbox-root.js +10 -8
  39. package/dist/listbox/root/listbox-root.d.ts +21 -0
  40. package/dist/listbox/root/listbox-root.js +37 -2
  41. package/dist/log/group/log-group.d.ts +18 -3
  42. package/dist/log/group/log-group.js +31 -4
  43. package/dist/log/root/log-root.d.ts +13 -3
  44. package/dist/log/root/log-root.js +5 -2
  45. package/dist/map/root/map-root.d.ts +11 -0
  46. package/dist/map/root/map-root.js +28 -12
  47. package/dist/menu/root/menu-root.d.ts +8 -0
  48. package/dist/menu/root/menu-root.js +22 -1
  49. package/dist/menu/section/menu-section.d.ts +10 -0
  50. package/dist/menu/section/menu-section.js +10 -0
  51. package/dist/meter/index.d.ts +1 -0
  52. package/dist/meter/index.js +1 -0
  53. package/dist/meter/root/meter-root.d.ts +16 -1
  54. package/dist/meter/root/meter-root.js +27 -11
  55. package/dist/meter/segment/meter-segment.d.ts +74 -0
  56. package/dist/meter/segment/meter-segment.js +47 -0
  57. package/dist/scroll-area/root/scroll-area-root.d.ts +20 -3
  58. package/dist/scroll-area/root/scroll-area-root.js +23 -4
  59. package/dist/spatial-bar-chart/bars.d.ts +125 -5
  60. package/dist/spatial-bar-chart/bars.js +194 -17
  61. package/dist/spatial-bar-chart/root/spatial-bar-chart-root.d.ts +148 -6
  62. package/dist/spatial-bar-chart/root/spatial-bar-chart-root.js +285 -16
  63. package/dist/splitter/root/splitter-root.js +1 -0
  64. package/dist/tabs/root/tabs-root.d.ts +4 -0
  65. package/dist/tabs/tab/tab.d.ts +1 -0
  66. package/dist/tabs/tab/tab.js +2 -2
  67. package/dist/tag/root/tag-root.d.ts +1 -1
  68. package/dist/terminal/root/terminal-root.d.ts +60 -32
  69. package/dist/terminal/root/terminal-root.js +82 -178
  70. package/dist/toolbar/root/toolbar-root.d.ts +4 -1
  71. package/dist/tooltip/root/tooltip-root.d.ts +23 -1
  72. package/dist/tooltip/root/tooltip-root.js +28 -5
  73. package/dist/tour/root/tour-root.d.ts +1 -0
  74. package/dist/tour/root/tour-root.js +4 -1
  75. package/dist/tour/stop/tour-stop.js +1 -0
  76. package/dist/tree/item/tree-item.d.ts +11 -0
  77. package/dist/tree/item/tree-item.js +19 -1
  78. package/examples.json +1 -1
  79. package/lint.json +1 -1
  80. package/package.json +5 -5
  81. package/types/jsx.d.ts +2222 -118
  82. package/types/svelte.d.ts +2 -0
  83. package/types/vue.d.ts +468 -19
  84. package/types/words.d.ts +96 -1
@@ -0,0 +1,577 @@
1
+ import { __decorate } from "tslib";
2
+ import { customElement, deepActiveElement, deepContains, drawIcon, elementById, findPattern, formatWords, HelixElement, HelixFoundEvent, MIRROR_RULE, MixinControllerOpen, matchesChord, onApple, stopPress, textFinder, words, } from '@fusion.dev/helix-core';
3
+ import { asterisk, caretDown, caretRight, caretUp, textAa, textAUnderline, x, } from '@fusion.dev/helix-icons';
4
+ import { nothing } from 'lit';
5
+ import { property, state } from 'lit/decorators.js';
6
+ import { keyed } from 'lit/directives/keyed.js';
7
+ import { live } from 'lit/directives/live.js';
8
+ import { html } from 'lit/static-html.js';
9
+ import '../../button/index.js';
10
+ import '../../icon-button/index.js';
11
+ import '../../toolbar/index.js';
12
+ const SEARCHED = ['for', 'matchCase', 'open', 'query', 'regex', 'skip', 'wholeWord'];
13
+ let HelixHeadlessFind = class HelixHeadlessFind extends MixinControllerOpen(HelixElement) {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.closeLabel = 'Close find';
17
+ this.controlsLabel = 'Find controls';
18
+ this.for = '';
19
+ this.invalidLabel = 'Not a valid regular expression';
20
+ this.label = 'Find';
21
+ this.matchCase = false;
22
+ this.matchCaseLabel = 'Match case';
23
+ this.matchesLabel = '{count, plural, =0 {No matches} one {{index} of # match} other {{index} of # matches}}';
24
+ this.nextLabel = 'Next match';
25
+ this.options = 'match-case whole-word regex';
26
+ this.previousLabel = 'Previous match';
27
+ this.query = '';
28
+ this.readOnly = false;
29
+ this.regex = false;
30
+ this.regexLabel = 'Use regular expression';
31
+ this.replaceAllLabel = 'Replace all';
32
+ this.replaceFieldLabel = 'Replace with';
33
+ this.replaceLabel = 'Replace';
34
+ this.replacement = '';
35
+ this.replaceToggleLabel = 'Find and replace';
36
+ this.shortcut = 'mod+f';
37
+ this.skip = '';
38
+ this.wholeWord = false;
39
+ this.wholeWordLabel = 'Match whole word';
40
+ this.result = undefined;
41
+ this.replaceOpen = false;
42
+ this.attached = undefined;
43
+ this.announcement = '';
44
+ this.said = 0;
45
+ this.inside = false;
46
+ this.handleWhere = (event) => {
47
+ this.inside = this.within(event);
48
+ };
49
+ this.handleShortcut = (event) => {
50
+ if (event.defaultPrevented ||
51
+ event.isComposing ||
52
+ this.shortcut === '' ||
53
+ !matchesChord(event, this.shortcut, onApple()) ||
54
+ !(this.inside || this.within(event)) ||
55
+ this.finder === undefined) {
56
+ return;
57
+ }
58
+ event.preventDefault();
59
+ void this.show();
60
+ };
61
+ this.handleInput = (event) => {
62
+ this.query = event.target.value;
63
+ };
64
+ this.handleReplaceInput = (event) => {
65
+ this.replacement = event.target.value;
66
+ };
67
+ this.handleKeys = (event) => {
68
+ if (event.defaultPrevented || event.isComposing) {
69
+ return;
70
+ }
71
+ if (event.key === 'Escape') {
72
+ event.preventDefault();
73
+ event.stopPropagation();
74
+ this.hide();
75
+ return;
76
+ }
77
+ if (event.key !== 'Enter') {
78
+ return;
79
+ }
80
+ const origin = event.composedPath()[0];
81
+ if (!(origin instanceof HTMLInputElement)) {
82
+ return;
83
+ }
84
+ event.preventDefault();
85
+ if (origin.getAttribute('part') === 'replace-field') {
86
+ this.replace(event.metaKey || event.ctrlKey);
87
+ }
88
+ else {
89
+ this.search(event.shiftKey ? 'previous' : 'next');
90
+ }
91
+ };
92
+ }
93
+ static { this.markRules = [MIRROR_RULE]; }
94
+ static { this.words = 'helix-find'; }
95
+ attach(finder) {
96
+ this.endSearch();
97
+ this.attached = finder;
98
+ this.replaceOpen = this.replaceOpen && finder.replace !== undefined;
99
+ if (this.open) {
100
+ queueMicrotask(() => this.search('first'));
101
+ }
102
+ return {
103
+ detach: () => {
104
+ if (this.attached === finder) {
105
+ this.endSearch();
106
+ this.attached = undefined;
107
+ }
108
+ },
109
+ found: (result) => {
110
+ if (this.attached === finder) {
111
+ this.report(result);
112
+ }
113
+ },
114
+ };
115
+ }
116
+ async show() {
117
+ const active = deepActiveElement();
118
+ if (active !== null && !deepContains(this, active)) {
119
+ this.returnTo = active;
120
+ }
121
+ const selected = this.attached ? '' : this.selectedText();
122
+ if (selected !== '') {
123
+ this.query = selected;
124
+ }
125
+ if (!this.requestOpen(true)) {
126
+ return;
127
+ }
128
+ await this.updateComplete;
129
+ const field = this.partNamed('field');
130
+ field?.focus();
131
+ field?.select();
132
+ }
133
+ hide() {
134
+ const active = deepActiveElement();
135
+ const focused = active !== null && deepContains(this, active);
136
+ if (!this.requestOpen(false)) {
137
+ return;
138
+ }
139
+ const back = this.returnTo;
140
+ this.returnTo = undefined;
141
+ if (focused && back?.isConnected) {
142
+ ;
143
+ back.focus();
144
+ }
145
+ }
146
+ next() {
147
+ if (this.open) {
148
+ this.search('next');
149
+ }
150
+ }
151
+ previous() {
152
+ if (this.open) {
153
+ this.search('previous');
154
+ }
155
+ }
156
+ refresh() {
157
+ if (this.open) {
158
+ this.search('first');
159
+ }
160
+ }
161
+ connectedCallback() {
162
+ super.connectedCallback();
163
+ const document = this.ownerDocument;
164
+ document.addEventListener('keydown', this.handleShortcut, true);
165
+ document.addEventListener('pointerdown', this.handleWhere, true);
166
+ document.addEventListener('focusin', this.handleWhere, true);
167
+ }
168
+ disconnectedCallback() {
169
+ super.disconnectedCallback();
170
+ const document = this.ownerDocument;
171
+ document.removeEventListener('keydown', this.handleShortcut, true);
172
+ document.removeEventListener('pointerdown', this.handleWhere, true);
173
+ document.removeEventListener('focusin', this.handleWhere, true);
174
+ this.endSearch();
175
+ }
176
+ firstUpdated(changed) {
177
+ super.firstUpdated(changed);
178
+ this.finishHydration();
179
+ }
180
+ willUpdate(changed) {
181
+ super.willUpdate(changed);
182
+ this.toggleState('replace-open', this.replacing);
183
+ }
184
+ updated(changed) {
185
+ super.updated(changed);
186
+ if (!this.open) {
187
+ if (changed.has('open')) {
188
+ this.endSearch();
189
+ }
190
+ return;
191
+ }
192
+ if (SEARCHED.some((name) => changed.has(name))) {
193
+ queueMicrotask(() => this.search('first'));
194
+ }
195
+ }
196
+ get target() {
197
+ return this.for === '' ? null : elementById(this, this.for);
198
+ }
199
+ get finder() {
200
+ if (this.attached) {
201
+ return this.attached;
202
+ }
203
+ const root = this.target;
204
+ if (root === null) {
205
+ return undefined;
206
+ }
207
+ if (this.own?.root !== root || this.own.skip !== this.skip) {
208
+ this.own?.finder.end();
209
+ this.own = {
210
+ finder: textFinder(root, { found: (result) => this.report(result), skip: this.skip }),
211
+ root,
212
+ skip: this.skip,
213
+ };
214
+ }
215
+ return this.own.finder;
216
+ }
217
+ get findQuery() {
218
+ return {
219
+ caseSensitive: this.matchCase,
220
+ regex: this.regex,
221
+ replace: this.replacement,
222
+ search: this.query,
223
+ wholeWord: this.wholeWord,
224
+ };
225
+ }
226
+ get readable() {
227
+ return this.query === '' || findPattern(this.findQuery) !== undefined;
228
+ }
229
+ get replaceable() {
230
+ return !this.hydrating && !this.readOnly && this.attached?.replace !== undefined;
231
+ }
232
+ get replacing() {
233
+ return this.replaceOpen && this.replaceable;
234
+ }
235
+ get countText() {
236
+ if (!this.readable) {
237
+ return this.invalidLabel;
238
+ }
239
+ return this.result === undefined
240
+ ? ''
241
+ : formatWords(this, 'matchesLabel', {
242
+ count: this.result.count,
243
+ index: Math.max(this.result.index, 0) + 1,
244
+ });
245
+ }
246
+ offers(option) {
247
+ return this.options.split(/\s+/).includes(option);
248
+ }
249
+ selectedText() {
250
+ const selection = this.ownerDocument.getSelection?.();
251
+ const root = this.target;
252
+ const text = selection?.toString() ?? '';
253
+ const anchor = selection?.anchorNode ?? null;
254
+ return root !== null &&
255
+ anchor !== null &&
256
+ root.contains(anchor) &&
257
+ text.trim() !== '' &&
258
+ !/[\r\n]/.test(text)
259
+ ? text
260
+ : '';
261
+ }
262
+ search(direction) {
263
+ const finder = this.finder;
264
+ if (!finder) {
265
+ return;
266
+ }
267
+ if (this.marking !== finder) {
268
+ this.endSearch();
269
+ }
270
+ if (this.query === '' || !this.readable) {
271
+ this.endSearch();
272
+ if (!this.readable) {
273
+ this.say(this.invalidLabel);
274
+ }
275
+ return;
276
+ }
277
+ this.marking = finder;
278
+ const result = finder.find(this.findQuery, direction);
279
+ if (result) {
280
+ this.report(result);
281
+ }
282
+ }
283
+ endSearch() {
284
+ this.marking?.end();
285
+ this.marking = undefined;
286
+ this.result = undefined;
287
+ }
288
+ report(result) {
289
+ if (!this.open) {
290
+ return;
291
+ }
292
+ this.result = result;
293
+ this.say(this.countText);
294
+ this.dispatchEvent(new HelixFoundEvent({ count: result.count, index: result.index }));
295
+ }
296
+ replace(all) {
297
+ const finder = this.finder;
298
+ if (!finder?.replace || this.readOnly || this.query === '' || !this.readable) {
299
+ return;
300
+ }
301
+ const result = finder.replace(this.findQuery, all);
302
+ if (result) {
303
+ this.report(result);
304
+ }
305
+ }
306
+ say(text) {
307
+ this.announcement = text;
308
+ this.said += 1;
309
+ }
310
+ within(event) {
311
+ const path = event.composedPath();
312
+ const root = this.target;
313
+ return path.includes(this) || (root !== null && path.includes(root));
314
+ }
315
+ toggleOption(option) {
316
+ this[option] = !this[option];
317
+ }
318
+ renderReplaceToggle() {
319
+ if (!this.replaceable) {
320
+ return nothing;
321
+ }
322
+ const button = this.tag('icon-button');
323
+ return html `<${button}
324
+ part="replace-toggle"
325
+ exportparts="button: replace-toggle-button, live: replace-toggle-live, spinner: replace-toggle-spinner, text: replace-toggle-text"
326
+ .expanded=${this.replacing}
327
+ label=${this.replaceToggleLabel}
328
+ @click=${() => {
329
+ this.replaceOpen = !this.replaceOpen;
330
+ }}
331
+ @helix-press=${stopPress}
332
+ >
333
+ ${this.replacing ? drawIcon(caretDown) : html `<span data-mirror>${drawIcon(caretRight)}</span>`}
334
+ </${button}>`;
335
+ }
336
+ renderOptionButtons() {
337
+ const button = this.tag('icon-button');
338
+ return html `${this.offers('match-case')
339
+ ? html `<${button}
340
+ part="match-case${this.matchCase ? ' match-case-pressed' : ''}"
341
+ exportparts="button: match-case-button, live: match-case-live, spinner: match-case-spinner, text: match-case-text"
342
+ aria-pressed=${this.matchCase ? 'true' : 'false'}
343
+ label=${this.matchCaseLabel}
344
+ @click=${() => this.toggleOption('matchCase')}
345
+ @helix-press=${stopPress}
346
+ >
347
+ <slot name="match-case-icon">${drawIcon(textAa)}</slot>
348
+ </${button}>`
349
+ : nothing}${this.offers('whole-word')
350
+ ? html `<${button}
351
+ part="whole-word${this.wholeWord ? ' whole-word-pressed' : ''}"
352
+ exportparts="button: whole-word-button, live: whole-word-live, spinner: whole-word-spinner, text: whole-word-text"
353
+ aria-pressed=${this.wholeWord ? 'true' : 'false'}
354
+ label=${this.wholeWordLabel}
355
+ @click=${() => this.toggleOption('wholeWord')}
356
+ @helix-press=${stopPress}
357
+ >
358
+ <slot name="whole-word-icon">${drawIcon(textAUnderline)}</slot>
359
+ </${button}>`
360
+ : nothing}${this.offers('regex')
361
+ ? html `<${button}
362
+ part="regex${this.regex ? ' regex-pressed' : ''}"
363
+ exportparts="button: regex-button, live: regex-live, spinner: regex-spinner, text: regex-text"
364
+ aria-pressed=${this.regex ? 'true' : 'false'}
365
+ label=${this.regexLabel}
366
+ @click=${() => this.toggleOption('regex')}
367
+ @helix-press=${stopPress}
368
+ >
369
+ <slot name="regex-icon">${drawIcon(asterisk)}</slot>
370
+ </${button}>`
371
+ : nothing}`;
372
+ }
373
+ renderControls() {
374
+ const toolbar = this.tag('toolbar');
375
+ const button = this.tag('icon-button');
376
+ const searchable = this.readable && (this.result?.count ?? 0) > 0;
377
+ return html `<${toolbar} part="controls" exportparts="toolbar: controls-toolbar" label=${this.controlsLabel}>
378
+ ${this.renderOptionButtons()}
379
+ <slot name="actions" part="actions"></slot>
380
+ <${button}
381
+ part="previous"
382
+ exportparts="button: previous-button, live: previous-live, spinner: previous-spinner, text: previous-text"
383
+ ?disabled=${!searchable}
384
+ label=${this.previousLabel}
385
+ @click=${() => this.search('previous')}
386
+ @helix-press=${stopPress}
387
+ >
388
+ <slot name="previous-icon">${drawIcon(caretUp)}</slot>
389
+ </${button}>
390
+ <${button}
391
+ part="next"
392
+ exportparts="button: next-button, live: next-live, spinner: next-spinner, text: next-text"
393
+ ?disabled=${!searchable}
394
+ label=${this.nextLabel}
395
+ @click=${() => this.search('next')}
396
+ @helix-press=${stopPress}
397
+ >
398
+ <slot name="next-icon">${drawIcon(caretDown)}</slot>
399
+ </${button}>
400
+ <${button}
401
+ part="close"
402
+ exportparts="button: close-button, live: close-live, spinner: close-spinner, text: close-text"
403
+ label=${this.closeLabel}
404
+ @click=${() => this.hide()}
405
+ @helix-press=${stopPress}
406
+ >
407
+ <slot name="close-icon">${drawIcon(x)}</slot>
408
+ </${button}>
409
+ </${toolbar}>`;
410
+ }
411
+ renderReplace() {
412
+ if (!this.replacing) {
413
+ return nothing;
414
+ }
415
+ const button = this.tag('button');
416
+ const searchable = this.readable && (this.result?.count ?? 0) > 0;
417
+ return html `<input
418
+ part="replace-field"
419
+ aria-label=${this.replaceFieldLabel}
420
+ autocomplete="off"
421
+ placeholder=${this.replaceFieldLabel}
422
+ spellcheck="false"
423
+ type="text"
424
+ .value=${live(this.replacement)}
425
+ @input=${this.handleReplaceInput}
426
+ />
427
+ <${button}
428
+ part="replace"
429
+ exportparts="button: replace-button, live: replace-live, spinner: replace-spinner, text: replace-text"
430
+ ?disabled=${!searchable}
431
+ @click=${() => this.replace(false)}
432
+ @helix-press=${stopPress}
433
+ >
434
+ ${this.replaceLabel}
435
+ </${button}>
436
+ <${button}
437
+ part="replace-all"
438
+ exportparts="button: replace-all-button, live: replace-all-live, spinner: replace-all-spinner, text: replace-all-text"
439
+ ?disabled=${!searchable}
440
+ @click=${() => this.replace(true)}
441
+ @helix-press=${stopPress}
442
+ >
443
+ ${this.replaceAllLabel}
444
+ </${button}>`;
445
+ }
446
+ render() {
447
+ return html `<div
448
+ part="bar"
449
+ role="search"
450
+ aria-label=${this.label}
451
+ ?hidden=${!this.open}
452
+ @keydown=${this.handleKeys}
453
+ >
454
+ ${this.renderReplaceToggle()}
455
+ <input
456
+ part="field"
457
+ aria-invalid=${this.readable ? nothing : 'true'}
458
+ aria-label=${this.label}
459
+ autocomplete="off"
460
+ placeholder=${this.label}
461
+ spellcheck="false"
462
+ type="search"
463
+ .value=${live(this.query)}
464
+ @input=${this.handleInput}
465
+ />
466
+ <span part="count" aria-hidden="true">${this.countText || nothing}</span>
467
+ ${this.renderControls()}
468
+ ${this.renderReplace()}
469
+ </div>
470
+ <span part="live" role="status">${keyed(this.said, this.announcement)}</span>`;
471
+ }
472
+ };
473
+ __decorate([
474
+ words,
475
+ property({ attribute: 'close-label' })
476
+ ], HelixHeadlessFind.prototype, "closeLabel", void 0);
477
+ __decorate([
478
+ words,
479
+ property({ attribute: 'controls-label' })
480
+ ], HelixHeadlessFind.prototype, "controlsLabel", void 0);
481
+ __decorate([
482
+ property()
483
+ ], HelixHeadlessFind.prototype, "for", void 0);
484
+ __decorate([
485
+ words,
486
+ property({ attribute: 'invalid-label' })
487
+ ], HelixHeadlessFind.prototype, "invalidLabel", void 0);
488
+ __decorate([
489
+ words,
490
+ property()
491
+ ], HelixHeadlessFind.prototype, "label", void 0);
492
+ __decorate([
493
+ property({ attribute: 'match-case', type: Boolean })
494
+ ], HelixHeadlessFind.prototype, "matchCase", void 0);
495
+ __decorate([
496
+ words,
497
+ property({ attribute: 'match-case-label' })
498
+ ], HelixHeadlessFind.prototype, "matchCaseLabel", void 0);
499
+ __decorate([
500
+ words,
501
+ property({ attribute: 'matches-label' })
502
+ ], HelixHeadlessFind.prototype, "matchesLabel", void 0);
503
+ __decorate([
504
+ words,
505
+ property({ attribute: 'next-label' })
506
+ ], HelixHeadlessFind.prototype, "nextLabel", void 0);
507
+ __decorate([
508
+ property()
509
+ ], HelixHeadlessFind.prototype, "options", void 0);
510
+ __decorate([
511
+ words,
512
+ property({ attribute: 'previous-label' })
513
+ ], HelixHeadlessFind.prototype, "previousLabel", void 0);
514
+ __decorate([
515
+ property()
516
+ ], HelixHeadlessFind.prototype, "query", void 0);
517
+ __decorate([
518
+ property({ attribute: 'readonly', type: Boolean })
519
+ ], HelixHeadlessFind.prototype, "readOnly", void 0);
520
+ __decorate([
521
+ property({ type: Boolean })
522
+ ], HelixHeadlessFind.prototype, "regex", void 0);
523
+ __decorate([
524
+ words,
525
+ property({ attribute: 'regex-label' })
526
+ ], HelixHeadlessFind.prototype, "regexLabel", void 0);
527
+ __decorate([
528
+ words,
529
+ property({ attribute: 'replace-all-label' })
530
+ ], HelixHeadlessFind.prototype, "replaceAllLabel", void 0);
531
+ __decorate([
532
+ words,
533
+ property({ attribute: 'replace-field-label' })
534
+ ], HelixHeadlessFind.prototype, "replaceFieldLabel", void 0);
535
+ __decorate([
536
+ words,
537
+ property({ attribute: 'replace-label' })
538
+ ], HelixHeadlessFind.prototype, "replaceLabel", void 0);
539
+ __decorate([
540
+ property()
541
+ ], HelixHeadlessFind.prototype, "replacement", void 0);
542
+ __decorate([
543
+ words,
544
+ property({ attribute: 'replace-toggle-label' })
545
+ ], HelixHeadlessFind.prototype, "replaceToggleLabel", void 0);
546
+ __decorate([
547
+ property()
548
+ ], HelixHeadlessFind.prototype, "shortcut", void 0);
549
+ __decorate([
550
+ property()
551
+ ], HelixHeadlessFind.prototype, "skip", void 0);
552
+ __decorate([
553
+ property({ attribute: 'whole-word', type: Boolean })
554
+ ], HelixHeadlessFind.prototype, "wholeWord", void 0);
555
+ __decorate([
556
+ words,
557
+ property({ attribute: 'whole-word-label' })
558
+ ], HelixHeadlessFind.prototype, "wholeWordLabel", void 0);
559
+ __decorate([
560
+ state()
561
+ ], HelixHeadlessFind.prototype, "result", void 0);
562
+ __decorate([
563
+ state()
564
+ ], HelixHeadlessFind.prototype, "replaceOpen", void 0);
565
+ __decorate([
566
+ state()
567
+ ], HelixHeadlessFind.prototype, "attached", void 0);
568
+ __decorate([
569
+ state()
570
+ ], HelixHeadlessFind.prototype, "announcement", void 0);
571
+ __decorate([
572
+ state()
573
+ ], HelixHeadlessFind.prototype, "said", void 0);
574
+ HelixHeadlessFind = __decorate([
575
+ customElement('helix-headless-find')
576
+ ], HelixHeadlessFind);
577
+ export { HelixHeadlessFind };
@@ -2,6 +2,7 @@ import { type GraphSignalDetail, HelixElement, ToolbarController, type ViewportP
2
2
  import { nothing, type PropertyValues, type TemplateResult } from 'lit';
3
3
  import { type StaticValue } from 'lit/static-html.js';
4
4
  import '../../icon-button/index.js';
5
+ import '../../tooltip/index.js';
5
6
  import { type GraphLink, type GraphNode } from './graph-model.js';
6
7
  declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.dev/helix-core").ViewportElement) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerActiveInterface) & typeof HelixElement;
7
8
  /**
@@ -149,6 +150,16 @@ declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.
149
150
  * @csspart settling - What is said while a layout runs unseen, where the reader asked for less motion or the page paused its motion, over the hidden drawing.
150
151
  * @csspart stage - The drawing and its controls.
151
152
  * @csspart stop-layout - The button that stops a layout that has run past five seconds, where the notes stand.
153
+ * @csspart tooltip-arrow - The arrow of the tooltip that names each button, forwarded from `Tooltip`.
154
+ * @csspart tooltip-arrow-bottom - The arrow while the bubble is below its button, on the bubble's top edge. Set together with `tooltip-arrow`.
155
+ * @csspart tooltip-arrow-left - The arrow while the bubble is left of its button, on the bubble's right edge. Set together with `tooltip-arrow`.
156
+ * @csspart tooltip-arrow-right - The arrow while the bubble is right of its button, on the bubble's left edge. Set together with `tooltip-arrow`.
157
+ * @csspart tooltip-arrow-top - The arrow while the bubble is above its button, on the bubble's bottom edge. Set together with `tooltip-arrow`.
158
+ * @csspart tooltip-surface - The bubble of the tooltip that names each button, forwarded from `Tooltip`.
159
+ * @csspart tooltip-surface-bottom - The bubble while it is below its button. Set together with `tooltip-surface`.
160
+ * @csspart tooltip-surface-left - The bubble while it is left of its button. Set together with `tooltip-surface`.
161
+ * @csspart tooltip-surface-right - The bubble while it is right of its button. Set together with `tooltip-surface`.
162
+ * @csspart tooltip-surface-top - The bubble while it is above its button. Set together with `tooltip-surface`.
152
163
  * @csspart viewport - The box the renderer draws in.
153
164
  * @csspart zoom-in - The zoom in button.
154
165
  * @csspart zoom-in-button - `zoom-in`'s inner button.
@@ -5,6 +5,7 @@ import { html, nothing } from 'lit';
5
5
  import { property, state } from 'lit/decorators.js';
6
6
  import { html as staticHtml } from 'lit/static-html.js';
7
7
  import '../../icon-button/index.js';
8
+ import '../../tooltip/index.js';
8
9
  import { repeat } from 'lit/directives/repeat.js';
9
10
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
10
11
  import { adjacencyOf, cursorAfter, entriesOf, groupsOf, nameOf, sortedOf, within, withoutGroups, } from './graph-model.js';
@@ -559,9 +560,11 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
559
560
  return nothing;
560
561
  }
561
562
  const button = this.controlTag;
563
+ const tip = this.tag('tooltip');
562
564
  const { material, raised } = this.controlAxes;
563
565
  return staticHtml `<${button}
564
566
  part="notes-toggle"
567
+ id="notes-toggle"
565
568
  exportparts="button: notes-toggle-button, live: notes-toggle-live, spinner: notes-toggle-spinner, text: notes-toggle-text"
566
569
  aria-controls="panel"
567
570
  .expanded=${this.panelOpen}
@@ -574,7 +577,7 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
574
577
  <svg aria-hidden="true" fill="currentColor" viewBox=${list.viewBox}>
575
578
  ${unsafeSVG(list.content)}
576
579
  </svg>
577
- </${button}>`;
580
+ </${button}><${tip} for="notes-toggle" content=${this.notesLabel} exportparts="arrow: tooltip-arrow, arrow-bottom: tooltip-arrow-bottom, arrow-left: tooltip-arrow-left, arrow-right: tooltip-arrow-right, arrow-top: tooltip-arrow-top, surface: tooltip-surface, surface-bottom: tooltip-surface-bottom, surface-left: tooltip-surface-left, surface-right: tooltip-surface-right, surface-top: tooltip-surface-top"></${tip}>`;
578
581
  }
579
582
  renderFilterIcon() {
580
583
  return html `<slot name="filter-icon">
package/dist/index.d.ts CHANGED
@@ -50,6 +50,7 @@ export * from './empty/index.js';
50
50
  export * from './file-input/index.js';
51
51
  export * from './filter-input/index.js';
52
52
  export * from './filter-input/menu/index.js';
53
+ export * from './find/index.js';
53
54
  export * from './format-date/index.js';
54
55
  export * from './graph/index.js';
55
56
  export * from './heatmap/index.js';
package/dist/index.js CHANGED
@@ -41,6 +41,7 @@ export * from './empty/index.js';
41
41
  export * from './file-input/index.js';
42
42
  export * from './filter-input/index.js';
43
43
  export * from './filter-input/menu/index.js';
44
+ export * from './find/index.js';
44
45
  export * from './format-date/index.js';
45
46
  export * from './graph/index.js';
46
47
  export * from './heatmap/index.js';
@@ -99,6 +99,12 @@ export declare class HelixHeadlessInput extends HelixHeadlessInput_base {
99
99
  * a token like `email` or `bday` to ask for autofill, or to `off` to refuse.
100
100
  */
101
101
  autocomplete: string;
102
+ /**
103
+ * Whether the browser corrects words as the reader types, as the platform's
104
+ * `autocorrect`. Turn it off, with `autocorrect="off"`, for text that is not
105
+ * prose, such as an address or a code, which corrections would change.
106
+ */
107
+ autocorrect: boolean;
102
108
  /**
103
109
  * Whether the field shows a button that empties it.
104
110
  *
@@ -13,6 +13,7 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinVoice(MixinContro
13
13
  this.announcesInput = true;
14
14
  this.autocapitalize = '';
15
15
  this.autocomplete = '';
16
+ this.autocorrect = true;
16
17
  this.clearable = false;
17
18
  this.clearLabel = 'Clear';
18
19
  this.enterKeyHint = '';
@@ -198,6 +199,7 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinVoice(MixinContro
198
199
  inputmode=${this.inputMode || nothing}
199
200
  enterkeyhint=${this.enterKeyHint || nothing}
200
201
  autocapitalize=${this.autocapitalize || nothing}
202
+ autocorrect=${this.autocorrect ? nothing : 'off'}
201
203
  aria-describedby=${this.describedBy ?? nothing}
202
204
  aria-invalid=${this.invalidity ?? nothing}
203
205
  ?disabled=${this.isDisabled}
@@ -243,6 +245,11 @@ __decorate([
243
245
  __decorate([
244
246
  property()
245
247
  ], HelixHeadlessInput.prototype, "autocomplete", void 0);
248
+ __decorate([
249
+ property({
250
+ converter: { fromAttribute: (value) => value?.toLowerCase() !== 'off' },
251
+ })
252
+ ], HelixHeadlessInput.prototype, "autocorrect", void 0);
246
253
  __decorate([
247
254
  property({ type: Boolean })
248
255
  ], HelixHeadlessInput.prototype, "clearable", void 0);