@myrmidon/gve-core 3.0.3 → 5.0.1
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.
- package/README.md +43 -0
- package/fesm2022/myrmidon-gve-core.mjs +697 -548
- package/fesm2022/myrmidon-gve-core.mjs.map +1 -1
- package/index.d.ts +1541 -3
- package/package.json +12 -11
- package/lib/components/animation-timeline/animation-timeline.component.d.ts +0 -61
- package/lib/components/animation-timeline-set/animation-timeline-set.component.d.ts +0 -52
- package/lib/components/animation-tween/animation-tween.component.d.ts +0 -58
- package/lib/components/base-text-char/base-text-char.component.d.ts +0 -42
- package/lib/components/base-text-editor/base-text-editor.component.d.ts +0 -42
- package/lib/components/base-text-view/base-text-view.component.d.ts +0 -69
- package/lib/components/batch-operation-editor/batch-operation-editor.component.d.ts +0 -44
- package/lib/components/chain-operation-editor/chain-operation-editor.component.d.ts +0 -149
- package/lib/components/chain-result-view/chain-result-view.component.d.ts +0 -58
- package/lib/components/chain-view/chain-view.component.d.ts +0 -42
- package/lib/components/feature-editor/feature-editor.component.d.ts +0 -82
- package/lib/components/feature-set-editor/feature-set-editor.component.d.ts +0 -76
- package/lib/components/feature-set-view/feature-set-view.component.d.ts +0 -54
- package/lib/components/ln-heights-editor/ln-heights-editor.component.d.ts +0 -41
- package/lib/components/operation-source-editor/operation-source-editor.component.d.ts +0 -52
- package/lib/components/snapshot-editor/snapshot-editor.component.d.ts +0 -293
- package/lib/components/snapshot-text-editor/snapshot-text-editor.component.d.ts +0 -37
- package/lib/components/steps-map/steps-map.component.d.ts +0 -48
- package/lib/models.d.ts +0 -15
- package/lib/services/gve-api.service.d.ts +0 -148
- package/lib/services/gve-graphviz.service.d.ts +0 -20
- package/lib/services/settings.service.d.ts +0 -89
- package/lib/validators/svg-validators.d.ts +0 -10
- package/public-api.d.ts +0 -21
|
@@ -1,53 +1,53 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { model, input, output, effect, Component, ViewChild, Injectable, Optional, Inject, computed, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
2
|
+
import { model, input, output, effect, Component, signal, ViewChild, Injectable, Optional, Inject, computed, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/forms';
|
|
4
4
|
import { Validators, ReactiveFormsModule, FormControl, FormGroup, FormsModule } from '@angular/forms';
|
|
5
|
-
import * as i2 from '@angular/
|
|
6
|
-
import { CommonModule } from '@angular/common';
|
|
7
|
-
import * as i3 from '@angular/material/button';
|
|
5
|
+
import * as i2 from '@angular/material/button';
|
|
8
6
|
import { MatButtonModule } from '@angular/material/button';
|
|
9
|
-
import * as
|
|
7
|
+
import * as i3$1 from '@angular/material/checkbox';
|
|
10
8
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
11
|
-
import * as
|
|
9
|
+
import * as i3 from '@angular/material/expansion';
|
|
12
10
|
import { MatExpansionModule } from '@angular/material/expansion';
|
|
13
|
-
import * as
|
|
11
|
+
import * as i4 from '@angular/material/form-field';
|
|
14
12
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
15
|
-
import * as
|
|
13
|
+
import * as i4$1 from '@angular/material/icon';
|
|
16
14
|
import { MatIconModule } from '@angular/material/icon';
|
|
17
|
-
import * as
|
|
15
|
+
import * as i5 from '@angular/material/input';
|
|
18
16
|
import { MatInputModule } from '@angular/material/input';
|
|
19
|
-
import * as
|
|
17
|
+
import * as i6 from '@angular/material/select';
|
|
20
18
|
import { MatSelectModule } from '@angular/material/select';
|
|
21
|
-
import * as
|
|
19
|
+
import * as i15 from '@angular/material/tabs';
|
|
22
20
|
import { MatTabsModule } from '@angular/material/tabs';
|
|
23
|
-
import * as
|
|
21
|
+
import * as i7 from '@angular/material/tooltip';
|
|
24
22
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
25
|
-
import * as i2$
|
|
26
|
-
import { NgxToolsValidators, ColorToContrastPipe, FlatLookupPipe, SafeHtmlPipe
|
|
23
|
+
import * as i2$1 from '@myrmidon/ngx-tools';
|
|
24
|
+
import { NgxToolsValidators, deepCopy, ColorToContrastPipe, FlatLookupPipe, SafeHtmlPipe } from '@myrmidon/ngx-tools';
|
|
27
25
|
import { debounceTime, distinctUntilChanged, catchError, BehaviorSubject } from 'rxjs';
|
|
28
|
-
import * as
|
|
26
|
+
import * as i4$2 from '@myrmidon/ngx-mat-tools';
|
|
27
|
+
import * as i1$1 from '@angular/material/core';
|
|
29
28
|
import { MatRippleModule } from '@angular/material/core';
|
|
30
29
|
import { FeatureSetPolicy, SnapshotViewService, OperationType, DEFAULT_SVG_BASE_TEXT_OPTIONS } from '@myrmidon/gve-snapshot-view';
|
|
31
|
-
import * as
|
|
32
|
-
import * as i3$1 from '@angular/material/dialog';
|
|
30
|
+
import * as i3$2 from '@angular/material/dialog';
|
|
33
31
|
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
34
|
-
import * as i1$
|
|
32
|
+
import * as i1$2 from '@angular/common/http';
|
|
35
33
|
import { filter, debounceTime as debounceTime$1 } from 'rxjs/operators';
|
|
36
|
-
import * as i2$
|
|
34
|
+
import * as i2$2 from '@angular/cdk/clipboard';
|
|
37
35
|
import { ClipboardModule } from '@angular/cdk/clipboard';
|
|
38
|
-
import * as
|
|
36
|
+
import * as i5$1 from '@angular/material/badge';
|
|
39
37
|
import { MatBadgeModule } from '@angular/material/badge';
|
|
40
|
-
import * as
|
|
38
|
+
import * as i15$1 from '@cisstech/nge/monaco';
|
|
41
39
|
import { NgeMonacoModule } from '@cisstech/nge/monaco';
|
|
42
40
|
import { customAlphabet } from 'nanoid';
|
|
41
|
+
import * as i17 from '@angular/common';
|
|
42
|
+
import { CommonModule } from '@angular/common';
|
|
43
43
|
import { VizComponent } from '@myrmidon/ngx-viz';
|
|
44
|
-
import * as i4$
|
|
44
|
+
import * as i4$3 from '@angular/material/snack-bar';
|
|
45
45
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
46
|
-
import * as
|
|
46
|
+
import * as i7$1 from '@angular/material/button-toggle';
|
|
47
47
|
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
48
|
-
import * as
|
|
48
|
+
import * as i13 from '@angular/material/progress-bar';
|
|
49
49
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
50
|
-
import * as
|
|
50
|
+
import * as i14 from '@angular/material/slider';
|
|
51
51
|
import { MatSliderModule } from '@angular/material/slider';
|
|
52
52
|
|
|
53
53
|
/**
|
|
@@ -66,16 +66,12 @@ class AnimationTweenComponent {
|
|
|
66
66
|
/**
|
|
67
67
|
* The tween to edit.
|
|
68
68
|
*/
|
|
69
|
-
this.tween = model();
|
|
69
|
+
this.tween = model(...(ngDevMode ? [undefined, { debugName: "tween" }] : []));
|
|
70
70
|
/**
|
|
71
71
|
* The IDs of the elements that can be selected by the tween.
|
|
72
72
|
* This list is used to allow the user to select an element from a dropdown.
|
|
73
73
|
*/
|
|
74
|
-
this.elementIds = input();
|
|
75
|
-
/**
|
|
76
|
-
* Emitted when the tween is changed.
|
|
77
|
-
*/
|
|
78
|
-
this.tweenChange = output();
|
|
74
|
+
this.elementIds = input(...(ngDevMode ? [undefined, { debugName: "elementIds" }] : []));
|
|
79
75
|
/**
|
|
80
76
|
* Emitted when the user cancels the edit.
|
|
81
77
|
*/
|
|
@@ -182,15 +178,13 @@ class AnimationTweenComponent {
|
|
|
182
178
|
return;
|
|
183
179
|
}
|
|
184
180
|
this.tween.set(this.getTween());
|
|
185
|
-
this.tweenChange.emit(this.tween());
|
|
186
181
|
}
|
|
187
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
188
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
182
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AnimationTweenComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
183
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: AnimationTweenComponent, isStandalone: true, selector: "gve-animation-tween", inputs: { tween: { classPropertyName: "tween", publicName: "tween", isSignal: true, isRequired: false, transformFunction: null }, elementIds: { classPropertyName: "elementIds", publicName: "elementIds", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { tween: "tweenChange", tweenCancel: "tweenCancel" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <mat-form-field>\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n @if ($any(label).errors?.required && (label.dirty || label.touched)) {\r\n <mat-error>label required</mat-error>\r\n } @if ($any(label).errors?.maxLength && (label.dirty || label.touched)) {\r\n <mat-error>label too long</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- type -->\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"type\">\r\n @for (t of types; track t) {\r\n <mat-option [value]=\"t\">{{ t }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- position -->\r\n <mat-form-field>\r\n <mat-label>position</mat-label>\r\n <input matInput [formControl]=\"position\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n [attr.aria-label]=\"'Information about position'\"\r\n (click)=\"\r\n openUrl(\r\n 'https://gsap.com/docs/v3/GSAP/Timeline/#positioning-animations-in-a-timeline'\r\n )\r\n \"\r\n >\r\n <mat-icon>info</mat-icon>\r\n </button>\r\n <mat-hint>time label < > += -=</mat-hint>\r\n @if ( $any(position).errors?.maxLength && (position.dirty ||\r\n position.touched) ) {\r\n <mat-error>position too long</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n\r\n <div class=\"form-row\">\r\n <!-- selector -->\r\n <mat-form-field>\r\n <mat-label>selector</mat-label>\r\n <input matInput [formControl]=\"selector\" />\r\n <mat-hint>CSS selector</mat-hint>\r\n @if ( $any(selector).errors?.required && (selector.dirty ||\r\n selector.touched) ) {\r\n <mat-error>selector required</mat-error>\r\n } @if ( $any(selector).errors?.maxLength && (selector.dirty ||\r\n selector.touched) ) {\r\n <mat-error>selector too long</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- element id -->\r\n @if ((elementIds())?.length) {\r\n <mat-form-field>\r\n <mat-label>element ID</mat-label>\r\n <mat-select [formControl]=\"elementId\">\r\n @for (id of elementIds(); track id) {\r\n <mat-option [value]=\"id\">{{ id }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <!-- note -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>note</mat-label>\r\n <textarea rows=\"2\" matInput [formControl]=\"note\"></textarea>\r\n @if ($any(note).errors?.maxLength && (note.dirty || note.touched)) {\r\n <mat-error>note too long</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- vars -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>vars</mat-label>\r\n <textarea matInput [formControl]=\"vars\"></textarea>\r\n <mat-hint>JSON object</mat-hint>\r\n @if ($any(vars).errors?.required && (vars.dirty || vars.touched)) {\r\n <mat-error>vars required</mat-error>\r\n } @if ($any(vars).errors?.json && (vars.dirty || vars.touched)) {\r\n <mat-error>invalid JSON</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- vars2 only when type is fromTo -->\r\n @if (type.value === 'fromTo') {\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>2nd vars</mat-label>\r\n <textarea matInput [formControl]=\"vars2\"></textarea>\r\n <mat-hint>JSON object</mat-hint>\r\n @if ($any(vars2).errors?.required && (vars2.dirty || vars2.touched)) {\r\n <mat-error>vars required</mat-error>\r\n } @if ($any(vars2).errors?.json && (vars2.dirty || vars2.touched)) {\r\n <mat-error>invalid JSON</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n }\r\n\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-icon-button\r\n matTooltip=\"Close tween\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-icon-button\r\n matTooltip=\"Save tween\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); }
|
|
189
184
|
}
|
|
190
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
185
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AnimationTweenComponent, decorators: [{
|
|
191
186
|
type: Component,
|
|
192
187
|
args: [{ selector: 'gve-animation-tween', imports: [
|
|
193
|
-
CommonModule,
|
|
194
188
|
ReactiveFormsModule,
|
|
195
189
|
MatButtonModule,
|
|
196
190
|
MatCheckboxModule,
|
|
@@ -200,7 +194,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
200
194
|
MatSelectModule,
|
|
201
195
|
MatTabsModule,
|
|
202
196
|
MatTooltipModule,
|
|
203
|
-
], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <mat-form-field>\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n
|
|
197
|
+
], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <mat-form-field>\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n @if ($any(label).errors?.required && (label.dirty || label.touched)) {\r\n <mat-error>label required</mat-error>\r\n } @if ($any(label).errors?.maxLength && (label.dirty || label.touched)) {\r\n <mat-error>label too long</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- type -->\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"type\">\r\n @for (t of types; track t) {\r\n <mat-option [value]=\"t\">{{ t }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- position -->\r\n <mat-form-field>\r\n <mat-label>position</mat-label>\r\n <input matInput [formControl]=\"position\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n [attr.aria-label]=\"'Information about position'\"\r\n (click)=\"\r\n openUrl(\r\n 'https://gsap.com/docs/v3/GSAP/Timeline/#positioning-animations-in-a-timeline'\r\n )\r\n \"\r\n >\r\n <mat-icon>info</mat-icon>\r\n </button>\r\n <mat-hint>time label < > += -=</mat-hint>\r\n @if ( $any(position).errors?.maxLength && (position.dirty ||\r\n position.touched) ) {\r\n <mat-error>position too long</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n\r\n <div class=\"form-row\">\r\n <!-- selector -->\r\n <mat-form-field>\r\n <mat-label>selector</mat-label>\r\n <input matInput [formControl]=\"selector\" />\r\n <mat-hint>CSS selector</mat-hint>\r\n @if ( $any(selector).errors?.required && (selector.dirty ||\r\n selector.touched) ) {\r\n <mat-error>selector required</mat-error>\r\n } @if ( $any(selector).errors?.maxLength && (selector.dirty ||\r\n selector.touched) ) {\r\n <mat-error>selector too long</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- element id -->\r\n @if ((elementIds())?.length) {\r\n <mat-form-field>\r\n <mat-label>element ID</mat-label>\r\n <mat-select [formControl]=\"elementId\">\r\n @for (id of elementIds(); track id) {\r\n <mat-option [value]=\"id\">{{ id }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <!-- note -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>note</mat-label>\r\n <textarea rows=\"2\" matInput [formControl]=\"note\"></textarea>\r\n @if ($any(note).errors?.maxLength && (note.dirty || note.touched)) {\r\n <mat-error>note too long</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- vars -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>vars</mat-label>\r\n <textarea matInput [formControl]=\"vars\"></textarea>\r\n <mat-hint>JSON object</mat-hint>\r\n @if ($any(vars).errors?.required && (vars.dirty || vars.touched)) {\r\n <mat-error>vars required</mat-error>\r\n } @if ($any(vars).errors?.json && (vars.dirty || vars.touched)) {\r\n <mat-error>invalid JSON</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- vars2 only when type is fromTo -->\r\n @if (type.value === 'fromTo') {\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>2nd vars</mat-label>\r\n <textarea matInput [formControl]=\"vars2\"></textarea>\r\n <mat-hint>JSON object</mat-hint>\r\n @if ($any(vars2).errors?.required && (vars2.dirty || vars2.touched)) {\r\n <mat-error>vars required</mat-error>\r\n } @if ($any(vars2).errors?.json && (vars2.dirty || vars2.touched)) {\r\n <mat-error>invalid JSON</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n }\r\n\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-icon-button\r\n matTooltip=\"Close tween\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-icon-button\r\n matTooltip=\"Save tween\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}\n"] }]
|
|
204
198
|
}], ctorParameters: () => [{ type: i1.FormBuilder }] });
|
|
205
199
|
|
|
206
200
|
/**
|
|
@@ -222,16 +216,16 @@ class AnimationTimelineComponent {
|
|
|
222
216
|
/**
|
|
223
217
|
* The animation timeline to edit.
|
|
224
218
|
*/
|
|
225
|
-
this.timeline = model();
|
|
219
|
+
this.timeline = model(...(ngDevMode ? [undefined, { debugName: "timeline" }] : []));
|
|
226
220
|
/**
|
|
227
221
|
* The IDs of the elements that can be selected by the tween.
|
|
228
222
|
* This list is used to allow the user to select an element from a dropdown.
|
|
229
223
|
*/
|
|
230
|
-
this.elementIds = input();
|
|
224
|
+
this.elementIds = input(...(ngDevMode ? [undefined, { debugName: "elementIds" }] : []));
|
|
231
225
|
/**
|
|
232
226
|
* The tags that can be used by the timeline.
|
|
233
227
|
*/
|
|
234
|
-
this.tags = input([]);
|
|
228
|
+
this.tags = input([], ...(ngDevMode ? [{ debugName: "tags" }] : []));
|
|
235
229
|
/**
|
|
236
230
|
* Emitted when the timeline is changed.
|
|
237
231
|
*/
|
|
@@ -240,7 +234,8 @@ class AnimationTimelineComponent {
|
|
|
240
234
|
* Emitted when the timeline editing is canceled.
|
|
241
235
|
*/
|
|
242
236
|
this.timelineCancel = output();
|
|
243
|
-
this.editedTweenIndex = -1;
|
|
237
|
+
this.editedTweenIndex = signal(-1, ...(ngDevMode ? [{ debugName: "editedTweenIndex" }] : []));
|
|
238
|
+
this.editedTween = signal(undefined, ...(ngDevMode ? [{ debugName: "editedTween" }] : []));
|
|
244
239
|
this.tag = formBuilder.control('', {
|
|
245
240
|
nonNullable: true,
|
|
246
241
|
validators: [Validators.required, Validators.maxLength(100)],
|
|
@@ -283,16 +278,16 @@ class AnimationTimelineComponent {
|
|
|
283
278
|
this.form.markAsPristine();
|
|
284
279
|
}
|
|
285
280
|
addTween() {
|
|
286
|
-
this.editedTweenIndex
|
|
287
|
-
this.editedTween
|
|
281
|
+
this.editedTweenIndex.set(-1);
|
|
282
|
+
this.editedTween.set({
|
|
288
283
|
label: 'tween #' + (this.tweens.value.length + 1),
|
|
289
284
|
type: 'to',
|
|
290
285
|
selector: '',
|
|
291
|
-
};
|
|
286
|
+
});
|
|
292
287
|
}
|
|
293
288
|
editTween(index) {
|
|
294
|
-
this.editedTweenIndex
|
|
295
|
-
this.editedTween
|
|
289
|
+
this.editedTweenIndex.set(index);
|
|
290
|
+
this.editedTween.set(deepCopy(this.tweens.value[index]));
|
|
296
291
|
}
|
|
297
292
|
deleteTween(index) {
|
|
298
293
|
this.tweens.setValue(this.tweens.value.filter((_, i) => i !== index));
|
|
@@ -300,15 +295,15 @@ class AnimationTimelineComponent {
|
|
|
300
295
|
this.tweens.updateValueAndValidity();
|
|
301
296
|
}
|
|
302
297
|
closeTween() {
|
|
303
|
-
this.editedTween
|
|
304
|
-
this.editedTweenIndex
|
|
298
|
+
this.editedTween.set(undefined);
|
|
299
|
+
this.editedTweenIndex.set(-1);
|
|
305
300
|
}
|
|
306
301
|
saveTween(tween) {
|
|
307
|
-
if (this.editedTweenIndex === -1) {
|
|
302
|
+
if (this.editedTweenIndex() === -1) {
|
|
308
303
|
this.tweens.setValue([...this.tweens.value, tween]);
|
|
309
304
|
}
|
|
310
305
|
else {
|
|
311
|
-
this.tweens.setValue(this.tweens.value.map((t, index) => index === this.editedTweenIndex ? tween : t));
|
|
306
|
+
this.tweens.setValue(this.tweens.value.map((t, index) => index === this.editedTweenIndex() ? tween : t));
|
|
312
307
|
}
|
|
313
308
|
this.tweens.markAsDirty();
|
|
314
309
|
this.tweens.updateValueAndValidity();
|
|
@@ -356,13 +351,12 @@ class AnimationTimelineComponent {
|
|
|
356
351
|
this.timelineChange.emit(this.timeline());
|
|
357
352
|
this.form.markAsPristine();
|
|
358
353
|
}
|
|
359
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
360
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: AnimationTimelineComponent, isStandalone: true, selector: "gve-animation-timeline", inputs: { timeline: { classPropertyName: "timeline", publicName: "timeline", isSignal: true, isRequired: false, transformFunction: null }, elementIds: { classPropertyName: "elementIds", publicName: "elementIds", isSignal: true, isRequired: false, transformFunction: null }, tags: { classPropertyName: "tags", publicName: "tags", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { timeline: "timelineChange", timelineChange: "timelineChange", timelineCancel: "timelineCancel" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- tag (bound) -->\r\n @if (tags().length) {\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <mat-select [formControl]=\"tag\">\r\n @for (t of tags(); track t) {\r\n <mat-option [value]=\"t\">{{ t }}</mat-option>\r\n }\r\n </mat-select>\r\n <mat-error\r\n *ngIf=\"$any(tag).errors?.required && (tag.dirty || tag.touched)\"\r\n >tag required</mat-error\r\n >\r\n </mat-form-field>\r\n } @else {\r\n <!-- tag (free) -->\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <input matInput [formControl]=\"tag\" />\r\n <mat-error\r\n *ngIf=\"$any(tag).errors?.required && (tag.dirty || tag.touched)\"\r\n >tag required</mat-error\r\n >\r\n <mat-error\r\n *ngIf=\"$any(tag).errors?.maxLength && (tag.dirty || tag.touched)\"\r\n >tag too long</mat-error\r\n >\r\n </mat-form-field>\r\n }\r\n\r\n <button\r\n mat-flat-button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n (click)=\"addTween()\"\r\n >\r\n <mat-icon>add_circle</mat-icon> tween\r\n </button>\r\n </div>\r\n\r\n <!-- vars -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>vars</mat-label>\r\n <textarea matInput [formControl]=\"vars\"></textarea>\r\n <mat-hint>JSON object</mat-hint>\r\n <mat-error *ngIf=\"$any(vars).errors?.json && (vars.dirty || vars.touched)\"\r\n >invalid JSON</mat-error\r\n >\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- tweens -->\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>label</th>\r\n <th>type</th>\r\n <th>selector</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (t of tweens.value; track t; let index = $index) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n color=\"primary\"\r\n (click)=\"editTween(index)\"\r\n matTooltip=\"Edit tween\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n color=\"warn\"\r\n (click)=\"deleteTween(index)\"\r\n matTooltip=\"Delete tween\"\r\n >\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n <!-- up -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n (click)=\"moveTweenUp(index)\"\r\n matTooltip=\"Move tween up\"\r\n [disabled]=\"index === 0\"\r\n >\r\n <mat-icon>arrow_circle_up</mat-icon>\r\n </button>\r\n <!-- down -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n (click)=\"moveTweenDown(index)\"\r\n matTooltip=\"Move tween down\"\r\n [disabled]=\"index === tweens.value.length - 1\"\r\n >\r\n <mat-icon>arrow_circle_down</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n {{ t.label }}\r\n </td>\r\n <td>\r\n {{ t.type }}\r\n </td>\r\n <td>\r\n {{ t.selector }}\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n\r\n <!-- tween editor -->\r\n <mat-expansion-panel [expanded]=\"editedTween\" [disabled]=\"!editedTween\">\r\n @if (editedTween) {\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>tween {{ editedTween.label }}</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n }\r\n <fieldset>\r\n <gve-animation-tween\r\n [elementIds]=\"elementIds()\"\r\n [tween]=\"editedTween\"\r\n (tweenChange)=\"saveTween($event)\"\r\n (tweenCancel)=\"closeTween()\"\r\n />\r\n </fieldset>\r\n </mat-expansion-panel>\r\n\r\n <!-- buttons -->\r\n <div class=\"button-row\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-icon-button\r\n matTooltip=\"Close timeline\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save timeline\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n timeline\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i5.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i8.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: AnimationTweenComponent, selector: "gve-animation-tween", inputs: ["tween", "elementIds"], outputs: ["tweenChange", "tweenCancel"] }] }); }
|
|
354
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AnimationTimelineComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
355
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: AnimationTimelineComponent, isStandalone: true, selector: "gve-animation-timeline", inputs: { timeline: { classPropertyName: "timeline", publicName: "timeline", isSignal: true, isRequired: false, transformFunction: null }, elementIds: { classPropertyName: "elementIds", publicName: "elementIds", isSignal: true, isRequired: false, transformFunction: null }, tags: { classPropertyName: "tags", publicName: "tags", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { timeline: "timelineChange", timelineChange: "timelineChange", timelineCancel: "timelineCancel" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- tag (bound) -->\r\n @if (tags().length) {\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <mat-select [formControl]=\"tag\">\r\n @for (t of tags(); track t) {\r\n <mat-option [value]=\"t\">{{ t }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(tag).errors?.required && (tag.dirty || tag.touched)) {\r\n <mat-error>tag required</mat-error>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <!-- tag (free) -->\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <input matInput [formControl]=\"tag\" />\r\n @if ($any(tag).errors?.required && (tag.dirty || tag.touched)) {\r\n <mat-error>tag required</mat-error>\r\n } @if ($any(tag).errors?.maxLength && (tag.dirty || tag.touched)) {\r\n <mat-error>tag too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <button\r\n mat-flat-button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n (click)=\"addTween()\"\r\n >\r\n <mat-icon>add_circle</mat-icon> tween\r\n </button>\r\n </div>\r\n\r\n <!-- vars -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>vars</mat-label>\r\n <textarea matInput [formControl]=\"vars\"></textarea>\r\n <mat-hint>JSON object</mat-hint>\r\n @if ($any(vars).errors?.json && (vars.dirty || vars.touched)) {\r\n <mat-error>invalid JSON</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- tweens -->\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>label</th>\r\n <th>type</th>\r\n <th>selector</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (t of tweens.value; track t; let index = $index) {\r\n <tr [class.selected]=\"index === editedTweenIndex()\">\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n color=\"primary\"\r\n (click)=\"editTween(index)\"\r\n matTooltip=\"Edit tween\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n color=\"warn\"\r\n (click)=\"deleteTween(index)\"\r\n matTooltip=\"Delete tween\"\r\n >\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n <!-- up -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n (click)=\"moveTweenUp(index)\"\r\n matTooltip=\"Move tween up\"\r\n [disabled]=\"index === 0\"\r\n >\r\n <mat-icon>arrow_circle_up</mat-icon>\r\n </button>\r\n <!-- down -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n (click)=\"moveTweenDown(index)\"\r\n matTooltip=\"Move tween down\"\r\n [disabled]=\"index === tweens.value.length - 1\"\r\n >\r\n <mat-icon>arrow_circle_down</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n {{ t.label }}\r\n </td>\r\n <td>\r\n {{ t.type }}\r\n </td>\r\n <td>\r\n {{ t.selector }}\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n\r\n <!-- tween editor -->\r\n @if (editedTween()) {\r\n <mat-expansion-panel [expanded]=\"editedTween()\" [disabled]=\"!editedTween()\">\r\n @if (editedTween()) {\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>tween #{{ editedTweenIndex() + 1 }}</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n }\r\n <fieldset>\r\n <gve-animation-tween\r\n [elementIds]=\"elementIds()\"\r\n [tween]=\"editedTween()\"\r\n (tweenChange)=\"saveTween($event)\"\r\n (tweenCancel)=\"closeTween()\"\r\n />\r\n </fieldset>\r\n </mat-expansion-panel>\r\n }\r\n\r\n <!-- buttons -->\r\n <div class=\"button-row\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-icon-button\r\n matTooltip=\"Close timeline\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save timeline\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n timeline\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: AnimationTweenComponent, selector: "gve-animation-tween", inputs: ["tween", "elementIds"], outputs: ["tweenChange", "tweenCancel"] }] }); }
|
|
361
356
|
}
|
|
362
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
357
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AnimationTimelineComponent, decorators: [{
|
|
363
358
|
type: Component,
|
|
364
359
|
args: [{ selector: 'gve-animation-timeline', imports: [
|
|
365
|
-
CommonModule,
|
|
366
360
|
ReactiveFormsModule,
|
|
367
361
|
MatButtonModule,
|
|
368
362
|
MatCheckboxModule,
|
|
@@ -373,10 +367,104 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
373
367
|
MatSelectModule,
|
|
374
368
|
MatTabsModule,
|
|
375
369
|
MatTooltipModule,
|
|
376
|
-
AnimationTweenComponent
|
|
377
|
-
], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- tag (bound) -->\r\n @if (tags().length) {\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <mat-select [formControl]=\"tag\">\r\n @for (t of tags(); track t) {\r\n <mat-option [value]=\"t\">{{ t }}</mat-option>\r\n }\r\n </mat-select>\r\n
|
|
370
|
+
AnimationTweenComponent
|
|
371
|
+
], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- tag (bound) -->\r\n @if (tags().length) {\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <mat-select [formControl]=\"tag\">\r\n @for (t of tags(); track t) {\r\n <mat-option [value]=\"t\">{{ t }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(tag).errors?.required && (tag.dirty || tag.touched)) {\r\n <mat-error>tag required</mat-error>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <!-- tag (free) -->\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <input matInput [formControl]=\"tag\" />\r\n @if ($any(tag).errors?.required && (tag.dirty || tag.touched)) {\r\n <mat-error>tag required</mat-error>\r\n } @if ($any(tag).errors?.maxLength && (tag.dirty || tag.touched)) {\r\n <mat-error>tag too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <button\r\n mat-flat-button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n (click)=\"addTween()\"\r\n >\r\n <mat-icon>add_circle</mat-icon> tween\r\n </button>\r\n </div>\r\n\r\n <!-- vars -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>vars</mat-label>\r\n <textarea matInput [formControl]=\"vars\"></textarea>\r\n <mat-hint>JSON object</mat-hint>\r\n @if ($any(vars).errors?.json && (vars.dirty || vars.touched)) {\r\n <mat-error>invalid JSON</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- tweens -->\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>label</th>\r\n <th>type</th>\r\n <th>selector</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (t of tweens.value; track t; let index = $index) {\r\n <tr [class.selected]=\"index === editedTweenIndex()\">\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n color=\"primary\"\r\n (click)=\"editTween(index)\"\r\n matTooltip=\"Edit tween\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n color=\"warn\"\r\n (click)=\"deleteTween(index)\"\r\n matTooltip=\"Delete tween\"\r\n >\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n <!-- up -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n (click)=\"moveTweenUp(index)\"\r\n matTooltip=\"Move tween up\"\r\n [disabled]=\"index === 0\"\r\n >\r\n <mat-icon>arrow_circle_up</mat-icon>\r\n </button>\r\n <!-- down -->\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n (click)=\"moveTweenDown(index)\"\r\n matTooltip=\"Move tween down\"\r\n [disabled]=\"index === tweens.value.length - 1\"\r\n >\r\n <mat-icon>arrow_circle_down</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n {{ t.label }}\r\n </td>\r\n <td>\r\n {{ t.type }}\r\n </td>\r\n <td>\r\n {{ t.selector }}\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n\r\n <!-- tween editor -->\r\n @if (editedTween()) {\r\n <mat-expansion-panel [expanded]=\"editedTween()\" [disabled]=\"!editedTween()\">\r\n @if (editedTween()) {\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>tween #{{ editedTweenIndex() + 1 }}</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n }\r\n <fieldset>\r\n <gve-animation-tween\r\n [elementIds]=\"elementIds()\"\r\n [tween]=\"editedTween()\"\r\n (tweenChange)=\"saveTween($event)\"\r\n (tweenCancel)=\"closeTween()\"\r\n />\r\n </fieldset>\r\n </mat-expansion-panel>\r\n }\r\n\r\n <!-- buttons -->\r\n <div class=\"button-row\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-icon-button\r\n matTooltip=\"Close timeline\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save timeline\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n timeline\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}\n"] }]
|
|
378
372
|
}], ctorParameters: () => [{ type: i1.FormBuilder }] });
|
|
379
373
|
|
|
374
|
+
/**
|
|
375
|
+
* 🔑 `gve-animation-timeline-set`
|
|
376
|
+
*
|
|
377
|
+
* A component to edit a set of animation timelines.
|
|
378
|
+
* Used by the `gve-snapshot-editor` component.
|
|
379
|
+
*
|
|
380
|
+
* - ▶️ `timelines` (`GveAnimationTimeline[]`): the animation timelines to edit.
|
|
381
|
+
* - ▶️ `elementIds` (`string[]`): the IDs of the elements that can be selected by the tween.
|
|
382
|
+
* - ▶️ `tags` (`string[]`): the tags that can be used by the timeline.
|
|
383
|
+
* - 🔥 `timelinesChange` (`GveAnimationTimeline[]`): emitted when the timelines are changed.
|
|
384
|
+
* - 🔥 `timelinesCancel` (`void`): emitted when the timeline editing is canceled.
|
|
385
|
+
*/
|
|
386
|
+
class AnimationTimelineSetComponent {
|
|
387
|
+
constructor(_dialogService) {
|
|
388
|
+
this._dialogService = _dialogService;
|
|
389
|
+
/**
|
|
390
|
+
* The animation timelines to edit.
|
|
391
|
+
*/
|
|
392
|
+
this.timelines = model([], ...(ngDevMode ? [{ debugName: "timelines" }] : []));
|
|
393
|
+
/**
|
|
394
|
+
* The IDs of the elements that can be selected by the tween.
|
|
395
|
+
* This list is used to allow the user to select an element from a dropdown.
|
|
396
|
+
*/
|
|
397
|
+
this.elementIds = input(...(ngDevMode ? [undefined, { debugName: "elementIds" }] : []));
|
|
398
|
+
/**
|
|
399
|
+
* The tags that can be used by the timeline.
|
|
400
|
+
*/
|
|
401
|
+
this.tags = input([], ...(ngDevMode ? [{ debugName: "tags" }] : []));
|
|
402
|
+
/**
|
|
403
|
+
* Emitted when the timeline editing is canceled.
|
|
404
|
+
*/
|
|
405
|
+
this.timelinesCancel = output();
|
|
406
|
+
this.editedTimeline = signal(undefined, ...(ngDevMode ? [{ debugName: "editedTimeline" }] : []));
|
|
407
|
+
this.editedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "editedIndex" }] : []));
|
|
408
|
+
}
|
|
409
|
+
closeTimeline() {
|
|
410
|
+
this.editedTimeline.set(undefined);
|
|
411
|
+
this.editedIndex.set(-1);
|
|
412
|
+
}
|
|
413
|
+
newTimeline() {
|
|
414
|
+
this.editedTimeline.set({
|
|
415
|
+
tag: '',
|
|
416
|
+
tweens: [],
|
|
417
|
+
});
|
|
418
|
+
this.editedIndex.set(-1);
|
|
419
|
+
}
|
|
420
|
+
editTimeline(index) {
|
|
421
|
+
this.editedTimeline.set(deepCopy(this.timelines()[index]));
|
|
422
|
+
this.editedIndex.set(index);
|
|
423
|
+
}
|
|
424
|
+
onTimelineChange(timeline) {
|
|
425
|
+
const timelines = [...this.timelines()];
|
|
426
|
+
if (this.editedIndex() === -1) {
|
|
427
|
+
timelines.push(timeline);
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
timelines.splice(this.editedIndex(), 1, timeline);
|
|
431
|
+
}
|
|
432
|
+
// sort timelines by tag
|
|
433
|
+
timelines.sort((a, b) => a.tag.localeCompare(b.tag));
|
|
434
|
+
this.timelines.set(timelines);
|
|
435
|
+
this.closeTimeline();
|
|
436
|
+
}
|
|
437
|
+
deleteTimeline(index) {
|
|
438
|
+
this._dialogService
|
|
439
|
+
.confirm('Confirm Deletion', `Delete ${this.timelines()[index].tag}?`)
|
|
440
|
+
.subscribe((yes) => {
|
|
441
|
+
if (yes) {
|
|
442
|
+
const timelines = [...this.timelines()];
|
|
443
|
+
timelines.splice(index, 1);
|
|
444
|
+
this.timelines.set(timelines);
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AnimationTimelineSetComponent, deps: [{ token: i4$2.DialogService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
449
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: AnimationTimelineSetComponent, isStandalone: true, selector: "gve-animation-timeline-set", inputs: { timelines: { classPropertyName: "timelines", publicName: "timelines", isSignal: true, isRequired: false, transformFunction: null }, elementIds: { classPropertyName: "elementIds", publicName: "elementIds", isSignal: true, isRequired: false, transformFunction: null }, tags: { classPropertyName: "tags", publicName: "tags", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { timelines: "timelinesChange", timelinesCancel: "timelinesCancel" }, ngImport: i0, template: "<div>\r\n <!-- add -->\r\n <div>\r\n <button\r\n type=\"button\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n (click)=\"newTimeline()\"\r\n >\r\n <mat-icon>add_circle</mat-icon>\r\n timeline\r\n </button>\r\n </div>\r\n\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>tag</th>\r\n <th>tweens</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (t of timelines(); track t.tag; let index = $index) {\r\n <tr [class.selected]=\"editedIndex() === index\">\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button type=\"button\" mat-icon-button (click)=\"editTimeline(index)\">\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button type=\"button\" mat-icon-button (click)=\"deleteTimeline(index)\">\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ t.tag }}</td>\r\n <td>{{ t.tweens.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n\r\n <!-- editor -->\r\n @if (editedTimeline()) {\r\n <mat-expansion-panel [disabled]=\"!editedTimeline\" [expanded]=\"editedTimeline\">\r\n <mat-expansion-panel-header>\r\n timeline {{ editedTimeline()?.tag }}\r\n </mat-expansion-panel-header>\r\n <gve-animation-timeline\r\n [elementIds]=\"elementIds()\"\r\n [tags]=\"tags()\"\r\n [timeline]=\"editedTimeline()\"\r\n (timelineChange)=\"onTimelineChange($event!)\"\r\n (timelineCancel)=\"closeTimeline()\"\r\n />\r\n </mat-expansion-panel>\r\n }\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: AnimationTimelineComponent, selector: "gve-animation-timeline", inputs: ["timeline", "elementIds", "tags"], outputs: ["timelineChange", "timelineCancel"] }] }); }
|
|
450
|
+
}
|
|
451
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: AnimationTimelineSetComponent, decorators: [{
|
|
452
|
+
type: Component,
|
|
453
|
+
args: [{ selector: 'gve-animation-timeline-set', imports: [
|
|
454
|
+
ReactiveFormsModule,
|
|
455
|
+
MatButtonModule,
|
|
456
|
+
MatCheckboxModule,
|
|
457
|
+
MatExpansionModule,
|
|
458
|
+
MatFormFieldModule,
|
|
459
|
+
MatIconModule,
|
|
460
|
+
MatInputModule,
|
|
461
|
+
MatSelectModule,
|
|
462
|
+
MatTabsModule,
|
|
463
|
+
MatTooltipModule,
|
|
464
|
+
AnimationTimelineComponent,
|
|
465
|
+
], template: "<div>\r\n <!-- add -->\r\n <div>\r\n <button\r\n type=\"button\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n (click)=\"newTimeline()\"\r\n >\r\n <mat-icon>add_circle</mat-icon>\r\n timeline\r\n </button>\r\n </div>\r\n\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>tag</th>\r\n <th>tweens</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (t of timelines(); track t.tag; let index = $index) {\r\n <tr [class.selected]=\"editedIndex() === index\">\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button type=\"button\" mat-icon-button (click)=\"editTimeline(index)\">\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button type=\"button\" mat-icon-button (click)=\"deleteTimeline(index)\">\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ t.tag }}</td>\r\n <td>{{ t.tweens.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n\r\n <!-- editor -->\r\n @if (editedTimeline()) {\r\n <mat-expansion-panel [disabled]=\"!editedTimeline\" [expanded]=\"editedTimeline\">\r\n <mat-expansion-panel-header>\r\n timeline {{ editedTimeline()?.tag }}\r\n </mat-expansion-panel-header>\r\n <gve-animation-timeline\r\n [elementIds]=\"elementIds()\"\r\n [tags]=\"tags()\"\r\n [timeline]=\"editedTimeline()\"\r\n (timelineChange)=\"onTimelineChange($event!)\"\r\n (timelineCancel)=\"closeTimeline()\"\r\n />\r\n </mat-expansion-panel>\r\n }\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}\n"] }]
|
|
466
|
+
}], ctorParameters: () => [{ type: i4$2.DialogService }] });
|
|
467
|
+
|
|
380
468
|
/**
|
|
381
469
|
* 🔑 `gve-base-text-char`
|
|
382
470
|
*
|
|
@@ -385,25 +473,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
385
473
|
*/
|
|
386
474
|
class BaseTextCharComponent {
|
|
387
475
|
constructor() {
|
|
388
|
-
this.defaultColor = '#D8D8D8';
|
|
389
|
-
this.defaultBorderColor = '#D8D8D8';
|
|
390
|
-
this.defaultEmSize = 1.5;
|
|
391
476
|
/**
|
|
392
477
|
* The character to display.
|
|
393
478
|
*/
|
|
394
|
-
this.char = input();
|
|
479
|
+
this.char = input(...(ngDevMode ? [undefined, { debugName: "char" }] : []));
|
|
395
480
|
/**
|
|
396
481
|
* Emitted when the character is clicked.
|
|
397
482
|
*/
|
|
398
483
|
this.charPick = output();
|
|
484
|
+
this.defaultColor = '#D8D8D8';
|
|
485
|
+
this.defaultBorderColor = '#D8D8D8';
|
|
486
|
+
this.defaultEmSize = 1.5;
|
|
399
487
|
}
|
|
400
488
|
onCharClick(event) {
|
|
401
489
|
this.charPick.emit({ char: this.char(), event });
|
|
402
490
|
}
|
|
403
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
404
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
491
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BaseTextCharComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
492
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: BaseTextCharComponent, isStandalone: true, selector: "gve-base-text-char", inputs: { char: { classPropertyName: "char", publicName: "char", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { charPick: "charPick" }, ngImport: i0, template: "@if (char()) {\r\n<div matRipple id=\"container\" (click)=\"onCharClick($event)\">\r\n <div\r\n id=\"c-label\"\r\n [style.fontSize]=\"char()!.emSize + 'em'\"\r\n [style.borderColor]=\"char()!.borderColor\"\r\n >\r\n {{ char()!.label }}\r\n </div>\r\n <div\r\n id=\"c-id\"\r\n [style.fontSize]=\"char()!.emSize / 2 + 'em'\"\r\n [style.color]=\"char()!.color | colorToContrast\"\r\n [style.borderColor]=\"char()!.borderColor\"\r\n [style.backgroundColor]=\"char()!.color\"\r\n >\r\n {{ char()!.id }}\r\n </div>\r\n</div>\r\n}\r\n", styles: ["div#container{cursor:pointer;flex-direction:column;align-items:center}div#c-label{border:1px solid silver;border-radius:6px;padding:6px;height:1.5em;align-items:center;justify-content:center;text-align:center}div#c-id{margin-top:4px;margin-bottom:16px;border:1px solid silver;border-radius:6px;padding:6px;align-items:center;justify-content:center;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: MatRippleModule }, { kind: "directive", type: i1$1.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "pipe", type: ColorToContrastPipe, name: "colorToContrast" }] }); }
|
|
405
493
|
}
|
|
406
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
494
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BaseTextCharComponent, decorators: [{
|
|
407
495
|
type: Component,
|
|
408
496
|
args: [{ selector: 'gve-base-text-char', imports: [MatRippleModule, ColorToContrastPipe], template: "@if (char()) {\r\n<div matRipple id=\"container\" (click)=\"onCharClick($event)\">\r\n <div\r\n id=\"c-label\"\r\n [style.fontSize]=\"char()!.emSize + 'em'\"\r\n [style.borderColor]=\"char()!.borderColor\"\r\n >\r\n {{ char()!.label }}\r\n </div>\r\n <div\r\n id=\"c-id\"\r\n [style.fontSize]=\"char()!.emSize / 2 + 'em'\"\r\n [style.color]=\"char()!.color | colorToContrast\"\r\n [style.borderColor]=\"char()!.borderColor\"\r\n [style.backgroundColor]=\"char()!.color\"\r\n >\r\n {{ char()!.id }}\r\n </div>\r\n</div>\r\n}\r\n", styles: ["div#container{cursor:pointer;flex-direction:column;align-items:center}div#c-label{border:1px solid silver;border-radius:6px;padding:6px;height:1.5em;align-items:center;justify-content:center;text-align:center}div#c-id{margin-top:4px;margin-bottom:16px;border:1px solid silver;border-radius:6px;padding:6px;align-items:center;justify-content:center;text-align:center}\n"] }]
|
|
409
497
|
}] });
|
|
@@ -411,13 +499,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
411
499
|
/**
|
|
412
500
|
* 🔑 `gve-base-text-view`
|
|
413
501
|
*
|
|
414
|
-
* A component to display a selectable base text.
|
|
502
|
+
* A component to display a selectable base text. Its input is either a string or an
|
|
503
|
+
* array of `CharNode`'s.
|
|
415
504
|
* Used by the chain result view component and the base text editor component.
|
|
416
505
|
*
|
|
417
506
|
* - ▶️ `defaultColor` (`string`): the default color for the text.
|
|
507
|
+
* - ▶️ `colorCallback` (callback): an optional callback to get the color of a
|
|
508
|
+
* character node.
|
|
418
509
|
* - ▶️ `defaultBorderColor` (`string`): the default border color for the text.
|
|
510
|
+
* - ▶️ `borderColorCallback` (callback): an optional callback to get the border color
|
|
511
|
+
* of a character node.
|
|
419
512
|
* - ▶️ `selectionColor` (`string`): the color for the selected text.
|
|
420
|
-
* - ▶️ `hasLineNumber` (`boolean`): true if line numbers should be displayed next
|
|
513
|
+
* - ▶️ `hasLineNumber` (`boolean`): true if line numbers should be displayed next
|
|
514
|
+
* to each line.
|
|
421
515
|
* - ▶️ `text` (`string` | `CharNode[]`): the text to display.
|
|
422
516
|
* - 🔥 `charPick` (`BaseTextCharEvent`): emitted when a character is picked.
|
|
423
517
|
* - 🔥 `rangePick` (`VarBaseTextRange`): emitted when a range is picked.
|
|
@@ -427,28 +521,33 @@ class BaseTextViewComponent {
|
|
|
427
521
|
/**
|
|
428
522
|
* The default color for the text.
|
|
429
523
|
*/
|
|
430
|
-
this.defaultColor = input('#DBDBDB');
|
|
524
|
+
this.defaultColor = input('#DBDBDB', ...(ngDevMode ? [{ debugName: "defaultColor" }] : []));
|
|
431
525
|
/**
|
|
432
526
|
* The default border color for the text.
|
|
433
527
|
*/
|
|
434
|
-
this.defaultBorderColor = input('#DBDBDB');
|
|
528
|
+
this.defaultBorderColor = input('#DBDBDB', ...(ngDevMode ? [{ debugName: "defaultBorderColor" }] : []));
|
|
435
529
|
/**
|
|
436
530
|
* The color for the selected text.
|
|
437
531
|
*/
|
|
438
|
-
this.selectionColor = input('#3E92CC');
|
|
532
|
+
this.selectionColor = input('#3E92CC', ...(ngDevMode ? [{ debugName: "selectionColor" }] : []));
|
|
439
533
|
/**
|
|
440
534
|
* True if line numbers should be displayed next to each line.
|
|
441
535
|
*/
|
|
442
|
-
this.hasLineNumber = input(false);
|
|
536
|
+
this.hasLineNumber = input(false, ...(ngDevMode ? [{ debugName: "hasLineNumber" }] : []));
|
|
443
537
|
/**
|
|
444
538
|
* The text to display.
|
|
445
539
|
*/
|
|
446
|
-
this.text = input([]);
|
|
540
|
+
this.text = input([], ...(ngDevMode ? [{ debugName: "text" }] : []));
|
|
541
|
+
/**
|
|
542
|
+
* An optional callback to get the color of a character node.
|
|
543
|
+
* Return null to use the default color.
|
|
544
|
+
*/
|
|
545
|
+
this.colorCallback = input(...(ngDevMode ? [undefined, { debugName: "colorCallback" }] : []));
|
|
447
546
|
/**
|
|
448
547
|
* An optional callback to get the color of a character node.
|
|
449
548
|
* Return null to use the default color.
|
|
450
549
|
*/
|
|
451
|
-
this.borderColorCallback = input();
|
|
550
|
+
this.borderColorCallback = input(...(ngDevMode ? [undefined, { debugName: "borderColorCallback" }] : []));
|
|
452
551
|
/**
|
|
453
552
|
* Emitted when a character is picked.
|
|
454
553
|
*/
|
|
@@ -459,15 +558,20 @@ class BaseTextViewComponent {
|
|
|
459
558
|
* The range is inclusive.
|
|
460
559
|
*/
|
|
461
560
|
this.rangePick = output();
|
|
462
|
-
this.lines = [];
|
|
561
|
+
this.lines = signal([], ...(ngDevMode ? [{ debugName: "lines" }] : []));
|
|
463
562
|
// build lines when text or border color callback change
|
|
464
563
|
effect(() => {
|
|
465
|
-
this.buildLines(this.text(), this.borderColorCallback());
|
|
564
|
+
this.buildLines(this.text(), this.colorCallback(), this.borderColorCallback());
|
|
565
|
+
});
|
|
566
|
+
// reset _lastSelectedChar when text changes
|
|
567
|
+
effect(() => {
|
|
568
|
+
this.text();
|
|
569
|
+
this._lastSelectedChar = undefined;
|
|
466
570
|
});
|
|
467
571
|
}
|
|
468
|
-
buildLines(text, borderColorCallback) {
|
|
572
|
+
buildLines(text, colorCallback, borderColorCallback) {
|
|
469
573
|
if (!text) {
|
|
470
|
-
this.lines
|
|
574
|
+
this.lines.set([]);
|
|
471
575
|
return;
|
|
472
576
|
}
|
|
473
577
|
const newLines = [];
|
|
@@ -478,61 +582,102 @@ class BaseTextViewComponent {
|
|
|
478
582
|
id: nodes[i].id,
|
|
479
583
|
value: nodes[i].data,
|
|
480
584
|
label: nodes[i].label,
|
|
481
|
-
color:
|
|
585
|
+
color: colorCallback
|
|
586
|
+
? colorCallback(nodes[i]) || this.defaultColor()
|
|
587
|
+
: this.defaultColor(),
|
|
482
588
|
borderColor: borderColorCallback
|
|
483
589
|
? borderColorCallback(nodes[i]) || this.defaultBorderColor()
|
|
484
590
|
: this.defaultBorderColor(),
|
|
485
591
|
emSize: 1.5,
|
|
486
592
|
};
|
|
593
|
+
char.oldColor = char.color;
|
|
594
|
+
char.oldBorderColor = char.borderColor;
|
|
487
595
|
newLines[newLines.length - 1].push(char);
|
|
488
596
|
if (char.value === '\n') {
|
|
489
597
|
newLines.push([]);
|
|
490
598
|
}
|
|
491
599
|
}
|
|
492
|
-
this.lines
|
|
600
|
+
this.lines.set(newLines);
|
|
493
601
|
}
|
|
494
602
|
resetColors() {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
603
|
+
if (!this.lines())
|
|
604
|
+
return;
|
|
605
|
+
const newLines = this.lines().map((line) => line.map((c) => {
|
|
606
|
+
if (!c)
|
|
607
|
+
return c;
|
|
608
|
+
return {
|
|
609
|
+
...c,
|
|
610
|
+
color: c.oldColor || this.defaultColor(),
|
|
611
|
+
borderColor: c.oldBorderColor || this.defaultBorderColor(),
|
|
612
|
+
};
|
|
613
|
+
}));
|
|
614
|
+
this.lines.set(newLines);
|
|
501
615
|
}
|
|
502
616
|
onCharPick(event) {
|
|
617
|
+
// guard against null/undefined event.char
|
|
618
|
+
if (!event?.char) {
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
// first reset all colors before updating
|
|
503
622
|
this.resetColors();
|
|
504
|
-
|
|
623
|
+
// calculate selection state
|
|
624
|
+
const isRangeSelection = Boolean(this._lastSelectedChar) &&
|
|
505
625
|
this._lastSelectedChar !== event.char &&
|
|
506
|
-
event.event
|
|
626
|
+
event.event?.ctrlKey;
|
|
627
|
+
let rangeToEmit;
|
|
628
|
+
if (isRangeSelection && this._lastSelectedChar) {
|
|
507
629
|
const minId = Math.min(this._lastSelectedChar.id, event.char.id);
|
|
508
630
|
const maxId = Math.max(this._lastSelectedChar.id, event.char.id);
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
631
|
+
// update UI to highlight range - create new objects
|
|
632
|
+
const newLines = this.lines().map((line) => line.map((c) => {
|
|
633
|
+
if (!c)
|
|
634
|
+
return c;
|
|
635
|
+
if (c.id >= minId && c.id <= maxId) {
|
|
636
|
+
return {
|
|
637
|
+
...c,
|
|
638
|
+
oldColor: c.color,
|
|
639
|
+
oldBorderColor: c.borderColor,
|
|
640
|
+
color: this.selectionColor(),
|
|
641
|
+
borderColor: this.selectionColor(),
|
|
642
|
+
};
|
|
515
643
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
this.
|
|
519
|
-
|
|
644
|
+
return c;
|
|
645
|
+
}));
|
|
646
|
+
this.lines.set(newLines);
|
|
647
|
+
rangeToEmit = { at: minId, run: maxId - minId + 1 };
|
|
520
648
|
}
|
|
521
649
|
else {
|
|
522
|
-
//
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
650
|
+
// single character selection - create new objects
|
|
651
|
+
const newLines = this.lines().map((line) => line.map((c) => {
|
|
652
|
+
if (!c)
|
|
653
|
+
return c;
|
|
654
|
+
if (c.id === event.char.id) {
|
|
655
|
+
const updatedChar = {
|
|
656
|
+
...c,
|
|
657
|
+
oldColor: c.color,
|
|
658
|
+
oldBorderColor: c.borderColor,
|
|
659
|
+
color: this.selectionColor(),
|
|
660
|
+
borderColor: this.selectionColor(),
|
|
661
|
+
};
|
|
662
|
+
// update last selected character reference
|
|
663
|
+
this._lastSelectedChar = updatedChar;
|
|
664
|
+
return updatedChar;
|
|
665
|
+
}
|
|
666
|
+
return c;
|
|
667
|
+
}));
|
|
668
|
+
this.lines.set(newLines);
|
|
669
|
+
rangeToEmit = { at: event.char.id, run: 1 };
|
|
527
670
|
}
|
|
528
|
-
|
|
671
|
+
// emit events last, after all internal state is updated
|
|
672
|
+
this.charPick.emit(event);
|
|
673
|
+
this.rangePick.emit(rangeToEmit);
|
|
529
674
|
}
|
|
530
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
531
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
675
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BaseTextViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
676
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: BaseTextViewComponent, isStandalone: true, selector: "gve-base-text-view", inputs: { defaultColor: { classPropertyName: "defaultColor", publicName: "defaultColor", isSignal: true, isRequired: false, transformFunction: null }, defaultBorderColor: { classPropertyName: "defaultBorderColor", publicName: "defaultBorderColor", isSignal: true, isRequired: false, transformFunction: null }, selectionColor: { classPropertyName: "selectionColor", publicName: "selectionColor", isSignal: true, isRequired: false, transformFunction: null }, hasLineNumber: { classPropertyName: "hasLineNumber", publicName: "hasLineNumber", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, colorCallback: { classPropertyName: "colorCallback", publicName: "colorCallback", isSignal: true, isRequired: false, transformFunction: null }, borderColorCallback: { classPropertyName: "borderColorCallback", publicName: "borderColorCallback", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { charPick: "charPick", rangePick: "rangePick" }, ngImport: i0, template: "<div id=\"text\">\r\n @for (line of lines(); track $index) {\r\n <div class=\"line\">\r\n @if (hasLineNumber()) {\r\n <div class=\"nr\">\r\n {{ lines().indexOf(line) + 1 }}\r\n </div>\r\n } @for (c of line; track c.id) {\r\n <gve-base-text-char [char]=\"c\" (charPick)=\"onCharPick($event)\" />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".line{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.line *{flex:0 0 auto}.nr{font-size:.8em;font-weight:700;color:silver;margin:0 4px}\n"], dependencies: [{ kind: "component", type: BaseTextCharComponent, selector: "gve-base-text-char", inputs: ["char"], outputs: ["charPick"] }] }); }
|
|
532
677
|
}
|
|
533
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
678
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BaseTextViewComponent, decorators: [{
|
|
534
679
|
type: Component,
|
|
535
|
-
args: [{ selector: 'gve-base-text-view', imports: [
|
|
680
|
+
args: [{ selector: 'gve-base-text-view', imports: [BaseTextCharComponent], template: "<div id=\"text\">\r\n @for (line of lines(); track $index) {\r\n <div class=\"line\">\r\n @if (hasLineNumber()) {\r\n <div class=\"nr\">\r\n {{ lines().indexOf(line) + 1 }}\r\n </div>\r\n } @for (c of line; track c.id) {\r\n <gve-base-text-char [char]=\"c\" (charPick)=\"onCharPick($event)\" />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".line{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.line *{flex:0 0 auto}.nr{font-size:.8em;font-weight:700;color:silver;margin:0 4px}\n"] }]
|
|
536
681
|
}], ctorParameters: () => [] });
|
|
537
682
|
|
|
538
683
|
/**
|
|
@@ -560,30 +705,27 @@ class FeatureEditorComponent {
|
|
|
560
705
|
* The list of feature names to display in the name selection.
|
|
561
706
|
* This is used when you have a closed list of features.
|
|
562
707
|
*/
|
|
563
|
-
this.featNames = input();
|
|
708
|
+
this.featNames = input(...(ngDevMode ? [undefined, { debugName: "featNames" }] : []));
|
|
564
709
|
/**
|
|
565
710
|
* The feature values map. When specified and the user selects a feature
|
|
566
711
|
* name present in the map keys, the corresponding values will be used
|
|
567
712
|
* to populate the value selection.
|
|
568
713
|
*/
|
|
569
|
-
this.featValues = input();
|
|
714
|
+
this.featValues = input(...(ngDevMode ? [undefined, { debugName: "featValues" }] : []));
|
|
570
715
|
/**
|
|
571
716
|
* The feature to edit.
|
|
572
717
|
*/
|
|
573
|
-
this.feature = model();
|
|
718
|
+
this.feature = model(...(ngDevMode ? [undefined, { debugName: "feature" }] : []));
|
|
574
719
|
/**
|
|
575
720
|
* True if the feature is a variant operation feature, which has
|
|
576
721
|
* additional properties like negation, global, and short-lived.
|
|
577
722
|
*/
|
|
578
|
-
this.isVar = input(false);
|
|
723
|
+
this.isVar = input(false, ...(ngDevMode ? [{ debugName: "isVar" }] : []));
|
|
579
724
|
/**
|
|
580
725
|
* Event emitted when the user cancels the feature editing.
|
|
581
726
|
*/
|
|
582
727
|
this.featureCancel = output();
|
|
583
|
-
|
|
584
|
-
* Event emitted when the user saves the edited feature.
|
|
585
|
-
*/
|
|
586
|
-
this.featureChange = output();
|
|
728
|
+
this.nameIds = signal(undefined, ...(ngDevMode ? [{ debugName: "nameIds" }] : []));
|
|
587
729
|
this.name = formBuilder.control('', {
|
|
588
730
|
validators: [Validators.required, Validators.maxLength(50)],
|
|
589
731
|
nonNullable: true,
|
|
@@ -611,7 +753,7 @@ class FeatureEditorComponent {
|
|
|
611
753
|
this.updateForm(this.feature());
|
|
612
754
|
setTimeout(() => {
|
|
613
755
|
this.nameControl?.nativeElement?.focus();
|
|
614
|
-
this.nameIds
|
|
756
|
+
this.nameIds.set(this.getLabeledIdsFor(this.name.value, this.featValues()));
|
|
615
757
|
}, 500);
|
|
616
758
|
});
|
|
617
759
|
}
|
|
@@ -622,7 +764,7 @@ class FeatureEditorComponent {
|
|
|
622
764
|
.subscribe((name) => {
|
|
623
765
|
if (!this._frozen && this.featNames()?.length) {
|
|
624
766
|
this.value.reset();
|
|
625
|
-
this.nameIds
|
|
767
|
+
this.nameIds.set(this.getLabeledIdsFor(name, this.featValues()));
|
|
626
768
|
}
|
|
627
769
|
});
|
|
628
770
|
}
|
|
@@ -672,15 +814,13 @@ class FeatureEditorComponent {
|
|
|
672
814
|
value: this.value.value.trim(),
|
|
673
815
|
setPolicy: this.setPolicy.value,
|
|
674
816
|
});
|
|
675
|
-
this.featureChange.emit(this.feature());
|
|
676
817
|
}
|
|
677
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
678
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
818
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FeatureEditorComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
819
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: FeatureEditorComponent, isStandalone: true, selector: "gve-feature-editor", inputs: { featNames: { classPropertyName: "featNames", publicName: "featNames", isSignal: true, isRequired: false, transformFunction: null }, featValues: { classPropertyName: "featValues", publicName: "featValues", isSignal: true, isRequired: false, transformFunction: null }, feature: { classPropertyName: "feature", publicName: "feature", isSignal: true, isRequired: false, transformFunction: null }, isVar: { classPropertyName: "isVar", publicName: "isVar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { feature: "featureChange", featureCancel: "featureCancel" }, viewQueries: [{ propertyName: "nameControl", first: true, predicate: ["nameCtl"], descendants: true }], ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n @if (featNames()?.length) {\r\n <!-- name (bound) -->\r\n <mat-form-field>\r\n <mat-label>name</mat-label>\r\n <mat-select #nameCtl [formControl]=\"name\">\r\n @for (i of featNames(); track i) {\r\n <mat-option [value]=\"i.id\">{{ i.label }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(name).errors?.required && (name.dirty || name.touched)) {\r\n <mat-error>name required</mat-error>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <!-- name (free) -->\r\n <mat-form-field>\r\n <mat-label>name</mat-label>\r\n <input #nameCtl matInput [formControl]=\"name\" />\r\n @if ($any(name).errors?.required && (name.dirty || name.touched)) {\r\n <mat-error>name required</mat-error>\r\n } @if ($any(name).errors?.maxLength && (name.dirty || name.touched)) {\r\n <mat-error>name too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- value (bound) -->\r\n @if (nameIds()?.length) {\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <mat-select [formControl]=\"value\">\r\n @for (e of nameIds(); track e) {\r\n <mat-option [value]=\"e.id\">{{ e.label }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(value).errors?.required && (value.dirty || value.touched)) {\r\n <mat-error>value required</mat-error>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <!-- value (free) -->\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n @if ($any(value).errors?.required && (value.dirty || value.touched)) {\r\n <mat-error>value required</mat-error>\r\n } @if ($any(value).errors?.maxLength && (value.dirty || value.touched)) {\r\n <mat-error>value too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- setPolicy -->\r\n <mat-form-field>\r\n <mat-label>set policy</mat-label>\r\n <mat-select [formControl]=\"setPolicy\">\r\n <mat-option [value]=\"0\">multiple</mat-option>\r\n <mat-option [value]=\"1\">single</mat-option>\r\n <mat-option [value]=\"2\">single first</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n @if (isVar()) {\r\n <div class=\"form-row\">\r\n <!-- isNegated -->\r\n <mat-checkbox [formControl]=\"isNegated\">negated</mat-checkbox>\r\n\r\n <!-- isShortLived -->\r\n <mat-checkbox [formControl]=\"isShortLived\">short-lived</mat-checkbox>\r\n\r\n <!-- isGlobal -->\r\n <mat-checkbox [formControl]=\"isGlobal\">global</mat-checkbox>\r\n </div>\r\n }\r\n\r\n <!-- buttons -->\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"cancel()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Accept changes\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i3$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); }
|
|
679
820
|
}
|
|
680
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
821
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FeatureEditorComponent, decorators: [{
|
|
681
822
|
type: Component,
|
|
682
823
|
args: [{ selector: 'gve-feature-editor', imports: [
|
|
683
|
-
CommonModule,
|
|
684
824
|
ReactiveFormsModule,
|
|
685
825
|
MatButtonModule,
|
|
686
826
|
MatCheckboxModule,
|
|
@@ -689,7 +829,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
689
829
|
MatInputModule,
|
|
690
830
|
MatSelectModule,
|
|
691
831
|
MatTooltipModule,
|
|
692
|
-
], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n @if (featNames()?.length) {\r\n <!-- name (bound) -->\r\n <mat-form-field>\r\n <mat-label>name</mat-label>\r\n <mat-select #nameCtl [formControl]=\"name\">\r\n
|
|
832
|
+
], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n @if (featNames()?.length) {\r\n <!-- name (bound) -->\r\n <mat-form-field>\r\n <mat-label>name</mat-label>\r\n <mat-select #nameCtl [formControl]=\"name\">\r\n @for (i of featNames(); track i) {\r\n <mat-option [value]=\"i.id\">{{ i.label }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(name).errors?.required && (name.dirty || name.touched)) {\r\n <mat-error>name required</mat-error>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <!-- name (free) -->\r\n <mat-form-field>\r\n <mat-label>name</mat-label>\r\n <input #nameCtl matInput [formControl]=\"name\" />\r\n @if ($any(name).errors?.required && (name.dirty || name.touched)) {\r\n <mat-error>name required</mat-error>\r\n } @if ($any(name).errors?.maxLength && (name.dirty || name.touched)) {\r\n <mat-error>name too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- value (bound) -->\r\n @if (nameIds()?.length) {\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <mat-select [formControl]=\"value\">\r\n @for (e of nameIds(); track e) {\r\n <mat-option [value]=\"e.id\">{{ e.label }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(value).errors?.required && (value.dirty || value.touched)) {\r\n <mat-error>value required</mat-error>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <!-- value (free) -->\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n @if ($any(value).errors?.required && (value.dirty || value.touched)) {\r\n <mat-error>value required</mat-error>\r\n } @if ($any(value).errors?.maxLength && (value.dirty || value.touched)) {\r\n <mat-error>value too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- setPolicy -->\r\n <mat-form-field>\r\n <mat-label>set policy</mat-label>\r\n <mat-select [formControl]=\"setPolicy\">\r\n <mat-option [value]=\"0\">multiple</mat-option>\r\n <mat-option [value]=\"1\">single</mat-option>\r\n <mat-option [value]=\"2\">single first</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n @if (isVar()) {\r\n <div class=\"form-row\">\r\n <!-- isNegated -->\r\n <mat-checkbox [formControl]=\"isNegated\">negated</mat-checkbox>\r\n\r\n <!-- isShortLived -->\r\n <mat-checkbox [formControl]=\"isShortLived\">short-lived</mat-checkbox>\r\n\r\n <!-- isGlobal -->\r\n <mat-checkbox [formControl]=\"isGlobal\">global</mat-checkbox>\r\n </div>\r\n }\r\n\r\n <!-- buttons -->\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"cancel()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Accept changes\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"] }]
|
|
693
833
|
}], ctorParameters: () => [{ type: i1.FormBuilder }], propDecorators: { nameControl: [{
|
|
694
834
|
type: ViewChild,
|
|
695
835
|
args: ['nameCtl']
|
|
@@ -721,48 +861,45 @@ class FeatureSetEditorComponent {
|
|
|
721
861
|
constructor(formBuilder) {
|
|
722
862
|
this.POLICIES = ['M', 'S', 'SF'];
|
|
723
863
|
/**
|
|
724
|
-
* True if the
|
|
864
|
+
* True if the feature is a variant operation feature, which has
|
|
865
|
+
* additional properties like negation, global, and short-lived.
|
|
725
866
|
*/
|
|
726
|
-
this.isVar = input(false);
|
|
867
|
+
this.isVar = input(false, ...(ngDevMode ? [{ debugName: "isVar" }] : []));
|
|
727
868
|
/**
|
|
728
869
|
* The list of feature names to display in the name selection.
|
|
729
870
|
* This is used when you have a closed list of features.
|
|
730
871
|
*/
|
|
731
|
-
this.featNames = input();
|
|
872
|
+
this.featNames = input(...(ngDevMode ? [undefined, { debugName: "featNames" }] : []));
|
|
732
873
|
/**
|
|
733
874
|
* The feature values map. When specified and the user selects a feature
|
|
734
875
|
* name present in the map keys, the corresponding values will be used
|
|
735
876
|
* to populate the value selection.
|
|
736
877
|
*/
|
|
737
|
-
this.featValues = input();
|
|
878
|
+
this.featValues = input(...(ngDevMode ? [undefined, { debugName: "featValues" }] : []));
|
|
738
879
|
/**
|
|
739
880
|
* The threshold at which the features filter should become visible.
|
|
740
881
|
* If set to 0, the filter is always visible; if set to -1, it is always
|
|
741
882
|
* invisible; otherwise, it gets visible when the number of features
|
|
742
883
|
* is greater than or equal to the threshold. Default is 5.
|
|
743
884
|
*/
|
|
744
|
-
this.filterThreshold = input(5);
|
|
885
|
+
this.filterThreshold = input(5, ...(ngDevMode ? [{ debugName: "filterThreshold" }] : []));
|
|
745
886
|
/**
|
|
746
887
|
* The features to edit.
|
|
747
888
|
*/
|
|
748
|
-
this.features = model([]);
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
this.featuresChange = output();
|
|
753
|
-
this.filteredFeatures = [];
|
|
889
|
+
this.features = model([], ...(ngDevMode ? [{ debugName: "features" }] : []));
|
|
890
|
+
this.editedFeature = signal(undefined, ...(ngDevMode ? [{ debugName: "editedFeature" }] : []));
|
|
891
|
+
this.editedFeatureIndex = signal(-1, ...(ngDevMode ? [{ debugName: "editedFeatureIndex" }] : []));
|
|
892
|
+
this.filteredFeatures = signal([], ...(ngDevMode ? [{ debugName: "filteredFeatures" }] : []));
|
|
754
893
|
this.filter = formBuilder.control(null);
|
|
755
|
-
this._editedFeatureIndex = -1;
|
|
756
894
|
// when features change, apply the filter
|
|
757
895
|
effect(() => {
|
|
758
896
|
this.applyFeatureFilter(this.features(), this.filter.value);
|
|
759
897
|
});
|
|
760
898
|
}
|
|
761
899
|
applyFeatureFilter(features, name) {
|
|
762
|
-
this.filteredFeatures
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
}) || [];
|
|
900
|
+
this.filteredFeatures.set(features.filter((feature) => {
|
|
901
|
+
return !name || feature.name.toLowerCase().includes(name.toLowerCase());
|
|
902
|
+
}) || []);
|
|
766
903
|
}
|
|
767
904
|
ngOnInit() {
|
|
768
905
|
// when the filter changes, apply the filter
|
|
@@ -776,16 +913,16 @@ class FeatureSetEditorComponent {
|
|
|
776
913
|
this._sub?.unsubscribe();
|
|
777
914
|
}
|
|
778
915
|
addFeature() {
|
|
779
|
-
this.editedFeature
|
|
916
|
+
this.editedFeature.set({
|
|
780
917
|
name: '',
|
|
781
918
|
value: '',
|
|
782
919
|
setPolicy: FeatureSetPolicy.multiple,
|
|
783
|
-
};
|
|
784
|
-
this.
|
|
920
|
+
});
|
|
921
|
+
this.editedFeatureIndex.set(-1);
|
|
785
922
|
}
|
|
786
923
|
editFeature(feature) {
|
|
787
|
-
this.editedFeature
|
|
788
|
-
this.
|
|
924
|
+
this.editedFeature.set(deepCopy(feature));
|
|
925
|
+
this.editedFeatureIndex.set(this.features().indexOf(feature));
|
|
789
926
|
}
|
|
790
927
|
deleteFeature(feature) {
|
|
791
928
|
const index = this.features().indexOf(feature);
|
|
@@ -795,7 +932,6 @@ class FeatureSetEditorComponent {
|
|
|
795
932
|
const features = [...this.features()];
|
|
796
933
|
features.splice(index, 1);
|
|
797
934
|
this.features.set(features);
|
|
798
|
-
this.featuresChange.emit(this.features());
|
|
799
935
|
}
|
|
800
936
|
onFeatureChange(feature) {
|
|
801
937
|
if (!feature) {
|
|
@@ -810,27 +946,25 @@ class FeatureSetEditorComponent {
|
|
|
810
946
|
}
|
|
811
947
|
}
|
|
812
948
|
}
|
|
813
|
-
if (this.
|
|
949
|
+
if (this.editedFeatureIndex() === -1) {
|
|
814
950
|
features.push(feature);
|
|
815
951
|
}
|
|
816
952
|
else {
|
|
817
|
-
features.splice(this.
|
|
953
|
+
features.splice(this.editedFeatureIndex(), 1, feature);
|
|
818
954
|
}
|
|
819
955
|
this.onFeatureCancel();
|
|
820
956
|
this.features.set(features);
|
|
821
|
-
this.featuresChange.emit(this.features());
|
|
822
957
|
}
|
|
823
958
|
onFeatureCancel() {
|
|
824
|
-
this.editedFeature
|
|
825
|
-
this.
|
|
959
|
+
this.editedFeature.set(undefined);
|
|
960
|
+
this.editedFeatureIndex.set(-1);
|
|
826
961
|
}
|
|
827
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
828
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
962
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FeatureSetEditorComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
963
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: FeatureSetEditorComponent, isStandalone: true, selector: "gve-feature-set-editor", inputs: { isVar: { classPropertyName: "isVar", publicName: "isVar", isSignal: true, isRequired: false, transformFunction: null }, featNames: { classPropertyName: "featNames", publicName: "featNames", isSignal: true, isRequired: false, transformFunction: null }, featValues: { classPropertyName: "featValues", publicName: "featValues", isSignal: true, isRequired: false, transformFunction: null }, filterThreshold: { classPropertyName: "filterThreshold", publicName: "filterThreshold", isSignal: true, isRequired: false, transformFunction: null }, features: { classPropertyName: "features", publicName: "features", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { features: "featuresChange" }, ngImport: i0, template: "<div>\r\n <div class=\"form-row\">\r\n <!-- filter -->\r\n @if (filterThreshold() === 0 || features().length >= filterThreshold()) {\r\n <mat-form-field>\r\n <input matInput placeholder=\"filter\" [formControl]=\"filter\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n (click)=\"filter.reset()\"\r\n [disabled]=\"!filter.value\"\r\n [attr.aria-label]=\"'Reset filter'\"\r\n >\r\n <mat-icon color=\"warn\" class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n\r\n <!-- add feature button -->\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Add a new feature\"\r\n (click)=\"addFeature()\"\r\n [class.in-row-button]=\"\r\n filterThreshold() === 0 || features()!.length >= filterThreshold()\r\n \"\r\n >\r\n <mat-icon>add</mat-icon>\r\n feature\r\n </button>\r\n </div>\r\n\r\n <!-- list -->\r\n @if (features().length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>feature</th>\r\n <th>value</th>\r\n <th>policy</th>\r\n @if (isVar()) {\r\n <th>negated</th>\r\n <th>global</th>\r\n <th>short-lived</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (feature of filteredFeatures(); track feature; let i = $index) {\r\n <tr [class.selected]=\"i === editedFeatureIndex()\">\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Edit this feature\"\r\n (click)=\"editFeature(feature)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Delete this feature\"\r\n (click)=\"deleteFeature(feature)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n @if (featNames()?.length) {\r\n <span>{{\r\n feature.name | flatLookup : featNames : \"id\" : \"label\"\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.name }}</span>\r\n }\r\n </td>\r\n <td>\r\n @if (featValues()) {\r\n <span>{{\r\n feature.value | flatLookup : featValues()![feature.name]\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.value }}</span>\r\n }\r\n </td>\r\n <td>\r\n <span>{{ POLICIES[feature.setPolicy] }}</span>\r\n </td>\r\n @if (isVar()) {\r\n <td>\r\n <span>{{ $any(feature).isNegated ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n <td>\r\n <span>{{ $any(feature).isGlobal ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n <td>\r\n <span>{{ $any(feature).isShortLived ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- editor -->\r\n @if (editedFeature()) {\r\n <mat-expansion-panel\r\n [disabled]=\"!editedFeature()\"\r\n [expanded]=\"editedFeature()\"\r\n >\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>\r\n <span>{{ editedFeature()?.name || \"feature\" }}</span>\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-feature-editor\r\n [isVar]=\"isVar()\"\r\n [featNames]=\"featNames()\"\r\n [featValues]=\"featValues()\"\r\n [feature]=\"editedFeature()\"\r\n (featureChange)=\"onFeatureChange($event)\"\r\n (featureCancel)=\"onFeatureCancel()\"\r\n />\r\n </mat-expansion-panel>\r\n }\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.in-row-button{margin-top:-16px}table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: FeatureEditorComponent, selector: "gve-feature-editor", inputs: ["featNames", "featValues", "feature", "isVar"], outputs: ["featureChange", "featureCancel"] }, { kind: "pipe", type: FlatLookupPipe, name: "flatLookup" }] }); }
|
|
829
964
|
}
|
|
830
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
965
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FeatureSetEditorComponent, decorators: [{
|
|
831
966
|
type: Component,
|
|
832
967
|
args: [{ selector: 'gve-feature-set-editor', imports: [
|
|
833
|
-
CommonModule,
|
|
834
968
|
ReactiveFormsModule,
|
|
835
969
|
MatButtonModule,
|
|
836
970
|
MatExpansionModule,
|
|
@@ -841,7 +975,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
841
975
|
MatTooltipModule,
|
|
842
976
|
FlatLookupPipe,
|
|
843
977
|
FeatureEditorComponent,
|
|
844
|
-
], template: "<div>\r\n <div class=\"form-row\">\r\n <!-- filter -->\r\n @if (filterThreshold() === 0 || features().length >= filterThreshold()) {\r\n <mat-form-field>\r\n <input matInput placeholder=\"filter\" [formControl]=\"filter\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n (click)=\"filter.reset()\"\r\n [disabled]=\"!filter.value\"\r\n [attr.aria-label]=\"'Reset filter'\"\r\n >\r\n <mat-icon color=\"warn\" class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n\r\n <!-- add feature button -->\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Add a new feature\"\r\n (click)=\"addFeature()\"\r\n [class.in-row-button]=\"\r\n filterThreshold() === 0 || features()!.length >= filterThreshold()\r\n \"\r\n >\r\n <mat-icon>add</mat-icon>\r\n feature\r\n </button>\r\n </div>\r\n\r\n <!-- list -->\r\n @if (features().length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>feature</th>\r\n <th>value</th>\r\n <th>policy</th>\r\n @if (isVar()) {\r\n <th>negated</th>\r\n <th>global</th>\r\n <th>short-lived</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (feature of filteredFeatures; track feature) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Edit this feature\"\r\n (click)=\"editFeature(feature)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Delete this feature\"\r\n (click)=\"deleteFeature(feature)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n @if (featNames()?.length) {\r\n <span>{{\r\n feature.name | flatLookup : featNames : \"id\" : \"label\"\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.name }}</span>\r\n }\r\n </td>\r\n <td>\r\n @if (featValues()) {\r\n <span>{{\r\n feature.value | flatLookup : featValues()![feature.name]\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.value }}</span>\r\n }\r\n </td>\r\n <td>\r\n <span>{{ POLICIES[feature.setPolicy] }}</span>\r\n </td>\r\n @if (isVar()) {\r\n <td>\r\n <span>{{ $any(feature).isNegated ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n <td>\r\n <span>{{ $any(feature).isGlobal ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n <td>\r\n <span>{{ $any(feature).isShortLived ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- editor -->\r\n <mat-expansion-panel
|
|
978
|
+
], template: "<div>\r\n <div class=\"form-row\">\r\n <!-- filter -->\r\n @if (filterThreshold() === 0 || features().length >= filterThreshold()) {\r\n <mat-form-field>\r\n <input matInput placeholder=\"filter\" [formControl]=\"filter\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n (click)=\"filter.reset()\"\r\n [disabled]=\"!filter.value\"\r\n [attr.aria-label]=\"'Reset filter'\"\r\n >\r\n <mat-icon color=\"warn\" class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n }\r\n\r\n <!-- add feature button -->\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Add a new feature\"\r\n (click)=\"addFeature()\"\r\n [class.in-row-button]=\"\r\n filterThreshold() === 0 || features()!.length >= filterThreshold()\r\n \"\r\n >\r\n <mat-icon>add</mat-icon>\r\n feature\r\n </button>\r\n </div>\r\n\r\n <!-- list -->\r\n @if (features().length) {\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>feature</th>\r\n <th>value</th>\r\n <th>policy</th>\r\n @if (isVar()) {\r\n <th>negated</th>\r\n <th>global</th>\r\n <th>short-lived</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (feature of filteredFeatures(); track feature; let i = $index) {\r\n <tr [class.selected]=\"i === editedFeatureIndex()\">\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Edit this feature\"\r\n (click)=\"editFeature(feature)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Delete this feature\"\r\n (click)=\"deleteFeature(feature)\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n @if (featNames()?.length) {\r\n <span>{{\r\n feature.name | flatLookup : featNames : \"id\" : \"label\"\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.name }}</span>\r\n }\r\n </td>\r\n <td>\r\n @if (featValues()) {\r\n <span>{{\r\n feature.value | flatLookup : featValues()![feature.name]\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.value }}</span>\r\n }\r\n </td>\r\n <td>\r\n <span>{{ POLICIES[feature.setPolicy] }}</span>\r\n </td>\r\n @if (isVar()) {\r\n <td>\r\n <span>{{ $any(feature).isNegated ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n <td>\r\n <span>{{ $any(feature).isGlobal ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n <td>\r\n <span>{{ $any(feature).isShortLived ? \"yes\" : \"no\" }}</span>\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- editor -->\r\n @if (editedFeature()) {\r\n <mat-expansion-panel\r\n [disabled]=\"!editedFeature()\"\r\n [expanded]=\"editedFeature()\"\r\n >\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>\r\n <span>{{ editedFeature()?.name || \"feature\" }}</span>\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-feature-editor\r\n [isVar]=\"isVar()\"\r\n [featNames]=\"featNames()\"\r\n [featValues]=\"featValues()\"\r\n [feature]=\"editedFeature()\"\r\n (featureChange)=\"onFeatureChange($event)\"\r\n (featureCancel)=\"onFeatureCancel()\"\r\n />\r\n </mat-expansion-panel>\r\n }\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.in-row-button{margin-top:-16px}table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}\n"] }]
|
|
845
979
|
}], ctorParameters: () => [{ type: i1.FormBuilder }] });
|
|
846
980
|
|
|
847
981
|
/**
|
|
@@ -861,24 +995,38 @@ class BaseTextEditorComponent {
|
|
|
861
995
|
* objects, or undefined. In output this will be an array of `CharNode`
|
|
862
996
|
* objects.
|
|
863
997
|
*/
|
|
864
|
-
this.text = input.required({
|
|
865
|
-
|
|
866
|
-
|
|
998
|
+
this.text = input.required(...(ngDevMode ? [{ debugName: "text", transform: (value) => {
|
|
999
|
+
if (value === undefined) {
|
|
1000
|
+
return undefined;
|
|
1001
|
+
}
|
|
1002
|
+
if (Array.isArray(value)) {
|
|
1003
|
+
return value;
|
|
1004
|
+
}
|
|
1005
|
+
if (typeof value === 'string') {
|
|
1006
|
+
return SnapshotViewService.stringToBaseChars(value);
|
|
1007
|
+
}
|
|
867
1008
|
return undefined;
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1009
|
+
} }] : [{
|
|
1010
|
+
transform: (value) => {
|
|
1011
|
+
if (value === undefined) {
|
|
1012
|
+
return undefined;
|
|
1013
|
+
}
|
|
1014
|
+
if (Array.isArray(value)) {
|
|
1015
|
+
return value;
|
|
1016
|
+
}
|
|
1017
|
+
if (typeof value === 'string') {
|
|
1018
|
+
return SnapshotViewService.stringToBaseChars(value);
|
|
1019
|
+
}
|
|
1020
|
+
return undefined;
|
|
1021
|
+
},
|
|
1022
|
+
}]));
|
|
878
1023
|
/**
|
|
879
1024
|
* Emitted for the edited text as an array of `CharNode`'s whenever it changes.
|
|
880
1025
|
*/
|
|
881
1026
|
this.textChange = output();
|
|
1027
|
+
this.selectedChar = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedChar" }] : []));
|
|
1028
|
+
this.selectedCharLabel = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedCharLabel" }] : []));
|
|
1029
|
+
this.textRange = signal(undefined, ...(ngDevMode ? [{ debugName: "textRange" }] : []));
|
|
882
1030
|
this.userText = formBuilder.control('', {
|
|
883
1031
|
nonNullable: true,
|
|
884
1032
|
validators: [Validators.required, Validators.maxLength(10000)],
|
|
@@ -901,19 +1049,24 @@ class BaseTextEditorComponent {
|
|
|
901
1049
|
});
|
|
902
1050
|
}
|
|
903
1051
|
resetSelectedChar() {
|
|
904
|
-
this.selectedChar
|
|
905
|
-
this.selectedCharLabel
|
|
1052
|
+
this.selectedChar.set(undefined);
|
|
1053
|
+
this.selectedCharLabel.set(undefined);
|
|
906
1054
|
}
|
|
907
1055
|
onSelectedChar(event) {
|
|
908
|
-
this.selectedChar
|
|
909
|
-
this.selectedCharLabel
|
|
1056
|
+
this.selectedChar.set(this.text().find((c) => c.id === event.char.id));
|
|
1057
|
+
this.selectedCharLabel.set(event.char.label);
|
|
910
1058
|
}
|
|
911
1059
|
onFeaturesChange(features) {
|
|
912
|
-
this.selectedChar
|
|
913
|
-
|
|
1060
|
+
const char = this.selectedChar();
|
|
1061
|
+
if (!char) {
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1064
|
+
const chars = this.text().map((c) => c.id === char.id ? { ...c, features } : c);
|
|
1065
|
+
this.selectedChar.set({ ...char, features });
|
|
1066
|
+
this.textChange.emit(chars);
|
|
914
1067
|
}
|
|
915
1068
|
onRangePick(range) {
|
|
916
|
-
this.textRange
|
|
1069
|
+
this.textRange.set(range);
|
|
917
1070
|
}
|
|
918
1071
|
patchTextFromUser() {
|
|
919
1072
|
// TODO
|
|
@@ -927,13 +1080,12 @@ class BaseTextEditorComponent {
|
|
|
927
1080
|
}
|
|
928
1081
|
});
|
|
929
1082
|
}
|
|
930
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
931
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1083
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BaseTextEditorComponent, deps: [{ token: i1.FormBuilder }, { token: i4$2.DialogService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1084
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: BaseTextEditorComponent, isStandalone: true, selector: "gve-base-text-editor", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { textChange: "textChange" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"setTextFromUser()\">\r\n <!-- text -->\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>text</mat-label>\r\n <textarea matInput [formControl]=\"userText\" rows=\"5\"></textarea>\r\n @if ( $any(userText).errors?.required && (userText.dirty ||\r\n userText.touched) ) {\r\n <mat-error>text required</mat-error>\r\n } @if ( $any(userText).errors?.maxLength && (userText.dirty ||\r\n userText.touched) ) {\r\n <mat-error>text too long</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n <!-- buttons -->\r\n <div class=\"form-row\">\r\n <!-- set -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n class=\"mat-warn\"\r\n matTooltip=\"Reset characters to newly entered text\"\r\n [disabled]=\"!userText.value\"\r\n (click)=\"setTextFromUser()\"\r\n >\r\n set\r\n </button>\r\n <!-- patch: TODO -->\r\n <!-- <button\r\n type=\"button\"\r\n mat-flat-button\r\n class=\"mat-primary\"\r\n matTooltip=\"Patch characters with newly entered text\"\r\n [disabled]=\"!userText.value\"\r\n (click)=\"patchTextFromUser()\"\r\n >\r\n patch\r\n </button> -->\r\n </div>\r\n\r\n <!-- base text -->\r\n <div id=\"text-view\">\r\n <gve-base-text-view\r\n [text]=\"text() || []\"\r\n (charPick)=\"onSelectedChar($event)\"\r\n (rangePick)=\"textRange.set($event)\"\r\n />\r\n\r\n <!-- text range -->\r\n @if (textRange()) {\r\n <div id=\"text-range\">{{ textRange()!.at }} \u00D7 {{ textRange()!.run }}</div>\r\n }\r\n </div>\r\n\r\n <!-- char features -->\r\n @if (selectedChar()) {\r\n <fieldset>\r\n <legend>features</legend>\r\n <gve-feature-set-editor\r\n [features]=\"selectedChar()!.features || []\"\r\n (featuresChange)=\"onFeaturesChange($event)\"\r\n />\r\n </fieldset>\r\n }\r\n</form>\r\n", styles: [".full-width{width:100%}#text-view{margin:8px 0}fieldset{border:1px solid #ccc;padding:10px;margin:10px 0;border-radius:5px}legend{color:silver}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: BaseTextViewComponent, selector: "gve-base-text-view", inputs: ["defaultColor", "defaultBorderColor", "selectionColor", "hasLineNumber", "text", "colorCallback", "borderColorCallback"], outputs: ["charPick", "rangePick"] }, { kind: "component", type: FeatureSetEditorComponent, selector: "gve-feature-set-editor", inputs: ["isVar", "featNames", "featValues", "filterThreshold", "features"], outputs: ["featuresChange"] }] }); }
|
|
932
1085
|
}
|
|
933
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1086
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BaseTextEditorComponent, decorators: [{
|
|
934
1087
|
type: Component,
|
|
935
1088
|
args: [{ selector: 'gve-base-text-editor', imports: [
|
|
936
|
-
CommonModule,
|
|
937
1089
|
ReactiveFormsModule,
|
|
938
1090
|
MatButtonModule,
|
|
939
1091
|
MatFormFieldModule,
|
|
@@ -942,8 +1094,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
942
1094
|
MatTooltipModule,
|
|
943
1095
|
BaseTextViewComponent,
|
|
944
1096
|
FeatureSetEditorComponent,
|
|
945
|
-
], template: "<form [formGroup]=\"form\" (submit)=\"setTextFromUser()\">\r\n <!-- text -->\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>text</mat-label>\r\n <textarea matInput [formControl]=\"userText\" rows=\"5\"></textarea>\r\n
|
|
946
|
-
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type:
|
|
1097
|
+
], template: "<form [formGroup]=\"form\" (submit)=\"setTextFromUser()\">\r\n <!-- text -->\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>text</mat-label>\r\n <textarea matInput [formControl]=\"userText\" rows=\"5\"></textarea>\r\n @if ( $any(userText).errors?.required && (userText.dirty ||\r\n userText.touched) ) {\r\n <mat-error>text required</mat-error>\r\n } @if ( $any(userText).errors?.maxLength && (userText.dirty ||\r\n userText.touched) ) {\r\n <mat-error>text too long</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n <!-- buttons -->\r\n <div class=\"form-row\">\r\n <!-- set -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n class=\"mat-warn\"\r\n matTooltip=\"Reset characters to newly entered text\"\r\n [disabled]=\"!userText.value\"\r\n (click)=\"setTextFromUser()\"\r\n >\r\n set\r\n </button>\r\n <!-- patch: TODO -->\r\n <!-- <button\r\n type=\"button\"\r\n mat-flat-button\r\n class=\"mat-primary\"\r\n matTooltip=\"Patch characters with newly entered text\"\r\n [disabled]=\"!userText.value\"\r\n (click)=\"patchTextFromUser()\"\r\n >\r\n patch\r\n </button> -->\r\n </div>\r\n\r\n <!-- base text -->\r\n <div id=\"text-view\">\r\n <gve-base-text-view\r\n [text]=\"text() || []\"\r\n (charPick)=\"onSelectedChar($event)\"\r\n (rangePick)=\"textRange.set($event)\"\r\n />\r\n\r\n <!-- text range -->\r\n @if (textRange()) {\r\n <div id=\"text-range\">{{ textRange()!.at }} \u00D7 {{ textRange()!.run }}</div>\r\n }\r\n </div>\r\n\r\n <!-- char features -->\r\n @if (selectedChar()) {\r\n <fieldset>\r\n <legend>features</legend>\r\n <gve-feature-set-editor\r\n [features]=\"selectedChar()!.features || []\"\r\n (featuresChange)=\"onFeaturesChange($event)\"\r\n />\r\n </fieldset>\r\n }\r\n</form>\r\n", styles: [".full-width{width:100%}#text-view{margin:8px 0}fieldset{border:1px solid #ccc;padding:10px;margin:10px 0;border-radius:5px}legend{color:silver}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"] }]
|
|
1098
|
+
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i4$2.DialogService }] });
|
|
947
1099
|
|
|
948
1100
|
/**
|
|
949
1101
|
* Service to interact with the GVE API.
|
|
@@ -1012,15 +1164,15 @@ class GveApiService {
|
|
|
1012
1164
|
})
|
|
1013
1165
|
.pipe(catchError(this._error.handleError));
|
|
1014
1166
|
}
|
|
1015
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1016
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1167
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: GveApiService, deps: [{ token: i1$2.HttpClient }, { token: i2$1.ErrorService }, { token: i2$1.EnvService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1168
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: GveApiService, providedIn: 'root' }); }
|
|
1017
1169
|
}
|
|
1018
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1170
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: GveApiService, decorators: [{
|
|
1019
1171
|
type: Injectable,
|
|
1020
1172
|
args: [{
|
|
1021
1173
|
providedIn: 'root',
|
|
1022
1174
|
}]
|
|
1023
|
-
}], ctorParameters: () => [{ type: i1$
|
|
1175
|
+
}], ctorParameters: () => [{ type: i1$2.HttpClient }, { type: i2$1.ErrorService }, { type: i2$1.EnvService }] });
|
|
1024
1176
|
|
|
1025
1177
|
/**
|
|
1026
1178
|
* 🔑 `gve-batch-operation-editor`
|
|
@@ -1038,11 +1190,13 @@ class BatchOperationEditorComponent {
|
|
|
1038
1190
|
this._api = _api;
|
|
1039
1191
|
this.dialogRef = dialogRef;
|
|
1040
1192
|
this.data = data;
|
|
1193
|
+
this.busy = signal(false, ...(ngDevMode ? [{ debugName: "busy" }] : []));
|
|
1194
|
+
this.parseError = signal(undefined, ...(ngDevMode ? [{ debugName: "parseError" }] : []));
|
|
1041
1195
|
/**
|
|
1042
1196
|
* The preset text to parse if any. Usually you start with a blank
|
|
1043
1197
|
* text, but sometimes you might want to pre-set it.
|
|
1044
1198
|
*/
|
|
1045
|
-
this.preset = input();
|
|
1199
|
+
this.preset = input(...(ngDevMode ? [undefined, { debugName: "preset" }] : []));
|
|
1046
1200
|
/**
|
|
1047
1201
|
* Emitted when operations change.
|
|
1048
1202
|
*/
|
|
@@ -1064,15 +1218,15 @@ class BatchOperationEditorComponent {
|
|
|
1064
1218
|
}
|
|
1065
1219
|
}
|
|
1066
1220
|
parseOperations(text) {
|
|
1067
|
-
if (this.busy || !text) {
|
|
1221
|
+
if (this.busy() || !text) {
|
|
1068
1222
|
return;
|
|
1069
1223
|
}
|
|
1070
|
-
this.busy
|
|
1071
|
-
this.parseError
|
|
1224
|
+
this.busy.set(true);
|
|
1225
|
+
this.parseError.set(undefined);
|
|
1072
1226
|
this._api.parseOperations(text).subscribe({
|
|
1073
1227
|
next: (wrapper) => {
|
|
1074
1228
|
if (wrapper.error) {
|
|
1075
|
-
this.parseError
|
|
1229
|
+
this.parseError.set(wrapper.error);
|
|
1076
1230
|
return;
|
|
1077
1231
|
}
|
|
1078
1232
|
this.operationsChange.emit(wrapper.result || []);
|
|
@@ -1081,20 +1235,20 @@ class BatchOperationEditorComponent {
|
|
|
1081
1235
|
}
|
|
1082
1236
|
},
|
|
1083
1237
|
error: (error) => {
|
|
1084
|
-
this.parseError
|
|
1238
|
+
this.parseError.set(error.message);
|
|
1085
1239
|
},
|
|
1086
1240
|
complete: () => {
|
|
1087
|
-
this.busy
|
|
1241
|
+
this.busy.set(false);
|
|
1088
1242
|
},
|
|
1089
1243
|
});
|
|
1090
1244
|
}
|
|
1091
1245
|
close() {
|
|
1092
1246
|
this.dialogRef?.close();
|
|
1093
1247
|
}
|
|
1094
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1095
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1248
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BatchOperationEditorComponent, deps: [{ token: i1.FormBuilder }, { token: GveApiService }, { token: i3$2.MatDialogRef, optional: true }, { token: MAT_DIALOG_DATA, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1249
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: BatchOperationEditorComponent, isStandalone: true, selector: "gve-batch-operation-editor", inputs: { preset: { classPropertyName: "preset", publicName: "preset", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { operationsChange: "operationsChange" }, ngImport: i0, template: "<div [style.padding]=\"dialogRef ? '8px' : '0'\">\r\n @if (dialogRef) {\r\n <div id=\"heading\">\r\n <h2>Add Operations</h2>\r\n </div>\r\n }\r\n <fieldset>\r\n <div id=\"batch-input\">\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>operations</mat-label>\r\n <textarea\r\n class=\"code\"\r\n matInput\r\n [formControl]=\"text\"\r\n rows=\"8\"\r\n spellcheck=\"false\"\r\n ></textarea>\r\n </mat-form-field>\r\n @if (parseError()) {\r\n <div class=\"error\">{{ parseError() }}</div>\r\n }\r\n </div>\r\n </div>\r\n <div id=\"batch-help\">\r\n <ul>\r\n <li>\r\n <strong>replace</strong>:\r\n <code>ATxRUN<strong>=</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>delete</strong>:\r\n <code>ATxRUN<strong>-</strong></code>\r\n </li>\r\n <li>\r\n <strong>add-before</strong>:\r\n <code>ATxRUN<strong>+[</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>add-after</strong>:\r\n <code>ATxRUN<strong>+]</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>move-before</strong>:\r\n <code>ATxRUN<strong>>[</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>move-after</strong>:\r\n <code>ATxRUN<strong>>]</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>swap</strong>:\r\n <code>ATxRUN<strong><></strong>TOxRUN</code>\r\n </li>\r\n <li>\r\n <strong>annotate</strong>:\r\n <code>ATxRUN<strong>:</strong></code>\r\n </li>\r\n </ul>\r\n <p>For all the operations:</p>\r\n <ul>\r\n <li>\r\n prefix <code>(ITAG:OTAG)</code> to define input and/or output tags,\r\n separated by colon.\r\n </li>\r\n <li>\r\n prepend <code>@</code> to AT to use character indexes (0-N)\r\n rather than IDs.\r\n </li>\r\n <li>RUN (where applicable) defaults to 1.</li>\r\n <li>\r\n append features like <code>[NAME OPERATOR VALUE]</code>, separated by\r\n space, where:\r\n </li>\r\n <li>\r\n <ol>\r\n <li>\r\n NAME is an arbitrary string. Prefixes:\r\n <code>*</code>=global features, <code>!</code>=remove feature (no\r\n value). Suffixes: <code>^</code>=short-lived (like\r\n <code>*version^=alpha</code>).\r\n </li>\r\n <li>\r\n OPERATOR is <code>=</code> (multiple), <code>:=</code> (single),\r\n <code>==</code> (first-single).\r\n </li>\r\n <li>\r\n VALUE is a string. If it includes spaces, wrap it in\r\n <code>\"\"</code>.\r\n </li>\r\n </ol>\r\n </li>\r\n </ul>\r\n </div>\r\n <div class=\"form-row-center\">\r\n @if (dialogRef) {\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Close dialog\"\r\n (click)=\"close()\"\r\n >\r\n close\r\n </button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Parse text into operations\"\r\n [disabled]=\"!text.value || busy()\"\r\n (click)=\"parseOperations(text.value!)\"\r\n >\r\n batch add\r\n </button>\r\n </div>\r\n </fieldset>\r\n</div>\r\n", styles: [".full-width{width:100%}.error{color:red}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}div#heading{margin:8px;text-align:center}div#batch-help strong{color:#ff8c00}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }] }); }
|
|
1096
1250
|
}
|
|
1097
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1251
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: BatchOperationEditorComponent, decorators: [{
|
|
1098
1252
|
type: Component,
|
|
1099
1253
|
args: [{ selector: 'gve-batch-operation-editor', imports: [
|
|
1100
1254
|
ReactiveFormsModule,
|
|
@@ -1102,8 +1256,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
1102
1256
|
MatFormFieldModule,
|
|
1103
1257
|
MatIconModule,
|
|
1104
1258
|
MatInputModule,
|
|
1105
|
-
], template: "<div [style.padding]=\"dialogRef ? '8px' : '0'\">\r\n @if (dialogRef) {\r\n <div id=\"heading\">\r\n <h2>Add Operations</h2>\r\n </div>\r\n }\r\n <fieldset>\r\n <div id=\"batch-input\">\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>operations</mat-label>\r\n <textarea\r\n class=\"code\"\r\n matInput\r\n [formControl]=\"text\"\r\n rows=\"8\"\r\n spellcheck=\"false\"\r\n ></textarea>\r\n </mat-form-field>\r\n @if (parseError) {\r\n <div class=\"error\">{{ parseError }}</div>\r\n }\r\n </div>\r\n </div>\r\n <div id=\"batch-help\">\r\n <ul>\r\n <li>\r\n <strong>replace</strong>:\r\n <code>ATxRUN<strong>=</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>delete</strong>:\r\n <code>ATxRUN<strong>-</strong></code>\r\n </li>\r\n <li>\r\n <strong>add-before</strong>:\r\n <code>ATxRUN<strong>+[</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>add-after</strong>:\r\n <code>ATxRUN<strong>+]</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>move-before</strong>:\r\n <code>ATxRUN<strong>>[</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>move-after</strong>:\r\n <code>ATxRUN<strong>>]</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>swap</strong>:\r\n <code>ATxRUN<strong><></strong>TOxRUN</code>\r\n </li>\r\n <li>\r\n <strong>annotate</strong>:\r\n <code>ATxRUN<strong>:</strong></code>\r\n </li>\r\n </ul>\r\n <p>For all the operations:</p>\r\n <ul>\r\n <li>\r\n prefix <code>(ITAG:OTAG)</code> to define input and/or output tags,\r\n separated by colon.\r\n </li>\r\n <li>\r\n prepend <code>@</code> to AT to use character indexes (0-N)\r\n rather than IDs.\r\n </li>\r\n <li>RUN (where applicable) defaults to 1.</li>\r\n <li>\r\n append features like <code>[NAME OPERATOR VALUE]</code>, separated by\r\n space, where:\r\n </li>\r\n <li>\r\n <ol>\r\n <li>\r\n NAME is an arbitrary string. Prefixes:\r\n <code>*</code>=global features, <code>!</code>=remove feature (no\r\n value). Suffixes: <code>^</code>=short-lived (like\r\n <code>*version^=alpha</code>).\r\n </li>\r\n <li>\r\n OPERATOR is <code>=</code> (multiple), <code>:=</code> (single),\r\n <code>==</code> (first-single).\r\n </li>\r\n <li>\r\n VALUE is a string. If it includes spaces, wrap it in\r\n <code>\"\"</code>.\r\n </li>\r\n </ol>\r\n </li>\r\n </ul>\r\n </div>\r\n <div class=\"form-row-center\">\r\n @if (dialogRef) {\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Close dialog\"\r\n (click)=\"close()\"\r\n >\r\n close\r\n </button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Parse text into operations\"\r\n [disabled]=\"!text.value || busy\"\r\n (click)=\"parseOperations(text.value!)\"\r\n >\r\n batch add\r\n </button>\r\n </div>\r\n </fieldset>\r\n</div>\r\n", styles: [".full-width{width:100%}.error{color:red}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}div#heading{margin:8px;text-align:center}div#batch-help strong{color:#ff8c00}\n"] }]
|
|
1106
|
-
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: GveApiService }, { type: i3$
|
|
1259
|
+
], template: "<div [style.padding]=\"dialogRef ? '8px' : '0'\">\r\n @if (dialogRef) {\r\n <div id=\"heading\">\r\n <h2>Add Operations</h2>\r\n </div>\r\n }\r\n <fieldset>\r\n <div id=\"batch-input\">\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>operations</mat-label>\r\n <textarea\r\n class=\"code\"\r\n matInput\r\n [formControl]=\"text\"\r\n rows=\"8\"\r\n spellcheck=\"false\"\r\n ></textarea>\r\n </mat-form-field>\r\n @if (parseError()) {\r\n <div class=\"error\">{{ parseError() }}</div>\r\n }\r\n </div>\r\n </div>\r\n <div id=\"batch-help\">\r\n <ul>\r\n <li>\r\n <strong>replace</strong>:\r\n <code>ATxRUN<strong>=</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>delete</strong>:\r\n <code>ATxRUN<strong>-</strong></code>\r\n </li>\r\n <li>\r\n <strong>add-before</strong>:\r\n <code>ATxRUN<strong>+[</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>add-after</strong>:\r\n <code>ATxRUN<strong>+]</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>move-before</strong>:\r\n <code>ATxRUN<strong>>[</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>move-after</strong>:\r\n <code>ATxRUN<strong>>]</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>swap</strong>:\r\n <code>ATxRUN<strong><></strong>TOxRUN</code>\r\n </li>\r\n <li>\r\n <strong>annotate</strong>:\r\n <code>ATxRUN<strong>:</strong></code>\r\n </li>\r\n </ul>\r\n <p>For all the operations:</p>\r\n <ul>\r\n <li>\r\n prefix <code>(ITAG:OTAG)</code> to define input and/or output tags,\r\n separated by colon.\r\n </li>\r\n <li>\r\n prepend <code>@</code> to AT to use character indexes (0-N)\r\n rather than IDs.\r\n </li>\r\n <li>RUN (where applicable) defaults to 1.</li>\r\n <li>\r\n append features like <code>[NAME OPERATOR VALUE]</code>, separated by\r\n space, where:\r\n </li>\r\n <li>\r\n <ol>\r\n <li>\r\n NAME is an arbitrary string. Prefixes:\r\n <code>*</code>=global features, <code>!</code>=remove feature (no\r\n value). Suffixes: <code>^</code>=short-lived (like\r\n <code>*version^=alpha</code>).\r\n </li>\r\n <li>\r\n OPERATOR is <code>=</code> (multiple), <code>:=</code> (single),\r\n <code>==</code> (first-single).\r\n </li>\r\n <li>\r\n VALUE is a string. If it includes spaces, wrap it in\r\n <code>\"\"</code>.\r\n </li>\r\n </ol>\r\n </li>\r\n </ul>\r\n </div>\r\n <div class=\"form-row-center\">\r\n @if (dialogRef) {\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Close dialog\"\r\n (click)=\"close()\"\r\n >\r\n close\r\n </button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Parse text into operations\"\r\n [disabled]=\"!text.value || busy()\"\r\n (click)=\"parseOperations(text.value!)\"\r\n >\r\n batch add\r\n </button>\r\n </div>\r\n </fieldset>\r\n</div>\r\n", styles: [".full-width{width:100%}.error{color:red}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}div#heading{margin:8px;text-align:center}div#batch-help strong{color:#ff8c00}\n"] }]
|
|
1260
|
+
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: GveApiService }, { type: i3$2.MatDialogRef, decorators: [{
|
|
1107
1261
|
type: Optional
|
|
1108
1262
|
}] }, { type: undefined, decorators: [{
|
|
1109
1263
|
type: Optional
|
|
@@ -1133,19 +1287,15 @@ class OperationSourceEditorComponent {
|
|
|
1133
1287
|
/**
|
|
1134
1288
|
* The source to edit.
|
|
1135
1289
|
*/
|
|
1136
|
-
this.source = model();
|
|
1290
|
+
this.source = model(...(ngDevMode ? [undefined, { debugName: "source" }] : []));
|
|
1137
1291
|
/**
|
|
1138
1292
|
* The list of source IDs when it's a closed set.
|
|
1139
1293
|
*/
|
|
1140
|
-
this.ids = input();
|
|
1294
|
+
this.ids = input(...(ngDevMode ? [undefined, { debugName: "ids" }] : []));
|
|
1141
1295
|
/**
|
|
1142
1296
|
* The list of source types when it's a closed set.
|
|
1143
1297
|
*/
|
|
1144
|
-
this.types = input();
|
|
1145
|
-
/**
|
|
1146
|
-
* The event emitted when the source changes.
|
|
1147
|
-
*/
|
|
1148
|
-
this.sourceChange = output();
|
|
1298
|
+
this.types = input(...(ngDevMode ? [undefined, { debugName: "types" }] : []));
|
|
1149
1299
|
/**
|
|
1150
1300
|
* The event emitted when the edit is canceled.
|
|
1151
1301
|
*/
|
|
@@ -1199,22 +1349,20 @@ class OperationSourceEditorComponent {
|
|
|
1199
1349
|
rank: this.rank.value,
|
|
1200
1350
|
note: this.note.value || undefined,
|
|
1201
1351
|
});
|
|
1202
|
-
this.sourceChange.emit(this.source());
|
|
1203
1352
|
}
|
|
1204
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1205
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1353
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: OperationSourceEditorComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1354
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: OperationSourceEditorComponent, isStandalone: true, selector: "gve-operation-source-editor", inputs: { source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: false, transformFunction: null }, ids: { classPropertyName: "ids", publicName: "ids", isSignal: true, isRequired: false, transformFunction: null }, types: { classPropertyName: "types", publicName: "types", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { source: "sourceChange", sourceCancel: "sourceCancel" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- id -->\r\n <!-- id (bound) -->\r\n @if (ids()?.length) {\r\n <mat-form-field>\r\n <mat-label>id</mat-label>\r\n <mat-select [formControl]=\"id\">\r\n @for (i of ids(); track i.id) {\r\n <mat-option [value]=\"i.id\">{{ i.label }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(id.errors)?.required && (id.dirty || id.touched)) {\r\n <mat-error>ID required</mat-error>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <!-- id (free) -->\r\n <mat-form-field>\r\n <mat-label>id</mat-label>\r\n <input matInput [formControl]=\"id\" />\r\n @if ($any(id.errors)?.required && (id.dirty || id.touched)) {\r\n <mat-error>ID required</mat-error>\r\n } @if ($any(id.errors)?.maxLength && (id.dirty || id.touched)) {\r\n <mat-error>id too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- type (bound) -->\r\n @if (types()?.length) {\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"type\">\r\n @for (i of types(); track i.id) {\r\n <mat-option [value]=\"i.id\">{{ i.label }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(type.errors)?.required && (type.dirty || type.touched)) {\r\n <mat-error>type required</mat-error>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <!-- type (free) -->\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <input matInput [formControl]=\"type\" />\r\n @if ($any(type.errors)?.required && (type.dirty || type.touched)) {\r\n <mat-error>type required</mat-error>\r\n } @if ($any(type.errors)?.maxLength && (type.dirty || type.touched)) {\r\n <mat-error>type too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- rank -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>rank</mat-label>\r\n <input matInput [formControl]=\"rank\" type=\"number\" min=\"0\" />\r\n </mat-form-field>\r\n </div>\r\n <!-- note -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>note</mat-label>\r\n <textarea matInput [formControl]=\"note\" class=\"long-text\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- buttons -->\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"cancel()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Accept changes\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".long-text{width:100%;max-width:800px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.nr{width:5em}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); }
|
|
1206
1355
|
}
|
|
1207
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1356
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: OperationSourceEditorComponent, decorators: [{
|
|
1208
1357
|
type: Component,
|
|
1209
1358
|
args: [{ selector: 'gve-operation-source-editor', imports: [
|
|
1210
|
-
CommonModule,
|
|
1211
1359
|
ReactiveFormsModule,
|
|
1212
1360
|
MatButtonModule,
|
|
1213
1361
|
MatFormFieldModule,
|
|
1214
1362
|
MatIconModule,
|
|
1215
1363
|
MatInputModule,
|
|
1216
1364
|
MatSelectModule,
|
|
1217
|
-
MatTooltipModule
|
|
1365
|
+
MatTooltipModule
|
|
1218
1366
|
], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <div class=\"form-row\">\r\n <!-- id -->\r\n <!-- id (bound) -->\r\n @if (ids()?.length) {\r\n <mat-form-field>\r\n <mat-label>id</mat-label>\r\n <mat-select [formControl]=\"id\">\r\n @for (i of ids(); track i.id) {\r\n <mat-option [value]=\"i.id\">{{ i.label }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(id.errors)?.required && (id.dirty || id.touched)) {\r\n <mat-error>ID required</mat-error>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <!-- id (free) -->\r\n <mat-form-field>\r\n <mat-label>id</mat-label>\r\n <input matInput [formControl]=\"id\" />\r\n @if ($any(id.errors)?.required && (id.dirty || id.touched)) {\r\n <mat-error>ID required</mat-error>\r\n } @if ($any(id.errors)?.maxLength && (id.dirty || id.touched)) {\r\n <mat-error>id too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- type (bound) -->\r\n @if (types()?.length) {\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"type\">\r\n @for (i of types(); track i.id) {\r\n <mat-option [value]=\"i.id\">{{ i.label }}</mat-option>\r\n }\r\n </mat-select>\r\n @if ($any(type.errors)?.required && (type.dirty || type.touched)) {\r\n <mat-error>type required</mat-error>\r\n }\r\n </mat-form-field>\r\n } @else {\r\n <!-- type (free) -->\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <input matInput [formControl]=\"type\" />\r\n @if ($any(type.errors)?.required && (type.dirty || type.touched)) {\r\n <mat-error>type required</mat-error>\r\n } @if ($any(type.errors)?.maxLength && (type.dirty || type.touched)) {\r\n <mat-error>type too long</mat-error>\r\n }\r\n </mat-form-field>\r\n }\r\n\r\n <!-- rank -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>rank</mat-label>\r\n <input matInput [formControl]=\"rank\" type=\"number\" min=\"0\" />\r\n </mat-form-field>\r\n </div>\r\n <!-- note -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>note</mat-label>\r\n <textarea matInput [formControl]=\"note\" class=\"long-text\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- buttons -->\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"cancel()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n <button\r\n type=\"submit\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Accept changes\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon class=\"mat-primary\">check_circle</mat-icon>\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".long-text{width:100%;max-width:800px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.nr{width:5em}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}\n"] }]
|
|
1219
1367
|
}], ctorParameters: () => [{ type: i1.FormBuilder }] });
|
|
1220
1368
|
|
|
@@ -1434,10 +1582,10 @@ class SettingsService {
|
|
|
1434
1582
|
// for when the cache was not in sync with the local storage
|
|
1435
1583
|
removedKeys.forEach((key) => this._subject.next(key));
|
|
1436
1584
|
}
|
|
1437
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1438
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1585
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SettingsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1586
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SettingsService, providedIn: 'root' }); }
|
|
1439
1587
|
}
|
|
1440
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1588
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SettingsService, decorators: [{
|
|
1441
1589
|
type: Injectable,
|
|
1442
1590
|
args: [{
|
|
1443
1591
|
providedIn: 'root',
|
|
@@ -1502,19 +1650,30 @@ class ChainOperationEditorComponent {
|
|
|
1502
1650
|
// monaco
|
|
1503
1651
|
this._disposables = [];
|
|
1504
1652
|
this._nanoid = customAlphabet('1234567890abcdef', 10);
|
|
1505
|
-
this._editedSourceIndex = -1;
|
|
1506
1653
|
/**
|
|
1507
1654
|
* The operation to edit.
|
|
1508
1655
|
*/
|
|
1509
|
-
this.operation = model();
|
|
1656
|
+
this.operation = model(...(ngDevMode ? [undefined, { debugName: "operation" }] : []));
|
|
1510
1657
|
/**
|
|
1511
1658
|
* The snapshot the operation refers to.
|
|
1512
1659
|
*/
|
|
1513
|
-
this.snapshot = input();
|
|
1660
|
+
this.snapshot = input(...(ngDevMode ? [undefined, { debugName: "snapshot" }] : []));
|
|
1514
1661
|
/**
|
|
1515
1662
|
* Whether to hide the preview request button.
|
|
1516
1663
|
*/
|
|
1517
|
-
this.hidePreview = input();
|
|
1664
|
+
this.hidePreview = input(...(ngDevMode ? [undefined, { debugName: "hidePreview" }] : []));
|
|
1665
|
+
/**
|
|
1666
|
+
* Definitions for features, including names and values.
|
|
1667
|
+
*/
|
|
1668
|
+
this.featureDefs = input(...(ngDevMode ? [undefined, { debugName: "featureDefs" }] : []));
|
|
1669
|
+
/**
|
|
1670
|
+
* Definitions for element features, including names and values.
|
|
1671
|
+
*/
|
|
1672
|
+
this.elementFeatureDefs = input(...(ngDevMode ? [undefined, { debugName: "elementFeatureDefs" }] : []));
|
|
1673
|
+
/**
|
|
1674
|
+
* Definitions for diplomatic features, including names and values.
|
|
1675
|
+
*/
|
|
1676
|
+
this.diplomaticFeatureDefs = input(...(ngDevMode ? [undefined, { debugName: "diplomaticFeatureDefs" }] : []));
|
|
1518
1677
|
/**
|
|
1519
1678
|
* Emitted when the operation is changed.
|
|
1520
1679
|
*/
|
|
@@ -1527,10 +1686,18 @@ class ChainOperationEditorComponent {
|
|
|
1527
1686
|
* Emitted when operation editing is cancelled.
|
|
1528
1687
|
*/
|
|
1529
1688
|
this.operationCancel = output();
|
|
1530
|
-
this.tabIndex = 0;
|
|
1531
|
-
this.
|
|
1532
|
-
this.
|
|
1533
|
-
this.
|
|
1689
|
+
this.tabIndex = signal(0, ...(ngDevMode ? [{ debugName: "tabIndex" }] : []));
|
|
1690
|
+
this.id = signal(undefined, ...(ngDevMode ? [{ debugName: "id" }] : []));
|
|
1691
|
+
this.hasTo = signal(false, ...(ngDevMode ? [{ debugName: "hasTo" }] : []));
|
|
1692
|
+
this.hasToRun = signal(false, ...(ngDevMode ? [{ debugName: "hasToRun" }] : []));
|
|
1693
|
+
this.hasValue = signal(false, ...(ngDevMode ? [{ debugName: "hasValue" }] : []));
|
|
1694
|
+
// elements parsed from SVG and having an id attribute;
|
|
1695
|
+
// we can attach features to each of these elements
|
|
1696
|
+
this.elements = signal([], ...(ngDevMode ? [{ debugName: "elements" }] : []));
|
|
1697
|
+
this.editedElementId = signal(undefined, ...(ngDevMode ? [{ debugName: "editedElementId" }] : []));
|
|
1698
|
+
// source
|
|
1699
|
+
this.editedSource = signal(undefined, ...(ngDevMode ? [{ debugName: "editedSource" }] : []));
|
|
1700
|
+
this.editedSourceIndex = signal(-1, ...(ngDevMode ? [{ debugName: "editedSourceIndex" }] : []));
|
|
1534
1701
|
this._subs = [];
|
|
1535
1702
|
// general
|
|
1536
1703
|
this.rank = formBuilder.control(0, { nonNullable: true });
|
|
@@ -1588,8 +1755,6 @@ class ChainOperationEditorComponent {
|
|
|
1588
1755
|
newTextHidden: this.newTextHidden,
|
|
1589
1756
|
dpFeatures: this.dpFeatures,
|
|
1590
1757
|
});
|
|
1591
|
-
// SVG elements
|
|
1592
|
-
this.elements = [];
|
|
1593
1758
|
// when operation changes, update form
|
|
1594
1759
|
effect(() => {
|
|
1595
1760
|
this.updateForm(this.operation());
|
|
@@ -1679,24 +1844,24 @@ class ChainOperationEditorComponent {
|
|
|
1679
1844
|
}
|
|
1680
1845
|
// #region sources
|
|
1681
1846
|
addSource() {
|
|
1682
|
-
this.editedSource
|
|
1683
|
-
this.
|
|
1847
|
+
this.editedSource.set({ id: '', type: '' });
|
|
1848
|
+
this.editedSourceIndex.set(-1);
|
|
1684
1849
|
}
|
|
1685
1850
|
editSource(index) {
|
|
1686
|
-
this.
|
|
1687
|
-
this.editedSource
|
|
1851
|
+
this.editedSourceIndex.set(index);
|
|
1852
|
+
this.editedSource.set(deepCopy(this.sources.value[index]));
|
|
1688
1853
|
}
|
|
1689
1854
|
closeSource() {
|
|
1690
|
-
this.
|
|
1691
|
-
this.editedSource
|
|
1855
|
+
this.editedSourceIndex.set(-1);
|
|
1856
|
+
this.editedSource.set(undefined);
|
|
1692
1857
|
}
|
|
1693
1858
|
onSourceChange(source) {
|
|
1694
1859
|
const sources = [...this.sources.value];
|
|
1695
|
-
if (this.
|
|
1860
|
+
if (this.editedSourceIndex() === -1) {
|
|
1696
1861
|
sources.push(source);
|
|
1697
1862
|
}
|
|
1698
1863
|
else {
|
|
1699
|
-
sources[this.
|
|
1864
|
+
sources[this.editedSourceIndex()] = source;
|
|
1700
1865
|
}
|
|
1701
1866
|
this.sources.setValue(sources);
|
|
1702
1867
|
this.closeSource();
|
|
@@ -1791,9 +1956,9 @@ class ChainOperationEditorComponent {
|
|
|
1791
1956
|
// #endregion
|
|
1792
1957
|
// #region element features
|
|
1793
1958
|
onTabIndexChange(index) {
|
|
1794
|
-
this.tabIndex
|
|
1959
|
+
this.tabIndex.set(index);
|
|
1795
1960
|
if (index === 3) {
|
|
1796
|
-
this.elements
|
|
1961
|
+
this.elements.set(this.parseSvg(this.svg.value));
|
|
1797
1962
|
}
|
|
1798
1963
|
}
|
|
1799
1964
|
editElementFeatures(element) {
|
|
@@ -1803,7 +1968,7 @@ class ChainOperationEditorComponent {
|
|
|
1803
1968
|
...this.elementFeatures.value,
|
|
1804
1969
|
[id]: features,
|
|
1805
1970
|
});
|
|
1806
|
-
this.editedElementId
|
|
1971
|
+
this.editedElementId.set(id);
|
|
1807
1972
|
}
|
|
1808
1973
|
deleteElementFeatures(element) {
|
|
1809
1974
|
const id = element.id;
|
|
@@ -1817,19 +1982,19 @@ class ChainOperationEditorComponent {
|
|
|
1817
1982
|
if (yes) {
|
|
1818
1983
|
delete elementFeatures[id];
|
|
1819
1984
|
this.elementFeatures.setValue(elementFeatures);
|
|
1820
|
-
if (this.editedElementId === id) {
|
|
1821
|
-
this.editedElementId
|
|
1985
|
+
if (this.editedElementId() === id) {
|
|
1986
|
+
this.editedElementId.set(undefined);
|
|
1822
1987
|
}
|
|
1823
1988
|
}
|
|
1824
1989
|
});
|
|
1825
1990
|
}
|
|
1826
1991
|
onElementFeaturesChange(features) {
|
|
1827
|
-
if (this.editedElementId) {
|
|
1992
|
+
if (this.editedElementId()) {
|
|
1828
1993
|
this.elementFeatures.setValue({
|
|
1829
1994
|
...this.elementFeatures.value,
|
|
1830
|
-
[this.editedElementId]: features,
|
|
1995
|
+
[this.editedElementId()]: features,
|
|
1831
1996
|
});
|
|
1832
|
-
this.editedElementId
|
|
1997
|
+
this.editedElementId.set(undefined);
|
|
1833
1998
|
}
|
|
1834
1999
|
}
|
|
1835
2000
|
// #endregion
|
|
@@ -1850,9 +2015,9 @@ class ChainOperationEditorComponent {
|
|
|
1850
2015
|
value = true;
|
|
1851
2016
|
break;
|
|
1852
2017
|
}
|
|
1853
|
-
this.hasTo
|
|
1854
|
-
this.hasToRun
|
|
1855
|
-
this.hasValue
|
|
2018
|
+
this.hasTo.set(to);
|
|
2019
|
+
this.hasToRun.set(toRun);
|
|
2020
|
+
this.hasValue.set(value);
|
|
1856
2021
|
if (!to) {
|
|
1857
2022
|
this.to.reset();
|
|
1858
2023
|
}
|
|
@@ -1871,10 +2036,10 @@ class ChainOperationEditorComponent {
|
|
|
1871
2036
|
}
|
|
1872
2037
|
// get or generate ID
|
|
1873
2038
|
if (operation.id) {
|
|
1874
|
-
this.id
|
|
2039
|
+
this.id.set(operation.id);
|
|
1875
2040
|
}
|
|
1876
2041
|
else {
|
|
1877
|
-
this.id
|
|
2042
|
+
this.id.set(this._nanoid());
|
|
1878
2043
|
}
|
|
1879
2044
|
this.rank.setValue(operation.rank || 0);
|
|
1880
2045
|
this.groupId.setValue(operation.groupId || null);
|
|
@@ -1896,7 +2061,7 @@ class ChainOperationEditorComponent {
|
|
|
1896
2061
|
this._editorModel?.setValue(this.svg.value || '');
|
|
1897
2062
|
this.elementFeatures.setValue(operation.diplomatics?.elementFeatures || {});
|
|
1898
2063
|
this.form.markAsPristine();
|
|
1899
|
-
this.elements
|
|
2064
|
+
this.elements.set(this.parseSvg(operation.diplomatics?.g));
|
|
1900
2065
|
this.updateArgsUI();
|
|
1901
2066
|
}
|
|
1902
2067
|
cancel() {
|
|
@@ -1914,7 +2079,7 @@ class ChainOperationEditorComponent {
|
|
|
1914
2079
|
features: this.dpFeatures.value,
|
|
1915
2080
|
elementFeatures: this.elementFeatures.value,
|
|
1916
2081
|
},
|
|
1917
|
-
id: this.id,
|
|
2082
|
+
id: this.id(),
|
|
1918
2083
|
type: this.type.value,
|
|
1919
2084
|
at: this.at.value,
|
|
1920
2085
|
atAsIndex: this.atAsIndex.value || undefined,
|
|
@@ -1937,21 +2102,13 @@ class ChainOperationEditorComponent {
|
|
|
1937
2102
|
this.operation.set(this.getOperation());
|
|
1938
2103
|
this.operationChange.emit(this.operation());
|
|
1939
2104
|
}
|
|
1940
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1941
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: ChainOperationEditorComponent, isStandalone: true, selector: "gve-chain-operation-editor", inputs: { operation: { classPropertyName: "operation", publicName: "operation", isSignal: true, isRequired: false, transformFunction: null }, snapshot: { classPropertyName: "snapshot", publicName: "snapshot", isSignal: true, isRequired: false, transformFunction: null }, hidePreview: { classPropertyName: "hidePreview", publicName: "hidePreview", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { operation: "operationChange", operationChange: "operationChange", operationPreview: "operationPreview", operationCancel: "operationCancel" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <!-- tabs -->\r\n <mat-tab-group\r\n [selectedIndex]=\"tabIndex\"\r\n (selectedIndexChange)=\"onTabIndexChange($event)\"\r\n >\r\n <!-- GENERAL -->\r\n <mat-tab label=\"general\">\r\n <div class=\"form-row\">\r\n <!-- id -->\r\n <div id=\"id\" class=\"muted\">{{ id }}</div>\r\n\r\n <!-- type -->\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"type\">\r\n <mat-option [value]=\"0\"\r\n ><mat-icon>layers</mat-icon> replace</mat-option\r\n >\r\n <mat-option [value]=\"1\"\r\n ><mat-icon>close</mat-icon>delete</mat-option\r\n >\r\n <mat-option [value]=\"2\"\r\n ><mat-icon>last_page</mat-icon>add-before</mat-option\r\n >\r\n <mat-option [value]=\"3\"\r\n ><mat-icon>first_page</mat-icon>add-after</mat-option\r\n >\r\n <mat-option [value]=\"4\"\r\n ><mat-icon>login</mat-icon>move-before</mat-option\r\n >\r\n <mat-option [value]=\"5\"\r\n ><mat-icon>logout</mat-icon>move-after</mat-option\r\n >\r\n <mat-option [value]=\"6\"\r\n ><mat-icon>compare_arrows</mat-icon>swap</mat-option\r\n >\r\n <mat-option [value]=\"7\"\r\n ><mat-icon>edit_note</mat-icon>annotate</mat-option\r\n >\r\n </mat-select>\r\n <mat-error\r\n *ngIf=\"$any(type).errors?.required && (type.dirty || type.touched)\"\r\n >type required</mat-error\r\n >\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- at -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>at</mat-label>\r\n <input matInput [formControl]=\"at\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(at).errors?.required && (at.dirty || at.touched)\"\r\n >at required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- atAsIndex -->\r\n <mat-checkbox [formControl]=\"atAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- run -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>run</mat-label>\r\n <input matInput [formControl]=\"run\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(run).errors?.required && (run.dirty || run.touched)\"\r\n >run required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- to -->\r\n @if (hasTo) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to</mat-label>\r\n <input matInput [formControl]=\"to\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(to).errors?.required && (to.dirty || to.touched)\"\r\n >to required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- toAsIndex -->\r\n <mat-checkbox [formControl]=\"toAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- toRun -->\r\n @if (hasToRun) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to run</mat-label>\r\n <input matInput [formControl]=\"toRun\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"\r\n $any(toRun).errors?.required && (toRun.dirty || toRun.touched)\r\n \"\r\n >to run required</mat-error\r\n >\r\n </mat-form-field>\r\n } }\r\n\r\n <!-- value -->\r\n @if (hasValue) {\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n </mat-form-field>\r\n }\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- rank -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>rank</mat-label>\r\n <input matInput [formControl]=\"rank\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(rank).errors?.required && (rank.dirty || rank.touched)\"\r\n >rank required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- groupId -->\r\n <mat-form-field>\r\n <mat-label>group ID</mat-label>\r\n <input matInput [formControl]=\"groupId\" />\r\n <mat-error\r\n *ngIf=\"\r\n $any(groupId).errors?.required &&\r\n (groupId.dirty || groupId.touched)\r\n \"\r\n >group ID required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- inputTag -->\r\n <mat-form-field>\r\n <mat-label>input tag</mat-label>\r\n <input matInput [formControl]=\"inputTag\" />\r\n <mat-hint>blank=latest</mat-hint>\r\n </mat-form-field>\r\n\r\n <!-- outputTag -->\r\n <mat-form-field>\r\n <mat-label>output tag</mat-label>\r\n <input matInput [formControl]=\"outputTag\" />\r\n <mat-hint>blank=auto (vN)</mat-hint>\r\n </mat-form-field>\r\n </div>\r\n <div>\r\n <!-- features -->\r\n <fieldset>\r\n <legend>operation features</legend>\r\n <gve-feature-set-editor\r\n [isVar]=\"true\"\r\n [features]=\"features.value\"\r\n (featuresChange)=\"onFeaturesChange($event)\"\r\n ></gve-feature-set-editor>\r\n </fieldset>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- SOURCES -->\r\n <mat-tab label=\"sources\">\r\n <div>\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n (click)=\"addSource()\"\r\n >\r\n <mat-icon>add_circle</mat-icon>\r\n source\r\n </button>\r\n </div>\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>type</th>\r\n <th>id</th>\r\n <th>rank</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (s of sources.value; track s) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n (click)=\"editSource($index)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button type=\"button\" mat-icon-button color=\"warn\">\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ s.type }}</td>\r\n <td>{{ s.id }}</td>\r\n <td>{{ s.rank }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n <!-- source editor -->\r\n <mat-expansion-panel [disabled]=\"!editedSource\" [expanded]=\"editedSource\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>source</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-operation-source-editor\r\n [source]=\"editedSource\"\r\n (sourceChange)=\"onSourceChange($event!)\"\r\n (sourceCancel)=\"closeSource()\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- DIPLOMATIC -->\r\n <mat-tab label=\"diplomatic\">\r\n <div class=\"toolbar-row\">\r\n <button\r\n id=\"btn-save\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Save to file\"\r\n [disabled]=\"!svg.value\"\r\n (click)=\"saveSvg()\"\r\n >\r\n <mat-icon>save</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-load\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Load from file\"\r\n (click)=\"loadSvg()\"\r\n >\r\n <mat-icon>folder</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-copy\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Copy\"\r\n [cdkCopyToClipboard]=\"svg.value\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-paste\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Set SVG from clipboard\"\r\n (click)=\"setSvgFromClipboard()\"\r\n >\r\n <mat-icon>content_paste_go</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-editor\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Open SVG external editor\"\r\n (click)=\"openSvgEditor()\"\r\n >\r\n <mat-icon>launch</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-decimals\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Remove decimals\"\r\n [disabled]=\"!svg.value\"\r\n (click)=\"removeDecimals()\"\r\n >\r\n <mat-icon>pin</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-group\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Wrap code in group\"\r\n (click)=\"wrapInGroup()\"\r\n >\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div id=\"code\">\r\n <nge-monaco-editor\r\n style=\"--editor-height: 400px\"\r\n (ready)=\"onCreateEditor($event)\"\r\n />\r\n @if (svg.invalid) {\r\n <mat-error>invalid SVG</mat-error>\r\n }\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- ELEMENTS -->\r\n <mat-tab label=\"elements\">\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>id</th>\r\n <th>visual</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (e of elements; track e.id) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Edit element features\"\r\n (click)=\"editElementFeatures(e)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n matTooltip=\"Delete all element features\"\r\n (click)=\"deleteElementFeatures(e)\"\r\n [disabled]=\"!$any(elementFeatures.value)[e.id]?.length\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n <span\r\n [matBadge]=\"$any(elementFeatures.value)[e.id]?.length || 0\"\r\n [matBadgeHidden]=\"!$any(elementFeatures.value)[e.id]?.length\"\r\n matBadgeOverlap=\"false\"\r\n >{{ e.id }}</span\r\n >\r\n </td>\r\n <td class=\"svg-cell\">\r\n <svg [innerHTML]=\"e.outerHTML | safeHtml : 'html'\"></svg>\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n\r\n <mat-expansion-panel\r\n [disabled]=\"!editedElementId\"\r\n [expanded]=\"editedElementId\"\r\n >\r\n <mat-expansion-panel-header>{{\r\n editedElementId\r\n }}</mat-expansion-panel-header>\r\n <gve-feature-set-editor\r\n [features]=\"elementFeatures.value[editedElementId!] || []\"\r\n (featuresChange)=\"onElementFeaturesChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- DP FEATS -->\r\n <mat-tab label=\"d-features\">\r\n <div>\r\n <mat-checkbox [formControl]=\"newTextHidden\">hide new text</mat-checkbox>\r\n </div>\r\n <gve-feature-set-editor\r\n [features]=\"dpFeatures.value\"\r\n (featuresChange)=\"onDpFeaturesChange($event)\"\r\n ></gve-feature-set-editor>\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- buttons -->\r\n <div id=\"submit-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Discard operation\"\r\n (click)=\"cancel()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n @if (!hidePreview()) {\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Preview operation\"\r\n (click)=\"requestPreview()\"\r\n >\r\n <mat-icon class=\"mat-primary\">preview</mat-icon>\r\n </button>\r\n }\r\n <button\r\n type=\"submit\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save operation\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}#submit-row{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap;margin-top:8px;border-top:1px solid silver}.toolbar-row{display:flex;align-items:center;flex-wrap:wrap}.nr{width:5em}.long-text{width:100%;max-width:800px}#id{border-radius:6px;padding:4px;background-color:#beb9b9;color:#fff;margin-top:-16px}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:silver}table{width:100%;border-collapse:collapse;margin:8px 0}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr{border-bottom:1px solid silver}th,td{text-align:center}#btn-save{color:#072d3e}#btn-load{color:#dbd112}#btn-copy{color:#22549f}#btn-preview{color:#095409}#code{height:500px;border:1px solid silver}#monaco{height:100%}.svg-cell{padding:0 8px}.svg-cell svg{border:1px solid silver;width:100%;height:auto}#preview{box-sizing:border-box;width:100%;border:1px solid silver;border-radius:4px;padding:8px}.tree-invisible{display:none}.tree ul,.tree li{margin-top:0;margin-bottom:0;list-style-type:none}.selected-node{background-color:#e5e5e5}.child-title{font-weight:700;margin:0;background-color:#ccc;color:#fff;padding:8px}#tree-container{display:grid;grid-template-rows:auto;grid-template-columns:auto 1fr;grid-template-areas:\"nav ed\";gap:0 16px;align-items:stretch}#tree-nav{grid-area:nav;border:1px solid silver;border-radius:6px;margin:8px 0;padding-right:8px}#tree-ed{grid-area:ed;border:1px solid silver;border-radius:6px;margin:8px 0}@media only screen and (max-width: 959px){div#container{grid-template-columns:1fr;grid-template-areas:\"nav\" \"ed\";gap:16px 0;align-items:start}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type:
|
|
1942
|
-
// material
|
|
1943
|
-
ClipboardModule }, { kind: "directive", type: i2$3.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i6$1.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i5.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i8.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i16.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i16.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type:
|
|
1944
|
-
// monaco
|
|
1945
|
-
NgeMonacoModule }, { kind: "component", type: i17.NgeMonacoEditorComponent, selector: "nge-monaco-editor", inputs: ["autoLayout", "options"], outputs: ["ready"] }, { kind: "pipe", type:
|
|
1946
|
-
// myrmex
|
|
1947
|
-
SafeHtmlPipe, name: "safeHtml" }, { kind: "component", type: FeatureSetEditorComponent, selector: "gve-feature-set-editor", inputs: ["isVar", "featNames", "featValues", "filterThreshold", "features"], outputs: ["featuresChange"] }, { kind: "component", type: OperationSourceEditorComponent, selector: "gve-operation-source-editor", inputs: ["source", "ids", "types"], outputs: ["sourceChange", "sourceCancel"] }] }); }
|
|
2105
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ChainOperationEditorComponent, deps: [{ token: i1.FormBuilder }, { token: i2$2.Clipboard }, { token: SettingsService }, { token: i4$2.DialogService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2106
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: ChainOperationEditorComponent, isStandalone: true, selector: "gve-chain-operation-editor", inputs: { operation: { classPropertyName: "operation", publicName: "operation", isSignal: true, isRequired: false, transformFunction: null }, snapshot: { classPropertyName: "snapshot", publicName: "snapshot", isSignal: true, isRequired: false, transformFunction: null }, hidePreview: { classPropertyName: "hidePreview", publicName: "hidePreview", isSignal: true, isRequired: false, transformFunction: null }, featureDefs: { classPropertyName: "featureDefs", publicName: "featureDefs", isSignal: true, isRequired: false, transformFunction: null }, elementFeatureDefs: { classPropertyName: "elementFeatureDefs", publicName: "elementFeatureDefs", isSignal: true, isRequired: false, transformFunction: null }, diplomaticFeatureDefs: { classPropertyName: "diplomaticFeatureDefs", publicName: "diplomaticFeatureDefs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { operation: "operationChange", operationChange: "operationChange", operationPreview: "operationPreview", operationCancel: "operationCancel" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <!-- tabs -->\r\n <mat-tab-group\r\n [selectedIndex]=\"tabIndex()\"\r\n (selectedIndexChange)=\"onTabIndexChange($event)\"\r\n >\r\n <!-- GENERAL -->\r\n <mat-tab label=\"general\">\r\n <div class=\"form-row\">\r\n <!-- id -->\r\n <div id=\"id\" class=\"muted\">{{ id() }}</div>\r\n\r\n <!-- type -->\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"type\">\r\n <mat-option [value]=\"0\"\r\n ><mat-icon>layers</mat-icon> replace</mat-option\r\n >\r\n <mat-option [value]=\"1\"\r\n ><mat-icon>close</mat-icon>delete</mat-option\r\n >\r\n <mat-option [value]=\"2\"\r\n ><mat-icon>last_page</mat-icon>add-before</mat-option\r\n >\r\n <mat-option [value]=\"3\"\r\n ><mat-icon>first_page</mat-icon>add-after</mat-option\r\n >\r\n <mat-option [value]=\"4\"\r\n ><mat-icon>login</mat-icon>move-before</mat-option\r\n >\r\n <mat-option [value]=\"5\"\r\n ><mat-icon>logout</mat-icon>move-after</mat-option\r\n >\r\n <mat-option [value]=\"6\"\r\n ><mat-icon>compare_arrows</mat-icon>swap</mat-option\r\n >\r\n <mat-option [value]=\"7\"\r\n ><mat-icon>edit_note</mat-icon>annotate</mat-option\r\n >\r\n </mat-select>\r\n @if ($any(type).errors?.required && (type.dirty || type.touched)) {\r\n <mat-error>type required</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- at -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>at</mat-label>\r\n <input matInput [formControl]=\"at\" type=\"number\" min=\"0\" />\r\n @if ($any(at).errors?.required && (at.dirty || at.touched)) {\r\n <mat-error>at required</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- atAsIndex -->\r\n <mat-checkbox [formControl]=\"atAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- run -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>run</mat-label>\r\n <input matInput [formControl]=\"run\" type=\"number\" min=\"0\" />\r\n @if ($any(run).errors?.required && (run.dirty || run.touched)) {\r\n <mat-error>run required</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- to -->\r\n @if (hasTo()) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to</mat-label>\r\n <input matInput [formControl]=\"to\" type=\"number\" min=\"0\" />\r\n @if ($any(to).errors?.required && (to.dirty || to.touched)) {\r\n <mat-error>to required</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- toAsIndex -->\r\n <mat-checkbox [formControl]=\"toAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- toRun -->\r\n @if (hasToRun()) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to run</mat-label>\r\n <input matInput [formControl]=\"toRun\" type=\"number\" min=\"0\" />\r\n @if ( $any(toRun).errors?.required && (toRun.dirty || toRun.touched) )\r\n {\r\n <mat-error>to run required</mat-error>\r\n }\r\n </mat-form-field>\r\n } }\r\n\r\n <!-- value -->\r\n @if (hasValue()) {\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n </mat-form-field>\r\n }\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- rank -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>rank</mat-label>\r\n <input matInput [formControl]=\"rank\" type=\"number\" min=\"0\" />\r\n @if ($any(rank).errors?.required && (rank.dirty || rank.touched)) {\r\n <mat-error>rank required</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- groupId -->\r\n <mat-form-field>\r\n <mat-label>group ID</mat-label>\r\n <input matInput [formControl]=\"groupId\" />\r\n @if ( $any(groupId).errors?.required && (groupId.dirty ||\r\n groupId.touched) ) {\r\n <mat-error>group ID required</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- inputTag -->\r\n <mat-form-field>\r\n <mat-label>input tag</mat-label>\r\n <input matInput [formControl]=\"inputTag\" />\r\n <mat-hint>blank=latest</mat-hint>\r\n </mat-form-field>\r\n\r\n <!-- outputTag -->\r\n <mat-form-field>\r\n <mat-label>output tag</mat-label>\r\n <input matInput [formControl]=\"outputTag\" />\r\n <mat-hint>blank=auto (vN)</mat-hint>\r\n </mat-form-field>\r\n </div>\r\n <div>\r\n <!-- features -->\r\n <fieldset>\r\n <legend>operation features</legend>\r\n <gve-feature-set-editor\r\n [isVar]=\"true\"\r\n [featNames]=\"featureDefs()?.names\"\r\n [featValues]=\"featureDefs()?.values\"\r\n [features]=\"features.value\"\r\n (featuresChange)=\"onFeaturesChange($event)\"\r\n />\r\n </fieldset>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- SOURCES -->\r\n <mat-tab label=\"sources\">\r\n <div>\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n (click)=\"addSource()\"\r\n >\r\n <mat-icon>add_circle</mat-icon>\r\n source\r\n </button>\r\n </div>\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>type</th>\r\n <th>id</th>\r\n <th>rank</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (s of sources.value; track s) {\r\n <tr [class.selected]=\"s === editedSource()\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n (click)=\"editSource($index)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button type=\"button\" mat-icon-button color=\"warn\">\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ s.type }}</td>\r\n <td>{{ s.id }}</td>\r\n <td>{{ s.rank }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (editedSource()) {\r\n <!-- source editor -->\r\n <mat-expansion-panel\r\n [disabled]=\"!editedSource()\"\r\n [expanded]=\"editedSource()\"\r\n >\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>source</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-operation-source-editor\r\n [source]=\"editedSource()\"\r\n (sourceChange)=\"onSourceChange($event!)\"\r\n (sourceCancel)=\"closeSource()\"\r\n />\r\n </mat-expansion-panel>\r\n }\r\n </mat-tab>\r\n\r\n <!-- DIPLOMATIC -->\r\n <mat-tab label=\"diplomatic\">\r\n <div class=\"toolbar-row\">\r\n <button\r\n id=\"btn-save\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Save to file\"\r\n [disabled]=\"!svg.value\"\r\n (click)=\"saveSvg()\"\r\n >\r\n <mat-icon>save</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-load\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Load from file\"\r\n (click)=\"loadSvg()\"\r\n >\r\n <mat-icon>folder</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-copy\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Copy\"\r\n [cdkCopyToClipboard]=\"svg.value\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-paste\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Set SVG from clipboard\"\r\n (click)=\"setSvgFromClipboard()\"\r\n >\r\n <mat-icon>content_paste_go</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-editor\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Open SVG external editor\"\r\n (click)=\"openSvgEditor()\"\r\n >\r\n <mat-icon>launch</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-decimals\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Remove decimals\"\r\n [disabled]=\"!svg.value\"\r\n (click)=\"removeDecimals()\"\r\n >\r\n <mat-icon>pin</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-group\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Wrap code in group\"\r\n (click)=\"wrapInGroup()\"\r\n >\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div id=\"code\">\r\n <nge-monaco-editor\r\n style=\"--editor-height: 400px\"\r\n (ready)=\"onCreateEditor($event)\"\r\n />\r\n @if (svg.invalid) {\r\n <mat-error>invalid SVG</mat-error>\r\n }\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- ELEMENTS -->\r\n <mat-tab label=\"elements\">\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>id</th>\r\n <th>visual</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (e of elements(); track e.id) {\r\n <tr [class.selected]=\"e.id === editedElementId()\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Edit element features\"\r\n (click)=\"editElementFeatures(e)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n matTooltip=\"Delete all element features\"\r\n (click)=\"deleteElementFeatures(e)\"\r\n [disabled]=\"!$any(elementFeatures.value)[e.id]?.length\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n <span\r\n [matBadge]=\"$any(elementFeatures.value)[e.id]?.length || 0\"\r\n [matBadgeHidden]=\"!$any(elementFeatures.value)[e.id]?.length\"\r\n matBadgeOverlap=\"false\"\r\n >{{ e.id }}</span\r\n >\r\n </td>\r\n <td class=\"svg-cell\">\r\n <svg [innerHTML]=\"e.outerHTML | safeHtml : 'html'\"></svg>\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (editedElementId()) {\r\n <mat-expansion-panel\r\n [disabled]=\"!editedElementId()\"\r\n [expanded]=\"editedElementId()\"\r\n >\r\n <mat-expansion-panel-header>{{\r\n editedElementId()\r\n }}</mat-expansion-panel-header>\r\n <gve-feature-set-editor\r\n [featNames]=\"elementFeatureDefs()?.names\"\r\n [featValues]=\"elementFeatureDefs()?.values\"\r\n [features]=\"elementFeatures.value[editedElementId()!] || []\"\r\n (featuresChange)=\"onElementFeaturesChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n }\r\n </mat-tab>\r\n\r\n <!-- DP FEATS -->\r\n <mat-tab label=\"d-features\">\r\n <div>\r\n <mat-checkbox [formControl]=\"newTextHidden\">hide new text</mat-checkbox>\r\n </div>\r\n <gve-feature-set-editor\r\n [featNames]=\"diplomaticFeatureDefs()?.names\"\r\n [featValues]=\"diplomaticFeatureDefs()?.values\"\r\n [features]=\"dpFeatures.value\"\r\n (featuresChange)=\"onDpFeaturesChange($event)\"\r\n />\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- buttons -->\r\n <div id=\"submit-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Discard operation\"\r\n (click)=\"cancel()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n @if (!hidePreview()) {\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Preview operation\"\r\n (click)=\"requestPreview()\"\r\n >\r\n <mat-icon class=\"mat-primary\">preview</mat-icon>\r\n </button>\r\n }\r\n <button\r\n type=\"submit\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save operation\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}#submit-row{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap;margin-top:8px;border-top:1px solid silver}.toolbar-row{display:flex;align-items:center;flex-wrap:wrap}.nr{width:5em}.long-text{width:100%;max-width:800px}#id{border-radius:6px;padding:4px;background-color:#beb9b9;color:#fff;margin-top:-16px}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:silver}table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}#btn-save{color:#072d3e}#btn-load{color:#dbd112}#btn-copy{color:#22549f}#btn-preview{color:#095409}#code{height:500px;border:1px solid silver}#monaco{height:100%}.svg-cell{padding:0 8px}.svg-cell svg{border:1px solid silver;width:100%;height:auto}#preview{box-sizing:border-box;width:100%;border:1px solid silver;border-radius:4px;padding:8px}.tree-invisible{display:none}.tree ul,.tree li{margin-top:0;margin-bottom:0;list-style-type:none}.selected-node{background-color:#e5e5e5}.child-title{font-weight:700;margin:0;background-color:#ccc;color:#fff;padding:8px}#tree-container{display:grid;grid-template-rows:auto;grid-template-columns:auto 1fr;grid-template-areas:\"nav ed\";gap:0 16px;align-items:stretch}#tree-nav{grid-area:nav;border:1px solid silver;border-radius:6px;margin:8px 0;padding-right:8px}#tree-ed{grid-area:ed;border:1px solid silver;border-radius:6px;margin:8px 0}@media only screen and (max-width: 959px){div#container{grid-template-columns:1fr;grid-template-areas:\"nav\" \"ed\";gap:16px 0;align-items:start}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ClipboardModule }, { kind: "directive", type: i2$2.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i5$1.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i3$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i15.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i15.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: NgeMonacoModule }, { kind: "component", type: i15$1.NgeMonacoEditorComponent, selector: "nge-monaco-editor", inputs: ["autoLayout", "options"], outputs: ["ready"] }, { kind: "component", type: FeatureSetEditorComponent, selector: "gve-feature-set-editor", inputs: ["isVar", "featNames", "featValues", "filterThreshold", "features"], outputs: ["featuresChange"] }, { kind: "component", type: OperationSourceEditorComponent, selector: "gve-operation-source-editor", inputs: ["source", "ids", "types"], outputs: ["sourceChange", "sourceCancel"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] }); }
|
|
1948
2107
|
}
|
|
1949
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2108
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ChainOperationEditorComponent, decorators: [{
|
|
1950
2109
|
type: Component,
|
|
1951
2110
|
args: [{ selector: 'gve-chain-operation-editor', imports: [
|
|
1952
|
-
CommonModule,
|
|
1953
2111
|
ReactiveFormsModule,
|
|
1954
|
-
// material
|
|
1955
2112
|
ClipboardModule,
|
|
1956
2113
|
MatBadgeModule,
|
|
1957
2114
|
MatButtonModule,
|
|
@@ -1963,14 +2120,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
1963
2120
|
MatSelectModule,
|
|
1964
2121
|
MatTabsModule,
|
|
1965
2122
|
MatTooltipModule,
|
|
1966
|
-
// monaco
|
|
1967
2123
|
NgeMonacoModule,
|
|
1968
|
-
// myrmex
|
|
1969
2124
|
SafeHtmlPipe,
|
|
1970
2125
|
FeatureSetEditorComponent,
|
|
1971
2126
|
OperationSourceEditorComponent,
|
|
1972
|
-
], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <!-- tabs -->\r\n <mat-tab-group\r\n [selectedIndex]=\"tabIndex\"\r\n (selectedIndexChange)=\"onTabIndexChange($event)\"\r\n >\r\n <!-- GENERAL -->\r\n <mat-tab label=\"general\">\r\n <div class=\"form-row\">\r\n <!-- id -->\r\n <div id=\"id\" class=\"muted\">{{ id }}</div>\r\n\r\n <!-- type -->\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"type\">\r\n <mat-option [value]=\"0\"\r\n ><mat-icon>layers</mat-icon> replace</mat-option\r\n >\r\n <mat-option [value]=\"1\"\r\n ><mat-icon>close</mat-icon>delete</mat-option\r\n >\r\n <mat-option [value]=\"2\"\r\n ><mat-icon>last_page</mat-icon>add-before</mat-option\r\n >\r\n <mat-option [value]=\"3\"\r\n ><mat-icon>first_page</mat-icon>add-after</mat-option\r\n >\r\n <mat-option [value]=\"4\"\r\n ><mat-icon>login</mat-icon>move-before</mat-option\r\n >\r\n <mat-option [value]=\"5\"\r\n ><mat-icon>logout</mat-icon>move-after</mat-option\r\n >\r\n <mat-option [value]=\"6\"\r\n ><mat-icon>compare_arrows</mat-icon>swap</mat-option\r\n >\r\n <mat-option [value]=\"7\"\r\n ><mat-icon>edit_note</mat-icon>annotate</mat-option\r\n >\r\n </mat-select>\r\n <mat-error\r\n *ngIf=\"$any(type).errors?.required && (type.dirty || type.touched)\"\r\n >type required</mat-error\r\n >\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- at -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>at</mat-label>\r\n <input matInput [formControl]=\"at\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(at).errors?.required && (at.dirty || at.touched)\"\r\n >at required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- atAsIndex -->\r\n <mat-checkbox [formControl]=\"atAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- run -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>run</mat-label>\r\n <input matInput [formControl]=\"run\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(run).errors?.required && (run.dirty || run.touched)\"\r\n >run required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- to -->\r\n @if (hasTo) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to</mat-label>\r\n <input matInput [formControl]=\"to\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(to).errors?.required && (to.dirty || to.touched)\"\r\n >to required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- toAsIndex -->\r\n <mat-checkbox [formControl]=\"toAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- toRun -->\r\n @if (hasToRun) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to run</mat-label>\r\n <input matInput [formControl]=\"toRun\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"\r\n $any(toRun).errors?.required && (toRun.dirty || toRun.touched)\r\n \"\r\n >to run required</mat-error\r\n >\r\n </mat-form-field>\r\n } }\r\n\r\n <!-- value -->\r\n @if (hasValue) {\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n </mat-form-field>\r\n }\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- rank -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>rank</mat-label>\r\n <input matInput [formControl]=\"rank\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(rank).errors?.required && (rank.dirty || rank.touched)\"\r\n >rank required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- groupId -->\r\n <mat-form-field>\r\n <mat-label>group ID</mat-label>\r\n <input matInput [formControl]=\"groupId\" />\r\n <mat-error\r\n *ngIf=\"\r\n $any(groupId).errors?.required &&\r\n (groupId.dirty || groupId.touched)\r\n \"\r\n >group ID required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- inputTag -->\r\n <mat-form-field>\r\n <mat-label>input tag</mat-label>\r\n <input matInput [formControl]=\"inputTag\" />\r\n <mat-hint>blank=latest</mat-hint>\r\n </mat-form-field>\r\n\r\n <!-- outputTag -->\r\n <mat-form-field>\r\n <mat-label>output tag</mat-label>\r\n <input matInput [formControl]=\"outputTag\" />\r\n <mat-hint>blank=auto (vN)</mat-hint>\r\n </mat-form-field>\r\n </div>\r\n <div>\r\n <!-- features -->\r\n <fieldset>\r\n <legend>operation features</legend>\r\n <gve-feature-set-editor\r\n [isVar]=\"true\"\r\n [features]=\"features.value\"\r\n (featuresChange)=\"onFeaturesChange($event)\"\r\n ></gve-feature-set-editor>\r\n </fieldset>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- SOURCES -->\r\n <mat-tab label=\"sources\">\r\n <div>\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n (click)=\"addSource()\"\r\n >\r\n <mat-icon>add_circle</mat-icon>\r\n source\r\n </button>\r\n </div>\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>type</th>\r\n <th>id</th>\r\n <th>rank</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (s of sources.value; track s) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n (click)=\"editSource($index)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button type=\"button\" mat-icon-button color=\"warn\">\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ s.type }}</td>\r\n <td>{{ s.id }}</td>\r\n <td>{{ s.rank }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n <!-- source editor -->\r\n <mat-expansion-panel [disabled]=\"!editedSource\" [expanded]=\"editedSource\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>source</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-operation-source-editor\r\n [source]=\"editedSource\"\r\n (sourceChange)=\"onSourceChange($event!)\"\r\n (sourceCancel)=\"closeSource()\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- DIPLOMATIC -->\r\n <mat-tab label=\"diplomatic\">\r\n <div class=\"toolbar-row\">\r\n <button\r\n id=\"btn-save\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Save to file\"\r\n [disabled]=\"!svg.value\"\r\n (click)=\"saveSvg()\"\r\n >\r\n <mat-icon>save</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-load\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Load from file\"\r\n (click)=\"loadSvg()\"\r\n >\r\n <mat-icon>folder</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-copy\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Copy\"\r\n [cdkCopyToClipboard]=\"svg.value\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-paste\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Set SVG from clipboard\"\r\n (click)=\"setSvgFromClipboard()\"\r\n >\r\n <mat-icon>content_paste_go</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-editor\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Open SVG external editor\"\r\n (click)=\"openSvgEditor()\"\r\n >\r\n <mat-icon>launch</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-decimals\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Remove decimals\"\r\n [disabled]=\"!svg.value\"\r\n (click)=\"removeDecimals()\"\r\n >\r\n <mat-icon>pin</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-group\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Wrap code in group\"\r\n (click)=\"wrapInGroup()\"\r\n >\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div id=\"code\">\r\n <nge-monaco-editor\r\n style=\"--editor-height: 400px\"\r\n (ready)=\"onCreateEditor($event)\"\r\n />\r\n @if (svg.invalid) {\r\n <mat-error>invalid SVG</mat-error>\r\n }\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- ELEMENTS -->\r\n <mat-tab label=\"elements\">\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>id</th>\r\n <th>visual</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (e of elements; track e.id) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Edit element features\"\r\n (click)=\"editElementFeatures(e)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n matTooltip=\"Delete all element features\"\r\n (click)=\"deleteElementFeatures(e)\"\r\n [disabled]=\"!$any(elementFeatures.value)[e.id]?.length\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n <span\r\n [matBadge]=\"$any(elementFeatures.value)[e.id]?.length || 0\"\r\n [matBadgeHidden]=\"!$any(elementFeatures.value)[e.id]?.length\"\r\n matBadgeOverlap=\"false\"\r\n >{{ e.id }}</span\r\n >\r\n </td>\r\n <td class=\"svg-cell\">\r\n <svg [innerHTML]=\"e.outerHTML | safeHtml : 'html'\"></svg>\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n\r\n <mat-expansion-panel\r\n [disabled]=\"!editedElementId\"\r\n [expanded]=\"editedElementId\"\r\n >\r\n <mat-expansion-panel-header>{{\r\n editedElementId\r\n }}</mat-expansion-panel-header>\r\n <gve-feature-set-editor\r\n [features]=\"elementFeatures.value[editedElementId!] || []\"\r\n (featuresChange)=\"onElementFeaturesChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- DP FEATS -->\r\n <mat-tab label=\"d-features\">\r\n <div>\r\n <mat-checkbox [formControl]=\"newTextHidden\">hide new text</mat-checkbox>\r\n </div>\r\n <gve-feature-set-editor\r\n [features]=\"dpFeatures.value\"\r\n (featuresChange)=\"onDpFeaturesChange($event)\"\r\n ></gve-feature-set-editor>\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- buttons -->\r\n <div id=\"submit-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Discard operation\"\r\n (click)=\"cancel()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n @if (!hidePreview()) {\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Preview operation\"\r\n (click)=\"requestPreview()\"\r\n >\r\n <mat-icon class=\"mat-primary\">preview</mat-icon>\r\n </button>\r\n }\r\n <button\r\n type=\"submit\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save operation\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}#submit-row{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap;margin-top:8px;border-top:1px solid silver}.toolbar-row{display:flex;align-items:center;flex-wrap:wrap}.nr{width:5em}.long-text{width:100%;max-width:800px}#id{border-radius:6px;padding:4px;background-color:#beb9b9;color:#fff;margin-top:-16px}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:silver}table{width:100%;border-collapse:collapse;margin:8px 0}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr{border-bottom:1px solid silver}th,td{text-align:center}#btn-save{color:#072d3e}#btn-load{color:#dbd112}#btn-copy{color:#22549f}#btn-preview{color:#095409}#code{height:500px;border:1px solid silver}#monaco{height:100%}.svg-cell{padding:0 8px}.svg-cell svg{border:1px solid silver;width:100%;height:auto}#preview{box-sizing:border-box;width:100%;border:1px solid silver;border-radius:4px;padding:8px}.tree-invisible{display:none}.tree ul,.tree li{margin-top:0;margin-bottom:0;list-style-type:none}.selected-node{background-color:#e5e5e5}.child-title{font-weight:700;margin:0;background-color:#ccc;color:#fff;padding:8px}#tree-container{display:grid;grid-template-rows:auto;grid-template-columns:auto 1fr;grid-template-areas:\"nav ed\";gap:0 16px;align-items:stretch}#tree-nav{grid-area:nav;border:1px solid silver;border-radius:6px;margin:8px 0;padding-right:8px}#tree-ed{grid-area:ed;border:1px solid silver;border-radius:6px;margin:8px 0}@media only screen and (max-width: 959px){div#container{grid-template-columns:1fr;grid-template-areas:\"nav\" \"ed\";gap:16px 0;align-items:start}}\n"] }]
|
|
1973
|
-
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2$
|
|
2127
|
+
], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <!-- tabs -->\r\n <mat-tab-group\r\n [selectedIndex]=\"tabIndex()\"\r\n (selectedIndexChange)=\"onTabIndexChange($event)\"\r\n >\r\n <!-- GENERAL -->\r\n <mat-tab label=\"general\">\r\n <div class=\"form-row\">\r\n <!-- id -->\r\n <div id=\"id\" class=\"muted\">{{ id() }}</div>\r\n\r\n <!-- type -->\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"type\">\r\n <mat-option [value]=\"0\"\r\n ><mat-icon>layers</mat-icon> replace</mat-option\r\n >\r\n <mat-option [value]=\"1\"\r\n ><mat-icon>close</mat-icon>delete</mat-option\r\n >\r\n <mat-option [value]=\"2\"\r\n ><mat-icon>last_page</mat-icon>add-before</mat-option\r\n >\r\n <mat-option [value]=\"3\"\r\n ><mat-icon>first_page</mat-icon>add-after</mat-option\r\n >\r\n <mat-option [value]=\"4\"\r\n ><mat-icon>login</mat-icon>move-before</mat-option\r\n >\r\n <mat-option [value]=\"5\"\r\n ><mat-icon>logout</mat-icon>move-after</mat-option\r\n >\r\n <mat-option [value]=\"6\"\r\n ><mat-icon>compare_arrows</mat-icon>swap</mat-option\r\n >\r\n <mat-option [value]=\"7\"\r\n ><mat-icon>edit_note</mat-icon>annotate</mat-option\r\n >\r\n </mat-select>\r\n @if ($any(type).errors?.required && (type.dirty || type.touched)) {\r\n <mat-error>type required</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- at -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>at</mat-label>\r\n <input matInput [formControl]=\"at\" type=\"number\" min=\"0\" />\r\n @if ($any(at).errors?.required && (at.dirty || at.touched)) {\r\n <mat-error>at required</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- atAsIndex -->\r\n <mat-checkbox [formControl]=\"atAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- run -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>run</mat-label>\r\n <input matInput [formControl]=\"run\" type=\"number\" min=\"0\" />\r\n @if ($any(run).errors?.required && (run.dirty || run.touched)) {\r\n <mat-error>run required</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- to -->\r\n @if (hasTo()) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to</mat-label>\r\n <input matInput [formControl]=\"to\" type=\"number\" min=\"0\" />\r\n @if ($any(to).errors?.required && (to.dirty || to.touched)) {\r\n <mat-error>to required</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- toAsIndex -->\r\n <mat-checkbox [formControl]=\"toAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- toRun -->\r\n @if (hasToRun()) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to run</mat-label>\r\n <input matInput [formControl]=\"toRun\" type=\"number\" min=\"0\" />\r\n @if ( $any(toRun).errors?.required && (toRun.dirty || toRun.touched) )\r\n {\r\n <mat-error>to run required</mat-error>\r\n }\r\n </mat-form-field>\r\n } }\r\n\r\n <!-- value -->\r\n @if (hasValue()) {\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n </mat-form-field>\r\n }\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- rank -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>rank</mat-label>\r\n <input matInput [formControl]=\"rank\" type=\"number\" min=\"0\" />\r\n @if ($any(rank).errors?.required && (rank.dirty || rank.touched)) {\r\n <mat-error>rank required</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- groupId -->\r\n <mat-form-field>\r\n <mat-label>group ID</mat-label>\r\n <input matInput [formControl]=\"groupId\" />\r\n @if ( $any(groupId).errors?.required && (groupId.dirty ||\r\n groupId.touched) ) {\r\n <mat-error>group ID required</mat-error>\r\n }\r\n </mat-form-field>\r\n\r\n <!-- inputTag -->\r\n <mat-form-field>\r\n <mat-label>input tag</mat-label>\r\n <input matInput [formControl]=\"inputTag\" />\r\n <mat-hint>blank=latest</mat-hint>\r\n </mat-form-field>\r\n\r\n <!-- outputTag -->\r\n <mat-form-field>\r\n <mat-label>output tag</mat-label>\r\n <input matInput [formControl]=\"outputTag\" />\r\n <mat-hint>blank=auto (vN)</mat-hint>\r\n </mat-form-field>\r\n </div>\r\n <div>\r\n <!-- features -->\r\n <fieldset>\r\n <legend>operation features</legend>\r\n <gve-feature-set-editor\r\n [isVar]=\"true\"\r\n [featNames]=\"featureDefs()?.names\"\r\n [featValues]=\"featureDefs()?.values\"\r\n [features]=\"features.value\"\r\n (featuresChange)=\"onFeaturesChange($event)\"\r\n />\r\n </fieldset>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- SOURCES -->\r\n <mat-tab label=\"sources\">\r\n <div>\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n (click)=\"addSource()\"\r\n >\r\n <mat-icon>add_circle</mat-icon>\r\n source\r\n </button>\r\n </div>\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>type</th>\r\n <th>id</th>\r\n <th>rank</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (s of sources.value; track s) {\r\n <tr [class.selected]=\"s === editedSource()\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n (click)=\"editSource($index)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button type=\"button\" mat-icon-button color=\"warn\">\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ s.type }}</td>\r\n <td>{{ s.id }}</td>\r\n <td>{{ s.rank }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (editedSource()) {\r\n <!-- source editor -->\r\n <mat-expansion-panel\r\n [disabled]=\"!editedSource()\"\r\n [expanded]=\"editedSource()\"\r\n >\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>source</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-operation-source-editor\r\n [source]=\"editedSource()\"\r\n (sourceChange)=\"onSourceChange($event!)\"\r\n (sourceCancel)=\"closeSource()\"\r\n />\r\n </mat-expansion-panel>\r\n }\r\n </mat-tab>\r\n\r\n <!-- DIPLOMATIC -->\r\n <mat-tab label=\"diplomatic\">\r\n <div class=\"toolbar-row\">\r\n <button\r\n id=\"btn-save\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Save to file\"\r\n [disabled]=\"!svg.value\"\r\n (click)=\"saveSvg()\"\r\n >\r\n <mat-icon>save</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-load\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Load from file\"\r\n (click)=\"loadSvg()\"\r\n >\r\n <mat-icon>folder</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-copy\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Copy\"\r\n [cdkCopyToClipboard]=\"svg.value\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-paste\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Set SVG from clipboard\"\r\n (click)=\"setSvgFromClipboard()\"\r\n >\r\n <mat-icon>content_paste_go</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-editor\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Open SVG external editor\"\r\n (click)=\"openSvgEditor()\"\r\n >\r\n <mat-icon>launch</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-decimals\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Remove decimals\"\r\n [disabled]=\"!svg.value\"\r\n (click)=\"removeDecimals()\"\r\n >\r\n <mat-icon>pin</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-group\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Wrap code in group\"\r\n (click)=\"wrapInGroup()\"\r\n >\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div id=\"code\">\r\n <nge-monaco-editor\r\n style=\"--editor-height: 400px\"\r\n (ready)=\"onCreateEditor($event)\"\r\n />\r\n @if (svg.invalid) {\r\n <mat-error>invalid SVG</mat-error>\r\n }\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- ELEMENTS -->\r\n <mat-tab label=\"elements\">\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>id</th>\r\n <th>visual</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (e of elements(); track e.id) {\r\n <tr [class.selected]=\"e.id === editedElementId()\">\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Edit element features\"\r\n (click)=\"editElementFeatures(e)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n matTooltip=\"Delete all element features\"\r\n (click)=\"deleteElementFeatures(e)\"\r\n [disabled]=\"!$any(elementFeatures.value)[e.id]?.length\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>\r\n <span\r\n [matBadge]=\"$any(elementFeatures.value)[e.id]?.length || 0\"\r\n [matBadgeHidden]=\"!$any(elementFeatures.value)[e.id]?.length\"\r\n matBadgeOverlap=\"false\"\r\n >{{ e.id }}</span\r\n >\r\n </td>\r\n <td class=\"svg-cell\">\r\n <svg [innerHTML]=\"e.outerHTML | safeHtml : 'html'\"></svg>\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n @if (editedElementId()) {\r\n <mat-expansion-panel\r\n [disabled]=\"!editedElementId()\"\r\n [expanded]=\"editedElementId()\"\r\n >\r\n <mat-expansion-panel-header>{{\r\n editedElementId()\r\n }}</mat-expansion-panel-header>\r\n <gve-feature-set-editor\r\n [featNames]=\"elementFeatureDefs()?.names\"\r\n [featValues]=\"elementFeatureDefs()?.values\"\r\n [features]=\"elementFeatures.value[editedElementId()!] || []\"\r\n (featuresChange)=\"onElementFeaturesChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n }\r\n </mat-tab>\r\n\r\n <!-- DP FEATS -->\r\n <mat-tab label=\"d-features\">\r\n <div>\r\n <mat-checkbox [formControl]=\"newTextHidden\">hide new text</mat-checkbox>\r\n </div>\r\n <gve-feature-set-editor\r\n [featNames]=\"diplomaticFeatureDefs()?.names\"\r\n [featValues]=\"diplomaticFeatureDefs()?.values\"\r\n [features]=\"dpFeatures.value\"\r\n (featuresChange)=\"onDpFeaturesChange($event)\"\r\n />\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- buttons -->\r\n <div id=\"submit-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Discard operation\"\r\n (click)=\"cancel()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n @if (!hidePreview()) {\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Preview operation\"\r\n (click)=\"requestPreview()\"\r\n >\r\n <mat-icon class=\"mat-primary\">preview</mat-icon>\r\n </button>\r\n }\r\n <button\r\n type=\"submit\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save operation\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}#submit-row{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap;margin-top:8px;border-top:1px solid silver}.toolbar-row{display:flex;align-items:center;flex-wrap:wrap}.nr{width:5em}.long-text{width:100%;max-width:800px}#id{border-radius:6px;padding:4px;background-color:#beb9b9;color:#fff;margin-top:-16px}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:silver}table{width:100%;border-collapse:collapse}tbody tr:nth-child(odd){background-color:#e2e2e2}th{text-align:left;font-weight:400;color:silver}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#d0d0d0!important}#btn-save{color:#072d3e}#btn-load{color:#dbd112}#btn-copy{color:#22549f}#btn-preview{color:#095409}#code{height:500px;border:1px solid silver}#monaco{height:100%}.svg-cell{padding:0 8px}.svg-cell svg{border:1px solid silver;width:100%;height:auto}#preview{box-sizing:border-box;width:100%;border:1px solid silver;border-radius:4px;padding:8px}.tree-invisible{display:none}.tree ul,.tree li{margin-top:0;margin-bottom:0;list-style-type:none}.selected-node{background-color:#e5e5e5}.child-title{font-weight:700;margin:0;background-color:#ccc;color:#fff;padding:8px}#tree-container{display:grid;grid-template-rows:auto;grid-template-columns:auto 1fr;grid-template-areas:\"nav ed\";gap:0 16px;align-items:stretch}#tree-nav{grid-area:nav;border:1px solid silver;border-radius:6px;margin:8px 0;padding-right:8px}#tree-ed{grid-area:ed;border:1px solid silver;border-radius:6px;margin:8px 0}@media only screen and (max-width: 959px){div#container{grid-template-columns:1fr;grid-template-areas:\"nav\" \"ed\";gap:16px 0;align-items:start}}\n"] }]
|
|
2128
|
+
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2$2.Clipboard }, { type: SettingsService }, { type: i4$2.DialogService }] });
|
|
1974
2129
|
|
|
1975
2130
|
/**
|
|
1976
2131
|
* 🔑 `gve-feature-set-view`
|
|
@@ -1994,26 +2149,26 @@ class FeatureSetViewComponent {
|
|
|
1994
2149
|
/**
|
|
1995
2150
|
* The features.
|
|
1996
2151
|
*/
|
|
1997
|
-
this.features = input([]);
|
|
2152
|
+
this.features = input([], ...(ngDevMode ? [{ debugName: "features" }] : []));
|
|
1998
2153
|
/**
|
|
1999
2154
|
* The list of feature names to display in the name selection.
|
|
2000
2155
|
* This is used when you have a closed list of features.
|
|
2001
2156
|
*/
|
|
2002
|
-
this.featNames = input();
|
|
2157
|
+
this.featNames = input(...(ngDevMode ? [undefined, { debugName: "featNames" }] : []));
|
|
2003
2158
|
/**
|
|
2004
2159
|
* The feature values map. When specified and the user selects a feature
|
|
2005
2160
|
* name present in the map keys, the corresponding values will be used
|
|
2006
2161
|
* to populate the value selection.
|
|
2007
2162
|
*/
|
|
2008
|
-
this.featValues = input();
|
|
2163
|
+
this.featValues = input(...(ngDevMode ? [undefined, { debugName: "featValues" }] : []));
|
|
2009
2164
|
/**
|
|
2010
2165
|
* The threshold at which the features filter should become visible.
|
|
2011
2166
|
* If set to 0, the filter is always visible; if set to -1, it is always
|
|
2012
2167
|
* invisible; otherwise, it gets visible when the number of features
|
|
2013
2168
|
* is greater than the threshold. Default is 5.
|
|
2014
2169
|
*/
|
|
2015
|
-
this.filterThreshold = input(5);
|
|
2016
|
-
this.filteredFeatures = [];
|
|
2170
|
+
this.filterThreshold = input(5, ...(ngDevMode ? [{ debugName: "filterThreshold" }] : []));
|
|
2171
|
+
this.filteredFeatures = signal([], ...(ngDevMode ? [{ debugName: "filteredFeatures" }] : []));
|
|
2017
2172
|
this.filter = formBuilder.control(null);
|
|
2018
2173
|
// when features change, reset the filter and apply it
|
|
2019
2174
|
effect(() => {
|
|
@@ -2023,9 +2178,9 @@ class FeatureSetViewComponent {
|
|
|
2023
2178
|
});
|
|
2024
2179
|
}
|
|
2025
2180
|
applyFeatureFilter(name) {
|
|
2026
|
-
this.filteredFeatures
|
|
2181
|
+
this.filteredFeatures.set(this.features().filter((feature) => {
|
|
2027
2182
|
return !name || feature.name.toLowerCase().includes(name.toLowerCase());
|
|
2028
|
-
});
|
|
2183
|
+
}));
|
|
2029
2184
|
}
|
|
2030
2185
|
ngOnInit() {
|
|
2031
2186
|
this._sub = this.filter.valueChanges
|
|
@@ -2038,20 +2193,19 @@ class FeatureSetViewComponent {
|
|
|
2038
2193
|
ngOnDestroy() {
|
|
2039
2194
|
this._sub?.unsubscribe();
|
|
2040
2195
|
}
|
|
2041
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2042
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2196
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FeatureSetViewComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2197
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: FeatureSetViewComponent, isStandalone: true, selector: "gve-feature-set-view", inputs: { features: { classPropertyName: "features", publicName: "features", isSignal: true, isRequired: false, transformFunction: null }, featNames: { classPropertyName: "featNames", publicName: "featNames", isSignal: true, isRequired: false, transformFunction: null }, featValues: { classPropertyName: "featValues", publicName: "featValues", isSignal: true, isRequired: false, transformFunction: null }, filterThreshold: { classPropertyName: "filterThreshold", publicName: "filterThreshold", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div>\r\n <!-- filter -->\r\n <div>\r\n @if (filterThreshold() === 0 || features()!.length > filterThreshold()) {\r\n <div class=\"form-row\">\r\n <mat-form-field id=\"filter\">\r\n <mat-label>filter</mat-label>\r\n <input matInput [formControl]=\"filter\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n (click)=\"filter.reset()\"\r\n [disabled]=\"!filter.value\"\r\n [attr.aria-label]=\"'Reset filter'\"\r\n >\r\n <mat-icon color=\"warn\" class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n <span id=\"badge\">{{ filteredFeatures().length }}</span>\r\n </div>\r\n }\r\n\r\n <!-- list -->\r\n @if (filteredFeatures().length) {\r\n <table>\r\n <tbody>\r\n @for (feature of filteredFeatures(); track $index) {\r\n <tr>\r\n <th>\r\n @if (featNames.length) {\r\n <span>{{\r\n feature.name | flatLookup : featNames : \"id\" : \"label\"\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.name }}</span>\r\n }\r\n </th>\r\n <td>\r\n @if (featValues()) {\r\n <span>{{\r\n feature.value | flatLookup : featValues()![feature.name]\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.value }}</span>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.in-row-button{margin-top:-16px}table{width:100%;border-collapse:collapse}th{text-align:left;background-color:#c8d9eb;color:#333;font-weight:400}th,td{border:1px solid silver;padding:4px}tr:nth-child(2n){background-color:#dfdfdf}#filter{width:7em}#badge{border:1px solid silver;border-radius:6px;padding:4px;margin-top:-18px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "pipe", type: FlatLookupPipe, name: "flatLookup" }] }); }
|
|
2043
2198
|
}
|
|
2044
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2199
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FeatureSetViewComponent, decorators: [{
|
|
2045
2200
|
type: Component,
|
|
2046
2201
|
args: [{ selector: 'gve-feature-set-view', imports: [
|
|
2047
|
-
CommonModule,
|
|
2048
2202
|
ReactiveFormsModule,
|
|
2049
2203
|
MatButtonModule,
|
|
2050
2204
|
MatFormFieldModule,
|
|
2051
2205
|
MatIconModule,
|
|
2052
2206
|
MatInputModule,
|
|
2053
2207
|
FlatLookupPipe,
|
|
2054
|
-
], template: "<div>\r\n <!-- filter -->\r\n <div>\r\n @if (filterThreshold() === 0 || features()!.length > filterThreshold()) {\r\n <div class=\"form-row\">\r\n <mat-form-field id=\"filter\">\r\n <mat-label>filter</mat-label>\r\n <input matInput [formControl]=\"filter\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n (click)=\"filter.reset()\"\r\n [disabled]=\"!filter.value\"\r\n [attr.aria-label]=\"'Reset filter'\"\r\n >\r\n <mat-icon color=\"warn\" class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n
|
|
2208
|
+
], template: "<div>\r\n <!-- filter -->\r\n <div>\r\n @if (filterThreshold() === 0 || features()!.length > filterThreshold()) {\r\n <div class=\"form-row\">\r\n <mat-form-field id=\"filter\">\r\n <mat-label>filter</mat-label>\r\n <input matInput [formControl]=\"filter\" />\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matSuffix\r\n (click)=\"filter.reset()\"\r\n [disabled]=\"!filter.value\"\r\n [attr.aria-label]=\"'Reset filter'\"\r\n >\r\n <mat-icon color=\"warn\" class=\"mat-warn\">cancel</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n <span id=\"badge\">{{ filteredFeatures().length }}</span>\r\n </div>\r\n }\r\n\r\n <!-- list -->\r\n @if (filteredFeatures().length) {\r\n <table>\r\n <tbody>\r\n @for (feature of filteredFeatures(); track $index) {\r\n <tr>\r\n <th>\r\n @if (featNames.length) {\r\n <span>{{\r\n feature.name | flatLookup : featNames : \"id\" : \"label\"\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.name }}</span>\r\n }\r\n </th>\r\n <td>\r\n @if (featValues()) {\r\n <span>{{\r\n feature.value | flatLookup : featValues()![feature.name]\r\n }}</span>\r\n } @else {\r\n <span>{{ feature.value }}</span>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n </div>\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.in-row-button{margin-top:-16px}table{width:100%;border-collapse:collapse}th{text-align:left;background-color:#c8d9eb;color:#333;font-weight:400}th,td{border:1px solid silver;padding:4px}tr:nth-child(2n){background-color:#dfdfdf}#filter{width:7em}#badge{border:1px solid silver;border-radius:6px;padding:4px;margin-top:-18px}\n"] }]
|
|
2055
2209
|
}], ctorParameters: () => [{ type: i1.FormBuilder }] });
|
|
2056
2210
|
|
|
2057
2211
|
/**
|
|
@@ -2075,61 +2229,99 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
2075
2229
|
*/
|
|
2076
2230
|
class StepsMapComponent {
|
|
2077
2231
|
constructor() {
|
|
2232
|
+
// track view initialization
|
|
2233
|
+
this._viewInitialized = signal(false, ...(ngDevMode ? [{ debugName: "_viewInitialized" }] : []));
|
|
2234
|
+
// track whether we've processed the steps/selection
|
|
2235
|
+
this._selectionProcessed = signal(false, ...(ngDevMode ? [{ debugName: "_selectionProcessed" }] : []));
|
|
2078
2236
|
// the lines of each version text, keyed under the output tag
|
|
2079
|
-
this.lines = {};
|
|
2237
|
+
this.lines = signal({}, ...(ngDevMode ? [{ debugName: "lines" }] : []));
|
|
2080
2238
|
/**
|
|
2081
2239
|
* The steps to display.
|
|
2082
2240
|
*/
|
|
2083
|
-
this.steps = input([]);
|
|
2241
|
+
this.steps = input([], ...(ngDevMode ? [{ debugName: "steps" }] : []));
|
|
2084
2242
|
/**
|
|
2085
2243
|
* The step that is currently selected.
|
|
2086
2244
|
*/
|
|
2087
|
-
this.selectedStep = model();
|
|
2245
|
+
this.selectedStep = model(...(ngDevMode ? [undefined, { debugName: "selectedStep" }] : []));
|
|
2088
2246
|
/**
|
|
2089
2247
|
* The font size of the steps text.
|
|
2090
2248
|
*/
|
|
2091
|
-
this.textFontSize = input('0.8em');
|
|
2092
|
-
|
|
2093
|
-
* Emitted when the selected step has changed by user, or when
|
|
2094
|
-
* the steps are set for the first time.
|
|
2095
|
-
*/
|
|
2096
|
-
this.selectedStepChange = output();
|
|
2097
|
-
// when the steps change, update lines and selected step
|
|
2249
|
+
this.textFontSize = input('0.8em', ...(ngDevMode ? [{ debugName: "textFontSize" }] : []));
|
|
2250
|
+
// handle steps updates
|
|
2098
2251
|
effect(() => {
|
|
2099
|
-
const
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
this.selectedStep.set(steps[steps.length - 1]);
|
|
2103
|
-
this.updateLines(steps);
|
|
2104
|
-
this.selectedStepChange.emit(this.selectedStep());
|
|
2252
|
+
const currentSteps = this.steps();
|
|
2253
|
+
if (currentSteps && currentSteps.length > 0) {
|
|
2254
|
+
this.updateLines(currentSteps);
|
|
2105
2255
|
}
|
|
2106
2256
|
else {
|
|
2107
|
-
this.
|
|
2108
|
-
|
|
2109
|
-
|
|
2257
|
+
this.lines.set({});
|
|
2258
|
+
}
|
|
2259
|
+
// reset selection processing when steps change
|
|
2260
|
+
this._selectionProcessed.set(false);
|
|
2261
|
+
});
|
|
2262
|
+
// handle synchronization between steps and selectedStep
|
|
2263
|
+
effect(() => {
|
|
2264
|
+
// only proceed if view is initialized and we haven't processed selection yet
|
|
2265
|
+
if (this._viewInitialized() && !this._selectionProcessed()) {
|
|
2266
|
+
const currentSteps = this.steps();
|
|
2267
|
+
const currentSelectedStep = this.selectedStep();
|
|
2268
|
+
// if we have steps, handle selection
|
|
2269
|
+
if (currentSteps && currentSteps.length > 0) {
|
|
2270
|
+
if (currentSelectedStep) {
|
|
2271
|
+
// if we have both inputs, verify selection is valid
|
|
2272
|
+
this.validateAndSetSelection(currentSelectedStep);
|
|
2273
|
+
}
|
|
2274
|
+
else {
|
|
2275
|
+
// auto-select last step if no selection provided
|
|
2276
|
+
this.selectedStep.set(currentSteps[currentSteps.length - 1]);
|
|
2277
|
+
}
|
|
2278
|
+
// mark as processed
|
|
2279
|
+
this._selectionProcessed.set(true);
|
|
2280
|
+
}
|
|
2110
2281
|
}
|
|
2111
2282
|
});
|
|
2112
2283
|
}
|
|
2284
|
+
validateAndSetSelection(step) {
|
|
2285
|
+
const currentSteps = this.steps();
|
|
2286
|
+
// check if the selected step exists in the steps array
|
|
2287
|
+
const stepExists = currentSteps.some((s) => s.outputTag === step.outputTag);
|
|
2288
|
+
if (stepExists) {
|
|
2289
|
+
// valid selection, keep it
|
|
2290
|
+
this.selectedStep.set(step);
|
|
2291
|
+
}
|
|
2292
|
+
else {
|
|
2293
|
+
// invalid selection, default to last step
|
|
2294
|
+
const lastStep = currentSteps[currentSteps.length - 1];
|
|
2295
|
+
this.selectedStep.set(lastStep);
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
ngAfterViewInit() {
|
|
2299
|
+
// signal that view is ready for selection processing
|
|
2300
|
+
setTimeout(() => {
|
|
2301
|
+
this._viewInitialized.set(true);
|
|
2302
|
+
});
|
|
2303
|
+
}
|
|
2113
2304
|
updateLines(steps) {
|
|
2114
2305
|
if (!steps) {
|
|
2115
|
-
this.lines
|
|
2306
|
+
this.lines.set({});
|
|
2116
2307
|
return;
|
|
2117
2308
|
}
|
|
2309
|
+
const lines = {};
|
|
2118
2310
|
for (let i = 0; i < steps.length; i++) {
|
|
2119
2311
|
const step = this.steps()[i];
|
|
2120
|
-
|
|
2312
|
+
lines[step.outputTag] = step.result?.split('\n') || [];
|
|
2121
2313
|
}
|
|
2314
|
+
this.lines.set(lines);
|
|
2122
2315
|
}
|
|
2123
2316
|
onStepClick(step) {
|
|
2124
2317
|
this.selectedStep.set(step);
|
|
2125
|
-
this.selectedStepChange.emit(this.selectedStep());
|
|
2126
2318
|
}
|
|
2127
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2128
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2319
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: StepsMapComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2320
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: StepsMapComponent, isStandalone: true, selector: "gve-steps-map", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null }, selectedStep: { classPropertyName: "selectedStep", publicName: "selectedStep", isSignal: true, isRequired: false, transformFunction: null }, textFontSize: { classPropertyName: "textFontSize", publicName: "textFontSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedStep: "selectedStepChange" }, ngImport: i0, template: "<div>\r\n @if (steps().length) { @for (step of steps(); track step.outputTag) {\r\n <div\r\n matRipple\r\n class=\"step form-row\"\r\n [class.selected]=\"step === selectedStep()\"\r\n (click)=\"onStepClick(step)\"\r\n >\r\n <!-- tag -->\r\n <div class=\"tag\">\r\n <span class=\"muted-tag\">{{ step.inputTag }} ▶ </span>\r\n {{ step.outputTag }}\r\n </div>\r\n <!-- text lines -->\r\n <div class=\"text\" [style.fontSize]=\"textFontSize()\">\r\n @for (line of lines()[step.outputTag]; track $index) {\r\n <div class=\"line\">{{ line }}</div>\r\n }\r\n <div></div>\r\n </div>\r\n </div>\r\n } }\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:start;flex-wrap:wrap}.form-row *{flex:0 0 auto}.selected{background-color:#ffc}.step{border:1px solid rgb(68,114,253);border-radius:6px;margin:8px 0}.tag{background-color:#4472fd;color:#fff;border:1px solid rgb(68,114,253);border-radius:6px;padding:4px;cursor:pointer}.muted-tag{color:silver}.text{font-size:.5em}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatRippleModule }, { kind: "directive", type: i1$1.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "ngmodule", type: MatTooltipModule }] }); }
|
|
2129
2321
|
}
|
|
2130
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2322
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: StepsMapComponent, decorators: [{
|
|
2131
2323
|
type: Component,
|
|
2132
|
-
args: [{ selector: 'gve-steps-map', imports: [CommonModule, MatButtonModule, MatRippleModule, MatTooltipModule], template: "<div>\r\n @if (steps().length) { @for (step of steps(); track step.outputTag) {\r\n <div\r\n matRipple\r\n class=\"step form-row\"\r\n [
|
|
2324
|
+
args: [{ selector: 'gve-steps-map', imports: [CommonModule, MatButtonModule, MatRippleModule, MatTooltipModule], template: "<div>\r\n @if (steps().length) { @for (step of steps(); track step.outputTag) {\r\n <div\r\n matRipple\r\n class=\"step form-row\"\r\n [class.selected]=\"step === selectedStep()\"\r\n (click)=\"onStepClick(step)\"\r\n >\r\n <!-- tag -->\r\n <div class=\"tag\">\r\n <span class=\"muted-tag\">{{ step.inputTag }} ▶ </span>\r\n {{ step.outputTag }}\r\n </div>\r\n <!-- text lines -->\r\n <div class=\"text\" [style.fontSize]=\"textFontSize()\">\r\n @for (line of lines()[step.outputTag]; track $index) {\r\n <div class=\"line\">{{ line }}</div>\r\n }\r\n <div></div>\r\n </div>\r\n </div>\r\n } }\r\n</div>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:start;flex-wrap:wrap}.form-row *{flex:0 0 auto}.selected{background-color:#ffc}.step{border:1px solid rgb(68,114,253);border-radius:6px;margin:8px 0}.tag{background-color:#4472fd;color:#fff;border:1px solid rgb(68,114,253);border-radius:6px;padding:4px;cursor:pointer}.muted-tag{color:silver}.text{font-size:.5em}\n"] }]
|
|
2133
2325
|
}], ctorParameters: () => [] });
|
|
2134
2326
|
|
|
2135
2327
|
/**
|
|
@@ -2147,24 +2339,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
2147
2339
|
*/
|
|
2148
2340
|
class ChainResultViewComponent {
|
|
2149
2341
|
constructor(formBuilder) {
|
|
2342
|
+
// track if we've already performed step selection
|
|
2343
|
+
this._stepSelectionDone = signal(false, ...(ngDevMode ? [{ debugName: "_stepSelectionDone" }] : []));
|
|
2344
|
+
// track if component view is initialized
|
|
2345
|
+
this._viewInitialized = signal(false, ...(ngDevMode ? [{ debugName: "_viewInitialized" }] : []));
|
|
2150
2346
|
/**
|
|
2151
2347
|
* The result to display.
|
|
2152
2348
|
*/
|
|
2153
|
-
this.result = input();
|
|
2349
|
+
this.result = input(...(ngDevMode ? [undefined, { debugName: "result" }] : []));
|
|
2154
2350
|
/**
|
|
2155
2351
|
* The index of the initial step to display after the result is set.
|
|
2156
2352
|
* If the index is negative, it is counted from the end of the steps.
|
|
2157
2353
|
*/
|
|
2158
|
-
this.initialStepIndex = input();
|
|
2354
|
+
this.initialStepIndex = input(...(ngDevMode ? [undefined, { debugName: "initialStepIndex" }] : []));
|
|
2159
2355
|
/**
|
|
2160
2356
|
* Emitted when a result's step is picked by the user.
|
|
2161
2357
|
*/
|
|
2162
2358
|
this.stepPick = output();
|
|
2163
|
-
this.versionTags = [];
|
|
2164
|
-
this.tags = [];
|
|
2165
|
-
this.
|
|
2359
|
+
this.versionTags = signal([], ...(ngDevMode ? [{ debugName: "versionTags" }] : []));
|
|
2360
|
+
this.tags = signal([], ...(ngDevMode ? [{ debugName: "tags" }] : []));
|
|
2361
|
+
this.step = signal(undefined, ...(ngDevMode ? [{ debugName: "step" }] : []));
|
|
2362
|
+
this.selection = signal(undefined, ...(ngDevMode ? [{ debugName: "selection" }] : []));
|
|
2363
|
+
this.selectionFeatures = signal([], ...(ngDevMode ? [{ debugName: "selectionFeatures" }] : []));
|
|
2166
2364
|
// bind callback methods
|
|
2167
|
-
this.
|
|
2365
|
+
this.getCharColor = this.getCharColor.bind(this);
|
|
2366
|
+
// this.getCharBorderColor = this.getCharBorderColor.bind(this);
|
|
2168
2367
|
this.versionTag = formBuilder.control(null);
|
|
2169
2368
|
this.tag = formBuilder.control(null);
|
|
2170
2369
|
// when result changes, update the form
|
|
@@ -2173,14 +2372,38 @@ class ChainResultViewComponent {
|
|
|
2173
2372
|
// select the initial step if set
|
|
2174
2373
|
this.selectInitialStep(this.initialStepIndex());
|
|
2175
2374
|
});
|
|
2176
|
-
// when initialStepIndex changes,
|
|
2375
|
+
// when either the result or initialStepIndex changes, try to select a step
|
|
2177
2376
|
effect(() => {
|
|
2178
|
-
|
|
2377
|
+
// only proceed if we haven't already done selection and view is ready
|
|
2378
|
+
if (!this._stepSelectionDone() && this._viewInitialized()) {
|
|
2379
|
+
const currentResult = this.result();
|
|
2380
|
+
const currentIndex = this.initialStepIndex();
|
|
2381
|
+
// if we have both pieces of data needed for selection, do it
|
|
2382
|
+
if (currentResult?.steps?.length && currentIndex !== undefined) {
|
|
2383
|
+
this.doInitialStepSelection(currentResult, currentIndex);
|
|
2384
|
+
this._stepSelectionDone.set(true);
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2179
2387
|
});
|
|
2180
2388
|
}
|
|
2389
|
+
doInitialStepSelection(result, initialStepIndex) {
|
|
2390
|
+
// calculate the effective index (handling negative indices)
|
|
2391
|
+
const effectiveIndex = initialStepIndex < 0
|
|
2392
|
+
? result.steps.length + initialStepIndex
|
|
2393
|
+
: initialStepIndex;
|
|
2394
|
+
// ensure the index is valid
|
|
2395
|
+
if (effectiveIndex >= 0 && effectiveIndex < result.steps.length) {
|
|
2396
|
+
const targetStep = result.steps[effectiveIndex];
|
|
2397
|
+
// if we have a tag control (which we do based on your code)
|
|
2398
|
+
if (targetStep.outputTag) {
|
|
2399
|
+
// using the tag control ensures all the necessary updates happen
|
|
2400
|
+
this.tag.setValue(targetStep.outputTag);
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2181
2404
|
ngOnInit() {
|
|
2182
2405
|
this._subs = [
|
|
2183
|
-
// whenever the staged version tag changes, update the
|
|
2406
|
+
// whenever the staged version tag changes, update the tag
|
|
2184
2407
|
this.versionTag.valueChanges
|
|
2185
2408
|
.pipe(distinctUntilChanged(), debounceTime(200))
|
|
2186
2409
|
.subscribe((value) => {
|
|
@@ -2190,25 +2413,34 @@ class ChainResultViewComponent {
|
|
|
2190
2413
|
this.tag.valueChanges
|
|
2191
2414
|
.pipe(distinctUntilChanged(), debounceTime(200))
|
|
2192
2415
|
.subscribe((value) => {
|
|
2193
|
-
this.
|
|
2194
|
-
|
|
2195
|
-
|
|
2416
|
+
this.selectionFeatures.set([]); // reset selection features
|
|
2417
|
+
this.step.set(this.result()?.steps.find((step) => step.outputTag === value));
|
|
2418
|
+
if (this.step()) {
|
|
2419
|
+
this.stepPick.emit(this.step());
|
|
2196
2420
|
}
|
|
2197
2421
|
}),
|
|
2198
2422
|
];
|
|
2199
2423
|
}
|
|
2200
|
-
|
|
2201
|
-
|
|
2424
|
+
ngAfterViewInit() {
|
|
2425
|
+
// signal that view is ready for initial selection
|
|
2426
|
+
setTimeout(() => {
|
|
2427
|
+
this._viewInitialized.set(true);
|
|
2428
|
+
});
|
|
2429
|
+
}
|
|
2430
|
+
getCharColor(node) {
|
|
2431
|
+
const features = this.getNodeFeatures(node.id);
|
|
2432
|
+
return features?.some((f) => f.name === '$seg-out' || f.name === '$seg2-out')
|
|
2433
|
+
? 'orange'
|
|
2434
|
+
: null;
|
|
2202
2435
|
}
|
|
2203
2436
|
selectInitialStep(initialStepIndex) {
|
|
2204
2437
|
if (initialStepIndex !== undefined && this.result()?.steps) {
|
|
2205
|
-
this.step
|
|
2206
|
-
this.result().steps
|
|
2207
|
-
|
|
2208
|
-
: initialStepIndex];
|
|
2438
|
+
this.step.set(this.result().steps[initialStepIndex < 0
|
|
2439
|
+
? this.result().steps.length + initialStepIndex
|
|
2440
|
+
: initialStepIndex]);
|
|
2209
2441
|
}
|
|
2210
2442
|
else {
|
|
2211
|
-
this.step
|
|
2443
|
+
this.step.set(undefined);
|
|
2212
2444
|
}
|
|
2213
2445
|
}
|
|
2214
2446
|
ngOnDestroy() {
|
|
@@ -2216,7 +2448,7 @@ class ChainResultViewComponent {
|
|
|
2216
2448
|
}
|
|
2217
2449
|
updateVersionTags() {
|
|
2218
2450
|
if (!this.result()) {
|
|
2219
|
-
this.versionTags
|
|
2451
|
+
this.versionTags.set([]);
|
|
2220
2452
|
return;
|
|
2221
2453
|
}
|
|
2222
2454
|
// extract version tags from result steps features named 'version'
|
|
@@ -2228,7 +2460,7 @@ class ChainResultViewComponent {
|
|
|
2228
2460
|
}
|
|
2229
2461
|
}
|
|
2230
2462
|
}
|
|
2231
|
-
this.versionTags
|
|
2463
|
+
this.versionTags.set(Array.from(tags).sort());
|
|
2232
2464
|
}
|
|
2233
2465
|
getTagFromVersion(version) {
|
|
2234
2466
|
if (!this.result() || !version) {
|
|
@@ -2244,26 +2476,29 @@ class ChainResultViewComponent {
|
|
|
2244
2476
|
return undefined;
|
|
2245
2477
|
}
|
|
2246
2478
|
updateForm(result) {
|
|
2247
|
-
this.selectionFeatures
|
|
2479
|
+
this.selectionFeatures.set([]);
|
|
2248
2480
|
if (!result) {
|
|
2249
|
-
this.step
|
|
2250
|
-
this.selection
|
|
2251
|
-
this.tags
|
|
2252
|
-
this.versionTags
|
|
2481
|
+
this.step.set(undefined);
|
|
2482
|
+
this.selection.set(undefined);
|
|
2483
|
+
this.tags.set([]);
|
|
2484
|
+
this.versionTags.set([]);
|
|
2253
2485
|
}
|
|
2254
2486
|
else {
|
|
2255
|
-
this.tags
|
|
2487
|
+
this.tags.set(result.chainTags.filter((t) => t.length > 0 && t !== 'v0'));
|
|
2256
2488
|
this.updateVersionTags();
|
|
2257
2489
|
}
|
|
2490
|
+
// reset step selection tracking when result changes
|
|
2491
|
+
this._stepSelectionDone.set(false);
|
|
2258
2492
|
}
|
|
2259
2493
|
getNodeFeatures(id) {
|
|
2260
|
-
if (!this.step) {
|
|
2494
|
+
if (!this.step()) {
|
|
2261
2495
|
return [];
|
|
2262
2496
|
}
|
|
2263
|
-
return (this.step.featureSet.nodeFeatures[this.step.outputTag + '_' + id] ||
|
|
2497
|
+
return (this.step().featureSet.nodeFeatures[this.step().outputTag + '_' + id] ||
|
|
2498
|
+
[]);
|
|
2264
2499
|
}
|
|
2265
2500
|
findNode(id) {
|
|
2266
|
-
if (!this.step) {
|
|
2501
|
+
if (!this.step()) {
|
|
2267
2502
|
return null;
|
|
2268
2503
|
}
|
|
2269
2504
|
for (let key of Object.keys(this.result().taggedNodes)) {
|
|
@@ -2274,18 +2509,18 @@ class ChainResultViewComponent {
|
|
|
2274
2509
|
}
|
|
2275
2510
|
return null;
|
|
2276
2511
|
}
|
|
2277
|
-
|
|
2512
|
+
onTextCharPick(event) {
|
|
2278
2513
|
const features = this.getNodeFeatures(event.char.id);
|
|
2279
2514
|
const node = this.findNode(event.char.id);
|
|
2280
|
-
this.selection
|
|
2281
|
-
this.selectionFeatures
|
|
2515
|
+
this.selection.set(`${event.char.label} (${node.sourceTag})`);
|
|
2516
|
+
this.selectionFeatures.set([...features]);
|
|
2282
2517
|
}
|
|
2283
|
-
|
|
2518
|
+
onTextRangePick(range) {
|
|
2284
2519
|
if (range.run === 1) {
|
|
2285
2520
|
// already handled by onStepCharPick
|
|
2286
2521
|
return;
|
|
2287
2522
|
}
|
|
2288
|
-
this.selection
|
|
2523
|
+
this.selection.set(range.at + '×' + range.run);
|
|
2289
2524
|
const end = range.at + range.run;
|
|
2290
2525
|
const features = [];
|
|
2291
2526
|
const tagNodes = this.result().taggedNodes[this.tag.value];
|
|
@@ -2304,22 +2539,21 @@ class ChainResultViewComponent {
|
|
|
2304
2539
|
}
|
|
2305
2540
|
}
|
|
2306
2541
|
}
|
|
2307
|
-
this.selectionFeatures
|
|
2542
|
+
this.selectionFeatures.set(features);
|
|
2308
2543
|
}
|
|
2309
2544
|
onStepChange(step) {
|
|
2545
|
+
this.selectionFeatures.set([]);
|
|
2310
2546
|
if (step) {
|
|
2311
2547
|
// setting the tag will trigger the step change
|
|
2312
2548
|
this.tag.setValue(step.outputTag);
|
|
2313
|
-
this.selectionFeatures = [];
|
|
2314
2549
|
}
|
|
2315
2550
|
}
|
|
2316
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2317
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2551
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ChainResultViewComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2552
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: ChainResultViewComponent, isStandalone: true, selector: "gve-chain-result-view", inputs: { result: { classPropertyName: "result", publicName: "result", isSignal: true, isRequired: false, transformFunction: null }, initialStepIndex: { classPropertyName: "initialStepIndex", publicName: "initialStepIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stepPick: "stepPick" }, ngImport: i0, template: "@if (result()) {\r\n<div id=\"container\">\r\n <div id=\"bar\" class=\"form-row\">\r\n <!-- version -->\r\n @if (versionTags().length) {\r\n <mat-form-field>\r\n <mat-label>version</mat-label>\r\n <mat-select [formControl]=\"versionTag\">\r\n <mat-option [value]=\"null\">-</mat-option>\r\n @for (t of versionTags(); track t) {\r\n <mat-option [value]=\"t\">{{ t }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n <!-- tag -->\r\n @if (tags().length) {\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <mat-select [formControl]=\"tag\">\r\n @for (t of tags(); track t) {\r\n <mat-option [value]=\"t\">{{ t }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <!-- step -->\r\n @if (step()) {\r\n <div id=\"step\">\r\n <!-- text -->\r\n <div id=\"text\">\r\n <gve-base-text-view\r\n [text]=\"result()!.taggedNodes[step()!.outputTag]\"\r\n [colorCallback]=\"getCharColor\"\r\n (charPick)=\"onTextCharPick($event)\"\r\n (rangePick)=\"onTextRangePick($event)\"\r\n />\r\n </div>\r\n <!-- features -->\r\n <div id=\"feats\" class=\"form-row-top\">\r\n <div id=\"g-feats\">\r\n <div class=\"feat-header\">{{ step()!.outputTag }}</div>\r\n <gve-feature-set-view [features]=\"step()!.featureSet.features\" />\r\n </div>\r\n <div id=\"n-feats\">\r\n @if (selectionFeatures().length) {\r\n <div class=\"feat-header\">{{ selection() }}</div>\r\n <gve-feature-set-view [features]=\"selectionFeatures()\" />\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- steps map -->\r\n <div id=\"map\">\r\n <gve-steps-map\r\n [steps]=\"result()!.steps\"\r\n [selectedStep]=\"step()\"\r\n (selectedStepChange)=\"onStepChange($event)\"\r\n />\r\n </div>\r\n</div>\r\n}\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.form-row-top{display:flex;gap:8px;align-items:start;flex-wrap:wrap}div#container{display:grid;grid-template-rows:auto 1fr;grid-template-columns:3fr 1fr;grid-template-areas:\"bar map\" \"step map\";gap:8px}div#bar{grid-area:bar}div#map{grid-area:map}div#step{grid-area:step}.feat-header{background-color:#3e92cc;color:#fff;text-align:center;border:1px solid #3e92cc;border-top-left-radius:4px;border-top-right-radius:4px}@media only screen and (max-width: 959px){div#container{grid-template-columns:1fr;grid-template-areas:\"bar\" \"step\"}#map{display:none}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: FeatureSetViewComponent, selector: "gve-feature-set-view", inputs: ["features", "featNames", "featValues", "filterThreshold"] }, { kind: "component", type: StepsMapComponent, selector: "gve-steps-map", inputs: ["steps", "selectedStep", "textFontSize"], outputs: ["selectedStepChange"] }, { kind: "component", type: BaseTextViewComponent, selector: "gve-base-text-view", inputs: ["defaultColor", "defaultBorderColor", "selectionColor", "hasLineNumber", "text", "colorCallback", "borderColorCallback"], outputs: ["charPick", "rangePick"] }] }); }
|
|
2318
2553
|
}
|
|
2319
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2554
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ChainResultViewComponent, decorators: [{
|
|
2320
2555
|
type: Component,
|
|
2321
2556
|
args: [{ selector: 'gve-chain-result-view', imports: [
|
|
2322
|
-
CommonModule,
|
|
2323
2557
|
ReactiveFormsModule,
|
|
2324
2558
|
MatButtonModule,
|
|
2325
2559
|
MatFormFieldModule,
|
|
@@ -2328,7 +2562,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
2328
2562
|
FeatureSetViewComponent,
|
|
2329
2563
|
StepsMapComponent,
|
|
2330
2564
|
BaseTextViewComponent,
|
|
2331
|
-
], template: "@if (result()) {\r\n<div id=\"container\">\r\n <div id=\"bar\" class=\"form-row\">\r\n <!-- version -->\r\n <mat-form-field
|
|
2565
|
+
], template: "@if (result()) {\r\n<div id=\"container\">\r\n <div id=\"bar\" class=\"form-row\">\r\n <!-- version -->\r\n @if (versionTags().length) {\r\n <mat-form-field>\r\n <mat-label>version</mat-label>\r\n <mat-select [formControl]=\"versionTag\">\r\n <mat-option [value]=\"null\">-</mat-option>\r\n @for (t of versionTags(); track t) {\r\n <mat-option [value]=\"t\">{{ t }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n <!-- tag -->\r\n @if (tags().length) {\r\n <mat-form-field>\r\n <mat-label>tag</mat-label>\r\n <mat-select [formControl]=\"tag\">\r\n @for (t of tags(); track t) {\r\n <mat-option [value]=\"t\">{{ t }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n </div>\r\n\r\n <!-- step -->\r\n @if (step()) {\r\n <div id=\"step\">\r\n <!-- text -->\r\n <div id=\"text\">\r\n <gve-base-text-view\r\n [text]=\"result()!.taggedNodes[step()!.outputTag]\"\r\n [colorCallback]=\"getCharColor\"\r\n (charPick)=\"onTextCharPick($event)\"\r\n (rangePick)=\"onTextRangePick($event)\"\r\n />\r\n </div>\r\n <!-- features -->\r\n <div id=\"feats\" class=\"form-row-top\">\r\n <div id=\"g-feats\">\r\n <div class=\"feat-header\">{{ step()!.outputTag }}</div>\r\n <gve-feature-set-view [features]=\"step()!.featureSet.features\" />\r\n </div>\r\n <div id=\"n-feats\">\r\n @if (selectionFeatures().length) {\r\n <div class=\"feat-header\">{{ selection() }}</div>\r\n <gve-feature-set-view [features]=\"selectionFeatures()\" />\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- steps map -->\r\n <div id=\"map\">\r\n <gve-steps-map\r\n [steps]=\"result()!.steps\"\r\n [selectedStep]=\"step()\"\r\n (selectedStepChange)=\"onStepChange($event)\"\r\n />\r\n </div>\r\n</div>\r\n}\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.form-row-top{display:flex;gap:8px;align-items:start;flex-wrap:wrap}div#container{display:grid;grid-template-rows:auto 1fr;grid-template-columns:3fr 1fr;grid-template-areas:\"bar map\" \"step map\";gap:8px}div#bar{grid-area:bar}div#map{grid-area:map}div#step{grid-area:step}.feat-header{background-color:#3e92cc;color:#fff;text-align:center;border:1px solid #3e92cc;border-top-left-radius:4px;border-top-right-radius:4px}@media only screen and (max-width: 959px){div#container{grid-template-columns:1fr;grid-template-areas:\"bar\" \"step\"}#map{display:none}}\n"] }]
|
|
2332
2566
|
}], ctorParameters: () => [{ type: i1.FormBuilder }] });
|
|
2333
2567
|
|
|
2334
2568
|
class GveGraphvizService {
|
|
@@ -2436,10 +2670,10 @@ class GveGraphvizService {
|
|
|
2436
2670
|
sb.push('}');
|
|
2437
2671
|
return sb.join('\n');
|
|
2438
2672
|
}
|
|
2439
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2440
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2673
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: GveGraphvizService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2674
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: GveGraphvizService, providedIn: 'root' }); }
|
|
2441
2675
|
}
|
|
2442
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2676
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: GveGraphvizService, decorators: [{
|
|
2443
2677
|
type: Injectable,
|
|
2444
2678
|
args: [{
|
|
2445
2679
|
providedIn: 'root',
|
|
@@ -2455,11 +2689,11 @@ class ChainViewComponent {
|
|
|
2455
2689
|
/**
|
|
2456
2690
|
* The chain to display.
|
|
2457
2691
|
*/
|
|
2458
|
-
this.chain = input();
|
|
2692
|
+
this.chain = input(...(ngDevMode ? [undefined, { debugName: "chain" }] : []));
|
|
2459
2693
|
/**
|
|
2460
2694
|
* The direction of the graph.
|
|
2461
2695
|
*/
|
|
2462
|
-
this.direction = input('LR');
|
|
2696
|
+
this.direction = input('LR', ...(ngDevMode ? [{ debugName: "direction" }] : []));
|
|
2463
2697
|
/**
|
|
2464
2698
|
* All the distinct tags in the chain.
|
|
2465
2699
|
*/
|
|
@@ -2473,11 +2707,11 @@ class ChainViewComponent {
|
|
|
2473
2707
|
set.add(link.tag);
|
|
2474
2708
|
}
|
|
2475
2709
|
return Array.from(set).sort();
|
|
2476
|
-
});
|
|
2710
|
+
}, ...(ngDevMode ? [{ debugName: "tags" }] : []));
|
|
2477
2711
|
/**
|
|
2478
2712
|
* The tags to show, or empty to show all of them.
|
|
2479
2713
|
*/
|
|
2480
|
-
this.selectedTags = model([]);
|
|
2714
|
+
this.selectedTags = model([], ...(ngDevMode ? [{ debugName: "selectedTags" }] : []));
|
|
2481
2715
|
/**
|
|
2482
2716
|
* The Graphviz representation of the chain.
|
|
2483
2717
|
*/
|
|
@@ -2487,7 +2721,7 @@ class ChainViewComponent {
|
|
|
2487
2721
|
tags = undefined;
|
|
2488
2722
|
}
|
|
2489
2723
|
return this._graphviz.generateGraph(this.chain(), tags, this.direction());
|
|
2490
|
-
});
|
|
2724
|
+
}, ...(ngDevMode ? [{ debugName: "graph" }] : []));
|
|
2491
2725
|
this.userTags = new FormControl([], {
|
|
2492
2726
|
nonNullable: true,
|
|
2493
2727
|
});
|
|
@@ -2537,22 +2771,21 @@ class ChainViewComponent {
|
|
|
2537
2771
|
}
|
|
2538
2772
|
window.open(url, '_blank');
|
|
2539
2773
|
}
|
|
2540
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2541
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2774
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ChainViewComponent, deps: [{ token: GveGraphvizService }, { token: SettingsService }, { token: i2$2.Clipboard }, { token: i4$3.MatSnackBar }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2775
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: ChainViewComponent, isStandalone: true, selector: "gve-chain-view", inputs: { chain: { classPropertyName: "chain", publicName: "chain", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, selectedTags: { classPropertyName: "selectedTags", publicName: "selectedTags", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedTags: "selectedTagsChange" }, ngImport: i0, template: "<div id=\"container\">\r\n <div>\r\n <ngx-viz [code]=\"graph()\" />\r\n </div>\r\n <div class=\"button-row\">\r\n <!-- select -->\r\n <mat-form-field>\r\n <mat-label>tags</mat-label>\r\n <mat-select [formControl]=\"userTags\" multiple>\r\n @for (tag of tags(); track tag) {\r\n <mat-option [value]=\"tag\">{{ tag }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n <!-- copy -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Copy graphviz code\"\r\n [disabled]=\"!graph()\"\r\n (click)=\"copyGraph()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <!--editor -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Open in editor\"\r\n [disabled]=\"!graph()\"\r\n (click)=\"openExternalEditor()\"\r\n >\r\n <mat-icon>launch</mat-icon>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: ["div#container{border:1px solid silver;border-radius:6px;padding:4px}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: VizComponent, selector: "ngx-viz", inputs: ["code"] }] }); }
|
|
2542
2776
|
}
|
|
2543
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2777
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ChainViewComponent, decorators: [{
|
|
2544
2778
|
type: Component,
|
|
2545
2779
|
args: [{ selector: 'gve-chain-view', imports: [
|
|
2546
|
-
CommonModule,
|
|
2547
2780
|
ReactiveFormsModule,
|
|
2548
2781
|
MatButtonModule,
|
|
2549
2782
|
MatFormFieldModule,
|
|
2550
2783
|
MatIconModule,
|
|
2551
2784
|
MatSelectModule,
|
|
2552
2785
|
MatTooltipModule,
|
|
2553
|
-
VizComponent
|
|
2786
|
+
VizComponent
|
|
2554
2787
|
], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div id=\"container\">\r\n <div>\r\n <ngx-viz [code]=\"graph()\" />\r\n </div>\r\n <div class=\"button-row\">\r\n <!-- select -->\r\n <mat-form-field>\r\n <mat-label>tags</mat-label>\r\n <mat-select [formControl]=\"userTags\" multiple>\r\n @for (tag of tags(); track tag) {\r\n <mat-option [value]=\"tag\">{{ tag }}</mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n <!-- copy -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Copy graphviz code\"\r\n [disabled]=\"!graph()\"\r\n (click)=\"copyGraph()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <!--editor -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Open in editor\"\r\n [disabled]=\"!graph()\"\r\n (click)=\"openExternalEditor()\"\r\n >\r\n <mat-icon>launch</mat-icon>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: ["div#container{border:1px solid silver;border-radius:6px;padding:4px}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}\n"] }]
|
|
2555
|
-
}], ctorParameters: () => [{ type: GveGraphvizService }, { type: SettingsService }, { type: i2$
|
|
2788
|
+
}], ctorParameters: () => [{ type: GveGraphvizService }, { type: SettingsService }, { type: i2$2.Clipboard }, { type: i4$3.MatSnackBar }] });
|
|
2556
2789
|
|
|
2557
2790
|
/**
|
|
2558
2791
|
* 🔑 `gve-ln-heights-editor`
|
|
@@ -2570,23 +2803,20 @@ class LnHeightsEditorComponent {
|
|
|
2570
2803
|
/**
|
|
2571
2804
|
* The total number of lines in the text.
|
|
2572
2805
|
*/
|
|
2573
|
-
this.lineCount = input(0);
|
|
2806
|
+
this.lineCount = input(0, ...(ngDevMode ? [{ debugName: "lineCount" }] : []));
|
|
2574
2807
|
/**
|
|
2575
2808
|
* The heights map of the lines. Each key is a line number and the value is
|
|
2576
2809
|
* the height of the line.
|
|
2577
2810
|
*/
|
|
2578
|
-
this.heights = input();
|
|
2811
|
+
this.heights = input(...(ngDevMode ? [undefined, { debugName: "heights" }] : []));
|
|
2579
2812
|
/**
|
|
2580
2813
|
* The event emitted when the heights change.
|
|
2581
2814
|
*/
|
|
2582
2815
|
this.heightsChange = output();
|
|
2583
|
-
|
|
2816
|
+
// when lineCount changes, update lineNumbers
|
|
2817
|
+
this.lineNumbers = computed(() => Array.from({ length: this.lineCount() }, (_, i) => i + 1), ...(ngDevMode ? [{ debugName: "lineNumbers" }] : []));
|
|
2584
2818
|
this.lineNumber = formBuilder.control(0, { nonNullable: true });
|
|
2585
2819
|
this.height = formBuilder.control(0, { nonNullable: true });
|
|
2586
|
-
// when lineCount changes, update lineNumbers
|
|
2587
|
-
effect(() => {
|
|
2588
|
-
this.lineNumbers = Array.from({ length: this.lineCount() }, (_, i) => i + 1);
|
|
2589
|
-
});
|
|
2590
2820
|
}
|
|
2591
2821
|
pruneHeights() {
|
|
2592
2822
|
// remove all the heigths with value=0
|
|
@@ -2605,8 +2835,13 @@ class LnHeightsEditorComponent {
|
|
|
2605
2835
|
if (!this._heights) {
|
|
2606
2836
|
this._heights = {};
|
|
2607
2837
|
}
|
|
2608
|
-
this.
|
|
2609
|
-
this.
|
|
2838
|
+
const ln = this.lineNumber.value;
|
|
2839
|
+
const newHeights = { ...(this._heights || {}) };
|
|
2840
|
+
newHeights[ln] = value;
|
|
2841
|
+
this._heights = Object.fromEntries(Object.entries(newHeights).filter(([_, v]) => v !== 0));
|
|
2842
|
+
if (Object.keys(this._heights).length === 0) {
|
|
2843
|
+
this._heights = undefined;
|
|
2844
|
+
}
|
|
2610
2845
|
this.heightsChange.emit(this._heights);
|
|
2611
2846
|
}));
|
|
2612
2847
|
// update height when line number changes
|
|
@@ -2625,13 +2860,12 @@ class LnHeightsEditorComponent {
|
|
|
2625
2860
|
this._heights = undefined;
|
|
2626
2861
|
this.heightsChange.emit(undefined);
|
|
2627
2862
|
}
|
|
2628
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2629
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2863
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LnHeightsEditorComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2864
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: LnHeightsEditorComponent, isStandalone: true, selector: "gve-ln-heights-editor", inputs: { lineCount: { classPropertyName: "lineCount", publicName: "lineCount", isSignal: true, isRequired: false, transformFunction: null }, heights: { classPropertyName: "heights", publicName: "heights", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { heightsChange: "heightsChange" }, ngImport: i0, template: "@if (lineNumbers().length) {\r\n <div class=\"form-row\">\r\n <!-- line number -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>line</mat-label>\r\n <mat-select [formControl]=\"lineNumber\">\r\n @for (n of lineNumbers(); track n) {\r\n <mat-option [value]=\"n\">\r\n {{ n }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n @if (lineNumber.value) {\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input matInput type=\"number\" [formControl]=\"height\" min=\"0\" />\r\n </mat-form-field>\r\n }\r\n\r\n <!-- reset button -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n (click)=\"reset()\"\r\n matTooltip=\"Remove all the heights\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </div>\r\n}\r\n", styles: [".input-nr{width:5em}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); }
|
|
2630
2865
|
}
|
|
2631
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2866
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LnHeightsEditorComponent, decorators: [{
|
|
2632
2867
|
type: Component,
|
|
2633
2868
|
args: [{ selector: 'gve-ln-heights-editor', imports: [
|
|
2634
|
-
CommonModule,
|
|
2635
2869
|
ReactiveFormsModule,
|
|
2636
2870
|
MatButtonModule,
|
|
2637
2871
|
MatFormFieldModule,
|
|
@@ -2639,130 +2873,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
2639
2873
|
MatInputModule,
|
|
2640
2874
|
MatSelectModule,
|
|
2641
2875
|
MatTooltipModule,
|
|
2642
|
-
], template: "@if (lineNumbers.length) {\r\n<div class=\"form-row\">\r\n
|
|
2876
|
+
], template: "@if (lineNumbers().length) {\r\n <div class=\"form-row\">\r\n <!-- line number -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>line</mat-label>\r\n <mat-select [formControl]=\"lineNumber\">\r\n @for (n of lineNumbers(); track n) {\r\n <mat-option [value]=\"n\">\r\n {{ n }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n @if (lineNumber.value) {\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input matInput type=\"number\" [formControl]=\"height\" min=\"0\" />\r\n </mat-form-field>\r\n }\r\n\r\n <!-- reset button -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n (click)=\"reset()\"\r\n matTooltip=\"Remove all the heights\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </div>\r\n}\r\n", styles: [".input-nr{width:5em}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"] }]
|
|
2643
2877
|
}], ctorParameters: () => [{ type: i1.FormBuilder }] });
|
|
2644
2878
|
|
|
2645
|
-
/**
|
|
2646
|
-
* 🔑 `gve-animation-timeline-set`
|
|
2647
|
-
*
|
|
2648
|
-
* A component to edit a set of animation timelines.
|
|
2649
|
-
* Used by the `gve-snapshot-editor` component.
|
|
2650
|
-
*
|
|
2651
|
-
* - ▶️ `timelines` (`GveAnimationTimeline[]`): the animation timelines to edit.
|
|
2652
|
-
* - ▶️ `elementIds` (`string[]`): the IDs of the elements that can be selected by the tween.
|
|
2653
|
-
* - ▶️ `tags` (`string[]`): the tags that can be used by the timeline.
|
|
2654
|
-
* - 🔥 `timelinesChange` (`GveAnimationTimeline[]`): emitted when the timelines are changed.
|
|
2655
|
-
* - 🔥 `timelinesCancel` (`void`): emitted when the timeline editing is canceled.
|
|
2656
|
-
*/
|
|
2657
|
-
class AnimationTimelineSetComponent {
|
|
2658
|
-
constructor(formBuilder, _dialogService) {
|
|
2659
|
-
this._dialogService = _dialogService;
|
|
2660
|
-
/**
|
|
2661
|
-
* The animation timelines to edit.
|
|
2662
|
-
*/
|
|
2663
|
-
this.timelines = model([]);
|
|
2664
|
-
/**
|
|
2665
|
-
* The IDs of the elements that can be selected by the tween.
|
|
2666
|
-
* This list is used to allow the user to select an element from a dropdown.
|
|
2667
|
-
*/
|
|
2668
|
-
this.elementIds = input();
|
|
2669
|
-
/**
|
|
2670
|
-
* The tags that can be used by the timeline.
|
|
2671
|
-
*/
|
|
2672
|
-
this.tags = input([]);
|
|
2673
|
-
/**
|
|
2674
|
-
* Emitted when the timelines are changed.
|
|
2675
|
-
*/
|
|
2676
|
-
this.timelinesChange = output();
|
|
2677
|
-
/**
|
|
2678
|
-
* Emitted when the timeline editing is canceled.
|
|
2679
|
-
*/
|
|
2680
|
-
this.timelinesCancel = output();
|
|
2681
|
-
this.set = formBuilder.control([], {
|
|
2682
|
-
nonNullable: true,
|
|
2683
|
-
});
|
|
2684
|
-
this.form = formBuilder.group({
|
|
2685
|
-
sets: this.set,
|
|
2686
|
-
});
|
|
2687
|
-
effect(() => {
|
|
2688
|
-
this.updateForm(this.timelines());
|
|
2689
|
-
});
|
|
2690
|
-
}
|
|
2691
|
-
updateForm(animations) {
|
|
2692
|
-
if (!animations?.length) {
|
|
2693
|
-
this.form.reset();
|
|
2694
|
-
}
|
|
2695
|
-
else {
|
|
2696
|
-
this.set.setValue(animations);
|
|
2697
|
-
this.set.markAsPristine();
|
|
2698
|
-
}
|
|
2699
|
-
}
|
|
2700
|
-
closeTimeline() {
|
|
2701
|
-
this.editedTimeline = undefined;
|
|
2702
|
-
}
|
|
2703
|
-
newTimeline() {
|
|
2704
|
-
this.editedTimeline = {
|
|
2705
|
-
tag: '',
|
|
2706
|
-
tweens: [],
|
|
2707
|
-
};
|
|
2708
|
-
}
|
|
2709
|
-
editTimeline(index) {
|
|
2710
|
-
this.editedTimeline = this.timelines()[index];
|
|
2711
|
-
}
|
|
2712
|
-
onTimelineChange(timeline) {
|
|
2713
|
-
const timelines = [...this.set.value];
|
|
2714
|
-
const i = timelines.findIndex((t) => t.tag === timeline.tag);
|
|
2715
|
-
if (i === -1) {
|
|
2716
|
-
timelines.push(timeline);
|
|
2717
|
-
}
|
|
2718
|
-
else {
|
|
2719
|
-
timelines[i] = timeline;
|
|
2720
|
-
}
|
|
2721
|
-
this.closeTimeline();
|
|
2722
|
-
// sort timelines by tag
|
|
2723
|
-
timelines.sort((a, b) => a.tag.localeCompare(b.tag));
|
|
2724
|
-
this.set.setValue(timelines);
|
|
2725
|
-
this.set.markAsDirty();
|
|
2726
|
-
this.set.updateValueAndValidity();
|
|
2727
|
-
this.timelines.set(this.set.value);
|
|
2728
|
-
this.timelinesChange.emit(this.timelines());
|
|
2729
|
-
}
|
|
2730
|
-
deleteTimeline(index) {
|
|
2731
|
-
this._dialogService
|
|
2732
|
-
.confirm('Confirm Deletion', `Delete ${this.set.value[index].tag}?`)
|
|
2733
|
-
.subscribe((yes) => {
|
|
2734
|
-
if (yes) {
|
|
2735
|
-
const timelines = [...this.set.value];
|
|
2736
|
-
timelines.splice(index, 1);
|
|
2737
|
-
this.set.setValue(timelines);
|
|
2738
|
-
this.set.markAsDirty();
|
|
2739
|
-
this.set.updateValueAndValidity();
|
|
2740
|
-
this.timelines.set(this.set.value);
|
|
2741
|
-
this.timelinesChange.emit(this.timelines());
|
|
2742
|
-
}
|
|
2743
|
-
});
|
|
2744
|
-
}
|
|
2745
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: AnimationTimelineSetComponent, deps: [{ token: i1.FormBuilder }, { token: i2$1.DialogService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2746
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: AnimationTimelineSetComponent, isStandalone: true, selector: "gve-animation-timeline-set", inputs: { timelines: { classPropertyName: "timelines", publicName: "timelines", isSignal: true, isRequired: false, transformFunction: null }, elementIds: { classPropertyName: "elementIds", publicName: "elementIds", isSignal: true, isRequired: false, transformFunction: null }, tags: { classPropertyName: "tags", publicName: "tags", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { timelines: "timelinesChange", timelinesChange: "timelinesChange", timelinesCancel: "timelinesCancel" }, ngImport: i0, template: "<form [formGroup]=\"form\">\r\n <!-- add -->\r\n <div>\r\n <button\r\n type=\"button\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n (click)=\"newTimeline()\"\r\n >\r\n <mat-icon>add_circle</mat-icon>\r\n timeline\r\n </button>\r\n </div>\r\n\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>tag</th>\r\n <th>tweens</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (t of set.value; track t.tag; let index = $index) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button type=\"button\" mat-icon-button (click)=\"editTimeline(index)\">\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button type=\"button\" mat-icon-button (click)=\"deleteTimeline(index)\">\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ t.tag }}</td>\r\n <td>{{ t.tweens.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n\r\n <!-- editor -->\r\n <mat-expansion-panel [disabled]=\"!editedTimeline\" [expanded]=\"editedTimeline\">\r\n <mat-expansion-panel-header>\r\n timeline {{ editedTimeline?.tag }}\r\n </mat-expansion-panel-header>\r\n <gve-animation-timeline\r\n [elementIds]=\"elementIds()\"\r\n [tags]=\"tags()\"\r\n [timeline]=\"editedTimeline\"\r\n (timelineChange)=\"onTimelineChange($event)\"\r\n (timelineCancel)=\"closeTimeline()\"\r\n />\r\n </mat-expansion-panel>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}table{width:100%;border-collapse:collapse;margin:8px 0}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: AnimationTimelineComponent, selector: "gve-animation-timeline", inputs: ["timeline", "elementIds", "tags"], outputs: ["timelineChange", "timelineCancel"] }] }); }
|
|
2747
|
-
}
|
|
2748
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: AnimationTimelineSetComponent, decorators: [{
|
|
2749
|
-
type: Component,
|
|
2750
|
-
args: [{ selector: 'gve-animation-timeline-set', imports: [
|
|
2751
|
-
CommonModule,
|
|
2752
|
-
ReactiveFormsModule,
|
|
2753
|
-
MatButtonModule,
|
|
2754
|
-
MatCheckboxModule,
|
|
2755
|
-
MatExpansionModule,
|
|
2756
|
-
MatFormFieldModule,
|
|
2757
|
-
MatIconModule,
|
|
2758
|
-
MatInputModule,
|
|
2759
|
-
MatSelectModule,
|
|
2760
|
-
MatTabsModule,
|
|
2761
|
-
MatTooltipModule,
|
|
2762
|
-
AnimationTimelineComponent,
|
|
2763
|
-
], template: "<form [formGroup]=\"form\">\r\n <!-- add -->\r\n <div>\r\n <button\r\n type=\"button\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n (click)=\"newTimeline()\"\r\n >\r\n <mat-icon>add_circle</mat-icon>\r\n timeline\r\n </button>\r\n </div>\r\n\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>tag</th>\r\n <th>tweens</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (t of set.value; track t.tag; let index = $index) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button type=\"button\" mat-icon-button (click)=\"editTimeline(index)\">\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button type=\"button\" mat-icon-button (click)=\"deleteTimeline(index)\">\r\n <mat-icon class=\"mat-warn\">remove_circle</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ t.tag }}</td>\r\n <td>{{ t.tweens.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n\r\n <!-- editor -->\r\n <mat-expansion-panel [disabled]=\"!editedTimeline\" [expanded]=\"editedTimeline\">\r\n <mat-expansion-panel-header>\r\n timeline {{ editedTimeline?.tag }}\r\n </mat-expansion-panel-header>\r\n <gve-animation-timeline\r\n [elementIds]=\"elementIds()\"\r\n [tags]=\"tags()\"\r\n [timeline]=\"editedTimeline\"\r\n (timelineChange)=\"onTimelineChange($event)\"\r\n (timelineCancel)=\"closeTimeline()\"\r\n />\r\n </mat-expansion-panel>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}table{width:100%;border-collapse:collapse;margin:8px 0}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}\n"] }]
|
|
2764
|
-
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2$1.DialogService }] });
|
|
2765
|
-
|
|
2766
2879
|
/**
|
|
2767
2880
|
* 🔑 `gve-snapshot-text-editor`
|
|
2768
2881
|
*
|
|
@@ -2778,11 +2891,7 @@ class SnapshotTextEditorComponent {
|
|
|
2778
2891
|
dialogRef, data) {
|
|
2779
2892
|
this.dialogRef = dialogRef;
|
|
2780
2893
|
this.data = data;
|
|
2781
|
-
this.text = model([]);
|
|
2782
|
-
/**
|
|
2783
|
-
* Emitted when text changes.
|
|
2784
|
-
*/
|
|
2785
|
-
this.textChange = output();
|
|
2894
|
+
this.text = model([], ...(ngDevMode ? [{ debugName: "text" }] : []));
|
|
2786
2895
|
this.userText = formBuilder.control('', {
|
|
2787
2896
|
nonNullable: true,
|
|
2788
2897
|
validators: [Validators.required, Validators.maxLength(5000)],
|
|
@@ -2817,13 +2926,12 @@ class SnapshotTextEditorComponent {
|
|
|
2817
2926
|
return;
|
|
2818
2927
|
}
|
|
2819
2928
|
this.text.set(SnapshotViewService.stringToBaseChars(this.userText.value));
|
|
2820
|
-
this.textChange.emit(this.text());
|
|
2821
2929
|
this.dialogRef?.close(this.text());
|
|
2822
2930
|
}
|
|
2823
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2824
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2931
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SnapshotTextEditorComponent, deps: [{ token: i1.FormBuilder }, { token: i3$2.MatDialogRef, optional: true }, { token: MAT_DIALOG_DATA, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2932
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: SnapshotTextEditorComponent, isStandalone: true, selector: "gve-snapshot-text-editor", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { text: "textChange" }, ngImport: i0, template: "<div [style.padding]=\"dialogRef ? '8px' : '0'\">\r\n @if (dialogRef) {\r\n <div id=\"heading\">\r\n <h2>Set Base Text</h2>\r\n </div>\r\n }\r\n <form [formGroup]=\"form\" (submit)=\"save()\">\r\n <fieldset>\r\n <div id=\"batch-input\">\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>base text</mat-label>\r\n <textarea matInput [formControl]=\"userText\" rows=\"8\"></textarea>\r\n @if ($any(userText).errors?.required && (userText.dirty ||\r\n userText.touched)) {\r\n <mat-error>text required</mat-error>\r\n } @if ($any(userText).errors?.maxLength && (userText.dirty ||\r\n userText.touched)) {\r\n <mat-error>text too long</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n <div class=\"form-row-center\">\r\n @if (dialogRef) {\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Close dialog\"\r\n (click)=\"close()\"\r\n >\r\n close\r\n </button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Set base text\"\r\n [disabled]=\"form.invalid\"\r\n (click)=\"save()\"\r\n >\r\n set\r\n </button>\r\n </div>\r\n </fieldset>\r\n </form>\r\n</div>\r\n", styles: [".full-width{width:100%}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}div#heading{margin:8px;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }] }); }
|
|
2825
2933
|
}
|
|
2826
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2934
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SnapshotTextEditorComponent, decorators: [{
|
|
2827
2935
|
type: Component,
|
|
2828
2936
|
args: [{ selector: 'gve-snapshot-text-editor', imports: [
|
|
2829
2937
|
ReactiveFormsModule,
|
|
@@ -2832,7 +2940,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
2832
2940
|
MatIconModule,
|
|
2833
2941
|
MatInputModule,
|
|
2834
2942
|
], template: "<div [style.padding]=\"dialogRef ? '8px' : '0'\">\r\n @if (dialogRef) {\r\n <div id=\"heading\">\r\n <h2>Set Base Text</h2>\r\n </div>\r\n }\r\n <form [formGroup]=\"form\" (submit)=\"save()\">\r\n <fieldset>\r\n <div id=\"batch-input\">\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>base text</mat-label>\r\n <textarea matInput [formControl]=\"userText\" rows=\"8\"></textarea>\r\n @if ($any(userText).errors?.required && (userText.dirty ||\r\n userText.touched)) {\r\n <mat-error>text required</mat-error>\r\n } @if ($any(userText).errors?.maxLength && (userText.dirty ||\r\n userText.touched)) {\r\n <mat-error>text too long</mat-error>\r\n }\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n <div class=\"form-row-center\">\r\n @if (dialogRef) {\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Close dialog\"\r\n (click)=\"close()\"\r\n >\r\n close\r\n </button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Set base text\"\r\n [disabled]=\"form.invalid\"\r\n (click)=\"save()\"\r\n >\r\n set\r\n </button>\r\n </div>\r\n </fieldset>\r\n </form>\r\n</div>\r\n", styles: [".full-width{width:100%}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}div#heading{margin:8px;text-align:center}\n"] }]
|
|
2835
|
-
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i3$
|
|
2943
|
+
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i3$2.MatDialogRef, decorators: [{
|
|
2836
2944
|
type: Optional
|
|
2837
2945
|
}] }, { type: undefined, decorators: [{
|
|
2838
2946
|
type: Optional
|
|
@@ -2867,34 +2975,54 @@ class SnapshotEditorComponent {
|
|
|
2867
2975
|
/**
|
|
2868
2976
|
* The snapshot to edit.
|
|
2869
2977
|
*/
|
|
2870
|
-
this.snapshot = model();
|
|
2978
|
+
this.snapshot = model(...(ngDevMode ? [undefined, { debugName: "snapshot" }] : []));
|
|
2871
2979
|
/**
|
|
2872
2980
|
* The batch operations text to set for the editor.
|
|
2873
2981
|
*/
|
|
2874
|
-
this.batchOps = input();
|
|
2982
|
+
this.batchOps = input(...(ngDevMode ? [undefined, { debugName: "batchOps" }] : []));
|
|
2875
2983
|
/**
|
|
2876
2984
|
* True to disable saving.
|
|
2877
2985
|
*/
|
|
2878
|
-
this.noSave = input();
|
|
2986
|
+
this.noSave = input(...(ngDevMode ? [undefined, { debugName: "noSave" }] : []));
|
|
2879
2987
|
/**
|
|
2880
2988
|
* True to enable debug mode for view rendition.
|
|
2881
2989
|
*/
|
|
2882
|
-
this.debug = input();
|
|
2990
|
+
this.debug = input(...(ngDevMode ? [undefined, { debugName: "debug" }] : []));
|
|
2883
2991
|
/**
|
|
2884
|
-
*
|
|
2992
|
+
* True to not show character decoration according to the trace
|
|
2993
|
+
* features in nodes.
|
|
2885
2994
|
*/
|
|
2886
|
-
this.
|
|
2995
|
+
this.noDecoration = input(...(ngDevMode ? [undefined, { debugName: "noDecoration" }] : []));
|
|
2996
|
+
/**
|
|
2997
|
+
* Definitions for features, including names and values.
|
|
2998
|
+
*/
|
|
2999
|
+
this.featureDefs = input(...(ngDevMode ? [undefined, { debugName: "featureDefs" }] : []));
|
|
3000
|
+
/**
|
|
3001
|
+
* Definitions for element features, including names and values.
|
|
3002
|
+
*/
|
|
3003
|
+
this.elementFeatureDefs = input(...(ngDevMode ? [undefined, { debugName: "elementFeatureDefs" }] : []));
|
|
3004
|
+
/**
|
|
3005
|
+
* Definitions for diplomatic features, including names and values.
|
|
3006
|
+
*/
|
|
3007
|
+
this.diplomaticFeatureDefs = input(...(ngDevMode ? [undefined, { debugName: "diplomaticFeatureDefs" }] : []));
|
|
2887
3008
|
/**
|
|
2888
3009
|
* Emitted when the user cancels the snapshot editing.
|
|
2889
3010
|
*/
|
|
2890
3011
|
this.snapshotCancel = output();
|
|
3012
|
+
this.showChain = new FormControl(false, { nonNullable: true });
|
|
3013
|
+
this.chain = signal(undefined, ...(ngDevMode ? [{ debugName: "chain" }] : []));
|
|
2891
3014
|
// list of operations output tags
|
|
2892
|
-
this.opTags = [];
|
|
3015
|
+
this.opTags = signal([], ...(ngDevMode ? [{ debugName: "opTags" }] : []));
|
|
2893
3016
|
// list of operation diplomatic.g element IDs
|
|
2894
|
-
this.opElementIds = [];
|
|
3017
|
+
this.opElementIds = signal([], ...(ngDevMode ? [{ debugName: "opElementIds" }] : []));
|
|
3018
|
+
// the currently picked base text range
|
|
3019
|
+
this.textRange = signal(undefined, ...(ngDevMode ? [{ debugName: "textRange" }] : []));
|
|
2895
3020
|
// the lines count for the current base text
|
|
2896
|
-
this.lineCount = 0;
|
|
2897
|
-
|
|
3021
|
+
this.lineCount = signal(0, ...(ngDevMode ? [{ debugName: "lineCount" }] : []));
|
|
3022
|
+
// the currently edited operation
|
|
3023
|
+
this.editedOp = signal(undefined, ...(ngDevMode ? [{ debugName: "editedOp" }] : []));
|
|
3024
|
+
this.editedOpIndex = signal(-1, ...(ngDevMode ? [{ debugName: "editedOpIndex" }] : []));
|
|
3025
|
+
this.busy = signal(false, ...(ngDevMode ? [{ debugName: "busy" }] : []));
|
|
2898
3026
|
this.opTypeMap = {
|
|
2899
3027
|
0: 'replace',
|
|
2900
3028
|
1: 'delete',
|
|
@@ -2909,7 +3037,6 @@ class SnapshotEditorComponent {
|
|
|
2909
3037
|
this.viewTitle = VIEW_TITLE;
|
|
2910
3038
|
this.rulers = true;
|
|
2911
3039
|
this.initialStepIndex = -1;
|
|
2912
|
-
this.showChain = new FormControl(false, { nonNullable: true });
|
|
2913
3040
|
// general
|
|
2914
3041
|
this.width = new FormControl(800, { nonNullable: true });
|
|
2915
3042
|
this.height = new FormControl(600, { nonNullable: true });
|
|
@@ -3053,7 +3180,7 @@ class SnapshotEditorComponent {
|
|
|
3053
3180
|
}
|
|
3054
3181
|
// #region base text
|
|
3055
3182
|
inputBaseText() {
|
|
3056
|
-
if (this.busy) {
|
|
3183
|
+
if (this.busy()) {
|
|
3057
3184
|
return;
|
|
3058
3185
|
}
|
|
3059
3186
|
const dialogRef = this._dialog.open(SnapshotTextEditorComponent, {
|
|
@@ -3066,7 +3193,7 @@ class SnapshotEditorComponent {
|
|
|
3066
3193
|
this.baseText.setValue(text);
|
|
3067
3194
|
this.baseText.updateValueAndValidity();
|
|
3068
3195
|
this.baseText.markAsDirty();
|
|
3069
|
-
this.textRange
|
|
3196
|
+
this.textRange.set(undefined);
|
|
3070
3197
|
// update the line count
|
|
3071
3198
|
this.updateLineCount(text);
|
|
3072
3199
|
// remove all operations and update the view data
|
|
@@ -3082,10 +3209,10 @@ class SnapshotEditorComponent {
|
|
|
3082
3209
|
*/
|
|
3083
3210
|
updateLineCount(text) {
|
|
3084
3211
|
if (!text.length) {
|
|
3085
|
-
this.lineCount
|
|
3212
|
+
this.lineCount.set(0);
|
|
3086
3213
|
}
|
|
3087
3214
|
else {
|
|
3088
|
-
this.lineCount
|
|
3215
|
+
this.lineCount.set(text.filter((c) => c.data === '\n').length + 1);
|
|
3089
3216
|
}
|
|
3090
3217
|
}
|
|
3091
3218
|
/**
|
|
@@ -3093,7 +3220,7 @@ class SnapshotEditorComponent {
|
|
|
3093
3220
|
* @param range The picked range.
|
|
3094
3221
|
*/
|
|
3095
3222
|
onRangePick(range) {
|
|
3096
|
-
this.textRange
|
|
3223
|
+
this.textRange.set(range);
|
|
3097
3224
|
}
|
|
3098
3225
|
// #endregion
|
|
3099
3226
|
// #region operations
|
|
@@ -3115,36 +3242,36 @@ class SnapshotEditorComponent {
|
|
|
3115
3242
|
this.parseSvgIds(op.diplomatics.g)?.forEach((id) => ids.add(id));
|
|
3116
3243
|
}
|
|
3117
3244
|
}
|
|
3118
|
-
this.opTags
|
|
3119
|
-
this.opElementIds
|
|
3245
|
+
this.opTags.set([...tags]);
|
|
3246
|
+
this.opElementIds.set([...ids]);
|
|
3120
3247
|
}
|
|
3121
3248
|
/**
|
|
3122
3249
|
* Edit a new operation.
|
|
3123
3250
|
*/
|
|
3124
3251
|
editNewOperation() {
|
|
3125
3252
|
// create a new operation and edit it
|
|
3126
|
-
this.editedOp
|
|
3253
|
+
this.editedOp.set({
|
|
3127
3254
|
id: this._nanoid(),
|
|
3128
3255
|
type: 0,
|
|
3129
|
-
at: this.textRange?.at || 0,
|
|
3130
|
-
run: this.textRange?.run || 1,
|
|
3131
|
-
};
|
|
3132
|
-
this.editedOpIndex
|
|
3256
|
+
at: this.textRange()?.at || 0,
|
|
3257
|
+
run: this.textRange()?.run || 1,
|
|
3258
|
+
});
|
|
3259
|
+
this.editedOpIndex.set(-1);
|
|
3133
3260
|
}
|
|
3134
3261
|
/**
|
|
3135
3262
|
* Edit (a copy of) the operation at the specified index.
|
|
3136
3263
|
* @param index The operation index.
|
|
3137
3264
|
*/
|
|
3138
3265
|
editOperation(index) {
|
|
3139
|
-
this.editedOpIndex
|
|
3140
|
-
this.editedOp
|
|
3266
|
+
this.editedOpIndex.set(index);
|
|
3267
|
+
this.editedOp.set(deepCopy(this.operations.value[index]));
|
|
3141
3268
|
}
|
|
3142
3269
|
/**
|
|
3143
3270
|
* Close the currently edited operation.
|
|
3144
3271
|
*/
|
|
3145
3272
|
closeEditedOperation() {
|
|
3146
|
-
this.editedOpIndex
|
|
3147
|
-
this.editedOp
|
|
3273
|
+
this.editedOpIndex.set(-1);
|
|
3274
|
+
this.editedOp.set(undefined);
|
|
3148
3275
|
}
|
|
3149
3276
|
/**
|
|
3150
3277
|
* Handle the event fired by the operation editor to cancel
|
|
@@ -3166,9 +3293,9 @@ class SnapshotEditorComponent {
|
|
|
3166
3293
|
console.log('operation change');
|
|
3167
3294
|
const operations = [...this.operations.value];
|
|
3168
3295
|
// replace or add the operation
|
|
3169
|
-
let i = this.editedOpIndex;
|
|
3170
|
-
if (this.editedOpIndex > -1) {
|
|
3171
|
-
operations.splice(this.editedOpIndex, 1, op);
|
|
3296
|
+
let i = this.editedOpIndex();
|
|
3297
|
+
if (this.editedOpIndex() > -1) {
|
|
3298
|
+
operations.splice(this.editedOpIndex(), 1, op);
|
|
3172
3299
|
}
|
|
3173
3300
|
else {
|
|
3174
3301
|
operations.push(op);
|
|
@@ -3195,7 +3322,7 @@ class SnapshotEditorComponent {
|
|
|
3195
3322
|
.subscribe((yes) => {
|
|
3196
3323
|
if (yes) {
|
|
3197
3324
|
// close the edited operation if it is the one being deleted
|
|
3198
|
-
if (this.editedOpIndex === index) {
|
|
3325
|
+
if (this.editedOpIndex() === index) {
|
|
3199
3326
|
this.closeEditedOperation();
|
|
3200
3327
|
}
|
|
3201
3328
|
// reset the result operation ID if it is the one being deleted
|
|
@@ -3222,7 +3349,7 @@ class SnapshotEditorComponent {
|
|
|
3222
3349
|
* snapshot operations.
|
|
3223
3350
|
*/
|
|
3224
3351
|
parseOperations() {
|
|
3225
|
-
if (this.busy) {
|
|
3352
|
+
if (this.busy()) {
|
|
3226
3353
|
return;
|
|
3227
3354
|
}
|
|
3228
3355
|
const dialogRef = this._dialog.open(BatchOperationEditorComponent, {
|
|
@@ -3253,8 +3380,8 @@ class SnapshotEditorComponent {
|
|
|
3253
3380
|
this.operations.reset();
|
|
3254
3381
|
this.operations.markAsDirty();
|
|
3255
3382
|
this.operations.updateValueAndValidity();
|
|
3256
|
-
this.opTags
|
|
3257
|
-
this.opElementIds
|
|
3383
|
+
this.opTags.set([]);
|
|
3384
|
+
this.opElementIds.set([]);
|
|
3258
3385
|
this.setViewData();
|
|
3259
3386
|
this.result = undefined;
|
|
3260
3387
|
}
|
|
@@ -3360,7 +3487,7 @@ class SnapshotEditorComponent {
|
|
|
3360
3487
|
* @returns A promise that resolves to the execution result.
|
|
3361
3488
|
*/
|
|
3362
3489
|
runTo(index, lastOperation) {
|
|
3363
|
-
if (this.busy) {
|
|
3490
|
+
if (this.busy()) {
|
|
3364
3491
|
return;
|
|
3365
3492
|
}
|
|
3366
3493
|
console.log('run to: ' + index);
|
|
@@ -3388,7 +3515,7 @@ class SnapshotEditorComponent {
|
|
|
3388
3515
|
// them visible.
|
|
3389
3516
|
this._transparentIds = this.getTransparentIds(snapshot.operations[index].diplomatics?.g);
|
|
3390
3517
|
// run the operations
|
|
3391
|
-
this.busy
|
|
3518
|
+
this.busy.set(true);
|
|
3392
3519
|
this.initialStepIndex = index;
|
|
3393
3520
|
this._api
|
|
3394
3521
|
.runOperations(snapshot.text, snapshot.operations)
|
|
@@ -3430,7 +3557,7 @@ class SnapshotEditorComponent {
|
|
|
3430
3557
|
this._snackbar.open('Error running operations', 'OK');
|
|
3431
3558
|
},
|
|
3432
3559
|
complete: () => {
|
|
3433
|
-
this.busy
|
|
3560
|
+
this.busy.set(false);
|
|
3434
3561
|
},
|
|
3435
3562
|
});
|
|
3436
3563
|
}
|
|
@@ -3464,7 +3591,7 @@ class SnapshotEditorComponent {
|
|
|
3464
3591
|
lastOperation = snapshot.operations[index];
|
|
3465
3592
|
snapshot.operations = snapshot.operations.slice(0, index + 1);
|
|
3466
3593
|
}
|
|
3467
|
-
this.busy
|
|
3594
|
+
this.busy.set(true);
|
|
3468
3595
|
this._api
|
|
3469
3596
|
.getChain(snapshot.text, snapshot.operations)
|
|
3470
3597
|
.subscribe({
|
|
@@ -3472,10 +3599,10 @@ class SnapshotEditorComponent {
|
|
|
3472
3599
|
// handle operation (non-fatal) error or result
|
|
3473
3600
|
if (wrapper.error) {
|
|
3474
3601
|
this._snackbar.open(wrapper.error, 'OK');
|
|
3475
|
-
this.chain
|
|
3602
|
+
this.chain.set(undefined);
|
|
3476
3603
|
}
|
|
3477
3604
|
else {
|
|
3478
|
-
this.chain
|
|
3605
|
+
this.chain.set(wrapper.result);
|
|
3479
3606
|
}
|
|
3480
3607
|
},
|
|
3481
3608
|
error: (error) => {
|
|
@@ -3484,7 +3611,7 @@ class SnapshotEditorComponent {
|
|
|
3484
3611
|
this._snackbar.open('Error running operations', 'OK');
|
|
3485
3612
|
},
|
|
3486
3613
|
complete: () => {
|
|
3487
|
-
this.busy
|
|
3614
|
+
this.busy.set(false);
|
|
3488
3615
|
},
|
|
3489
3616
|
});
|
|
3490
3617
|
}
|
|
@@ -3496,12 +3623,12 @@ class SnapshotEditorComponent {
|
|
|
3496
3623
|
*/
|
|
3497
3624
|
onOperationPreview(operation) {
|
|
3498
3625
|
// no multiple previews or previewing a new operation
|
|
3499
|
-
if (this._previewing || this.editedOpIndex < 0) {
|
|
3626
|
+
if (this._previewing || this.editedOpIndex() < 0) {
|
|
3500
3627
|
return;
|
|
3501
3628
|
}
|
|
3502
3629
|
this._previewing = true;
|
|
3503
3630
|
setTimeout(() => {
|
|
3504
|
-
this.runTo(this.editedOpIndex, operation);
|
|
3631
|
+
this.runTo(this.editedOpIndex(), operation);
|
|
3505
3632
|
this._previewing = false;
|
|
3506
3633
|
}, 0);
|
|
3507
3634
|
}
|
|
@@ -3674,6 +3801,25 @@ class SnapshotEditorComponent {
|
|
|
3674
3801
|
}
|
|
3675
3802
|
this.rulers = this._renderer.toggleRulers();
|
|
3676
3803
|
}
|
|
3804
|
+
defaultCharDecorator(char, lineNumber, x, y) {
|
|
3805
|
+
const features = char.features;
|
|
3806
|
+
const segOut = features?.find((f) => f.name === '$seg-out');
|
|
3807
|
+
const seg2Out = features?.find((f) => f.name === '$seg2-out');
|
|
3808
|
+
const segIn = features?.find((f) => f.name === '$seg-in');
|
|
3809
|
+
const seg2In = features?.find((f) => f.name === '$seg2-in');
|
|
3810
|
+
if (!segOut && !seg2Out && !segIn && !seg2In) {
|
|
3811
|
+
return null;
|
|
3812
|
+
}
|
|
3813
|
+
const decoration = {};
|
|
3814
|
+
if (segOut || seg2Out) {
|
|
3815
|
+
decoration.fill = segOut ? '#9B2915' : '#9B6F91';
|
|
3816
|
+
}
|
|
3817
|
+
// if (segIn || seg2In) {
|
|
3818
|
+
// decoration.stroke = segIn ? '#E9B44C' : '#DF928E';
|
|
3819
|
+
// decoration.strokeWidth = 3;
|
|
3820
|
+
// }
|
|
3821
|
+
return decoration;
|
|
3822
|
+
}
|
|
3677
3823
|
/**
|
|
3678
3824
|
* Get a snapshot from the form data.
|
|
3679
3825
|
*
|
|
@@ -3704,6 +3850,10 @@ class SnapshotEditorComponent {
|
|
|
3704
3850
|
operations: [...this.operations.value],
|
|
3705
3851
|
opStyle: this.opStyle.value || undefined,
|
|
3706
3852
|
};
|
|
3853
|
+
// add char decoration unless opted out
|
|
3854
|
+
if (!this.noDecoration()) {
|
|
3855
|
+
snapshot.textOptions.charDecorator = this.defaultCharDecorator;
|
|
3856
|
+
}
|
|
3707
3857
|
// image
|
|
3708
3858
|
if (this.imageUrl.value) {
|
|
3709
3859
|
snapshot.image = {
|
|
@@ -3743,12 +3893,11 @@ class SnapshotEditorComponent {
|
|
|
3743
3893
|
return;
|
|
3744
3894
|
}
|
|
3745
3895
|
this.snapshot.set(this.getSnapshot());
|
|
3746
|
-
this.snapshotChange.emit(this.snapshot());
|
|
3747
3896
|
}
|
|
3748
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3749
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: SnapshotEditorComponent, isStandalone: true, selector: "gve-snapshot-editor", inputs: { snapshot: { classPropertyName: "snapshot", publicName: "snapshot", isSignal: true, isRequired: false, transformFunction: null }, batchOps: { classPropertyName: "batchOps", publicName: "batchOps", isSignal: true, isRequired: false, transformFunction: null }, noSave: { classPropertyName: "noSave", publicName: "noSave", isSignal: true, isRequired: false, transformFunction: null }, debug: { classPropertyName: "debug", publicName: "debug", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { snapshot: "snapshotChange", snapshotChange: "snapshotChange", snapshotCancel: "snapshotCancel" }, viewQueries: [{ propertyName: "snapshotView", first: true, predicate: ["snapshotView"], descendants: true }], ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <mat-tab-group>\r\n <!-- text -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>article</mat-icon> <span class=\"label\">text</span>\r\n </ng-template>\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>\r\n <mat-panel-title> base text </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <!-- base text -->\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"mat-warn\"\r\n matTooltip=\"Enter base text\"\r\n (click)=\"inputBaseText()\"\r\n [disabled]=\"busy\"\r\n >\r\n <mat-icon>edit</mat-icon> base text\r\n </button>\r\n\r\n @if (textRange) {\r\n <span id=\"text-range\">{{ textRange.at }}\u00D7{{ textRange.run }}</span>\r\n }\r\n </div>\r\n <!-- base text metadata -->\r\n <fieldset>\r\n <div class=\"form-row\">\r\n <!-- offsetX -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetX\"\r\n placeholder=\"X offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- offsetY -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetY\"\r\n placeholder=\"Y offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- lineHeightOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>ln h-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"lineHeightOffset\"\r\n placeholder=\"ln h-offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- charSpacingOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>char spacing</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"charSpacingOffset\"\r\n placeholder=\"char spacing\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- spcWidthOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>spc w-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"spcWidthOffset\"\r\n placeholder=\"spc w-offset\"\r\n />\r\n </mat-form-field>\r\n <!-- minLineHeights -->\r\n <div class=\"boxed\">\r\n <gve-ln-heights-editor\r\n [lineCount]=\"lineCount\"\r\n [heights]=\"lnHeights.value || undefined\"\r\n (heightsChange)=\"onHeightsChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n <!-- textStyle -->\r\n <div>\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>text style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"textStyle\"\r\n placeholder=\"text style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </fieldset>\r\n <!-- text characters -->\r\n <gve-base-text-view\r\n [text]=\"baseText.value\"\r\n [hasLineNumber]=\"true\"\r\n (rangePick)=\"onRangePick($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- operations -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>edit</mat-icon> <span class=\"label\">operations</span>\r\n </ng-template>\r\n\r\n <div id=\"snapshot-container\">\r\n <div id=\"general\">\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"width\"\r\n placeholder=\"width\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"height\"\r\n placeholder=\"height\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- chain -->\r\n <mat-checkbox [formControl]=\"showChain\">show chain</mat-checkbox>\r\n\r\n <div class=\"form-row right\">\r\n <!-- remove ops -->\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Remove all the operations\"\r\n [disabled]=\"!operations.value.length || busy\"\r\n (click)=\"clearOperations()\"\r\n >\r\n <mat-icon>delete_forever</mat-icon> clear\r\n </button>\r\n\r\n <!-- batch add ops -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n matTooltip=\"Add a batch of operations\"\r\n class=\"mat-primary\"\r\n [disabled]=\"busy\"\r\n (click)=\"parseOperations()\"\r\n >\r\n <mat-icon>post_add</mat-icon> batch\r\n </button>\r\n\r\n <!-- add op -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n class=\"mat-primary\"\r\n [disabled]=\"!baseText.value\"\r\n (click)=\"editNewOperation()\"\r\n >\r\n <mat-icon>add_circle</mat-icon> operation\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- ops -->\r\n <div id=\"ops\">\r\n <!-- operations list -->\r\n @if (operations.value.length) {\r\n <table id=\"list\">\r\n <thead>\r\n <tr>\r\n <th>nr.</th>\r\n <th></th>\r\n <th>ID</th>\r\n <th>type</th>\r\n <th>at</th>\r\n <th>run</th>\r\n <th>value</th>\r\n <th>itag</th>\r\n <th>otag</th>\r\n <th>gid</th>\r\n <th>feats</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (operation of operations.value; track operation.id; let\r\n index=$index) {\r\n <tr\r\n [ngClass]=\"{ selected: operation.id === resultOperationId }\"\r\n [ngClass]=\"{ edited: operation.id === editedOp?.id }\"\r\n >\r\n <td class=\"fit-width\">{{ index + 1 }}.</td>\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-primary\"\r\n (click)=\"editOperation(index)\"\r\n matTooltip=\"Edit operation\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-warn\"\r\n (click)=\"deleteOperation(index)\"\r\n matTooltip=\"Delete operation\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n <!-- run to -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-accent\"\r\n (click)=\"runTo(index)\"\r\n matTooltip=\"Run to this operation\"\r\n >\r\n <mat-icon class=\"mat-accent\">subscriptions</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ operation.id }}</td>\r\n <td>{{ operation.type | flatLookup : opTypeMap }}</td>\r\n <td>{{ operation.at }}</td>\r\n <td>{{ operation.run }}</td>\r\n <td>{{ operation.value }}</td>\r\n <td>{{ operation.inputTag }}</td>\r\n <td>{{ operation.outputTag }}</td>\r\n <td>{{ operation.groupId }}</td>\r\n <td>{{ operation.features?.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- operation editor -->\r\n <mat-expansion-panel [expanded]=\"editedOp\" [disabled]=\"!editedOp\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>operation {{ editedOp?.id }}</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <gve-chain-operation-editor\r\n [hidePreview]=\"editedOpIndex === -1\"\r\n [operation]=\"editedOp\"\r\n (operationCancel)=\"onOperationCancel()\"\r\n (operationChange)=\"onOperationChange($event)\"\r\n (operationPreview)=\"onOperationPreview($event)\"\r\n />\r\n </fieldset>\r\n </mat-expansion-panel>\r\n\r\n <!-- opStyle -->\r\n <div id=\"opStyle\">\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>operations style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"opStyle\"\r\n placeholder=\"operations style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- image -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>image</mat-icon> <span class=\"label\">image</span>\r\n </ng-template>\r\n\r\n <div id=\"image\">\r\n <div id=\"image-ctl\">\r\n <!-- url -->\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>URL</mat-label>\r\n <input matInput [formControl]=\"imageUrl\" />\r\n </mat-form-field>\r\n <div class=\"form-row\">\r\n <!-- x -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageX\"\r\n placeholder=\"X\"\r\n />\r\n </mat-form-field>\r\n <!-- y -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageY\"\r\n placeholder=\"Y\"\r\n />\r\n </mat-form-field>\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageWidth\"\r\n />\r\n </mat-form-field>\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageHeight\"\r\n />\r\n </mat-form-field>\r\n <!-- reset -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Reset image metadata\"\r\n (click)=\"resetImgMetadata()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </div>\r\n <div>\r\n <!-- image opacity -->\r\n <mat-slider\r\n min=\"0\"\r\n max=\"1\"\r\n step=\"0.01\"\r\n thumbLabel\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n matTooltip=\"Image opacity\"\r\n >\r\n <input\r\n matSliderThumb\r\n [value]=\"imageOpacity.value\"\r\n (valueChange)=\"onImageOpacityChange($event)\"\r\n />\r\n </mat-slider>\r\n <span id=\"opacity-value\">{{\r\n imageOpacity.value | number : \"1.2-2\"\r\n }}</span>\r\n </div>\r\n <!-- defs -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>defs</mat-label>\r\n <textarea matInput [formControl]=\"defs\" rows=\"3\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n <div id=\"image-view\">\r\n @if (imageUrl.value) {\r\n <img\r\n #imgElement\r\n alt=\"background\"\r\n [src]=\"imageUrl.value\"\r\n width=\"600\"\r\n (load)=\"onImageLoad(imgElement)\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- timelines -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>animation</mat-icon> <span class=\"label\">animation</span>\r\n </ng-template>\r\n\r\n <gve-animation-timeline-set\r\n [tags]=\"opTags\"\r\n [elementIds]=\"opElementIds\"\r\n [timelines]=\"timelines.value\"\r\n (timelinesChange)=\"onTimelinesChange($event)\"\r\n />\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- progress -->\r\n <div>\r\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"busy\" />\r\n </div>\r\n\r\n <!-- result -->\r\n @if (result) {\r\n <fieldset id=\"result\">\r\n <legend>result</legend>\r\n <gve-chain-result-view\r\n [result]=\"result\"\r\n [initialStepIndex]=\"initialStepIndex\"\r\n (stepPick)=\"onStepPick($event)\"\r\n />\r\n </fieldset>\r\n }\r\n\r\n <!-- snapshot view -->\r\n <fieldset id=\"preview\">\r\n <legend class=\"button-row\">\r\n <span>{{ viewTitle }}</span>\r\n </legend>\r\n <!-- snapshot view -->\r\n <gve-snapshot-view\r\n #snapshotView\r\n [debug]=\"debug()\"\r\n [data]=\"viewData\"\r\n (snapshotRender)=\"onSnapshotRender($any($event))\"\r\n (visualEvent)=\"onVisualEvent($any($event))\"\r\n />\r\n <div class=\"button-row\">\r\n <!-- toggle ruler -->\r\n <mat-button-toggle\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Toggle rulers\"\r\n [checked]=\"rulers\"\r\n (change)=\"toggleRulers()\"\r\n >\r\n <mat-icon class=\"mat-primary\">straighten</mat-icon>\r\n </mat-button-toggle>\r\n <!-- run to last -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"primary\"\r\n matTooltip=\"Refresh preview\"\r\n (click)=\"runToLast()\"\r\n >\r\n <mat-icon>refresh</mat-icon>\r\n </button>\r\n </div>\r\n @if (visualInfo) {\r\n <div id=\"visual-info\">{{ visualInfo }}</div>\r\n }\r\n </fieldset>\r\n\r\n <!-- chain view -->\r\n @if (chain) {\r\n <div id=\"chain-view\">\r\n <gve-chain-view [chain]=\"chain\" />\r\n </div>\r\n }\r\n\r\n <!--buttons -->\r\n <div class=\"form-row-center\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n close\r\n </button>\r\n @if (!noSave()) {\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save changes\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n }\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}.form-row .right{margin-left:auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}#text-range{margin:8px;border:1px solid silver;border-radius:6px;padding:6px}mat-expansion-panel{margin:8px 0}div#visual-info{font-size:95%;color:#909090;margin:8px}#list{margin:8px 0}#opStyle{margin-top:8px}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#c8d9eb}tr.edited{background-color:#f6f6e4}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:#909090}.error{color:red}.input-nr{width:6em}.full-width{width:100%}.code{font-family:Courier New,Courier,monospace}.boxed{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}span.label{margin-left:8px}gve-animation-timeline-set{margin:8px 0}div#image{display:grid;gap:8px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"image-ctl image-view\"}div#image-ctl{grid-area:image-ctl}div#image-view{grid-area:image-view}div#chain-view{margin-bottom:8px}@media only screen and (max-width: 959px){div#image{grid-template-columns:1fr;grid-template-areas:\"image-ctl\" \"image-view\"}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.DecimalPipe, name: "number" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "component", type: i8$1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i14.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatSliderModule }, { kind: "component", type: i15.MatSlider, selector: "mat-slider", inputs: ["disabled", "discrete", "showTickMarks", "min", "color", "disableRipple", "max", "step", "displayWith"], exportAs: ["matSlider"] }, { kind: "directive", type: i15.MatSliderThumb, selector: "input[matSliderThumb]", inputs: ["value"], outputs: ["valueChange", "dragStart", "dragEnd"], exportAs: ["matSliderThumb"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i16.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i16.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i16.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: ChainOperationEditorComponent, selector: "gve-chain-operation-editor", inputs: ["operation", "snapshot", "hidePreview"], outputs: ["operationChange", "operationPreview", "operationCancel"] }, { kind: "component", type: ChainResultViewComponent, selector: "gve-chain-result-view", inputs: ["result", "initialStepIndex"], outputs: ["stepPick"] }, { kind: "component", type: BaseTextViewComponent, selector: "gve-base-text-view", inputs: ["defaultColor", "defaultBorderColor", "selectionColor", "hasLineNumber", "text", "borderColorCallback"], outputs: ["charPick", "rangePick"] }, { kind: "component", type: LnHeightsEditorComponent, selector: "gve-ln-heights-editor", inputs: ["lineCount", "heights"], outputs: ["heightsChange"] }, { kind: "component", type: AnimationTimelineSetComponent, selector: "gve-animation-timeline-set", inputs: ["timelines", "elementIds", "tags"], outputs: ["timelinesChange", "timelinesCancel"] }, { kind: "pipe", type: FlatLookupPipe, name: "flatLookup" }, { kind: "component", type: ChainViewComponent, selector: "gve-chain-view", inputs: ["chain", "direction", "selectedTags"], outputs: ["selectedTagsChange"] }] }); }
|
|
3897
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SnapshotEditorComponent, deps: [{ token: i1.FormBuilder }, { token: GveApiService }, { token: i3$2.MatDialog }, { token: i4$2.DialogService }, { token: i4$3.MatSnackBar }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3898
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: SnapshotEditorComponent, isStandalone: true, selector: "gve-snapshot-editor", inputs: { snapshot: { classPropertyName: "snapshot", publicName: "snapshot", isSignal: true, isRequired: false, transformFunction: null }, batchOps: { classPropertyName: "batchOps", publicName: "batchOps", isSignal: true, isRequired: false, transformFunction: null }, noSave: { classPropertyName: "noSave", publicName: "noSave", isSignal: true, isRequired: false, transformFunction: null }, debug: { classPropertyName: "debug", publicName: "debug", isSignal: true, isRequired: false, transformFunction: null }, noDecoration: { classPropertyName: "noDecoration", publicName: "noDecoration", isSignal: true, isRequired: false, transformFunction: null }, featureDefs: { classPropertyName: "featureDefs", publicName: "featureDefs", isSignal: true, isRequired: false, transformFunction: null }, elementFeatureDefs: { classPropertyName: "elementFeatureDefs", publicName: "elementFeatureDefs", isSignal: true, isRequired: false, transformFunction: null }, diplomaticFeatureDefs: { classPropertyName: "diplomaticFeatureDefs", publicName: "diplomaticFeatureDefs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { snapshot: "snapshotChange", snapshotCancel: "snapshotCancel" }, viewQueries: [{ propertyName: "snapshotView", first: true, predicate: ["snapshotView"], descendants: true }], ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <mat-tab-group>\r\n <!-- text -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>article</mat-icon> <span class=\"label\">text</span>\r\n </ng-template>\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>\r\n <mat-panel-title> base text </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <!-- base text -->\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"mat-warn\"\r\n matTooltip=\"Enter base text\"\r\n (click)=\"inputBaseText()\"\r\n [disabled]=\"busy()\"\r\n >\r\n <mat-icon>edit</mat-icon> base text\r\n </button>\r\n\r\n @if (textRange()) {\r\n <span id=\"text-range\"\r\n >{{ textRange()!.at }}\u00D7{{ textRange()!.run }}</span\r\n >\r\n }\r\n </div>\r\n <!-- base text metadata -->\r\n <fieldset>\r\n <div class=\"form-row\">\r\n <!-- offsetX -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetX\"\r\n placeholder=\"X offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- offsetY -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetY\"\r\n placeholder=\"Y offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- lineHeightOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>ln h-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"lineHeightOffset\"\r\n placeholder=\"ln h-offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- charSpacingOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>char spacing</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"charSpacingOffset\"\r\n placeholder=\"char spacing\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- spcWidthOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>spc w-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"spcWidthOffset\"\r\n placeholder=\"spc w-offset\"\r\n />\r\n </mat-form-field>\r\n <!-- minLineHeights -->\r\n <div class=\"boxed\">\r\n <gve-ln-heights-editor\r\n [lineCount]=\"lineCount()\"\r\n [heights]=\"lnHeights.value || undefined\"\r\n (heightsChange)=\"onHeightsChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n <!-- textStyle -->\r\n <div>\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>text style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"textStyle\"\r\n placeholder=\"text style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </fieldset>\r\n <!-- text characters -->\r\n <gve-base-text-view\r\n [text]=\"baseText.value\"\r\n [hasLineNumber]=\"true\"\r\n (rangePick)=\"onRangePick($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- operations -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>edit</mat-icon> <span class=\"label\">operations</span>\r\n </ng-template>\r\n\r\n <div id=\"snapshot-container\">\r\n <div id=\"general\">\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"width\"\r\n placeholder=\"width\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"height\"\r\n placeholder=\"height\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- chain -->\r\n <mat-checkbox [formControl]=\"showChain\">show chain</mat-checkbox>\r\n\r\n <div class=\"form-row right\">\r\n <!-- remove ops -->\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Remove all the operations\"\r\n [disabled]=\"!operations.value.length || busy()\"\r\n (click)=\"clearOperations()\"\r\n >\r\n <mat-icon>delete_forever</mat-icon> clear\r\n </button>\r\n\r\n <!-- batch add ops -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n matTooltip=\"Add a batch of operations\"\r\n class=\"mat-primary\"\r\n [disabled]=\"busy()\"\r\n (click)=\"parseOperations()\"\r\n >\r\n <mat-icon>post_add</mat-icon> batch\r\n </button>\r\n\r\n <!-- add op -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n class=\"mat-primary\"\r\n [disabled]=\"!baseText.value\"\r\n (click)=\"editNewOperation()\"\r\n >\r\n <mat-icon>add_circle</mat-icon> operation\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- ops -->\r\n <div id=\"ops\">\r\n <!-- operations list -->\r\n @if (operations.value.length) {\r\n <table id=\"list\">\r\n <thead>\r\n <tr>\r\n <th>nr.</th>\r\n <th></th>\r\n <th>ID</th>\r\n <th>type</th>\r\n <th>at</th>\r\n <th>run</th>\r\n <th>value</th>\r\n <th>itag</th>\r\n <th>otag</th>\r\n <th>gid</th>\r\n <th>feats</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (operation of operations.value; track operation.id; let\r\n index=$index) {\r\n <tr\r\n [class.selected]=\"operation.id === resultOperationId\"\r\n [class.edited]=\"operation.id === editedOp()?.id\"\r\n >\r\n <td class=\"fit-width\">{{ index + 1 }}.</td>\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-primary\"\r\n (click)=\"editOperation(index)\"\r\n matTooltip=\"Edit operation\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-warn\"\r\n (click)=\"deleteOperation(index)\"\r\n matTooltip=\"Delete operation\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n <!-- run to -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-accent\"\r\n (click)=\"runTo(index)\"\r\n matTooltip=\"Run to this operation\"\r\n >\r\n <mat-icon class=\"mat-accent\">subscriptions</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ operation.id }}</td>\r\n <td>{{ operation.type | flatLookup : opTypeMap }}</td>\r\n <td>{{ operation.at }}</td>\r\n <td>{{ operation.run }}</td>\r\n <td>{{ operation.value }}</td>\r\n <td>{{ operation.inputTag }}</td>\r\n <td>{{ operation.outputTag }}</td>\r\n <td>{{ operation.groupId }}</td>\r\n <td>{{ operation.features?.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- operation editor -->\r\n @if (editedOp()) {\r\n <mat-expansion-panel [expanded]=\"editedOp()\" [disabled]=\"!editedOp()\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>operation {{ editedOp()?.id }}</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <gve-chain-operation-editor\r\n [featureDefs]=\"featureDefs()\"\r\n [elementFeatureDefs]=\"elementFeatureDefs()\"\r\n [diplomaticFeatureDefs]=\"diplomaticFeatureDefs()\"\r\n [hidePreview]=\"editedOpIndex() === -1\"\r\n [operation]=\"editedOp()\"\r\n (operationCancel)=\"onOperationCancel()\"\r\n (operationChange)=\"onOperationChange($event)\"\r\n (operationPreview)=\"onOperationPreview($event)\"\r\n />\r\n </fieldset>\r\n </mat-expansion-panel>\r\n }\r\n\r\n <!-- opStyle -->\r\n <div id=\"opStyle\">\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>operations style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"opStyle\"\r\n placeholder=\"operations style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- image -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>image</mat-icon> <span class=\"label\">image</span>\r\n </ng-template>\r\n\r\n <div id=\"image\">\r\n <div id=\"image-ctl\">\r\n <!-- url -->\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>URL</mat-label>\r\n <input matInput [formControl]=\"imageUrl\" />\r\n </mat-form-field>\r\n <div class=\"form-row\">\r\n <!-- x -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageX\"\r\n placeholder=\"X\"\r\n />\r\n </mat-form-field>\r\n <!-- y -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageY\"\r\n placeholder=\"Y\"\r\n />\r\n </mat-form-field>\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageWidth\"\r\n />\r\n </mat-form-field>\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageHeight\"\r\n />\r\n </mat-form-field>\r\n <!-- reset -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Reset image metadata\"\r\n (click)=\"resetImgMetadata()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </div>\r\n <div>\r\n <!-- image opacity -->\r\n <mat-slider\r\n min=\"0\"\r\n max=\"1\"\r\n step=\"0.01\"\r\n thumbLabel\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n matTooltip=\"Image opacity\"\r\n >\r\n <input\r\n matSliderThumb\r\n [value]=\"imageOpacity.value\"\r\n (valueChange)=\"onImageOpacityChange($event)\"\r\n />\r\n </mat-slider>\r\n <span id=\"opacity-value\">{{\r\n imageOpacity.value | number : \"1.2-2\"\r\n }}</span>\r\n </div>\r\n <!-- defs -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>defs</mat-label>\r\n <textarea matInput [formControl]=\"defs\" rows=\"3\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n <div id=\"image-view\">\r\n @if (imageUrl.value) {\r\n <img\r\n #imgElement\r\n alt=\"background\"\r\n [src]=\"imageUrl.value\"\r\n width=\"600\"\r\n (load)=\"onImageLoad(imgElement)\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- timelines -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>animation</mat-icon> <span class=\"label\">animation</span>\r\n </ng-template>\r\n\r\n <gve-animation-timeline-set\r\n [tags]=\"opTags()\"\r\n [elementIds]=\"opElementIds()\"\r\n [timelines]=\"timelines.value\"\r\n (timelinesChange)=\"onTimelinesChange($event)\"\r\n />\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- progress -->\r\n <div>\r\n @if (busy()) {\r\n <mat-progress-bar mode=\"indeterminate\" />\r\n }\r\n </div>\r\n\r\n <!-- result -->\r\n @if (result) {\r\n <fieldset id=\"result\">\r\n <legend>result</legend>\r\n <gve-chain-result-view\r\n [result]=\"result\"\r\n [initialStepIndex]=\"initialStepIndex\"\r\n (stepPick)=\"onStepPick($event)\"\r\n />\r\n </fieldset>\r\n }\r\n\r\n <!-- snapshot view -->\r\n <fieldset id=\"preview\">\r\n <legend class=\"button-row\">\r\n <span>{{ viewTitle }}</span>\r\n </legend>\r\n <!-- snapshot view -->\r\n <gve-snapshot-view\r\n #snapshotView\r\n [debug]=\"debug()\"\r\n [data]=\"viewData\"\r\n (snapshotRender)=\"onSnapshotRender($any($event))\"\r\n (visualEvent)=\"onVisualEvent($any($event))\"\r\n />\r\n <div class=\"button-row\">\r\n <!-- toggle ruler -->\r\n <mat-button-toggle\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Toggle rulers\"\r\n [checked]=\"rulers\"\r\n (change)=\"toggleRulers()\"\r\n >\r\n <mat-icon class=\"mat-primary\">straighten</mat-icon>\r\n </mat-button-toggle>\r\n <!-- run to last -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"primary\"\r\n matTooltip=\"Refresh preview\"\r\n (click)=\"runToLast()\"\r\n >\r\n <mat-icon>refresh</mat-icon>\r\n </button>\r\n </div>\r\n @if (visualInfo) {\r\n <div id=\"visual-info\">{{ visualInfo }}</div>\r\n }\r\n </fieldset>\r\n\r\n <!-- chain view -->\r\n @if (chain()) {\r\n <div id=\"chain-view\">\r\n <gve-chain-view [chain]=\"chain()\" />\r\n </div>\r\n }\r\n\r\n <!--buttons -->\r\n <div class=\"form-row-center\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n close\r\n </button>\r\n @if (!noSave()) {\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save changes\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n }\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}.form-row .right{margin-left:auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}#text-range{margin:8px;border:1px solid silver;border-radius:6px;padding:6px}mat-expansion-panel{margin:8px 0}div#visual-info{font-size:95%;color:#909090;margin:8px}#list{margin:8px 0}#opStyle{margin-top:8px}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#c8d9eb}tr.edited{background-color:#f6f6e4}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:#909090}.error{color:red}.input-nr{width:6em}.full-width{width:100%}.code{font-family:Courier New,Courier,monospace}.boxed{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}span.label{margin-left:8px}gve-animation-timeline-set{margin:8px 0}div#image{display:grid;gap:8px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"image-ctl image-view\"}div#image-ctl{grid-area:image-ctl}div#image-view{grid-area:image-view}div#chain-view{margin-bottom:8px}@media only screen and (max-width: 959px){div#image{grid-template-columns:1fr;grid-template-areas:\"image-ctl\" \"image-view\"}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "component", type: i7$1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i3$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i13.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatSliderModule }, { kind: "component", type: i14.MatSlider, selector: "mat-slider", inputs: ["disabled", "discrete", "showTickMarks", "min", "color", "disableRipple", "max", "step", "displayWith"], exportAs: ["matSlider"] }, { kind: "directive", type: i14.MatSliderThumb, selector: "input[matSliderThumb]", inputs: ["value"], outputs: ["valueChange", "dragStart", "dragEnd"], exportAs: ["matSliderThumb"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i15.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i15.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i15.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: ChainOperationEditorComponent, selector: "gve-chain-operation-editor", inputs: ["operation", "snapshot", "hidePreview", "featureDefs", "elementFeatureDefs", "diplomaticFeatureDefs"], outputs: ["operationChange", "operationPreview", "operationCancel"] }, { kind: "component", type: ChainResultViewComponent, selector: "gve-chain-result-view", inputs: ["result", "initialStepIndex"], outputs: ["stepPick"] }, { kind: "component", type: BaseTextViewComponent, selector: "gve-base-text-view", inputs: ["defaultColor", "defaultBorderColor", "selectionColor", "hasLineNumber", "text", "colorCallback", "borderColorCallback"], outputs: ["charPick", "rangePick"] }, { kind: "component", type: LnHeightsEditorComponent, selector: "gve-ln-heights-editor", inputs: ["lineCount", "heights"], outputs: ["heightsChange"] }, { kind: "component", type: AnimationTimelineSetComponent, selector: "gve-animation-timeline-set", inputs: ["timelines", "elementIds", "tags"], outputs: ["timelinesChange", "timelinesCancel"] }, { kind: "component", type: ChainViewComponent, selector: "gve-chain-view", inputs: ["chain", "direction", "selectedTags"], outputs: ["selectedTagsChange"] }, { kind: "pipe", type: i17.DecimalPipe, name: "number" }, { kind: "pipe", type: FlatLookupPipe, name: "flatLookup" }] }); }
|
|
3750
3899
|
}
|
|
3751
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3900
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SnapshotEditorComponent, decorators: [{
|
|
3752
3901
|
type: Component,
|
|
3753
3902
|
args: [{ selector: 'gve-snapshot-editor', imports: [
|
|
3754
3903
|
CommonModule,
|
|
@@ -3773,8 +3922,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
3773
3922
|
AnimationTimelineSetComponent,
|
|
3774
3923
|
FlatLookupPipe,
|
|
3775
3924
|
ChainViewComponent,
|
|
3776
|
-
], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <mat-tab-group>\r\n <!-- text -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>article</mat-icon> <span class=\"label\">text</span>\r\n </ng-template>\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>\r\n <mat-panel-title> base text </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <!-- base text -->\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"mat-warn\"\r\n matTooltip=\"Enter base text\"\r\n (click)=\"inputBaseText()\"\r\n [disabled]=\"busy\"\r\n >\r\n <mat-icon>edit</mat-icon> base text\r\n </button>\r\n\r\n @if (textRange) {\r\n <span id=\"text-range\">{{ textRange.at }}\u00D7{{ textRange.run }}</span>\r\n }\r\n </div>\r\n <!-- base text metadata -->\r\n <fieldset>\r\n <div class=\"form-row\">\r\n <!-- offsetX -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetX\"\r\n placeholder=\"X offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- offsetY -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetY\"\r\n placeholder=\"Y offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- lineHeightOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>ln h-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"lineHeightOffset\"\r\n placeholder=\"ln h-offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- charSpacingOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>char spacing</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"charSpacingOffset\"\r\n placeholder=\"char spacing\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- spcWidthOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>spc w-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"spcWidthOffset\"\r\n placeholder=\"spc w-offset\"\r\n />\r\n </mat-form-field>\r\n <!-- minLineHeights -->\r\n <div class=\"boxed\">\r\n <gve-ln-heights-editor\r\n [lineCount]=\"lineCount\"\r\n [heights]=\"lnHeights.value || undefined\"\r\n (heightsChange)=\"onHeightsChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n <!-- textStyle -->\r\n <div>\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>text style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"textStyle\"\r\n placeholder=\"text style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </fieldset>\r\n <!-- text characters -->\r\n <gve-base-text-view\r\n [text]=\"baseText.value\"\r\n [hasLineNumber]=\"true\"\r\n (rangePick)=\"onRangePick($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- operations -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>edit</mat-icon> <span class=\"label\">operations</span>\r\n </ng-template>\r\n\r\n <div id=\"snapshot-container\">\r\n <div id=\"general\">\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"width\"\r\n placeholder=\"width\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"height\"\r\n placeholder=\"height\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- chain -->\r\n <mat-checkbox [formControl]=\"showChain\">show chain</mat-checkbox>\r\n\r\n <div class=\"form-row right\">\r\n <!-- remove ops -->\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Remove all the operations\"\r\n [disabled]=\"!operations.value.length || busy\"\r\n (click)=\"clearOperations()\"\r\n >\r\n <mat-icon>delete_forever</mat-icon> clear\r\n </button>\r\n\r\n <!-- batch add ops -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n matTooltip=\"Add a batch of operations\"\r\n class=\"mat-primary\"\r\n [disabled]=\"busy\"\r\n (click)=\"parseOperations()\"\r\n >\r\n <mat-icon>post_add</mat-icon> batch\r\n </button>\r\n\r\n <!-- add op -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n class=\"mat-primary\"\r\n [disabled]=\"!baseText.value\"\r\n (click)=\"editNewOperation()\"\r\n >\r\n <mat-icon>add_circle</mat-icon> operation\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- ops -->\r\n <div id=\"ops\">\r\n <!-- operations list -->\r\n @if (operations.value.length) {\r\n <table id=\"list\">\r\n <thead>\r\n <tr>\r\n <th>nr.</th>\r\n <th></th>\r\n <th>ID</th>\r\n <th>type</th>\r\n <th>at</th>\r\n <th>run</th>\r\n <th>value</th>\r\n <th>itag</th>\r\n <th>otag</th>\r\n <th>gid</th>\r\n <th>feats</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (operation of operations.value; track operation.id; let\r\n index=$index) {\r\n <tr\r\n [ngClass]=\"{ selected: operation.id === resultOperationId }\"\r\n [ngClass]=\"{ edited: operation.id === editedOp?.id }\"\r\n >\r\n <td class=\"fit-width\">{{ index + 1 }}.</td>\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-primary\"\r\n (click)=\"editOperation(index)\"\r\n matTooltip=\"Edit operation\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-warn\"\r\n (click)=\"deleteOperation(index)\"\r\n matTooltip=\"Delete operation\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n <!-- run to -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-accent\"\r\n (click)=\"runTo(index)\"\r\n matTooltip=\"Run to this operation\"\r\n >\r\n <mat-icon class=\"mat-accent\">subscriptions</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ operation.id }}</td>\r\n <td>{{ operation.type | flatLookup : opTypeMap }}</td>\r\n <td>{{ operation.at }}</td>\r\n <td>{{ operation.run }}</td>\r\n <td>{{ operation.value }}</td>\r\n <td>{{ operation.inputTag }}</td>\r\n <td>{{ operation.outputTag }}</td>\r\n <td>{{ operation.groupId }}</td>\r\n <td>{{ operation.features?.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- operation editor -->\r\n <mat-expansion-panel [expanded]=\"editedOp\" [disabled]=\"!editedOp\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>operation {{ editedOp?.id }}</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <gve-chain-operation-editor\r\n [hidePreview]=\"editedOpIndex === -1\"\r\n [operation]=\"editedOp\"\r\n (operationCancel)=\"onOperationCancel()\"\r\n (operationChange)=\"onOperationChange($event)\"\r\n (operationPreview)=\"onOperationPreview($event)\"\r\n />\r\n </fieldset>\r\n </mat-expansion-panel>\r\n\r\n <!-- opStyle -->\r\n <div id=\"opStyle\">\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>operations style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"opStyle\"\r\n placeholder=\"operations style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- image -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>image</mat-icon> <span class=\"label\">image</span>\r\n </ng-template>\r\n\r\n <div id=\"image\">\r\n <div id=\"image-ctl\">\r\n <!-- url -->\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>URL</mat-label>\r\n <input matInput [formControl]=\"imageUrl\" />\r\n </mat-form-field>\r\n <div class=\"form-row\">\r\n <!-- x -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageX\"\r\n placeholder=\"X\"\r\n />\r\n </mat-form-field>\r\n <!-- y -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageY\"\r\n placeholder=\"Y\"\r\n />\r\n </mat-form-field>\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageWidth\"\r\n />\r\n </mat-form-field>\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageHeight\"\r\n />\r\n </mat-form-field>\r\n <!-- reset -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Reset image metadata\"\r\n (click)=\"resetImgMetadata()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </div>\r\n <div>\r\n <!-- image opacity -->\r\n <mat-slider\r\n min=\"0\"\r\n max=\"1\"\r\n step=\"0.01\"\r\n thumbLabel\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n matTooltip=\"Image opacity\"\r\n >\r\n <input\r\n matSliderThumb\r\n [value]=\"imageOpacity.value\"\r\n (valueChange)=\"onImageOpacityChange($event)\"\r\n />\r\n </mat-slider>\r\n <span id=\"opacity-value\">{{\r\n imageOpacity.value | number : \"1.2-2\"\r\n }}</span>\r\n </div>\r\n <!-- defs -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>defs</mat-label>\r\n <textarea matInput [formControl]=\"defs\" rows=\"3\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n <div id=\"image-view\">\r\n @if (imageUrl.value) {\r\n <img\r\n #imgElement\r\n alt=\"background\"\r\n [src]=\"imageUrl.value\"\r\n width=\"600\"\r\n (load)=\"onImageLoad(imgElement)\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- timelines -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>animation</mat-icon> <span class=\"label\">animation</span>\r\n </ng-template>\r\n\r\n <gve-animation-timeline-set\r\n [tags]=\"opTags\"\r\n [elementIds]=\"opElementIds\"\r\n [timelines]=\"timelines.value\"\r\n (timelinesChange)=\"onTimelinesChange($event)\"\r\n />\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- progress -->\r\n <div>\r\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"busy\" />\r\n </div>\r\n\r\n <!-- result -->\r\n @if (result) {\r\n <fieldset id=\"result\">\r\n <legend>result</legend>\r\n <gve-chain-result-view\r\n [result]=\"result\"\r\n [initialStepIndex]=\"initialStepIndex\"\r\n (stepPick)=\"onStepPick($event)\"\r\n />\r\n </fieldset>\r\n }\r\n\r\n <!-- snapshot view -->\r\n <fieldset id=\"preview\">\r\n <legend class=\"button-row\">\r\n <span>{{ viewTitle }}</span>\r\n </legend>\r\n <!-- snapshot view -->\r\n <gve-snapshot-view\r\n #snapshotView\r\n [debug]=\"debug()\"\r\n [data]=\"viewData\"\r\n (snapshotRender)=\"onSnapshotRender($any($event))\"\r\n (visualEvent)=\"onVisualEvent($any($event))\"\r\n />\r\n <div class=\"button-row\">\r\n <!-- toggle ruler -->\r\n <mat-button-toggle\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Toggle rulers\"\r\n [checked]=\"rulers\"\r\n (change)=\"toggleRulers()\"\r\n >\r\n <mat-icon class=\"mat-primary\">straighten</mat-icon>\r\n </mat-button-toggle>\r\n <!-- run to last -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"primary\"\r\n matTooltip=\"Refresh preview\"\r\n (click)=\"runToLast()\"\r\n >\r\n <mat-icon>refresh</mat-icon>\r\n </button>\r\n </div>\r\n @if (visualInfo) {\r\n <div id=\"visual-info\">{{ visualInfo }}</div>\r\n }\r\n </fieldset>\r\n\r\n <!-- chain view -->\r\n @if (chain) {\r\n <div id=\"chain-view\">\r\n <gve-chain-view [chain]=\"chain\" />\r\n </div>\r\n }\r\n\r\n <!--buttons -->\r\n <div class=\"form-row-center\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n close\r\n </button>\r\n @if (!noSave()) {\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save changes\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n }\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}.form-row .right{margin-left:auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}#text-range{margin:8px;border:1px solid silver;border-radius:6px;padding:6px}mat-expansion-panel{margin:8px 0}div#visual-info{font-size:95%;color:#909090;margin:8px}#list{margin:8px 0}#opStyle{margin-top:8px}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#c8d9eb}tr.edited{background-color:#f6f6e4}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:#909090}.error{color:red}.input-nr{width:6em}.full-width{width:100%}.code{font-family:Courier New,Courier,monospace}.boxed{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}span.label{margin-left:8px}gve-animation-timeline-set{margin:8px 0}div#image{display:grid;gap:8px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"image-ctl image-view\"}div#image-ctl{grid-area:image-ctl}div#image-view{grid-area:image-view}div#chain-view{margin-bottom:8px}@media only screen and (max-width: 959px){div#image{grid-template-columns:1fr;grid-template-areas:\"image-ctl\" \"image-view\"}}\n"] }]
|
|
3777
|
-
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: GveApiService }, { type: i3$
|
|
3925
|
+
], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <mat-tab-group>\r\n <!-- text -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>article</mat-icon> <span class=\"label\">text</span>\r\n </ng-template>\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>\r\n <mat-panel-title> base text </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <!-- base text -->\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"mat-warn\"\r\n matTooltip=\"Enter base text\"\r\n (click)=\"inputBaseText()\"\r\n [disabled]=\"busy()\"\r\n >\r\n <mat-icon>edit</mat-icon> base text\r\n </button>\r\n\r\n @if (textRange()) {\r\n <span id=\"text-range\"\r\n >{{ textRange()!.at }}\u00D7{{ textRange()!.run }}</span\r\n >\r\n }\r\n </div>\r\n <!-- base text metadata -->\r\n <fieldset>\r\n <div class=\"form-row\">\r\n <!-- offsetX -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetX\"\r\n placeholder=\"X offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- offsetY -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetY\"\r\n placeholder=\"Y offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- lineHeightOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>ln h-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"lineHeightOffset\"\r\n placeholder=\"ln h-offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- charSpacingOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>char spacing</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"charSpacingOffset\"\r\n placeholder=\"char spacing\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- spcWidthOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>spc w-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"spcWidthOffset\"\r\n placeholder=\"spc w-offset\"\r\n />\r\n </mat-form-field>\r\n <!-- minLineHeights -->\r\n <div class=\"boxed\">\r\n <gve-ln-heights-editor\r\n [lineCount]=\"lineCount()\"\r\n [heights]=\"lnHeights.value || undefined\"\r\n (heightsChange)=\"onHeightsChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n <!-- textStyle -->\r\n <div>\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>text style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"textStyle\"\r\n placeholder=\"text style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </fieldset>\r\n <!-- text characters -->\r\n <gve-base-text-view\r\n [text]=\"baseText.value\"\r\n [hasLineNumber]=\"true\"\r\n (rangePick)=\"onRangePick($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- operations -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>edit</mat-icon> <span class=\"label\">operations</span>\r\n </ng-template>\r\n\r\n <div id=\"snapshot-container\">\r\n <div id=\"general\">\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"width\"\r\n placeholder=\"width\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"height\"\r\n placeholder=\"height\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- chain -->\r\n <mat-checkbox [formControl]=\"showChain\">show chain</mat-checkbox>\r\n\r\n <div class=\"form-row right\">\r\n <!-- remove ops -->\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Remove all the operations\"\r\n [disabled]=\"!operations.value.length || busy()\"\r\n (click)=\"clearOperations()\"\r\n >\r\n <mat-icon>delete_forever</mat-icon> clear\r\n </button>\r\n\r\n <!-- batch add ops -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n matTooltip=\"Add a batch of operations\"\r\n class=\"mat-primary\"\r\n [disabled]=\"busy()\"\r\n (click)=\"parseOperations()\"\r\n >\r\n <mat-icon>post_add</mat-icon> batch\r\n </button>\r\n\r\n <!-- add op -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n class=\"mat-primary\"\r\n [disabled]=\"!baseText.value\"\r\n (click)=\"editNewOperation()\"\r\n >\r\n <mat-icon>add_circle</mat-icon> operation\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- ops -->\r\n <div id=\"ops\">\r\n <!-- operations list -->\r\n @if (operations.value.length) {\r\n <table id=\"list\">\r\n <thead>\r\n <tr>\r\n <th>nr.</th>\r\n <th></th>\r\n <th>ID</th>\r\n <th>type</th>\r\n <th>at</th>\r\n <th>run</th>\r\n <th>value</th>\r\n <th>itag</th>\r\n <th>otag</th>\r\n <th>gid</th>\r\n <th>feats</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (operation of operations.value; track operation.id; let\r\n index=$index) {\r\n <tr\r\n [class.selected]=\"operation.id === resultOperationId\"\r\n [class.edited]=\"operation.id === editedOp()?.id\"\r\n >\r\n <td class=\"fit-width\">{{ index + 1 }}.</td>\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-primary\"\r\n (click)=\"editOperation(index)\"\r\n matTooltip=\"Edit operation\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-warn\"\r\n (click)=\"deleteOperation(index)\"\r\n matTooltip=\"Delete operation\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n <!-- run to -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-accent\"\r\n (click)=\"runTo(index)\"\r\n matTooltip=\"Run to this operation\"\r\n >\r\n <mat-icon class=\"mat-accent\">subscriptions</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ operation.id }}</td>\r\n <td>{{ operation.type | flatLookup : opTypeMap }}</td>\r\n <td>{{ operation.at }}</td>\r\n <td>{{ operation.run }}</td>\r\n <td>{{ operation.value }}</td>\r\n <td>{{ operation.inputTag }}</td>\r\n <td>{{ operation.outputTag }}</td>\r\n <td>{{ operation.groupId }}</td>\r\n <td>{{ operation.features?.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- operation editor -->\r\n @if (editedOp()) {\r\n <mat-expansion-panel [expanded]=\"editedOp()\" [disabled]=\"!editedOp()\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>operation {{ editedOp()?.id }}</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <gve-chain-operation-editor\r\n [featureDefs]=\"featureDefs()\"\r\n [elementFeatureDefs]=\"elementFeatureDefs()\"\r\n [diplomaticFeatureDefs]=\"diplomaticFeatureDefs()\"\r\n [hidePreview]=\"editedOpIndex() === -1\"\r\n [operation]=\"editedOp()\"\r\n (operationCancel)=\"onOperationCancel()\"\r\n (operationChange)=\"onOperationChange($event)\"\r\n (operationPreview)=\"onOperationPreview($event)\"\r\n />\r\n </fieldset>\r\n </mat-expansion-panel>\r\n }\r\n\r\n <!-- opStyle -->\r\n <div id=\"opStyle\">\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>operations style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"opStyle\"\r\n placeholder=\"operations style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- image -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>image</mat-icon> <span class=\"label\">image</span>\r\n </ng-template>\r\n\r\n <div id=\"image\">\r\n <div id=\"image-ctl\">\r\n <!-- url -->\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>URL</mat-label>\r\n <input matInput [formControl]=\"imageUrl\" />\r\n </mat-form-field>\r\n <div class=\"form-row\">\r\n <!-- x -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageX\"\r\n placeholder=\"X\"\r\n />\r\n </mat-form-field>\r\n <!-- y -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageY\"\r\n placeholder=\"Y\"\r\n />\r\n </mat-form-field>\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageWidth\"\r\n />\r\n </mat-form-field>\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageHeight\"\r\n />\r\n </mat-form-field>\r\n <!-- reset -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Reset image metadata\"\r\n (click)=\"resetImgMetadata()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n </div>\r\n <div>\r\n <!-- image opacity -->\r\n <mat-slider\r\n min=\"0\"\r\n max=\"1\"\r\n step=\"0.01\"\r\n thumbLabel\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n matTooltip=\"Image opacity\"\r\n >\r\n <input\r\n matSliderThumb\r\n [value]=\"imageOpacity.value\"\r\n (valueChange)=\"onImageOpacityChange($event)\"\r\n />\r\n </mat-slider>\r\n <span id=\"opacity-value\">{{\r\n imageOpacity.value | number : \"1.2-2\"\r\n }}</span>\r\n </div>\r\n <!-- defs -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>defs</mat-label>\r\n <textarea matInput [formControl]=\"defs\" rows=\"3\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n <div id=\"image-view\">\r\n @if (imageUrl.value) {\r\n <img\r\n #imgElement\r\n alt=\"background\"\r\n [src]=\"imageUrl.value\"\r\n width=\"600\"\r\n (load)=\"onImageLoad(imgElement)\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- timelines -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>animation</mat-icon> <span class=\"label\">animation</span>\r\n </ng-template>\r\n\r\n <gve-animation-timeline-set\r\n [tags]=\"opTags()\"\r\n [elementIds]=\"opElementIds()\"\r\n [timelines]=\"timelines.value\"\r\n (timelinesChange)=\"onTimelinesChange($event)\"\r\n />\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- progress -->\r\n <div>\r\n @if (busy()) {\r\n <mat-progress-bar mode=\"indeterminate\" />\r\n }\r\n </div>\r\n\r\n <!-- result -->\r\n @if (result) {\r\n <fieldset id=\"result\">\r\n <legend>result</legend>\r\n <gve-chain-result-view\r\n [result]=\"result\"\r\n [initialStepIndex]=\"initialStepIndex\"\r\n (stepPick)=\"onStepPick($event)\"\r\n />\r\n </fieldset>\r\n }\r\n\r\n <!-- snapshot view -->\r\n <fieldset id=\"preview\">\r\n <legend class=\"button-row\">\r\n <span>{{ viewTitle }}</span>\r\n </legend>\r\n <!-- snapshot view -->\r\n <gve-snapshot-view\r\n #snapshotView\r\n [debug]=\"debug()\"\r\n [data]=\"viewData\"\r\n (snapshotRender)=\"onSnapshotRender($any($event))\"\r\n (visualEvent)=\"onVisualEvent($any($event))\"\r\n />\r\n <div class=\"button-row\">\r\n <!-- toggle ruler -->\r\n <mat-button-toggle\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Toggle rulers\"\r\n [checked]=\"rulers\"\r\n (change)=\"toggleRulers()\"\r\n >\r\n <mat-icon class=\"mat-primary\">straighten</mat-icon>\r\n </mat-button-toggle>\r\n <!-- run to last -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"primary\"\r\n matTooltip=\"Refresh preview\"\r\n (click)=\"runToLast()\"\r\n >\r\n <mat-icon>refresh</mat-icon>\r\n </button>\r\n </div>\r\n @if (visualInfo) {\r\n <div id=\"visual-info\">{{ visualInfo }}</div>\r\n }\r\n </fieldset>\r\n\r\n <!-- chain view -->\r\n @if (chain()) {\r\n <div id=\"chain-view\">\r\n <gve-chain-view [chain]=\"chain()\" />\r\n </div>\r\n }\r\n\r\n <!--buttons -->\r\n <div class=\"form-row-center\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n close\r\n </button>\r\n @if (!noSave()) {\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save changes\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n }\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}.form-row .right{margin-left:auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}#text-range{margin:8px;border:1px solid silver;border-radius:6px;padding:6px}mat-expansion-panel{margin:8px 0}div#visual-info{font-size:95%;color:#909090;margin:8px}#list{margin:8px 0}#opStyle{margin-top:8px}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#c8d9eb}tr.edited{background-color:#f6f6e4}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:#909090}.error{color:red}.input-nr{width:6em}.full-width{width:100%}.code{font-family:Courier New,Courier,monospace}.boxed{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}span.label{margin-left:8px}gve-animation-timeline-set{margin:8px 0}div#image{display:grid;gap:8px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"image-ctl image-view\"}div#image-ctl{grid-area:image-ctl}div#image-view{grid-area:image-view}div#chain-view{margin-bottom:8px}@media only screen and (max-width: 959px){div#image{grid-template-columns:1fr;grid-template-areas:\"image-ctl\" \"image-view\"}}\n"] }]
|
|
3926
|
+
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: GveApiService }, { type: i3$2.MatDialog }, { type: i4$2.DialogService }, { type: i4$3.MatSnackBar }], propDecorators: { snapshotView: [{
|
|
3778
3927
|
type: ViewChild,
|
|
3779
3928
|
args: ['snapshotView', { static: false }]
|
|
3780
3929
|
}] } });
|
|
@@ -3787,5 +3936,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImpor
|
|
|
3787
3936
|
* Generated bundle index. Do not edit.
|
|
3788
3937
|
*/
|
|
3789
3938
|
|
|
3790
|
-
export { AnimationTimelineComponent, AnimationTweenComponent, BaseTextCharComponent, BaseTextEditorComponent, BaseTextViewComponent, BatchOperationEditorComponent, ChainOperationEditorComponent, ChainResultViewComponent, ChainViewComponent, FeatureEditorComponent, FeatureSetEditorComponent, FeatureSetViewComponent, GveApiService, GveGraphvizService, LnHeightsEditorComponent, OperationSourceEditorComponent, SettingsService, SnapshotEditorComponent, SnapshotTextEditorComponent, StepsMapComponent };
|
|
3939
|
+
export { AnimationTimelineComponent, AnimationTimelineSetComponent, AnimationTweenComponent, BaseTextCharComponent, BaseTextEditorComponent, BaseTextViewComponent, BatchOperationEditorComponent, ChainOperationEditorComponent, ChainResultViewComponent, ChainViewComponent, FeatureEditorComponent, FeatureSetEditorComponent, FeatureSetViewComponent, GveApiService, GveGraphvizService, LnHeightsEditorComponent, OperationSourceEditorComponent, SettingsService, SnapshotEditorComponent, SnapshotTextEditorComponent, StepsMapComponent };
|
|
3791
3940
|
//# sourceMappingURL=myrmidon-gve-core.mjs.map
|