@esfaenza/core 20.3.80 → 20.3.82

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.
@@ -14,7 +14,7 @@ import { PreferencesService, CacheService } from '@esfaenza/preferences';
14
14
  import * as i5 from '@esfaenza/localizations';
15
15
  import { LocalizationService } from '@esfaenza/localizations';
16
16
  import { JaceIdentity, ApplicationJob, ApplicationMenu, SearchResult, SearchResultContainer, ActiveModuleView, EntityFeedsWidgetConfiguration, Feed, CreateUpdateFeedDto, UserAccount, UpdatePasswordDto } from '@esfaenza/core/domain';
17
- import { Subscription, ReplaySubject, Subject } from 'rxjs';
17
+ import { Subscription, ReplaySubject, Subject, Observable } from 'rxjs';
18
18
  import * as i3 from '@angular/forms';
19
19
  import { NgForm, NgModel } from '@angular/forms';
20
20
  import * as i4 from '@esfaenza/core/directives';
@@ -473,9 +473,77 @@ declare class EntityFeedsWidgetComponent {
473
473
  static ɵcmp: i0.ɵɵComponentDeclaration<EntityFeedsWidgetComponent, "entity-feeds-widget", never, { "EntityType": { "alias": "EntityType"; "required": false; }; "EntityId": { "alias": "EntityId"; "required": false; }; "RefreshSubject": { "alias": "RefreshSubject"; "required": false; }; "GetFeedsAPI": { "alias": "GetFeedsAPI"; "required": false; }; "CreateFeedAPI": { "alias": "CreateFeedAPI"; "required": false; }; "UpdateFeedAPI": { "alias": "UpdateFeedAPI"; "required": false; }; "DeleteFeedAPI": { "alias": "DeleteFeedAPI"; "required": false; }; "ReactToFeedAPI": { "alias": "ReactToFeedAPI"; "required": false; }; "GetUserTagsAPI": { "alias": "GetUserTagsAPI"; "required": false; }; "GetFeedAttachmentAPI": { "alias": "GetFeedAttachmentAPI"; "required": false; }; "WidgetTitle": { "alias": "WidgetTitle"; "required": false; }; "MaxHeight": { "alias": "MaxHeight"; "required": false; }; "Readonly": { "alias": "Readonly"; "required": false; }; "AllowUserTags": { "alias": "AllowUserTags"; "required": false; }; "AllowReactions": { "alias": "AllowReactions"; "required": false; }; "AllowAttachments": { "alias": "AllowAttachments"; "required": false; }; "AllowComments": { "alias": "AllowComments"; "required": false; }; "AllowReplies": { "alias": "AllowReplies"; "required": false; }; "DebugMode": { "alias": "DebugMode"; "required": false; }; "ModuleConfig": { "alias": "ModuleConfig"; "required": false; }; }, {}, never, never, true, never>;
474
474
  }
475
475
 
