@praxisui/settings-panel 8.0.0-beta.8 → 8.0.0-beta.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -0
- package/fesm2022/praxisui-settings-panel.mjs +690 -249
- package/package.json +13 -11
- package/{index.d.ts → types/praxisui-settings-panel.d.ts} +18 -4
|
@@ -23,9 +23,9 @@ import { ComponentPortal } from '@angular/cdk/portal';
|
|
|
23
23
|
import * as i1$2 from '@angular/cdk/overlay';
|
|
24
24
|
import * as i2$1 from '@angular/material/snack-bar';
|
|
25
25
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
26
|
-
import * as
|
|
26
|
+
import * as i3$1 from '@angular/material/expansion';
|
|
27
27
|
import { MatExpansionModule } from '@angular/material/expansion';
|
|
28
|
-
import * as
|
|
28
|
+
import * as i8 from '@angular/material/chips';
|
|
29
29
|
import { MatChipsModule } from '@angular/material/chips';
|
|
30
30
|
import { AiBackendApiService } from '@praxisui/ai';
|
|
31
31
|
|
|
@@ -480,6 +480,12 @@ function providePraxisSettingsPanelI18n() {
|
|
|
480
480
|
});
|
|
481
481
|
}
|
|
482
482
|
|
|
483
|
+
const DEFAULT_DIAGNOSTICS = {
|
|
484
|
+
showStatusMessage: true,
|
|
485
|
+
showDisabledReason: true,
|
|
486
|
+
showBusyState: true,
|
|
487
|
+
exposeValidationState: true,
|
|
488
|
+
};
|
|
483
489
|
class SettingsPanelComponent {
|
|
484
490
|
cdr;
|
|
485
491
|
dialog;
|
|
@@ -498,6 +504,9 @@ class SettingsPanelComponent {
|
|
|
498
504
|
isDirty = false;
|
|
499
505
|
isValid = true;
|
|
500
506
|
isBusy = false;
|
|
507
|
+
diagnostics = {
|
|
508
|
+
...DEFAULT_DIAGNOSTICS,
|
|
509
|
+
};
|
|
501
510
|
lastSavedAt = null;
|
|
502
511
|
activePointerId = null;
|
|
503
512
|
dragStartX = 0;
|
|
@@ -541,9 +550,20 @@ class SettingsPanelComponent {
|
|
|
541
550
|
}
|
|
542
551
|
return '';
|
|
543
552
|
}
|
|
553
|
+
get applySaveDisabledReason() {
|
|
554
|
+
return this.diagnostics.showDisabledReason ? this.disabledReason : '';
|
|
555
|
+
}
|
|
556
|
+
get showStatusMessage() {
|
|
557
|
+
return this.diagnostics.showStatusMessage;
|
|
558
|
+
}
|
|
559
|
+
get showBusyIndicator() {
|
|
560
|
+
return this.isBusy && this.diagnostics.showBusyState;
|
|
561
|
+
}
|
|
544
562
|
get statusTone() {
|
|
545
|
-
if (this.isBusy)
|
|
563
|
+
if (this.isBusy && this.diagnostics.showBusyState)
|
|
546
564
|
return 'busy';
|
|
565
|
+
if (!this.isValid && this.diagnostics.exposeValidationState)
|
|
566
|
+
return 'invalid';
|
|
547
567
|
if (this.isDirty)
|
|
548
568
|
return 'dirty';
|
|
549
569
|
if (this.lastSavedAt)
|
|
@@ -554,6 +574,9 @@ class SettingsPanelComponent {
|
|
|
554
574
|
if (this.statusTone === 'busy') {
|
|
555
575
|
return this.tx('Operation in progress...');
|
|
556
576
|
}
|
|
577
|
+
if (this.statusTone === 'invalid') {
|
|
578
|
+
return this.tx('The form contains errors that need to be fixed.');
|
|
579
|
+
}
|
|
557
580
|
if (this.statusTone === 'dirty') {
|
|
558
581
|
return this.tx('Unsaved changes');
|
|
559
582
|
}
|
|
@@ -726,6 +749,13 @@ class SettingsPanelComponent {
|
|
|
726
749
|
this.expanded = false;
|
|
727
750
|
this.collapsedWidthBeforeExpand = null;
|
|
728
751
|
}
|
|
752
|
+
configureDiagnostics(config) {
|
|
753
|
+
this.diagnostics = {
|
|
754
|
+
...DEFAULT_DIAGNOSTICS,
|
|
755
|
+
...(config ?? {}),
|
|
756
|
+
};
|
|
757
|
+
this.cdr.markForCheck();
|
|
758
|
+
}
|
|
729
759
|
toggleExpand() {
|
|
730
760
|
if (!this.expanded) {
|
|
731
761
|
this.collapsedWidthBeforeExpand = this.width;
|
|
@@ -910,10 +940,10 @@ class SettingsPanelComponent {
|
|
|
910
940
|
.open(ConfirmDialogComponent, { data: dialogData, autoFocus: false })
|
|
911
941
|
.afterClosed();
|
|
912
942
|
}
|
|
913
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
914
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: SettingsPanelComponent, isStandalone: true, selector: "praxis-settings-panel", host: { listeners: { "document:keydown": "handleKeydown($event)", "document:pointermove": "onDocumentPointerMove($event)", "document:pointerup": "onDocumentPointerEnd($event)", "document:pointercancel": "onDocumentPointerEnd($event)" } }, providers: [providePraxisSettingsPanelI18n()], viewQueries: [{ propertyName: "contentHost", first: true, predicate: ["contentHost"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div\n class=\"settings-panel\"\n data-testid=\"settings-panel-root\"\n [class.expanded]=\"expanded\"\n [class.is-resizable]=\"showResizeHandle\"\n [ngStyle]=\"panelInlineStyles\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"titleId\"\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n>\n @if (showResizeHandle) {\n <div\n class=\"settings-panel__resize-handle\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"resizeHandleLabel\"\n (pointerdown)=\"onResizeHandlePointerDown($event)\"\n (keydown)=\"onResizeHandleKeydown($event)\"\n ></div>\n }\n <header class=\"settings-panel-header\">\n <h2 class=\"settings-panel-title\" [id]=\"titleId\">\n <mat-icon *ngIf=\"titleIcon\" class=\"title-icon\" [praxisIcon]=\"titleIcon\"></mat-icon>\n <span>{{ title }}</span>\n </h2>\n <span class=\"spacer\"></span>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-toggle-expand\"\n [attr.aria-label]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n [attr.aria-expanded]=\"expanded\"\n [matTooltip]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n (click)=\"toggleExpand()\"\n >\n <mat-icon [praxisIcon]=\"expanded ? 'close_fullscreen' : 'open_in_full'\"></mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-close-icon\"\n [attr.aria-label]=\"tx('Close')\"\n [matTooltip]=\"tx('Close')\"\n (click)=\"onCancel()\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </header>\n <div\n class=\"settings-panel-status\"\n [attr.data-status]=\"statusTone\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <mat-icon\n aria-hidden=\"true\"\n [praxisIcon]=\"\n statusTone === 'dirty'\n ? 'warning'\n : statusTone === 'saved'\n ? 'check_circle'\n : statusTone === 'busy'\n ? 'autorenew'\n : 'info'\n \"\n ></mat-icon>\n <span>{{ statusMessage }}</span>\n </div>\n <div class=\"settings-panel-body\">\n <ng-template #contentHost></ng-template>\n </div>\n <footer class=\"settings-panel-footer\">\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-reset\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onReset()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'restart_alt'\"></mat-icon>\n <span>{{ tx('Reset') }}</span>\n </button>\n <span class=\"spacer\"></span>\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-cancel\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onCancel()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'close'\"></mat-icon>\n <span>{{ tx('Cancel') }}</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"settings-panel-apply\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onApply()\"\n [disabled]=\"!canApply\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canApply\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'done'\"></mat-icon>\n <span>{{ tx('Apply') }}</span>\n </ng-container>\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"settings-panel-save\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onSave()\"\n [disabled]=\"!canSave\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canSave\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'save'\"></mat-icon>\n <span>{{ tx('Save & Close') }}</span>\n </ng-container>\n </button>\n </footer>\n</div>\n", styles: ["@charset \"UTF-8\";praxis-settings-panel{display:block;height:100%;width:100%;min-width:0;flex:1 1 auto}praxis-settings-panel .settings-panel{position:relative;--pfx-settings-panel-surface-container: var( --md-sys-color-surface-container, #ffffff );--pfx-settings-panel-surface-container-high: var( --md-sys-color-surface-container-high, #f7f7f7 );--pfx-settings-panel-surface-container-low: var( --md-sys-color-surface-container-low, #f2f4f7 );--pfx-settings-panel-surface: var(--md-sys-color-surface, #ffffff);--pfx-settings-panel-on-surface: var(--md-sys-color-on-surface, #111827);--pfx-settings-panel-on-surface-variant: var( --md-sys-color-on-surface-variant, rgba(17, 24, 39, .72) );--pfx-settings-panel-outline: var( --md-sys-color-outline, rgba(15, 23, 42, .24) );--pfx-settings-panel-outline-variant: var( --md-sys-color-outline-variant, rgba(15, 23, 42, .12) );--pfx-settings-panel-primary: var(--md-sys-color-primary, #2563eb);--pfx-settings-panel-primary-container: var( --md-sys-color-primary-container, rgba(37, 99, 235, .14) );--pfx-settings-panel-on-primary-container: var( --md-sys-color-on-primary-container, #0f172a );--pfx-settings-panel-secondary: var( --md-sys-color-secondary, var(--pfx-settings-panel-primary) );--pfx-settings-panel-error: var(--md-sys-color-error, #b3261e);--pfx-settings-panel-error-container: var( --md-sys-color-error-container, rgba(179, 38, 30, .14) );display:grid;grid-template-rows:auto auto 1fr auto;grid-template-areas:\"header\" \"status\" \"body\" \"footer\";height:100%;background:var(--pfx-settings-panel-surface-container);color:var(--pfx-settings-panel-on-surface);border-left:1px solid var(--pfx-settings-panel-outline-variant);width:var(--pfx-settings-panel-width, 720px);transition:width .3s ease;box-shadow:var(--pfx-settings-panel-elevation, var(--md-sys-elevation-level2, 0 8px 24px rgba(0, 0, 0, .16)));overflow:hidden}praxis-settings-panel .settings-panel.expanded{width:min(var(--pfx-settings-panel-width-expanded, 95vw),var(--pfx-settings-panel-max-width, 2400px))}praxis-settings-panel .settings-panel__resize-handle{position:absolute;inset:0 auto 0 0;width:12px;cursor:col-resize;touch-action:none;z-index:3;outline:none}praxis-settings-panel .settings-panel__resize-handle:before{content:\"\";position:absolute;inset:0 auto 0 4px;width:2px;background:transparent;transition:background-color var(--pfx-side-panel-motion-duration, .16s) ease,opacity var(--pfx-side-panel-motion-duration, .16s) ease;opacity:0}praxis-settings-panel .settings-panel.is-resizable:hover .settings-panel__resize-handle:before,praxis-settings-panel .settings-panel__resize-handle:focus-visible:before{opacity:1;background:var(--pfx-settings-panel-outline)}praxis-settings-panel .settings-panel-header{grid-area:header;display:flex;align-items:center;gap:var(--pfx-settings-panel-header-gap, 8px);padding:0 var(--pfx-settings-panel-header-padding-x, 16px);height:var(--pfx-settings-panel-header-height, 64px);border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);box-shadow:var(--pfx-settings-panel-header-shadow, var(--md-sys-elevation-level1, 0 2px 6px rgba(0, 0, 0, .08)));flex-shrink:0}praxis-settings-panel .settings-panel-header .spacer{flex:1}praxis-settings-panel .settings-panel-status{grid-area:status;display:flex;align-items:center;gap:8px;min-height:36px;padding:6px 16px;border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);color:var(--pfx-settings-panel-on-surface);font-size:.85rem;font-weight:500}praxis-settings-panel .settings-panel-status mat-icon{width:18px;height:18px;font-size:18px}praxis-settings-panel .settings-panel-status[data-status=dirty]{color:var(--pfx-settings-panel-error);background:color-mix(in srgb,var(--pfx-settings-panel-error-container) 30%,var(--pfx-settings-panel-surface-container-high))}praxis-settings-panel .settings-panel-status[data-status=saved]{color:var(--pfx-settings-panel-primary);background:color-mix(in srgb,var(--pfx-settings-panel-primary-container) 28%,var(--pfx-settings-panel-surface-container-high))}praxis-settings-panel .settings-panel-body{grid-area:body;overflow-y:auto;min-height:0;padding:var(--pfx-settings-panel-body-padding, 8px 8px 24px 8px);background:var(--pfx-settings-panel-surface);display:flex;flex-direction:column}praxis-settings-panel .settings-panel-content{display:block}praxis-settings-panel .settings-panel-footer{grid-area:footer;border-top:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);box-shadow:var(--pfx-settings-panel-footer-shadow, var(--md-sys-elevation-level1, 0 -2px 6px rgba(0, 0, 0, .08)));display:flex;align-items:center;padding:var(--pfx-settings-panel-footer-padding, 12px 16px);column-gap:var(--pfx-settings-panel-footer-gap, 12px);flex-shrink:0}praxis-settings-panel .spacer{flex:1}praxis-settings-panel .settings-panel-title{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-title-gap, 8px);font-weight:700;letter-spacing:.2px;margin:0}praxis-settings-panel .settings-panel-title mat-icon{color:var(--pfx-settings-panel-primary)}praxis-settings-panel .settings-panel-title .title-icon{width:20px;height:20px;font-size:20px}praxis-settings-panel .settings-panel-footer button+button{margin-left:var(--pfx-settings-panel-footer-gap, 12px)}praxis-settings-panel .settings-panel-footer button{display:inline-flex;align-items:center}praxis-settings-panel .settings-panel-footer button .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}praxis-settings-panel .settings-panel-footer .mat-button-wrapper{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px)}praxis-settings-panel .settings-panel-footer .mat-progress-spinner{margin-right:8px}praxis-settings-panel .settings-panel-footer .mat-flat-button[color=primary]{font-weight:600}praxis-settings-panel .settings-panel .mdc-button__label{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px);line-height:1}praxis-settings-panel .settings-panel .mdc-button__label>span{display:inline-flex;align-items:center;line-height:1}praxis-settings-panel .settings-panel .mdc-button__label .mat-icon{display:inline-flex;align-items:center;justify-content:center;line-height:1}praxis-settings-panel .settings-panel .mat-divider{background-color:var(--pfx-settings-panel-outline-variant)!important}praxis-settings-panel .settings-panel .mat-expansion-panel{background:var(--pfx-settings-panel-surface-container)!important;border:1px solid var(--pfx-settings-panel-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08));color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-content{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:hover{background:color-mix(in srgb,var(--pfx-settings-panel-surface-container-high) 84%,var(--pfx-settings-panel-primary) 16%)}praxis-settings-panel .settings-panel .mat-expansion-panel.mat-expanded>.mat-expansion-panel-header{background:var(--pfx-settings-panel-surface-container-high)!important}praxis-settings-panel .settings-panel .mat-expansion-panel-header mat-icon,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-icon{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title>*,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description>*{color:inherit}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title small,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description small{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-indicator,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-indicator:after{color:var(--pfx-settings-panel-on-surface-variant);border-color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-action-row{border-top-color:var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-accordion,praxis-settings-panel .settings-panel .mat-accordion .mat-expansion-panel-spacing{background:transparent!important}praxis-settings-panel .settings-panel .mat-expansion-panel-content,praxis-settings-panel .settings-panel .mat-expansion-panel-content-wrapper,praxis-settings-panel .settings-panel .mat-expansion-panel-body{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-expansion-panel-body{padding:8px}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-expansion-panel-body>*{color:inherit}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header{border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab{min-width:0}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab:hover .mdc-tab__text-label,praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab:focus .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination-chevron{border-color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination:not(.mat-mdc-tab-header-pagination-disabled):hover{background:color-mix(in srgb,var(--pfx-settings-panel-surface-container-high) 84%,var(--pfx-settings-panel-primary) 16%)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab-indicator__content--underline{border-color:var(--pfx-settings-panel-primary)}praxis-settings-panel .settings-panel .mat-mdc-card{background:var(--pfx-settings-panel-surface-container-low);border:1px solid var(--pfx-settings-panel-outline-variant);color:var(--pfx-settings-panel-on-surface);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08))}praxis-settings-panel .settings-panel .mat-mdc-card-subtitle,praxis-settings-panel .settings-panel .mat-mdc-card-content{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-card-title{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-form-field{width:100%;--mdc-filled-text-field-container-color: var( --pfx-settings-panel-surface-container );--mdc-filled-text-field-hover-container-color: var( --pfx-settings-panel-surface-container-high );--mdc-filled-text-field-focus-container-color: var( --pfx-settings-panel-surface-container-high );--mdc-filled-text-field-active-indicator-color: var( --pfx-settings-panel-outline-variant );--mdc-filled-text-field-hover-active-indicator-color: var( --pfx-settings-panel-secondary );--mdc-filled-text-field-focus-active-indicator-color: var( --pfx-settings-panel-primary );--mdc-filled-text-field-label-text-color: var( --pfx-settings-panel-on-surface-variant );--mdc-filled-text-field-focus-label-text-color: var( --pfx-settings-panel-primary );--mdc-filled-text-field-input-text-color: var( --pfx-settings-panel-on-surface );--mdc-filled-text-field-caret-color: var(--pfx-settings-panel-primary);--mdc-outlined-text-field-outline-color: var( --pfx-settings-panel-outline-variant );--mdc-outlined-text-field-hover-outline-color: var( --pfx-settings-panel-secondary );--mdc-outlined-text-field-focus-outline-color: var( --pfx-settings-panel-primary );--mdc-outlined-text-field-label-text-color: var( --pfx-settings-panel-on-surface-variant );--mdc-outlined-text-field-focus-label-text-color: var( --pfx-settings-panel-primary );--mdc-outlined-text-field-input-text-color: var( --pfx-settings-panel-on-surface );--mdc-outlined-text-field-caret-color: var(--pfx-settings-panel-primary);--mat-form-field-focus-select-arrow-color: var( --pfx-settings-panel-primary );--mat-form-field-enabled-select-arrow-color: var( --pfx-settings-panel-on-surface-variant )}praxis-settings-panel .settings-panel .mdc-text-field--filled{background-color:var(--pfx-settings-panel-surface-container)!important;border-radius:var(--md-sys-shape-corner-small, 8px) var(--md-sys-shape-corner-small, 8px) 0 0}praxis-settings-panel .settings-panel .mat-mdc-text-field-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-flex,praxis-settings-panel .settings-panel .mat-mdc-form-field-infix,praxis-settings-panel .settings-panel .mat-mdc-form-field-focus-overlay{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-form-field-focus-overlay{opacity:0}praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-text-field__input,praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-floating-label,praxis-settings-panel .settings-panel .mat-mdc-select-value,praxis-settings-panel .settings-panel .mat-mdc-select-arrow,praxis-settings-panel .settings-panel .mat-mdc-form-field .mat-mdc-floating-label{color:var(--pfx-settings-panel-on-surface-variant)!important}praxis-settings-panel .settings-panel .mdc-text-field--filled.mdc-text-field--focused .mdc-floating-label,praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-text-field__input{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-mdc-form-field input,praxis-settings-panel .settings-panel .mat-mdc-form-field textarea,praxis-settings-panel .settings-panel .mat-mdc-form-field .mdc-text-field__input{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-mdc-form-field-subscript-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-hint-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-error-wrapper,praxis-settings-panel .settings-panel .mat-mdc-hint{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-button-toggle-group{border-color:var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-button-toggle{background:var(--pfx-settings-panel-surface-container-low);color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-button-toggle+.mat-button-toggle{border-left-color:var(--pfx-settings-panel-outline-variant)}praxis-settings-panel .settings-panel .mat-button-toggle-checked{background:var(--pfx-settings-panel-primary-container)!important;color:var(--pfx-settings-panel-on-primary-container)!important}praxis-settings-panel .settings-panel .mat-button-toggle .mat-icon,praxis-settings-panel .settings-panel .mat-button-toggle-checked .mat-icon{color:inherit}praxis-settings-panel .settings-panel .mat-mdc-slide-toggle .mdc-label{color:var(--pfx-settings-panel-on-surface)}.praxis-settings-panel-backdrop{background:var(--pfx-backdrop, var(--md-sys-color-scrim, rgba(8, 15, 26, .42)));backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%)}.praxis-settings-panel-pane{position:fixed!important;top:0!important;right:0!important;display:flex!important;align-items:stretch!important;height:100vh!important;max-height:100vh!important;z-index:var(--praxis-layer-settings-panel, 1220)!important}.praxis-settings-panel-pane .settings-panel{pointer-events:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatDialogModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
943
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SettingsPanelComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
|
|
944
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: SettingsPanelComponent, isStandalone: true, selector: "praxis-settings-panel", host: { listeners: { "document:keydown": "handleKeydown($event)", "document:pointermove": "onDocumentPointerMove($event)", "document:pointerup": "onDocumentPointerEnd($event)", "document:pointercancel": "onDocumentPointerEnd($event)" } }, providers: [providePraxisSettingsPanelI18n()], viewQueries: [{ propertyName: "contentHost", first: true, predicate: ["contentHost"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div\n class=\"settings-panel\"\n data-testid=\"settings-panel-root\"\n [class.expanded]=\"expanded\"\n [class.is-resizable]=\"showResizeHandle\"\n [ngStyle]=\"panelInlineStyles\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"titleId\"\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n >\n @if (showResizeHandle) {\n <div\n class=\"settings-panel__resize-handle\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"resizeHandleLabel\"\n (pointerdown)=\"onResizeHandlePointerDown($event)\"\n (keydown)=\"onResizeHandleKeydown($event)\"\n ></div>\n }\n <header class=\"settings-panel-header\">\n <h2 class=\"settings-panel-title\" [id]=\"titleId\">\n @if (titleIcon) {\n <mat-icon class=\"title-icon\" [praxisIcon]=\"titleIcon\"></mat-icon>\n }\n <span>{{ title }}</span>\n </h2>\n <span class=\"spacer\"></span>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-toggle-expand\"\n [attr.aria-label]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n [attr.aria-expanded]=\"expanded\"\n [matTooltip]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n (click)=\"toggleExpand()\"\n >\n <mat-icon [praxisIcon]=\"expanded ? 'close_fullscreen' : 'open_in_full'\"></mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-close-icon\"\n [attr.aria-label]=\"tx('Close')\"\n [matTooltip]=\"tx('Close')\"\n (click)=\"onCancel()\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </header>\n @if (showStatusMessage) {\n <div\n class=\"settings-panel-status\"\n [attr.data-status]=\"statusTone\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <mat-icon\n aria-hidden=\"true\"\n [praxisIcon]=\"\n statusTone === 'dirty' || statusTone === 'invalid'\n ? 'warning'\n : statusTone === 'saved'\n ? 'check_circle'\n : statusTone === 'busy'\n ? 'autorenew'\n : 'info'\n \"\n ></mat-icon>\n <span>{{ statusMessage }}</span>\n </div>\n }\n <div class=\"settings-panel-body\">\n <ng-template #contentHost></ng-template>\n </div>\n <footer class=\"settings-panel-footer\">\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-reset\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onReset()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'restart_alt'\"></mat-icon>\n <span>{{ tx('Reset') }}</span>\n </button>\n <span class=\"spacer\"></span>\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-cancel\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onCancel()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'close'\"></mat-icon>\n <span>{{ tx('Cancel') }}</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"settings-panel-apply\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onApply()\"\n [disabled]=\"!canApply\"\n [matTooltip]=\"applySaveDisabledReason\"\n [matTooltipDisabled]=\"canApply || !diagnostics.showDisabledReason\"\n [attr.aria-busy]=\"isBusy\"\n >\n @if (showBusyIndicator) {\n <mat-progress-spinner\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n }\n @if (!showBusyIndicator) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'done'\"></mat-icon>\n <span>{{ tx('Apply') }}</span>\n }\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"settings-panel-save\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onSave()\"\n [disabled]=\"!canSave\"\n [matTooltip]=\"applySaveDisabledReason\"\n [matTooltipDisabled]=\"canSave || !diagnostics.showDisabledReason\"\n [attr.aria-busy]=\"isBusy\"\n >\n @if (showBusyIndicator) {\n <mat-progress-spinner\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n }\n @if (!showBusyIndicator) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'save'\"></mat-icon>\n <span>{{ tx('Save & Close') }}</span>\n }\n </button>\n </footer>\n</div>\n", styles: ["@charset \"UTF-8\";praxis-settings-panel{display:block;height:100%;width:100%;min-width:0;flex:1 1 auto}praxis-settings-panel .settings-panel{position:relative;--pfx-settings-panel-surface-container: var( --md-sys-color-surface-container, #ffffff );--pfx-settings-panel-surface-container-high: var( --md-sys-color-surface-container-high, #f7f7f7 );--pfx-settings-panel-surface-container-low: var( --md-sys-color-surface-container-low, #f2f4f7 );--pfx-settings-panel-surface: var(--md-sys-color-surface, #ffffff);--pfx-settings-panel-on-surface: var(--md-sys-color-on-surface, #111827);--pfx-settings-panel-on-surface-variant: var( --md-sys-color-on-surface-variant, rgba(17, 24, 39, .72) );--pfx-settings-panel-outline: var( --md-sys-color-outline, rgba(15, 23, 42, .24) );--pfx-settings-panel-outline-variant: var( --md-sys-color-outline-variant, rgba(15, 23, 42, .12) );--pfx-settings-panel-primary: var(--md-sys-color-primary, #2563eb);--pfx-settings-panel-primary-container: var( --md-sys-color-primary-container, rgba(37, 99, 235, .14) );--pfx-settings-panel-on-primary-container: var( --md-sys-color-on-primary-container, #0f172a );--pfx-settings-panel-secondary: var( --md-sys-color-secondary, var(--pfx-settings-panel-primary) );--pfx-settings-panel-error: var(--md-sys-color-error, #b3261e);--pfx-settings-panel-error-container: var( --md-sys-color-error-container, rgba(179, 38, 30, .14) );display:grid;grid-template-rows:auto auto 1fr auto;grid-template-areas:\"header\" \"status\" \"body\" \"footer\";height:100%;background:var(--pfx-settings-panel-surface-container);color:var(--pfx-settings-panel-on-surface);border-left:1px solid var(--pfx-settings-panel-outline-variant);width:var(--pfx-settings-panel-width, 720px);transition:width .3s ease;box-shadow:var(--pfx-settings-panel-elevation, var(--md-sys-elevation-level2, 0 8px 24px rgba(0, 0, 0, .16)));overflow:hidden}praxis-settings-panel .settings-panel.expanded{width:min(var(--pfx-settings-panel-width-expanded, 95vw),var(--pfx-settings-panel-max-width, 2400px))}praxis-settings-panel .settings-panel__resize-handle{position:absolute;inset:0 auto 0 0;width:12px;cursor:col-resize;touch-action:none;z-index:3;outline:none}praxis-settings-panel .settings-panel__resize-handle:before{content:\"\";position:absolute;inset:0 auto 0 4px;width:2px;background:transparent;transition:background-color var(--pfx-side-panel-motion-duration, .16s) ease,opacity var(--pfx-side-panel-motion-duration, .16s) ease;opacity:0}praxis-settings-panel .settings-panel.is-resizable:hover .settings-panel__resize-handle:before,praxis-settings-panel .settings-panel__resize-handle:focus-visible:before{opacity:1;background:var(--pfx-settings-panel-outline)}praxis-settings-panel .settings-panel-header{grid-area:header;display:flex;align-items:center;gap:var(--pfx-settings-panel-header-gap, 8px);padding:0 var(--pfx-settings-panel-header-padding-x, 16px);height:var(--pfx-settings-panel-header-height, 64px);border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);box-shadow:var(--pfx-settings-panel-header-shadow, var(--md-sys-elevation-level1, 0 2px 6px rgba(0, 0, 0, .08)));flex-shrink:0}praxis-settings-panel .settings-panel-header .spacer{flex:1}praxis-settings-panel .settings-panel-status{grid-area:status;display:flex;align-items:center;gap:8px;min-height:36px;padding:6px 16px;border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);color:var(--pfx-settings-panel-on-surface);font-size:.85rem;font-weight:500}praxis-settings-panel .settings-panel-status mat-icon{width:18px;height:18px;font-size:18px}praxis-settings-panel .settings-panel-status[data-status=dirty],praxis-settings-panel .settings-panel-status[data-status=invalid]{color:var(--pfx-settings-panel-error);background:color-mix(in srgb,var(--pfx-settings-panel-error-container) 30%,var(--pfx-settings-panel-surface-container-high))}praxis-settings-panel .settings-panel-status[data-status=saved]{color:var(--pfx-settings-panel-primary);background:color-mix(in srgb,var(--pfx-settings-panel-primary-container) 28%,var(--pfx-settings-panel-surface-container-high))}praxis-settings-panel .settings-panel-body{grid-area:body;overflow-y:auto;min-height:0;padding:var(--pfx-settings-panel-body-padding, 8px 8px 24px 8px);background:var(--pfx-settings-panel-surface);display:flex;flex-direction:column}praxis-settings-panel .settings-panel-content{display:block}praxis-settings-panel .settings-panel-footer{grid-area:footer;border-top:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);box-shadow:var(--pfx-settings-panel-footer-shadow, var(--md-sys-elevation-level1, 0 -2px 6px rgba(0, 0, 0, .08)));display:flex;align-items:center;padding:var(--pfx-settings-panel-footer-padding, 12px 16px);column-gap:var(--pfx-settings-panel-footer-gap, 12px);flex-shrink:0}praxis-settings-panel .spacer{flex:1}praxis-settings-panel .settings-panel-title{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-title-gap, 8px);font-weight:700;letter-spacing:.2px;margin:0}praxis-settings-panel .settings-panel-title mat-icon{color:var(--pfx-settings-panel-primary)}praxis-settings-panel .settings-panel-title .title-icon{width:20px;height:20px;font-size:20px}praxis-settings-panel .settings-panel-footer button+button{margin-left:var(--pfx-settings-panel-footer-gap, 12px)}praxis-settings-panel .settings-panel-footer button{display:inline-flex;align-items:center}praxis-settings-panel .settings-panel-footer button .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}praxis-settings-panel .settings-panel-footer .mat-button-wrapper{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px)}praxis-settings-panel .settings-panel-footer .mat-progress-spinner{margin-right:8px}praxis-settings-panel .settings-panel-footer .mat-flat-button[color=primary]{font-weight:600}praxis-settings-panel .settings-panel .mdc-button__label{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px);line-height:1}praxis-settings-panel .settings-panel .mdc-button__label>span{display:inline-flex;align-items:center;line-height:1}praxis-settings-panel .settings-panel .mdc-button__label .mat-icon{display:inline-flex;align-items:center;justify-content:center;line-height:1}praxis-settings-panel .settings-panel .mat-divider{background-color:var(--pfx-settings-panel-outline-variant)!important}praxis-settings-panel .settings-panel .mat-expansion-panel{background:var(--pfx-settings-panel-surface-container)!important;border:1px solid var(--pfx-settings-panel-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08));color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-content{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:hover{background:color-mix(in srgb,var(--pfx-settings-panel-surface-container-high) 84%,var(--pfx-settings-panel-primary) 16%)}praxis-settings-panel .settings-panel .mat-expansion-panel.mat-expanded>.mat-expansion-panel-header{background:var(--pfx-settings-panel-surface-container-high)!important}praxis-settings-panel .settings-panel .mat-expansion-panel-header mat-icon,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-icon{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title>*,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description>*{color:inherit}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title small,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description small{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-indicator,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-indicator:after{color:var(--pfx-settings-panel-on-surface-variant);border-color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-action-row{border-top-color:var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-accordion,praxis-settings-panel .settings-panel .mat-accordion .mat-expansion-panel-spacing{background:transparent!important}praxis-settings-panel .settings-panel .mat-expansion-panel-content,praxis-settings-panel .settings-panel .mat-expansion-panel-content-wrapper,praxis-settings-panel .settings-panel .mat-expansion-panel-body{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-expansion-panel-body{padding:8px}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-expansion-panel-body>*{color:inherit}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header{border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab{min-width:0}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab:hover .mdc-tab__text-label,praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab:focus .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination-chevron{border-color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination:not(.mat-mdc-tab-header-pagination-disabled):hover{background:color-mix(in srgb,var(--pfx-settings-panel-surface-container-high) 84%,var(--pfx-settings-panel-primary) 16%)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab-indicator__content--underline{border-color:var(--pfx-settings-panel-primary)}praxis-settings-panel .settings-panel .mat-mdc-card{background:var(--pfx-settings-panel-surface-container-low);border:1px solid var(--pfx-settings-panel-outline-variant);color:var(--pfx-settings-panel-on-surface);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08))}praxis-settings-panel .settings-panel .mat-mdc-card-subtitle,praxis-settings-panel .settings-panel .mat-mdc-card-content{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-card-title{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-form-field{width:100%;--mdc-filled-text-field-container-color: var( --pfx-settings-panel-surface-container );--mdc-filled-text-field-hover-container-color: var( --pfx-settings-panel-surface-container-high );--mdc-filled-text-field-focus-container-color: var( --pfx-settings-panel-surface-container-high );--mdc-filled-text-field-active-indicator-color: var( --pfx-settings-panel-outline-variant );--mdc-filled-text-field-hover-active-indicator-color: var( --pfx-settings-panel-secondary );--mdc-filled-text-field-focus-active-indicator-color: var( --pfx-settings-panel-primary );--mdc-filled-text-field-label-text-color: var( --pfx-settings-panel-on-surface-variant );--mdc-filled-text-field-focus-label-text-color: var( --pfx-settings-panel-primary );--mdc-filled-text-field-input-text-color: var( --pfx-settings-panel-on-surface );--mdc-filled-text-field-caret-color: var(--pfx-settings-panel-primary);--mdc-outlined-text-field-outline-color: var( --pfx-settings-panel-outline-variant );--mdc-outlined-text-field-hover-outline-color: var( --pfx-settings-panel-secondary );--mdc-outlined-text-field-focus-outline-color: var( --pfx-settings-panel-primary );--mdc-outlined-text-field-label-text-color: var( --pfx-settings-panel-on-surface-variant );--mdc-outlined-text-field-focus-label-text-color: var( --pfx-settings-panel-primary );--mdc-outlined-text-field-input-text-color: var( --pfx-settings-panel-on-surface );--mdc-outlined-text-field-caret-color: var(--pfx-settings-panel-primary);--mat-form-field-focus-select-arrow-color: var( --pfx-settings-panel-primary );--mat-form-field-enabled-select-arrow-color: var( --pfx-settings-panel-on-surface-variant )}praxis-settings-panel .settings-panel .mdc-text-field--filled{background-color:var(--pfx-settings-panel-surface-container)!important;border-radius:var(--md-sys-shape-corner-small, 8px) var(--md-sys-shape-corner-small, 8px) 0 0}praxis-settings-panel .settings-panel .mat-mdc-text-field-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-flex,praxis-settings-panel .settings-panel .mat-mdc-form-field-infix,praxis-settings-panel .settings-panel .mat-mdc-form-field-focus-overlay{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-form-field-focus-overlay{opacity:0}praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-text-field__input,praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-floating-label,praxis-settings-panel .settings-panel .mat-mdc-select-value,praxis-settings-panel .settings-panel .mat-mdc-select-arrow,praxis-settings-panel .settings-panel .mat-mdc-form-field .mat-mdc-floating-label{color:var(--pfx-settings-panel-on-surface-variant)!important}praxis-settings-panel .settings-panel .mdc-text-field--filled.mdc-text-field--focused .mdc-floating-label,praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-text-field__input{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-mdc-form-field input,praxis-settings-panel .settings-panel .mat-mdc-form-field textarea,praxis-settings-panel .settings-panel .mat-mdc-form-field .mdc-text-field__input{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-mdc-form-field-subscript-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-hint-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-error-wrapper,praxis-settings-panel .settings-panel .mat-mdc-hint{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-button-toggle-group{border-color:var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-button-toggle{background:var(--pfx-settings-panel-surface-container-low);color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-button-toggle+.mat-button-toggle{border-left-color:var(--pfx-settings-panel-outline-variant)}praxis-settings-panel .settings-panel .mat-button-toggle-checked{background:var(--pfx-settings-panel-primary-container)!important;color:var(--pfx-settings-panel-on-primary-container)!important}praxis-settings-panel .settings-panel .mat-button-toggle .mat-icon,praxis-settings-panel .settings-panel .mat-button-toggle-checked .mat-icon{color:inherit}praxis-settings-panel .settings-panel .mat-mdc-slide-toggle .mdc-label{color:var(--pfx-settings-panel-on-surface)}.praxis-settings-panel-backdrop{background:var(--pfx-backdrop, var(--md-sys-color-scrim, rgba(8, 15, 26, .42)));backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%)}.praxis-settings-panel-pane{position:fixed!important;top:0!important;right:0!important;display:flex!important;align-items:stretch!important;height:100vh!important;max-height:100vh!important;z-index:var(--praxis-layer-settings-panel, 1220)!important}.praxis-settings-panel-pane .settings-panel{pointer-events:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatDialogModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
915
945
|
}
|
|
916
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
946
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SettingsPanelComponent, decorators: [{
|
|
917
947
|
type: Component,
|
|
918
948
|
args: [{ selector: 'praxis-settings-panel', standalone: true, imports: [
|
|
919
949
|
CommonModule,
|
|
@@ -925,7 +955,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
925
955
|
CdkTrapFocus,
|
|
926
956
|
MatProgressSpinnerModule,
|
|
927
957
|
MatDialogModule,
|
|
928
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [providePraxisSettingsPanelI18n()], template: "<div\n class=\"settings-panel\"\n data-testid=\"settings-panel-root\"\n [class.expanded]=\"expanded\"\n [class.is-resizable]=\"showResizeHandle\"\n [ngStyle]=\"panelInlineStyles\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"titleId\"\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n>\n @if (showResizeHandle) {\n <div\n class=\"settings-panel__resize-handle\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"resizeHandleLabel\"\n (pointerdown)=\"onResizeHandlePointerDown($event)\"\n (keydown)=\"onResizeHandleKeydown($event)\"\n ></div>\n }\n <header class=\"settings-panel-header\">\n <h2 class=\"settings-panel-title\" [id]=\"titleId\">\n <mat-icon *ngIf=\"titleIcon\" class=\"title-icon\" [praxisIcon]=\"titleIcon\"></mat-icon>\n <span>{{ title }}</span>\n </h2>\n <span class=\"spacer\"></span>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-toggle-expand\"\n [attr.aria-label]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n [attr.aria-expanded]=\"expanded\"\n [matTooltip]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n (click)=\"toggleExpand()\"\n >\n <mat-icon [praxisIcon]=\"expanded ? 'close_fullscreen' : 'open_in_full'\"></mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-close-icon\"\n [attr.aria-label]=\"tx('Close')\"\n [matTooltip]=\"tx('Close')\"\n (click)=\"onCancel()\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </header>\n <div\n class=\"settings-panel-status\"\n [attr.data-status]=\"statusTone\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <mat-icon\n aria-hidden=\"true\"\n [praxisIcon]=\"\n statusTone === 'dirty'\n ? 'warning'\n : statusTone === 'saved'\n ? 'check_circle'\n : statusTone === 'busy'\n ? 'autorenew'\n : 'info'\n \"\n ></mat-icon>\n <span>{{ statusMessage }}</span>\n </div>\n <div class=\"settings-panel-body\">\n <ng-template #contentHost></ng-template>\n </div>\n <footer class=\"settings-panel-footer\">\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-reset\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onReset()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'restart_alt'\"></mat-icon>\n <span>{{ tx('Reset') }}</span>\n </button>\n <span class=\"spacer\"></span>\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-cancel\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onCancel()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'close'\"></mat-icon>\n <span>{{ tx('Cancel') }}</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"settings-panel-apply\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onApply()\"\n [disabled]=\"!canApply\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canApply\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'done'\"></mat-icon>\n <span>{{ tx('Apply') }}</span>\n </ng-container>\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"settings-panel-save\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onSave()\"\n [disabled]=\"!canSave\"\n [matTooltip]=\"disabledReason\"\n [matTooltipDisabled]=\"canSave\"\n [attr.aria-busy]=\"isBusy\"\n >\n <mat-progress-spinner\n *ngIf=\"isBusy\"\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n <ng-container *ngIf=\"!isBusy\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'save'\"></mat-icon>\n <span>{{ tx('Save & Close') }}</span>\n </ng-container>\n </button>\n </footer>\n</div>\n", styles: ["@charset \"UTF-8\";praxis-settings-panel{display:block;height:100%;width:100%;min-width:0;flex:1 1 auto}praxis-settings-panel .settings-panel{position:relative;--pfx-settings-panel-surface-container: var( --md-sys-color-surface-container, #ffffff );--pfx-settings-panel-surface-container-high: var( --md-sys-color-surface-container-high, #f7f7f7 );--pfx-settings-panel-surface-container-low: var( --md-sys-color-surface-container-low, #f2f4f7 );--pfx-settings-panel-surface: var(--md-sys-color-surface, #ffffff);--pfx-settings-panel-on-surface: var(--md-sys-color-on-surface, #111827);--pfx-settings-panel-on-surface-variant: var( --md-sys-color-on-surface-variant, rgba(17, 24, 39, .72) );--pfx-settings-panel-outline: var( --md-sys-color-outline, rgba(15, 23, 42, .24) );--pfx-settings-panel-outline-variant: var( --md-sys-color-outline-variant, rgba(15, 23, 42, .12) );--pfx-settings-panel-primary: var(--md-sys-color-primary, #2563eb);--pfx-settings-panel-primary-container: var( --md-sys-color-primary-container, rgba(37, 99, 235, .14) );--pfx-settings-panel-on-primary-container: var( --md-sys-color-on-primary-container, #0f172a );--pfx-settings-panel-secondary: var( --md-sys-color-secondary, var(--pfx-settings-panel-primary) );--pfx-settings-panel-error: var(--md-sys-color-error, #b3261e);--pfx-settings-panel-error-container: var( --md-sys-color-error-container, rgba(179, 38, 30, .14) );display:grid;grid-template-rows:auto auto 1fr auto;grid-template-areas:\"header\" \"status\" \"body\" \"footer\";height:100%;background:var(--pfx-settings-panel-surface-container);color:var(--pfx-settings-panel-on-surface);border-left:1px solid var(--pfx-settings-panel-outline-variant);width:var(--pfx-settings-panel-width, 720px);transition:width .3s ease;box-shadow:var(--pfx-settings-panel-elevation, var(--md-sys-elevation-level2, 0 8px 24px rgba(0, 0, 0, .16)));overflow:hidden}praxis-settings-panel .settings-panel.expanded{width:min(var(--pfx-settings-panel-width-expanded, 95vw),var(--pfx-settings-panel-max-width, 2400px))}praxis-settings-panel .settings-panel__resize-handle{position:absolute;inset:0 auto 0 0;width:12px;cursor:col-resize;touch-action:none;z-index:3;outline:none}praxis-settings-panel .settings-panel__resize-handle:before{content:\"\";position:absolute;inset:0 auto 0 4px;width:2px;background:transparent;transition:background-color var(--pfx-side-panel-motion-duration, .16s) ease,opacity var(--pfx-side-panel-motion-duration, .16s) ease;opacity:0}praxis-settings-panel .settings-panel.is-resizable:hover .settings-panel__resize-handle:before,praxis-settings-panel .settings-panel__resize-handle:focus-visible:before{opacity:1;background:var(--pfx-settings-panel-outline)}praxis-settings-panel .settings-panel-header{grid-area:header;display:flex;align-items:center;gap:var(--pfx-settings-panel-header-gap, 8px);padding:0 var(--pfx-settings-panel-header-padding-x, 16px);height:var(--pfx-settings-panel-header-height, 64px);border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);box-shadow:var(--pfx-settings-panel-header-shadow, var(--md-sys-elevation-level1, 0 2px 6px rgba(0, 0, 0, .08)));flex-shrink:0}praxis-settings-panel .settings-panel-header .spacer{flex:1}praxis-settings-panel .settings-panel-status{grid-area:status;display:flex;align-items:center;gap:8px;min-height:36px;padding:6px 16px;border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);color:var(--pfx-settings-panel-on-surface);font-size:.85rem;font-weight:500}praxis-settings-panel .settings-panel-status mat-icon{width:18px;height:18px;font-size:18px}praxis-settings-panel .settings-panel-status[data-status=dirty]{color:var(--pfx-settings-panel-error);background:color-mix(in srgb,var(--pfx-settings-panel-error-container) 30%,var(--pfx-settings-panel-surface-container-high))}praxis-settings-panel .settings-panel-status[data-status=saved]{color:var(--pfx-settings-panel-primary);background:color-mix(in srgb,var(--pfx-settings-panel-primary-container) 28%,var(--pfx-settings-panel-surface-container-high))}praxis-settings-panel .settings-panel-body{grid-area:body;overflow-y:auto;min-height:0;padding:var(--pfx-settings-panel-body-padding, 8px 8px 24px 8px);background:var(--pfx-settings-panel-surface);display:flex;flex-direction:column}praxis-settings-panel .settings-panel-content{display:block}praxis-settings-panel .settings-panel-footer{grid-area:footer;border-top:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);box-shadow:var(--pfx-settings-panel-footer-shadow, var(--md-sys-elevation-level1, 0 -2px 6px rgba(0, 0, 0, .08)));display:flex;align-items:center;padding:var(--pfx-settings-panel-footer-padding, 12px 16px);column-gap:var(--pfx-settings-panel-footer-gap, 12px);flex-shrink:0}praxis-settings-panel .spacer{flex:1}praxis-settings-panel .settings-panel-title{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-title-gap, 8px);font-weight:700;letter-spacing:.2px;margin:0}praxis-settings-panel .settings-panel-title mat-icon{color:var(--pfx-settings-panel-primary)}praxis-settings-panel .settings-panel-title .title-icon{width:20px;height:20px;font-size:20px}praxis-settings-panel .settings-panel-footer button+button{margin-left:var(--pfx-settings-panel-footer-gap, 12px)}praxis-settings-panel .settings-panel-footer button{display:inline-flex;align-items:center}praxis-settings-panel .settings-panel-footer button .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}praxis-settings-panel .settings-panel-footer .mat-button-wrapper{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px)}praxis-settings-panel .settings-panel-footer .mat-progress-spinner{margin-right:8px}praxis-settings-panel .settings-panel-footer .mat-flat-button[color=primary]{font-weight:600}praxis-settings-panel .settings-panel .mdc-button__label{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px);line-height:1}praxis-settings-panel .settings-panel .mdc-button__label>span{display:inline-flex;align-items:center;line-height:1}praxis-settings-panel .settings-panel .mdc-button__label .mat-icon{display:inline-flex;align-items:center;justify-content:center;line-height:1}praxis-settings-panel .settings-panel .mat-divider{background-color:var(--pfx-settings-panel-outline-variant)!important}praxis-settings-panel .settings-panel .mat-expansion-panel{background:var(--pfx-settings-panel-surface-container)!important;border:1px solid var(--pfx-settings-panel-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08));color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-content{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:hover{background:color-mix(in srgb,var(--pfx-settings-panel-surface-container-high) 84%,var(--pfx-settings-panel-primary) 16%)}praxis-settings-panel .settings-panel .mat-expansion-panel.mat-expanded>.mat-expansion-panel-header{background:var(--pfx-settings-panel-surface-container-high)!important}praxis-settings-panel .settings-panel .mat-expansion-panel-header mat-icon,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-icon{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title>*,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description>*{color:inherit}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title small,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description small{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-indicator,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-indicator:after{color:var(--pfx-settings-panel-on-surface-variant);border-color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-action-row{border-top-color:var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-accordion,praxis-settings-panel .settings-panel .mat-accordion .mat-expansion-panel-spacing{background:transparent!important}praxis-settings-panel .settings-panel .mat-expansion-panel-content,praxis-settings-panel .settings-panel .mat-expansion-panel-content-wrapper,praxis-settings-panel .settings-panel .mat-expansion-panel-body{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-expansion-panel-body{padding:8px}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-expansion-panel-body>*{color:inherit}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header{border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab{min-width:0}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab:hover .mdc-tab__text-label,praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab:focus .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination-chevron{border-color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination:not(.mat-mdc-tab-header-pagination-disabled):hover{background:color-mix(in srgb,var(--pfx-settings-panel-surface-container-high) 84%,var(--pfx-settings-panel-primary) 16%)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab-indicator__content--underline{border-color:var(--pfx-settings-panel-primary)}praxis-settings-panel .settings-panel .mat-mdc-card{background:var(--pfx-settings-panel-surface-container-low);border:1px solid var(--pfx-settings-panel-outline-variant);color:var(--pfx-settings-panel-on-surface);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08))}praxis-settings-panel .settings-panel .mat-mdc-card-subtitle,praxis-settings-panel .settings-panel .mat-mdc-card-content{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-card-title{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-form-field{width:100%;--mdc-filled-text-field-container-color: var( --pfx-settings-panel-surface-container );--mdc-filled-text-field-hover-container-color: var( --pfx-settings-panel-surface-container-high );--mdc-filled-text-field-focus-container-color: var( --pfx-settings-panel-surface-container-high );--mdc-filled-text-field-active-indicator-color: var( --pfx-settings-panel-outline-variant );--mdc-filled-text-field-hover-active-indicator-color: var( --pfx-settings-panel-secondary );--mdc-filled-text-field-focus-active-indicator-color: var( --pfx-settings-panel-primary );--mdc-filled-text-field-label-text-color: var( --pfx-settings-panel-on-surface-variant );--mdc-filled-text-field-focus-label-text-color: var( --pfx-settings-panel-primary );--mdc-filled-text-field-input-text-color: var( --pfx-settings-panel-on-surface );--mdc-filled-text-field-caret-color: var(--pfx-settings-panel-primary);--mdc-outlined-text-field-outline-color: var( --pfx-settings-panel-outline-variant );--mdc-outlined-text-field-hover-outline-color: var( --pfx-settings-panel-secondary );--mdc-outlined-text-field-focus-outline-color: var( --pfx-settings-panel-primary );--mdc-outlined-text-field-label-text-color: var( --pfx-settings-panel-on-surface-variant );--mdc-outlined-text-field-focus-label-text-color: var( --pfx-settings-panel-primary );--mdc-outlined-text-field-input-text-color: var( --pfx-settings-panel-on-surface );--mdc-outlined-text-field-caret-color: var(--pfx-settings-panel-primary);--mat-form-field-focus-select-arrow-color: var( --pfx-settings-panel-primary );--mat-form-field-enabled-select-arrow-color: var( --pfx-settings-panel-on-surface-variant )}praxis-settings-panel .settings-panel .mdc-text-field--filled{background-color:var(--pfx-settings-panel-surface-container)!important;border-radius:var(--md-sys-shape-corner-small, 8px) var(--md-sys-shape-corner-small, 8px) 0 0}praxis-settings-panel .settings-panel .mat-mdc-text-field-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-flex,praxis-settings-panel .settings-panel .mat-mdc-form-field-infix,praxis-settings-panel .settings-panel .mat-mdc-form-field-focus-overlay{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-form-field-focus-overlay{opacity:0}praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-text-field__input,praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-floating-label,praxis-settings-panel .settings-panel .mat-mdc-select-value,praxis-settings-panel .settings-panel .mat-mdc-select-arrow,praxis-settings-panel .settings-panel .mat-mdc-form-field .mat-mdc-floating-label{color:var(--pfx-settings-panel-on-surface-variant)!important}praxis-settings-panel .settings-panel .mdc-text-field--filled.mdc-text-field--focused .mdc-floating-label,praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-text-field__input{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-mdc-form-field input,praxis-settings-panel .settings-panel .mat-mdc-form-field textarea,praxis-settings-panel .settings-panel .mat-mdc-form-field .mdc-text-field__input{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-mdc-form-field-subscript-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-hint-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-error-wrapper,praxis-settings-panel .settings-panel .mat-mdc-hint{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-button-toggle-group{border-color:var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-button-toggle{background:var(--pfx-settings-panel-surface-container-low);color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-button-toggle+.mat-button-toggle{border-left-color:var(--pfx-settings-panel-outline-variant)}praxis-settings-panel .settings-panel .mat-button-toggle-checked{background:var(--pfx-settings-panel-primary-container)!important;color:var(--pfx-settings-panel-on-primary-container)!important}praxis-settings-panel .settings-panel .mat-button-toggle .mat-icon,praxis-settings-panel .settings-panel .mat-button-toggle-checked .mat-icon{color:inherit}praxis-settings-panel .settings-panel .mat-mdc-slide-toggle .mdc-label{color:var(--pfx-settings-panel-on-surface)}.praxis-settings-panel-backdrop{background:var(--pfx-backdrop, var(--md-sys-color-scrim, rgba(8, 15, 26, .42)));backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%)}.praxis-settings-panel-pane{position:fixed!important;top:0!important;right:0!important;display:flex!important;align-items:stretch!important;height:100vh!important;max-height:100vh!important;z-index:var(--praxis-layer-settings-panel, 1220)!important}.praxis-settings-panel-pane .settings-panel{pointer-events:auto}\n"] }]
|
|
958
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [providePraxisSettingsPanelI18n()], template: "<div\n class=\"settings-panel\"\n data-testid=\"settings-panel-root\"\n [class.expanded]=\"expanded\"\n [class.is-resizable]=\"showResizeHandle\"\n [ngStyle]=\"panelInlineStyles\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"titleId\"\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n >\n @if (showResizeHandle) {\n <div\n class=\"settings-panel__resize-handle\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"resizeHandleLabel\"\n (pointerdown)=\"onResizeHandlePointerDown($event)\"\n (keydown)=\"onResizeHandleKeydown($event)\"\n ></div>\n }\n <header class=\"settings-panel-header\">\n <h2 class=\"settings-panel-title\" [id]=\"titleId\">\n @if (titleIcon) {\n <mat-icon class=\"title-icon\" [praxisIcon]=\"titleIcon\"></mat-icon>\n }\n <span>{{ title }}</span>\n </h2>\n <span class=\"spacer\"></span>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-toggle-expand\"\n [attr.aria-label]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n [attr.aria-expanded]=\"expanded\"\n [matTooltip]=\"expanded ? tx('Collapse panel') : tx('Expand panel')\"\n (click)=\"toggleExpand()\"\n >\n <mat-icon [praxisIcon]=\"expanded ? 'close_fullscreen' : 'open_in_full'\"></mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n data-testid=\"settings-panel-close-icon\"\n [attr.aria-label]=\"tx('Close')\"\n [matTooltip]=\"tx('Close')\"\n (click)=\"onCancel()\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </header>\n @if (showStatusMessage) {\n <div\n class=\"settings-panel-status\"\n [attr.data-status]=\"statusTone\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <mat-icon\n aria-hidden=\"true\"\n [praxisIcon]=\"\n statusTone === 'dirty' || statusTone === 'invalid'\n ? 'warning'\n : statusTone === 'saved'\n ? 'check_circle'\n : statusTone === 'busy'\n ? 'autorenew'\n : 'info'\n \"\n ></mat-icon>\n <span>{{ statusMessage }}</span>\n </div>\n }\n <div class=\"settings-panel-body\">\n <ng-template #contentHost></ng-template>\n </div>\n <footer class=\"settings-panel-footer\">\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-reset\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onReset()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'restart_alt'\"></mat-icon>\n <span>{{ tx('Reset') }}</span>\n </button>\n <span class=\"spacer\"></span>\n <button\n mat-button\n type=\"button\"\n data-testid=\"settings-panel-cancel\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onCancel()\"\n [disabled]=\"isBusy\"\n >\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'close'\"></mat-icon>\n <span>{{ tx('Cancel') }}</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"settings-panel-apply\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onApply()\"\n [disabled]=\"!canApply\"\n [matTooltip]=\"applySaveDisabledReason\"\n [matTooltipDisabled]=\"canApply || !diagnostics.showDisabledReason\"\n [attr.aria-busy]=\"isBusy\"\n >\n @if (showBusyIndicator) {\n <mat-progress-spinner\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n }\n @if (!showBusyIndicator) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'done'\"></mat-icon>\n <span>{{ tx('Apply') }}</span>\n }\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"settings-panel-save\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); onSave()\"\n [disabled]=\"!canSave\"\n [matTooltip]=\"applySaveDisabledReason\"\n [matTooltipDisabled]=\"canSave || !diagnostics.showDisabledReason\"\n [attr.aria-busy]=\"isBusy\"\n >\n @if (showBusyIndicator) {\n <mat-progress-spinner\n mode=\"indeterminate\"\n diameter=\"20\"\n ></mat-progress-spinner>\n }\n @if (!showBusyIndicator) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'save'\"></mat-icon>\n <span>{{ tx('Save & Close') }}</span>\n }\n </button>\n </footer>\n</div>\n", styles: ["@charset \"UTF-8\";praxis-settings-panel{display:block;height:100%;width:100%;min-width:0;flex:1 1 auto}praxis-settings-panel .settings-panel{position:relative;--pfx-settings-panel-surface-container: var( --md-sys-color-surface-container, #ffffff );--pfx-settings-panel-surface-container-high: var( --md-sys-color-surface-container-high, #f7f7f7 );--pfx-settings-panel-surface-container-low: var( --md-sys-color-surface-container-low, #f2f4f7 );--pfx-settings-panel-surface: var(--md-sys-color-surface, #ffffff);--pfx-settings-panel-on-surface: var(--md-sys-color-on-surface, #111827);--pfx-settings-panel-on-surface-variant: var( --md-sys-color-on-surface-variant, rgba(17, 24, 39, .72) );--pfx-settings-panel-outline: var( --md-sys-color-outline, rgba(15, 23, 42, .24) );--pfx-settings-panel-outline-variant: var( --md-sys-color-outline-variant, rgba(15, 23, 42, .12) );--pfx-settings-panel-primary: var(--md-sys-color-primary, #2563eb);--pfx-settings-panel-primary-container: var( --md-sys-color-primary-container, rgba(37, 99, 235, .14) );--pfx-settings-panel-on-primary-container: var( --md-sys-color-on-primary-container, #0f172a );--pfx-settings-panel-secondary: var( --md-sys-color-secondary, var(--pfx-settings-panel-primary) );--pfx-settings-panel-error: var(--md-sys-color-error, #b3261e);--pfx-settings-panel-error-container: var( --md-sys-color-error-container, rgba(179, 38, 30, .14) );display:grid;grid-template-rows:auto auto 1fr auto;grid-template-areas:\"header\" \"status\" \"body\" \"footer\";height:100%;background:var(--pfx-settings-panel-surface-container);color:var(--pfx-settings-panel-on-surface);border-left:1px solid var(--pfx-settings-panel-outline-variant);width:var(--pfx-settings-panel-width, 720px);transition:width .3s ease;box-shadow:var(--pfx-settings-panel-elevation, var(--md-sys-elevation-level2, 0 8px 24px rgba(0, 0, 0, .16)));overflow:hidden}praxis-settings-panel .settings-panel.expanded{width:min(var(--pfx-settings-panel-width-expanded, 95vw),var(--pfx-settings-panel-max-width, 2400px))}praxis-settings-panel .settings-panel__resize-handle{position:absolute;inset:0 auto 0 0;width:12px;cursor:col-resize;touch-action:none;z-index:3;outline:none}praxis-settings-panel .settings-panel__resize-handle:before{content:\"\";position:absolute;inset:0 auto 0 4px;width:2px;background:transparent;transition:background-color var(--pfx-side-panel-motion-duration, .16s) ease,opacity var(--pfx-side-panel-motion-duration, .16s) ease;opacity:0}praxis-settings-panel .settings-panel.is-resizable:hover .settings-panel__resize-handle:before,praxis-settings-panel .settings-panel__resize-handle:focus-visible:before{opacity:1;background:var(--pfx-settings-panel-outline)}praxis-settings-panel .settings-panel-header{grid-area:header;display:flex;align-items:center;gap:var(--pfx-settings-panel-header-gap, 8px);padding:0 var(--pfx-settings-panel-header-padding-x, 16px);height:var(--pfx-settings-panel-header-height, 64px);border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);box-shadow:var(--pfx-settings-panel-header-shadow, var(--md-sys-elevation-level1, 0 2px 6px rgba(0, 0, 0, .08)));flex-shrink:0}praxis-settings-panel .settings-panel-header .spacer{flex:1}praxis-settings-panel .settings-panel-status{grid-area:status;display:flex;align-items:center;gap:8px;min-height:36px;padding:6px 16px;border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);color:var(--pfx-settings-panel-on-surface);font-size:.85rem;font-weight:500}praxis-settings-panel .settings-panel-status mat-icon{width:18px;height:18px;font-size:18px}praxis-settings-panel .settings-panel-status[data-status=dirty],praxis-settings-panel .settings-panel-status[data-status=invalid]{color:var(--pfx-settings-panel-error);background:color-mix(in srgb,var(--pfx-settings-panel-error-container) 30%,var(--pfx-settings-panel-surface-container-high))}praxis-settings-panel .settings-panel-status[data-status=saved]{color:var(--pfx-settings-panel-primary);background:color-mix(in srgb,var(--pfx-settings-panel-primary-container) 28%,var(--pfx-settings-panel-surface-container-high))}praxis-settings-panel .settings-panel-body{grid-area:body;overflow-y:auto;min-height:0;padding:var(--pfx-settings-panel-body-padding, 8px 8px 24px 8px);background:var(--pfx-settings-panel-surface);display:flex;flex-direction:column}praxis-settings-panel .settings-panel-content{display:block}praxis-settings-panel .settings-panel-footer{grid-area:footer;border-top:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-high);box-shadow:var(--pfx-settings-panel-footer-shadow, var(--md-sys-elevation-level1, 0 -2px 6px rgba(0, 0, 0, .08)));display:flex;align-items:center;padding:var(--pfx-settings-panel-footer-padding, 12px 16px);column-gap:var(--pfx-settings-panel-footer-gap, 12px);flex-shrink:0}praxis-settings-panel .spacer{flex:1}praxis-settings-panel .settings-panel-title{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-title-gap, 8px);font-weight:700;letter-spacing:.2px;margin:0}praxis-settings-panel .settings-panel-title mat-icon{color:var(--pfx-settings-panel-primary)}praxis-settings-panel .settings-panel-title .title-icon{width:20px;height:20px;font-size:20px}praxis-settings-panel .settings-panel-footer button+button{margin-left:var(--pfx-settings-panel-footer-gap, 12px)}praxis-settings-panel .settings-panel-footer button{display:inline-flex;align-items:center}praxis-settings-panel .settings-panel-footer button .mat-icon{font-size:20px;width:20px;height:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center}praxis-settings-panel .settings-panel-footer .mat-button-wrapper{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px)}praxis-settings-panel .settings-panel-footer .mat-progress-spinner{margin-right:8px}praxis-settings-panel .settings-panel-footer .mat-flat-button[color=primary]{font-weight:600}praxis-settings-panel .settings-panel .mdc-button__label{display:inline-flex;align-items:center;gap:var(--pfx-settings-panel-button-gap, 8px);line-height:1}praxis-settings-panel .settings-panel .mdc-button__label>span{display:inline-flex;align-items:center;line-height:1}praxis-settings-panel .settings-panel .mdc-button__label .mat-icon{display:inline-flex;align-items:center;justify-content:center;line-height:1}praxis-settings-panel .settings-panel .mat-divider{background-color:var(--pfx-settings-panel-outline-variant)!important}praxis-settings-panel .settings-panel .mat-expansion-panel{background:var(--pfx-settings-panel-surface-container)!important;border:1px solid var(--pfx-settings-panel-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08));color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-content{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:hover{background:color-mix(in srgb,var(--pfx-settings-panel-surface-container-high) 84%,var(--pfx-settings-panel-primary) 16%)}praxis-settings-panel .settings-panel .mat-expansion-panel.mat-expanded>.mat-expansion-panel-header{background:var(--pfx-settings-panel-surface-container-high)!important}praxis-settings-panel .settings-panel .mat-expansion-panel-header mat-icon,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-icon{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title>*,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description>*{color:inherit}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-title small,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-panel-header-description small{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-indicator,praxis-settings-panel .settings-panel .mat-expansion-panel-header .mat-expansion-indicator:after{color:var(--pfx-settings-panel-on-surface-variant);border-color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-action-row{border-top-color:var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-accordion,praxis-settings-panel .settings-panel .mat-accordion .mat-expansion-panel-spacing{background:transparent!important}praxis-settings-panel .settings-panel .mat-expansion-panel-content,praxis-settings-panel .settings-panel .mat-expansion-panel-content-wrapper,praxis-settings-panel .settings-panel .mat-expansion-panel-body{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-expansion-panel-body{padding:8px}praxis-settings-panel .settings-panel .mat-expansion-panel .mat-expansion-panel-body>*{color:inherit}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header{border-bottom:1px solid var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab{min-width:0}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab:hover .mdc-tab__text-label,praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab:focus .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination-chevron{border-color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mat-mdc-tab-header-pagination:not(.mat-mdc-tab-header-pagination-disabled):hover{background:color-mix(in srgb,var(--pfx-settings-panel-surface-container-high) 84%,var(--pfx-settings-panel-primary) 16%)}praxis-settings-panel .settings-panel .mat-mdc-tab-group .mdc-tab-indicator__content--underline{border-color:var(--pfx-settings-panel-primary)}praxis-settings-panel .settings-panel .mat-mdc-card{background:var(--pfx-settings-panel-surface-container-low);border:1px solid var(--pfx-settings-panel-outline-variant);color:var(--pfx-settings-panel-on-surface);box-shadow:var(--md-sys-elevation-level1, 0 2px 8px rgba(0, 0, 0, .08))}praxis-settings-panel .settings-panel .mat-mdc-card-subtitle,praxis-settings-panel .settings-panel .mat-mdc-card-content{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-mdc-card-title{color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-form-field{width:100%;--mdc-filled-text-field-container-color: var( --pfx-settings-panel-surface-container );--mdc-filled-text-field-hover-container-color: var( --pfx-settings-panel-surface-container-high );--mdc-filled-text-field-focus-container-color: var( --pfx-settings-panel-surface-container-high );--mdc-filled-text-field-active-indicator-color: var( --pfx-settings-panel-outline-variant );--mdc-filled-text-field-hover-active-indicator-color: var( --pfx-settings-panel-secondary );--mdc-filled-text-field-focus-active-indicator-color: var( --pfx-settings-panel-primary );--mdc-filled-text-field-label-text-color: var( --pfx-settings-panel-on-surface-variant );--mdc-filled-text-field-focus-label-text-color: var( --pfx-settings-panel-primary );--mdc-filled-text-field-input-text-color: var( --pfx-settings-panel-on-surface );--mdc-filled-text-field-caret-color: var(--pfx-settings-panel-primary);--mdc-outlined-text-field-outline-color: var( --pfx-settings-panel-outline-variant );--mdc-outlined-text-field-hover-outline-color: var( --pfx-settings-panel-secondary );--mdc-outlined-text-field-focus-outline-color: var( --pfx-settings-panel-primary );--mdc-outlined-text-field-label-text-color: var( --pfx-settings-panel-on-surface-variant );--mdc-outlined-text-field-focus-label-text-color: var( --pfx-settings-panel-primary );--mdc-outlined-text-field-input-text-color: var( --pfx-settings-panel-on-surface );--mdc-outlined-text-field-caret-color: var(--pfx-settings-panel-primary);--mat-form-field-focus-select-arrow-color: var( --pfx-settings-panel-primary );--mat-form-field-enabled-select-arrow-color: var( --pfx-settings-panel-on-surface-variant )}praxis-settings-panel .settings-panel .mdc-text-field--filled{background-color:var(--pfx-settings-panel-surface-container)!important;border-radius:var(--md-sys-shape-corner-small, 8px) var(--md-sys-shape-corner-small, 8px) 0 0}praxis-settings-panel .settings-panel .mat-mdc-text-field-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-flex,praxis-settings-panel .settings-panel .mat-mdc-form-field-infix,praxis-settings-panel .settings-panel .mat-mdc-form-field-focus-overlay{background:var(--pfx-settings-panel-surface-container)!important;color:var(--pfx-settings-panel-on-surface)}praxis-settings-panel .settings-panel .mat-mdc-form-field-focus-overlay{opacity:0}praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-text-field__input,praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-floating-label,praxis-settings-panel .settings-panel .mat-mdc-select-value,praxis-settings-panel .settings-panel .mat-mdc-select-arrow,praxis-settings-panel .settings-panel .mat-mdc-form-field .mat-mdc-floating-label{color:var(--pfx-settings-panel-on-surface-variant)!important}praxis-settings-panel .settings-panel .mdc-text-field--filled.mdc-text-field--focused .mdc-floating-label,praxis-settings-panel .settings-panel .mdc-text-field--filled .mdc-text-field__input{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-mdc-form-field input,praxis-settings-panel .settings-panel .mat-mdc-form-field textarea,praxis-settings-panel .settings-panel .mat-mdc-form-field .mdc-text-field__input{color:var(--pfx-settings-panel-on-surface)!important}praxis-settings-panel .settings-panel .mat-mdc-form-field-subscript-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-hint-wrapper,praxis-settings-panel .settings-panel .mat-mdc-form-field-error-wrapper,praxis-settings-panel .settings-panel .mat-mdc-hint{color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-button-toggle-group{border-color:var(--pfx-settings-panel-outline-variant);background:var(--pfx-settings-panel-surface-container-low)}praxis-settings-panel .settings-panel .mat-button-toggle{background:var(--pfx-settings-panel-surface-container-low);color:var(--pfx-settings-panel-on-surface-variant)}praxis-settings-panel .settings-panel .mat-button-toggle+.mat-button-toggle{border-left-color:var(--pfx-settings-panel-outline-variant)}praxis-settings-panel .settings-panel .mat-button-toggle-checked{background:var(--pfx-settings-panel-primary-container)!important;color:var(--pfx-settings-panel-on-primary-container)!important}praxis-settings-panel .settings-panel .mat-button-toggle .mat-icon,praxis-settings-panel .settings-panel .mat-button-toggle-checked .mat-icon{color:inherit}praxis-settings-panel .settings-panel .mat-mdc-slide-toggle .mdc-label{color:var(--pfx-settings-panel-on-surface)}.praxis-settings-panel-backdrop{background:var(--pfx-backdrop, var(--md-sys-color-scrim, rgba(8, 15, 26, .42)));backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%);-webkit-backdrop-filter:blur(var(--pfx-backdrop-blur, 6px)) saturate(110%)}.praxis-settings-panel-pane{position:fixed!important;top:0!important;right:0!important;display:flex!important;align-items:stretch!important;height:100vh!important;max-height:100vh!important;z-index:var(--praxis-layer-settings-panel, 1220)!important}.praxis-settings-panel-pane .settings-panel{pointer-events:auto}\n"] }]
|
|
929
959
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.MatDialog }], propDecorators: { contentHost: [{
|
|
930
960
|
type: ViewChild,
|
|
931
961
|
args: ['contentHost', { read: ViewContainerRef, static: true }]
|
|
@@ -1291,10 +1321,10 @@ class BaseSidePanelComponent {
|
|
|
1291
1321
|
const parsed = Number.parseFloat(normalized.slice(0, -2));
|
|
1292
1322
|
return Number.isFinite(parsed) ? parsed : null;
|
|
1293
1323
|
}
|
|
1294
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1295
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1324
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BaseSidePanelComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$1.PraxisI18nService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1325
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: BaseSidePanelComponent, isStandalone: true, selector: "praxis-base-side-panel", host: { listeners: { "document:pointermove": "onDocumentPointerMove($event)", "document:pointerup": "onDocumentPointerEnd($event)", "document:pointercancel": "onDocumentPointerEnd($event)" } }, viewQueries: [{ propertyName: "contentHost", first: true, predicate: ["contentHost"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "footerHost", first: true, predicate: ["footerHost"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div\n class=\"pfx-base-side-panel\"\n [class.has-header]=\"hasHeader\"\n [class.has-footer]=\"hasFooter\"\n [class.width-narrow]=\"widthClass === 'width-narrow'\"\n [class.width-default]=\"widthClass === 'width-default'\"\n [class.width-wide]=\"widthClass === 'width-wide'\"\n [class.width-full]=\"widthClass === 'width-full'\"\n [class.use-host-width]=\"useHostWidth\"\n [class.is-resizable]=\"showResizeHandle\"\n [ngClass]=\"hostClasses\"\n [ngStyle]=\"mergedHostStyles\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"hasHeader ? titleId : null\"\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n>\n @if (showResizeHandle) {\n <div\n class=\"pfx-base-side-panel__resize-handle\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"resizeHandleLabel\"\n (pointerdown)=\"onResizeHandlePointerDown($event)\"\n (keydown)=\"onResizeHandleKeydown($event)\"\n ></div>\n }\n @if (hasHeader) {\n <header class=\"pfx-base-side-panel__header\">\n <div class=\"pfx-base-side-panel__title-block\">\n @if (titleIcon) {\n <mat-icon class=\"pfx-base-side-panel__title-icon\" [praxisIcon]=\"titleIcon\"></mat-icon>\n }\n <div class=\"pfx-base-side-panel__copy\">\n @if (title) {\n <h2 class=\"pfx-base-side-panel__title\" [id]=\"titleId\">{{ title }}</h2>\n }\n @if (subtitle) {\n <p class=\"pfx-base-side-panel__subtitle\">{{ subtitle }}</p>\n }\n </div>\n </div>\n <button\n mat-icon-button\n type=\"button\"\n class=\"pfx-base-side-panel__close\"\n [attr.aria-label]=\"closeLabel\"\n [matTooltip]=\"closeLabel\"\n (click)=\"onClose?.()\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </header>\n }\n\n <section class=\"pfx-base-side-panel__body\">\n <ng-template #contentHost></ng-template>\n </section>\n\n <footer class=\"pfx-base-side-panel__footer\" [hidden]=\"!hasFooter\">\n <ng-template #footerHost></ng-template>\n </footer>\n</div>\n", styles: [":host{display:block;height:100%;width:100%;min-width:0;flex:1 1 auto}.pfx-base-side-panel{position:relative;display:grid;grid-template-rows:auto 1fr auto;height:100%;min-width:0;overflow:hidden;background:var(--md-sys-color-surface-container, #fff);color:var(--md-sys-color-on-surface, #111);border-left:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));border-radius:var(--pfx-side-panel-border-radius, 0);box-shadow:var(--pfx-side-panel-elevation, var(--md-sys-elevation-level2, 0 8px 24px rgba(0, 0, 0, .16)));width:var(--pfx-side-panel-width, 720px)}.pfx-base-side-panel__resize-handle{position:absolute;inset:0 auto 0 0;width:12px;cursor:col-resize;touch-action:none;z-index:2;outline:none}.pfx-base-side-panel__resize-handle:before{content:\"\";position:absolute;inset:0 auto 0 4px;width:2px;background:transparent;transition:background-color var(--pfx-side-panel-motion-duration, .16s) ease,opacity var(--pfx-side-panel-motion-duration, .16s) ease;opacity:0}.pfx-base-side-panel.is-resizable:hover .pfx-base-side-panel__resize-handle:before,.pfx-base-side-panel__resize-handle:focus-visible:before{opacity:1;background:var(--md-sys-color-outline, rgba(0, 0, 0, .24))}.pfx-base-side-panel.use-host-width{width:100%;max-width:100%}.pfx-base-side-panel.width-narrow{width:var(--pfx-side-panel-width, 420px)}.pfx-base-side-panel.width-default{width:var(--pfx-side-panel-width, 720px)}.pfx-base-side-panel.width-wide{width:var(--pfx-side-panel-width, 960px)}.pfx-base-side-panel.width-full{width:min(100vw,var(--pfx-side-panel-max-width, 100vw))}.pfx-base-side-panel__header{display:flex;align-items:center;gap:var(--pfx-side-panel-header-gap, 8px);min-height:var(--pfx-side-panel-header-height, 64px);padding:0 var(--pfx-side-panel-header-padding-x, 16px);border-bottom:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));background:var(--md-sys-color-surface-container-high, #f7f7f7)}.pfx-base-side-panel__title-block{display:flex;align-items:flex-start;gap:10px;min-width:0;flex:1 1 auto}.pfx-base-side-panel__title-icon{color:var(--md-sys-color-primary, currentColor)}.pfx-base-side-panel__copy{min-width:0}.pfx-base-side-panel__title,.pfx-base-side-panel__subtitle{margin:0}.pfx-base-side-panel__title{font-size:1rem;font-weight:600}.pfx-base-side-panel__subtitle{margin-top:4px;color:var(--md-sys-color-on-surface-variant, rgba(0, 0, 0, .64));font-size:.875rem}.pfx-base-side-panel__body{min-height:0;overflow:auto;padding:var(--pfx-side-panel-body-padding, 16px);background:var(--md-sys-color-surface, #fff)}.pfx-base-side-panel__footer{border-top:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));background:var(--md-sys-color-surface-container-high, #f7f7f7);padding:var(--pfx-side-panel-footer-padding, 12px 16px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1296
1326
|
}
|
|
1297
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1327
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BaseSidePanelComponent, decorators: [{
|
|
1298
1328
|
type: Component,
|
|
1299
1329
|
args: [{ selector: 'praxis-base-side-panel', standalone: true, imports: [
|
|
1300
1330
|
CommonModule,
|
|
@@ -1554,10 +1584,10 @@ class BaseSidePanelService {
|
|
|
1554
1584
|
}
|
|
1555
1585
|
});
|
|
1556
1586
|
}
|
|
1557
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1558
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1587
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BaseSidePanelService, deps: [{ token: i1$2.Overlay }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1588
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BaseSidePanelService, providedIn: 'root' });
|
|
1559
1589
|
}
|
|
1560
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1590
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BaseSidePanelService, decorators: [{
|
|
1561
1591
|
type: Injectable,
|
|
1562
1592
|
args: [{ providedIn: 'root' }]
|
|
1563
1593
|
}], ctorParameters: () => [{ type: i1$2.Overlay }, { type: i0.Injector }] });
|
|
@@ -1636,6 +1666,7 @@ class SettingsPanelService {
|
|
|
1636
1666
|
maxWidth: resolvedConfig.maxWidth,
|
|
1637
1667
|
expanded: config.expanded || false,
|
|
1638
1668
|
});
|
|
1669
|
+
panelRef.instance.configureDiagnostics(config.diagnostics);
|
|
1639
1670
|
this.currentPanelInstance = panelRef.instance;
|
|
1640
1671
|
const inputs = config.content.inputs;
|
|
1641
1672
|
const injector = Injector.create({
|
|
@@ -1666,10 +1697,10 @@ class SettingsPanelService {
|
|
|
1666
1697
|
this.currentRef = undefined;
|
|
1667
1698
|
this.currentPanelInstance = undefined;
|
|
1668
1699
|
}
|
|
1669
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1670
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1700
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SettingsPanelService, deps: [{ token: BaseSidePanelService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1701
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SettingsPanelService, providedIn: 'root' });
|
|
1671
1702
|
}
|
|
1672
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1703
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SettingsPanelService, decorators: [{
|
|
1673
1704
|
type: Injectable,
|
|
1674
1705
|
args: [{ providedIn: 'root' }]
|
|
1675
1706
|
}], ctorParameters: () => [{ type: BaseSidePanelService }, { type: i0.Injector }] });
|
|
@@ -1746,12 +1777,13 @@ class SurfaceDrawerComponent {
|
|
|
1746
1777
|
return;
|
|
1747
1778
|
}
|
|
1748
1779
|
const supportedInputs = this.resolveSupportedInputs(componentRef);
|
|
1780
|
+
const canUseSetInput = typeof componentRef.setInput === 'function';
|
|
1749
1781
|
for (const [key, value] of Object.entries(inputs)) {
|
|
1750
|
-
if (supportedInputs && !supportedInputs.has(key)) {
|
|
1782
|
+
if (!canUseSetInput && supportedInputs && !supportedInputs.has(key)) {
|
|
1751
1783
|
continue;
|
|
1752
1784
|
}
|
|
1753
1785
|
try {
|
|
1754
|
-
if (
|
|
1786
|
+
if (canUseSetInput) {
|
|
1755
1787
|
componentRef.setInput(key, value);
|
|
1756
1788
|
}
|
|
1757
1789
|
else {
|
|
@@ -1770,10 +1802,10 @@ class SurfaceDrawerComponent {
|
|
|
1770
1802
|
}
|
|
1771
1803
|
return new Set(Object.keys(declaredInputs));
|
|
1772
1804
|
}
|
|
1773
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1774
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1805
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SurfaceDrawerComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$1.PraxisI18nService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1806
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: SurfaceDrawerComponent, isStandalone: true, selector: "praxis-surface-drawer", viewQueries: [{ propertyName: "contentHost", first: true, predicate: ["contentHost"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div\n class=\"pfx-surface-drawer\"\n [class.has-header]=\"hasHeader\"\n [class.width-narrow]=\"widthClass === 'width-narrow'\"\n [class.width-default]=\"widthClass === 'width-default'\"\n [class.width-wide]=\"widthClass === 'width-wide'\"\n [class.width-full]=\"widthClass === 'width-full'\"\n [class.use-host-width]=\"useHostWidth\"\n [ngClass]=\"hostClasses\"\n [ngStyle]=\"hostCssVars\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"hasHeader ? titleId : null\"\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n>\n @if (hasHeader) {\n <header class=\"pfx-surface-drawer__header\">\n <div class=\"pfx-surface-drawer__title-block\">\n @if (titleIcon) {\n <mat-icon class=\"pfx-surface-drawer__title-icon\" [praxisIcon]=\"titleIcon\"></mat-icon>\n }\n <div class=\"pfx-surface-drawer__copy\">\n @if (title) {\n <h2 class=\"pfx-surface-drawer__title\" [id]=\"titleId\">{{ title }}</h2>\n }\n @if (subtitle) {\n <p class=\"pfx-surface-drawer__subtitle\">{{ subtitle }}</p>\n }\n </div>\n </div>\n <button\n mat-icon-button\n type=\"button\"\n class=\"pfx-surface-drawer__close\"\n [attr.aria-label]=\"closeLabel\"\n [matTooltip]=\"closeLabel\"\n (click)=\"onClose?.()\"\n >\n <mat-icon [praxisIcon]=\"'close'\"></mat-icon>\n </button>\n </header>\n }\n\n <section class=\"pfx-surface-drawer__body\">\n <ng-template #contentHost></ng-template>\n </section>\n</div>\n", styles: [":host{display:block;height:100%;width:100%;min-width:0;flex:1 1 auto}.pfx-surface-drawer{display:grid;grid-template-rows:auto 1fr;height:100%;min-width:0;overflow:hidden;background:var(--md-sys-color-surface-container, #fff);color:var(--md-sys-color-on-surface, #111);border-left:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));border-radius:var(--pfx-side-panel-border-radius, 0);box-shadow:var(--pfx-side-panel-elevation, var(--md-sys-elevation-level2, 0 8px 24px rgba(0, 0, 0, .16)));width:var(--pfx-side-panel-width, 720px);transition:width var(--pfx-side-panel-motion-duration-enter, .22s) var(--pfx-side-panel-motion-easing-enter, cubic-bezier(.2, 0, 0, 1)),box-shadow var(--pfx-side-panel-motion-duration-enter, .22s) var(--pfx-side-panel-motion-easing-enter, cubic-bezier(.2, 0, 0, 1))}.pfx-surface-drawer.use-host-width{width:100%;max-width:100%}.pfx-surface-drawer.width-narrow{width:var(--pfx-side-panel-width, 420px)}.pfx-surface-drawer.width-default{width:var(--pfx-side-panel-width, 720px)}.pfx-surface-drawer.width-wide{width:var(--pfx-side-panel-width, 960px)}.pfx-surface-drawer.width-full{width:min(100vw,var(--pfx-side-panel-max-width, 100vw))}.pfx-surface-drawer__header{display:flex;align-items:center;gap:var(--pfx-side-panel-header-gap, 8px);min-height:var(--pfx-side-panel-header-height, 64px);padding:0 var(--pfx-side-panel-header-padding-x, 16px);border-bottom:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));background:var(--md-sys-color-surface-container-high, #f7f7f7)}.pfx-surface-drawer__title-block{display:flex;align-items:flex-start;gap:10px;min-width:0;flex:1 1 auto}.pfx-surface-drawer__title-icon{color:var(--md-sys-color-primary, currentColor)}.pfx-surface-drawer__copy{min-width:0}.pfx-surface-drawer__title,.pfx-surface-drawer__subtitle{margin:0}.pfx-surface-drawer__title{font-size:1rem;font-weight:600}.pfx-surface-drawer__subtitle{margin-top:4px;color:var(--md-sys-color-on-surface-variant, rgba(0, 0, 0, .64));font-size:.875rem}.pfx-surface-drawer__body{min-height:0;overflow:auto;padding:var(--pfx-side-panel-body-padding, 16px);background:var(--md-sys-color-surface, #fff)}@media(prefers-reduced-motion:reduce){.pfx-surface-drawer{transition:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1775
1807
|
}
|
|
1776
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1808
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SurfaceDrawerComponent, decorators: [{
|
|
1777
1809
|
type: Component,
|
|
1778
1810
|
args: [{ selector: 'praxis-surface-drawer', standalone: true, imports: [
|
|
1779
1811
|
CommonModule,
|
|
@@ -1915,10 +1947,10 @@ class GlobalConfigAdminService {
|
|
|
1915
1947
|
clearStoredConfig() {
|
|
1916
1948
|
return this.global.clearGlobalConfig();
|
|
1917
1949
|
}
|
|
1918
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1919
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1950
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GlobalConfigAdminService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1951
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GlobalConfigAdminService, providedIn: 'root' });
|
|
1920
1952
|
}
|
|
1921
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1953
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GlobalConfigAdminService, decorators: [{
|
|
1922
1954
|
type: Injectable,
|
|
1923
1955
|
args: [{ providedIn: 'root' }]
|
|
1924
1956
|
}] });
|
|
@@ -3852,8 +3884,8 @@ class GlobalConfigEditorComponent {
|
|
|
3852
3884
|
}
|
|
3853
3885
|
return true;
|
|
3854
3886
|
}
|
|
3855
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3856
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
3887
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GlobalConfigEditorComponent, deps: [{ token: GlobalConfigAdminService }, { token: i2$1.MatSnackBar }], target: i0.ɵɵFactoryTarget.Component });
|
|
3888
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: GlobalConfigEditorComponent, isStandalone: true, selector: "praxis-global-config-editor", viewQueries: [{ propertyName: "hostCrud", first: true, predicate: ["hostCrud"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "hostFields", first: true, predicate: ["hostFields"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "hostCache", first: true, predicate: ["hostCache"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "hostTable", first: true, predicate: ["hostTable"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "hostDialog", first: true, predicate: ["hostDialog"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "hostAiCredentials", first: true, predicate: ["hostAiCredentials"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "hostAiModel", first: true, predicate: ["hostAiModel"], descendants: true, read: ViewContainerRef }, { propertyName: "hostAiEmbedding", first: true, predicate: ["hostAiEmbedding"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: `
|
|
3857
3889
|
<mat-accordion multi>
|
|
3858
3890
|
<mat-expansion-panel>
|
|
3859
3891
|
<mat-expansion-panel-header>
|
|
@@ -3893,32 +3925,36 @@ class GlobalConfigEditorComponent {
|
|
|
3893
3925
|
</mat-panel-title>
|
|
3894
3926
|
<mat-panel-description>{{ tx('LLM integration') }}</mat-panel-description>
|
|
3895
3927
|
</mat-expansion-panel-header>
|
|
3896
|
-
|
|
3928
|
+
|
|
3897
3929
|
<div class="ai-config-container">
|
|
3898
3930
|
<div class="ai-config-source">
|
|
3899
3931
|
<div class="ai-config-source__meta">
|
|
3900
3932
|
<mat-icon>settings_suggest</mat-icon>
|
|
3901
3933
|
<span>{{ configSourceLabel }}</span>
|
|
3902
3934
|
</div>
|
|
3935
|
+
@if (hasStoredGlobalConfig) {
|
|
3903
3936
|
<button
|
|
3904
3937
|
mat-stroked-button
|
|
3905
3938
|
type="button"
|
|
3906
3939
|
class="ai-action-btn ai-action-btn--clear"
|
|
3907
|
-
*ngIf="hasStoredGlobalConfig"
|
|
3908
3940
|
[attr.aria-busy]="isClearingGlobalConfig ? 'true' : null"
|
|
3909
3941
|
[disabled]="isClearingGlobalConfig"
|
|
3910
3942
|
(click)="clearStoredConfig()"
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3943
|
+
[matTooltip]="tx('Clear saved config and return to server defaults')"
|
|
3944
|
+
>
|
|
3945
|
+
@if (isClearingGlobalConfig) {
|
|
3946
|
+
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
3947
|
+
<span class="ai-action-label">{{ tx('Clearing...') }}</span>
|
|
3948
|
+
} @else {
|
|
3949
|
+
<mat-icon>delete_sweep</mat-icon>
|
|
3950
|
+
<span class="ai-action-label">{{ tx('Clear saved config') }}</span>
|
|
3951
|
+
}
|
|
3952
|
+
<ng-template #clearContent>
|
|
3953
|
+
<mat-icon>delete_sweep</mat-icon>
|
|
3954
|
+
<span class="ai-action-label">{{ tx('Clear saved config') }}</span>
|
|
3955
|
+
</ng-template>
|
|
3956
|
+
</button>
|
|
3957
|
+
}
|
|
3922
3958
|
</div>
|
|
3923
3959
|
<!-- Group 1: Credentials -->
|
|
3924
3960
|
<div class="ai-group">
|
|
@@ -3926,18 +3962,23 @@ class GlobalConfigEditorComponent {
|
|
|
3926
3962
|
<div class="ai-group-title">
|
|
3927
3963
|
<mat-icon>vpn_key</mat-icon> {{ tx('Credentials') }}
|
|
3928
3964
|
</div>
|
|
3929
|
-
<button mat-stroked-button
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3965
|
+
<button mat-stroked-button
|
|
3966
|
+
type="button"
|
|
3967
|
+
class="ai-action-btn"
|
|
3968
|
+
[class.is-success]="aiTestResult?.success"
|
|
3969
|
+
[attr.aria-busy]="isTestingAi ? 'true' : null"
|
|
3970
|
+
(click)="testAiConnection()"
|
|
3971
|
+
[disabled]="isTestingAi || !hasApiKey"
|
|
3972
|
+
[matTooltip]="tx('Test connection with the provided key')">
|
|
3973
|
+
@if (isTestingAi) {
|
|
3938
3974
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
3939
3975
|
<span class="ai-action-label">{{ tx('Connecting...') }}</span>
|
|
3940
|
-
|
|
3976
|
+
} @else {
|
|
3977
|
+
<mat-icon>{{ aiTestResult?.success ? 'check' : 'bolt' }}</mat-icon>
|
|
3978
|
+
<span class="ai-action-label">
|
|
3979
|
+
{{ aiTestResult?.success ? tx('Connected') : tx('Test connection') }}
|
|
3980
|
+
</span>
|
|
3981
|
+
}
|
|
3941
3982
|
<ng-template #btnContent>
|
|
3942
3983
|
<mat-icon>{{ aiTestResult?.success ? 'check' : 'bolt' }}</mat-icon>
|
|
3943
3984
|
<span class="ai-action-label">
|
|
@@ -3946,59 +3987,76 @@ class GlobalConfigEditorComponent {
|
|
|
3946
3987
|
</ng-template>
|
|
3947
3988
|
</button>
|
|
3948
3989
|
</div>
|
|
3949
|
-
|
|
3950
|
-
<
|
|
3951
|
-
<
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
<
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3990
|
+
@if (selectedProvider) {
|
|
3991
|
+
<div class="ai-provider-summary">
|
|
3992
|
+
<span class="ai-provider-icon" aria-hidden="true">
|
|
3993
|
+
@switch (selectedProvider.iconKey) {
|
|
3994
|
+
@case ('gemini') {
|
|
3995
|
+
<svg viewBox="0 0 24 24" class="provider-svg" fill="none" stroke="currentColor" stroke-width="1.6">
|
|
3996
|
+
<path d="M12 3l2.6 5.4L20 11l-5.4 2.6L12 19l-2.6-5.4L4 11l5.4-2.6L12 3z" />
|
|
3997
|
+
</svg>
|
|
3998
|
+
}
|
|
3999
|
+
@case ('openai') {
|
|
4000
|
+
<svg viewBox="0 0 24 24" class="provider-svg" fill="none" stroke="currentColor" stroke-width="1.6">
|
|
4001
|
+
<polygon points="12,2 20,7 20,17 12,22 4,17 4,7" />
|
|
4002
|
+
</svg>
|
|
4003
|
+
}
|
|
4004
|
+
@case ('xai') {
|
|
4005
|
+
<svg viewBox="0 0 24 24" class="provider-svg" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round">
|
|
4006
|
+
<line x1="5" y1="5" x2="19" y2="19" />
|
|
4007
|
+
<line x1="19" y1="5" x2="5" y2="19" />
|
|
4008
|
+
</svg>
|
|
4009
|
+
}
|
|
4010
|
+
@case ('mock') {
|
|
4011
|
+
<svg viewBox="0 0 24 24" class="provider-svg" fill="none" stroke="currentColor" stroke-width="1.6">
|
|
4012
|
+
<rect x="4.5" y="4.5" width="15" height="15" rx="2" ry="2" stroke-dasharray="2 2" />
|
|
4013
|
+
</svg>
|
|
4014
|
+
}
|
|
4015
|
+
@default {
|
|
4016
|
+
<svg viewBox="0 0 24 24" class="provider-svg" fill="none" stroke="currentColor" stroke-width="1.6">
|
|
4017
|
+
<circle cx="12" cy="12" r="7.5" />
|
|
4018
|
+
</svg>
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
</span>
|
|
4022
|
+
<div class="ai-provider-meta">
|
|
4023
|
+
<div class="ai-provider-name">{{ selectedProvider.label }}</div>
|
|
4024
|
+
<div class="ai-provider-desc">{{ selectedProvider.description }}</div>
|
|
4025
|
+
</div>
|
|
4026
|
+
@if (selectedProvider?.requiresApiKey !== false) {
|
|
4027
|
+
<div
|
|
4028
|
+
class="ai-provider-key"
|
|
4029
|
+
[class.is-present]="hasCurrentApiKey"
|
|
4030
|
+
[class.is-saved]="!hasCurrentApiKey && (apiKeyLast4 || hasStoredApiKey)"
|
|
4031
|
+
[class.is-missing]="!hasCurrentApiKey && !apiKeyLast4 && !hasStoredApiKey"
|
|
4032
|
+
>
|
|
4033
|
+
<mat-icon>vpn_key</mat-icon>
|
|
4034
|
+
<span>{{ apiKeyStatusLabel }}</span>
|
|
4035
|
+
</div>
|
|
4036
|
+
}
|
|
4037
|
+
@if (selectedProvider?.requiresApiKey === false) {
|
|
4038
|
+
<div class="ai-provider-key is-unlocked">
|
|
4039
|
+
<mat-icon>check_circle</mat-icon>
|
|
4040
|
+
<span>{{ tx('No key required') }}</span>
|
|
4041
|
+
</div>
|
|
4042
|
+
}
|
|
3987
4043
|
</div>
|
|
3988
|
-
|
|
4044
|
+
}
|
|
3989
4045
|
<div class="ai-credentials-row">
|
|
3990
4046
|
<div class="ai-form-inline">
|
|
3991
4047
|
<ng-template #hostAiCredentials></ng-template>
|
|
3992
4048
|
</div>
|
|
3993
4049
|
</div>
|
|
3994
|
-
|
|
4050
|
+
|
|
3995
4051
|
<!-- Feedback / Error Message -->
|
|
3996
|
-
|
|
3997
|
-
<
|
|
3998
|
-
|
|
3999
|
-
|
|
4052
|
+
@if (aiTestResult && !aiTestResult.success) {
|
|
4053
|
+
<div class="ai-feedback">
|
|
4054
|
+
<mat-icon color="warn">error</mat-icon>
|
|
4055
|
+
<span class="error-text">{{ aiTestResult.message }}</span>
|
|
4056
|
+
</div>
|
|
4057
|
+
}
|
|
4000
4058
|
</div>
|
|
4001
|
-
|
|
4059
|
+
|
|
4002
4060
|
<!-- Group 2: Model & Behavior (Only visible if Key is present) -->
|
|
4003
4061
|
<div class="ai-group" [class.disabled-group]="!hasApiKey">
|
|
4004
4062
|
<div class="ai-group-header">
|
|
@@ -4006,31 +4064,40 @@ class GlobalConfigEditorComponent {
|
|
|
4006
4064
|
<mat-icon>smart_toy</mat-icon> {{ tx('Model & Behavior') }}
|
|
4007
4065
|
</div>
|
|
4008
4066
|
<div class="ai-header-actions">
|
|
4009
|
-
|
|
4010
|
-
|
|
4067
|
+
@if (hasApiKey) {
|
|
4068
|
+
<span class="ai-subtext">{{ tx('Choose the model after validating the key.') }}</span>
|
|
4069
|
+
}
|
|
4070
|
+
@if (!hasApiKey) {
|
|
4071
|
+
<mat-chip-option disabled>{{ tx('API key validated required') }}</mat-chip-option>
|
|
4072
|
+
}
|
|
4011
4073
|
<button mat-icon-button (click)="refreshModels(true)" [disabled]="isTestingAi || !hasApiKey" [matTooltip]="tx('Refresh model list')" [attr.aria-label]="tx('Refresh model list')">
|
|
4012
4074
|
<mat-icon [class.spin]="isRefetchingModels">sync</mat-icon>
|
|
4013
4075
|
</button>
|
|
4014
4076
|
</div>
|
|
4015
4077
|
</div>
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
<div class="ai-model-
|
|
4019
|
-
|
|
4078
|
+
|
|
4079
|
+
@if (hasApiKey) {
|
|
4080
|
+
<div class="ai-model-content">
|
|
4081
|
+
<div class="ai-model-controls">
|
|
4082
|
+
<ng-template #hostAiModel></ng-template>
|
|
4083
|
+
</div>
|
|
4084
|
+
<!-- Model Details (Placeholder for future metadata) -->
|
|
4085
|
+
@if (selectedModelDetails) {
|
|
4086
|
+
<div class="ai-model-details">
|
|
4087
|
+
<mat-icon inline>info</mat-icon> {{ selectedModelDetails }}
|
|
4088
|
+
</div>
|
|
4089
|
+
}
|
|
4020
4090
|
</div>
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4091
|
+
}
|
|
4092
|
+
|
|
4093
|
+
@if (!hasApiKey) {
|
|
4094
|
+
<div class="ai-placeholder">
|
|
4095
|
+
<mat-icon>lock</mat-icon>
|
|
4096
|
+
<span>{{ tx('Configure and test your API key to unlock model selection.') }}</span>
|
|
4025
4097
|
</div>
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
<div class="ai-placeholder" *ngIf="!hasApiKey">
|
|
4029
|
-
<mat-icon>lock</mat-icon>
|
|
4030
|
-
<span>{{ tx('Configure and test your API key to unlock model selection.') }}</span>
|
|
4031
|
-
</div>
|
|
4098
|
+
}
|
|
4032
4099
|
</div>
|
|
4033
|
-
|
|
4100
|
+
|
|
4034
4101
|
<!-- Group 3: Embeddings (RAG) -->
|
|
4035
4102
|
<div class="ai-group">
|
|
4036
4103
|
<div class="ai-group-header">
|
|
@@ -4045,31 +4112,37 @@ class GlobalConfigEditorComponent {
|
|
|
4045
4112
|
(click)="useLlmForEmbeddings()"
|
|
4046
4113
|
[disabled]="!canUseLlmForEmbeddings"
|
|
4047
4114
|
[matTooltip]="tx('Use the LLM provider and key for embeddings')"
|
|
4048
|
-
|
|
4115
|
+
>
|
|
4049
4116
|
<mat-icon>merge_type</mat-icon>
|
|
4050
4117
|
<span class="ai-action-label">{{ tx('Use the LLM provider and key for embeddings') }}</span>
|
|
4051
4118
|
</button>
|
|
4052
|
-
|
|
4119
|
+
@if (!canUseLlmForEmbeddings) {
|
|
4120
|
+
<mat-chip-option disabled>{{ tx('Provider has no embeddings') }}</mat-chip-option>
|
|
4121
|
+
}
|
|
4053
4122
|
</div>
|
|
4054
4123
|
</div>
|
|
4055
4124
|
<div class="ai-subtext">
|
|
4056
4125
|
{{ tx('Configure the embeddings provider for vector search (templates and schemas).') }}
|
|
4057
4126
|
</div>
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4127
|
+
@if (embeddingUseSameAsLlm) {
|
|
4128
|
+
<div class="ai-subtext">
|
|
4129
|
+
{{ tx('Synchronized with the LLM. The fields below follow the primary credential.') }}
|
|
4130
|
+
</div>
|
|
4131
|
+
}
|
|
4061
4132
|
<div class="ai-embedding-row">
|
|
4062
4133
|
<ng-template #hostAiEmbedding></ng-template>
|
|
4063
4134
|
</div>
|
|
4064
|
-
|
|
4065
|
-
<
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4135
|
+
@if (embeddingDimensionMismatch) {
|
|
4136
|
+
<div class="ai-feedback ai-feedback--warn">
|
|
4137
|
+
<mat-icon>warning</mat-icon>
|
|
4138
|
+
<span class="error-text">
|
|
4139
|
+
{{ tx('Embedding dimension mismatch with database (768). Adjust to 768 or redo the migration.') }}
|
|
4140
|
+
</span>
|
|
4141
|
+
</div>
|
|
4142
|
+
}
|
|
4070
4143
|
</div>
|
|
4071
4144
|
</div>
|
|
4072
|
-
|
|
4145
|
+
|
|
4073
4146
|
</mat-expansion-panel>
|
|
4074
4147
|
<mat-expansion-panel>
|
|
4075
4148
|
<mat-expansion-panel-header>
|
|
@@ -4093,27 +4166,33 @@ class GlobalConfigEditorComponent {
|
|
|
4093
4166
|
<!-- Icon UX helpers for Dialog variants -->
|
|
4094
4167
|
<div class="dlg-icon-helpers">
|
|
4095
4168
|
<div class="dlg-icon-helpers__head">{{ tx('Icons by profile (shortcuts)') }}</div>
|
|
4096
|
-
|
|
4097
|
-
<div class="dlg-icon-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
<mat-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4169
|
+
@for (k of dialogVariantKeys; track k) {
|
|
4170
|
+
<div class="dlg-icon-helpers__row">
|
|
4171
|
+
<div class="dlg-icon-helpers__label">{{ k }}</div>
|
|
4172
|
+
<mat-icon aria-hidden="true" [praxisIcon]="getVariantIcon(k) || 'mi:help_outline'" class="dlg-icon-helpers__preview"></mat-icon>
|
|
4173
|
+
<button mat-stroked-button color="primary" type="button" (click)="pickVariantIcon(k)" [matTooltip]="tx('Pick icon for {{key}}', { key: k })">
|
|
4174
|
+
<mat-icon>search</mat-icon>
|
|
4175
|
+
{{ tx('Pick icon') }}
|
|
4176
|
+
</button>
|
|
4177
|
+
@if (getVariantIcon(k)) {
|
|
4178
|
+
<button mat-icon-button type="button" (click)="clearVariantIcon(k)" [matTooltip]="tx('Clear icon for {{key}}', { key: k })" [attr.aria-label]="tx('Clear icon')">
|
|
4179
|
+
<mat-icon>backspace</mat-icon>
|
|
4180
|
+
</button>
|
|
4181
|
+
}
|
|
4182
|
+
@if (getVariantIcon(k)) {
|
|
4183
|
+
<span class="dlg-icon-helpers__value">{{ getVariantIcon(k) }}</span>
|
|
4184
|
+
}
|
|
4185
|
+
</div>
|
|
4186
|
+
}
|
|
4108
4187
|
<div class="dlg-icon-helpers__hint">{{ tx('The text field above remains editable. These buttons only help with selection/clear preview.') }}</div>
|
|
4109
4188
|
</div>
|
|
4110
4189
|
</mat-expansion-panel>
|
|
4111
4190
|
</mat-accordion>
|
|
4112
|
-
`, isInline: true, styles: [".dlg-icon-helpers{margin:12px 16px 4px;padding:12px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:var(--md-sys-shape-corner-small, 8px)}.dlg-icon-helpers__head{font-weight:600;margin-bottom:8px;opacity:.8}.dlg-icon-helpers__row{display:flex;align-items:center;gap:12px;padding:6px 0}.dlg-icon-helpers__label{text-transform:capitalize;width:96px;opacity:.8}.dlg-icon-helpers__preview{width:24px;height:24px}.dlg-icon-helpers__value{font-family:monospace;font-size:12px;opacity:.8}.dlg-icon-helpers__hint{margin-top:8px;font-size:12px;opacity:.7}.panel-icon{margin-right:12px;color:var(--md-sys-color-primary)}.ai-config-container{padding:16px;display:flex;flex-direction:column;gap:24px}.ai-config-source{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;border-radius:var(--md-sys-shape-corner-medium, 10px);border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);font-size:12px;color:var(--md-sys-color-on-surface-variant);flex-wrap:wrap}.ai-config-source__meta{display:inline-flex;align-items:center;gap:8px}.ai-action-btn--clear{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);--mdc-outlined-button-container-color: var(--md-sys-color-error-container);--mdc-outlined-button-label-text-color: var(--md-sys-color-on-error-container);--mdc-outlined-button-outline-color: var(--md-sys-color-error);--mat-mdc-button-persistent-ripple-color: var(--md-sys-color-on-error-container);--mat-mdc-button-ripple-color: var(--md-sys-color-on-error-container)}.ai-action-btn--clear:hover{background:var(--md-sys-color-error-container)}.ai-group-title{display:flex;align-items:center;gap:8px;font-weight:500;font-size:14px;color:var(--md-sys-color-primary);margin-bottom:12px;border-bottom:1px solid var(--md-sys-color-outline-variant);padding-bottom:4px}.ai-group-title mat-icon{font-size:20px;width:20px;height:20px}.ai-group ::ng-deep .form-actions,.ai-group ::ng-deep button[type=submit]{display:none!important}.ai-credentials-row{display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap}.ai-group-header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.ai-provider-summary{display:flex;align-items:center;gap:12px;padding:8px 12px;border-radius:var(--md-sys-shape-corner-medium, 10px);background:var(--md-sys-color-surface-variant);border:1px solid var(--md-sys-color-outline-variant);margin:8px 0 4px;flex-wrap:wrap}.ai-provider-icon{width:32px;height:32px;border-radius:var(--md-sys-shape-corner-small, 8px);border:1px solid var(--md-sys-color-outline-variant);display:flex;align-items:center;justify-content:center;background:var(--md-sys-color-surface);color:var(--md-sys-color-primary);flex:0 0 auto}.provider-svg{width:18px;height:18px}.ai-provider-meta{display:flex;flex-direction:column;gap:2px;min-width:200px;flex:1 1 auto}.ai-provider-name{font-weight:600;font-size:13px}.ai-provider-desc{font-size:12px;opacity:.75}.ai-provider-key{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:600;letter-spacing:.2px;box-shadow:var(--md-sys-elevation-level1, 0 1px 2px rgba(0,0,0,.2))}.ai-provider-key mat-icon{width:16px;height:16px;font-size:16px}.ai-provider-key.is-present{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);border-color:var(--md-sys-color-primary)}.ai-provider-key.is-saved{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);border-color:var(--md-sys-color-secondary)}.ai-provider-key.is-missing{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);border-style:dashed;opacity:.9}.ai-provider-key.is-unlocked{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container);border-color:var(--md-sys-color-tertiary)}.ai-action-btn{display:inline-flex;align-items:center;gap:8px;height:40px;padding:0 14px;min-width:168px;border-radius:var(--md-sys-shape-corner-medium, 12px);white-space:nowrap;background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);border-color:var(--md-sys-color-outline-variant);box-shadow:var(--md-sys-elevation-level1, 0 1px 2px rgba(0,0,0,.2));transition:background-color .15s ease,box-shadow .15s ease,transform .06s ease;--mdc-outlined-button-container-color: var(--md-sys-color-secondary-container);--mdc-outlined-button-label-text-color: var(--md-sys-color-on-secondary-container);--mdc-outlined-button-outline-color: var(--md-sys-color-outline-variant);--mat-mdc-button-persistent-ripple-color: var(--md-sys-color-on-secondary-container);--mat-mdc-button-ripple-color: var(--md-sys-color-on-secondary-container)}.ai-action-btn .mat-button-wrapper,.ai-action-btn .mdc-button__label{display:inline-flex;align-items:center;gap:8px;line-height:1;height:100%}.ai-action-btn .mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.ai-action-btn .ai-action-label{display:inline-flex;align-items:center;line-height:1}.ai-action-btn .mat-progress-spinner,.ai-action-btn .btn-spinner{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.ai-action-btn:hover{background:var(--md-sys-color-secondary-container);box-shadow:var(--md-sys-elevation-level2, 0 2px 6px rgba(0,0,0,.25))}.ai-action-btn:active{transform:translateY(1px)}.ai-action-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.ai-action-btn.is-success{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container);border-color:var(--md-sys-color-tertiary);--mdc-outlined-button-container-color: var(--md-sys-color-tertiary-container);--mdc-outlined-button-label-text-color: var(--md-sys-color-on-tertiary-container);--mdc-outlined-button-outline-color: var(--md-sys-color-tertiary);--mat-mdc-button-persistent-ripple-color: var(--md-sys-color-on-tertiary-container);--mat-mdc-button-ripple-color: var(--md-sys-color-on-tertiary-container)}.ai-action-btn.is-success:hover{background:var(--md-sys-color-tertiary-container)}.ai-action-btn:disabled{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);border-color:var(--md-sys-color-outline-variant);box-shadow:none;opacity:.7}.ai-form-inline{flex:1;min-width:300px}.ai-credentials-row button{margin-top:4px;height:40px}.btn-spinner{margin-right:8px}.ai-feedback{margin-top:8px;display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-radius:var(--md-sys-shape-corner-extra-small, 4px);font-size:13px}.ai-feedback--warn{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container)}.disabled-group{opacity:.6;pointer-events:none}.ai-model-content{display:flex;flex-direction:column;gap:8px}.ai-model-controls{display:flex;align-items:flex-start;gap:8px}.ai-model-controls ::ng-deep praxis-dynamic-form{flex:1}.ai-model-details{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-left:4px}.ai-subtext{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.ai-header-actions{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}.ai-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px;background:var(--md-sys-color-surface-container-low);border-radius:var(--md-sys-shape-corner-small, 8px);color:var(--md-sys-color-outline);gap:8px;text-align:center;font-size:13px}.spin{animation:spin 1s linear infinite}@keyframes spin{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i4$1.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i4$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i4$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i4$1.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i9.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
|
|
4191
|
+
`, isInline: true, styles: [".dlg-icon-helpers{margin:12px 16px 4px;padding:12px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:var(--md-sys-shape-corner-small, 8px)}.dlg-icon-helpers__head{font-weight:600;margin-bottom:8px;opacity:.8}.dlg-icon-helpers__row{display:flex;align-items:center;gap:12px;padding:6px 0}.dlg-icon-helpers__label{text-transform:capitalize;width:96px;opacity:.8}.dlg-icon-helpers__preview{width:24px;height:24px}.dlg-icon-helpers__value{font-family:monospace;font-size:12px;opacity:.8}.dlg-icon-helpers__hint{margin-top:8px;font-size:12px;opacity:.7}.panel-icon{margin-right:12px;color:var(--md-sys-color-primary)}.ai-config-container{padding:16px;display:flex;flex-direction:column;gap:24px}.ai-config-source{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;border-radius:var(--md-sys-shape-corner-medium, 10px);border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);font-size:12px;color:var(--md-sys-color-on-surface-variant);flex-wrap:wrap}.ai-config-source__meta{display:inline-flex;align-items:center;gap:8px}.ai-action-btn--clear{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);--mdc-outlined-button-container-color: var(--md-sys-color-error-container);--mdc-outlined-button-label-text-color: var(--md-sys-color-on-error-container);--mdc-outlined-button-outline-color: var(--md-sys-color-error);--mat-mdc-button-persistent-ripple-color: var(--md-sys-color-on-error-container);--mat-mdc-button-ripple-color: var(--md-sys-color-on-error-container)}.ai-action-btn--clear:hover{background:var(--md-sys-color-error-container)}.ai-group-title{display:flex;align-items:center;gap:8px;font-weight:500;font-size:14px;color:var(--md-sys-color-primary);margin-bottom:12px;border-bottom:1px solid var(--md-sys-color-outline-variant);padding-bottom:4px}.ai-group-title mat-icon{font-size:20px;width:20px;height:20px}.ai-group ::ng-deep .form-actions,.ai-group ::ng-deep button[type=submit]{display:none!important}.ai-credentials-row{display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap}.ai-group-header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.ai-provider-summary{display:flex;align-items:center;gap:12px;padding:8px 12px;border-radius:var(--md-sys-shape-corner-medium, 10px);background:var(--md-sys-color-surface-variant);border:1px solid var(--md-sys-color-outline-variant);margin:8px 0 4px;flex-wrap:wrap}.ai-provider-icon{width:32px;height:32px;border-radius:var(--md-sys-shape-corner-small, 8px);border:1px solid var(--md-sys-color-outline-variant);display:flex;align-items:center;justify-content:center;background:var(--md-sys-color-surface);color:var(--md-sys-color-primary);flex:0 0 auto}.provider-svg{width:18px;height:18px}.ai-provider-meta{display:flex;flex-direction:column;gap:2px;min-width:200px;flex:1 1 auto}.ai-provider-name{font-weight:600;font-size:13px}.ai-provider-desc{font-size:12px;opacity:.75}.ai-provider-key{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:600;letter-spacing:.2px;box-shadow:var(--md-sys-elevation-level1, 0 1px 2px rgba(0,0,0,.2))}.ai-provider-key mat-icon{width:16px;height:16px;font-size:16px}.ai-provider-key.is-present{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);border-color:var(--md-sys-color-primary)}.ai-provider-key.is-saved{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);border-color:var(--md-sys-color-secondary)}.ai-provider-key.is-missing{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);border-style:dashed;opacity:.9}.ai-provider-key.is-unlocked{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container);border-color:var(--md-sys-color-tertiary)}.ai-action-btn{display:inline-flex;align-items:center;gap:8px;height:40px;padding:0 14px;min-width:168px;border-radius:var(--md-sys-shape-corner-medium, 12px);white-space:nowrap;background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);border-color:var(--md-sys-color-outline-variant);box-shadow:var(--md-sys-elevation-level1, 0 1px 2px rgba(0,0,0,.2));transition:background-color .15s ease,box-shadow .15s ease,transform .06s ease;--mdc-outlined-button-container-color: var(--md-sys-color-secondary-container);--mdc-outlined-button-label-text-color: var(--md-sys-color-on-secondary-container);--mdc-outlined-button-outline-color: var(--md-sys-color-outline-variant);--mat-mdc-button-persistent-ripple-color: var(--md-sys-color-on-secondary-container);--mat-mdc-button-ripple-color: var(--md-sys-color-on-secondary-container)}.ai-action-btn .mat-button-wrapper,.ai-action-btn .mdc-button__label{display:inline-flex;align-items:center;gap:8px;line-height:1;height:100%}.ai-action-btn .mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.ai-action-btn .ai-action-label{display:inline-flex;align-items:center;line-height:1}.ai-action-btn .mat-progress-spinner,.ai-action-btn .btn-spinner{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.ai-action-btn:hover{background:var(--md-sys-color-secondary-container);box-shadow:var(--md-sys-elevation-level2, 0 2px 6px rgba(0,0,0,.25))}.ai-action-btn:active{transform:translateY(1px)}.ai-action-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.ai-action-btn.is-success{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container);border-color:var(--md-sys-color-tertiary);--mdc-outlined-button-container-color: var(--md-sys-color-tertiary-container);--mdc-outlined-button-label-text-color: var(--md-sys-color-on-tertiary-container);--mdc-outlined-button-outline-color: var(--md-sys-color-tertiary);--mat-mdc-button-persistent-ripple-color: var(--md-sys-color-on-tertiary-container);--mat-mdc-button-ripple-color: var(--md-sys-color-on-tertiary-container)}.ai-action-btn.is-success:hover{background:var(--md-sys-color-tertiary-container)}.ai-action-btn:disabled{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);border-color:var(--md-sys-color-outline-variant);box-shadow:none;opacity:.7}.ai-form-inline{flex:1;min-width:300px}.ai-credentials-row button{margin-top:4px;height:40px}.btn-spinner{margin-right:8px}.ai-feedback{margin-top:8px;display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-radius:var(--md-sys-shape-corner-extra-small, 4px);font-size:13px}.ai-feedback--warn{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container)}.disabled-group{opacity:.6;pointer-events:none}.ai-model-content{display:flex;flex-direction:column;gap:8px}.ai-model-controls{display:flex;align-items:flex-start;gap:8px}.ai-model-controls ::ng-deep praxis-dynamic-form{flex:1}.ai-model-details{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-left:4px}.ai-subtext{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.ai-header-actions{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}.ai-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px;background:var(--md-sys-color-surface-container-low);border-radius:var(--md-sys-shape-corner-small, 8px);color:var(--md-sys-color-outline);gap:8px;text-align:center;font-size:13px}.spin{animation:spin 1s linear infinite}@keyframes spin{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i3$1.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i3$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i3$1.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i8.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
|
|
4113
4192
|
}
|
|
4114
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4193
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GlobalConfigEditorComponent, decorators: [{
|
|
4115
4194
|
type: Component,
|
|
4116
|
-
args: [{ selector: 'praxis-global-config-editor', standalone: true, imports: [
|
|
4195
|
+
args: [{ selector: 'praxis-global-config-editor', standalone: true, imports: [MatSnackBarModule, MatExpansionModule, MatIconModule, MatButtonModule, MatTooltipModule, MatProgressSpinnerModule, MatChipsModule, PraxisIconDirective], template: `
|
|
4117
4196
|
<mat-accordion multi>
|
|
4118
4197
|
<mat-expansion-panel>
|
|
4119
4198
|
<mat-expansion-panel-header>
|
|
@@ -4153,32 +4232,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
4153
4232
|
</mat-panel-title>
|
|
4154
4233
|
<mat-panel-description>{{ tx('LLM integration') }}</mat-panel-description>
|
|
4155
4234
|
</mat-expansion-panel-header>
|
|
4156
|
-
|
|
4235
|
+
|
|
4157
4236
|
<div class="ai-config-container">
|
|
4158
4237
|
<div class="ai-config-source">
|
|
4159
4238
|
<div class="ai-config-source__meta">
|
|
4160
4239
|
<mat-icon>settings_suggest</mat-icon>
|
|
4161
4240
|
<span>{{ configSourceLabel }}</span>
|
|
4162
4241
|
</div>
|
|
4242
|
+
@if (hasStoredGlobalConfig) {
|
|
4163
4243
|
<button
|
|
4164
4244
|
mat-stroked-button
|
|
4165
4245
|
type="button"
|
|
4166
4246
|
class="ai-action-btn ai-action-btn--clear"
|
|
4167
|
-
*ngIf="hasStoredGlobalConfig"
|
|
4168
4247
|
[attr.aria-busy]="isClearingGlobalConfig ? 'true' : null"
|
|
4169
4248
|
[disabled]="isClearingGlobalConfig"
|
|
4170
4249
|
(click)="clearStoredConfig()"
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4250
|
+
[matTooltip]="tx('Clear saved config and return to server defaults')"
|
|
4251
|
+
>
|
|
4252
|
+
@if (isClearingGlobalConfig) {
|
|
4253
|
+
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
4254
|
+
<span class="ai-action-label">{{ tx('Clearing...') }}</span>
|
|
4255
|
+
} @else {
|
|
4256
|
+
<mat-icon>delete_sweep</mat-icon>
|
|
4257
|
+
<span class="ai-action-label">{{ tx('Clear saved config') }}</span>
|
|
4258
|
+
}
|
|
4259
|
+
<ng-template #clearContent>
|
|
4260
|
+
<mat-icon>delete_sweep</mat-icon>
|
|
4261
|
+
<span class="ai-action-label">{{ tx('Clear saved config') }}</span>
|
|
4262
|
+
</ng-template>
|
|
4263
|
+
</button>
|
|
4264
|
+
}
|
|
4182
4265
|
</div>
|
|
4183
4266
|
<!-- Group 1: Credentials -->
|
|
4184
4267
|
<div class="ai-group">
|
|
@@ -4186,18 +4269,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
4186
4269
|
<div class="ai-group-title">
|
|
4187
4270
|
<mat-icon>vpn_key</mat-icon> {{ tx('Credentials') }}
|
|
4188
4271
|
</div>
|
|
4189
|
-
<button mat-stroked-button
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4272
|
+
<button mat-stroked-button
|
|
4273
|
+
type="button"
|
|
4274
|
+
class="ai-action-btn"
|
|
4275
|
+
[class.is-success]="aiTestResult?.success"
|
|
4276
|
+
[attr.aria-busy]="isTestingAi ? 'true' : null"
|
|
4277
|
+
(click)="testAiConnection()"
|
|
4278
|
+
[disabled]="isTestingAi || !hasApiKey"
|
|
4279
|
+
[matTooltip]="tx('Test connection with the provided key')">
|
|
4280
|
+
@if (isTestingAi) {
|
|
4198
4281
|
<mat-spinner diameter="16" class="btn-spinner"></mat-spinner>
|
|
4199
4282
|
<span class="ai-action-label">{{ tx('Connecting...') }}</span>
|
|
4200
|
-
|
|
4283
|
+
} @else {
|
|
4284
|
+
<mat-icon>{{ aiTestResult?.success ? 'check' : 'bolt' }}</mat-icon>
|
|
4285
|
+
<span class="ai-action-label">
|
|
4286
|
+
{{ aiTestResult?.success ? tx('Connected') : tx('Test connection') }}
|
|
4287
|
+
</span>
|
|
4288
|
+
}
|
|
4201
4289
|
<ng-template #btnContent>
|
|
4202
4290
|
<mat-icon>{{ aiTestResult?.success ? 'check' : 'bolt' }}</mat-icon>
|
|
4203
4291
|
<span class="ai-action-label">
|
|
@@ -4206,59 +4294,76 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
4206
4294
|
</ng-template>
|
|
4207
4295
|
</button>
|
|
4208
4296
|
</div>
|
|
4209
|
-
|
|
4210
|
-
<
|
|
4211
|
-
<
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
<
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4297
|
+
@if (selectedProvider) {
|
|
4298
|
+
<div class="ai-provider-summary">
|
|
4299
|
+
<span class="ai-provider-icon" aria-hidden="true">
|
|
4300
|
+
@switch (selectedProvider.iconKey) {
|
|
4301
|
+
@case ('gemini') {
|
|
4302
|
+
<svg viewBox="0 0 24 24" class="provider-svg" fill="none" stroke="currentColor" stroke-width="1.6">
|
|
4303
|
+
<path d="M12 3l2.6 5.4L20 11l-5.4 2.6L12 19l-2.6-5.4L4 11l5.4-2.6L12 3z" />
|
|
4304
|
+
</svg>
|
|
4305
|
+
}
|
|
4306
|
+
@case ('openai') {
|
|
4307
|
+
<svg viewBox="0 0 24 24" class="provider-svg" fill="none" stroke="currentColor" stroke-width="1.6">
|
|
4308
|
+
<polygon points="12,2 20,7 20,17 12,22 4,17 4,7" />
|
|
4309
|
+
</svg>
|
|
4310
|
+
}
|
|
4311
|
+
@case ('xai') {
|
|
4312
|
+
<svg viewBox="0 0 24 24" class="provider-svg" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round">
|
|
4313
|
+
<line x1="5" y1="5" x2="19" y2="19" />
|
|
4314
|
+
<line x1="19" y1="5" x2="5" y2="19" />
|
|
4315
|
+
</svg>
|
|
4316
|
+
}
|
|
4317
|
+
@case ('mock') {
|
|
4318
|
+
<svg viewBox="0 0 24 24" class="provider-svg" fill="none" stroke="currentColor" stroke-width="1.6">
|
|
4319
|
+
<rect x="4.5" y="4.5" width="15" height="15" rx="2" ry="2" stroke-dasharray="2 2" />
|
|
4320
|
+
</svg>
|
|
4321
|
+
}
|
|
4322
|
+
@default {
|
|
4323
|
+
<svg viewBox="0 0 24 24" class="provider-svg" fill="none" stroke="currentColor" stroke-width="1.6">
|
|
4324
|
+
<circle cx="12" cy="12" r="7.5" />
|
|
4325
|
+
</svg>
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
4328
|
+
</span>
|
|
4329
|
+
<div class="ai-provider-meta">
|
|
4330
|
+
<div class="ai-provider-name">{{ selectedProvider.label }}</div>
|
|
4331
|
+
<div class="ai-provider-desc">{{ selectedProvider.description }}</div>
|
|
4332
|
+
</div>
|
|
4333
|
+
@if (selectedProvider?.requiresApiKey !== false) {
|
|
4334
|
+
<div
|
|
4335
|
+
class="ai-provider-key"
|
|
4336
|
+
[class.is-present]="hasCurrentApiKey"
|
|
4337
|
+
[class.is-saved]="!hasCurrentApiKey && (apiKeyLast4 || hasStoredApiKey)"
|
|
4338
|
+
[class.is-missing]="!hasCurrentApiKey && !apiKeyLast4 && !hasStoredApiKey"
|
|
4339
|
+
>
|
|
4340
|
+
<mat-icon>vpn_key</mat-icon>
|
|
4341
|
+
<span>{{ apiKeyStatusLabel }}</span>
|
|
4342
|
+
</div>
|
|
4343
|
+
}
|
|
4344
|
+
@if (selectedProvider?.requiresApiKey === false) {
|
|
4345
|
+
<div class="ai-provider-key is-unlocked">
|
|
4346
|
+
<mat-icon>check_circle</mat-icon>
|
|
4347
|
+
<span>{{ tx('No key required') }}</span>
|
|
4348
|
+
</div>
|
|
4349
|
+
}
|
|
4247
4350
|
</div>
|
|
4248
|
-
|
|
4351
|
+
}
|
|
4249
4352
|
<div class="ai-credentials-row">
|
|
4250
4353
|
<div class="ai-form-inline">
|
|
4251
4354
|
<ng-template #hostAiCredentials></ng-template>
|
|
4252
4355
|
</div>
|
|
4253
4356
|
</div>
|
|
4254
|
-
|
|
4357
|
+
|
|
4255
4358
|
<!-- Feedback / Error Message -->
|
|
4256
|
-
|
|
4257
|
-
<
|
|
4258
|
-
|
|
4259
|
-
|
|
4359
|
+
@if (aiTestResult && !aiTestResult.success) {
|
|
4360
|
+
<div class="ai-feedback">
|
|
4361
|
+
<mat-icon color="warn">error</mat-icon>
|
|
4362
|
+
<span class="error-text">{{ aiTestResult.message }}</span>
|
|
4363
|
+
</div>
|
|
4364
|
+
}
|
|
4260
4365
|
</div>
|
|
4261
|
-
|
|
4366
|
+
|
|
4262
4367
|
<!-- Group 2: Model & Behavior (Only visible if Key is present) -->
|
|
4263
4368
|
<div class="ai-group" [class.disabled-group]="!hasApiKey">
|
|
4264
4369
|
<div class="ai-group-header">
|
|
@@ -4266,31 +4371,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
4266
4371
|
<mat-icon>smart_toy</mat-icon> {{ tx('Model & Behavior') }}
|
|
4267
4372
|
</div>
|
|
4268
4373
|
<div class="ai-header-actions">
|
|
4269
|
-
|
|
4270
|
-
|
|
4374
|
+
@if (hasApiKey) {
|
|
4375
|
+
<span class="ai-subtext">{{ tx('Choose the model after validating the key.') }}</span>
|
|
4376
|
+
}
|
|
4377
|
+
@if (!hasApiKey) {
|
|
4378
|
+
<mat-chip-option disabled>{{ tx('API key validated required') }}</mat-chip-option>
|
|
4379
|
+
}
|
|
4271
4380
|
<button mat-icon-button (click)="refreshModels(true)" [disabled]="isTestingAi || !hasApiKey" [matTooltip]="tx('Refresh model list')" [attr.aria-label]="tx('Refresh model list')">
|
|
4272
4381
|
<mat-icon [class.spin]="isRefetchingModels">sync</mat-icon>
|
|
4273
4382
|
</button>
|
|
4274
4383
|
</div>
|
|
4275
4384
|
</div>
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
<div class="ai-model-
|
|
4279
|
-
|
|
4385
|
+
|
|
4386
|
+
@if (hasApiKey) {
|
|
4387
|
+
<div class="ai-model-content">
|
|
4388
|
+
<div class="ai-model-controls">
|
|
4389
|
+
<ng-template #hostAiModel></ng-template>
|
|
4390
|
+
</div>
|
|
4391
|
+
<!-- Model Details (Placeholder for future metadata) -->
|
|
4392
|
+
@if (selectedModelDetails) {
|
|
4393
|
+
<div class="ai-model-details">
|
|
4394
|
+
<mat-icon inline>info</mat-icon> {{ selectedModelDetails }}
|
|
4395
|
+
</div>
|
|
4396
|
+
}
|
|
4280
4397
|
</div>
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4398
|
+
}
|
|
4399
|
+
|
|
4400
|
+
@if (!hasApiKey) {
|
|
4401
|
+
<div class="ai-placeholder">
|
|
4402
|
+
<mat-icon>lock</mat-icon>
|
|
4403
|
+
<span>{{ tx('Configure and test your API key to unlock model selection.') }}</span>
|
|
4285
4404
|
</div>
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
<div class="ai-placeholder" *ngIf="!hasApiKey">
|
|
4289
|
-
<mat-icon>lock</mat-icon>
|
|
4290
|
-
<span>{{ tx('Configure and test your API key to unlock model selection.') }}</span>
|
|
4291
|
-
</div>
|
|
4405
|
+
}
|
|
4292
4406
|
</div>
|
|
4293
|
-
|
|
4407
|
+
|
|
4294
4408
|
<!-- Group 3: Embeddings (RAG) -->
|
|
4295
4409
|
<div class="ai-group">
|
|
4296
4410
|
<div class="ai-group-header">
|
|
@@ -4305,31 +4419,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
4305
4419
|
(click)="useLlmForEmbeddings()"
|
|
4306
4420
|
[disabled]="!canUseLlmForEmbeddings"
|
|
4307
4421
|
[matTooltip]="tx('Use the LLM provider and key for embeddings')"
|
|
4308
|
-
|
|
4422
|
+
>
|
|
4309
4423
|
<mat-icon>merge_type</mat-icon>
|
|
4310
4424
|
<span class="ai-action-label">{{ tx('Use the LLM provider and key for embeddings') }}</span>
|
|
4311
4425
|
</button>
|
|
4312
|
-
|
|
4426
|
+
@if (!canUseLlmForEmbeddings) {
|
|
4427
|
+
<mat-chip-option disabled>{{ tx('Provider has no embeddings') }}</mat-chip-option>
|
|
4428
|
+
}
|
|
4313
4429
|
</div>
|
|
4314
4430
|
</div>
|
|
4315
4431
|
<div class="ai-subtext">
|
|
4316
4432
|
{{ tx('Configure the embeddings provider for vector search (templates and schemas).') }}
|
|
4317
4433
|
</div>
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4434
|
+
@if (embeddingUseSameAsLlm) {
|
|
4435
|
+
<div class="ai-subtext">
|
|
4436
|
+
{{ tx('Synchronized with the LLM. The fields below follow the primary credential.') }}
|
|
4437
|
+
</div>
|
|
4438
|
+
}
|
|
4321
4439
|
<div class="ai-embedding-row">
|
|
4322
4440
|
<ng-template #hostAiEmbedding></ng-template>
|
|
4323
4441
|
</div>
|
|
4324
|
-
|
|
4325
|
-
<
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4442
|
+
@if (embeddingDimensionMismatch) {
|
|
4443
|
+
<div class="ai-feedback ai-feedback--warn">
|
|
4444
|
+
<mat-icon>warning</mat-icon>
|
|
4445
|
+
<span class="error-text">
|
|
4446
|
+
{{ tx('Embedding dimension mismatch with database (768). Adjust to 768 or redo the migration.') }}
|
|
4447
|
+
</span>
|
|
4448
|
+
</div>
|
|
4449
|
+
}
|
|
4330
4450
|
</div>
|
|
4331
4451
|
</div>
|
|
4332
|
-
|
|
4452
|
+
|
|
4333
4453
|
</mat-expansion-panel>
|
|
4334
4454
|
<mat-expansion-panel>
|
|
4335
4455
|
<mat-expansion-panel-header>
|
|
@@ -4353,23 +4473,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
4353
4473
|
<!-- Icon UX helpers for Dialog variants -->
|
|
4354
4474
|
<div class="dlg-icon-helpers">
|
|
4355
4475
|
<div class="dlg-icon-helpers__head">{{ tx('Icons by profile (shortcuts)') }}</div>
|
|
4356
|
-
|
|
4357
|
-
<div class="dlg-icon-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
<mat-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4476
|
+
@for (k of dialogVariantKeys; track k) {
|
|
4477
|
+
<div class="dlg-icon-helpers__row">
|
|
4478
|
+
<div class="dlg-icon-helpers__label">{{ k }}</div>
|
|
4479
|
+
<mat-icon aria-hidden="true" [praxisIcon]="getVariantIcon(k) || 'mi:help_outline'" class="dlg-icon-helpers__preview"></mat-icon>
|
|
4480
|
+
<button mat-stroked-button color="primary" type="button" (click)="pickVariantIcon(k)" [matTooltip]="tx('Pick icon for {{key}}', { key: k })">
|
|
4481
|
+
<mat-icon>search</mat-icon>
|
|
4482
|
+
{{ tx('Pick icon') }}
|
|
4483
|
+
</button>
|
|
4484
|
+
@if (getVariantIcon(k)) {
|
|
4485
|
+
<button mat-icon-button type="button" (click)="clearVariantIcon(k)" [matTooltip]="tx('Clear icon for {{key}}', { key: k })" [attr.aria-label]="tx('Clear icon')">
|
|
4486
|
+
<mat-icon>backspace</mat-icon>
|
|
4487
|
+
</button>
|
|
4488
|
+
}
|
|
4489
|
+
@if (getVariantIcon(k)) {
|
|
4490
|
+
<span class="dlg-icon-helpers__value">{{ getVariantIcon(k) }}</span>
|
|
4491
|
+
}
|
|
4492
|
+
</div>
|
|
4493
|
+
}
|
|
4368
4494
|
<div class="dlg-icon-helpers__hint">{{ tx('The text field above remains editable. These buttons only help with selection/clear preview.') }}</div>
|
|
4369
4495
|
</div>
|
|
4370
4496
|
</mat-expansion-panel>
|
|
4371
4497
|
</mat-accordion>
|
|
4372
|
-
|
|
4498
|
+
`, styles: [".dlg-icon-helpers{margin:12px 16px 4px;padding:12px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:var(--md-sys-shape-corner-small, 8px)}.dlg-icon-helpers__head{font-weight:600;margin-bottom:8px;opacity:.8}.dlg-icon-helpers__row{display:flex;align-items:center;gap:12px;padding:6px 0}.dlg-icon-helpers__label{text-transform:capitalize;width:96px;opacity:.8}.dlg-icon-helpers__preview{width:24px;height:24px}.dlg-icon-helpers__value{font-family:monospace;font-size:12px;opacity:.8}.dlg-icon-helpers__hint{margin-top:8px;font-size:12px;opacity:.7}.panel-icon{margin-right:12px;color:var(--md-sys-color-primary)}.ai-config-container{padding:16px;display:flex;flex-direction:column;gap:24px}.ai-config-source{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;border-radius:var(--md-sys-shape-corner-medium, 10px);border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);font-size:12px;color:var(--md-sys-color-on-surface-variant);flex-wrap:wrap}.ai-config-source__meta{display:inline-flex;align-items:center;gap:8px}.ai-action-btn--clear{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);--mdc-outlined-button-container-color: var(--md-sys-color-error-container);--mdc-outlined-button-label-text-color: var(--md-sys-color-on-error-container);--mdc-outlined-button-outline-color: var(--md-sys-color-error);--mat-mdc-button-persistent-ripple-color: var(--md-sys-color-on-error-container);--mat-mdc-button-ripple-color: var(--md-sys-color-on-error-container)}.ai-action-btn--clear:hover{background:var(--md-sys-color-error-container)}.ai-group-title{display:flex;align-items:center;gap:8px;font-weight:500;font-size:14px;color:var(--md-sys-color-primary);margin-bottom:12px;border-bottom:1px solid var(--md-sys-color-outline-variant);padding-bottom:4px}.ai-group-title mat-icon{font-size:20px;width:20px;height:20px}.ai-group ::ng-deep .form-actions,.ai-group ::ng-deep button[type=submit]{display:none!important}.ai-credentials-row{display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap}.ai-group-header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.ai-provider-summary{display:flex;align-items:center;gap:12px;padding:8px 12px;border-radius:var(--md-sys-shape-corner-medium, 10px);background:var(--md-sys-color-surface-variant);border:1px solid var(--md-sys-color-outline-variant);margin:8px 0 4px;flex-wrap:wrap}.ai-provider-icon{width:32px;height:32px;border-radius:var(--md-sys-shape-corner-small, 8px);border:1px solid var(--md-sys-color-outline-variant);display:flex;align-items:center;justify-content:center;background:var(--md-sys-color-surface);color:var(--md-sys-color-primary);flex:0 0 auto}.provider-svg{width:18px;height:18px}.ai-provider-meta{display:flex;flex-direction:column;gap:2px;min-width:200px;flex:1 1 auto}.ai-provider-name{font-weight:600;font-size:13px}.ai-provider-desc{font-size:12px;opacity:.75}.ai-provider-key{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:600;letter-spacing:.2px;box-shadow:var(--md-sys-elevation-level1, 0 1px 2px rgba(0,0,0,.2))}.ai-provider-key mat-icon{width:16px;height:16px;font-size:16px}.ai-provider-key.is-present{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container);border-color:var(--md-sys-color-primary)}.ai-provider-key.is-saved{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);border-color:var(--md-sys-color-secondary)}.ai-provider-key.is-missing{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);border-style:dashed;opacity:.9}.ai-provider-key.is-unlocked{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container);border-color:var(--md-sys-color-tertiary)}.ai-action-btn{display:inline-flex;align-items:center;gap:8px;height:40px;padding:0 14px;min-width:168px;border-radius:var(--md-sys-shape-corner-medium, 12px);white-space:nowrap;background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);border-color:var(--md-sys-color-outline-variant);box-shadow:var(--md-sys-elevation-level1, 0 1px 2px rgba(0,0,0,.2));transition:background-color .15s ease,box-shadow .15s ease,transform .06s ease;--mdc-outlined-button-container-color: var(--md-sys-color-secondary-container);--mdc-outlined-button-label-text-color: var(--md-sys-color-on-secondary-container);--mdc-outlined-button-outline-color: var(--md-sys-color-outline-variant);--mat-mdc-button-persistent-ripple-color: var(--md-sys-color-on-secondary-container);--mat-mdc-button-ripple-color: var(--md-sys-color-on-secondary-container)}.ai-action-btn .mat-button-wrapper,.ai-action-btn .mdc-button__label{display:inline-flex;align-items:center;gap:8px;line-height:1;height:100%}.ai-action-btn .mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.ai-action-btn .ai-action-label{display:inline-flex;align-items:center;line-height:1}.ai-action-btn .mat-progress-spinner,.ai-action-btn .btn-spinner{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.ai-action-btn:hover{background:var(--md-sys-color-secondary-container);box-shadow:var(--md-sys-elevation-level2, 0 2px 6px rgba(0,0,0,.25))}.ai-action-btn:active{transform:translateY(1px)}.ai-action-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.ai-action-btn.is-success{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container);border-color:var(--md-sys-color-tertiary);--mdc-outlined-button-container-color: var(--md-sys-color-tertiary-container);--mdc-outlined-button-label-text-color: var(--md-sys-color-on-tertiary-container);--mdc-outlined-button-outline-color: var(--md-sys-color-tertiary);--mat-mdc-button-persistent-ripple-color: var(--md-sys-color-on-tertiary-container);--mat-mdc-button-ripple-color: var(--md-sys-color-on-tertiary-container)}.ai-action-btn.is-success:hover{background:var(--md-sys-color-tertiary-container)}.ai-action-btn:disabled{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);border-color:var(--md-sys-color-outline-variant);box-shadow:none;opacity:.7}.ai-form-inline{flex:1;min-width:300px}.ai-credentials-row button{margin-top:4px;height:40px}.btn-spinner{margin-right:8px}.ai-feedback{margin-top:8px;display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-radius:var(--md-sys-shape-corner-extra-small, 4px);font-size:13px}.ai-feedback--warn{background:var(--md-sys-color-tertiary-container);color:var(--md-sys-color-on-tertiary-container)}.disabled-group{opacity:.6;pointer-events:none}.ai-model-content{display:flex;flex-direction:column;gap:8px}.ai-model-controls{display:flex;align-items:flex-start;gap:8px}.ai-model-controls ::ng-deep praxis-dynamic-form{flex:1}.ai-model-details{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-left:4px}.ai-subtext{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.ai-header-actions{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}.ai-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px;background:var(--md-sys-color-surface-container-low);border-radius:var(--md-sys-shape-corner-small, 8px);color:var(--md-sys-color-outline);gap:8px;text-align:center;font-size:13px}.spin{animation:spin 1s linear infinite}@keyframes spin{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}\n"] }]
|
|
4373
4499
|
}], ctorParameters: () => [{ type: GlobalConfigAdminService }, { type: i2$1.MatSnackBar }], propDecorators: { hostCrud: [{
|
|
4374
4500
|
type: ViewChild,
|
|
4375
4501
|
args: ['hostCrud', { read: ViewContainerRef, static: true }]
|
|
@@ -4426,6 +4552,15 @@ const SETTINGS_PANEL_AI_CAPABILITIES = {
|
|
|
4426
4552
|
{ path: 'title', category: 'identity', valueKind: 'string', description: 'Titulo do painel.' },
|
|
4427
4553
|
{ path: 'titleIcon', category: 'identity', valueKind: 'string', description: 'Icone do titulo (Material icon name).' },
|
|
4428
4554
|
{ path: 'expanded', category: 'behavior', valueKind: 'boolean', description: 'Estado inicial expandido.' },
|
|
4555
|
+
{ path: 'resizable', category: 'behavior', valueKind: 'boolean', description: 'Habilita resize horizontal do painel autoral.' },
|
|
4556
|
+
{ path: 'persistSizeKey', category: 'behavior', valueKind: 'string', description: 'Chave estavel para persistencia de largura.' },
|
|
4557
|
+
{ path: 'minWidth', category: 'layout', valueKind: 'string', description: 'Largura minima do painel.' },
|
|
4558
|
+
{ path: 'maxWidth', category: 'layout', valueKind: 'string', description: 'Largura maxima do painel.' },
|
|
4559
|
+
{ path: 'diagnostics', category: 'behavior', valueKind: 'object', description: 'Configuracao opcional de visibilidade dos diagnosticos do shell.' },
|
|
4560
|
+
{ path: 'diagnostics.showStatusMessage', category: 'behavior', valueKind: 'boolean', description: 'Controla a faixa de status do painel.' },
|
|
4561
|
+
{ path: 'diagnostics.showDisabledReason', category: 'behavior', valueKind: 'boolean', description: 'Controla tooltips com motivo de acoes desabilitadas.' },
|
|
4562
|
+
{ path: 'diagnostics.showBusyState', category: 'behavior', valueKind: 'boolean', description: 'Controla indicadores visuais de busy no shell.' },
|
|
4563
|
+
{ path: 'diagnostics.exposeValidationState', category: 'behavior', valueKind: 'boolean', description: 'Controla a exposicao visual de invalidade do provider.' },
|
|
4429
4564
|
{ path: 'content', category: 'content', valueKind: 'object', description: 'Conteudo do painel.' },
|
|
4430
4565
|
{
|
|
4431
4566
|
path: 'content.component',
|
|
@@ -4444,8 +4579,314 @@ const SETTINGS_PANEL_AI_CAPABILITIES = {
|
|
|
4444
4579
|
],
|
|
4445
4580
|
};
|
|
4446
4581
|
|
|
4582
|
+
const panelSizeSchema = {
|
|
4583
|
+
type: 'object',
|
|
4584
|
+
minProperties: 1,
|
|
4585
|
+
properties: {
|
|
4586
|
+
width: { oneOf: [{ type: 'string' }, { type: 'number' }] },
|
|
4587
|
+
minWidth: { type: 'string' },
|
|
4588
|
+
maxWidth: { type: 'string' },
|
|
4589
|
+
resizable: { type: 'boolean' },
|
|
4590
|
+
persistSizeKey: { type: 'string' },
|
|
4591
|
+
expanded: { type: 'boolean' },
|
|
4592
|
+
},
|
|
4593
|
+
};
|
|
4594
|
+
const panelShellSchema = {
|
|
4595
|
+
type: 'object',
|
|
4596
|
+
minProperties: 1,
|
|
4597
|
+
properties: {
|
|
4598
|
+
id: { type: 'string' },
|
|
4599
|
+
title: { type: 'string' },
|
|
4600
|
+
titleIcon: { type: 'string' },
|
|
4601
|
+
},
|
|
4602
|
+
};
|
|
4603
|
+
const editorHostSchema = {
|
|
4604
|
+
type: 'object',
|
|
4605
|
+
required: ['componentId'],
|
|
4606
|
+
properties: {
|
|
4607
|
+
componentId: { type: 'string' },
|
|
4608
|
+
inputs: { type: 'object' },
|
|
4609
|
+
configManifestComponentId: { type: 'string' },
|
|
4610
|
+
editorContract: {
|
|
4611
|
+
enum: ['SettingsValueProvider'],
|
|
4612
|
+
},
|
|
4613
|
+
},
|
|
4614
|
+
};
|
|
4615
|
+
const behaviorSchema = {
|
|
4616
|
+
type: 'object',
|
|
4617
|
+
minProperties: 1,
|
|
4618
|
+
properties: {
|
|
4619
|
+
requireDirty: { type: 'boolean' },
|
|
4620
|
+
requireValid: { type: 'boolean' },
|
|
4621
|
+
blockWhileBusy: { type: 'boolean' },
|
|
4622
|
+
useProviderHook: { type: 'boolean' },
|
|
4623
|
+
closeAfterSave: { type: 'boolean' },
|
|
4624
|
+
},
|
|
4625
|
+
};
|
|
4626
|
+
const PRAXIS_SETTINGS_PANEL_AUTHORING_MANIFEST = {
|
|
4627
|
+
schemaVersion: '1.0.0',
|
|
4628
|
+
componentId: 'praxis-settings-panel',
|
|
4629
|
+
ownerPackage: '@praxisui/settings-panel',
|
|
4630
|
+
configSchemaId: 'SettingsPanelConfig',
|
|
4631
|
+
manifestVersion: '1.0.0',
|
|
4632
|
+
runtimeInputs: [
|
|
4633
|
+
{ name: 'config', type: 'SettingsPanelConfig', description: 'Canonical settings panel shell config passed to SettingsPanelService.open.' },
|
|
4634
|
+
{ name: 'config.diagnostics', type: 'SettingsPanelDiagnosticsConfig', description: 'Optional shell diagnostics visibility config for status, disabled reason, busy state and validation state.' },
|
|
4635
|
+
{ name: 'content.component', type: 'Type<SettingsValueProvider>', description: 'Standalone editor component hosted inside the authoring shell.' },
|
|
4636
|
+
{ name: 'content.inputs', type: 'Record<string, unknown>', description: 'Initial editor inputs owned by the consumer component manifest.' },
|
|
4637
|
+
{ name: 'ref', type: 'SettingsPanelRef', description: 'Panel ref that emits applied, saved, reset, closed and sizeChanged events.' },
|
|
4638
|
+
{ name: 'provider', type: 'SettingsValueProvider', description: 'Editor protocol for dirty, valid, busy, getSettingsValue, onSave, reset and close hooks.' },
|
|
4639
|
+
],
|
|
4640
|
+
editableTargets: [
|
|
4641
|
+
{ kind: 'panelShell', resolver: 'settings-panel-config-root', description: 'Top-level shell identity and title fields owned by SettingsPanelConfig.' },
|
|
4642
|
+
{ kind: 'openMode', resolver: 'settings-panel-open-mode', description: 'Initial expanded state, replacement mediation and close behavior for an authoring panel.' },
|
|
4643
|
+
{ kind: 'panelSize', resolver: 'settings-panel-size-and-resize', description: 'Width, min/max width, resize enablement and persisted size key.' },
|
|
4644
|
+
{ kind: 'applyBehavior', resolver: 'settings-value-provider-apply-contract', description: 'Apply availability and payload emission through getSettingsValue().' },
|
|
4645
|
+
{ kind: 'saveBehavior', resolver: 'settings-value-provider-save-contract', description: 'Save availability, onSave fallback and close-after-save behavior.' },
|
|
4646
|
+
{ kind: 'resetBehavior', resolver: 'settings-value-provider-reset-contract', description: 'Reset confirmation, provider reset hook and reset event emission.' },
|
|
4647
|
+
{ kind: 'editorHost', resolver: 'settings-panel-editor-host', description: 'Hosted editor component and serializable input envelope.' },
|
|
4648
|
+
{ kind: 'diagnostics', resolver: 'settings-panel-state-diagnostics', description: 'Dirty, valid, busy, disabled reason and status message visibility.' },
|
|
4649
|
+
],
|
|
4650
|
+
operations: [
|
|
4651
|
+
{
|
|
4652
|
+
operationId: 'panel.shell.configure',
|
|
4653
|
+
title: 'Configure panel shell identity',
|
|
4654
|
+
scope: 'global',
|
|
4655
|
+
targetKind: 'panelShell',
|
|
4656
|
+
target: { kind: 'panelShell', resolver: 'settings-panel-config-root', ambiguityPolicy: 'fail', required: true },
|
|
4657
|
+
inputSchema: panelShellSchema,
|
|
4658
|
+
effects: [{ kind: 'merge-object', path: 'config' }],
|
|
4659
|
+
validators: ['panel-id-stable', 'title-i18n-compatible', 'settings-panel-round-trip'],
|
|
4660
|
+
affectedPaths: ['config.id', 'config.title', 'config.titleIcon'],
|
|
4661
|
+
submissionImpact: 'config-only',
|
|
4662
|
+
destructive: false,
|
|
4663
|
+
requiresConfirmation: false,
|
|
4664
|
+
preconditions: ['config-initialized'],
|
|
4665
|
+
},
|
|
4666
|
+
{
|
|
4667
|
+
operationId: 'panel.openMode.set',
|
|
4668
|
+
title: 'Set panel open mode',
|
|
4669
|
+
scope: 'global',
|
|
4670
|
+
targetKind: 'openMode',
|
|
4671
|
+
target: { kind: 'openMode', resolver: 'settings-panel-open-mode', ambiguityPolicy: 'fail', required: false },
|
|
4672
|
+
inputSchema: {
|
|
4673
|
+
type: 'object',
|
|
4674
|
+
minProperties: 1,
|
|
4675
|
+
properties: {
|
|
4676
|
+
expanded: { type: 'boolean' },
|
|
4677
|
+
replacementPolicy: { enum: ['consult-current-editor', 'reject-when-dirty', 'force-close-disallowed'] },
|
|
4678
|
+
},
|
|
4679
|
+
},
|
|
4680
|
+
effects: [{ kind: 'merge-object', path: 'config' }],
|
|
4681
|
+
validators: ['replacement-mediates-before-close', 'settings-panel-round-trip'],
|
|
4682
|
+
affectedPaths: ['config.expanded'],
|
|
4683
|
+
submissionImpact: 'config-only',
|
|
4684
|
+
destructive: false,
|
|
4685
|
+
requiresConfirmation: false,
|
|
4686
|
+
preconditions: ['config-initialized'],
|
|
4687
|
+
},
|
|
4688
|
+
{
|
|
4689
|
+
operationId: 'panel.size.set',
|
|
4690
|
+
title: 'Set panel size and resize policy',
|
|
4691
|
+
scope: 'layout',
|
|
4692
|
+
targetKind: 'panelSize',
|
|
4693
|
+
target: { kind: 'panelSize', resolver: 'settings-panel-size-and-resize', ambiguityPolicy: 'fail', required: false },
|
|
4694
|
+
inputSchema: panelSizeSchema,
|
|
4695
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'settings-panel-size-set', handlerContract: {
|
|
4696
|
+
reads: ['SettingsPanelConfig', 'SettingsPanelRef.sizeChanged$', 'persistSizeKey'],
|
|
4697
|
+
writes: ['config.minWidth', 'config.maxWidth', 'config.resizable', 'config.persistSizeKey', 'runtime.size'],
|
|
4698
|
+
identityKeys: ['config.id', 'persistSizeKey'],
|
|
4699
|
+
inputSchema: panelSizeSchema,
|
|
4700
|
+
failureModes: ['invalid-css-size', 'min-width-greater-than-max-width', 'persist-size-key-missing-for-persistence'],
|
|
4701
|
+
description: 'Applies shell size configuration and open-panel width changes through SettingsPanelRef.updateSize without changing hosted editor config semantics.',
|
|
4702
|
+
} }],
|
|
4703
|
+
validators: ['panel-size-safe', 'panel-min-max-consistent', 'resize-persistence-explicit', 'settings-panel-round-trip'],
|
|
4704
|
+
affectedPaths: ['config.minWidth', 'config.maxWidth', 'config.resizable', 'config.persistSizeKey', 'runtime.width'],
|
|
4705
|
+
submissionImpact: 'visual-only',
|
|
4706
|
+
destructive: false,
|
|
4707
|
+
requiresConfirmation: false,
|
|
4708
|
+
preconditions: ['config-initialized'],
|
|
4709
|
+
},
|
|
4710
|
+
{
|
|
4711
|
+
operationId: 'panel.applyBehavior.set',
|
|
4712
|
+
title: 'Set apply behavior',
|
|
4713
|
+
scope: 'interaction',
|
|
4714
|
+
targetKind: 'applyBehavior',
|
|
4715
|
+
target: { kind: 'applyBehavior', resolver: 'settings-value-provider-apply-contract', ambiguityPolicy: 'fail', required: false },
|
|
4716
|
+
inputSchema: behaviorSchema,
|
|
4717
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'settings-panel-apply-behavior-set', handlerContract: {
|
|
4718
|
+
reads: ['SettingsValueProvider.isDirty$', 'SettingsValueProvider.isValid$', 'SettingsValueProvider.isBusy$', 'SettingsValueProvider.getSettingsValue'],
|
|
4719
|
+
writes: ['SettingsPanelRef.applied$'],
|
|
4720
|
+
identityKeys: ['config.id', 'provider.getSettingsValue'],
|
|
4721
|
+
inputSchema: behaviorSchema,
|
|
4722
|
+
failureModes: ['provider-missing-get-settings-value', 'apply-while-invalid', 'apply-while-busy', 'apply-without-dirty-state'],
|
|
4723
|
+
description: 'Keeps Apply gated by dirty, valid and busy state and emits the provider value through SettingsPanelRef.applied$.',
|
|
4724
|
+
} }],
|
|
4725
|
+
validators: ['apply-requires-provider-value', 'dirty-valid-busy-gates-preserved', 'apply-does-not-close-panel', 'settings-panel-round-trip'],
|
|
4726
|
+
affectedPaths: ['provider.isDirty$', 'provider.isValid$', 'provider.isBusy$', 'ref.applied$'],
|
|
4727
|
+
submissionImpact: 'none',
|
|
4728
|
+
destructive: false,
|
|
4729
|
+
requiresConfirmation: false,
|
|
4730
|
+
preconditions: ['settings-value-provider-attached'],
|
|
4731
|
+
},
|
|
4732
|
+
{
|
|
4733
|
+
operationId: 'panel.saveBehavior.set',
|
|
4734
|
+
title: 'Set save behavior',
|
|
4735
|
+
scope: 'interaction',
|
|
4736
|
+
targetKind: 'saveBehavior',
|
|
4737
|
+
target: { kind: 'saveBehavior', resolver: 'settings-value-provider-save-contract', ambiguityPolicy: 'fail', required: false },
|
|
4738
|
+
inputSchema: behaviorSchema,
|
|
4739
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'settings-panel-save-behavior-set', handlerContract: {
|
|
4740
|
+
reads: ['SettingsValueProvider.onSave', 'SettingsValueProvider.getSettingsValue', 'SettingsValueProvider.isDirty$', 'SettingsValueProvider.isValid$', 'SettingsValueProvider.isBusy$'],
|
|
4741
|
+
writes: ['SettingsPanelRef.saved$', 'SettingsPanelRef.closed$'],
|
|
4742
|
+
identityKeys: ['config.id', 'provider.onSave'],
|
|
4743
|
+
inputSchema: behaviorSchema,
|
|
4744
|
+
failureModes: ['save-while-invalid', 'save-while-busy', 'save-result-undefined', 'provider-save-rejected'],
|
|
4745
|
+
description: 'Keeps Save gated by dirty, valid and busy state, prefers onSave when present, falls back to getSettingsValue and closes with reason save.',
|
|
4746
|
+
} }],
|
|
4747
|
+
validators: ['save-prefers-provider-hook', 'save-fallback-value-preserved', 'save-closes-with-save-reason', 'dirty-valid-busy-gates-preserved'],
|
|
4748
|
+
affectedPaths: ['provider.onSave', 'provider.getSettingsValue', 'ref.saved$', 'ref.closed$'],
|
|
4749
|
+
submissionImpact: 'config-only',
|
|
4750
|
+
destructive: false,
|
|
4751
|
+
requiresConfirmation: false,
|
|
4752
|
+
preconditions: ['settings-value-provider-attached'],
|
|
4753
|
+
},
|
|
4754
|
+
{
|
|
4755
|
+
operationId: 'panel.resetBehavior.set',
|
|
4756
|
+
title: 'Set reset behavior',
|
|
4757
|
+
scope: 'interaction',
|
|
4758
|
+
targetKind: 'resetBehavior',
|
|
4759
|
+
target: { kind: 'resetBehavior', resolver: 'settings-value-provider-reset-contract', ambiguityPolicy: 'fail', required: false },
|
|
4760
|
+
inputSchema: {
|
|
4761
|
+
type: 'object',
|
|
4762
|
+
minProperties: 1,
|
|
4763
|
+
properties: {
|
|
4764
|
+
requireConfirmation: { type: 'boolean' },
|
|
4765
|
+
callProviderReset: { type: 'boolean' },
|
|
4766
|
+
emitResetEvent: { type: 'boolean' },
|
|
4767
|
+
clearSavedStatus: { type: 'boolean' },
|
|
4768
|
+
},
|
|
4769
|
+
},
|
|
4770
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'settings-panel-reset-behavior-set', handlerContract: {
|
|
4771
|
+
reads: ['SettingsValueProvider.reset', 'SettingsPanelRef.reset$', 'ConfirmDialogComponent'],
|
|
4772
|
+
writes: ['provider.reset()', 'SettingsPanelRef.reset$', 'panel.lastSavedAt'],
|
|
4773
|
+
identityKeys: ['config.id', 'provider.reset'],
|
|
4774
|
+
inputSchema: { type: 'object', properties: { requireConfirmation: { type: 'boolean' }, callProviderReset: { type: 'boolean' }, emitResetEvent: { type: 'boolean' } } },
|
|
4775
|
+
failureModes: ['reset-confirmation-missing', 'provider-reset-failed', 'reset-event-not-emitted'],
|
|
4776
|
+
description: 'Preserves Reset as a confirmed shell action that calls the provider reset hook and emits SettingsPanelRef.reset$.',
|
|
4777
|
+
} }],
|
|
4778
|
+
destructive: true,
|
|
4779
|
+
requiresConfirmation: true,
|
|
4780
|
+
validators: ['reset-requires-confirmation', 'reset-calls-provider-reset', 'reset-event-emitted', 'settings-panel-round-trip'],
|
|
4781
|
+
affectedPaths: ['provider.reset', 'ref.reset$', 'panel.lastSavedAt'],
|
|
4782
|
+
submissionImpact: 'config-only',
|
|
4783
|
+
preconditions: ['settings-value-provider-attached', 'confirmation-collected'],
|
|
4784
|
+
},
|
|
4785
|
+
{
|
|
4786
|
+
operationId: 'editor.host.configure',
|
|
4787
|
+
title: 'Configure hosted editor',
|
|
4788
|
+
scope: 'templating',
|
|
4789
|
+
targetKind: 'editorHost',
|
|
4790
|
+
target: { kind: 'editorHost', resolver: 'settings-panel-editor-host', ambiguityPolicy: 'fail', required: true },
|
|
4791
|
+
inputSchema: editorHostSchema,
|
|
4792
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'settings-panel-editor-host-configure', handlerContract: {
|
|
4793
|
+
reads: ['ComponentMetadataRegistry', 'SettingsPanelConfig.content', 'SettingsValueProvider', 'component.authoringManifest'],
|
|
4794
|
+
writes: ['config.content.component', 'config.content.inputs', 'delegatedConsumerPatch'],
|
|
4795
|
+
identityKeys: ['componentId', 'configManifestComponentId'],
|
|
4796
|
+
inputSchema: editorHostSchema,
|
|
4797
|
+
failureModes: ['editor-component-not-registered', 'settings-value-provider-missing', 'consumer-manifest-required', 'consumer-config-boundary-violation'],
|
|
4798
|
+
description: 'Configures the hosted editor component and input envelope while delegating consumer-specific config edits to the owning component manifest.',
|
|
4799
|
+
} }],
|
|
4800
|
+
validators: ['editor-component-registered', 'settings-value-provider-contract-present', 'consumer-config-delegated', 'editor-inputs-serializable'],
|
|
4801
|
+
affectedPaths: ['config.content.component', 'config.content.inputs', 'delegatedConsumerPatch'],
|
|
4802
|
+
submissionImpact: 'config-only',
|
|
4803
|
+
destructive: false,
|
|
4804
|
+
requiresConfirmation: false,
|
|
4805
|
+
preconditions: ['component-metadata-resolved'],
|
|
4806
|
+
},
|
|
4807
|
+
{
|
|
4808
|
+
operationId: 'diagnostics.visibility.set',
|
|
4809
|
+
title: 'Set panel diagnostics visibility',
|
|
4810
|
+
scope: 'interaction',
|
|
4811
|
+
targetKind: 'diagnostics',
|
|
4812
|
+
target: { kind: 'diagnostics', resolver: 'settings-panel-state-diagnostics', ambiguityPolicy: 'fail', required: false },
|
|
4813
|
+
inputSchema: {
|
|
4814
|
+
type: 'object',
|
|
4815
|
+
minProperties: 1,
|
|
4816
|
+
properties: {
|
|
4817
|
+
showStatusMessage: { type: 'boolean' },
|
|
4818
|
+
showDisabledReason: { type: 'boolean' },
|
|
4819
|
+
showBusyState: { type: 'boolean' },
|
|
4820
|
+
exposeValidationState: { type: 'boolean' },
|
|
4821
|
+
},
|
|
4822
|
+
},
|
|
4823
|
+
effects: [{ kind: 'merge-object', path: 'config.diagnostics' }],
|
|
4824
|
+
validators: ['diagnostics-follow-provider-state', 'diagnostics-i18n-compatible', 'busy-valid-dirty-visible-when-needed', 'settings-panel-round-trip'],
|
|
4825
|
+
affectedPaths: [
|
|
4826
|
+
'config.diagnostics.showStatusMessage',
|
|
4827
|
+
'config.diagnostics.showDisabledReason',
|
|
4828
|
+
'config.diagnostics.showBusyState',
|
|
4829
|
+
'config.diagnostics.exposeValidationState',
|
|
4830
|
+
'panel.statusMessage',
|
|
4831
|
+
'panel.disabledReason',
|
|
4832
|
+
'panel.isDirty',
|
|
4833
|
+
'panel.isValid',
|
|
4834
|
+
'panel.isBusy',
|
|
4835
|
+
],
|
|
4836
|
+
submissionImpact: 'visual-only',
|
|
4837
|
+
destructive: false,
|
|
4838
|
+
requiresConfirmation: false,
|
|
4839
|
+
preconditions: ['settings-value-provider-attached'],
|
|
4840
|
+
},
|
|
4841
|
+
],
|
|
4842
|
+
validators: [
|
|
4843
|
+
{ validatorId: 'panel-id-stable', level: 'error', code: 'SETTINGS_PANEL_ID_STABLE', description: 'Panel id must remain stable for replacement, persistence and diagnostics.' },
|
|
4844
|
+
{ validatorId: 'replacement-mediates-before-close', level: 'error', code: 'SETTINGS_PANEL_REPLACEMENT_MEDIATES_CLOSE', description: 'Opening a replacement panel must consult the current editor onBeforeClose before closing.' },
|
|
4845
|
+
{ validatorId: 'title-i18n-compatible', level: 'warning', code: 'SETTINGS_PANEL_TITLE_I18N_COMPATIBLE', description: 'Authoring chrome text must remain compatible with the settings panel i18n namespace.' },
|
|
4846
|
+
{ validatorId: 'panel-size-safe', level: 'error', code: 'SETTINGS_PANEL_SIZE_SAFE', description: 'Panel sizes must be finite numbers or safe CSS size strings.' },
|
|
4847
|
+
{ validatorId: 'panel-min-max-consistent', level: 'error', code: 'SETTINGS_PANEL_MIN_MAX_CONSISTENT', description: 'Minimum width must not exceed maximum width.' },
|
|
4848
|
+
{ validatorId: 'resize-persistence-explicit', level: 'error', code: 'SETTINGS_PANEL_RESIZE_PERSISTENCE_EXPLICIT', description: 'Persisted resize must use a stable persistSizeKey or be explicitly transient.' },
|
|
4849
|
+
{ validatorId: 'apply-requires-provider-value', level: 'error', code: 'SETTINGS_PANEL_APPLY_REQUIRES_PROVIDER_VALUE', description: 'Apply must obtain payloads from SettingsValueProvider.getSettingsValue().' },
|
|
4850
|
+
{ validatorId: 'apply-does-not-close-panel', level: 'error', code: 'SETTINGS_PANEL_APPLY_DOES_NOT_CLOSE', description: 'Apply emits preview payloads without closing the panel.' },
|
|
4851
|
+
{ validatorId: 'dirty-valid-busy-gates-preserved', level: 'error', code: 'SETTINGS_PANEL_STATE_GATES_PRESERVED', description: 'Apply and Save remain gated by dirty, valid and busy state.' },
|
|
4852
|
+
{ validatorId: 'save-prefers-provider-hook', level: 'error', code: 'SETTINGS_PANEL_SAVE_PREFERS_PROVIDER_HOOK', description: 'Save must call onSave when provided before falling back to getSettingsValue().' },
|
|
4853
|
+
{ validatorId: 'save-fallback-value-preserved', level: 'error', code: 'SETTINGS_PANEL_SAVE_FALLBACK_PRESERVED', description: 'Save fallback must preserve getSettingsValue payload semantics.' },
|
|
4854
|
+
{ validatorId: 'save-closes-with-save-reason', level: 'error', code: 'SETTINGS_PANEL_SAVE_CLOSE_REASON', description: 'Successful save must emit saved$ and close with reason save.' },
|
|
4855
|
+
{ validatorId: 'reset-requires-confirmation', level: 'error', code: 'SETTINGS_PANEL_RESET_REQUIRES_CONFIRMATION', description: 'Reset is destructive and must remain confirmed before provider reset is called.' },
|
|
4856
|
+
{ validatorId: 'reset-calls-provider-reset', level: 'error', code: 'SETTINGS_PANEL_RESET_CALLS_PROVIDER', description: 'Reset must call the hosted provider reset hook when present.' },
|
|
4857
|
+
{ validatorId: 'reset-event-emitted', level: 'error', code: 'SETTINGS_PANEL_RESET_EVENT_EMITTED', description: 'Reset must emit SettingsPanelRef.reset$ so hosts can coordinate state.' },
|
|
4858
|
+
{ validatorId: 'editor-component-registered', level: 'error', code: 'SETTINGS_PANEL_EDITOR_REGISTERED', description: 'Hosted editor component must resolve from governed component metadata or host registration.' },
|
|
4859
|
+
{ validatorId: 'settings-value-provider-contract-present', level: 'error', code: 'SETTINGS_PANEL_PROVIDER_CONTRACT_PRESENT', description: 'Hosted authoring editors must implement SettingsValueProvider state and value contract.' },
|
|
4860
|
+
{ validatorId: 'consumer-config-delegated', level: 'error', code: 'SETTINGS_PANEL_CONSUMER_CONFIG_DELEGATED', description: 'Consumer-specific config operations must delegate to the owning component manifest.' },
|
|
4861
|
+
{ validatorId: 'editor-inputs-serializable', level: 'error', code: 'SETTINGS_PANEL_EDITOR_INPUTS_SERIALIZABLE', description: 'Persisted editor host inputs must be serializable safe values.' },
|
|
4862
|
+
{ validatorId: 'diagnostics-follow-provider-state', level: 'error', code: 'SETTINGS_PANEL_DIAGNOSTICS_PROVIDER_STATE', description: 'Diagnostics must reflect provider dirty, valid and busy state.' },
|
|
4863
|
+
{ validatorId: 'diagnostics-i18n-compatible', level: 'warning', code: 'SETTINGS_PANEL_DIAGNOSTICS_I18N_COMPATIBLE', description: 'Diagnostics copy must use the settings panel i18n namespace.' },
|
|
4864
|
+
{ validatorId: 'busy-valid-dirty-visible-when-needed', level: 'error', code: 'SETTINGS_PANEL_STATE_VISIBLE', description: 'Busy, invalid and dirty states must remain visible or explain disabled actions.' },
|
|
4865
|
+
{ validatorId: 'settings-panel-round-trip', level: 'error', code: 'SETTINGS_PANEL_ROUND_TRIP', description: 'Open, edit, apply, save, reset and reopen must preserve the shell protocol without mutating consumer config semantics.' },
|
|
4866
|
+
],
|
|
4867
|
+
roundTripRequirements: [
|
|
4868
|
+
'SettingsPanelConfig owns only shell fields: identity, title, size, resize persistence and hosted editor envelope.',
|
|
4869
|
+
'SettingsValueProvider owns apply/save/reset payload extraction, while consumer config semantics stay delegated to the owning component manifest.',
|
|
4870
|
+
'Apply must emit applied$ without closing; Save must emit saved$ and close with reason save; Reset must be confirmed and emit reset$.',
|
|
4871
|
+
'Busy, dirty and valid state must gate Apply and Save consistently and remain visible through diagnostics.',
|
|
4872
|
+
'Opening a replacement panel must pass through the current editor onBeforeClose and dirty-discard mediation.',
|
|
4873
|
+
],
|
|
4874
|
+
examples: [
|
|
4875
|
+
{ id: 'open-component-editor', request: 'Open the table settings editor in the settings panel.', operationId: 'editor.host.configure', params: { componentId: 'praxis-table', inputs: { tableId: 'orders' }, configManifestComponentId: 'praxis-table', editorContract: 'SettingsValueProvider' }, isPositive: true },
|
|
4876
|
+
{ id: 'start-expanded', request: 'Open this settings panel expanded.', operationId: 'panel.openMode.set', params: { expanded: true }, isPositive: true },
|
|
4877
|
+
{ id: 'set-resizable-width', request: 'Make the settings drawer resizable between 420px and 960px.', operationId: 'panel.size.set', params: { resizable: true, minWidth: '420px', maxWidth: '960px', persistSizeKey: 'settings-panel:orders' }, isPositive: true },
|
|
4878
|
+
{ id: 'apply-preview', request: 'Apply the editor change without saving or closing.', operationId: 'panel.applyBehavior.set', params: { requireDirty: true, requireValid: true, blockWhileBusy: true }, isPositive: true },
|
|
4879
|
+
{ id: 'save-and-close', request: 'Save this editor value and close the panel.', operationId: 'panel.saveBehavior.set', params: { requireDirty: true, requireValid: true, blockWhileBusy: true, useProviderHook: true, closeAfterSave: true }, isPositive: true },
|
|
4880
|
+
{ id: 'reset-to-original', request: 'Reset this editor to its original value.', operationId: 'panel.resetBehavior.set', params: { requireConfirmation: true, callProviderReset: true, emitResetEvent: true }, isPositive: true },
|
|
4881
|
+
{ id: 'show-busy-diagnostics', request: 'Show why Apply and Save are disabled while the editor is busy.', operationId: 'diagnostics.visibility.set', params: { showStatusMessage: true, showDisabledReason: true, showBusyState: true }, isPositive: true },
|
|
4882
|
+
{ id: 'reject-table-column-direct-edit', request: 'Use settings-panel to rename a table column directly.', operationId: 'editor.host.configure', params: { componentId: 'praxis-settings-panel', inputs: { columns: [{ field: 'name', label: 'Name' }] } }, isPositive: false },
|
|
4883
|
+
{ id: 'reject-missing-provider', request: 'Host a component that has no dirty, valid, busy or getSettingsValue contract.', operationId: 'editor.host.configure', params: { componentId: 'plain-info-card' }, isPositive: false },
|
|
4884
|
+
{ id: 'reject-reset-without-confirmation', request: 'Reset the editor immediately without confirmation.', operationId: 'panel.resetBehavior.set', params: { requireConfirmation: false, callProviderReset: true }, isPositive: false },
|
|
4885
|
+
],
|
|
4886
|
+
};
|
|
4887
|
+
|
|
4447
4888
|
/**
|
|
4448
4889
|
* Generated bundle index. Do not edit.
|
|
4449
4890
|
*/
|
|
4450
4891
|
|
|
4451
|
-
export { BASE_SIDE_PANEL_DATA, BASE_SIDE_PANEL_REF, BaseSidePanelComponent, BaseSidePanelOverlayRef, BaseSidePanelService, DeferredSettingsPanelRef, GLOBAL_CONFIG_DYNAMIC_FORM_COMPONENT, GlobalConfigAdminService, GlobalConfigEditorComponent, SETTINGS_PANEL_AI_CAPABILITIES, SETTINGS_PANEL_DATA, SETTINGS_PANEL_REF, SIDE_PANEL_THEME_CSS_VARS, SettingsPanelComponent, SettingsPanelRef, SettingsPanelService, SurfaceDrawerComponent, buildGlobalConfigFormConfig, openGlobalConfigEditor, providePraxisSettingsPanelBridge, providePraxisSurfaceDrawerBridge };
|
|
4892
|
+
export { BASE_SIDE_PANEL_DATA, BASE_SIDE_PANEL_REF, BaseSidePanelComponent, BaseSidePanelOverlayRef, BaseSidePanelService, DeferredSettingsPanelRef, GLOBAL_CONFIG_DYNAMIC_FORM_COMPONENT, GlobalConfigAdminService, GlobalConfigEditorComponent, PRAXIS_SETTINGS_PANEL_AUTHORING_MANIFEST, SETTINGS_PANEL_AI_CAPABILITIES, SETTINGS_PANEL_DATA, SETTINGS_PANEL_REF, SIDE_PANEL_THEME_CSS_VARS, SettingsPanelComponent, SettingsPanelRef, SettingsPanelService, SurfaceDrawerComponent, buildGlobalConfigFormConfig, openGlobalConfigEditor, providePraxisSettingsPanelBridge, providePraxisSurfaceDrawerBridge };
|