@fusion.dev/helix-headless 0.208.1 → 0.209.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.
@@ -0,0 +1,710 @@
1
+ import { __decorate } from "tslib";
2
+ import { CopyController, customElement, drawIcon, FullscreenController, formatWords, HelixElement, HelixTerminalBellEvent, HelixTerminalInputEvent, HelixTerminalLinkEvent, HelixTerminalResizeEvent, HelixTerminalRestartEvent, HelixTerminalTitleEvent, numberConverter, onApple, words, } from '@fusion.dev/helix-core';
3
+ import { arrowClockwise, broom, caretDown, caretUp, copy, cornersOut, magnifyingGlass, 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
+ import { isTab, shortcutOf, spokenChord } from '../keys.js';
13
+ const ANSI = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'];
14
+ const camel = (name) => name.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
15
+ const unset = (color) => color === '' || color === 'transparent' || /^rgba\(\s*0,\s*0,\s*0,\s*0\s*\)$/.test(color);
16
+ const stopPress = (event) => event.stopPropagation();
17
+ const BELL = 200;
18
+ const RESTING_CONTROLS = 'find clear';
19
+ const opens = (href) => /^https?:\/\//i.test(href);
20
+ let HelixHeadlessTerminal = class HelixHeadlessTerminal extends HelixElement {
21
+ constructor() {
22
+ super(...arguments);
23
+ this.clearLabel = 'Clear';
24
+ this.controlsLabel = 'Terminal controls';
25
+ this.copiedLabel = 'Copied';
26
+ this.copyLabel = 'Copy';
27
+ this.exitedLabel = '{code, select, 0 {The process exited.} other {The process exited with code {code}.}}';
28
+ this.fallbackLabel = 'Terminal';
29
+ this.findCloseLabel = 'Close find';
30
+ this.findControlsLabel = 'Find controls';
31
+ this.findLabel = 'Find';
32
+ this.findNextLabel = 'Next match';
33
+ this.findPreviousLabel = 'Previous match';
34
+ this.fullscreenLabel = 'Fill the screen';
35
+ this.inputLabel = 'Terminal input';
36
+ this.label = '';
37
+ this.matchesLabel = '{count, plural, =0 {No matches} one {{index} of # match} other {{index} of # matches}}';
38
+ this.readOnly = false;
39
+ this.restartLabel = 'Restart';
40
+ this.screenReaderMode = false;
41
+ this.tabHintLabel = 'Press {key} to move focus with Tab.';
42
+ this.tabMovesFocusLabel = 'Tab moves focus. Press {key} to type Tab in the terminal.';
43
+ this.tabTypesLabel = 'Tab types in the terminal.';
44
+ this.findOpen = false;
45
+ this.query = '';
46
+ this.matchIndex = -1;
47
+ this.matchCount = undefined;
48
+ this.tabMovesFocus = false;
49
+ this.anySelected = false;
50
+ this.hasActions = false;
51
+ this.hasLabel = false;
52
+ this.announcement = '';
53
+ this.said = 0;
54
+ this.renderer = undefined;
55
+ this.pending = [];
56
+ this.inputWas = undefined;
57
+ this.ringing = undefined;
58
+ this.copier = new CopyController(this);
59
+ this.filled = false;
60
+ this.fullscreen = new FullscreenController(this, (full) => {
61
+ this.filled = full;
62
+ this.toggleState('fullscreen', full);
63
+ });
64
+ this.handleKeys = (event) => {
65
+ if (event.defaultPrevented || event.isComposing) {
66
+ return;
67
+ }
68
+ const origin = event.composedPath()[0];
69
+ const inGrid = origin instanceof Node &&
70
+ [...this.children].some((child) => !child.slot && child.contains(origin));
71
+ const shortcut = shortcutOf(event, onApple());
72
+ if (shortcut === 'find' && this.takes('find')) {
73
+ event.preventDefault();
74
+ event.stopPropagation();
75
+ void this.openFind();
76
+ return;
77
+ }
78
+ if (!inGrid || !this.renderer) {
79
+ return;
80
+ }
81
+ if (shortcut === 'copy' && this.takes('copy')) {
82
+ event.preventDefault();
83
+ event.stopPropagation();
84
+ void this.copySelection();
85
+ return;
86
+ }
87
+ if (shortcut === 'tab-focus') {
88
+ event.preventDefault();
89
+ event.stopPropagation();
90
+ this.tabMovesFocus = !this.tabMovesFocus;
91
+ this.say(this.tabMovesFocus
92
+ ? formatWords(this, 'tabMovesFocusLabel', { key: this.tabKey })
93
+ : this.tabTypesLabel);
94
+ return;
95
+ }
96
+ if (this.tabMovesFocus && isTab(event)) {
97
+ event.stopPropagation();
98
+ }
99
+ };
100
+ this.handleFindInput = (event) => {
101
+ this.query = event.target.value;
102
+ this.search(false, true);
103
+ };
104
+ this.handleFindKeys = (event) => {
105
+ if (event.key === 'Escape') {
106
+ event.preventDefault();
107
+ this.closeFind();
108
+ }
109
+ else if (event.key === 'Enter') {
110
+ event.preventDefault();
111
+ this.search(event.shiftKey);
112
+ }
113
+ };
114
+ this.handleActions = (event) => {
115
+ this.hasActions = event.target.assignedNodes().length > 0;
116
+ };
117
+ this.handleLabel = (event) => {
118
+ this.hasLabel = event.target.assignedNodes().length > 0;
119
+ };
120
+ this.handleRestart = () => {
121
+ this.dispatchEvent(new HelixTerminalRestartEvent());
122
+ };
123
+ }
124
+ static { this.words = 'helix-terminal'; }
125
+ write(data) {
126
+ return new Promise((resolve) => {
127
+ if (this.renderer) {
128
+ this.renderer.write(data, resolve);
129
+ }
130
+ else {
131
+ this.pending.push({ data, done: resolve });
132
+ }
133
+ });
134
+ }
135
+ paste(text) {
136
+ if (this.renderer?.paste) {
137
+ this.renderer.paste(text);
138
+ }
139
+ else {
140
+ this.send(text, false);
141
+ }
142
+ }
143
+ clear() {
144
+ this.renderer?.clear?.();
145
+ }
146
+ reset() {
147
+ this.renderer?.reset?.();
148
+ }
149
+ text(scope = 'screen') {
150
+ return this.renderer?.text?.(scope) ?? '';
151
+ }
152
+ look() {
153
+ const colors = {};
154
+ for (const probe of this.renderRoot.querySelectorAll('[data-look] > [data-color]')) {
155
+ const color = getComputedStyle(probe).color;
156
+ if (!unset(color)) {
157
+ colors[camel(probe.dataset.color ?? '')] = color;
158
+ }
159
+ }
160
+ const viewport = this.partNamed('viewport');
161
+ const face = viewport ? getComputedStyle(viewport) : undefined;
162
+ const size = face ? Number.parseFloat(face.fontSize) : Number.NaN;
163
+ return {
164
+ colors,
165
+ font: face && Number.isFinite(size) ? { family: face.fontFamily, size } : undefined,
166
+ };
167
+ }
168
+ focus(options) {
169
+ if (this.renderer?.focus) {
170
+ this.renderer.focus();
171
+ return;
172
+ }
173
+ const input = this.renderer?.input?.();
174
+ if (input) {
175
+ input.focus(options);
176
+ return;
177
+ }
178
+ super.focus(options);
179
+ }
180
+ attach(renderer) {
181
+ this.release();
182
+ this.renderer = renderer;
183
+ for (const { data, done } of this.pending.splice(0)) {
184
+ renderer.write(data, done);
185
+ }
186
+ renderer.settings?.(this.settings);
187
+ this.nameInput();
188
+ const current = () => this.renderer === renderer;
189
+ return {
190
+ bell: () => {
191
+ if (current()) {
192
+ this.ring();
193
+ }
194
+ },
195
+ detach: () => {
196
+ if (current()) {
197
+ this.release();
198
+ this.renderer = undefined;
199
+ }
200
+ },
201
+ found: (index, count) => {
202
+ if (current()) {
203
+ this.matchIndex = index;
204
+ this.matchCount = count;
205
+ this.say(this.countText);
206
+ }
207
+ },
208
+ input: (data, binary = false) => {
209
+ if (current()) {
210
+ this.send(data, binary);
211
+ }
212
+ },
213
+ link: (href) => {
214
+ if (current()) {
215
+ this.follow(href);
216
+ }
217
+ },
218
+ resized: (size) => {
219
+ if (current()) {
220
+ this.dispatchEvent(new HelixTerminalResizeEvent(size));
221
+ }
222
+ },
223
+ selected: (any) => {
224
+ if (current()) {
225
+ this.anySelected = any;
226
+ }
227
+ },
228
+ title: (title) => {
229
+ if (current()) {
230
+ this.dispatchEvent(new HelixTerminalTitleEvent({ title }));
231
+ }
232
+ },
233
+ };
234
+ }
235
+ get settings() {
236
+ const fixed = this.columns !== undefined && this.rows !== undefined;
237
+ return {
238
+ columns: fixed ? this.columns : undefined,
239
+ cursor: !this.readOnly,
240
+ input: !this.readOnly && this.exitCode === undefined,
241
+ rows: fixed ? this.rows : undefined,
242
+ screenReader: this.screenReaderMode,
243
+ };
244
+ }
245
+ send(data, binary) {
246
+ if (this.readOnly || this.exitCode !== undefined || data === '') {
247
+ return;
248
+ }
249
+ this.dispatchEvent(new HelixTerminalInputEvent({ binary, data }));
250
+ }
251
+ follow(href) {
252
+ const event = new HelixTerminalLinkEvent({ href });
253
+ this.dispatchEvent(event);
254
+ if (!event.defaultPrevented && opens(href)) {
255
+ window.open(href, '_blank', 'noopener,noreferrer');
256
+ }
257
+ }
258
+ ring() {
259
+ clearTimeout(this.ringing);
260
+ this.toggleState('bell', true);
261
+ this.ringing = setTimeout(() => this.toggleState('bell', false), BELL);
262
+ this.dispatchEvent(new HelixTerminalBellEvent());
263
+ }
264
+ say(text) {
265
+ this.announcement = text;
266
+ this.said += 1;
267
+ }
268
+ draws(control) {
269
+ if (!(this.controls ?? RESTING_CONTROLS).split(/\s+/).includes(control)) {
270
+ return false;
271
+ }
272
+ const renderer = this.renderer;
273
+ if (!renderer || control === 'fullscreen') {
274
+ return true;
275
+ }
276
+ return control === 'clear'
277
+ ? renderer.clear !== undefined
278
+ : control === 'copy'
279
+ ? renderer.selection !== undefined
280
+ : renderer.find !== undefined;
281
+ }
282
+ get countText() {
283
+ return this.matchCount === undefined
284
+ ? ''
285
+ : formatWords(this, 'matchesLabel', {
286
+ count: this.matchCount,
287
+ index: Math.max(this.matchIndex, 0) + 1,
288
+ });
289
+ }
290
+ get tabKey() {
291
+ return spokenChord('tab-focus', onApple());
292
+ }
293
+ nameInput() {
294
+ const element = this.renderer?.input?.();
295
+ if (!element) {
296
+ return;
297
+ }
298
+ if (this.inputWas?.element !== element) {
299
+ this.restoreInput();
300
+ this.inputWas = {
301
+ element,
302
+ values: Object.fromEntries(['aria-description', 'aria-keyshortcuts', 'aria-label'].map((name) => [
303
+ name,
304
+ element.getAttribute(name),
305
+ ])),
306
+ };
307
+ }
308
+ const apple = onApple();
309
+ const keys = ['find', 'copy', 'tab-focus']
310
+ .filter((shortcut) => this.takes(shortcut))
311
+ .map((shortcut) => spokenChord(shortcut, apple))
312
+ .filter((chord) => chord !== '');
313
+ element.setAttribute('aria-label', this.inputLabel);
314
+ element.setAttribute('aria-description', formatWords(this, 'tabHintLabel', { key: this.tabKey }));
315
+ element.setAttribute('aria-keyshortcuts', keys.join(' '));
316
+ }
317
+ restoreInput() {
318
+ const was = this.inputWas;
319
+ if (!was) {
320
+ return;
321
+ }
322
+ for (const [name, value] of Object.entries(was.values)) {
323
+ if (value === null) {
324
+ was.element.removeAttribute(name);
325
+ }
326
+ else {
327
+ was.element.setAttribute(name, value);
328
+ }
329
+ }
330
+ this.inputWas = undefined;
331
+ }
332
+ release() {
333
+ this.restoreInput();
334
+ this.findOpen = false;
335
+ this.matchCount = undefined;
336
+ this.anySelected = false;
337
+ }
338
+ takes(shortcut) {
339
+ const renderer = this.renderer;
340
+ if (!renderer) {
341
+ return false;
342
+ }
343
+ if (shortcut === 'find') {
344
+ return renderer.find !== undefined;
345
+ }
346
+ if (shortcut === 'copy') {
347
+ return renderer.selection !== undefined;
348
+ }
349
+ return true;
350
+ }
351
+ async openFind() {
352
+ this.findOpen = true;
353
+ await this.updateComplete;
354
+ const field = this.partNamed('find-field');
355
+ field?.focus();
356
+ field?.select();
357
+ if (this.query !== '') {
358
+ this.search(false, true);
359
+ }
360
+ }
361
+ closeFind() {
362
+ this.findOpen = false;
363
+ this.matchCount = undefined;
364
+ this.matchIndex = -1;
365
+ this.renderer?.findEnd?.();
366
+ this.focus();
367
+ }
368
+ search(backward, incremental = false) {
369
+ if (this.query === '') {
370
+ this.matchCount = undefined;
371
+ this.renderer?.findEnd?.();
372
+ return;
373
+ }
374
+ this.renderer?.find?.(this.query, { backward, incremental });
375
+ }
376
+ async copySelection() {
377
+ const text = this.renderer?.selection?.() ?? '';
378
+ if (text !== '' && (await this.copier.copy(text))) {
379
+ this.say(this.copiedLabel);
380
+ }
381
+ }
382
+ willUpdate(changed) {
383
+ super.willUpdate(changed);
384
+ if (this.hasUpdated && changed.has('exitCode') && this.exitCode !== undefined) {
385
+ this.say(formatWords(this, 'exitedLabel', { code: String(this.exitCode) }));
386
+ }
387
+ }
388
+ updated(changed) {
389
+ super.updated(changed);
390
+ const exited = this.exitCode !== undefined;
391
+ this.toggleState('exited', exited);
392
+ this.toggleState('find-open', this.findOpen);
393
+ this.toggleState('tab-moves-focus', this.tabMovesFocus);
394
+ if (this.renderer &&
395
+ (changed.has('columns') ||
396
+ changed.has('rows') ||
397
+ changed.has('readOnly') ||
398
+ changed.has('exitCode') ||
399
+ changed.has('screenReaderMode'))) {
400
+ this.renderer.settings?.(this.settings);
401
+ }
402
+ if (this.renderer && (changed.has('inputLabel') || changed.has('tabHintLabel'))) {
403
+ this.nameInput();
404
+ }
405
+ }
406
+ connectedCallback() {
407
+ super.connectedCallback();
408
+ this.addEventListener('keydown', this.handleKeys, { capture: true });
409
+ }
410
+ disconnectedCallback() {
411
+ super.disconnectedCallback();
412
+ this.removeEventListener('keydown', this.handleKeys, { capture: true });
413
+ clearTimeout(this.ringing);
414
+ }
415
+ get drawsAny() {
416
+ return ['find', 'copy', 'clear', 'fullscreen'].some((control) => this.draws(control));
417
+ }
418
+ renderControls() {
419
+ const toolbar = this.tag('toolbar');
420
+ const button = this.tag('icon-button');
421
+ return html `<${toolbar} part="controls" exportparts="toolbar: controls-toolbar" label=${this.controlsLabel}>
422
+ <slot name="actions" part="actions" @slotchange=${this.handleActions}></slot>
423
+ ${this.draws('find')
424
+ ? html `<${button}
425
+ part="find"
426
+ exportparts="button: find-button, live: find-live, spinner: find-spinner, text: find-text"
427
+ .expanded=${this.findOpen}
428
+ label=${this.findLabel}
429
+ @click=${() => (this.findOpen ? this.closeFind() : void this.openFind())}
430
+ @helix-press=${stopPress}
431
+ >
432
+ <slot name="find-icon">${drawIcon(magnifyingGlass)}</slot>
433
+ </${button}>`
434
+ : nothing}
435
+ ${this.draws('copy')
436
+ ? html `<${button}
437
+ part="copy"
438
+ exportparts="button: copy-button, live: copy-live, spinner: copy-spinner, text: copy-text"
439
+ ?disabled=${!this.anySelected}
440
+ label=${this.copyLabel}
441
+ @click=${() => void this.copySelection()}
442
+ @helix-press=${stopPress}
443
+ >
444
+ <slot name="copy-icon">${drawIcon(copy)}</slot>
445
+ </${button}>`
446
+ : nothing}
447
+ ${this.draws('clear')
448
+ ? html `<${button}
449
+ part="clear"
450
+ exportparts="button: clear-button, live: clear-live, spinner: clear-spinner, text: clear-text"
451
+ label=${this.clearLabel}
452
+ @click=${() => this.clear()}
453
+ @helix-press=${stopPress}
454
+ >
455
+ <slot name="clear-icon">${drawIcon(broom)}</slot>
456
+ </${button}>`
457
+ : nothing}
458
+ ${this.draws('fullscreen')
459
+ ? html `<${button}
460
+ part="fullscreen"
461
+ exportparts="button: fullscreen-button, live: fullscreen-live, spinner: fullscreen-spinner, text: fullscreen-text"
462
+ aria-pressed=${this.filled ? 'true' : 'false'}
463
+ label=${this.fullscreenLabel}
464
+ @click=${() => void this.fullscreen.toggle()}
465
+ @helix-press=${stopPress}
466
+ >
467
+ <slot name="fullscreen-icon">${drawIcon(cornersOut)}</slot>
468
+ </${button}>`
469
+ : nothing}
470
+ </${toolbar}>`;
471
+ }
472
+ renderFind() {
473
+ if (!this.draws('find')) {
474
+ return nothing;
475
+ }
476
+ const toolbar = this.tag('toolbar');
477
+ const button = this.tag('icon-button');
478
+ return html `<div part="find-bar" role="search" aria-label=${this.findLabel} ?hidden=${!this.findOpen}>
479
+ <input
480
+ part="find-field"
481
+ aria-label=${this.findLabel}
482
+ autocomplete="off"
483
+ placeholder=${this.findLabel}
484
+ spellcheck="false"
485
+ type="search"
486
+ .value=${live(this.query)}
487
+ @input=${this.handleFindInput}
488
+ @keydown=${this.handleFindKeys}
489
+ />
490
+ <span part="find-count" aria-hidden="true">${this.countText}</span>
491
+ <${toolbar} part="find-controls" exportparts="toolbar: find-controls-toolbar" label=${this.findControlsLabel}>
492
+ <slot name="find-actions" part="find-actions"></slot>
493
+ <${button}
494
+ part="find-previous"
495
+ exportparts="button: find-previous-button, live: find-previous-live, spinner: find-previous-spinner, text: find-previous-text"
496
+ ?disabled=${!this.matchCount}
497
+ label=${this.findPreviousLabel}
498
+ @click=${() => this.search(true)}
499
+ @helix-press=${stopPress}
500
+ >
501
+ <slot name="find-previous-icon">${drawIcon(caretUp)}</slot>
502
+ </${button}>
503
+ <${button}
504
+ part="find-next"
505
+ exportparts="button: find-next-button, live: find-next-live, spinner: find-next-spinner, text: find-next-text"
506
+ ?disabled=${!this.matchCount}
507
+ label=${this.findNextLabel}
508
+ @click=${() => this.search(false)}
509
+ @helix-press=${stopPress}
510
+ >
511
+ <slot name="find-next-icon">${drawIcon(caretDown)}</slot>
512
+ </${button}>
513
+ <${button}
514
+ part="find-close"
515
+ exportparts="button: find-close-button, live: find-close-live, spinner: find-close-spinner, text: find-close-text"
516
+ label=${this.findCloseLabel}
517
+ @click=${() => this.closeFind()}
518
+ @helix-press=${stopPress}
519
+ >
520
+ <slot name="find-close-icon">${drawIcon(x)}</slot>
521
+ </${button}>
522
+ </${toolbar}>
523
+ </div>`;
524
+ }
525
+ renderLook() {
526
+ return html `<span data-look hidden aria-hidden="true" style="color: transparent">
527
+ <span data-color="active-match" style="color: var(--terminal-active-match-background-color)"></span>
528
+ <span data-color="active-match-border" style="color: var(--terminal-active-match-border-color)"></span>
529
+ <span data-color="background" style="color: var(--terminal-background-color)"></span>
530
+ <span data-color="cursor" style="color: var(--terminal-cursor-color)"></span>
531
+ <span data-color="foreground" style="color: var(--terminal-color)"></span>
532
+ <span data-color="match" style="color: var(--terminal-match-background-color)"></span>
533
+ <span data-color="scrollbar" style="color: var(--terminal-scrollbar-thumb-color)"></span>
534
+ <span data-color="selection" style="color: var(--terminal-selection-background-color)"></span>
535
+ ${ANSI.map((name) => html `<span data-color=${name} style="color: var(--terminal-ansi-${name})"></span>`)}
536
+ ${ANSI.map((name) => html `<span data-color=${`bright-${name}`} style="color: var(--terminal-ansi-bright-${name})"></span>`)}
537
+ </span>`;
538
+ }
539
+ renderStatus() {
540
+ const exited = this.exitCode !== undefined;
541
+ const button = this.tag('button');
542
+ return html `<div part="status" ?hidden=${!exited && !this.tabMovesFocus}>
543
+ ${exited
544
+ ? html `<span>${formatWords(this, 'exitedLabel', { code: String(this.exitCode ?? 0) })}</span>
545
+ <${button}
546
+ part="restart"
547
+ exportparts="button: restart-button, live: restart-live, spinner: restart-spinner, text: restart-text"
548
+ @click=${this.handleRestart}
549
+ @helix-press=${stopPress}
550
+ >
551
+ <slot name="restart-icon" slot="start">${drawIcon(arrowClockwise)}</slot>
552
+ ${this.restartLabel}
553
+ </${button}>
554
+ <slot name="exit-actions" part="exit-actions"></slot>`
555
+ : nothing}
556
+ ${this.tabMovesFocus ? html `<span>${formatWords(this, 'tabMovesFocusLabel', { key: this.tabKey })}</span>` : nothing}
557
+ </div>`;
558
+ }
559
+ render() {
560
+ const headed = this.label !== '' || this.hasLabel || this.hasActions || this.drawsAny;
561
+ return html `<div
562
+ part="region"
563
+ role="group"
564
+ aria-label=${this.label || this.getAttribute('aria-label') || this.fallbackLabel}
565
+ >
566
+ <div part="header" ?hidden=${!headed}>
567
+ <slot name="label" part="label" @slotchange=${this.handleLabel}>${this.label}</slot>
568
+ ${this.renderControls()}
569
+ </div>
570
+ ${this.renderFind()}
571
+ <div part="viewport"><slot></slot></div>
572
+ ${this.renderStatus()}
573
+ <span part="live" role="status">${keyed(this.said, this.announcement)}</span>
574
+ </div>
575
+ ${this.renderLook()}`;
576
+ }
577
+ };
578
+ __decorate([
579
+ words,
580
+ property({ attribute: 'clear-label' })
581
+ ], HelixHeadlessTerminal.prototype, "clearLabel", void 0);
582
+ __decorate([
583
+ property({ converter: numberConverter('columns', undefined) })
584
+ ], HelixHeadlessTerminal.prototype, "columns", void 0);
585
+ __decorate([
586
+ property({ reflect: true })
587
+ ], HelixHeadlessTerminal.prototype, "controls", void 0);
588
+ __decorate([
589
+ words,
590
+ property({ attribute: 'controls-label' })
591
+ ], HelixHeadlessTerminal.prototype, "controlsLabel", void 0);
592
+ __decorate([
593
+ words,
594
+ property({ attribute: 'copied-label' })
595
+ ], HelixHeadlessTerminal.prototype, "copiedLabel", void 0);
596
+ __decorate([
597
+ words,
598
+ property({ attribute: 'copy-label' })
599
+ ], HelixHeadlessTerminal.prototype, "copyLabel", void 0);
600
+ __decorate([
601
+ property({ attribute: 'exit-code', converter: numberConverter('exit-code', undefined) })
602
+ ], HelixHeadlessTerminal.prototype, "exitCode", void 0);
603
+ __decorate([
604
+ words,
605
+ property({ attribute: 'exited-label' })
606
+ ], HelixHeadlessTerminal.prototype, "exitedLabel", void 0);
607
+ __decorate([
608
+ words,
609
+ property({ attribute: 'fallback-label' })
610
+ ], HelixHeadlessTerminal.prototype, "fallbackLabel", void 0);
611
+ __decorate([
612
+ words,
613
+ property({ attribute: 'find-close-label' })
614
+ ], HelixHeadlessTerminal.prototype, "findCloseLabel", void 0);
615
+ __decorate([
616
+ words,
617
+ property({ attribute: 'find-controls-label' })
618
+ ], HelixHeadlessTerminal.prototype, "findControlsLabel", void 0);
619
+ __decorate([
620
+ words,
621
+ property({ attribute: 'find-label' })
622
+ ], HelixHeadlessTerminal.prototype, "findLabel", void 0);
623
+ __decorate([
624
+ words,
625
+ property({ attribute: 'find-next-label' })
626
+ ], HelixHeadlessTerminal.prototype, "findNextLabel", void 0);
627
+ __decorate([
628
+ words,
629
+ property({ attribute: 'find-previous-label' })
630
+ ], HelixHeadlessTerminal.prototype, "findPreviousLabel", void 0);
631
+ __decorate([
632
+ words,
633
+ property({ attribute: 'fullscreen-label' })
634
+ ], HelixHeadlessTerminal.prototype, "fullscreenLabel", void 0);
635
+ __decorate([
636
+ words,
637
+ property({ attribute: 'input-label' })
638
+ ], HelixHeadlessTerminal.prototype, "inputLabel", void 0);
639
+ __decorate([
640
+ property()
641
+ ], HelixHeadlessTerminal.prototype, "label", void 0);
642
+ __decorate([
643
+ words,
644
+ property({ attribute: 'matches-label' })
645
+ ], HelixHeadlessTerminal.prototype, "matchesLabel", void 0);
646
+ __decorate([
647
+ property({ attribute: 'readonly', type: Boolean })
648
+ ], HelixHeadlessTerminal.prototype, "readOnly", void 0);
649
+ __decorate([
650
+ words,
651
+ property({ attribute: 'restart-label' })
652
+ ], HelixHeadlessTerminal.prototype, "restartLabel", void 0);
653
+ __decorate([
654
+ property({ converter: numberConverter('rows', undefined) })
655
+ ], HelixHeadlessTerminal.prototype, "rows", void 0);
656
+ __decorate([
657
+ property({ attribute: 'screen-reader-mode', type: Boolean })
658
+ ], HelixHeadlessTerminal.prototype, "screenReaderMode", void 0);
659
+ __decorate([
660
+ words,
661
+ property({ attribute: 'tab-hint-label' })
662
+ ], HelixHeadlessTerminal.prototype, "tabHintLabel", void 0);
663
+ __decorate([
664
+ words,
665
+ property({ attribute: 'tab-moves-focus-label' })
666
+ ], HelixHeadlessTerminal.prototype, "tabMovesFocusLabel", void 0);
667
+ __decorate([
668
+ words,
669
+ property({ attribute: 'tab-types-label' })
670
+ ], HelixHeadlessTerminal.prototype, "tabTypesLabel", void 0);
671
+ __decorate([
672
+ state()
673
+ ], HelixHeadlessTerminal.prototype, "findOpen", void 0);
674
+ __decorate([
675
+ state()
676
+ ], HelixHeadlessTerminal.prototype, "query", void 0);
677
+ __decorate([
678
+ state()
679
+ ], HelixHeadlessTerminal.prototype, "matchIndex", void 0);
680
+ __decorate([
681
+ state()
682
+ ], HelixHeadlessTerminal.prototype, "matchCount", void 0);
683
+ __decorate([
684
+ state()
685
+ ], HelixHeadlessTerminal.prototype, "tabMovesFocus", void 0);
686
+ __decorate([
687
+ state()
688
+ ], HelixHeadlessTerminal.prototype, "anySelected", void 0);
689
+ __decorate([
690
+ state()
691
+ ], HelixHeadlessTerminal.prototype, "hasActions", void 0);
692
+ __decorate([
693
+ state()
694
+ ], HelixHeadlessTerminal.prototype, "hasLabel", void 0);
695
+ __decorate([
696
+ state()
697
+ ], HelixHeadlessTerminal.prototype, "announcement", void 0);
698
+ __decorate([
699
+ state()
700
+ ], HelixHeadlessTerminal.prototype, "said", void 0);
701
+ __decorate([
702
+ state()
703
+ ], HelixHeadlessTerminal.prototype, "renderer", void 0);
704
+ __decorate([
705
+ state()
706
+ ], HelixHeadlessTerminal.prototype, "filled", void 0);
707
+ HelixHeadlessTerminal = __decorate([
708
+ customElement('helix-headless-terminal')
709
+ ], HelixHeadlessTerminal);
710
+ export { HelixHeadlessTerminal };