476
+ /** Risposta a un comando: testo prodotto, eventuale errore e il prompt da mostrare da lì in avanti */
477
+ interface EsTerminalResult {
478
+ Output?: string;
479
+ Error?: string;
480
+ Prompt?: string;
481
+ }
482
+ /** Esegue un comando: la riga digitata arriva così com'è, anche vuota (serve agli interpreti con prompt di continuazione) */
483
+ type EsTerminalExecutor = (command: string) => Observable<EsTerminalResult> | Promise<EsTerminalResult> | EsTerminalResult;
484
+ type EsTerminalLineKind = "greeting" | "command" | "output" | "error" | "info";
485
+ interface EsTerminalLine {
486
+ Kind: EsTerminalLineKind;
487
+ Text: string;
488
+ Prompt?: string;
489
+ }
490
+ /**
491
+ * Terminale testuale senza dipendenze: storico delle righe, prompt, cronologia dei comandi (frecce su/giù),
492
+ * incolla di più righe eseguite in sequenza. Ogni comando passa all'Executor; finché non risponde l'input è sospeso.
493
+ *
494
+ * Tasti: Invio esegue, ↑/↓ cronologia, Tab inserisce 4 spazi, Ctrl+C (senza testo selezionato) annulla la riga, Ctrl+L pulisce.
495
+ * Colori e font si cambiano con le variabili CSS --es-terminal-* sull'elemento.
496
+ */
497
+ declare class EsTerminalComponent {
498
+ /** Testo mostrato all'apertura */
499
+ Greetings: string;
500
+ /** Prompt iniziale; l'Executor può cambiarlo con ogni risposta */
501
+ set Prompt(value: string);
502
+ Executor: EsTerminalExecutor;
503
+ /** Chiave in localStorage per conservare la cronologia dei comandi fra una sessione e l'altra; senza chiave resta in memoria */
504
+ HistoryKey: string;
505
+ MaxHistory: number;
506
+ /** Prende il focus all'apertura */
507
+ AutoFocus: boolean;
508
+ private screen;
509
+ private input;
510
+ Lines: i0.WritableSignal<EsTerminalLine[]>;
511
+ CurrentPrompt: i0.WritableSignal<string>;
512
+ Busy: i0.WritableSignal<boolean>;
513
+ Command: string;
514
+ private history;
515
+ private historyIndex;
516
+ private draft;
517
+ private queue;
518
+ ngOnInit(): void;
519
+ ngAfterViewInit(): void;
520
+ /** Aggiunge del testo allo schermo */
521
+ echo(text: string, kind?: EsTerminalLineKind): void;
522
+ error(text: string): void;
523
+ clear(): void;
524
+ setPrompt(prompt: string): void;
525
+ focus(): void;
526
+ /** Esegue un comando come se fosse stato digitato */
527
+ exec(command: string): void;
528
+ onKeyDown(e: KeyboardEvent): void;
529
+ onPaste(e: ClipboardEvent): void;
530
+ onScreenClick(): void;
531
+ private runQueue;
532
+ private run;
533
+ private addToHistory;
534
+ private moveInHistory;
535
+ private loadHistory;
536
+ private saveHistory;
537
+ private insertAtCursor;
538
+ private hasSelection;
539
+ private scrollToBottom;
540
+ static ɵfac: i0.ɵɵFactoryDeclaration<EsTerminalComponent, never>;
541
+ static ɵcmp: i0.ɵɵComponentDeclaration<EsTerminalComponent, "es-terminal", never, { "Greetings": { "alias": "Greetings"; "required": false; }; "Prompt": { "alias": "Prompt"; "required": false; }; "Executor": { "alias": "Executor"; "required": false; }; "HistoryKey": { "alias": "HistoryKey"; "required": false; }; "MaxHistory": { "alias": "MaxHistory"; "required": false; }; "AutoFocus": { "alias": "AutoFocus"; "required": false; }; }, {}, never, never, true, never>;
542
+ }
543
+
476
544
  declare class ComponentsModule {
477
545
  static ɵfac: i0.ɵɵFactoryDeclaration<ComponentsModule, never>;
478
- static ɵmod: i0.ɵɵNgModuleDeclaration<ComponentsModule, never, [typeof i1.CommonModule, typeof i2.RouterModule, typeof i3.FormsModule, typeof i4.DirectivesModule, typeof i5.LocalizationModule, typeof i6.ProgressbarModule, typeof i7.BsDropdownModule, typeof i8.ModalModule, typeof i9.EsTableModule, typeof BackTop, typeof Breadcrumb, typeof ErrorPageComponent, typeof PagesComponent, typeof ExternalPagesComponent, typeof JaceLoginComponent, typeof Navbar, typeof RedirecterComponent, typeof Sidebar, typeof JaceResourceComponent, typeof EsModalComponent, typeof EsModalHeadComponent, typeof LabeledSpanComponent, typeof EsImageCropperComponent, typeof FormSelectorComponent, typeof FormSelectorDialogComponent, typeof EntityFeedsWidgetComponent], [typeof BackTop, typeof Breadcrumb, typeof ErrorPageComponent, typeof PagesComponent, typeof ExternalPagesComponent, typeof JaceLoginComponent, typeof Navbar, typeof RedirecterComponent, typeof Sidebar, typeof JaceResourceComponent, typeof EsModalComponent, typeof EsModalHeadComponent, typeof LabeledSpanComponent, typeof EsImageCropperComponent, typeof FormSelectorComponent, typeof FormSelectorDialogComponent, typeof EntityFeedsWidgetComponent]>;
546
+ static ɵmod: i0.ɵɵNgModuleDeclaration<ComponentsModule, never, [typeof i1.CommonModule, typeof i2.RouterModule, typeof i3.FormsModule, typeof i4.DirectivesModule, typeof i5.LocalizationModule, typeof i6.ProgressbarModule, typeof i7.BsDropdownModule, typeof i8.ModalModule, typeof i9.EsTableModule, typeof BackTop, typeof Breadcrumb, typeof ErrorPageComponent, typeof PagesComponent, typeof ExternalPagesComponent, typeof JaceLoginComponent, typeof Navbar, typeof RedirecterComponent, typeof Sidebar, typeof JaceResourceComponent, typeof EsModalComponent, typeof EsModalHeadComponent, typeof LabeledSpanComponent, typeof EsImageCropperComponent, typeof FormSelectorComponent, typeof FormSelectorDialogComponent, typeof EntityFeedsWidgetComponent, typeof EsTerminalComponent], [typeof BackTop, typeof Breadcrumb, typeof ErrorPageComponent, typeof PagesComponent, typeof ExternalPagesComponent, typeof JaceLoginComponent, typeof Navbar, typeof RedirecterComponent, typeof Sidebar, typeof JaceResourceComponent, typeof EsModalComponent, typeof EsModalHeadComponent, typeof LabeledSpanComponent, typeof EsImageCropperComponent, typeof FormSelectorComponent, typeof FormSelectorDialogComponent, typeof EntityFeedsWidgetComponent, typeof EsTerminalComponent]>;
479
547
  static ɵinj: i0.ɵɵInjectorDeclaration<ComponentsModule>;
480
548
  }
