@franzzemen/brokenstock-shell 0.0.39 → 0.0.41
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.
|
@@ -53,8 +53,10 @@ function provideShellConfig(config) {
|
|
|
53
53
|
|
|
54
54
|
class ThinkingService {
|
|
55
55
|
constructor() {
|
|
56
|
-
this.#activeCount = signal(0,
|
|
57
|
-
|
|
56
|
+
this.#activeCount = signal(0, /* @ts-ignore */
|
|
57
|
+
...(ngDevMode ? [{ debugName: "#activeCount" }] : /* istanbul ignore next */ []));
|
|
58
|
+
this.isThinking = computed(() => this.#activeCount() > 0, /* @ts-ignore */
|
|
59
|
+
...(ngDevMode ? [{ debugName: "isThinking" }] : /* istanbul ignore next */ []));
|
|
58
60
|
}
|
|
59
61
|
#activeCount;
|
|
60
62
|
startThinking() {
|
|
@@ -66,22 +68,31 @@ class ThinkingService {
|
|
|
66
68
|
reset() {
|
|
67
69
|
this.#activeCount.set(0);
|
|
68
70
|
}
|
|
69
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
70
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
71
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: ThinkingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
72
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: ThinkingService, providedIn: 'root' }); }
|
|
71
73
|
}
|
|
72
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
74
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: ThinkingService, decorators: [{
|
|
73
75
|
type: Injectable,
|
|
74
76
|
args: [{ providedIn: 'root' }]
|
|
75
77
|
}] });
|
|
76
78
|
|
|
77
79
|
class AuthenticationService {
|
|
78
80
|
constructor() {
|
|
79
|
-
this.authenticated = signal(false,
|
|
80
|
-
|
|
81
|
-
this.
|
|
82
|
-
|
|
83
|
-
this.
|
|
84
|
-
|
|
81
|
+
this.authenticated = signal(false, /* @ts-ignore */
|
|
82
|
+
...(ngDevMode ? [{ debugName: "authenticated" }] : /* istanbul ignore next */ []));
|
|
83
|
+
this.authenticating = signal(false, /* @ts-ignore */
|
|
84
|
+
...(ngDevMode ? [{ debugName: "authenticating" }] : /* istanbul ignore next */ []));
|
|
85
|
+
this.userSession = signal(undefined, /* @ts-ignore */
|
|
86
|
+
...(ngDevMode ? [{ debugName: "userSession" }] : /* istanbul ignore next */ []));
|
|
87
|
+
this.effectivePermissions = signal({}, /* @ts-ignore */
|
|
88
|
+
...(ngDevMode ? [{ debugName: "effectivePermissions" }] : /* istanbul ignore next */ []));
|
|
89
|
+
/** First-class plan-feature grants for the current session (supersedes effectivePermissions). */
|
|
90
|
+
this.features = signal({}, /* @ts-ignore */
|
|
91
|
+
...(ngDevMode ? [{ debugName: "features" }] : /* istanbul ignore next */ []));
|
|
92
|
+
this.conflictSessions = signal(undefined, /* @ts-ignore */
|
|
93
|
+
...(ngDevMode ? [{ debugName: "conflictSessions" }] : /* istanbul ignore next */ []));
|
|
94
|
+
this.pendingCredentials = signal(undefined, /* @ts-ignore */
|
|
95
|
+
...(ngDevMode ? [{ debugName: "pendingCredentials" }] : /* istanbul ignore next */ []));
|
|
85
96
|
this.#refreshing = null;
|
|
86
97
|
this.#auth = 'Bearer ..';
|
|
87
98
|
this.#httpClient = inject(HttpClient);
|
|
@@ -106,6 +117,18 @@ class AuthenticationService {
|
|
|
106
117
|
hasAnyRole(roleNames) {
|
|
107
118
|
return this.authenticated() && roleNames.some(r => this.userSession()?.roles.includes(r) === true);
|
|
108
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Check whether the current session holds a plan-feature (truthy grant).
|
|
122
|
+
* Works for boolean features (`true`) and quantity features (limit > 0).
|
|
123
|
+
* e.g. `hasFeature('real-time')`.
|
|
124
|
+
*/
|
|
125
|
+
hasFeature(slug) {
|
|
126
|
+
return this.authenticated() && !!this.features()[slug];
|
|
127
|
+
}
|
|
128
|
+
/** Raw plan-feature value (`true` for boolean grants, the numeric limit for quantity features, else undefined). */
|
|
129
|
+
featureValue(slug) {
|
|
130
|
+
return this.features()[slug];
|
|
131
|
+
}
|
|
109
132
|
refresh() {
|
|
110
133
|
if (this.#refreshing) {
|
|
111
134
|
return this.#refreshing;
|
|
@@ -164,6 +187,7 @@ class AuthenticationService {
|
|
|
164
187
|
delete authResponse.session.token;
|
|
165
188
|
this.userSession.set(authResponse.session);
|
|
166
189
|
this.effectivePermissions.set(authResponse.effectivePermissions ?? {});
|
|
190
|
+
this.features.set(authResponse.features ?? {});
|
|
167
191
|
const auth = response.headers.get(HttpHeader.Authorization);
|
|
168
192
|
if (!auth || !BEARER_TOKEN_REGEX.test(auth)) {
|
|
169
193
|
reject('Unable to login');
|
|
@@ -222,6 +246,7 @@ class AuthenticationService {
|
|
|
222
246
|
this.#auth = auth;
|
|
223
247
|
this.userSession.set(body.session);
|
|
224
248
|
this.effectivePermissions.set(body.effectivePermissions ?? {});
|
|
249
|
+
this.features.set(body.features ?? {});
|
|
225
250
|
return true;
|
|
226
251
|
}
|
|
227
252
|
catch {
|
|
@@ -232,15 +257,16 @@ class AuthenticationService {
|
|
|
232
257
|
this.authenticated.set(false);
|
|
233
258
|
this.userSession.set(undefined);
|
|
234
259
|
this.effectivePermissions.set({});
|
|
260
|
+
this.features.set({});
|
|
235
261
|
this.conflictSessions.set(undefined);
|
|
236
262
|
this.pendingCredentials.set(undefined);
|
|
237
263
|
this.#auth = 'Bearer ..';
|
|
238
264
|
this.#router.navigate(['/login']).catch(console.error);
|
|
239
265
|
}
|
|
240
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
241
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
266
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: AuthenticationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
267
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: AuthenticationService, providedIn: 'root' }); }
|
|
242
268
|
}
|
|
243
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
269
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: AuthenticationService, decorators: [{
|
|
244
270
|
type: Injectable,
|
|
245
271
|
args: [{ providedIn: 'root' }]
|
|
246
272
|
}] });
|
|
@@ -306,7 +332,8 @@ const authInterceptor = (req, next) => {
|
|
|
306
332
|
|
|
307
333
|
class RegexValidatorDirective {
|
|
308
334
|
constructor() {
|
|
309
|
-
this.regex = input(/^[A-Z0-9._%+-@!?]{4,64}$/i,
|
|
335
|
+
this.regex = input(/^[A-Z0-9._%+-@!?]{4,64}$/i, /* @ts-ignore */
|
|
336
|
+
...(ngDevMode ? [{ debugName: "regex" }] : /* istanbul ignore next */ []));
|
|
310
337
|
}
|
|
311
338
|
validate(control) {
|
|
312
339
|
if (!control.value || !this.regex().test(control.value)) {
|
|
@@ -314,10 +341,10 @@ class RegexValidatorDirective {
|
|
|
314
341
|
}
|
|
315
342
|
return null;
|
|
316
343
|
}
|
|
317
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
318
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
344
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: RegexValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
345
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.4", type: RegexValidatorDirective, isStandalone: true, selector: "[regexValidator]", inputs: { regex: { classPropertyName: "regex", publicName: "regex", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: NG_VALIDATORS, useExisting: RegexValidatorDirective, multi: true }], ngImport: i0 }); }
|
|
319
346
|
}
|
|
320
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
347
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: RegexValidatorDirective, decorators: [{
|
|
321
348
|
type: Directive,
|
|
322
349
|
args: [{
|
|
323
350
|
selector: '[regexValidator]',
|
|
@@ -406,10 +433,10 @@ class FaqMarkdownRendererService {
|
|
|
406
433
|
},
|
|
407
434
|
};
|
|
408
435
|
}
|
|
409
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
410
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
436
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqMarkdownRendererService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
437
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqMarkdownRendererService, providedIn: 'root' }); }
|
|
411
438
|
}
|
|
412
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
439
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqMarkdownRendererService, decorators: [{
|
|
413
440
|
type: Injectable,
|
|
414
441
|
args: [{ providedIn: 'root' }]
|
|
415
442
|
}] });
|
|
@@ -459,10 +486,10 @@ class HttpFaqContentLoader {
|
|
|
459
486
|
this.contentCache.set(key, fetchPromise);
|
|
460
487
|
return fetchPromise;
|
|
461
488
|
}
|
|
462
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
463
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
489
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: HttpFaqContentLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
490
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: HttpFaqContentLoader, providedIn: 'root' }); }
|
|
464
491
|
}
|
|
465
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
492
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: HttpFaqContentLoader, decorators: [{
|
|
466
493
|
type: Injectable,
|
|
467
494
|
args: [{ providedIn: 'root' }]
|
|
468
495
|
}] });
|
|
@@ -488,8 +515,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
488
515
|
*/
|
|
489
516
|
class FaqHistoryService {
|
|
490
517
|
constructor() {
|
|
491
|
-
this._stack = signal([],
|
|
492
|
-
|
|
518
|
+
this._stack = signal([], /* @ts-ignore */
|
|
519
|
+
...(ngDevMode ? [{ debugName: "_stack" }] : /* istanbul ignore next */ []));
|
|
520
|
+
this._position = signal(0, /* @ts-ignore */
|
|
521
|
+
...(ngDevMode ? [{ debugName: "_position" }] : /* istanbul ignore next */ []));
|
|
493
522
|
this.stack = this._stack.asReadonly();
|
|
494
523
|
this.position = this._position.asReadonly();
|
|
495
524
|
/** True when popstate is processing the unwind kicked off by closeAndUnwind(). */
|
|
@@ -614,10 +643,10 @@ class FaqHistoryService {
|
|
|
614
643
|
this.teardown();
|
|
615
644
|
exit?.();
|
|
616
645
|
}
|
|
617
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
618
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
646
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqHistoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
647
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqHistoryService, providedIn: 'root' }); }
|
|
619
648
|
}
|
|
620
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
649
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqHistoryService, decorators: [{
|
|
621
650
|
type: Injectable,
|
|
622
651
|
args: [{ providedIn: 'root' }]
|
|
623
652
|
}] });
|
|
@@ -638,28 +667,39 @@ class FaqService {
|
|
|
638
667
|
this.history = inject(FaqHistoryService);
|
|
639
668
|
this.auth = inject(AuthenticationService);
|
|
640
669
|
this.router = inject(Router);
|
|
641
|
-
this._currentFaqKey = signal(null,
|
|
670
|
+
this._currentFaqKey = signal(null, /* @ts-ignore */
|
|
671
|
+
...(ngDevMode ? [{ debugName: "_currentFaqKey" }] : /* istanbul ignore next */ []));
|
|
642
672
|
/** Component-set current key. Bare `faq` opens at this key. */
|
|
643
673
|
this.currentFaqKey = this._currentFaqKey.asReadonly();
|
|
644
|
-
this._manifest = signal(null,
|
|
674
|
+
this._manifest = signal(null, /* @ts-ignore */
|
|
675
|
+
...(ngDevMode ? [{ debugName: "_manifest" }] : /* istanbul ignore next */ []));
|
|
645
676
|
this.manifest = this._manifest.asReadonly();
|
|
646
|
-
this.entries = computed(() => this._manifest()?.entries ?? [],
|
|
677
|
+
this.entries = computed(() => this._manifest()?.entries ?? [], /* @ts-ignore */
|
|
678
|
+
...(ngDevMode ? [{ debugName: "entries" }] : /* istanbul ignore next */ []));
|
|
647
679
|
// Modal state (E3 + E8).
|
|
648
|
-
this._modalOpen = signal(false,
|
|
680
|
+
this._modalOpen = signal(false, /* @ts-ignore */
|
|
681
|
+
...(ngDevMode ? [{ debugName: "_modalOpen" }] : /* istanbul ignore next */ []));
|
|
649
682
|
this.modalOpen = this._modalOpen.asReadonly();
|
|
650
|
-
this._activeEntry = signal(null,
|
|
683
|
+
this._activeEntry = signal(null, /* @ts-ignore */
|
|
684
|
+
...(ngDevMode ? [{ debugName: "_activeEntry" }] : /* istanbul ignore next */ []));
|
|
651
685
|
this.activeEntry = this._activeEntry.asReadonly();
|
|
652
|
-
this._activeContent = signal(null,
|
|
686
|
+
this._activeContent = signal(null, /* @ts-ignore */
|
|
687
|
+
...(ngDevMode ? [{ debugName: "_activeContent" }] : /* istanbul ignore next */ []));
|
|
653
688
|
this.activeContent = this._activeContent.asReadonly();
|
|
654
|
-
this._activeAttempted = signal([],
|
|
689
|
+
this._activeAttempted = signal([], /* @ts-ignore */
|
|
690
|
+
...(ngDevMode ? [{ debugName: "_activeAttempted" }] : /* istanbul ignore next */ []));
|
|
655
691
|
this.activeAttempted = this._activeAttempted.asReadonly();
|
|
656
|
-
this._navigating = signal(false,
|
|
692
|
+
this._navigating = signal(false, /* @ts-ignore */
|
|
693
|
+
...(ngDevMode ? [{ debugName: "_navigating" }] : /* istanbul ignore next */ []));
|
|
657
694
|
this.navigating = this._navigating.asReadonly();
|
|
658
695
|
// Search pre-fill consumed by E4 search UI on modal open / navigateTo.
|
|
659
|
-
this._initialSearchTerm = signal(null,
|
|
696
|
+
this._initialSearchTerm = signal(null, /* @ts-ignore */
|
|
697
|
+
...(ngDevMode ? [{ debugName: "_initialSearchTerm" }] : /* istanbul ignore next */ []));
|
|
660
698
|
this.initialSearchTerm = this._initialSearchTerm.asReadonly();
|
|
661
|
-
this.canGoBack = computed(() => this.history.position() > 0,
|
|
662
|
-
|
|
699
|
+
this.canGoBack = computed(() => this.history.position() > 0, /* @ts-ignore */
|
|
700
|
+
...(ngDevMode ? [{ debugName: "canGoBack" }] : /* istanbul ignore next */ []));
|
|
701
|
+
this.canGoForward = computed(() => this.history.position() < this.history.stack().length - 1, /* @ts-ignore */
|
|
702
|
+
...(ngDevMode ? [{ debugName: "canGoForward" }] : /* istanbul ignore next */ []));
|
|
663
703
|
this.manifestPromise = null;
|
|
664
704
|
}
|
|
665
705
|
/** Called by the search UI once it has consumed the pre-fill term. */
|
|
@@ -819,10 +859,10 @@ class FaqService {
|
|
|
819
859
|
this._navigating.set(false);
|
|
820
860
|
}
|
|
821
861
|
}
|
|
822
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
823
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
862
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
863
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqService, providedIn: 'root' }); }
|
|
824
864
|
}
|
|
825
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
865
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqService, decorators: [{
|
|
826
866
|
type: Injectable,
|
|
827
867
|
args: [{ providedIn: 'root' }]
|
|
828
868
|
}] });
|
|
@@ -894,11 +934,16 @@ class FaqModal {
|
|
|
894
934
|
this.attempted = this.faq.activeAttempted;
|
|
895
935
|
this.canGoBack = this.faq.canGoBack;
|
|
896
936
|
this.canGoForward = this.faq.canGoForward;
|
|
897
|
-
this.sidebarCollapsed = signal(false,
|
|
898
|
-
|
|
899
|
-
this.
|
|
900
|
-
|
|
901
|
-
this.
|
|
937
|
+
this.sidebarCollapsed = signal(false, /* @ts-ignore */
|
|
938
|
+
...(ngDevMode ? [{ debugName: "sidebarCollapsed" }] : /* istanbul ignore next */ []));
|
|
939
|
+
this.searchMode = signal(false, /* @ts-ignore */
|
|
940
|
+
...(ngDevMode ? [{ debugName: "searchMode" }] : /* istanbul ignore next */ []));
|
|
941
|
+
this.searchQuery = signal('', /* @ts-ignore */
|
|
942
|
+
...(ngDevMode ? [{ debugName: "searchQuery" }] : /* istanbul ignore next */ []));
|
|
943
|
+
this.searchLoading = signal(false, /* @ts-ignore */
|
|
944
|
+
...(ngDevMode ? [{ debugName: "searchLoading" }] : /* istanbul ignore next */ []));
|
|
945
|
+
this.searchResults = signal([], /* @ts-ignore */
|
|
946
|
+
...(ngDevMode ? [{ debugName: "searchResults" }] : /* istanbul ignore next */ []));
|
|
902
947
|
this.fuse = null;
|
|
903
948
|
this.fuseBuild = null;
|
|
904
949
|
this.renderedHtml = computed(() => {
|
|
@@ -911,7 +956,8 @@ class FaqModal {
|
|
|
911
956
|
context: 'modal',
|
|
912
957
|
imagePrefix: entry?.imagePrefix ?? parsed.frontmatter['image-prefix'],
|
|
913
958
|
});
|
|
914
|
-
},
|
|
959
|
+
}, /* @ts-ignore */
|
|
960
|
+
...(ngDevMode ? [{ debugName: "renderedHtml" }] : /* istanbul ignore next */ []));
|
|
915
961
|
this.toc = computed(() => {
|
|
916
962
|
const isAuth = this.auth.authenticated();
|
|
917
963
|
const entries = this.faq.entries().filter((e) => {
|
|
@@ -931,7 +977,8 @@ class FaqModal {
|
|
|
931
977
|
category,
|
|
932
978
|
entries: list.sort((a, b) => a.order - b.order || a.title.localeCompare(b.title)),
|
|
933
979
|
}));
|
|
934
|
-
},
|
|
980
|
+
}, /* @ts-ignore */
|
|
981
|
+
...(ngDevMode ? [{ debugName: "toc" }] : /* istanbul ignore next */ []));
|
|
935
982
|
// Scroll content pane to top on key change.
|
|
936
983
|
effect(() => {
|
|
937
984
|
this.activeEntry();
|
|
@@ -1104,10 +1151,13 @@ class FaqModal {
|
|
|
1104
1151
|
return;
|
|
1105
1152
|
}
|
|
1106
1153
|
}
|
|
1107
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1108
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: FaqModal, isStandalone: true, selector: "faq-modal", host: { listeners: { "document:keydown.escape": "onEscape()" } }, viewQueries: [{ propertyName: "contentPaneRef", first: true, predicate: ["contentPane"], descendants: true }], ngImport: i0, template: "@if (open()) {\n <div class=\"faq-backdrop\" (click)=\"onBackdropClick()\" role=\"presentation\">\n <div\n class=\"faq-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"activeEntry()?.title ?? 'FAQ'\"\n (click)=\"stopPropagation($event)\"\n >\n <header class=\"faq-toolbar\">\n <div class=\"faq-toolbar-nav\">\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"toggleSidebar()\"\n [attr.aria-label]=\"sidebarCollapsed() ? 'Show contents' : 'Hide contents'\"\n [attr.aria-pressed]=\"!sidebarCollapsed()\"\n >\u2630</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"goBack()\"\n [disabled]=\"!canGoBack()\"\n aria-label=\"Back\"\n >\u2039</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"goForward()\"\n [disabled]=\"!canGoForward()\"\n aria-label=\"Forward\"\n >\u203A</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"goIndex()\"\n aria-label=\"Index\"\n >\u2302</button>\n </div>\n <div class=\"faq-toolbar-title\">\n @if (activeEntry(); as entry) {\n <span class=\"faq-category\">{{ entry.category }}</span>\n <span class=\"faq-sep\">/</span>\n <span class=\"faq-title\">{{ entry.title }}</span>\n } @else {\n <span class=\"faq-title\">FAQ</span>\n }\n </div>\n <div class=\"faq-toolbar-actions\">\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"toggleSearch()\"\n [class.active]=\"searchMode()\"\n aria-label=\"Search\"\n >\u2315</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn faq-close-btn\"\n (click)=\"close()\"\n aria-label=\"Close\"\n >\u2715</button>\n </div>\n </header>\n\n <div class=\"faq-body\" [class.sidebar-collapsed]=\"sidebarCollapsed()\">\n <aside class=\"faq-sidebar\" aria-label=\"FAQ contents\">\n @if (searchMode()) {\n <div class=\"faq-search\">\n <input\n type=\"search\"\n class=\"faq-search-input\"\n placeholder=\"Search FAQ\u2026\"\n aria-label=\"Search FAQ\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n />\n @if (searchLoading()) {\n <p class=\"faq-search-status\">Building index\u2026</p>\n } @else if (!searchQuery().trim()) {\n <p class=\"faq-search-status\">Type to search titles and content.</p>\n } @else if (searchResults().length === 0) {\n <p class=\"faq-search-status\">No matches.</p>\n } @else {\n <ul class=\"faq-search-results\">\n @for (r of searchResults(); track r.key) {\n <li>\n <button\n type=\"button\"\n class=\"faq-search-result\"\n [class.active]=\"activeEntry()?.key === r.key\"\n (click)=\"onSearchResultClick(r.key)\"\n >\n <span class=\"faq-search-result-title\">{{ r.title }}</span>\n <span class=\"faq-search-result-category\">{{ r.category }}</span>\n @if (r.snippet) {\n <span class=\"faq-search-result-snippet\">{{ r.snippet }}</span>\n }\n </button>\n </li>\n }\n </ul>\n }\n </div>\n } @else {\n <nav class=\"faq-toc\">\n @for (group of toc(); track group.category) {\n <div class=\"faq-toc-group\">\n <h3 class=\"faq-toc-category\">{{ group.category }}</h3>\n <ul>\n @for (entry of group.entries; track entry.key) {\n <li>\n <button\n type=\"button\"\n class=\"faq-toc-link\"\n [class.active]=\"activeEntry()?.key === entry.key\"\n (click)=\"onTocClick(entry.key)\"\n >{{ entry.title }}</button>\n </li>\n }\n </ul>\n </div>\n } @empty {\n <p class=\"faq-toc-empty\">No FAQ entries yet.</p>\n }\n </nav>\n }\n </aside>\n\n <main\n #contentPane\n class=\"faq-content\"\n (click)=\"onContentClick($event)\"\n >\n @if (navigating()) {\n <div class=\"faq-loading\">Loading\u2026</div>\n } @else if (renderedHtml(); as html) {\n <article class=\"faq-article\" [innerHTML]=\"html\"></article>\n @if (devMode && activeEntry(); as entry) {\n @defer (when devMode) {\n <faq-authoring-panel\n mode=\"existing\"\n [key]=\"entry.key\"\n [attempted]=\"attempted()\"\n [entry]=\"entry\"\n />\n }\n }\n } @else {\n <div class=\"faq-empty\">\n <h2>No FAQ available</h2>\n <p>No content is registered for this route.</p>\n @if (attempted().length) {\n <p class=\"faq-empty-chain\">\n Attempted keys:\n <code>{{ attempted().join(' \u2192 ') }}</code>\n </p>\n }\n @if (devMode && attempted().length) {\n @defer (when devMode) {\n <faq-authoring-panel\n mode=\"missing\"\n [key]=\"attempted()[0]\"\n [attempted]=\"attempted()\"\n />\n } @loading (minimum 100ms) {\n <p class=\"faq-empty-hint\">Loading authoring panel\u2026</p>\n }\n }\n </div>\n }\n </main>\n </div>\n </div>\n </div>\n}\n", styles: [":host{display:contents}.faq-backdrop{position:fixed;inset:0;z-index:1100;background:#0000008c;display:flex;align-items:center;justify-content:center;padding:5vh 5vw}.faq-modal{width:80vw;height:80vh;max-width:1600px;max-height:1100px;background:var(--shell-surface, #1d1f23);color:var(--shell-fg, #e6e6e6);border-radius:8px;box-shadow:0 12px 32px #00000080;display:grid;grid-template-rows:auto 1fr;overflow:hidden;font-family:var(--shell-font, system-ui, sans-serif)}.faq-toolbar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:.5rem;padding:.5rem .75rem;border-bottom:1px solid var(--shell-border, rgba(255, 255, 255, .08));background:var(--shell-surface-2, rgba(255, 255, 255, .03))}.faq-toolbar-nav,.faq-toolbar-actions{display:flex;gap:.25rem}.faq-toolbar-title{text-align:center;font-size:.95rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.faq-category{opacity:.7;margin-right:.25rem}.faq-sep{opacity:.4;margin:0 .25rem}.faq-title{font-weight:600}.faq-icon-btn{background:transparent;border:1px solid transparent;color:inherit;width:2rem;height:2rem;border-radius:4px;cursor:pointer;font-size:1rem;line-height:1;display:inline-flex;align-items:center;justify-content:center}.faq-icon-btn:hover:not(:disabled){background:#ffffff14}.faq-icon-btn:disabled{opacity:.35;cursor:not-allowed}.faq-icon-btn.active{background:#ffffff1f;border-color:#ffffff2e}.faq-body{display:grid;grid-template-columns:260px 1fr;min-height:0}.faq-body.sidebar-collapsed{grid-template-columns:0 1fr}.faq-body.sidebar-collapsed .faq-sidebar{display:none}.faq-sidebar{border-right:1px solid var(--shell-border, rgba(255, 255, 255, .08));overflow-y:auto;padding:.75rem .5rem;background:var(--shell-surface, #1d1f23)}.faq-toc-group{margin-bottom:1rem}.faq-toc-category{font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;opacity:.6;margin:0 0 .4rem .4rem}.faq-toc ul{list-style:none;padding:0;margin:0}.faq-toc-link{display:block;width:100%;text-align:left;background:transparent;border:none;color:inherit;padding:.35rem .5rem;border-radius:4px;cursor:pointer;font-size:.88rem}.faq-toc-link:hover{background:#ffffff0f}.faq-toc-link.active{background:#ffffff1f;font-weight:600}.faq-toc-empty{padding:1rem .5rem;opacity:.7;font-size:.85rem}.faq-search{display:flex;flex-direction:column;gap:.5rem;padding:.25rem}.faq-search-input{width:100%;padding:.5rem .6rem;border-radius:4px;border:1px solid rgba(255,255,255,.18);background:#00000040;color:inherit;font-size:.9rem;box-sizing:border-box}.faq-search-input:focus{outline:none;border-color:#fff6}.faq-search-status{padding:.5rem;opacity:.65;font-size:.82rem;margin:0}.faq-search-results{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:.15rem}.faq-search-result{display:flex;flex-direction:column;gap:.15rem;width:100%;text-align:left;background:transparent;border:none;color:inherit;padding:.45rem .5rem;border-radius:4px;cursor:pointer}.faq-search-result:hover{background:#ffffff0f}.faq-search-result.active{background:#ffffff1f}.faq-search-result-title{font-size:.9rem;font-weight:600}.faq-search-result-category{font-size:.72rem;opacity:.6;text-transform:uppercase;letter-spacing:.04em}.faq-search-result-snippet{font-size:.78rem;opacity:.75;line-height:1.35}.faq-content{overflow-y:auto;padding:1.25rem 2rem;min-width:0}.faq-loading,.faq-empty{opacity:.75;padding:1rem 0}.faq-empty-chain code{background:#ffffff14;padding:.1rem .4rem;border-radius:3px;font-size:.85rem}.faq-empty-hint{margin-top:1rem;opacity:.55;font-size:.85rem}.faq-article{max-width:70ch;line-height:1.55;font-size:.95rem}.faq-article h1,.faq-article h2,.faq-article h3{font-weight:600;margin:1.4rem 0 .6rem}.faq-article h1{font-size:1.4rem;margin-top:0}.faq-article h2{font-size:1.15rem}.faq-article h3{font-size:1rem}.faq-article p{margin:.6rem 0}.faq-article a{color:var(--shell-link, #6ea8fe);text-decoration:none}.faq-article a:hover{text-decoration:underline}.faq-article a[data-faq-kind=external]:after{content:\" \\2197\";opacity:.65;font-size:.85em}.faq-article .faq-app-arrow{opacity:.7;font-size:.9em}.faq-article code{background:#ffffff14;padding:.1rem .35rem;border-radius:3px;font-size:.88em}.faq-article pre{background:#00000059;padding:.75rem 1rem;border-radius:4px;overflow-x:auto}.faq-article pre code{background:transparent;padding:0}.faq-article img{max-width:100%;border-radius:4px;margin:.6rem 0}.faq-article ul,.faq-article ol{padding-left:1.4rem;margin:.6rem 0}.faq-article blockquote{border-left:3px solid var(--shell-border, rgba(255, 255, 255, .15));padding-left:.9rem;margin:.8rem 0;opacity:.85}@media(max-width:900px){.faq-modal{width:100vw;height:100vh;border-radius:0;max-width:none;max-height:none}.faq-backdrop{padding:0}.faq-body{grid-template-columns:1fr}.faq-sidebar{display:none}.faq-body:not(.sidebar-collapsed) .faq-sidebar{display:block;position:absolute;inset:0;z-index:1}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None, deferBlockDependencies: [() => [Promise.resolve().then(function () { return faqAuthoringPanel; }).then(m => m.FaqAuthoringPanel)], () => [Promise.resolve().then(function () { return faqAuthoringPanel; }).then(m => m.FaqAuthoringPanel)]] }); }
|
|
1154
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqModal, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1155
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: FaqModal, isStandalone: true, selector: "faq-modal", host: { listeners: { "document:keydown.escape": "onEscape()" } }, viewQueries: [{ propertyName: "contentPaneRef", first: true, predicate: ["contentPane"], descendants: true }], ngImport: i0, template: "@if (open()) {\n <div class=\"faq-backdrop\" (click)=\"onBackdropClick()\" role=\"presentation\">\n <div\n class=\"faq-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"activeEntry()?.title ?? 'FAQ'\"\n (click)=\"stopPropagation($event)\"\n >\n <header class=\"faq-toolbar\">\n <div class=\"faq-toolbar-nav\">\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"toggleSidebar()\"\n [attr.aria-label]=\"sidebarCollapsed() ? 'Show contents' : 'Hide contents'\"\n [attr.aria-pressed]=\"!sidebarCollapsed()\"\n >\u2630</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"goBack()\"\n [disabled]=\"!canGoBack()\"\n aria-label=\"Back\"\n >\u2039</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"goForward()\"\n [disabled]=\"!canGoForward()\"\n aria-label=\"Forward\"\n >\u203A</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"goIndex()\"\n aria-label=\"Index\"\n >\u2302</button>\n </div>\n <div class=\"faq-toolbar-title\">\n @if (activeEntry(); as entry) {\n <span class=\"faq-category\">{{ entry.category }}</span>\n <span class=\"faq-sep\">/</span>\n <span class=\"faq-title\">{{ entry.title }}</span>\n } @else {\n <span class=\"faq-title\">FAQ</span>\n }\n </div>\n <div class=\"faq-toolbar-actions\">\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"toggleSearch()\"\n [class.active]=\"searchMode()\"\n aria-label=\"Search\"\n >\u2315</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn faq-close-btn\"\n (click)=\"close()\"\n aria-label=\"Close\"\n >\u2715</button>\n </div>\n </header>\n\n <div class=\"faq-body\" [class.sidebar-collapsed]=\"sidebarCollapsed()\">\n <aside class=\"faq-sidebar\" aria-label=\"FAQ contents\">\n @if (searchMode()) {\n <div class=\"faq-search\">\n <input\n type=\"search\"\n class=\"faq-search-input\"\n placeholder=\"Search FAQ\u2026\"\n aria-label=\"Search FAQ\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n />\n @if (searchLoading()) {\n <p class=\"faq-search-status\">Building index\u2026</p>\n } @else if (!searchQuery().trim()) {\n <p class=\"faq-search-status\">Type to search titles and content.</p>\n } @else if (searchResults().length === 0) {\n <p class=\"faq-search-status\">No matches.</p>\n } @else {\n <ul class=\"faq-search-results\">\n @for (r of searchResults(); track r.key) {\n <li>\n <button\n type=\"button\"\n class=\"faq-search-result\"\n [class.active]=\"activeEntry()?.key === r.key\"\n (click)=\"onSearchResultClick(r.key)\"\n >\n <span class=\"faq-search-result-title\">{{ r.title }}</span>\n <span class=\"faq-search-result-category\">{{ r.category }}</span>\n @if (r.snippet) {\n <span class=\"faq-search-result-snippet\">{{ r.snippet }}</span>\n }\n </button>\n </li>\n }\n </ul>\n }\n </div>\n } @else {\n <nav class=\"faq-toc\">\n @for (group of toc(); track group.category) {\n <div class=\"faq-toc-group\">\n <h3 class=\"faq-toc-category\">{{ group.category }}</h3>\n <ul>\n @for (entry of group.entries; track entry.key) {\n <li>\n <button\n type=\"button\"\n class=\"faq-toc-link\"\n [class.active]=\"activeEntry()?.key === entry.key\"\n (click)=\"onTocClick(entry.key)\"\n >{{ entry.title }}</button>\n </li>\n }\n </ul>\n </div>\n } @empty {\n <p class=\"faq-toc-empty\">No FAQ entries yet.</p>\n }\n </nav>\n }\n </aside>\n\n <main\n #contentPane\n class=\"faq-content\"\n (click)=\"onContentClick($event)\"\n >\n @if (navigating()) {\n <div class=\"faq-loading\">Loading\u2026</div>\n } @else if (renderedHtml(); as html) {\n <article class=\"faq-article\" [innerHTML]=\"html\"></article>\n @if (devMode && activeEntry(); as entry) {\n @defer (when devMode) {\n <faq-authoring-panel\n mode=\"existing\"\n [key]=\"entry.key\"\n [attempted]=\"attempted()\"\n [entry]=\"entry\"\n />\n }\n }\n } @else {\n <div class=\"faq-empty\">\n <h2>No FAQ available</h2>\n <p>No content is registered for this route.</p>\n @if (attempted().length) {\n <p class=\"faq-empty-chain\">\n Attempted keys:\n <code>{{ attempted().join(' \u2192 ') }}</code>\n </p>\n }\n @if (devMode && attempted().length) {\n @defer (when devMode) {\n <faq-authoring-panel\n mode=\"missing\"\n [key]=\"attempted()[0]\"\n [attempted]=\"attempted()\"\n />\n } @loading (minimum 100ms) {\n <p class=\"faq-empty-hint\">Loading authoring panel\u2026</p>\n }\n }\n </div>\n }\n </main>\n </div>\n </div>\n </div>\n}\n", styles: [":host{display:contents}.faq-backdrop{position:fixed;inset:0;z-index:1100;background:#0000008c;display:flex;align-items:center;justify-content:center;padding:5vh 5vw}.faq-modal{width:80vw;height:80vh;max-width:1600px;max-height:1100px;background:var(--shell-surface, #1d1f23);color:var(--shell-fg, #e6e6e6);border-radius:8px;box-shadow:0 12px 32px #00000080;display:grid;grid-template-rows:auto 1fr;overflow:hidden;font-family:var(--shell-font, system-ui, sans-serif)}.faq-toolbar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:.5rem;padding:.5rem .75rem;border-bottom:1px solid var(--shell-border, rgba(255, 255, 255, .08));background:var(--shell-surface-2, rgba(255, 255, 255, .03))}.faq-toolbar-nav,.faq-toolbar-actions{display:flex;gap:.25rem}.faq-toolbar-title{text-align:center;font-size:.95rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.faq-category{opacity:.7;margin-right:.25rem}.faq-sep{opacity:.4;margin:0 .25rem}.faq-title{font-weight:600}.faq-icon-btn{background:transparent;border:1px solid transparent;color:inherit;width:2rem;height:2rem;border-radius:4px;cursor:pointer;font-size:1rem;line-height:1;display:inline-flex;align-items:center;justify-content:center}.faq-icon-btn:hover:not(:disabled){background:#ffffff14}.faq-icon-btn:disabled{opacity:.35;cursor:not-allowed}.faq-icon-btn.active{background:#ffffff1f;border-color:#ffffff2e}.faq-body{display:grid;grid-template-columns:260px 1fr;min-height:0}.faq-body.sidebar-collapsed{grid-template-columns:0 1fr}.faq-body.sidebar-collapsed .faq-sidebar{display:none}.faq-sidebar{border-right:1px solid var(--shell-border, rgba(255, 255, 255, .08));overflow-y:auto;padding:.75rem .5rem;background:var(--shell-surface, #1d1f23)}.faq-toc-group{margin-bottom:1rem}.faq-toc-category{font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;opacity:.6;margin:0 0 .4rem .4rem}.faq-toc ul{list-style:none;padding:0;margin:0}.faq-toc-link{display:block;width:100%;text-align:left;background:transparent;border:none;color:inherit;padding:.35rem .5rem;border-radius:4px;cursor:pointer;font-size:.88rem}.faq-toc-link:hover{background:#ffffff0f}.faq-toc-link.active{background:#ffffff1f;font-weight:600}.faq-toc-empty{padding:1rem .5rem;opacity:.7;font-size:.85rem}.faq-search{display:flex;flex-direction:column;gap:.5rem;padding:.25rem}.faq-search-input{width:100%;padding:.5rem .6rem;border-radius:4px;border:1px solid rgba(255,255,255,.18);background:#00000040;color:inherit;font-size:.9rem;box-sizing:border-box}.faq-search-input:focus{outline:none;border-color:#fff6}.faq-search-status{padding:.5rem;opacity:.65;font-size:.82rem;margin:0}.faq-search-results{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:.15rem}.faq-search-result{display:flex;flex-direction:column;gap:.15rem;width:100%;text-align:left;background:transparent;border:none;color:inherit;padding:.45rem .5rem;border-radius:4px;cursor:pointer}.faq-search-result:hover{background:#ffffff0f}.faq-search-result.active{background:#ffffff1f}.faq-search-result-title{font-size:.9rem;font-weight:600}.faq-search-result-category{font-size:.72rem;opacity:.6;text-transform:uppercase;letter-spacing:.04em}.faq-search-result-snippet{font-size:.78rem;opacity:.75;line-height:1.35}.faq-content{overflow-y:auto;padding:1.25rem 2rem;min-width:0}.faq-loading,.faq-empty{opacity:.75;padding:1rem 0}.faq-empty-chain code{background:#ffffff14;padding:.1rem .4rem;border-radius:3px;font-size:.85rem}.faq-empty-hint{margin-top:1rem;opacity:.55;font-size:.85rem}.faq-article{max-width:70ch;line-height:1.55;font-size:.95rem}.faq-article h1,.faq-article h2,.faq-article h3{font-weight:600;margin:1.4rem 0 .6rem}.faq-article h1{font-size:1.4rem;margin-top:0}.faq-article h2{font-size:1.15rem}.faq-article h3{font-size:1rem}.faq-article p{margin:.6rem 0}.faq-article a{color:var(--shell-link, #6ea8fe);text-decoration:none}.faq-article a:hover{text-decoration:underline}.faq-article a[data-faq-kind=external]:after{content:\" \\2197\";opacity:.65;font-size:.85em}.faq-article .faq-app-arrow{opacity:.7;font-size:.9em}.faq-article code{background:#ffffff14;padding:.1rem .35rem;border-radius:3px;font-size:.88em}.faq-article pre{background:#00000059;padding:.75rem 1rem;border-radius:4px;overflow-x:auto}.faq-article pre code{background:transparent;padding:0}.faq-article img{max-width:100%;border-radius:4px;margin:.6rem 0}.faq-article ul,.faq-article ol{padding-left:1.4rem;margin:.6rem 0}.faq-article blockquote{border-left:3px solid var(--shell-border, rgba(255, 255, 255, .15));padding-left:.9rem;margin:.8rem 0;opacity:.85}@media(max-width:900px){.faq-modal{width:100vw;height:100vh;border-radius:0;max-width:none;max-height:none}.faq-backdrop{padding:0}.faq-body{grid-template-columns:1fr}.faq-sidebar{display:none}.faq-body:not(.sidebar-collapsed) .faq-sidebar{display:block;position:absolute;inset:0;z-index:1}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None, deferBlockDependencies: [() => [/* @ts-ignore */
|
|
1156
|
+
Promise.resolve().then(function () { return faqAuthoringPanel; }).then(m => m.FaqAuthoringPanel)], () => [/* @ts-ignore */
|
|
1157
|
+
Promise.resolve().then(function () { return faqAuthoringPanel; }).then(m => m.FaqAuthoringPanel)]] }); }
|
|
1109
1158
|
}
|
|
1110
|
-
i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "
|
|
1159
|
+
i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.0.4", ngImport: i0, type: FaqModal, resolveDeferredDeps: () => [/* @ts-ignore */
|
|
1160
|
+
Promise.resolve().then(function () { return faqAuthoringPanel; }).then(m => m.FaqAuthoringPanel)], resolveMetadata: FaqAuthoringPanel => ({ decorators: [{
|
|
1111
1161
|
type: Component,
|
|
1112
1162
|
args: [{ selector: 'faq-modal', standalone: true, imports: [FaqAuthoringPanel], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if (open()) {\n <div class=\"faq-backdrop\" (click)=\"onBackdropClick()\" role=\"presentation\">\n <div\n class=\"faq-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"activeEntry()?.title ?? 'FAQ'\"\n (click)=\"stopPropagation($event)\"\n >\n <header class=\"faq-toolbar\">\n <div class=\"faq-toolbar-nav\">\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"toggleSidebar()\"\n [attr.aria-label]=\"sidebarCollapsed() ? 'Show contents' : 'Hide contents'\"\n [attr.aria-pressed]=\"!sidebarCollapsed()\"\n >\u2630</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"goBack()\"\n [disabled]=\"!canGoBack()\"\n aria-label=\"Back\"\n >\u2039</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"goForward()\"\n [disabled]=\"!canGoForward()\"\n aria-label=\"Forward\"\n >\u203A</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"goIndex()\"\n aria-label=\"Index\"\n >\u2302</button>\n </div>\n <div class=\"faq-toolbar-title\">\n @if (activeEntry(); as entry) {\n <span class=\"faq-category\">{{ entry.category }}</span>\n <span class=\"faq-sep\">/</span>\n <span class=\"faq-title\">{{ entry.title }}</span>\n } @else {\n <span class=\"faq-title\">FAQ</span>\n }\n </div>\n <div class=\"faq-toolbar-actions\">\n <button\n type=\"button\"\n class=\"faq-icon-btn\"\n (click)=\"toggleSearch()\"\n [class.active]=\"searchMode()\"\n aria-label=\"Search\"\n >\u2315</button>\n <button\n type=\"button\"\n class=\"faq-icon-btn faq-close-btn\"\n (click)=\"close()\"\n aria-label=\"Close\"\n >\u2715</button>\n </div>\n </header>\n\n <div class=\"faq-body\" [class.sidebar-collapsed]=\"sidebarCollapsed()\">\n <aside class=\"faq-sidebar\" aria-label=\"FAQ contents\">\n @if (searchMode()) {\n <div class=\"faq-search\">\n <input\n type=\"search\"\n class=\"faq-search-input\"\n placeholder=\"Search FAQ\u2026\"\n aria-label=\"Search FAQ\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n />\n @if (searchLoading()) {\n <p class=\"faq-search-status\">Building index\u2026</p>\n } @else if (!searchQuery().trim()) {\n <p class=\"faq-search-status\">Type to search titles and content.</p>\n } @else if (searchResults().length === 0) {\n <p class=\"faq-search-status\">No matches.</p>\n } @else {\n <ul class=\"faq-search-results\">\n @for (r of searchResults(); track r.key) {\n <li>\n <button\n type=\"button\"\n class=\"faq-search-result\"\n [class.active]=\"activeEntry()?.key === r.key\"\n (click)=\"onSearchResultClick(r.key)\"\n >\n <span class=\"faq-search-result-title\">{{ r.title }}</span>\n <span class=\"faq-search-result-category\">{{ r.category }}</span>\n @if (r.snippet) {\n <span class=\"faq-search-result-snippet\">{{ r.snippet }}</span>\n }\n </button>\n </li>\n }\n </ul>\n }\n </div>\n } @else {\n <nav class=\"faq-toc\">\n @for (group of toc(); track group.category) {\n <div class=\"faq-toc-group\">\n <h3 class=\"faq-toc-category\">{{ group.category }}</h3>\n <ul>\n @for (entry of group.entries; track entry.key) {\n <li>\n <button\n type=\"button\"\n class=\"faq-toc-link\"\n [class.active]=\"activeEntry()?.key === entry.key\"\n (click)=\"onTocClick(entry.key)\"\n >{{ entry.title }}</button>\n </li>\n }\n </ul>\n </div>\n } @empty {\n <p class=\"faq-toc-empty\">No FAQ entries yet.</p>\n }\n </nav>\n }\n </aside>\n\n <main\n #contentPane\n class=\"faq-content\"\n (click)=\"onContentClick($event)\"\n >\n @if (navigating()) {\n <div class=\"faq-loading\">Loading\u2026</div>\n } @else if (renderedHtml(); as html) {\n <article class=\"faq-article\" [innerHTML]=\"html\"></article>\n @if (devMode && activeEntry(); as entry) {\n @defer (when devMode) {\n <faq-authoring-panel\n mode=\"existing\"\n [key]=\"entry.key\"\n [attempted]=\"attempted()\"\n [entry]=\"entry\"\n />\n }\n }\n } @else {\n <div class=\"faq-empty\">\n <h2>No FAQ available</h2>\n <p>No content is registered for this route.</p>\n @if (attempted().length) {\n <p class=\"faq-empty-chain\">\n Attempted keys:\n <code>{{ attempted().join(' \u2192 ') }}</code>\n </p>\n }\n @if (devMode && attempted().length) {\n @defer (when devMode) {\n <faq-authoring-panel\n mode=\"missing\"\n [key]=\"attempted()[0]\"\n [attempted]=\"attempted()\"\n />\n } @loading (minimum 100ms) {\n <p class=\"faq-empty-hint\">Loading authoring panel\u2026</p>\n }\n }\n </div>\n }\n </main>\n </div>\n </div>\n </div>\n}\n", styles: [":host{display:contents}.faq-backdrop{position:fixed;inset:0;z-index:1100;background:#0000008c;display:flex;align-items:center;justify-content:center;padding:5vh 5vw}.faq-modal{width:80vw;height:80vh;max-width:1600px;max-height:1100px;background:var(--shell-surface, #1d1f23);color:var(--shell-fg, #e6e6e6);border-radius:8px;box-shadow:0 12px 32px #00000080;display:grid;grid-template-rows:auto 1fr;overflow:hidden;font-family:var(--shell-font, system-ui, sans-serif)}.faq-toolbar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:.5rem;padding:.5rem .75rem;border-bottom:1px solid var(--shell-border, rgba(255, 255, 255, .08));background:var(--shell-surface-2, rgba(255, 255, 255, .03))}.faq-toolbar-nav,.faq-toolbar-actions{display:flex;gap:.25rem}.faq-toolbar-title{text-align:center;font-size:.95rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.faq-category{opacity:.7;margin-right:.25rem}.faq-sep{opacity:.4;margin:0 .25rem}.faq-title{font-weight:600}.faq-icon-btn{background:transparent;border:1px solid transparent;color:inherit;width:2rem;height:2rem;border-radius:4px;cursor:pointer;font-size:1rem;line-height:1;display:inline-flex;align-items:center;justify-content:center}.faq-icon-btn:hover:not(:disabled){background:#ffffff14}.faq-icon-btn:disabled{opacity:.35;cursor:not-allowed}.faq-icon-btn.active{background:#ffffff1f;border-color:#ffffff2e}.faq-body{display:grid;grid-template-columns:260px 1fr;min-height:0}.faq-body.sidebar-collapsed{grid-template-columns:0 1fr}.faq-body.sidebar-collapsed .faq-sidebar{display:none}.faq-sidebar{border-right:1px solid var(--shell-border, rgba(255, 255, 255, .08));overflow-y:auto;padding:.75rem .5rem;background:var(--shell-surface, #1d1f23)}.faq-toc-group{margin-bottom:1rem}.faq-toc-category{font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;opacity:.6;margin:0 0 .4rem .4rem}.faq-toc ul{list-style:none;padding:0;margin:0}.faq-toc-link{display:block;width:100%;text-align:left;background:transparent;border:none;color:inherit;padding:.35rem .5rem;border-radius:4px;cursor:pointer;font-size:.88rem}.faq-toc-link:hover{background:#ffffff0f}.faq-toc-link.active{background:#ffffff1f;font-weight:600}.faq-toc-empty{padding:1rem .5rem;opacity:.7;font-size:.85rem}.faq-search{display:flex;flex-direction:column;gap:.5rem;padding:.25rem}.faq-search-input{width:100%;padding:.5rem .6rem;border-radius:4px;border:1px solid rgba(255,255,255,.18);background:#00000040;color:inherit;font-size:.9rem;box-sizing:border-box}.faq-search-input:focus{outline:none;border-color:#fff6}.faq-search-status{padding:.5rem;opacity:.65;font-size:.82rem;margin:0}.faq-search-results{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:.15rem}.faq-search-result{display:flex;flex-direction:column;gap:.15rem;width:100%;text-align:left;background:transparent;border:none;color:inherit;padding:.45rem .5rem;border-radius:4px;cursor:pointer}.faq-search-result:hover{background:#ffffff0f}.faq-search-result.active{background:#ffffff1f}.faq-search-result-title{font-size:.9rem;font-weight:600}.faq-search-result-category{font-size:.72rem;opacity:.6;text-transform:uppercase;letter-spacing:.04em}.faq-search-result-snippet{font-size:.78rem;opacity:.75;line-height:1.35}.faq-content{overflow-y:auto;padding:1.25rem 2rem;min-width:0}.faq-loading,.faq-empty{opacity:.75;padding:1rem 0}.faq-empty-chain code{background:#ffffff14;padding:.1rem .4rem;border-radius:3px;font-size:.85rem}.faq-empty-hint{margin-top:1rem;opacity:.55;font-size:.85rem}.faq-article{max-width:70ch;line-height:1.55;font-size:.95rem}.faq-article h1,.faq-article h2,.faq-article h3{font-weight:600;margin:1.4rem 0 .6rem}.faq-article h1{font-size:1.4rem;margin-top:0}.faq-article h2{font-size:1.15rem}.faq-article h3{font-size:1rem}.faq-article p{margin:.6rem 0}.faq-article a{color:var(--shell-link, #6ea8fe);text-decoration:none}.faq-article a:hover{text-decoration:underline}.faq-article a[data-faq-kind=external]:after{content:\" \\2197\";opacity:.65;font-size:.85em}.faq-article .faq-app-arrow{opacity:.7;font-size:.9em}.faq-article code{background:#ffffff14;padding:.1rem .35rem;border-radius:3px;font-size:.88em}.faq-article pre{background:#00000059;padding:.75rem 1rem;border-radius:4px;overflow-x:auto}.faq-article pre code{background:transparent;padding:0}.faq-article img{max-width:100%;border-radius:4px;margin:.6rem 0}.faq-article ul,.faq-article ol{padding-left:1.4rem;margin:.6rem 0}.faq-article blockquote{border-left:3px solid var(--shell-border, rgba(255, 255, 255, .15));padding-left:.9rem;margin:.8rem 0;opacity:.85}@media(max-width:900px){.faq-modal{width:100vw;height:100vh;border-radius:0;max-width:none;max-height:none}.faq-backdrop{padding:0}.faq-body{grid-template-columns:1fr}.faq-sidebar{display:none}.faq-body:not(.sidebar-collapsed) .faq-sidebar{display:block;position:absolute;inset:0;z-index:1}}\n"] }]
|
|
1113
1163
|
}], ctorParameters: () => [], propDecorators: { contentPaneRef: [{
|
|
@@ -1157,37 +1207,49 @@ class FaqAuthoringPanel {
|
|
|
1157
1207
|
this.workspaceRoot = inject(FAQ_DEV_WORKSPACE_ROOT);
|
|
1158
1208
|
this.editor = inject(FAQ_DEV_EDITOR);
|
|
1159
1209
|
/** `'missing'` shows the full scaffold; `'existing'` shows the collapsed strip. */
|
|
1160
|
-
this.mode = input.required(
|
|
1210
|
+
this.mode = input.required(/* @ts-ignore */
|
|
1211
|
+
...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
1161
1212
|
/**
|
|
1162
1213
|
* The dot-notation key actually being authored. For `missing` mode this is
|
|
1163
1214
|
* the deepest attempted key (chain[0]); for `existing` it's the resolved key.
|
|
1164
1215
|
*/
|
|
1165
|
-
this.key = input.required(
|
|
1216
|
+
this.key = input.required(/* @ts-ignore */
|
|
1217
|
+
...(ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []));
|
|
1166
1218
|
/** Fallback chain that was attempted. For `missing` every entry is missing. */
|
|
1167
|
-
this.attempted = input([],
|
|
1219
|
+
this.attempted = input([], /* @ts-ignore */
|
|
1220
|
+
...(ngDevMode ? [{ debugName: "attempted" }] : /* istanbul ignore next */ []));
|
|
1168
1221
|
/** Resolved entry — only set in `existing` mode. */
|
|
1169
|
-
this.entry = input(null,
|
|
1170
|
-
|
|
1171
|
-
this.
|
|
1172
|
-
|
|
1222
|
+
this.entry = input(null, /* @ts-ignore */
|
|
1223
|
+
...(ngDevMode ? [{ debugName: "entry" }] : /* istanbul ignore next */ []));
|
|
1224
|
+
this.expanded = signal(false, /* @ts-ignore */
|
|
1225
|
+
...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
1226
|
+
this.showAllFiles = signal(false, /* @ts-ignore */
|
|
1227
|
+
...(ngDevMode ? [{ debugName: "showAllFiles" }] : /* istanbul ignore next */ []));
|
|
1228
|
+
this.copyState = signal(null, /* @ts-ignore */
|
|
1229
|
+
...(ngDevMode ? [{ debugName: "copyState" }] : /* istanbul ignore next */ []));
|
|
1173
1230
|
this.relPath = computed(() => {
|
|
1174
1231
|
const e = this.entry();
|
|
1175
1232
|
if (e)
|
|
1176
1233
|
return `src/assets/faq/${e.file}.md`;
|
|
1177
1234
|
return `src/assets/faq/${keyToFilePath(this.key())}.md`;
|
|
1178
|
-
},
|
|
1235
|
+
}, /* @ts-ignore */
|
|
1236
|
+
...(ngDevMode ? [{ debugName: "relPath" }] : /* istanbul ignore next */ []));
|
|
1179
1237
|
this.absPath = computed(() => {
|
|
1180
1238
|
const rel = this.relPath();
|
|
1181
1239
|
return this.workspaceRoot ? joinPosix(this.workspaceRoot, rel) : rel;
|
|
1182
|
-
},
|
|
1240
|
+
}, /* @ts-ignore */
|
|
1241
|
+
...(ngDevMode ? [{ debugName: "absPath" }] : /* istanbul ignore next */ []));
|
|
1183
1242
|
this.editorHref = computed(() => {
|
|
1184
1243
|
const abs = this.absPath();
|
|
1185
1244
|
if (this.editor === 'vscode')
|
|
1186
1245
|
return `vscode://file/${abs}`;
|
|
1187
1246
|
return `webstorm://open?file=${encodeURI(abs)}`;
|
|
1188
|
-
},
|
|
1189
|
-
|
|
1190
|
-
this.
|
|
1247
|
+
}, /* @ts-ignore */
|
|
1248
|
+
...(ngDevMode ? [{ debugName: "editorHref" }] : /* istanbul ignore next */ []));
|
|
1249
|
+
this.editorLabel = computed(() => this.editor === 'vscode' ? 'Open in VS Code' : 'Open in WebStorm', /* @ts-ignore */
|
|
1250
|
+
...(ngDevMode ? [{ debugName: "editorLabel" }] : /* istanbul ignore next */ []));
|
|
1251
|
+
this.scaffoldCmd = computed(() => `npm run faq:new -- ${this.key()}`, /* @ts-ignore */
|
|
1252
|
+
...(ngDevMode ? [{ debugName: "scaffoldCmd" }] : /* istanbul ignore next */ []));
|
|
1191
1253
|
this.frontmatterScaffold = computed(() => {
|
|
1192
1254
|
const k = this.key();
|
|
1193
1255
|
const title = humanize(k);
|
|
@@ -1206,12 +1268,15 @@ class FaqAuthoringPanel {
|
|
|
1206
1268
|
`TODO: write content for "${title}".`,
|
|
1207
1269
|
'',
|
|
1208
1270
|
].join('\n');
|
|
1209
|
-
},
|
|
1210
|
-
|
|
1271
|
+
}, /* @ts-ignore */
|
|
1272
|
+
...(ngDevMode ? [{ debugName: "frontmatterScaffold" }] : /* istanbul ignore next */ []));
|
|
1273
|
+
this.allEntries = computed(() => this.faq.entries(), /* @ts-ignore */
|
|
1274
|
+
...(ngDevMode ? [{ debugName: "allEntries" }] : /* istanbul ignore next */ []));
|
|
1211
1275
|
this.missedChain = computed(() => {
|
|
1212
1276
|
const present = new Set(this.allEntries().map((e) => e.key));
|
|
1213
1277
|
return this.attempted().map((k) => ({ key: k, present: present.has(k) }));
|
|
1214
|
-
},
|
|
1278
|
+
}, /* @ts-ignore */
|
|
1279
|
+
...(ngDevMode ? [{ debugName: "missedChain" }] : /* istanbul ignore next */ []));
|
|
1215
1280
|
}
|
|
1216
1281
|
toggleExpanded() {
|
|
1217
1282
|
this.expanded.update((v) => !v);
|
|
@@ -1232,10 +1297,10 @@ class FaqAuthoringPanel {
|
|
|
1232
1297
|
this.copyState.set(`${label}:err`);
|
|
1233
1298
|
}
|
|
1234
1299
|
}
|
|
1235
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1236
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1300
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqAuthoringPanel, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1301
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: FaqAuthoringPanel, isStandalone: true, selector: "faq-authoring-panel", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, attempted: { classPropertyName: "attempted", publicName: "attempted", isSignal: true, isRequired: false, transformFunction: null }, entry: { classPropertyName: "entry", publicName: "entry", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (mode() === 'missing') {\n <section class=\"faq-authoring missing\" aria-label=\"FAQ authoring panel\">\n <header class=\"faq-authoring-header\">\n <span class=\"faq-authoring-tag\">[dev]</span>\n <h3>Start authoring this FAQ</h3>\n </header>\n\n <dl class=\"faq-authoring-meta\">\n <dt>Key</dt>\n <dd><code>{{ key() }}</code></dd>\n\n <dt>Fallback chain</dt>\n <dd>\n <ul class=\"faq-authoring-chain\">\n @for (step of missedChain(); track step.key) {\n <li [ngClass]=\"step.present ? 'present' : 'missed'\">\n <span class=\"mark\">{{ step.present ? '\u2713' : '\u2717' }}</span>\n <code>{{ step.key }}</code>\n </li>\n }\n </ul>\n </dd>\n\n <dt>Target file</dt>\n <dd>\n <code>{{ relPath() }}</code>\n <a\n class=\"faq-authoring-editor\"\n [href]=\"editorHref()\"\n >{{ editorLabel() }} \u2197</a>\n </dd>\n </dl>\n\n <div class=\"faq-authoring-block\">\n <div class=\"faq-authoring-block-head\">\n <span>Scaffold via CLI</span>\n <button type=\"button\" (click)=\"copy(scaffoldCmd(), 'cmd')\">\n {{ copyState() === 'cmd' ? 'Copied \u2713' : 'Copy' }}\n </button>\n </div>\n <pre><code>{{ scaffoldCmd() }}</code></pre>\n </div>\n\n <div class=\"faq-authoring-block\">\n <div class=\"faq-authoring-block-head\">\n <span>Frontmatter scaffold</span>\n <button type=\"button\" (click)=\"copy(frontmatterScaffold(), 'fm')\">\n {{ copyState() === 'fm' ? 'Copied \u2713' : 'Copy' }}\n </button>\n </div>\n <pre><code>{{ frontmatterScaffold() }}</code></pre>\n </div>\n\n <details class=\"faq-authoring-cheat\">\n <summary>Link syntax cheat sheet</summary>\n <ul>\n <li><code>[label](faq:trade.segments)</code> \u2014 in-modal nav</li>\n <li><code>[label](app:/settings)</code> \u2014 navigates the app (modal closes)</li>\n <li><code>[label](https://example.com)</code> \u2014 external (new tab)</li>\n <li><code>[label](#section-id)</code> \u2014 intra-page anchor</li>\n <li><code></code> \u2014 image (drop into <code>src/assets/faq/images/</code>)</li>\n </ul>\n </details>\n\n <details class=\"faq-authoring-all\" [open]=\"showAllFiles()\">\n <summary (click)=\"toggleAllFiles(); $event.preventDefault()\">\n Show all FAQ files ({{ allEntries().length }})\n </summary>\n <ul class=\"faq-authoring-file-list\">\n @for (e of allEntries(); track e.key) {\n <li>\n <code>{{ e.key }}</code>\n <span class=\"faq-authoring-file-path\">src/assets/faq/{{ e.file }}.md</span>\n </li>\n } @empty {\n <li class=\"empty\">Manifest is empty.</li>\n }\n </ul>\n </details>\n </section>\n} @else {\n <aside class=\"faq-authoring existing\" aria-label=\"FAQ source info\">\n <div class=\"faq-authoring-strip\">\n <span class=\"faq-authoring-tag\">[dev]</span>\n <span>Key: <code>{{ key() }}</code></span>\n <span class=\"sep\">\u2022</span>\n <span>Source: <code>{{ relPath() }}</code></span>\n <a class=\"faq-authoring-editor\" [href]=\"editorHref()\">{{ editorLabel() }} \u2197</a>\n <button type=\"button\" class=\"faq-authoring-more\" (click)=\"toggleExpanded()\">\n {{ expanded() ? '\u25B2 Less' : '\u25BC More' }}\n </button>\n </div>\n @if (expanded()) {\n <div class=\"faq-authoring-expanded\">\n <div>\n <strong>Fallback chain attempted:</strong>\n <ul class=\"faq-authoring-chain inline\">\n @for (step of missedChain(); track step.key) {\n <li [ngClass]=\"step.present ? 'present' : 'missed'\">\n <span class=\"mark\">{{ step.present ? '\u2713' : '\u2717' }}</span>\n <code>{{ step.key }}</code>\n </li>\n }\n </ul>\n </div>\n <details class=\"faq-authoring-cheat\" open>\n <summary>Link syntax cheat sheet</summary>\n <ul>\n <li><code>[label](faq:trade.segments)</code> \u2014 in-modal nav</li>\n <li><code>[label](app:/settings)</code> \u2014 navigates the app</li>\n <li><code>[label](https://example.com)</code> \u2014 external</li>\n <li><code>[label](#section-id)</code> \u2014 intra-page anchor</li>\n <li><code></code> \u2014 image</li>\n </ul>\n </details>\n <div class=\"faq-authoring-rescaffold\">\n <span>Re-scaffold (overwrites if you delete first):</span>\n <code>{{ scaffoldCmd() }}</code>\n <button type=\"button\" (click)=\"copy(scaffoldCmd(), 'cmd')\">\n {{ copyState() === 'cmd' ? 'Copied \u2713' : 'Copy' }}\n </button>\n </div>\n </div>\n }\n </aside>\n}\n", styles: [":host{display:block;font-family:var(--shell-font, system-ui, sans-serif);font-size:.875rem;color:var(--shell-fg, #e6e6e6)}.faq-authoring{border:1px dashed var(--shell-accent, #6aa0ff);border-radius:6px;background:#6aa0ff0a}.faq-authoring.missing{padding:1rem 1.25rem;display:grid;gap:.85rem}.faq-authoring.existing{margin-top:1.5rem;padding:.5rem .75rem;background:#6aa0ff08;border-style:dotted}.faq-authoring-header{display:flex;align-items:baseline;gap:.5rem;margin:0}.faq-authoring-header h3{margin:0;font-size:1rem}.faq-authoring-tag{display:inline-block;padding:.05rem .4rem;background:var(--shell-accent, #6aa0ff);color:#0b0d11;border-radius:3px;font-size:.7rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.faq-authoring-meta{display:grid;grid-template-columns:max-content 1fr;gap:.35rem .85rem;margin:0}.faq-authoring-meta dt{font-weight:600;opacity:.75}.faq-authoring-meta dd{margin:0}.faq-authoring code{font-family:var(--shell-mono, ui-monospace, monospace);background:#ffffff0f;padding:.05rem .3rem;border-radius:3px;font-size:.85em}.faq-authoring-chain{list-style:none;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:.4rem}.faq-authoring-chain.inline{display:inline-flex;margin-left:.5rem}.faq-authoring-chain li{display:inline-flex;align-items:center;gap:.25rem}.faq-authoring-chain .mark{font-weight:700}.faq-authoring-chain .missed .mark{color:#ff7676}.faq-authoring-chain .present .mark{color:#8ad27a}.faq-authoring-editor{margin-left:.75rem;color:var(--shell-accent, #6aa0ff);text-decoration:none}.faq-authoring-editor:hover{text-decoration:underline}.faq-authoring-block{border:1px solid var(--shell-border, rgba(255, 255, 255, .08));border-radius:4px;overflow:hidden}.faq-authoring-block-head{display:flex;justify-content:space-between;align-items:center;padding:.4rem .6rem;background:#ffffff0a;font-weight:600;font-size:.8rem}.faq-authoring-block-head button,.faq-authoring-more,.faq-authoring-rescaffold button{background:var(--shell-accent, #6aa0ff);color:#0b0d11;border:0;border-radius:3px;padding:.2rem .55rem;font-size:.75rem;cursor:pointer;font-family:inherit}.faq-authoring-block pre{margin:0;padding:.6rem .75rem;overflow-x:auto;background:#00000040;font-size:.8rem}.faq-authoring-cheat,.faq-authoring-all{font-size:.85rem}.faq-authoring-cheat summary,.faq-authoring-all summary{cursor:pointer;opacity:.85}.faq-authoring-cheat ul,.faq-authoring-file-list{margin:.4rem 0 0;padding-left:1.25rem}.faq-authoring-file-list{list-style:none;padding-left:0;max-height:200px;overflow-y:auto}.faq-authoring-file-list li{display:flex;justify-content:space-between;gap:.5rem;padding:.15rem 0;border-bottom:1px solid rgba(255,255,255,.04)}.faq-authoring-file-path{opacity:.6;font-family:var(--shell-mono, ui-monospace, monospace);font-size:.75rem}.faq-authoring-strip{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;font-size:.8rem}.faq-authoring-strip .sep{opacity:.4}.faq-authoring-more{margin-left:auto}.faq-authoring-expanded{margin-top:.6rem;padding-top:.5rem;border-top:1px solid rgba(255,255,255,.08);display:grid;gap:.6rem}.faq-authoring-rescaffold{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;font-size:.8rem}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1237
1302
|
}
|
|
1238
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1303
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqAuthoringPanel, decorators: [{
|
|
1239
1304
|
type: Component,
|
|
1240
1305
|
args: [{ selector: 'faq-authoring-panel', standalone: true, imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (mode() === 'missing') {\n <section class=\"faq-authoring missing\" aria-label=\"FAQ authoring panel\">\n <header class=\"faq-authoring-header\">\n <span class=\"faq-authoring-tag\">[dev]</span>\n <h3>Start authoring this FAQ</h3>\n </header>\n\n <dl class=\"faq-authoring-meta\">\n <dt>Key</dt>\n <dd><code>{{ key() }}</code></dd>\n\n <dt>Fallback chain</dt>\n <dd>\n <ul class=\"faq-authoring-chain\">\n @for (step of missedChain(); track step.key) {\n <li [ngClass]=\"step.present ? 'present' : 'missed'\">\n <span class=\"mark\">{{ step.present ? '\u2713' : '\u2717' }}</span>\n <code>{{ step.key }}</code>\n </li>\n }\n </ul>\n </dd>\n\n <dt>Target file</dt>\n <dd>\n <code>{{ relPath() }}</code>\n <a\n class=\"faq-authoring-editor\"\n [href]=\"editorHref()\"\n >{{ editorLabel() }} \u2197</a>\n </dd>\n </dl>\n\n <div class=\"faq-authoring-block\">\n <div class=\"faq-authoring-block-head\">\n <span>Scaffold via CLI</span>\n <button type=\"button\" (click)=\"copy(scaffoldCmd(), 'cmd')\">\n {{ copyState() === 'cmd' ? 'Copied \u2713' : 'Copy' }}\n </button>\n </div>\n <pre><code>{{ scaffoldCmd() }}</code></pre>\n </div>\n\n <div class=\"faq-authoring-block\">\n <div class=\"faq-authoring-block-head\">\n <span>Frontmatter scaffold</span>\n <button type=\"button\" (click)=\"copy(frontmatterScaffold(), 'fm')\">\n {{ copyState() === 'fm' ? 'Copied \u2713' : 'Copy' }}\n </button>\n </div>\n <pre><code>{{ frontmatterScaffold() }}</code></pre>\n </div>\n\n <details class=\"faq-authoring-cheat\">\n <summary>Link syntax cheat sheet</summary>\n <ul>\n <li><code>[label](faq:trade.segments)</code> \u2014 in-modal nav</li>\n <li><code>[label](app:/settings)</code> \u2014 navigates the app (modal closes)</li>\n <li><code>[label](https://example.com)</code> \u2014 external (new tab)</li>\n <li><code>[label](#section-id)</code> \u2014 intra-page anchor</li>\n <li><code></code> \u2014 image (drop into <code>src/assets/faq/images/</code>)</li>\n </ul>\n </details>\n\n <details class=\"faq-authoring-all\" [open]=\"showAllFiles()\">\n <summary (click)=\"toggleAllFiles(); $event.preventDefault()\">\n Show all FAQ files ({{ allEntries().length }})\n </summary>\n <ul class=\"faq-authoring-file-list\">\n @for (e of allEntries(); track e.key) {\n <li>\n <code>{{ e.key }}</code>\n <span class=\"faq-authoring-file-path\">src/assets/faq/{{ e.file }}.md</span>\n </li>\n } @empty {\n <li class=\"empty\">Manifest is empty.</li>\n }\n </ul>\n </details>\n </section>\n} @else {\n <aside class=\"faq-authoring existing\" aria-label=\"FAQ source info\">\n <div class=\"faq-authoring-strip\">\n <span class=\"faq-authoring-tag\">[dev]</span>\n <span>Key: <code>{{ key() }}</code></span>\n <span class=\"sep\">\u2022</span>\n <span>Source: <code>{{ relPath() }}</code></span>\n <a class=\"faq-authoring-editor\" [href]=\"editorHref()\">{{ editorLabel() }} \u2197</a>\n <button type=\"button\" class=\"faq-authoring-more\" (click)=\"toggleExpanded()\">\n {{ expanded() ? '\u25B2 Less' : '\u25BC More' }}\n </button>\n </div>\n @if (expanded()) {\n <div class=\"faq-authoring-expanded\">\n <div>\n <strong>Fallback chain attempted:</strong>\n <ul class=\"faq-authoring-chain inline\">\n @for (step of missedChain(); track step.key) {\n <li [ngClass]=\"step.present ? 'present' : 'missed'\">\n <span class=\"mark\">{{ step.present ? '\u2713' : '\u2717' }}</span>\n <code>{{ step.key }}</code>\n </li>\n }\n </ul>\n </div>\n <details class=\"faq-authoring-cheat\" open>\n <summary>Link syntax cheat sheet</summary>\n <ul>\n <li><code>[label](faq:trade.segments)</code> \u2014 in-modal nav</li>\n <li><code>[label](app:/settings)</code> \u2014 navigates the app</li>\n <li><code>[label](https://example.com)</code> \u2014 external</li>\n <li><code>[label](#section-id)</code> \u2014 intra-page anchor</li>\n <li><code></code> \u2014 image</li>\n </ul>\n </details>\n <div class=\"faq-authoring-rescaffold\">\n <span>Re-scaffold (overwrites if you delete first):</span>\n <code>{{ scaffoldCmd() }}</code>\n <button type=\"button\" (click)=\"copy(scaffoldCmd(), 'cmd')\">\n {{ copyState() === 'cmd' ? 'Copied \u2713' : 'Copy' }}\n </button>\n </div>\n </div>\n }\n </aside>\n}\n", styles: [":host{display:block;font-family:var(--shell-font, system-ui, sans-serif);font-size:.875rem;color:var(--shell-fg, #e6e6e6)}.faq-authoring{border:1px dashed var(--shell-accent, #6aa0ff);border-radius:6px;background:#6aa0ff0a}.faq-authoring.missing{padding:1rem 1.25rem;display:grid;gap:.85rem}.faq-authoring.existing{margin-top:1.5rem;padding:.5rem .75rem;background:#6aa0ff08;border-style:dotted}.faq-authoring-header{display:flex;align-items:baseline;gap:.5rem;margin:0}.faq-authoring-header h3{margin:0;font-size:1rem}.faq-authoring-tag{display:inline-block;padding:.05rem .4rem;background:var(--shell-accent, #6aa0ff);color:#0b0d11;border-radius:3px;font-size:.7rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.faq-authoring-meta{display:grid;grid-template-columns:max-content 1fr;gap:.35rem .85rem;margin:0}.faq-authoring-meta dt{font-weight:600;opacity:.75}.faq-authoring-meta dd{margin:0}.faq-authoring code{font-family:var(--shell-mono, ui-monospace, monospace);background:#ffffff0f;padding:.05rem .3rem;border-radius:3px;font-size:.85em}.faq-authoring-chain{list-style:none;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:.4rem}.faq-authoring-chain.inline{display:inline-flex;margin-left:.5rem}.faq-authoring-chain li{display:inline-flex;align-items:center;gap:.25rem}.faq-authoring-chain .mark{font-weight:700}.faq-authoring-chain .missed .mark{color:#ff7676}.faq-authoring-chain .present .mark{color:#8ad27a}.faq-authoring-editor{margin-left:.75rem;color:var(--shell-accent, #6aa0ff);text-decoration:none}.faq-authoring-editor:hover{text-decoration:underline}.faq-authoring-block{border:1px solid var(--shell-border, rgba(255, 255, 255, .08));border-radius:4px;overflow:hidden}.faq-authoring-block-head{display:flex;justify-content:space-between;align-items:center;padding:.4rem .6rem;background:#ffffff0a;font-weight:600;font-size:.8rem}.faq-authoring-block-head button,.faq-authoring-more,.faq-authoring-rescaffold button{background:var(--shell-accent, #6aa0ff);color:#0b0d11;border:0;border-radius:3px;padding:.2rem .55rem;font-size:.75rem;cursor:pointer;font-family:inherit}.faq-authoring-block pre{margin:0;padding:.6rem .75rem;overflow-x:auto;background:#00000040;font-size:.8rem}.faq-authoring-cheat,.faq-authoring-all{font-size:.85rem}.faq-authoring-cheat summary,.faq-authoring-all summary{cursor:pointer;opacity:.85}.faq-authoring-cheat ul,.faq-authoring-file-list{margin:.4rem 0 0;padding-left:1.25rem}.faq-authoring-file-list{list-style:none;padding-left:0;max-height:200px;overflow-y:auto}.faq-authoring-file-list li{display:flex;justify-content:space-between;gap:.5rem;padding:.15rem 0;border-bottom:1px solid rgba(255,255,255,.04)}.faq-authoring-file-path{opacity:.6;font-family:var(--shell-mono, ui-monospace, monospace);font-size:.75rem}.faq-authoring-strip{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;font-size:.8rem}.faq-authoring-strip .sep{opacity:.4}.faq-authoring-more{margin-left:auto}.faq-authoring-expanded{margin-top:.6rem;padding-top:.5rem;border-top:1px solid rgba(255,255,255,.08);display:grid;gap:.6rem}.faq-authoring-rescaffold{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;font-size:.8rem}\n"] }]
|
|
1241
1306
|
}], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], attempted: [{ type: i0.Input, args: [{ isSignal: true, alias: "attempted", required: false }] }], entry: [{ type: i0.Input, args: [{ isSignal: true, alias: "entry", required: false }] }] } });
|
|
@@ -1273,8 +1338,10 @@ class PublicFaqToc {
|
|
|
1273
1338
|
constructor() {
|
|
1274
1339
|
this.loader = inject(FAQ_CONTENT_LOADER);
|
|
1275
1340
|
/** Currently-active entry file path (e.g. `landing`). Empty/undefined on the index. */
|
|
1276
|
-
this.activeFile = input(undefined,
|
|
1277
|
-
|
|
1341
|
+
this.activeFile = input(undefined, /* @ts-ignore */
|
|
1342
|
+
...(ngDevMode ? [{ debugName: "activeFile" }] : /* istanbul ignore next */ []));
|
|
1343
|
+
this._entries = signal([], /* @ts-ignore */
|
|
1344
|
+
...(ngDevMode ? [{ debugName: "_entries" }] : /* istanbul ignore next */ []));
|
|
1278
1345
|
this.groups = computed(() => {
|
|
1279
1346
|
const visible = this._entries().filter((e) => e.audience === 'public' && e.seoReady);
|
|
1280
1347
|
const byCategory = new Map();
|
|
@@ -1290,14 +1357,15 @@ class PublicFaqToc {
|
|
|
1290
1357
|
}
|
|
1291
1358
|
groups.sort((a, b) => a.category.localeCompare(b.category));
|
|
1292
1359
|
return groups;
|
|
1293
|
-
},
|
|
1360
|
+
}, /* @ts-ignore */
|
|
1361
|
+
...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
|
|
1294
1362
|
}
|
|
1295
1363
|
async ngOnInit() {
|
|
1296
1364
|
const manifest = await this.loader.loadManifest();
|
|
1297
1365
|
this._entries.set(manifest.entries);
|
|
1298
1366
|
}
|
|
1299
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1300
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1367
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PublicFaqToc, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1368
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: PublicFaqToc, isStandalone: true, selector: "public-faq-toc", inputs: { activeFile: { classPropertyName: "activeFile", publicName: "activeFile", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
1301
1369
|
<nav class="public-faq-toc" aria-label="Help contents">
|
|
1302
1370
|
<a
|
|
1303
1371
|
class="public-faq-toc__index"
|
|
@@ -1321,9 +1389,9 @@ class PublicFaqToc {
|
|
|
1321
1389
|
</div>
|
|
1322
1390
|
}
|
|
1323
1391
|
</nav>
|
|
1324
|
-
`, isInline: true, styles: [":host{display:block}.public-faq-toc{padding:1.25rem 1rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;font-size:.95rem;line-height:1.4}.public-faq-toc__index{display:block;font-weight:600;color:#cfd6e4;text-decoration:none;padding:.4rem .5rem;border-radius:4px;margin-bottom:.75rem}.public-faq-toc__index.active,.public-faq-toc__index:hover{background:#ffffff0f}.public-faq-toc__group{margin-bottom:1rem}.public-faq-toc__category{font-size:.75rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#8a93a3;margin:0 0 .35rem;padding:0 .5rem}.public-faq-toc ul{list-style:none;padding:0;margin:0}.public-faq-toc li a{display:block;padding:.35rem .5rem;border-radius:4px;color:#cfd6e4;text-decoration:none}.public-faq-toc li a:hover{background:#ffffff0d}.public-faq-toc li a.active{background:#6ea8fe2e;color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] }); }
|
|
1392
|
+
`, isInline: true, styles: [":host{display:block}.public-faq-toc{padding:1.25rem 1rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;font-size:.95rem;line-height:1.4}.public-faq-toc__index{display:block;font-weight:600;color:#cfd6e4;text-decoration:none;padding:.4rem .5rem;border-radius:4px;margin-bottom:.75rem}.public-faq-toc__index.active,.public-faq-toc__index:hover{background:#ffffff0f}.public-faq-toc__group{margin-bottom:1rem}.public-faq-toc__category{font-size:.75rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#8a93a3;margin:0 0 .35rem;padding:0 .5rem}.public-faq-toc ul{list-style:none;padding:0;margin:0}.public-faq-toc li a{display:block;padding:.35rem .5rem;border-radius:4px;color:#cfd6e4;text-decoration:none}.public-faq-toc li a:hover{background:#ffffff0d}.public-faq-toc li a.active{background:#6ea8fe2e;color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
1325
1393
|
}
|
|
1326
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1394
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PublicFaqToc, decorators: [{
|
|
1327
1395
|
type: Component,
|
|
1328
1396
|
args: [{ selector: 'public-faq-toc', standalone: true, imports: [CommonModule, RouterLink, RouterLinkActive], template: `
|
|
1329
1397
|
<nav class="public-faq-toc" aria-label="Help contents">
|
|
@@ -1349,7 +1417,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
1349
1417
|
</div>
|
|
1350
1418
|
}
|
|
1351
1419
|
</nav>
|
|
1352
|
-
`, styles: [":host{display:block}.public-faq-toc{padding:1.25rem 1rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;font-size:.95rem;line-height:1.4}.public-faq-toc__index{display:block;font-weight:600;color:#cfd6e4;text-decoration:none;padding:.4rem .5rem;border-radius:4px;margin-bottom:.75rem}.public-faq-toc__index.active,.public-faq-toc__index:hover{background:#ffffff0f}.public-faq-toc__group{margin-bottom:1rem}.public-faq-toc__category{font-size:.75rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#8a93a3;margin:0 0 .35rem;padding:0 .5rem}.public-faq-toc ul{list-style:none;padding:0;margin:0}.public-faq-toc li a{display:block;padding:.35rem .5rem;border-radius:4px;color:#cfd6e4;text-decoration:none}.public-faq-toc li a:hover{background:#ffffff0d}.public-faq-toc li a.active{background:#6ea8fe2e;color:#fff}\n"] }]
|
|
1420
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block}.public-faq-toc{padding:1.25rem 1rem;font-family:system-ui,-apple-system,Segoe UI,sans-serif;font-size:.95rem;line-height:1.4}.public-faq-toc__index{display:block;font-weight:600;color:#cfd6e4;text-decoration:none;padding:.4rem .5rem;border-radius:4px;margin-bottom:.75rem}.public-faq-toc__index.active,.public-faq-toc__index:hover{background:#ffffff0f}.public-faq-toc__group{margin-bottom:1rem}.public-faq-toc__category{font-size:.75rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:#8a93a3;margin:0 0 .35rem;padding:0 .5rem}.public-faq-toc ul{list-style:none;padding:0;margin:0}.public-faq-toc li a{display:block;padding:.35rem .5rem;border-radius:4px;color:#cfd6e4;text-decoration:none}.public-faq-toc li a:hover{background:#ffffff0d}.public-faq-toc li a.active{background:#6ea8fe2e;color:#fff}\n"] }]
|
|
1353
1421
|
}], propDecorators: { activeFile: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeFile", required: false }] }] } });
|
|
1354
1422
|
|
|
1355
1423
|
/**
|
|
@@ -1379,9 +1447,12 @@ class PublicFaqIndex {
|
|
|
1379
1447
|
this.meta = inject(Meta);
|
|
1380
1448
|
this.siteBase = inject(FAQ_PUBLIC_SITE_BASE_URL);
|
|
1381
1449
|
this.publisher = inject(FAQ_PUBLIC_PUBLISHER);
|
|
1382
|
-
this._entries = signal([],
|
|
1383
|
-
|
|
1384
|
-
this.
|
|
1450
|
+
this._entries = signal([], /* @ts-ignore */
|
|
1451
|
+
...(ngDevMode ? [{ debugName: "_entries" }] : /* istanbul ignore next */ []));
|
|
1452
|
+
this.loading = signal(true, /* @ts-ignore */
|
|
1453
|
+
...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
1454
|
+
this.visibleEntries = computed(() => this._entries().filter((e) => e.audience === 'public' && e.seoReady), /* @ts-ignore */
|
|
1455
|
+
...(ngDevMode ? [{ debugName: "visibleEntries" }] : /* istanbul ignore next */ []));
|
|
1385
1456
|
this.groups = computed(() => {
|
|
1386
1457
|
const visible = this.visibleEntries();
|
|
1387
1458
|
const byCategory = new Map();
|
|
@@ -1397,7 +1468,8 @@ class PublicFaqIndex {
|
|
|
1397
1468
|
}
|
|
1398
1469
|
groups.sort((a, b) => a.category.localeCompare(b.category));
|
|
1399
1470
|
return groups;
|
|
1400
|
-
},
|
|
1471
|
+
}, /* @ts-ignore */
|
|
1472
|
+
...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
|
|
1401
1473
|
this.jsonLd = computed(() => {
|
|
1402
1474
|
const entries = this.visibleEntries();
|
|
1403
1475
|
if (entries.length === 0)
|
|
@@ -1431,7 +1503,8 @@ class PublicFaqIndex {
|
|
|
1431
1503
|
ld['publisher'] = pub;
|
|
1432
1504
|
}
|
|
1433
1505
|
return serializeJsonLd$1(ld);
|
|
1434
|
-
},
|
|
1506
|
+
}, /* @ts-ignore */
|
|
1507
|
+
...(ngDevMode ? [{ debugName: "jsonLd" }] : /* istanbul ignore next */ []));
|
|
1435
1508
|
}
|
|
1436
1509
|
async ngOnInit() {
|
|
1437
1510
|
try {
|
|
@@ -1460,8 +1533,8 @@ class PublicFaqIndex {
|
|
|
1460
1533
|
this.meta.updateTag({ name: 'twitter:title', content: 'Help — Brokenstock' });
|
|
1461
1534
|
this.meta.updateTag({ name: 'twitter:description', content: description });
|
|
1462
1535
|
}
|
|
1463
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1464
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1536
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PublicFaqIndex, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1537
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: PublicFaqIndex, isStandalone: true, selector: "public-faq-index", ngImport: i0, template: `
|
|
1465
1538
|
<div class="public-faq-layout">
|
|
1466
1539
|
<aside class="public-faq-sidebar">
|
|
1467
1540
|
<public-faq-toc />
|
|
@@ -1497,9 +1570,9 @@ class PublicFaqIndex {
|
|
|
1497
1570
|
}
|
|
1498
1571
|
</article>
|
|
1499
1572
|
</div>
|
|
1500
|
-
`, isInline: true, styles: [":host{display:block}.public-faq-layout{display:grid;grid-template-columns:minmax(220px,280px) 1fr;gap:1.5rem;max-width:1280px;margin:0 auto;padding:1.5rem 1.25rem 4rem}.public-faq-sidebar{border-right:1px solid rgba(255,255,255,.08);align-self:start;position:sticky;top:1rem;max-height:calc(100vh - 2rem);overflow-y:auto}.public-faq-index{max-width:860px;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.55}header h1{font-size:2.25rem;margin:0 0 .5rem}.lead{color:#9aa3b3;margin:0 0 2rem;font-size:1.1rem}h2{font-size:1.35rem;margin:1.75rem 0 .5rem;border-bottom:1px solid rgba(255,255,255,.08);padding-bottom:.25rem}ul{list-style:none;padding:0;margin:0}li{padding:.4rem 0}.public-faq-index a{color:#6ea8fe;text-decoration:none;font-weight:500}.public-faq-index a:hover{text-decoration:underline}.desc{color:#8a93a3;font-weight:400}@media(max-width:900px){.public-faq-layout{grid-template-columns:1fr}.public-faq-sidebar{position:static;max-height:none;border-right:none;border-bottom:1px solid rgba(255,255,255,.08)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: PublicFaqToc, selector: "public-faq-toc", inputs: ["activeFile"] }] }); }
|
|
1573
|
+
`, isInline: true, styles: [":host{display:block}.public-faq-layout{display:grid;grid-template-columns:minmax(220px,280px) 1fr;gap:1.5rem;max-width:1280px;margin:0 auto;padding:1.5rem 1.25rem 4rem}.public-faq-sidebar{border-right:1px solid rgba(255,255,255,.08);align-self:start;position:sticky;top:1rem;max-height:calc(100vh - 2rem);overflow-y:auto}.public-faq-index{max-width:860px;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.55}header h1{font-size:2.25rem;margin:0 0 .5rem}.lead{color:#9aa3b3;margin:0 0 2rem;font-size:1.1rem}h2{font-size:1.35rem;margin:1.75rem 0 .5rem;border-bottom:1px solid rgba(255,255,255,.08);padding-bottom:.25rem}ul{list-style:none;padding:0;margin:0}li{padding:.4rem 0}.public-faq-index a{color:#6ea8fe;text-decoration:none;font-weight:500}.public-faq-index a:hover{text-decoration:underline}.desc{color:#8a93a3;font-weight:400}@media(max-width:900px){.public-faq-layout{grid-template-columns:1fr}.public-faq-sidebar{position:static;max-height:none;border-right:none;border-bottom:1px solid rgba(255,255,255,.08)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "component", type: PublicFaqToc, selector: "public-faq-toc", inputs: ["activeFile"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
1501
1574
|
}
|
|
1502
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1575
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PublicFaqIndex, decorators: [{
|
|
1503
1576
|
type: Component,
|
|
1504
1577
|
args: [{ selector: 'public-faq-index', standalone: true, imports: [CommonModule, RouterLink, PublicFaqToc], template: `
|
|
1505
1578
|
<div class="public-faq-layout">
|
|
@@ -1537,7 +1610,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
1537
1610
|
}
|
|
1538
1611
|
</article>
|
|
1539
1612
|
</div>
|
|
1540
|
-
`, styles: [":host{display:block}.public-faq-layout{display:grid;grid-template-columns:minmax(220px,280px) 1fr;gap:1.5rem;max-width:1280px;margin:0 auto;padding:1.5rem 1.25rem 4rem}.public-faq-sidebar{border-right:1px solid rgba(255,255,255,.08);align-self:start;position:sticky;top:1rem;max-height:calc(100vh - 2rem);overflow-y:auto}.public-faq-index{max-width:860px;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.55}header h1{font-size:2.25rem;margin:0 0 .5rem}.lead{color:#9aa3b3;margin:0 0 2rem;font-size:1.1rem}h2{font-size:1.35rem;margin:1.75rem 0 .5rem;border-bottom:1px solid rgba(255,255,255,.08);padding-bottom:.25rem}ul{list-style:none;padding:0;margin:0}li{padding:.4rem 0}.public-faq-index a{color:#6ea8fe;text-decoration:none;font-weight:500}.public-faq-index a:hover{text-decoration:underline}.desc{color:#8a93a3;font-weight:400}@media(max-width:900px){.public-faq-layout{grid-template-columns:1fr}.public-faq-sidebar{position:static;max-height:none;border-right:none;border-bottom:1px solid rgba(255,255,255,.08)}}\n"] }]
|
|
1613
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block}.public-faq-layout{display:grid;grid-template-columns:minmax(220px,280px) 1fr;gap:1.5rem;max-width:1280px;margin:0 auto;padding:1.5rem 1.25rem 4rem}.public-faq-sidebar{border-right:1px solid rgba(255,255,255,.08);align-self:start;position:sticky;top:1rem;max-height:calc(100vh - 2rem);overflow-y:auto}.public-faq-index{max-width:860px;font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.55}header h1{font-size:2.25rem;margin:0 0 .5rem}.lead{color:#9aa3b3;margin:0 0 2rem;font-size:1.1rem}h2{font-size:1.35rem;margin:1.75rem 0 .5rem;border-bottom:1px solid rgba(255,255,255,.08);padding-bottom:.25rem}ul{list-style:none;padding:0;margin:0}li{padding:.4rem 0}.public-faq-index a{color:#6ea8fe;text-decoration:none;font-weight:500}.public-faq-index a:hover{text-decoration:underline}.desc{color:#8a93a3;font-weight:400}@media(max-width:900px){.public-faq-layout{grid-template-columns:1fr}.public-faq-sidebar{position:static;max-height:none;border-right:none;border-bottom:1px solid rgba(255,255,255,.08)}}\n"] }]
|
|
1541
1614
|
}] });
|
|
1542
1615
|
function serializeJsonLd$1(obj) {
|
|
1543
1616
|
return JSON.stringify(obj).replace(/</g, '\\u003c');
|
|
@@ -1566,10 +1639,14 @@ class PublicFaqPage {
|
|
|
1566
1639
|
this.meta = inject(Meta);
|
|
1567
1640
|
this.siteBase = inject(FAQ_PUBLIC_SITE_BASE_URL);
|
|
1568
1641
|
this.publisher = inject(FAQ_PUBLIC_PUBLISHER);
|
|
1569
|
-
this.entry = signal(null,
|
|
1570
|
-
|
|
1571
|
-
this.
|
|
1572
|
-
|
|
1642
|
+
this.entry = signal(null, /* @ts-ignore */
|
|
1643
|
+
...(ngDevMode ? [{ debugName: "entry" }] : /* istanbul ignore next */ []));
|
|
1644
|
+
this.body = signal('', /* @ts-ignore */
|
|
1645
|
+
...(ngDevMode ? [{ debugName: "body" }] : /* istanbul ignore next */ []));
|
|
1646
|
+
this.loading = signal(true, /* @ts-ignore */
|
|
1647
|
+
...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
1648
|
+
this.activeFile = computed(() => this.entry()?.file, /* @ts-ignore */
|
|
1649
|
+
...(ngDevMode ? [{ debugName: "activeFile" }] : /* istanbul ignore next */ []));
|
|
1573
1650
|
this.renderedHtml = computed(() => {
|
|
1574
1651
|
const entry = this.entry();
|
|
1575
1652
|
const body = this.body();
|
|
@@ -1581,7 +1658,8 @@ class PublicFaqPage {
|
|
|
1581
1658
|
? `/assets/faq/${entry.imagePrefix}`
|
|
1582
1659
|
: undefined,
|
|
1583
1660
|
});
|
|
1584
|
-
},
|
|
1661
|
+
}, /* @ts-ignore */
|
|
1662
|
+
...(ngDevMode ? [{ debugName: "renderedHtml" }] : /* istanbul ignore next */ []));
|
|
1585
1663
|
this.jsonLd = computed(() => {
|
|
1586
1664
|
const entry = this.entry();
|
|
1587
1665
|
if (!entry)
|
|
@@ -1609,7 +1687,8 @@ class PublicFaqPage {
|
|
|
1609
1687
|
ld['author'] = pub;
|
|
1610
1688
|
}
|
|
1611
1689
|
return serializeJsonLd(ld);
|
|
1612
|
-
},
|
|
1690
|
+
}, /* @ts-ignore */
|
|
1691
|
+
...(ngDevMode ? [{ debugName: "jsonLd" }] : /* istanbul ignore next */ []));
|
|
1613
1692
|
}
|
|
1614
1693
|
async ngOnInit() {
|
|
1615
1694
|
try {
|
|
@@ -1664,8 +1743,8 @@ class PublicFaqPage {
|
|
|
1664
1743
|
const base = this.siteBase.replace(/\/+$/, '');
|
|
1665
1744
|
return `${base}/help/${entry.file}`;
|
|
1666
1745
|
}
|
|
1667
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1668
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1746
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PublicFaqPage, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1747
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: PublicFaqPage, isStandalone: true, selector: "public-faq-page", ngImport: i0, template: `
|
|
1669
1748
|
<div class="public-faq-layout">
|
|
1670
1749
|
<aside class="public-faq-sidebar">
|
|
1671
1750
|
<public-faq-toc [activeFile]="activeFile()" />
|
|
@@ -1692,9 +1771,9 @@ class PublicFaqPage {
|
|
|
1692
1771
|
}
|
|
1693
1772
|
</article>
|
|
1694
1773
|
</div>
|
|
1695
|
-
`, isInline: true, styles: [":host{display:block}.public-faq-layout{display:grid;grid-template-columns:minmax(220px,280px) 1fr;gap:1.5rem;max-width:1280px;margin:0 auto;padding:1.5rem 1.25rem 4rem}.public-faq-sidebar{border-right:1px solid rgba(255,255,255,.08);align-self:start;position:sticky;top:1rem;max-height:calc(100vh - 2rem);overflow-y:auto}.public-faq-page{font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.6;max-width:860px}header h1{font-size:2.1rem;margin:0 0 .5rem}.lead{color:#9aa3b3;font-size:1.1rem;margin:0 0 1.5rem}.body :is(h1,h2,h3,h4){margin-top:2rem}.body a{color:#6ea8fe}.body img{max-width:100%;height:auto}.body pre{background:#00000059;padding:.75rem 1rem;border-radius:6px;overflow-x:auto}.body code{background:#ffffff14;padding:.1rem .3rem;border-radius:3px;font-size:.9em}.body pre code{background:transparent;padding:0}@media(max-width:900px){.public-faq-layout{grid-template-columns:1fr}.public-faq-sidebar{position:static;max-height:none;border-right:none;border-bottom:1px solid rgba(255,255,255,.08)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: PublicFaqToc, selector: "public-faq-toc", inputs: ["activeFile"] }] }); }
|
|
1774
|
+
`, isInline: true, styles: [":host{display:block}.public-faq-layout{display:grid;grid-template-columns:minmax(220px,280px) 1fr;gap:1.5rem;max-width:1280px;margin:0 auto;padding:1.5rem 1.25rem 4rem}.public-faq-sidebar{border-right:1px solid rgba(255,255,255,.08);align-self:start;position:sticky;top:1rem;max-height:calc(100vh - 2rem);overflow-y:auto}.public-faq-page{font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.6;max-width:860px}header h1{font-size:2.1rem;margin:0 0 .5rem}.lead{color:#9aa3b3;font-size:1.1rem;margin:0 0 1.5rem}.body :is(h1,h2,h3,h4){margin-top:2rem}.body a{color:#6ea8fe}.body img{max-width:100%;height:auto}.body pre{background:#00000059;padding:.75rem 1rem;border-radius:6px;overflow-x:auto}.body code{background:#ffffff14;padding:.1rem .3rem;border-radius:3px;font-size:.9em}.body pre code{background:transparent;padding:0}@media(max-width:900px){.public-faq-layout{grid-template-columns:1fr}.public-faq-sidebar{position:static;max-height:none;border-right:none;border-bottom:1px solid rgba(255,255,255,.08)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "component", type: PublicFaqToc, selector: "public-faq-toc", inputs: ["activeFile"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
1696
1775
|
}
|
|
1697
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1776
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: PublicFaqPage, decorators: [{
|
|
1698
1777
|
type: Component,
|
|
1699
1778
|
args: [{ selector: 'public-faq-page', standalone: true, imports: [CommonModule, RouterLink, PublicFaqToc], template: `
|
|
1700
1779
|
<div class="public-faq-layout">
|
|
@@ -1723,7 +1802,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
1723
1802
|
}
|
|
1724
1803
|
</article>
|
|
1725
1804
|
</div>
|
|
1726
|
-
`, styles: [":host{display:block}.public-faq-layout{display:grid;grid-template-columns:minmax(220px,280px) 1fr;gap:1.5rem;max-width:1280px;margin:0 auto;padding:1.5rem 1.25rem 4rem}.public-faq-sidebar{border-right:1px solid rgba(255,255,255,.08);align-self:start;position:sticky;top:1rem;max-height:calc(100vh - 2rem);overflow-y:auto}.public-faq-page{font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.6;max-width:860px}header h1{font-size:2.1rem;margin:0 0 .5rem}.lead{color:#9aa3b3;font-size:1.1rem;margin:0 0 1.5rem}.body :is(h1,h2,h3,h4){margin-top:2rem}.body a{color:#6ea8fe}.body img{max-width:100%;height:auto}.body pre{background:#00000059;padding:.75rem 1rem;border-radius:6px;overflow-x:auto}.body code{background:#ffffff14;padding:.1rem .3rem;border-radius:3px;font-size:.9em}.body pre code{background:transparent;padding:0}@media(max-width:900px){.public-faq-layout{grid-template-columns:1fr}.public-faq-sidebar{position:static;max-height:none;border-right:none;border-bottom:1px solid rgba(255,255,255,.08)}}\n"] }]
|
|
1805
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block}.public-faq-layout{display:grid;grid-template-columns:minmax(220px,280px) 1fr;gap:1.5rem;max-width:1280px;margin:0 auto;padding:1.5rem 1.25rem 4rem}.public-faq-sidebar{border-right:1px solid rgba(255,255,255,.08);align-self:start;position:sticky;top:1rem;max-height:calc(100vh - 2rem);overflow-y:auto}.public-faq-page{font-family:system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.6;max-width:860px}header h1{font-size:2.1rem;margin:0 0 .5rem}.lead{color:#9aa3b3;font-size:1.1rem;margin:0 0 1.5rem}.body :is(h1,h2,h3,h4){margin-top:2rem}.body a{color:#6ea8fe}.body img{max-width:100%;height:auto}.body pre{background:#00000059;padding:.75rem 1rem;border-radius:6px;overflow-x:auto}.body code{background:#ffffff14;padding:.1rem .3rem;border-radius:3px;font-size:.9em}.body pre code{background:transparent;padding:0}@media(max-width:900px){.public-faq-layout{grid-template-columns:1fr}.public-faq-sidebar{position:static;max-height:none;border-right:none;border-bottom:1px solid rgba(255,255,255,.08)}}\n"] }]
|
|
1727
1806
|
}] });
|
|
1728
1807
|
/**
|
|
1729
1808
|
* Serializes a JSON-LD object for safe inclusion in a
|
|
@@ -1738,28 +1817,31 @@ function serializeJsonLd(obj) {
|
|
|
1738
1817
|
|
|
1739
1818
|
class ThemeService {
|
|
1740
1819
|
constructor() {
|
|
1741
|
-
this.mode = signal('dark',
|
|
1742
|
-
|
|
1820
|
+
this.mode = signal('dark', /* @ts-ignore */
|
|
1821
|
+
...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
1822
|
+
this.isDark = computed(() => this.mode() === 'dark', /* @ts-ignore */
|
|
1823
|
+
...(ngDevMode ? [{ debugName: "isDark" }] : /* istanbul ignore next */ []));
|
|
1743
1824
|
}
|
|
1744
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1745
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1825
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: ThemeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1826
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: ThemeService, providedIn: 'root' }); }
|
|
1746
1827
|
}
|
|
1747
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1828
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: ThemeService, decorators: [{
|
|
1748
1829
|
type: Injectable,
|
|
1749
1830
|
args: [{ providedIn: 'root' }]
|
|
1750
1831
|
}] });
|
|
1751
1832
|
|
|
1752
1833
|
class TerminalFocusService {
|
|
1753
1834
|
constructor() {
|
|
1754
|
-
this.focusRequested = signal(0,
|
|
1835
|
+
this.focusRequested = signal(0, /* @ts-ignore */
|
|
1836
|
+
...(ngDevMode ? [{ debugName: "focusRequested" }] : /* istanbul ignore next */ []));
|
|
1755
1837
|
}
|
|
1756
1838
|
requestFocus() {
|
|
1757
1839
|
this.focusRequested.update(v => v + 1);
|
|
1758
1840
|
}
|
|
1759
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1760
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1841
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: TerminalFocusService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1842
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: TerminalFocusService, providedIn: 'root' }); }
|
|
1761
1843
|
}
|
|
1762
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1844
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: TerminalFocusService, decorators: [{
|
|
1763
1845
|
type: Injectable,
|
|
1764
1846
|
args: [{ providedIn: 'root' }]
|
|
1765
1847
|
}] });
|
|
@@ -1772,11 +1854,13 @@ class KeyboardShortcutService {
|
|
|
1772
1854
|
#focusService;
|
|
1773
1855
|
constructor() {
|
|
1774
1856
|
this.#groups = new Map();
|
|
1775
|
-
this.#activeGroupId = signal(null,
|
|
1857
|
+
this.#activeGroupId = signal(null, /* @ts-ignore */
|
|
1858
|
+
...(ngDevMode ? [{ debugName: "#activeGroupId" }] : /* istanbul ignore next */ []));
|
|
1776
1859
|
this.#document = inject(DOCUMENT);
|
|
1777
1860
|
this.#zone = inject(NgZone);
|
|
1778
1861
|
this.#focusService = inject(TerminalFocusService);
|
|
1779
|
-
this.helpVisible = signal(false,
|
|
1862
|
+
this.helpVisible = signal(false, /* @ts-ignore */
|
|
1863
|
+
...(ngDevMode ? [{ debugName: "helpVisible" }] : /* istanbul ignore next */ []));
|
|
1780
1864
|
this.activeShortcuts = computed(() => {
|
|
1781
1865
|
const groupId = this.#activeGroupId();
|
|
1782
1866
|
if (!groupId)
|
|
@@ -1785,7 +1869,8 @@ class KeyboardShortcutService {
|
|
|
1785
1869
|
if (!shortcuts)
|
|
1786
1870
|
return null;
|
|
1787
1871
|
return { groupId, shortcuts };
|
|
1788
|
-
},
|
|
1872
|
+
}, /* @ts-ignore */
|
|
1873
|
+
...(ngDevMode ? [{ debugName: "activeShortcuts" }] : /* istanbul ignore next */ []));
|
|
1789
1874
|
this.#zone.runOutsideAngular(() => {
|
|
1790
1875
|
this.#document.addEventListener('keydown', (event) => {
|
|
1791
1876
|
this.#handleKeydown(event);
|
|
@@ -1840,10 +1925,10 @@ class KeyboardShortcutService {
|
|
|
1840
1925
|
}
|
|
1841
1926
|
return false;
|
|
1842
1927
|
}
|
|
1843
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1844
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1928
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: KeyboardShortcutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1929
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: KeyboardShortcutService, providedIn: 'root' }); }
|
|
1845
1930
|
}
|
|
1846
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1931
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: KeyboardShortcutService, decorators: [{
|
|
1847
1932
|
type: Injectable,
|
|
1848
1933
|
args: [{ providedIn: 'root' }]
|
|
1849
1934
|
}], ctorParameters: () => [] });
|
|
@@ -1895,10 +1980,10 @@ class FaqCommand {
|
|
|
1895
1980
|
void this.faqService.openModal(args[0]);
|
|
1896
1981
|
return { success: true, message: '', timestamp: ts() };
|
|
1897
1982
|
}
|
|
1898
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1899
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1983
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1984
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqCommand, providedIn: 'root' }); }
|
|
1900
1985
|
}
|
|
1901
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1986
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: FaqCommand, decorators: [{
|
|
1902
1987
|
type: Injectable,
|
|
1903
1988
|
args: [{ providedIn: 'root' }]
|
|
1904
1989
|
}] });
|
|
@@ -1940,10 +2025,10 @@ class CommandRegistryService {
|
|
|
1940
2025
|
.filter(name => name.startsWith(prefix) && name !== prefix)
|
|
1941
2026
|
.sort();
|
|
1942
2027
|
}
|
|
1943
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1944
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2028
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: CommandRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2029
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: CommandRegistryService, providedIn: 'root' }); }
|
|
1945
2030
|
}
|
|
1946
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2031
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: CommandRegistryService, decorators: [{
|
|
1947
2032
|
type: Injectable,
|
|
1948
2033
|
args: [{ providedIn: 'root' }]
|
|
1949
2034
|
}], ctorParameters: () => [] });
|
|
@@ -1966,16 +2051,21 @@ const HELP_USAGE = 'help [command]\n\n' +
|
|
|
1966
2051
|
const CommandInputSchema = z.string().trim().min(1, 'Command cannot be empty');
|
|
1967
2052
|
class CommandService {
|
|
1968
2053
|
constructor() {
|
|
1969
|
-
this.history = signal([],
|
|
1970
|
-
|
|
1971
|
-
this.
|
|
1972
|
-
|
|
2054
|
+
this.history = signal([], /* @ts-ignore */
|
|
2055
|
+
...(ngDevMode ? [{ debugName: "history" }] : /* istanbul ignore next */ []));
|
|
2056
|
+
this.currentInput = signal('', /* @ts-ignore */
|
|
2057
|
+
...(ngDevMode ? [{ debugName: "currentInput" }] : /* istanbul ignore next */ []));
|
|
2058
|
+
this.isProcessing = signal(false, /* @ts-ignore */
|
|
2059
|
+
...(ngDevMode ? [{ debugName: "isProcessing" }] : /* istanbul ignore next */ []));
|
|
2060
|
+
this.helpOverlay = signal(null, /* @ts-ignore */
|
|
2061
|
+
...(ngDevMode ? [{ debugName: "helpOverlay" }] : /* istanbul ignore next */ []));
|
|
1973
2062
|
this.authService = inject(AuthenticationService);
|
|
1974
2063
|
this.registry = inject(CommandRegistryService);
|
|
1975
2064
|
this.lastResult = computed(() => {
|
|
1976
2065
|
const h = this.history();
|
|
1977
2066
|
return h.length > 0 ? h[h.length - 1].result : null;
|
|
1978
|
-
},
|
|
2067
|
+
}, /* @ts-ignore */
|
|
2068
|
+
...(ngDevMode ? [{ debugName: "lastResult" }] : /* istanbul ignore next */ []));
|
|
1979
2069
|
effect(() => {
|
|
1980
2070
|
if (!this.authService.authenticated()) {
|
|
1981
2071
|
this.history.set([]);
|
|
@@ -2141,10 +2231,10 @@ class CommandService {
|
|
|
2141
2231
|
return { success: false, message: `Unknown command: ${name}`, timestamp: new Date() };
|
|
2142
2232
|
return { success: true, message: def.usage, timestamp: new Date(), isHelp: true };
|
|
2143
2233
|
}
|
|
2144
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2145
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2234
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: CommandService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2235
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: CommandService, providedIn: 'root' }); }
|
|
2146
2236
|
}
|
|
2147
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2237
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: CommandService, decorators: [{
|
|
2148
2238
|
type: Injectable,
|
|
2149
2239
|
args: [{ providedIn: 'root' }]
|
|
2150
2240
|
}], ctorParameters: () => [] });
|
|
@@ -2159,7 +2249,8 @@ class StatusBar {
|
|
|
2159
2249
|
? 'Authenticating...'
|
|
2160
2250
|
: this.#authService.authenticated()
|
|
2161
2251
|
? 'Logged in'
|
|
2162
|
-
: 'Not logged in',
|
|
2252
|
+
: 'Not logged in', /* @ts-ignore */
|
|
2253
|
+
...(ngDevMode ? [{ debugName: "loginStatus" }] : /* istanbul ignore next */ []));
|
|
2163
2254
|
}
|
|
2164
2255
|
#authService;
|
|
2165
2256
|
#focusService;
|
|
@@ -2173,12 +2264,12 @@ class StatusBar {
|
|
|
2173
2264
|
this.#commandService.execute('faq');
|
|
2174
2265
|
this.#focusService.requestFocus();
|
|
2175
2266
|
}
|
|
2176
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2177
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2267
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: StatusBar, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2268
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: StatusBar, isStandalone: true, selector: "shell-status-bar", ngImport: i0, template: "<div class=\"status-bar\">\n <div class=\"status-item\">\n <span class=\"status-label text-secondary-info\">Status:</span>\n @if (isAuthenticated()) {\n <a class=\"status-value text-interactive logout-link\" (click)=\"logout()\">Log Out</a>\n } @else {\n <span class=\"status-value text-loss\">{{ loginStatus() }}</span>\n }\n </div>\n @if (isAuthenticated()) {\n <ng-content />\n }\n <button\n type=\"button\"\n class=\"faq-button text-interactive\"\n (click)=\"openFaq()\"\n title=\"Open FAQ (or type `faq`)\"\n aria-label=\"Open FAQ\"\n >?</button>\n</div>\n", styles: [".status-bar{display:flex;align-items:center;gap:24px;padding:0 16px;height:100%;background-color:var(--color-surface);border-bottom:1px solid var(--color-surface-border);font-size:.8rem}.status-item{display:flex;align-items:baseline;gap:6px}.status-label{font-weight:500;text-transform:uppercase;letter-spacing:.05em;font-size:.7rem}.logout-link{cursor:pointer;text-decoration:underline}.logout-link:hover{opacity:.8}.faq-button{margin-left:auto;background:none;border:1px solid var(--color-surface-border);border-radius:50%;width:22px;height:22px;font-size:.85rem;font-weight:600;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0}.faq-button:hover{opacity:.8}\n"], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2178
2269
|
}
|
|
2179
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2270
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: StatusBar, decorators: [{
|
|
2180
2271
|
type: Component,
|
|
2181
|
-
args: [{ selector: 'shell-status-bar', template: "<div class=\"status-bar\">\n <div class=\"status-item\">\n <span class=\"status-label text-secondary-info\">Status:</span>\n @if (isAuthenticated()) {\n <a class=\"status-value text-interactive logout-link\" (click)=\"logout()\">Log Out</a>\n } @else {\n <span class=\"status-value text-loss\">{{ loginStatus() }}</span>\n }\n </div>\n @if (isAuthenticated()) {\n <ng-content />\n }\n <button\n type=\"button\"\n class=\"faq-button text-interactive\"\n (click)=\"openFaq()\"\n title=\"Open FAQ (or type `faq`)\"\n aria-label=\"Open FAQ\"\n >?</button>\n</div>\n", styles: [".status-bar{display:flex;align-items:center;gap:24px;padding:0 16px;height:100%;background-color:var(--color-surface);border-bottom:1px solid var(--color-surface-border);font-size:.8rem}.status-item{display:flex;align-items:baseline;gap:6px}.status-label{font-weight:500;text-transform:uppercase;letter-spacing:.05em;font-size:.7rem}.logout-link{cursor:pointer;text-decoration:underline}.logout-link:hover{opacity:.8}.faq-button{margin-left:auto;background:none;border:1px solid var(--color-surface-border);border-radius:50%;width:22px;height:22px;font-size:.85rem;font-weight:600;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0}.faq-button:hover{opacity:.8}\n"] }]
|
|
2272
|
+
args: [{ selector: 'shell-status-bar', changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"status-bar\">\n <div class=\"status-item\">\n <span class=\"status-label text-secondary-info\">Status:</span>\n @if (isAuthenticated()) {\n <a class=\"status-value text-interactive logout-link\" (click)=\"logout()\">Log Out</a>\n } @else {\n <span class=\"status-value text-loss\">{{ loginStatus() }}</span>\n }\n </div>\n @if (isAuthenticated()) {\n <ng-content />\n }\n <button\n type=\"button\"\n class=\"faq-button text-interactive\"\n (click)=\"openFaq()\"\n title=\"Open FAQ (or type `faq`)\"\n aria-label=\"Open FAQ\"\n >?</button>\n</div>\n", styles: [".status-bar{display:flex;align-items:center;gap:24px;padding:0 16px;height:100%;background-color:var(--color-surface);border-bottom:1px solid var(--color-surface-border);font-size:.8rem}.status-item{display:flex;align-items:baseline;gap:6px}.status-label{font-weight:500;text-transform:uppercase;letter-spacing:.05em;font-size:.7rem}.logout-link{cursor:pointer;text-decoration:underline}.logout-link:hover{opacity:.8}.faq-button{margin-left:auto;background:none;border:1px solid var(--color-surface-border);border-radius:50%;width:22px;height:22px;font-size:.85rem;font-weight:600;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0}.faq-button:hover{opacity:.8}\n"] }]
|
|
2182
2273
|
}] });
|
|
2183
2274
|
|
|
2184
2275
|
class SideMenu {
|
|
@@ -2188,7 +2279,8 @@ class SideMenu {
|
|
|
2188
2279
|
this.#shortcutService = inject(KeyboardShortcutService);
|
|
2189
2280
|
this.hasShortcuts = this.#shortcutService.activeShortcuts;
|
|
2190
2281
|
this.#allMenuItems = inject(SHELL_MENU_ITEMS, { optional: true }) ?? [];
|
|
2191
|
-
this.menuItems = computed(() => this.#allMenuItems.filter(item => !item.visible || item.visible()),
|
|
2282
|
+
this.menuItems = computed(() => this.#allMenuItems.filter(item => !item.visible || item.visible()), /* @ts-ignore */
|
|
2283
|
+
...(ngDevMode ? [{ debugName: "menuItems" }] : /* istanbul ignore next */ []));
|
|
2192
2284
|
}
|
|
2193
2285
|
#focusService;
|
|
2194
2286
|
#commandService;
|
|
@@ -2203,12 +2295,12 @@ class SideMenu {
|
|
|
2203
2295
|
toggleHelp() {
|
|
2204
2296
|
this.#shortcutService.toggleHelp();
|
|
2205
2297
|
}
|
|
2206
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2207
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2298
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: SideMenu, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2299
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: SideMenu, isStandalone: true, selector: "shell-side-menu", ngImport: i0, template: "<nav class=\"side-menu\">\n @for (item of menuItems(); track item.route) {\n <a\n class=\"menu-item\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"active\"\n [matTooltip]=\"item.label\"\n matTooltipPosition=\"right\"\n (click)=\"onMenuClick(item)\"\n >\n <mat-icon>{{ item.icon }}</mat-icon>\n </a>\n }\n <div class=\"menu-spacer\"></div>\n @if (hasShortcuts()) {\n <button\n class=\"help-button\"\n matTooltip=\"Keyboard shortcuts\"\n matTooltipPosition=\"right\"\n (click)=\"toggleHelp()\"\n >\n <span class=\"help-modifier\">Alt+</span><span class=\"help-key\">?</span>\n </button>\n }\n</nav>\n", styles: [".side-menu{display:flex;flex-direction:column;align-items:center;padding-top:8px;gap:4px;height:100%;background-color:var(--color-surface);border-right:1px solid var(--color-surface-border)}.menu-item{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;color:var(--color-secondary-info);text-decoration:none;transition:background-color .15s,color .15s}.menu-item:hover{background-color:var(--color-surface-light);color:var(--color-interactive)}.menu-item.active,.menu-item.active:hover{background-color:var(--color-interactive, #00e5ff);color:var(--color-surface-dark, #0d1117)}.menu-spacer{flex:1}.help-button{margin-bottom:8px;padding:4px 6px;border:1px solid var(--color-surface-border);border-radius:6px;background:none;font-size:.7rem;font-family:Roboto Mono,monospace;cursor:pointer;color:var(--color-interactive);transition:background-color .15s}.help-button:hover{background-color:var(--color-surface-light)}.help-modifier{opacity:.6}.help-key{font-weight:700}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2208
2300
|
}
|
|
2209
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2301
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: SideMenu, decorators: [{
|
|
2210
2302
|
type: Component,
|
|
2211
|
-
args: [{ selector: 'shell-side-menu', imports: [RouterLink, RouterLinkActive, MatIconModule, MatTooltipModule], template: "<nav class=\"side-menu\">\n @for (item of menuItems(); track item.route) {\n <a\n class=\"menu-item\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"active\"\n [matTooltip]=\"item.label\"\n matTooltipPosition=\"right\"\n (click)=\"onMenuClick(item)\"\n >\n <mat-icon>{{ item.icon }}</mat-icon>\n </a>\n }\n <div class=\"menu-spacer\"></div>\n @if (hasShortcuts()) {\n <button\n class=\"help-button\"\n matTooltip=\"Keyboard shortcuts\"\n matTooltipPosition=\"right\"\n (click)=\"toggleHelp()\"\n >\n <span class=\"help-modifier\">Alt+</span><span class=\"help-key\">?</span>\n </button>\n }\n</nav>\n", styles: [".side-menu{display:flex;flex-direction:column;align-items:center;padding-top:8px;gap:4px;height:100%;background-color:var(--color-surface);border-right:1px solid var(--color-surface-border)}.menu-item{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;color:var(--color-secondary-info);text-decoration:none;transition:background-color .15s,color .15s}.menu-item:hover{background-color:var(--color-surface-light);color:var(--color-interactive)}.menu-item.active,.menu-item.active:hover{background-color:var(--color-interactive, #00e5ff);color:var(--color-surface-dark, #0d1117)}.menu-spacer{flex:1}.help-button{margin-bottom:8px;padding:4px 6px;border:1px solid var(--color-surface-border);border-radius:6px;background:none;font-size:.7rem;font-family:Roboto Mono,monospace;cursor:pointer;color:var(--color-interactive);transition:background-color .15s}.help-button:hover{background-color:var(--color-surface-light)}.help-modifier{opacity:.6}.help-key{font-weight:700}\n"] }]
|
|
2303
|
+
args: [{ selector: 'shell-side-menu', imports: [RouterLink, RouterLinkActive, MatIconModule, MatTooltipModule], changeDetection: ChangeDetectionStrategy.Eager, template: "<nav class=\"side-menu\">\n @for (item of menuItems(); track item.route) {\n <a\n class=\"menu-item\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"active\"\n [matTooltip]=\"item.label\"\n matTooltipPosition=\"right\"\n (click)=\"onMenuClick(item)\"\n >\n <mat-icon>{{ item.icon }}</mat-icon>\n </a>\n }\n <div class=\"menu-spacer\"></div>\n @if (hasShortcuts()) {\n <button\n class=\"help-button\"\n matTooltip=\"Keyboard shortcuts\"\n matTooltipPosition=\"right\"\n (click)=\"toggleHelp()\"\n >\n <span class=\"help-modifier\">Alt+</span><span class=\"help-key\">?</span>\n </button>\n }\n</nav>\n", styles: [".side-menu{display:flex;flex-direction:column;align-items:center;padding-top:8px;gap:4px;height:100%;background-color:var(--color-surface);border-right:1px solid var(--color-surface-border)}.menu-item{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;color:var(--color-secondary-info);text-decoration:none;transition:background-color .15s,color .15s}.menu-item:hover{background-color:var(--color-surface-light);color:var(--color-interactive)}.menu-item.active,.menu-item.active:hover{background-color:var(--color-interactive, #00e5ff);color:var(--color-surface-dark, #0d1117)}.menu-spacer{flex:1}.help-button{margin-bottom:8px;padding:4px 6px;border:1px solid var(--color-surface-border);border-radius:6px;background:none;font-size:.7rem;font-family:Roboto Mono,monospace;cursor:pointer;color:var(--color-interactive);transition:background-color .15s}.help-button:hover{background-color:var(--color-surface-light)}.help-modifier{opacity:.6}.help-key{font-weight:700}\n"] }]
|
|
2212
2304
|
}] });
|
|
2213
2305
|
|
|
2214
2306
|
class MainContent {
|
|
@@ -2231,12 +2323,12 @@ class MainContent {
|
|
|
2231
2323
|
closeShortcutHelp() {
|
|
2232
2324
|
this.#shortcutService.helpVisible.set(false);
|
|
2233
2325
|
}
|
|
2234
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2235
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2326
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: MainContent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2327
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: MainContent, isStandalone: true, selector: "shell-main-content", ngImport: i0, template: "<div class=\"main-content\">\n <div class=\"content-area\">\n <router-outlet />\n </div>\n @if (shortcutHelpVisible() && activeShortcuts()) {\n <div class=\"shortcut-overlay\" (click)=\"closeShortcutHelp()\">\n <div class=\"shortcut-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"shortcut-title text-secondary-info\">{{ activeShortcuts()!.groupId }} shortcuts</div>\n @for (s of activeShortcuts()!.shortcuts; track s.key) {\n <div class=\"shortcut-row\">\n <kbd class=\"shortcut-key\">Alt+{{ formatKey(s.key) }}</kbd>\n <span class=\"shortcut-desc text-text-primary\">{{ s.description }}</span>\n </div>\n }\n <div class=\"shortcut-row shortcut-dismiss\">\n <kbd class=\"shortcut-key\">Alt+?</kbd>\n <span class=\"shortcut-desc text-secondary-info\">or</span>\n <kbd class=\"shortcut-key\">Esc</kbd>\n <span class=\"shortcut-desc text-secondary-info\">dismiss</span>\n </div>\n </div>\n </div>\n }\n @if (isThinking()) {\n <div class=\"thinking-overlay\">\n <mat-spinner diameter=\"48\" />\n </div>\n }\n</div>\n", styles: [".main-content{position:relative;height:100%;overflow:hidden}.content-area{height:100%;overflow-y:auto;padding:16px}.shortcut-overlay{position:absolute;inset:0;z-index:15;display:flex;align-items:center;justify-content:center;background-color:#0a0e1480}.shortcut-panel{background-color:var(--color-terminal-bg);border:1px solid var(--color-surface-border);border-radius:6px;padding:14px 18px;font-size:.8rem;box-shadow:0 4px 16px #00000080;min-width:220px}.shortcut-title{font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px;font-weight:500}.shortcut-row{display:flex;align-items:center;gap:10px;padding:3px 0}.shortcut-row.shortcut-dismiss{margin-top:6px;border-top:1px solid var(--color-surface-border);padding-top:8px}.shortcut-key{font-family:Roboto Mono,monospace;font-size:.75rem;background-color:#ffffff14;border:1px solid var(--color-surface-border);border-radius:3px;padding:1px 6px;min-width:70px;text-align:center}.shortcut-desc{font-size:.78rem}.thinking-overlay{position:absolute;inset:0;z-index:20;background-color:#0a0e14b3;display:flex;align-items:center;justify-content:center;pointer-events:all;cursor:wait}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i1$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2236
2328
|
}
|
|
2237
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2329
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: MainContent, decorators: [{
|
|
2238
2330
|
type: Component,
|
|
2239
|
-
args: [{ selector: 'shell-main-content', imports: [RouterOutlet, MatProgressSpinnerModule], template: "<div class=\"main-content\">\n <div class=\"content-area\">\n <router-outlet />\n </div>\n @if (shortcutHelpVisible() && activeShortcuts()) {\n <div class=\"shortcut-overlay\" (click)=\"closeShortcutHelp()\">\n <div class=\"shortcut-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"shortcut-title text-secondary-info\">{{ activeShortcuts()!.groupId }} shortcuts</div>\n @for (s of activeShortcuts()!.shortcuts; track s.key) {\n <div class=\"shortcut-row\">\n <kbd class=\"shortcut-key\">Alt+{{ formatKey(s.key) }}</kbd>\n <span class=\"shortcut-desc text-text-primary\">{{ s.description }}</span>\n </div>\n }\n <div class=\"shortcut-row shortcut-dismiss\">\n <kbd class=\"shortcut-key\">Alt+?</kbd>\n <span class=\"shortcut-desc text-secondary-info\">or</span>\n <kbd class=\"shortcut-key\">Esc</kbd>\n <span class=\"shortcut-desc text-secondary-info\">dismiss</span>\n </div>\n </div>\n </div>\n }\n @if (isThinking()) {\n <div class=\"thinking-overlay\">\n <mat-spinner diameter=\"48\" />\n </div>\n }\n</div>\n", styles: [".main-content{position:relative;height:100%;overflow:hidden}.content-area{height:100%;overflow-y:auto;padding:16px}.shortcut-overlay{position:absolute;inset:0;z-index:15;display:flex;align-items:center;justify-content:center;background-color:#0a0e1480}.shortcut-panel{background-color:var(--color-terminal-bg);border:1px solid var(--color-surface-border);border-radius:6px;padding:14px 18px;font-size:.8rem;box-shadow:0 4px 16px #00000080;min-width:220px}.shortcut-title{font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px;font-weight:500}.shortcut-row{display:flex;align-items:center;gap:10px;padding:3px 0}.shortcut-row.shortcut-dismiss{margin-top:6px;border-top:1px solid var(--color-surface-border);padding-top:8px}.shortcut-key{font-family:Roboto Mono,monospace;font-size:.75rem;background-color:#ffffff14;border:1px solid var(--color-surface-border);border-radius:3px;padding:1px 6px;min-width:70px;text-align:center}.shortcut-desc{font-size:.78rem}.thinking-overlay{position:absolute;inset:0;z-index:20;background-color:#0a0e14b3;display:flex;align-items:center;justify-content:center;pointer-events:all;cursor:wait}\n"] }]
|
|
2331
|
+
args: [{ selector: 'shell-main-content', imports: [RouterOutlet, MatProgressSpinnerModule], changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"main-content\">\n <div class=\"content-area\">\n <router-outlet />\n </div>\n @if (shortcutHelpVisible() && activeShortcuts()) {\n <div class=\"shortcut-overlay\" (click)=\"closeShortcutHelp()\">\n <div class=\"shortcut-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"shortcut-title text-secondary-info\">{{ activeShortcuts()!.groupId }} shortcuts</div>\n @for (s of activeShortcuts()!.shortcuts; track s.key) {\n <div class=\"shortcut-row\">\n <kbd class=\"shortcut-key\">Alt+{{ formatKey(s.key) }}</kbd>\n <span class=\"shortcut-desc text-text-primary\">{{ s.description }}</span>\n </div>\n }\n <div class=\"shortcut-row shortcut-dismiss\">\n <kbd class=\"shortcut-key\">Alt+?</kbd>\n <span class=\"shortcut-desc text-secondary-info\">or</span>\n <kbd class=\"shortcut-key\">Esc</kbd>\n <span class=\"shortcut-desc text-secondary-info\">dismiss</span>\n </div>\n </div>\n </div>\n }\n @if (isThinking()) {\n <div class=\"thinking-overlay\">\n <mat-spinner diameter=\"48\" />\n </div>\n }\n</div>\n", styles: [".main-content{position:relative;height:100%;overflow:hidden}.content-area{height:100%;overflow-y:auto;padding:16px}.shortcut-overlay{position:absolute;inset:0;z-index:15;display:flex;align-items:center;justify-content:center;background-color:#0a0e1480}.shortcut-panel{background-color:var(--color-terminal-bg);border:1px solid var(--color-surface-border);border-radius:6px;padding:14px 18px;font-size:.8rem;box-shadow:0 4px 16px #00000080;min-width:220px}.shortcut-title{font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px;font-weight:500}.shortcut-row{display:flex;align-items:center;gap:10px;padding:3px 0}.shortcut-row.shortcut-dismiss{margin-top:6px;border-top:1px solid var(--color-surface-border);padding-top:8px}.shortcut-key{font-family:Roboto Mono,monospace;font-size:.75rem;background-color:#ffffff14;border:1px solid var(--color-surface-border);border-radius:3px;padding:1px 6px;min-width:70px;text-align:center}.shortcut-desc{font-size:.78rem}.thinking-overlay{position:absolute;inset:0;z-index:20;background-color:#0a0e14b3;display:flex;align-items:center;justify-content:center;pointer-events:all;cursor:wait}\n"] }]
|
|
2240
2332
|
}] });
|
|
2241
2333
|
|
|
2242
2334
|
class CommandTerminal {
|
|
@@ -2245,10 +2337,12 @@ class CommandTerminal {
|
|
|
2245
2337
|
this.registry = inject(CommandRegistryService);
|
|
2246
2338
|
this.authService = inject(AuthenticationService);
|
|
2247
2339
|
this.terminalFocusService = inject(TerminalFocusService);
|
|
2248
|
-
this.history = computed(() => [...this.commandService.history()].reverse(),
|
|
2340
|
+
this.history = computed(() => [...this.commandService.history()].reverse(), /* @ts-ignore */
|
|
2341
|
+
...(ngDevMode ? [{ debugName: "history" }] : /* istanbul ignore next */ []));
|
|
2249
2342
|
this.currentInput = this.commandService.currentInput;
|
|
2250
2343
|
this.isProcessing = this.commandService.isProcessing;
|
|
2251
|
-
this.inputEl = viewChild('terminalInput',
|
|
2344
|
+
this.inputEl = viewChild('terminalInput', /* @ts-ignore */
|
|
2345
|
+
...(ngDevMode ? [{ debugName: "inputEl" }] : /* istanbul ignore next */ []));
|
|
2252
2346
|
this.tabCycleIndex = -1;
|
|
2253
2347
|
this.lastTabPrefix = '';
|
|
2254
2348
|
this.ghostText = computed(() => {
|
|
@@ -2258,7 +2352,8 @@ class CommandTerminal {
|
|
|
2258
2352
|
const prefix = input.toLowerCase();
|
|
2259
2353
|
const suggestions = this.registry.getSuggestions(prefix, this.authService.authenticated());
|
|
2260
2354
|
return suggestions.length > 0 ? suggestions[0] : '';
|
|
2261
|
-
},
|
|
2355
|
+
}, /* @ts-ignore */
|
|
2356
|
+
...(ngDevMode ? [{ debugName: "ghostText" }] : /* istanbul ignore next */ []));
|
|
2262
2357
|
afterNextRender(() => this.focusInput());
|
|
2263
2358
|
effect(() => {
|
|
2264
2359
|
if (!this.isProcessing()) {
|
|
@@ -2329,12 +2424,12 @@ class CommandTerminal {
|
|
|
2329
2424
|
focusInput() {
|
|
2330
2425
|
this.inputEl()?.nativeElement.focus();
|
|
2331
2426
|
}
|
|
2332
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2333
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2427
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: CommandTerminal, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2428
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: CommandTerminal, isStandalone: true, selector: "shell-command-terminal", viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["terminalInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"terminal\">\n <div class=\"terminal-input-row\">\n <span class=\"prompt\">$</span>\n <div class=\"input-wrapper\">\n @if (ghostText()) {\n <input\n class=\"ghost-input\"\n type=\"text\"\n [value]=\"ghostText()\"\n disabled\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <input\n #terminalInput\n class=\"terminal-input\"\n type=\"text\"\n [ngModel]=\"currentInput()\"\n (ngModelChange)=\"onInputChange($event)\"\n (keydown.enter)=\"onSubmit()\"\n (keydown.tab)=\"onTab($any($event))\"\n (keydown.escape)=\"dismissHelp()\"\n placeholder=\"Type a command...\"\n [disabled]=\"isProcessing()\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n </div>\n </div>\n <div class=\"terminal-output\">\n @for (entry of history(); track entry.result.timestamp) {\n @if (entry.input) {\n <div class=\"terminal-line\">\n <span class=\"prompt\">$</span>\n <span class=\"command-text\">{{ entry.input }}@if ((entry.repeatCount ?? 1) > 1) { <span class=\"repeat-count\">(\u00D7{{ entry.repeatCount }})</span>}</span>\n </div>\n }\n @if (entry.result.message) {\n <div class=\"terminal-line\" [class]=\"getSeverityClass(entry.result)\">{{ entry.result.message }}</div>\n }\n }\n </div>\n</div>\n", styles: [".terminal{display:flex;flex-direction:column;height:100%;background-color:var(--color-terminal-bg);border-top:1px solid var(--color-surface-border);font-family:Roboto Mono,Courier New,monospace;font-size:.85rem}.terminal-output{flex:1;overflow-y:auto;padding:8px 12px;display:flex;flex-direction:column}.terminal-line{line-height:1.6;color:var(--color-text-primary);white-space:pre-wrap}.terminal-line.error{color:var(--color-loss)}.terminal-line.warning{color:var(--color-warning)}.terminal-line.info{color:var(--color-info)}.prompt{color:var(--color-terminal-prompt);margin-right:8px;font-weight:700}.command-text{color:var(--color-terminal-text)}.repeat-count{color:var(--color-secondary-info);opacity:.6;margin-left:4px}.terminal-input-row{display:flex;align-items:center;padding:8px 12px;border-bottom:1px solid var(--color-surface-border)}.input-wrapper{flex:1;display:grid}.ghost-input,.terminal-input{grid-area:1 / 1;font-family:inherit;font-size:inherit;line-height:normal;margin:0;padding:0;border:none;background:transparent;outline:none;-webkit-appearance:none;appearance:none;width:100%}.ghost-input{color:var(--color-secondary-info);opacity:.3;pointer-events:none}.terminal-input{color:var(--color-terminal-text);caret-color:var(--color-terminal-prompt)}.terminal-input::placeholder{color:var(--color-secondary-info);opacity:.5}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2334
2429
|
}
|
|
2335
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2430
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: CommandTerminal, decorators: [{
|
|
2336
2431
|
type: Component,
|
|
2337
|
-
args: [{ selector: 'shell-command-terminal', imports: [FormsModule], template: "<div class=\"terminal\">\n <div class=\"terminal-input-row\">\n <span class=\"prompt\">$</span>\n <div class=\"input-wrapper\">\n @if (ghostText()) {\n <input\n class=\"ghost-input\"\n type=\"text\"\n [value]=\"ghostText()\"\n disabled\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <input\n #terminalInput\n class=\"terminal-input\"\n type=\"text\"\n [ngModel]=\"currentInput()\"\n (ngModelChange)=\"onInputChange($event)\"\n (keydown.enter)=\"onSubmit()\"\n (keydown.tab)=\"onTab($any($event))\"\n (keydown.escape)=\"dismissHelp()\"\n placeholder=\"Type a command...\"\n [disabled]=\"isProcessing()\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n </div>\n </div>\n <div class=\"terminal-output\">\n @for (entry of history(); track entry.result.timestamp) {\n @if (entry.input) {\n <div class=\"terminal-line\">\n <span class=\"prompt\">$</span>\n <span class=\"command-text\">{{ entry.input }}@if ((entry.repeatCount ?? 1) > 1) { <span class=\"repeat-count\">(\u00D7{{ entry.repeatCount }})</span>}</span>\n </div>\n }\n @if (entry.result.message) {\n <div class=\"terminal-line\" [class]=\"getSeverityClass(entry.result)\">{{ entry.result.message }}</div>\n }\n }\n </div>\n</div>\n", styles: [".terminal{display:flex;flex-direction:column;height:100%;background-color:var(--color-terminal-bg);border-top:1px solid var(--color-surface-border);font-family:Roboto Mono,Courier New,monospace;font-size:.85rem}.terminal-output{flex:1;overflow-y:auto;padding:8px 12px;display:flex;flex-direction:column}.terminal-line{line-height:1.6;color:var(--color-text-primary);white-space:pre-wrap}.terminal-line.error{color:var(--color-loss)}.terminal-line.warning{color:var(--color-warning)}.terminal-line.info{color:var(--color-info)}.prompt{color:var(--color-terminal-prompt);margin-right:8px;font-weight:700}.command-text{color:var(--color-terminal-text)}.repeat-count{color:var(--color-secondary-info);opacity:.6;margin-left:4px}.terminal-input-row{display:flex;align-items:center;padding:8px 12px;border-bottom:1px solid var(--color-surface-border)}.input-wrapper{flex:1;display:grid}.ghost-input,.terminal-input{grid-area:1 / 1;font-family:inherit;font-size:inherit;line-height:normal;margin:0;padding:0;border:none;background:transparent;outline:none;-webkit-appearance:none;appearance:none;width:100%}.ghost-input{color:var(--color-secondary-info);opacity:.3;pointer-events:none}.terminal-input{color:var(--color-terminal-text);caret-color:var(--color-terminal-prompt)}.terminal-input::placeholder{color:var(--color-secondary-info);opacity:.5}\n"] }]
|
|
2432
|
+
args: [{ selector: 'shell-command-terminal', imports: [FormsModule], changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"terminal\">\n <div class=\"terminal-input-row\">\n <span class=\"prompt\">$</span>\n <div class=\"input-wrapper\">\n @if (ghostText()) {\n <input\n class=\"ghost-input\"\n type=\"text\"\n [value]=\"ghostText()\"\n disabled\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <input\n #terminalInput\n class=\"terminal-input\"\n type=\"text\"\n [ngModel]=\"currentInput()\"\n (ngModelChange)=\"onInputChange($event)\"\n (keydown.enter)=\"onSubmit()\"\n (keydown.tab)=\"onTab($any($event))\"\n (keydown.escape)=\"dismissHelp()\"\n placeholder=\"Type a command...\"\n [disabled]=\"isProcessing()\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n </div>\n </div>\n <div class=\"terminal-output\">\n @for (entry of history(); track entry.result.timestamp) {\n @if (entry.input) {\n <div class=\"terminal-line\">\n <span class=\"prompt\">$</span>\n <span class=\"command-text\">{{ entry.input }}@if ((entry.repeatCount ?? 1) > 1) { <span class=\"repeat-count\">(\u00D7{{ entry.repeatCount }})</span>}</span>\n </div>\n }\n @if (entry.result.message) {\n <div class=\"terminal-line\" [class]=\"getSeverityClass(entry.result)\">{{ entry.result.message }}</div>\n }\n }\n </div>\n</div>\n", styles: [".terminal{display:flex;flex-direction:column;height:100%;background-color:var(--color-terminal-bg);border-top:1px solid var(--color-surface-border);font-family:Roboto Mono,Courier New,monospace;font-size:.85rem}.terminal-output{flex:1;overflow-y:auto;padding:8px 12px;display:flex;flex-direction:column}.terminal-line{line-height:1.6;color:var(--color-text-primary);white-space:pre-wrap}.terminal-line.error{color:var(--color-loss)}.terminal-line.warning{color:var(--color-warning)}.terminal-line.info{color:var(--color-info)}.prompt{color:var(--color-terminal-prompt);margin-right:8px;font-weight:700}.command-text{color:var(--color-terminal-text)}.repeat-count{color:var(--color-secondary-info);opacity:.6;margin-left:4px}.terminal-input-row{display:flex;align-items:center;padding:8px 12px;border-bottom:1px solid var(--color-surface-border)}.input-wrapper{flex:1;display:grid}.ghost-input,.terminal-input{grid-area:1 / 1;font-family:inherit;font-size:inherit;line-height:normal;margin:0;padding:0;border:none;background:transparent;outline:none;-webkit-appearance:none;appearance:none;width:100%}.ghost-input{color:var(--color-secondary-info);opacity:.3;pointer-events:none}.terminal-input{color:var(--color-terminal-text);caret-color:var(--color-terminal-prompt)}.terminal-input::placeholder{color:var(--color-secondary-info);opacity:.5}\n"] }]
|
|
2338
2433
|
}], ctorParameters: () => [], propDecorators: { inputEl: [{ type: i0.ViewChild, args: ['terminalInput', { isSignal: true }] }] } });
|
|
2339
2434
|
|
|
2340
2435
|
const MIN_TERMINAL_HEIGHT = 80;
|
|
@@ -2348,8 +2443,10 @@ class Shell {
|
|
|
2348
2443
|
this.isThinking = this.#thinkingService.isThinking;
|
|
2349
2444
|
this.isAuthenticated = this.#authService.authenticated;
|
|
2350
2445
|
this.helpOverlay = this.#commandService.helpOverlay;
|
|
2351
|
-
this.terminalHeight = signal(`${DEFAULT_TERMINAL_HEIGHT}px`,
|
|
2352
|
-
|
|
2446
|
+
this.terminalHeight = signal(`${DEFAULT_TERMINAL_HEIGHT}px`, /* @ts-ignore */
|
|
2447
|
+
...(ngDevMode ? [{ debugName: "terminalHeight" }] : /* istanbul ignore next */ []));
|
|
2448
|
+
this.isDragging = signal(false, /* @ts-ignore */
|
|
2449
|
+
...(ngDevMode ? [{ debugName: "isDragging" }] : /* istanbul ignore next */ []));
|
|
2353
2450
|
this.#startY = 0;
|
|
2354
2451
|
this.#startHeight = DEFAULT_TERMINAL_HEIGHT;
|
|
2355
2452
|
this.#onMouseMove = (event) => {
|
|
@@ -2382,12 +2479,12 @@ class Shell {
|
|
|
2382
2479
|
document.addEventListener('mousemove', this.#onMouseMove);
|
|
2383
2480
|
document.addEventListener('mouseup', this.#onMouseUp);
|
|
2384
2481
|
}
|
|
2385
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2386
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2482
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: Shell, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2483
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: Shell, isStandalone: true, selector: "shell-root", ngImport: i0, template: "<div class=\"shell\" [style.--terminal-height]=\"terminalHeight()\" [class.is-dragging]=\"isDragging()\">\n <shell-status-bar class=\"shell-status\" [class.disabled-zone]=\"isThinking()\">\n <ng-content />\n </shell-status-bar>\n @if (isAuthenticated()) {\n <shell-side-menu class=\"shell-menu\" [class.disabled-zone]=\"isThinking()\" />\n }\n <shell-main-content class=\"shell-main\" [class.full-width]=\"!isAuthenticated()\" />\n <div class=\"shell-resize\" [class.dragging]=\"isDragging()\" (mousedown)=\"onResizeStart($event)\"></div>\n <shell-command-terminal class=\"shell-terminal\" [class.disabled-zone]=\"isThinking()\" />\n <faq-modal />\n\n @if (helpOverlay(); as helpText) {\n <div class=\"help-backdrop\" (click)=\"dismissHelp()\">\n <div class=\"help-panel\" (click)=\"$event.stopPropagation()\" role=\"dialog\" aria-label=\"Command help\">\n <div class=\"help-panel-header\">\n <span class=\"help-panel-title\">Help</span>\n <button class=\"help-panel-close\" type=\"button\" (click)=\"dismissHelp()\" aria-label=\"Close help\">\u2715</button>\n </div>\n <div class=\"help-panel-content\">{{ helpText }}</div>\n <div class=\"help-panel-footer\">\n <span>Tip: for most commands you can swap the first and second words \u2014 e.g. \"disable user\" works the same as \"user disable\"</span>\n <span class=\"help-panel-footer-dismiss\">Press Escape, click outside, or start typing to close</span>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".shell{position:relative;display:grid;grid-template-areas:\"status status\" \"menu main\" \"resize resize\" \"terminal terminal\";grid-template-columns:56px 1fr;grid-template-rows:48px 1fr 4px var(--terminal-height, 160px);height:100vh;width:100vw;overflow:hidden;background-color:var(--color-surface-dark)}.shell-status{grid-area:status}.shell-menu{grid-area:menu}.shell-main{grid-area:main;overflow:hidden}.shell-main.full-width{grid-column:1 / -1}.shell-resize{grid-area:resize;cursor:row-resize;background-color:var(--color-surface-border);transition:background-color .15s ease}.shell-resize:hover,.shell-resize.dragging{background-color:var(--color-interactive)}.shell-terminal{grid-area:terminal}.shell.is-dragging{user-select:none;-webkit-user-select:none}.disabled-zone{pointer-events:none;opacity:.4;transition:opacity .2s ease}.help-backdrop{position:absolute;inset:0;z-index:100;background-color:#000000a6;display:flex;align-items:center;justify-content:center}.help-panel{background-color:var(--color-surface, #161b22);border:2px solid var(--color-interactive, #00e5ff);border-radius:4px;width:70%;max-width:820px;max-height:75vh;display:flex;flex-direction:column;font-family:Roboto Mono,Courier New,monospace;font-size:.85rem}.help-panel-header{display:flex;justify-content:space-between;align-items:center;padding:8px 16px;background-color:var(--color-surface-light, #21262d);border-bottom:1px solid var(--color-interactive, #00e5ff);border-radius:2px 2px 0 0;flex-shrink:0}.help-panel-title{color:var(--color-interactive, #00e5ff);font-weight:700;letter-spacing:.05em;text-transform:uppercase;font-size:.75rem}.help-panel-close{background:none;border:1px solid var(--color-surface-border, #30363d);color:var(--color-secondary-info, #9e9e9e);cursor:pointer;padding:2px 8px;font-size:.9rem;line-height:1.4;border-radius:3px;transition:color .15s ease,border-color .15s ease}.help-panel-close:hover{color:var(--color-text-primary, #ffffff);border-color:var(--color-interactive, #00e5ff)}.help-panel-content{flex:1;overflow-y:auto;padding:16px 20px;color:var(--color-text-primary, #ffffff);white-space:pre-wrap;line-height:1.7}.help-panel-footer{padding:6px 16px;background-color:var(--color-surface-light, #21262d);border-top:1px solid var(--color-surface-border, #30363d);border-radius:0 0 2px 2px;color:var(--color-secondary-info, #9e9e9e);font-size:.75rem;flex-shrink:0;display:flex;flex-direction:column;gap:2px}.help-panel-footer-dismiss{opacity:.6}\n"], dependencies: [{ kind: "component", type: StatusBar, selector: "shell-status-bar" }, { kind: "component", type: SideMenu, selector: "shell-side-menu" }, { kind: "component", type: MainContent, selector: "shell-main-content" }, { kind: "component", type: CommandTerminal, selector: "shell-command-terminal" }, { kind: "component", type: FaqModal, selector: "faq-modal" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2387
2484
|
}
|
|
2388
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2485
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: Shell, decorators: [{
|
|
2389
2486
|
type: Component,
|
|
2390
|
-
args: [{ selector: 'shell-root', imports: [StatusBar, SideMenu, MainContent, CommandTerminal, FaqModal], template: "<div class=\"shell\" [style.--terminal-height]=\"terminalHeight()\" [class.is-dragging]=\"isDragging()\">\n <shell-status-bar class=\"shell-status\" [class.disabled-zone]=\"isThinking()\">\n <ng-content />\n </shell-status-bar>\n @if (isAuthenticated()) {\n <shell-side-menu class=\"shell-menu\" [class.disabled-zone]=\"isThinking()\" />\n }\n <shell-main-content class=\"shell-main\" [class.full-width]=\"!isAuthenticated()\" />\n <div class=\"shell-resize\" [class.dragging]=\"isDragging()\" (mousedown)=\"onResizeStart($event)\"></div>\n <shell-command-terminal class=\"shell-terminal\" [class.disabled-zone]=\"isThinking()\" />\n <faq-modal />\n\n @if (helpOverlay(); as helpText) {\n <div class=\"help-backdrop\" (click)=\"dismissHelp()\">\n <div class=\"help-panel\" (click)=\"$event.stopPropagation()\" role=\"dialog\" aria-label=\"Command help\">\n <div class=\"help-panel-header\">\n <span class=\"help-panel-title\">Help</span>\n <button class=\"help-panel-close\" type=\"button\" (click)=\"dismissHelp()\" aria-label=\"Close help\">\u2715</button>\n </div>\n <div class=\"help-panel-content\">{{ helpText }}</div>\n <div class=\"help-panel-footer\">\n <span>Tip: for most commands you can swap the first and second words \u2014 e.g. \"disable user\" works the same as \"user disable\"</span>\n <span class=\"help-panel-footer-dismiss\">Press Escape, click outside, or start typing to close</span>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".shell{position:relative;display:grid;grid-template-areas:\"status status\" \"menu main\" \"resize resize\" \"terminal terminal\";grid-template-columns:56px 1fr;grid-template-rows:48px 1fr 4px var(--terminal-height, 160px);height:100vh;width:100vw;overflow:hidden;background-color:var(--color-surface-dark)}.shell-status{grid-area:status}.shell-menu{grid-area:menu}.shell-main{grid-area:main;overflow:hidden}.shell-main.full-width{grid-column:1 / -1}.shell-resize{grid-area:resize;cursor:row-resize;background-color:var(--color-surface-border);transition:background-color .15s ease}.shell-resize:hover,.shell-resize.dragging{background-color:var(--color-interactive)}.shell-terminal{grid-area:terminal}.shell.is-dragging{user-select:none;-webkit-user-select:none}.disabled-zone{pointer-events:none;opacity:.4;transition:opacity .2s ease}.help-backdrop{position:absolute;inset:0;z-index:100;background-color:#000000a6;display:flex;align-items:center;justify-content:center}.help-panel{background-color:var(--color-surface, #161b22);border:2px solid var(--color-interactive, #00e5ff);border-radius:4px;width:70%;max-width:820px;max-height:75vh;display:flex;flex-direction:column;font-family:Roboto Mono,Courier New,monospace;font-size:.85rem}.help-panel-header{display:flex;justify-content:space-between;align-items:center;padding:8px 16px;background-color:var(--color-surface-light, #21262d);border-bottom:1px solid var(--color-interactive, #00e5ff);border-radius:2px 2px 0 0;flex-shrink:0}.help-panel-title{color:var(--color-interactive, #00e5ff);font-weight:700;letter-spacing:.05em;text-transform:uppercase;font-size:.75rem}.help-panel-close{background:none;border:1px solid var(--color-surface-border, #30363d);color:var(--color-secondary-info, #9e9e9e);cursor:pointer;padding:2px 8px;font-size:.9rem;line-height:1.4;border-radius:3px;transition:color .15s ease,border-color .15s ease}.help-panel-close:hover{color:var(--color-text-primary, #ffffff);border-color:var(--color-interactive, #00e5ff)}.help-panel-content{flex:1;overflow-y:auto;padding:16px 20px;color:var(--color-text-primary, #ffffff);white-space:pre-wrap;line-height:1.7}.help-panel-footer{padding:6px 16px;background-color:var(--color-surface-light, #21262d);border-top:1px solid var(--color-surface-border, #30363d);border-radius:0 0 2px 2px;color:var(--color-secondary-info, #9e9e9e);font-size:.75rem;flex-shrink:0;display:flex;flex-direction:column;gap:2px}.help-panel-footer-dismiss{opacity:.6}\n"] }]
|
|
2487
|
+
args: [{ selector: 'shell-root', imports: [StatusBar, SideMenu, MainContent, CommandTerminal, FaqModal], changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"shell\" [style.--terminal-height]=\"terminalHeight()\" [class.is-dragging]=\"isDragging()\">\n <shell-status-bar class=\"shell-status\" [class.disabled-zone]=\"isThinking()\">\n <ng-content />\n </shell-status-bar>\n @if (isAuthenticated()) {\n <shell-side-menu class=\"shell-menu\" [class.disabled-zone]=\"isThinking()\" />\n }\n <shell-main-content class=\"shell-main\" [class.full-width]=\"!isAuthenticated()\" />\n <div class=\"shell-resize\" [class.dragging]=\"isDragging()\" (mousedown)=\"onResizeStart($event)\"></div>\n <shell-command-terminal class=\"shell-terminal\" [class.disabled-zone]=\"isThinking()\" />\n <faq-modal />\n\n @if (helpOverlay(); as helpText) {\n <div class=\"help-backdrop\" (click)=\"dismissHelp()\">\n <div class=\"help-panel\" (click)=\"$event.stopPropagation()\" role=\"dialog\" aria-label=\"Command help\">\n <div class=\"help-panel-header\">\n <span class=\"help-panel-title\">Help</span>\n <button class=\"help-panel-close\" type=\"button\" (click)=\"dismissHelp()\" aria-label=\"Close help\">\u2715</button>\n </div>\n <div class=\"help-panel-content\">{{ helpText }}</div>\n <div class=\"help-panel-footer\">\n <span>Tip: for most commands you can swap the first and second words \u2014 e.g. \"disable user\" works the same as \"user disable\"</span>\n <span class=\"help-panel-footer-dismiss\">Press Escape, click outside, or start typing to close</span>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [".shell{position:relative;display:grid;grid-template-areas:\"status status\" \"menu main\" \"resize resize\" \"terminal terminal\";grid-template-columns:56px 1fr;grid-template-rows:48px 1fr 4px var(--terminal-height, 160px);height:100vh;width:100vw;overflow:hidden;background-color:var(--color-surface-dark)}.shell-status{grid-area:status}.shell-menu{grid-area:menu}.shell-main{grid-area:main;overflow:hidden}.shell-main.full-width{grid-column:1 / -1}.shell-resize{grid-area:resize;cursor:row-resize;background-color:var(--color-surface-border);transition:background-color .15s ease}.shell-resize:hover,.shell-resize.dragging{background-color:var(--color-interactive)}.shell-terminal{grid-area:terminal}.shell.is-dragging{user-select:none;-webkit-user-select:none}.disabled-zone{pointer-events:none;opacity:.4;transition:opacity .2s ease}.help-backdrop{position:absolute;inset:0;z-index:100;background-color:#000000a6;display:flex;align-items:center;justify-content:center}.help-panel{background-color:var(--color-surface, #161b22);border:2px solid var(--color-interactive, #00e5ff);border-radius:4px;width:70%;max-width:820px;max-height:75vh;display:flex;flex-direction:column;font-family:Roboto Mono,Courier New,monospace;font-size:.85rem}.help-panel-header{display:flex;justify-content:space-between;align-items:center;padding:8px 16px;background-color:var(--color-surface-light, #21262d);border-bottom:1px solid var(--color-interactive, #00e5ff);border-radius:2px 2px 0 0;flex-shrink:0}.help-panel-title{color:var(--color-interactive, #00e5ff);font-weight:700;letter-spacing:.05em;text-transform:uppercase;font-size:.75rem}.help-panel-close{background:none;border:1px solid var(--color-surface-border, #30363d);color:var(--color-secondary-info, #9e9e9e);cursor:pointer;padding:2px 8px;font-size:.9rem;line-height:1.4;border-radius:3px;transition:color .15s ease,border-color .15s ease}.help-panel-close:hover{color:var(--color-text-primary, #ffffff);border-color:var(--color-interactive, #00e5ff)}.help-panel-content{flex:1;overflow-y:auto;padding:16px 20px;color:var(--color-text-primary, #ffffff);white-space:pre-wrap;line-height:1.7}.help-panel-footer{padding:6px 16px;background-color:var(--color-surface-light, #21262d);border-top:1px solid var(--color-surface-border, #30363d);border-radius:0 0 2px 2px;color:var(--color-secondary-info, #9e9e9e);font-size:.75rem;flex-shrink:0;display:flex;flex-direction:column;gap:2px}.help-panel-footer-dismiss{opacity:.6}\n"] }]
|
|
2391
2488
|
}] });
|
|
2392
2489
|
|
|
2393
2490
|
class Login {
|
|
@@ -2400,8 +2497,10 @@ class Login {
|
|
|
2400
2497
|
this.router = router;
|
|
2401
2498
|
this.model = { username: '', password: '' };
|
|
2402
2499
|
this.submitted = false;
|
|
2403
|
-
this.hide = signal(true,
|
|
2404
|
-
|
|
2500
|
+
this.hide = signal(true, /* @ts-ignore */
|
|
2501
|
+
...(ngDevMode ? [{ debugName: "hide" }] : /* istanbul ignore next */ []));
|
|
2502
|
+
this.takeover = signal(true, /* @ts-ignore */
|
|
2503
|
+
...(ngDevMode ? [{ debugName: "takeover" }] : /* istanbul ignore next */ []));
|
|
2405
2504
|
this.errors = [];
|
|
2406
2505
|
this.USERNAME_REGEX = USERNAME_REGEX;
|
|
2407
2506
|
this.PASSWORD_REGEX = PASSWORD_REGEX;
|
|
@@ -2482,12 +2581,12 @@ class Login {
|
|
|
2482
2581
|
this.submitted = false;
|
|
2483
2582
|
});
|
|
2484
2583
|
}
|
|
2485
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2486
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2584
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: Login, deps: [{ token: AuthenticationService }, { token: i2$1.Router }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2585
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: Login, isStandalone: true, selector: "shell-login", ngImport: i0, template: "@let usernameRegex = USERNAME_REGEX;\n@let passwordRegex = PASSWORD_REGEX;\n<div class=\"login-container\">\n <div class=\"login-header\">\n <h2 class=\"text-text-primary\">{{ appName }}</h2>\n <p class=\"text-secondary-info\">Sign in to continue</p>\n </div>\n <form #loginForm=\"ngForm\" (ngSubmit)=\"onSubmit($event)\" class=\"login-form\">\n <mat-form-field appearance=\"outline\" class=\"login-field\">\n <mat-label>Username</mat-label>\n <input\n #usernameInput\n matInput\n placeholder=\"Enter username\"\n [(ngModel)]=\"model.username\"\n name=\"username\"\n [disabled]=\"submitted\"\n required\n regexValidator\n [regex]=\"usernameRegex\"\n (cdkAutofill)=\"onAutofill($event, usernameInput)\"\n />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"login-field\">\n <mat-label>Password</mat-label>\n <input\n #passwordInput\n matInput\n placeholder=\"Enter password\"\n [type]=\"hide() ? 'password' : 'text'\"\n [(ngModel)]=\"model.password\"\n name=\"password\"\n [disabled]=\"submitted\"\n regexValidator\n [regex]=\"passwordRegex\"\n (cdkAutofill)=\"onAutofill($event, passwordInput)\"\n />\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n (click)=\"clickEvent($event)\"\n [attr.aria-label]=\"'Hide password'\"\n [attr.aria-pressed]=\"hide()\"\n >\n <mat-icon>{{ hide() ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n </mat-form-field>\n <mat-checkbox\n class=\"login-takeover\"\n name=\"takeover\"\n [checked]=\"takeover()\"\n (change)=\"takeover.set($event.checked)\"\n [disabled]=\"submitted\"\n >\n Takeover session if logged in elsewhere\n </mat-checkbox>\n <button mat-flat-button type=\"submit\" [disabled]=\"submitted\" class=\"login-button\">\n Login\n </button>\n </form>\n @if (errors.length > 0) {\n <div class=\"login-errors\">\n @for (error of errors; track error.ndx) {\n <div class=\"login-error text-loss\">{{ error.message }}</div>\n }\n </div>\n }\n @if (authenticationService.conflictSessions(); as sessions) {\n <div class=\"login-conflict\">\n @for (session of sessions; track $index) {\n <p class=\"text-secondary-info\">\n Already logged in from <strong>{{ session.appContext }}</strong>\n since {{ session.startEpoch | date:'short' }}.\n </p>\n }\n <p class=\"text-secondary-info\">Log in here and end that session?</p>\n <div class=\"login-conflict-actions\">\n <button mat-stroked-button type=\"button\" (click)=\"onCancelConflict()\">Cancel</button>\n <button mat-flat-button type=\"button\" (click)=\"onTakeOver()\">Take Over</button>\n </div>\n </div>\n }\n</div>\n", styles: [".login-container{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;text-align:center}.login-header{margin-bottom:32px}.login-header h2{font-size:1.5rem;font-weight:300;margin-bottom:8px}.login-form{display:flex;flex-direction:column;align-items:center;gap:8px;width:320px}.login-field{width:100%;text-align:left}.login-takeover{align-self:flex-start;margin-top:4px}.login-button{margin-top:8px;width:100%}.login-errors{margin-top:16px;max-width:320px}.login-conflict{margin-top:16px;max-width:320px;padding:12px 16px;border-radius:4px;background-color:var(--color-surface-light);font-size:.85rem;text-align:left}.login-conflict p{margin:0 0 8px}.login-conflict-actions{display:flex;gap:8px;margin-top:12px;justify-content:flex-end}.login-error{padding:8px 12px;margin-bottom:4px;font-size:.85rem;border-radius:4px;background-color:var(--color-surface-light)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: 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: MatInputModule }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i5.CdkAutofill, selector: "[cdkAutofill]", outputs: ["cdkAutofill"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.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: i6.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i7.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: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: RegexValidatorDirective, selector: "[regexValidator]", inputs: ["regex"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "pipe", type: DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2487
2586
|
}
|
|
2488
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2587
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: Login, decorators: [{
|
|
2489
2588
|
type: Component,
|
|
2490
|
-
args: [{ selector: 'shell-login', imports: [
|
|
2589
|
+
args: [{ selector: 'shell-login', changeDetection: ChangeDetectionStrategy.Eager, imports: [
|
|
2491
2590
|
FormsModule,
|
|
2492
2591
|
MatFormField,
|
|
2493
2592
|
MatLabel,
|
|
@@ -2507,8 +2606,8 @@ class ConfirmDialog {
|
|
|
2507
2606
|
this.data = inject(MAT_DIALOG_DATA);
|
|
2508
2607
|
this.dialogRef = inject((MatDialogRef));
|
|
2509
2608
|
}
|
|
2510
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2511
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2609
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: ConfirmDialog, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2610
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: ConfirmDialog, isStandalone: true, selector: "shell-confirm-dialog", ngImport: i0, template: `
|
|
2512
2611
|
<h2 mat-dialog-title>{{ data.title }}</h2>
|
|
2513
2612
|
<mat-dialog-content>
|
|
2514
2613
|
<p>{{ data.message }}</p>
|
|
@@ -2520,9 +2619,9 @@ class ConfirmDialog {
|
|
|
2520
2619
|
<button mat-button (click)="dialogRef.close(false)">{{ data.cancelLabel ?? 'Cancel' }}</button>
|
|
2521
2620
|
<button mat-flat-button color="warn" (click)="dialogRef.close(true)">{{ data.confirmLabel ?? 'Confirm' }}</button>
|
|
2522
2621
|
</mat-dialog-actions>
|
|
2523
|
-
`, isInline: true, styles: [":host{display:block}.warning-message{color:var(--color-warning);margin-top:8px}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.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"] }] }); }
|
|
2622
|
+
`, isInline: true, styles: [":host{display:block}.warning-message{color:var(--color-warning);margin-top:8px}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.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"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2524
2623
|
}
|
|
2525
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2624
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: ConfirmDialog, decorators: [{
|
|
2526
2625
|
type: Component,
|
|
2527
2626
|
args: [{ selector: 'shell-confirm-dialog', imports: [MatDialogModule, MatButtonModule], template: `
|
|
2528
2627
|
<h2 mat-dialog-title>{{ data.title }}</h2>
|
|
@@ -2536,7 +2635,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
2536
2635
|
<button mat-button (click)="dialogRef.close(false)">{{ data.cancelLabel ?? 'Cancel' }}</button>
|
|
2537
2636
|
<button mat-flat-button color="warn" (click)="dialogRef.close(true)">{{ data.confirmLabel ?? 'Confirm' }}</button>
|
|
2538
2637
|
</mat-dialog-actions>
|
|
2539
|
-
`, styles: [":host{display:block}.warning-message{color:var(--color-warning);margin-top:8px}\n"] }]
|
|
2638
|
+
`, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:block}.warning-message{color:var(--color-warning);margin-top:8px}\n"] }]
|
|
2540
2639
|
}] });
|
|
2541
2640
|
|
|
2542
2641
|
/*
|