481
549
 
@@ -695,4 +763,5 @@ declare abstract class BaseSearchComponent<TSearch extends AppSearch<TItem>, TIt
695
763
  static ɵcmp: i0.ɵɵComponentDeclaration<BaseSearchComponent<any, any>, "ng-component", never, {}, {}, never, never, true, never>;
696
764
  }
697
765
 
698
- export { BackTop, BaseComponent, BaseSearchComponent, BaseSelectorComponent, BaseSelectorInitialization, Breadcrumb, BreadcrumbItem, ComponentsModule, EmbeddingComponent, EntityFeedsWidgetComponent, ErrorPageComponent, EsImageCropperComponent, EsModalComponent, EsModalHeadComponent, ExternalPagesComponent, FormSelectorComponent, FormSelectorDialogComponent, JaceLoginComponent, JaceResourceComponent, LabeledSpanComponent, Navbar, PagesComponent, ReactiveComponent, RedirecterComponent, Sidebar, UserInfosComponent };
766
+ export { BackTop, BaseComponent, BaseSearchComponent, BaseSelectorComponent, BaseSelectorInitialization, Breadcrumb, BreadcrumbItem, ComponentsModule, EmbeddingComponent, EntityFeedsWidgetComponent, ErrorPageComponent, EsImageCropperComponent, EsModalComponent, EsModalHeadComponent, EsTerminalComponent, ExternalPagesComponent, FormSelectorComponent, FormSelectorDialogComponent, JaceLoginComponent, JaceResourceComponent, LabeledSpanComponent, Navbar, PagesComponent, ReactiveComponent, RedirecterComponent, Sidebar, UserInfosComponent };
767
+ export type { EsTerminalExecutor, EsTerminalLine, EsTerminalLineKind, EsTerminalResult };
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { HostListener, ViewChild, Input, ViewEncapsulation, Component, EventEmitter, Output, Inject, Injectable, Optional, ChangeDetectionStrategy, input, model, NgModule, viewChild, contentChild } from '@angular/core';
2
+ import { HostListener, ViewChild, Input, ViewEncapsulation, Component, EventEmitter, Output, Inject, Injectable, Optional, ChangeDetectionStrategy, input, model, signal, NgModule, viewChild, contentChild } from '@angular/core';
3
3
  import * as i2 from '@angular/router';
4
4
  import { NavigationEnd, RouterLink, RouterLinkActive, RouterOutlet, ActivatedRoute, Router, RouterModule } from '@angular/router';
5
5
  import * as i4 from '@angular/common';
6
6
  import { NgIf, NgFor, NgTemplateOutlet, NgClass, CommonModule, AsyncPipe, Location } from '@angular/common';
7
7
  import { filter, map, mergeMap, takeUntil } from 'rxjs/operators';
8
- import { Subject, combineLatest, of, firstValueFrom, ReplaySubject, interval, startWith, takeUntil as takeUntil$1, takeWhile, take, map as map$1 } from 'rxjs';
8
+ import { Subject, combineLatest, of, firstValueFrom, ReplaySubject, interval, startWith, takeUntil as takeUntil$1, takeWhile, isObservable, take, map as map$1 } from 'rxjs';
9
9
  import * as i1 from '@esfaenza/core/services';
10
10
  import { AppState } from '@esfaenza/core/services';
11
11
  import * as i3 from '@angular/platform-browser';
@@ -1616,6 +1616,262 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImpo
1616
1616
  args: ["dlgFeedContent"]
1617
1617
  }] } });
1618
1618
 
1619
+ // Angular
1620
+ /**
1621
+ * Terminale testuale senza dipendenze: storico delle righe, prompt, cronologia dei comandi (frecce su/giù),
1622
+ * incolla di più righe eseguite in sequenza. Ogni comando passa all'Executor; finché non risponde l'input è sospeso.
1623
+ *
1624
+ * Tasti: Invio esegue, ↑/↓ cronologia, Tab inserisce 4 spazi, Ctrl+C (senza testo selezionato) annulla la riga, Ctrl+L pulisce.
1625
+ * Colori e font si cambiano con le variabili CSS --es-terminal-* sull'elemento.
1626
+ */
1627
+ class EsTerminalComponent {
1628
+ constructor() {
1629
+ /** Testo mostrato all'apertura */
1630
+ this.Greetings = "";
1631
+ this.MaxHistory = 200;
1632
+ /** Prende il focus all'apertura */
1633
+ this.AutoFocus = true;
1634
+ this.Lines = signal([], ...(ngDevMode ? [{ debugName: "Lines" }] : []));
1635
+ this.CurrentPrompt = signal(">", ...(ngDevMode ? [{ debugName: "CurrentPrompt" }] : []));
1636
+ this.Busy = signal(false, ...(ngDevMode ? [{ debugName: "Busy" }] : []));
1637
+ this.Command = "";
1638
+ this.history = [];
1639
+ //Posizione nella cronologia mentre si scorre con le frecce: history.length vuol dire "riga nuova", con la bozza salvata a parte
1640
+ this.historyIndex = 0;
1641
+ this.draft = "";
1642
+ //Righe incollate in attesa di essere eseguite, una alla volta
1643
+ this.queue = [];
1644
+ }
1645
+ /** Prompt iniziale; l'Executor può cambiarlo con ogni risposta */
1646
+ set Prompt(value) { this.CurrentPrompt.set(value ?? ""); }
1647
+ ngOnInit() {
1648
+ this.history = this.loadHistory();
1649
+ this.historyIndex = this.history.length;
1650
+ if (this.Greetings)
1651
+ this.Lines.set([{ Kind: "greeting", Text: this.Greetings }]);
1652
+ }
1653
+ ngAfterViewInit() {
1654
+ if (this.AutoFocus)
1655
+ setTimeout(() => this.focus());
1656
+ }
1657
+ //******************************************************************* API pubblica
1658
+ /** Aggiunge del testo allo schermo */
1659
+ echo(text, kind = "output") {
1660
+ if (text === null || text === undefined)
1661
+ return;
1662
+ //Gli a capo finali (spesso \r\n) lascerebbero una riga vuota sotto ogni risposta
1663
+ text = text.replace(/\r\n?/g, "\n").replace(/\n+$/, "");
1664
+ this.Lines.update(l => [...l, { Kind: kind, Text: text }]);
1665
+ this.scrollToBottom();
1666
+ }
1667
+ error(text) {
1668
+ this.echo(text, "error");
1669
+ }
1670
+ clear() {
1671
+ this.Lines.set([]);
1672
+ }
1673
+ setPrompt(prompt) {
1674
+ this.CurrentPrompt.set(prompt ?? "");
1675
+ }
1676
+ focus() {
1677
+ this.input?.nativeElement.focus({ preventScroll: true });
1678
+ }
1679
+ /** Esegue un comando come se fosse stato digitato */
1680
+ exec(command) {
1681
+ this.queue.push(command);
1682
+ if (!this.Busy())
1683
+ this.runQueue();
1684
+ }
1685
+ //******************************************************************* Input
1686
+ onKeyDown(e) {
1687
+ if (this.Busy())
1688
+ return;
1689
+ switch (e.key) {
1690
+ case "Enter":
1691
+ e.preventDefault();
1692
+ let command = this.Command;
1693
+ this.Command = "";
1694
+ this.exec(command);
1695
+ return;
1696
+ case "ArrowUp":
1697
+ e.preventDefault();
1698
+ this.moveInHistory(-1);
1699
+ return;
1700
+ case "ArrowDown":
1701
+ e.preventDefault();
1702
+ this.moveInHistory(1);
1703
+ return;
1704
+ case "Tab":
1705
+ e.preventDefault();
1706
+ this.insertAtCursor(" ");
1707
+ return;
1708
+ }
1709
+ if (e.ctrlKey && !e.altKey && !e.metaKey) {
1710
+ let key = e.key.toLowerCase();
1711
+ //Ctrl+C copia se c'è testo selezionato, altrimenti annulla la riga come in una shell
1712
+ if (key == "c" && !this.hasSelection()) {
1713
+ e.preventDefault();
1714
+ this.Lines.update(l => [...l, { Kind: "command", Prompt: this.CurrentPrompt(), Text: this.Command + "^C" }]);
1715
+ this.Command = "";
1716
+ this.historyIndex = this.history.length;
1717
+ this.scrollToBottom();
1718
+ }
1719
+ else if (key == "l") {
1720
+ e.preventDefault();
1721
+ this.clear();
1722
+ }
1723
+ }
1724
+ }
1725
+ onPaste(e) {
1726
+ let text = e.clipboardData?.getData("text") ?? "";
1727
+ if (!/[\r\n]/.test(text))
1728
+ return;
1729
+ //Più righe: la prima completa quella in corso, le altre vengono eseguite in fila; l'ultima, se non chiusa da un a capo, resta da completare
1730
+ e.preventDefault();
1731
+ let lines = text.replace(/\r\n?/g, "\n").split("\n");
1732
+ let last = lines.pop();
1733
+ lines[0] = this.Command + lines[0];
1734
+ this.Command = last;
1735
+ lines.forEach(l => this.queue.push(l));
1736
+ if (!this.Busy())
1737
+ this.runQueue();
1738
+ }
1739
+ //Un clic sullo schermo porta il focus sull'input, a meno che non si stia selezionando del testo da copiare
1740
+ onScreenClick() {
1741
+ if (!this.hasSelection())
1742
+ this.focus();
1743
+ }
1744
+ //******************************************************************* Esecuzione
1745
+ async runQueue() {
1746
+ while (this.queue.length > 0) {
1747
+ let command = this.queue.shift();
1748
+ await this.run(command);
1749
+ }
1750
+ setTimeout(() => this.focus());
1751
+ }
1752
+ async run(command) {
1753
+ this.Lines.update(l => [...l, { Kind: "command", Prompt: this.CurrentPrompt(), Text: command }]);
1754
+ this.addToHistory(command);
1755
+ this.scrollToBottom();
1756
+ if (!this.Executor)
1757
+ return;
1758
+ this.Busy.set(true);
1759
+ try {
1760
+ let ret = this.Executor(command);
1761
+ let res = isObservable(ret) ? await firstValueFrom(ret, { defaultValue: null }) : await ret;
1762
+ if (res?.Output)
1763
+ this.echo(res.Output, "output");
1764
+ if (res?.Error)
1765
+ this.echo(res.Error, "error");
1766
+ if (res?.Prompt !== undefined && res?.Prompt !== null)
1767
+ this.CurrentPrompt.set(res.Prompt);
1768
+ }
1769
+ catch (ex) {
1770
+ //Un errore della chiamata non deve bloccare il terminale: lo mostro e si continua
1771
+ this.echo(ex?.message ?? ex?.toString() ?? "Errore", "error");
1772
+ }
1773
+ finally {
1774
+ this.Busy.set(false);
1775
+ this.scrollToBottom();
1776
+ }
1777
+ }
1778
+ //******************************************************************* Cronologia
1779
+ addToHistory(command) {
1780
+ if (command.trim() && this.history[this.history.length - 1] !== command) {
1781
+ this.history.push(command);
1782
+ if (this.history.length > this.MaxHistory)
1783
+ this.history.splice(0, this.history.length - this.MaxHistory);
1784
+ this.saveHistory();
1785
+ }
1786
+ this.historyIndex = this.history.length;
1787
+ this.draft = "";
1788
+ }
1789
+ moveInHistory(step) {
1790
+ let next = this.historyIndex + step;
1791
+ if (next < 0 || next > this.history.length)
1792
+ return;
1793
+ //Uscendo dalla riga nuova ne tengo la bozza, per ritrovarla scendendo
1794
+ if (this.historyIndex == this.history.length)
1795
+ this.draft = this.Command;
1796
+ this.historyIndex = next;
1797
+ this.Command = next == this.history.length ? this.draft : this.history[next];
1798
+ //Cursore in fondo, come nelle shell
1799
+ setTimeout(() => {
1800
+ let el = this.input?.nativeElement;
1801
+ if (el)
1802
+ el.setSelectionRange(el.value.length, el.value.length);
1803
+ });
1804
+ }
1805
+ loadHistory() {
1806
+ if (!this.HistoryKey)
1807
+ return [];
1808
+ try {
1809
+ let saved = JSON.parse(localStorage.getItem(this.HistoryKey) ?? "[]");
1810
+ return Array.isArray(saved) ? saved.filter(t => typeof t === "string") : [];
1811
+ }
1812
+ catch {
1813
+ return [];
1814
+ }
1815
+ }
1816
+ saveHistory() {
1817
+ if (!this.HistoryKey)
1818
+ return;
1819
+ try {
1820
+ localStorage.setItem(this.HistoryKey, JSON.stringify(this.history));
1821
+ }
1822
+ catch { }
1823
+ }
1824
+ //******************************************************************* Utilità
1825
+ insertAtCursor(text) {
1826
+ let el = this.input?.nativeElement;
1827
+ if (!el)
1828
+ return;
1829
+ let start = el.selectionStart ?? this.Command.length;
1830
+ let end = el.selectionEnd ?? start;
1831
+ this.Command = this.Command.substring(0, start) + text + this.Command.substring(end);
1832
+ setTimeout(() => el.setSelectionRange(start + text.length, start + text.length));
1833
+ }
1834
+ //Testo selezionato sullo schermo o dentro l'input (la selezione di un input non compare in window.getSelection)
1835
+ hasSelection() {
1836
+ let el = this.input?.nativeElement;
1837
+ if (el && document.activeElement === el && el.selectionStart !== el.selectionEnd)
1838
+ return true;
1839
+ let sel = window.getSelection();
1840
+ return !!sel && !sel.isCollapsed && sel.toString().length > 0;
1841
+ }
1842
+ scrollToBottom() {
1843
+ setTimeout(() => {
1844
+ let el = this.screen?.nativeElement;
1845
+ if (el)
1846
+ el.scrollTop = el.scrollHeight;
1847
+ });
1848
+ }
1849
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: EsTerminalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1850
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.34", type: EsTerminalComponent, isStandalone: true, selector: "es-terminal", inputs: { Greetings: "Greetings", Prompt: "Prompt", Executor: "Executor", HistoryKey: "HistoryKey", MaxHistory: "MaxHistory", AutoFocus: "AutoFocus" }, viewQueries: [{ propertyName: "screen", first: true, predicate: ["screen"], descendants: true, static: true }, { propertyName: "input", first: true, predicate: ["input"], descendants: true }], ngImport: i0, template: "<div class=\"es-terminal\" #screen (click)=\"onScreenClick()\">\n @for (line of Lines(); track $index) {\n @if (line.Kind == 'command') {\n <div class=\"es-terminal-line es-terminal-command\"><span class=\"es-terminal-prompt\">{{line.Prompt}}</span>{{line.Text}}</div>\n } @else {\n <div class=\"es-terminal-line\" [class]=\"'es-terminal-' + line.Kind\">{{line.Text}}</div>\n }\n }\n\n <div class=\"es-terminal-line es-terminal-input-line\" [class.es-terminal-busy]=\"Busy()\">\n @if (Busy()) {\n <span class=\"es-terminal-spinner\"></span>\n } @else {\n <span class=\"es-terminal-prompt\">{{CurrentPrompt()}}</span>\n }\n <input #input class=\"es-terminal-input\" type=\"text\" autocomplete=\"off\" autocapitalize=\"off\" spellcheck=\"false\"\n aria-label=\"Comando\" [readonly]=\"Busy()\" [(ngModel)]=\"Command\" (keydown)=\"onKeyDown($event)\" (paste)=\"onPaste($event)\" />\n </div>\n</div>\n", styles: ["es-terminal{--es-terminal-background: #1e1e1e;--es-terminal-color: #d4d4d4;--es-terminal-command-color: #ffffff;--es-terminal-prompt-color: #4ec9b0;--es-terminal-greeting-color: #569cd6;--es-terminal-info-color: #9a9a9a;--es-terminal-error-color: #f48771;--es-terminal-selection: rgba(255, 255, 255, .25);--es-terminal-font: Consolas, \"Cascadia Mono\", \"DejaVu Sans Mono\", \"Courier New\", monospace;--es-terminal-font-size: 13px;--es-terminal-line-height: 1.45;display:block;height:100%;min-height:0}.es-terminal{height:100%;overflow-y:auto;overflow-x:hidden;padding:10px 12px;box-sizing:border-box;background:var(--es-terminal-background);color:var(--es-terminal-color);font-family:var(--es-terminal-font);font-size:var(--es-terminal-font-size);line-height:var(--es-terminal-line-height);cursor:text}.es-terminal ::selection{background:var(--es-terminal-selection)}.es-terminal-line{white-space:pre-wrap;overflow-wrap:anywhere;min-height:calc(var(--es-terminal-font-size) * var(--es-terminal-line-height))}.es-terminal-command{color:var(--es-terminal-command-color)}.es-terminal-greeting{color:var(--es-terminal-greeting-color);margin-bottom:4px}.es-terminal-info{color:var(--es-terminal-info-color)}.es-terminal-error{color:var(--es-terminal-error-color)}.es-terminal-prompt{color:var(--es-terminal-prompt-color);white-space:pre;margin-right:.5ch;-webkit-user-select:none;user-select:none}.es-terminal-input-line{display:flex;align-items:baseline}.es-terminal-input{flex:1 1 auto;min-width:0;padding:0;margin:0;border:none;outline:none;background:transparent;color:var(--es-terminal-command-color);caret-color:var(--es-terminal-command-color);font:inherit;line-height:inherit}.es-terminal-busy .es-terminal-input{color:transparent;caret-color:transparent}.es-terminal-spinner{display:inline-block;width:1ch;margin-right:.5ch;color:var(--es-terminal-prompt-color)}.es-terminal-spinner:after{content:\"|\";animation:es-terminal-spin .6s steps(4) infinite}@keyframes es-terminal-spin{0%{content:\"|\"}25%{content:\"/\"}50%{content:\"-\"}75%{content:\"\\\\\"}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], encapsulation: i0.ViewEncapsulation.None }); }
1851
+ }
1852
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: EsTerminalComponent, decorators: [{
1853
+ type: Component,
1854
+ args: [{ selector: "es-terminal", encapsulation: ViewEncapsulation.None, imports: [FormsModule], template: "<div class=\"es-terminal\" #screen (click)=\"onScreenClick()\">\n @for (line of Lines(); track $index) {\n @if (line.Kind == 'command') {\n <div class=\"es-terminal-line es-terminal-command\"><span class=\"es-terminal-prompt\">{{line.Prompt}}</span>{{line.Text}}</div>\n } @else {\n <div class=\"es-terminal-line\" [class]=\"'es-terminal-' + line.Kind\">{{line.Text}}</div>\n }\n }\n\n <div class=\"es-terminal-line es-terminal-input-line\" [class.es-terminal-busy]=\"Busy()\">\n @if (Busy()) {\n <span class=\"es-terminal-spinner\"></span>\n } @else {\n <span class=\"es-terminal-prompt\">{{CurrentPrompt()}}</span>\n }\n <input #input class=\"es-terminal-input\" type=\"text\" autocomplete=\"off\" autocapitalize=\"off\" spellcheck=\"false\"\n aria-label=\"Comando\" [readonly]=\"Busy()\" [(ngModel)]=\"Command\" (keydown)=\"onKeyDown($event)\" (paste)=\"onPaste($event)\" />\n </div>\n</div>\n", styles: ["es-terminal{--es-terminal-background: #1e1e1e;--es-terminal-color: #d4d4d4;--es-terminal-command-color: #ffffff;--es-terminal-prompt-color: #4ec9b0;--es-terminal-greeting-color: #569cd6;--es-terminal-info-color: #9a9a9a;--es-terminal-error-color: #f48771;--es-terminal-selection: rgba(255, 255, 255, .25);--es-terminal-font: Consolas, \"Cascadia Mono\", \"DejaVu Sans Mono\", \"Courier New\", monospace;--es-terminal-font-size: 13px;--es-terminal-line-height: 1.45;display:block;height:100%;min-height:0}.es-terminal{height:100%;overflow-y:auto;overflow-x:hidden;padding:10px 12px;box-sizing:border-box;background:var(--es-terminal-background);color:var(--es-terminal-color);font-family:var(--es-terminal-font);font-size:var(--es-terminal-font-size);line-height:var(--es-terminal-line-height);cursor:text}.es-terminal ::selection{background:var(--es-terminal-selection)}.es-terminal-line{white-space:pre-wrap;overflow-wrap:anywhere;min-height:calc(var(--es-terminal-font-size) * var(--es-terminal-line-height))}.es-terminal-command{color:var(--es-terminal-command-color)}.es-terminal-greeting{color:var(--es-terminal-greeting-color);margin-bottom:4px}.es-terminal-info{color:var(--es-terminal-info-color)}.es-terminal-error{color:var(--es-terminal-error-color)}.es-terminal-prompt{color:var(--es-terminal-prompt-color);white-space:pre;margin-right:.5ch;-webkit-user-select:none;user-select:none}.es-terminal-input-line{display:flex;align-items:baseline}.es-terminal-input{flex:1 1 auto;min-width:0;padding:0;margin:0;border:none;outline:none;background:transparent;color:var(--es-terminal-command-color);caret-color:var(--es-terminal-command-color);font:inherit;line-height:inherit}.es-terminal-busy .es-terminal-input{color:transparent;caret-color:transparent}.es-terminal-spinner{display:inline-block;width:1ch;margin-right:.5ch;color:var(--es-terminal-prompt-color)}.es-terminal-spinner:after{content:\"|\";animation:es-terminal-spin .6s steps(4) infinite}@keyframes es-terminal-spin{0%{content:\"|\"}25%{content:\"/\"}50%{content:\"-\"}75%{content:\"\\\\\"}}\n"] }]
1855
+ }], propDecorators: { Greetings: [{
1856
+ type: Input
1857
+ }], Prompt: [{
1858
+ type: Input
1859
+ }], Executor: [{
1860
+ type: Input
1861
+ }], HistoryKey: [{
1862
+ type: Input
1863
+ }], MaxHistory: [{
1864
+ type: Input
1865
+ }], AutoFocus: [{
1866
+ type: Input
1867
+ }], screen: [{
1868
+ type: ViewChild,
1869
+ args: ["screen", { static: true }]
1870
+ }], input: [{
1871
+ type: ViewChild,
1872
+ args: ["input", { static: false }]
1873
+ }] } });
1874
+
1619
1875
  // Angular
1620
1876
  const COMPONENTS = [
1621
1877
  BackTop,
@@ -1634,7 +1890,8 @@ const COMPONENTS = [
1634
1890
  EsImageCropperComponent,
1635
1891
  FormSelectorComponent,
1636
1892
  FormSelectorDialogComponent,
1637
- EntityFeedsWidgetComponent
1893
+ EntityFeedsWidgetComponent,
1894
+ EsTerminalComponent
1638
1895
  ];
1639
1896
  class ComponentsModule {
1640
1897
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: ComponentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
@@ -1654,7 +1911,8 @@ class ComponentsModule {
1654
1911
  EsImageCropperComponent,
1655
1912
  FormSelectorComponent,
1656
1913
  FormSelectorDialogComponent,
1657
- EntityFeedsWidgetComponent], exports: [BackTop,
1914
+ EntityFeedsWidgetComponent,
1915
+ EsTerminalComponent], exports: [BackTop,
1658
1916
  Breadcrumb,
1659
1917
  ErrorPageComponent,
1660
1918
  PagesComponent,
@@ -1670,7 +1928,8 @@ class ComponentsModule {
1670
1928
  EsImageCropperComponent,
1671
1929
  FormSelectorComponent,
1672
1930
  FormSelectorDialogComponent,
1673
- EntityFeedsWidgetComponent] }); }
1931
+ EntityFeedsWidgetComponent,
1932
+ EsTerminalComponent] }); }
1674
1933
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: ComponentsModule, imports: [CommonModule, RouterModule, FormsModule, DirectivesModule, LocalizationModule, ProgressbarModule, BsDropdownModule, ModalModule, EsTableModule, ErrorPageComponent,
1675
1934
  PagesComponent,
1676
1935
  Navbar,
@@ -1678,7 +1937,8 @@ class ComponentsModule {
1678
1937
  EsImageCropperComponent,
1679
1938
  FormSelectorComponent,
1680
1939
  FormSelectorDialogComponent,
1681
- EntityFeedsWidgetComponent] }); }
1940
+ EntityFeedsWidgetComponent,
1941
+ EsTerminalComponent] }); }
1682
1942
  }
1683
1943
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: ComponentsModule, decorators: [{
1684
1944
  type: NgModule,
@@ -2460,5 +2720,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImpo
2460
2720
  * Generated bundle index. Do not edit.
2461
2721
  */
2462
2722
 
2463
- export { BackTop, BaseComponent, BaseSearchComponent, BaseSelectorComponent, BaseSelectorInitialization, Breadcrumb, BreadcrumbItem, ComponentsModule, EmbeddingComponent, EntityFeedsWidgetComponent, ErrorPageComponent, EsImageCropperComponent, EsModalComponent, EsModalHeadComponent, ExternalPagesComponent, FormSelectorComponent, FormSelectorDialogComponent, JaceLoginComponent, JaceResourceComponent, LabeledSpanComponent, Navbar, PagesComponent, ReactiveComponent, RedirecterComponent, Sidebar, UserInfosComponent };
2723
+ export { BackTop, BaseComponent, BaseSearchComponent, BaseSelectorComponent, BaseSelectorInitialization, Breadcrumb, BreadcrumbItem, ComponentsModule, EmbeddingComponent, EntityFeedsWidgetComponent, ErrorPageComponent, EsImageCropperComponent, EsModalComponent, EsModalHeadComponent, EsTerminalComponent, ExternalPagesComponent, FormSelectorComponent, FormSelectorDialogComponent, JaceLoginComponent, JaceResourceComponent, LabeledSpanComponent, Navbar, PagesComponent, ReactiveComponent, RedirecterComponent, Sidebar, UserInfosComponent };
2464
2724
  //# sourceMappingURL=esfaenza-core-components.mjs.map