@praxisui/core 9.0.64 → 9.0.66

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, InjectionToken, Injectable, inject, Inject, Optional, SkipSelf, makeEnvironmentProviders, APP_INITIALIZER, signal, computed, DestroyRef, ENVIRONMENT_INITIALIZER, ErrorHandler, Input, Directive, input, booleanAttribute, ChangeDetectionStrategy, EventEmitter, Output, SecurityContext, ViewContainerRef, Injector, isSignal, effect, SimpleChange, contentChild, HostBinding, output, ElementRef, ChangeDetectorRef, afterNextRender, HostListener, ViewChildren, ViewChild } from '@angular/core';
2
+ import { Component, InjectionToken, Injectable, inject, Inject, Optional, SkipSelf, makeEnvironmentProviders, APP_INITIALIZER, signal, computed, DestroyRef, ENVIRONMENT_INITIALIZER, ErrorHandler, Input, Directive, input, booleanAttribute, ChangeDetectionStrategy, EventEmitter, Output, SecurityContext, ViewContainerRef, Injector, isSignal, effect, SimpleChange, ChangeDetectorRef, ElementRef, afterEveryRender, contentChild, HostBinding, output, afterNextRender, HostListener, ViewChildren, ViewChild } from '@angular/core';
3
3
  import * as i1 from '@angular/common/http';
4
4
  import { HttpHeaders, HttpClient, HttpParams, HttpResponse, HttpContextToken, HTTP_INTERCEPTORS, withInterceptors } from '@angular/common/http';
5
5
  import { of, defer, throwError, from, EMPTY, BehaviorSubject, firstValueFrom, Subject, finalize as finalize$1, shareReplay as shareReplay$1, map as map$1, switchMap as switchMap$1, catchError as catchError$1, forkJoin } from 'rxjs';
@@ -22,19 +22,21 @@ import * as i6 from '@angular/material/select';
22
22
  import { MatSelectModule } from '@angular/material/select';
23
23
  import * as i7 from '@angular/material/slide-toggle';
24
24
  import { MatSlideToggleModule } from '@angular/material/slide-toggle';
25
- import * as i8 from '@angular/material/tooltip';
25
+ import * as i3 from '@angular/material/tooltip';
26
26
  import { MatTooltipModule } from '@angular/material/tooltip';
27
27
  import { DomSanitizer } from '@angular/platform-browser';
28
28
  import * as i4$1 from '@angular/material/menu';
29
29
  import { MatMenuModule } from '@angular/material/menu';
30
- import * as i3 from '@angular/material/progress-spinner';
30
+ import * as i4$2 from '@angular/cdk/overlay';
31
+ import { OverlayModule } from '@angular/cdk/overlay';
32
+ import * as i3$1 from '@angular/material/progress-spinner';
31
33
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
32
- import * as i3$1 from '@angular/material/button-toggle';
34
+ import * as i3$2 from '@angular/material/button-toggle';
33
35
  import { MatButtonToggleModule } from '@angular/material/button-toggle';
34
36
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
35
37
  import * as i1$4 from '@angular/material/dialog';
36
38
  import { MAT_DIALOG_DATA, MatDialogModule, MatDialog } from '@angular/material/dialog';
37
- import * as i8$1 from '@angular/material/chips';
39
+ import * as i8 from '@angular/material/chips';
38
40
  import { MatChipsModule } from '@angular/material/chips';
39
41
  import * as i2$1 from '@angular/material/card';
40
42
  import { MatCardModule } from '@angular/material/card';
@@ -27539,7 +27541,7 @@ class SurfaceOpenActionEditorComponent {
27539
27541
  </mat-form-field>
27540
27542
  </div>
27541
27543
  </div>
27542
- `, isInline: true, styles: [".surface-editor{display:grid;gap:14px;min-width:0}.surface-section{display:grid;gap:10px;min-width:0;padding:14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.surface-section-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:0}.surface-section-title{font-size:12px;font-weight:700;letter-spacing:0;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);margin-bottom:0}.surface-section-header .surface-section-title{margin-bottom:0}.surface-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:12px 16px;min-width:0}.surface-preset-row{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.surface-span-2{grid-column:span 2}.surface-span-all{width:100%;min-width:0}.surface-component-meta{display:grid;gap:4px;padding:10px 12px;border-radius:8px;background:var(--md-sys-color-surface-container)}.surface-component-title{font-weight:600;color:var(--md-sys-color-on-surface)}.surface-component-description,.surface-empty{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.surface-bindings{display:grid;gap:10px;min-width:0}.surface-binding-row{display:grid;grid-template-columns:minmax(min(220px,100%),1.15fr) minmax(min(240px,100%),1.25fr) minmax(128px,.55fr) auto;gap:10px;align-items:start;min-width:0;padding:10px;border-radius:8px;background:var(--md-sys-color-surface-container)}.surface-binding-row mat-form-field:nth-child(4){grid-column:1 / -2}.surface-binding-remove{color:var(--md-sys-color-error)}.surface-guidance{display:grid;gap:4px;padding:10px 12px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 18%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.surface-guidance__item{overflow-wrap:anywhere}.surface-guidance__item--primary{color:var(--md-sys-color-on-surface)}mat-form-field{width:100%;min-width:0}@media(max-width:960px){.surface-section{padding:12px}.surface-span-2{grid-column:1 / -1}.surface-binding-row{grid-template-columns:minmax(0,1fr)}.surface-binding-row mat-form-field:nth-child(4){grid-column:auto}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }] });
27544
+ `, isInline: true, styles: [".surface-editor{display:grid;gap:14px;min-width:0}.surface-section{display:grid;gap:10px;min-width:0;padding:14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.surface-section-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:0}.surface-section-title{font-size:12px;font-weight:700;letter-spacing:0;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);margin-bottom:0}.surface-section-header .surface-section-title{margin-bottom:0}.surface-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:12px 16px;min-width:0}.surface-preset-row{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}.surface-span-2{grid-column:span 2}.surface-span-all{width:100%;min-width:0}.surface-component-meta{display:grid;gap:4px;padding:10px 12px;border-radius:8px;background:var(--md-sys-color-surface-container)}.surface-component-title{font-weight:600;color:var(--md-sys-color-on-surface)}.surface-component-description,.surface-empty{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.surface-bindings{display:grid;gap:10px;min-width:0}.surface-binding-row{display:grid;grid-template-columns:minmax(min(220px,100%),1.15fr) minmax(min(240px,100%),1.25fr) minmax(128px,.55fr) auto;gap:10px;align-items:start;min-width:0;padding:10px;border-radius:8px;background:var(--md-sys-color-surface-container)}.surface-binding-row mat-form-field:nth-child(4){grid-column:1 / -2}.surface-binding-remove{color:var(--md-sys-color-error)}.surface-guidance{display:grid;gap:4px;padding:10px 12px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 18%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.surface-guidance__item{overflow-wrap:anywhere}.surface-guidance__item--primary{color:var(--md-sys-color-on-surface)}mat-form-field{width:100%;min-width:0}@media(max-width:960px){.surface-section{padding:12px}.surface-span-2{grid-column:1 / -1}.surface-binding-row{grid-template-columns:minmax(0,1fr)}.surface-binding-row mat-form-field:nth-child(4){grid-column:auto}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }] });
27543
27545
  }
27544
27546
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SurfaceOpenActionEditorComponent, decorators: [{
27545
27547
  type: Component,
@@ -33132,6 +33134,22 @@ function isRecord(value) {
33132
33134
  return !!value && typeof value === 'object' && !Array.isArray(value);
33133
33135
  }
33134
33136
 
33137
+ /** Private rendered geometry shared by shell recovery and canvas authoring. */
33138
+ function measureWidgetShellHeight(shell) {
33139
+ const body = shell.querySelector(':scope > .pdx-shell-body');
33140
+ if (!body || body.classList.contains('hidden') || !shell.getBoundingClientRect().height)
33141
+ return undefined;
33142
+ const header = shell.querySelector(':scope > .pdx-shell-header');
33143
+ const bodyStyle = getComputedStyle(body);
33144
+ const padding = (parseFloat(bodyStyle.paddingTop) || 0) + (parseFloat(bodyStyle.paddingBottom) || 0);
33145
+ const shellStyle = getComputedStyle(shell);
33146
+ const chrome = (header?.getBoundingClientRect().height || 0)
33147
+ + (parseFloat(shellStyle.borderTopWidth) || 0) + (parseFloat(shellStyle.borderBottomWidth) || 0);
33148
+ // Structural viewport reserve only; not business-component UX certification.
33149
+ const reserve = Math.min(160, Math.max(0, body.scrollHeight - padding));
33150
+ return { minimum: Math.ceil(chrome + padding + reserve), available: shell.getBoundingClientRect().height };
33151
+ }
33152
+
33135
33153
  const WIDGET_SHELL_I18N_NAMESPACE = 'widgetShell';
33136
33154
  const WIDGET_SHELL_I18N_CONFIG = {
33137
33155
  namespaces: {
@@ -33334,6 +33352,70 @@ const BUILTIN_SHELL_PRESETS = {
33334
33352
  };
33335
33353
  class WidgetShellComponent {
33336
33354
  i18n = inject(PraxisI18nService);
33355
+ changeDetector = inject(ChangeDetectorRef);
33356
+ destroyRef = inject(DestroyRef);
33357
+ element = inject(ElementRef);
33358
+ scrollRecovery = signal(false, ...(ngDevMode ? [{ debugName: "scrollRecovery" }] : /* istanbul ignore next */ []));
33359
+ scrollResizeObserver;
33360
+ scrollMutationObserver;
33361
+ scrollObservedElements = [];
33362
+ scrollObservedBody;
33363
+ scrollFrame;
33364
+ constructor() {
33365
+ afterEveryRender({ read: () => this.observeScrollGeometry() });
33366
+ this.destroyRef.onDestroy(() => this.disconnectScrollGeometry());
33367
+ }
33368
+ disconnectScrollGeometry() {
33369
+ this.scrollResizeObserver?.disconnect();
33370
+ this.scrollMutationObserver?.disconnect();
33371
+ this.scrollObservedElements = [];
33372
+ this.scrollObservedBody = undefined;
33373
+ if (this.scrollFrame !== undefined)
33374
+ cancelAnimationFrame(this.scrollFrame);
33375
+ this.scrollFrame = undefined;
33376
+ }
33377
+ observeScrollGeometry() {
33378
+ if (this.shell?.bodyLayout !== 'scroll' || this.collapsed || this.expanded || this.fullscreen) {
33379
+ this.disconnectScrollGeometry();
33380
+ this.scrollRecovery.set(false);
33381
+ return;
33382
+ }
33383
+ const shell = this.element.nativeElement.querySelector(':scope > .pdx-shell');
33384
+ const body = shell?.querySelector(':scope > .pdx-shell-body');
33385
+ if (!shell || !body)
33386
+ return;
33387
+ const schedule = () => {
33388
+ if (this.scrollFrame !== undefined || this.destroyRef.destroyed)
33389
+ return;
33390
+ this.scrollFrame = requestAnimationFrame(() => {
33391
+ this.scrollFrame = undefined;
33392
+ if (!this.destroyRef.destroyed)
33393
+ this.observeScrollGeometry();
33394
+ });
33395
+ };
33396
+ const elements = [shell, ...Array.from(shell.children), ...Array.from(body.children)];
33397
+ if (typeof ResizeObserver === 'function' && (elements.length !== this.scrollObservedElements.length
33398
+ || elements.some((element, index) => element !== this.scrollObservedElements[index]))) {
33399
+ this.scrollResizeObserver ??= new ResizeObserver(schedule);
33400
+ this.scrollResizeObserver.disconnect();
33401
+ elements.forEach(element => this.scrollResizeObserver.observe(element));
33402
+ this.scrollObservedElements = elements;
33403
+ }
33404
+ if (typeof MutationObserver === 'function' && this.scrollObservedBody !== body) {
33405
+ this.scrollMutationObserver ??= new MutationObserver(schedule);
33406
+ this.scrollMutationObserver.disconnect();
33407
+ this.scrollMutationObserver.observe(body, { subtree: true, childList: true, characterData: true, attributes: true });
33408
+ this.scrollObservedBody = body;
33409
+ }
33410
+ const measure = measureWidgetShellHeight(shell);
33411
+ const recovery = !!measure && measure.minimum > Math.ceil(measure.available);
33412
+ if (this.scrollRecovery() !== recovery) {
33413
+ this.scrollRecovery.set(recovery);
33414
+ // A scroll position in the outer shell must not hide its header after recovery.
33415
+ if (!recovery)
33416
+ shell.scrollTop = 0;
33417
+ }
33418
+ }
33337
33419
  get hostCollapsed() {
33338
33420
  return this.collapsed && !this.expanded && !this.fullscreen;
33339
33421
  }
@@ -33362,6 +33444,7 @@ class WidgetShellComponent {
33362
33444
  collapsed = false;
33363
33445
  expanded = false;
33364
33446
  fullscreen = false;
33447
+ overlayReturnFocus = null;
33365
33448
  initializedWindowState = false;
33366
33449
  lastWindowStateInputs;
33367
33450
  ngOnChanges(changes) {
@@ -33427,7 +33510,17 @@ class WidgetShellComponent {
33427
33510
  }
33428
33511
  onAction(action, ev) {
33429
33512
  ev.stopPropagation();
33513
+ if (action.disabled)
33514
+ return;
33515
+ const wasOverlay = this.expanded || this.fullscreen;
33516
+ if (!wasOverlay && (action.id === 'expand' || action.id === 'fullscreen')) {
33517
+ this.overlayReturnFocus =
33518
+ ev.target instanceof Element ? ev.target.closest('button') : null;
33519
+ }
33430
33520
  const handled = this.handleWindowAction(action);
33521
+ if (wasOverlay && !this.expanded && !this.fullscreen) {
33522
+ this.restoreOverlayFocus();
33523
+ }
33431
33524
  const payload = action.payload ?? handled?.payload;
33432
33525
  const event = {
33433
33526
  id: action.id,
@@ -33480,6 +33573,16 @@ class WidgetShellComponent {
33480
33573
  }
33481
33574
  this.dragSurfaceKeydown.emit(event);
33482
33575
  }
33576
+ onAuthoringDragPointerDown(event) {
33577
+ if (!this.dragSurfaceInteractive)
33578
+ return;
33579
+ this.dragSurfacePointerDown.emit(event);
33580
+ }
33581
+ onAuthoringDragKeydown(event) {
33582
+ if (!this.dragSurfaceInteractive)
33583
+ return;
33584
+ this.dragSurfaceKeydown.emit(event);
33585
+ }
33483
33586
  stopIfExpanded(ev) {
33484
33587
  if (this.expanded || this.fullscreen)
33485
33588
  ev.stopPropagation();
@@ -33487,6 +33590,27 @@ class WidgetShellComponent {
33487
33590
  closeOverlay() {
33488
33591
  this.expanded = false;
33489
33592
  this.fullscreen = false;
33593
+ this.restoreOverlayFocus();
33594
+ }
33595
+ onOverlayEscape(event) {
33596
+ if (event.defaultPrevented || (!this.expanded && !this.fullscreen))
33597
+ return;
33598
+ // Connected overlays such as MatSelect consume Escape at the CDK body
33599
+ // dispatcher. A task (not a microtask between native listeners) lets the
33600
+ // complete event propagation finish before treating it as a shell command.
33601
+ setTimeout(() => {
33602
+ if (this.destroyRef.destroyed || event.defaultPrevented || (!this.expanded && !this.fullscreen))
33603
+ return;
33604
+ event.preventDefault();
33605
+ this.closeOverlay();
33606
+ this.changeDetector.markForCheck();
33607
+ }, 0);
33608
+ }
33609
+ restoreOverlayFocus() {
33610
+ if (this.overlayReturnFocus?.isConnected) {
33611
+ this.overlayReturnFocus.focus({ preventScroll: true });
33612
+ }
33613
+ this.overlayReturnFocus = null;
33490
33614
  }
33491
33615
  moreActionsLabel() {
33492
33616
  return this.t('controls.moreActions', 'Mais ações');
@@ -33598,9 +33722,19 @@ class WidgetShellComponent {
33598
33722
  return this.i18n.t(key, undefined, fallback, WIDGET_SHELL_I18N_NAMESPACE);
33599
33723
  }
33600
33724
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: WidgetShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
33601
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: WidgetShellComponent, isStandalone: true, selector: "praxis-widget-shell", inputs: { shell: "shell", context: "context", dragSurfaceEnabled: "dragSurfaceEnabled", dragSurfaceLabel: "dragSurfaceLabel" }, outputs: { action: "action", dragSurfacePointerDown: "dragSurfacePointerDown", dragSurfaceKeydown: "dragSurfaceKeydown" }, host: { properties: { "class.pdx-widget-shell-collapsed": "this.hostCollapsed" } }, providers: [providePraxisI18nConfig(WIDGET_SHELL_I18N_CONFIG)], queries: [{ propertyName: "loader", first: true, predicate: DynamicWidgetLoaderDirective, descendants: true, isSignal: true }], usesOnChanges: true, ngImport: i0, template: `
33725
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: WidgetShellComponent, isStandalone: true, selector: "praxis-widget-shell", inputs: { shell: "shell", context: "context", dragSurfaceEnabled: "dragSurfaceEnabled", dragSurfaceLabel: "dragSurfaceLabel" }, outputs: { action: "action", dragSurfacePointerDown: "dragSurfacePointerDown", dragSurfaceKeydown: "dragSurfaceKeydown" }, host: { listeners: { "keydown.escape": "onOverlayEscape($event)" }, properties: { "class.pdx-widget-shell-collapsed": "this.hostCollapsed" } }, providers: [providePraxisI18nConfig(WIDGET_SHELL_I18N_CONFIG)], queries: [{ propertyName: "loader", first: true, predicate: DynamicWidgetLoaderDirective, descendants: true, isSignal: true }], usesOnChanges: true, ngImport: i0, template: `
33726
+ @if (expanded || fullscreen) {
33727
+ <div
33728
+ class="pdx-shell-overlay-surface"
33729
+ [class.expanded]="expanded"
33730
+ [class.fullscreen]="fullscreen"
33731
+ [style.border-radius]="fullscreen ? null : appearance?.card?.borderRadius || null"
33732
+ aria-hidden="true"
33733
+ ></div>
33734
+ }
33602
33735
  <section
33603
33736
  class="pdx-shell"
33737
+ [attr.tabindex]="expanded || fullscreen ? -1 : null"
33604
33738
  [class.no-shell]="!shellEnabled"
33605
33739
  [class.dashboard]="shellEnabled"
33606
33740
  [class.collapsed]="collapsed"
@@ -33608,6 +33742,7 @@ class WidgetShellComponent {
33608
33742
  [class.fullscreen]="fullscreen"
33609
33743
  [class.body-fill]="shell?.bodyLayout === 'fill'"
33610
33744
  [class.body-scroll]="shell?.bodyLayout === 'scroll'"
33745
+ [class.pdx-shell--scroll-recovery]="scrollRecovery() && !collapsed && !expanded && !fullscreen"
33611
33746
  [style.--pdx-shell-card-bg]="appearance?.card?.background || null"
33612
33747
  [style.--pdx-shell-card-border]="appearance?.card?.borderColor || null"
33613
33748
  [style.--pdx-shell-card-radius]="appearance?.card?.borderRadius || null"
@@ -33647,11 +33782,11 @@ class WidgetShellComponent {
33647
33782
  <mat-icon [praxisIcon]="shell?.icon"></mat-icon>
33648
33783
  }
33649
33784
  <div class="pdx-shell-text">
33650
- <div class="pdx-shell-title-text">
33785
+ <div class="pdx-shell-title-text" [matTooltip]="shellText(shell?.title)">
33651
33786
  {{ shellText(shell?.title) }}
33652
33787
  </div>
33653
33788
  @if (shell?.subtitle) {
33654
- <div class="pdx-shell-subtitle">
33789
+ <div class="pdx-shell-subtitle" [matTooltip]="shellText(shell?.subtitle)">
33655
33790
  {{ shellText(shell?.subtitle) }}
33656
33791
  </div>
33657
33792
  }
@@ -33765,6 +33900,7 @@ class WidgetShellComponent {
33765
33900
  @for (action of overflowHeaderActions; track action.id) {
33766
33901
  <button
33767
33902
  mat-menu-item
33903
+ [disabled]="action.disabled"
33768
33904
  [attr.aria-pressed]="
33769
33905
  action.pressed == null ? null : action.pressed
33770
33906
  "
@@ -33782,6 +33918,18 @@ class WidgetShellComponent {
33782
33918
  }
33783
33919
  </mat-menu>
33784
33920
  </header>
33921
+ } @else if (dragSurfaceInteractive) {
33922
+ <button
33923
+ class="pdx-shell-authoring-drag"
33924
+ praxisIconButton="ms:drag_indicator"
33925
+ size="compact"
33926
+ type="button"
33927
+ [matTooltip]="dragSurfaceLabel || ''"
33928
+ matTooltipPosition="above"
33929
+ [attr.aria-label]="dragSurfaceLabel"
33930
+ (pointerdown)="onAuthoringDragPointerDown($event)"
33931
+ (keydown)="onAuthoringDragKeydown($event)"
33932
+ ></button>
33785
33933
  }
33786
33934
  <div class="pdx-shell-body" [class.hidden]="collapsed">
33787
33935
  <ng-content></ng-content>
@@ -33790,7 +33938,7 @@ class WidgetShellComponent {
33790
33938
  @if (expanded || fullscreen) {
33791
33939
  <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
33792
33940
  }
33793
- `, isInline: true, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var( --pdx-shell-card-bg, var( --pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low) ) );border:1px solid var( --pdx-shell-card-border, var( --pdx-dashboard-card-border, var(--md-sys-color-outline-variant) ) );border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var( --pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06) );overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var( --pdx-shell-header-bg, var(--md-sys-color-surface-container) )}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);color:var( --pdx-shell-subtitle-color, var(--md-sys-color-on-surface-variant, currentColor) );white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;align-items:center;gap:4px}.pdx-shell-window-actions{margin-left:auto}@media(max-width:640px){.pdx-shell-header,.pdx-shell-title{align-items:flex-start}.pdx-shell-text{display:grid;gap:2px}.pdx-shell-title-text,.pdx-shell-subtitle{display:-webkit-box;white-space:normal;overflow-wrap:anywhere;-webkit-box-orient:vertical}.pdx-shell-title-text,.pdx-shell-subtitle{-webkit-line-clamp:2}.pdx-shell-actions{flex:0 0 auto}}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-shell-action--pressed:not(.praxis-icon-button){color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed{height:auto}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.body-fill .pdx-shell-body,.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.collapsed .pdx-shell-body{display:none}.pdx-shell.body-fill .pdx-shell-body{overflow:hidden}.pdx-shell.body-scroll .pdx-shell-body{overflow:auto}.pdx-shell.body-fill .pdx-shell-body>*,.pdx-shell.body-scroll .pdx-shell-body>*,.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen{position:fixed;inset:0;width:auto;height:auto;transform:none;border-radius:0;z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
33941
+ `, isInline: true, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{box-sizing:border-box;position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var( --pdx-shell-card-bg, var( --pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low) ) );border:1px solid var( --pdx-shell-card-border, var( --pdx-dashboard-card-border, var(--md-sys-color-outline-variant) ) );border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var( --pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06) );overflow:hidden}.pdx-shell-header{flex-shrink:0;display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var( --pdx-shell-header-bg, var(--md-sys-color-surface-container) )}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-authoring-drag{flex:0 0 auto;align-self:flex-start;margin:4px 6px 0;z-index:2;cursor:grab;touch-action:none}.pdx-shell-authoring-drag:active{cursor:grabbing}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1 1 14rem;max-width:100%;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{flex:0 0 auto;color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0;flex:1}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);color:var( --pdx-shell-subtitle-color, var(--md-sys-color-on-surface-variant, currentColor) );white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;flex-wrap:wrap;align-items:center;gap:4px;max-width:100%}.pdx-shell-actions{margin-left:auto;min-width:0}.pdx-shell-actions>button{max-width:100%}.pdx-shell-window-actions{margin-left:auto}.pdx-shell-text{display:grid;gap:2px}.pdx-shell-title-text,.pdx-shell-subtitle{display:-webkit-box;white-space:normal;overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-shell-action--pressed:not(.praxis-icon-button){color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed{height:auto}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.body-fill .pdx-shell-body,.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.collapsed .pdx-shell-body{display:none}.pdx-shell.body-fill .pdx-shell-body{overflow:hidden}.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.body-scroll.pdx-shell--scroll-recovery{overflow:auto}.pdx-shell.body-scroll.pdx-shell--scroll-recovery>.pdx-shell-body{flex:0 0 auto;overflow:visible}.pdx-shell.body-fill .pdx-shell-body>*,.pdx-shell.body-scroll .pdx-shell-body>*,.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded,.pdx-shell-overlay-surface.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen,.pdx-shell-overlay-surface.fullscreen{position:fixed;inset:0;width:auto;height:auto;transform:none;border-radius:0;z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-overlay-surface{background:var(--md-sys-color-surface);border-radius:var(--pdx-dashboard-card-radius, 16px);pointer-events:none}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
33794
33942
  }
33795
33943
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: WidgetShellComponent, decorators: [{
33796
33944
  type: Component,
@@ -33802,9 +33950,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
33802
33950
  MatTooltipModule,
33803
33951
  PraxisIconButtonComponent,
33804
33952
  PraxisIconDirective,
33805
- ], providers: [providePraxisI18nConfig(WIDGET_SHELL_I18N_CONFIG)], template: `
33953
+ ], providers: [providePraxisI18nConfig(WIDGET_SHELL_I18N_CONFIG)], host: { '(keydown.escape)': 'onOverlayEscape($event)' }, template: `
33954
+ @if (expanded || fullscreen) {
33955
+ <div
33956
+ class="pdx-shell-overlay-surface"
33957
+ [class.expanded]="expanded"
33958
+ [class.fullscreen]="fullscreen"
33959
+ [style.border-radius]="fullscreen ? null : appearance?.card?.borderRadius || null"
33960
+ aria-hidden="true"
33961
+ ></div>
33962
+ }
33806
33963
  <section
33807
33964
  class="pdx-shell"
33965
+ [attr.tabindex]="expanded || fullscreen ? -1 : null"
33808
33966
  [class.no-shell]="!shellEnabled"
33809
33967
  [class.dashboard]="shellEnabled"
33810
33968
  [class.collapsed]="collapsed"
@@ -33812,6 +33970,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
33812
33970
  [class.fullscreen]="fullscreen"
33813
33971
  [class.body-fill]="shell?.bodyLayout === 'fill'"
33814
33972
  [class.body-scroll]="shell?.bodyLayout === 'scroll'"
33973
+ [class.pdx-shell--scroll-recovery]="scrollRecovery() && !collapsed && !expanded && !fullscreen"
33815
33974
  [style.--pdx-shell-card-bg]="appearance?.card?.background || null"
33816
33975
  [style.--pdx-shell-card-border]="appearance?.card?.borderColor || null"
33817
33976
  [style.--pdx-shell-card-radius]="appearance?.card?.borderRadius || null"
@@ -33851,11 +34010,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
33851
34010
  <mat-icon [praxisIcon]="shell?.icon"></mat-icon>
33852
34011
  }
33853
34012
  <div class="pdx-shell-text">
33854
- <div class="pdx-shell-title-text">
34013
+ <div class="pdx-shell-title-text" [matTooltip]="shellText(shell?.title)">
33855
34014
  {{ shellText(shell?.title) }}
33856
34015
  </div>
33857
34016
  @if (shell?.subtitle) {
33858
- <div class="pdx-shell-subtitle">
34017
+ <div class="pdx-shell-subtitle" [matTooltip]="shellText(shell?.subtitle)">
33859
34018
  {{ shellText(shell?.subtitle) }}
33860
34019
  </div>
33861
34020
  }
@@ -33969,6 +34128,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
33969
34128
  @for (action of overflowHeaderActions; track action.id) {
33970
34129
  <button
33971
34130
  mat-menu-item
34131
+ [disabled]="action.disabled"
33972
34132
  [attr.aria-pressed]="
33973
34133
  action.pressed == null ? null : action.pressed
33974
34134
  "
@@ -33986,6 +34146,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
33986
34146
  }
33987
34147
  </mat-menu>
33988
34148
  </header>
34149
+ } @else if (dragSurfaceInteractive) {
34150
+ <button
34151
+ class="pdx-shell-authoring-drag"
34152
+ praxisIconButton="ms:drag_indicator"
34153
+ size="compact"
34154
+ type="button"
34155
+ [matTooltip]="dragSurfaceLabel || ''"
34156
+ matTooltipPosition="above"
34157
+ [attr.aria-label]="dragSurfaceLabel"
34158
+ (pointerdown)="onAuthoringDragPointerDown($event)"
34159
+ (keydown)="onAuthoringDragKeydown($event)"
34160
+ ></button>
33989
34161
  }
33990
34162
  <div class="pdx-shell-body" [class.hidden]="collapsed">
33991
34163
  <ng-content></ng-content>
@@ -33994,8 +34166,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
33994
34166
  @if (expanded || fullscreen) {
33995
34167
  <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
33996
34168
  }
33997
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var( --pdx-shell-card-bg, var( --pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low) ) );border:1px solid var( --pdx-shell-card-border, var( --pdx-dashboard-card-border, var(--md-sys-color-outline-variant) ) );border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var( --pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06) );overflow:hidden}.pdx-shell-header{display:flex;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var( --pdx-shell-header-bg, var(--md-sys-color-surface-container) )}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);color:var( --pdx-shell-subtitle-color, var(--md-sys-color-on-surface-variant, currentColor) );white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;align-items:center;gap:4px}.pdx-shell-window-actions{margin-left:auto}@media(max-width:640px){.pdx-shell-header,.pdx-shell-title{align-items:flex-start}.pdx-shell-text{display:grid;gap:2px}.pdx-shell-title-text,.pdx-shell-subtitle{display:-webkit-box;white-space:normal;overflow-wrap:anywhere;-webkit-box-orient:vertical}.pdx-shell-title-text,.pdx-shell-subtitle{-webkit-line-clamp:2}.pdx-shell-actions{flex:0 0 auto}}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-shell-action--pressed:not(.praxis-icon-button){color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed{height:auto}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.body-fill .pdx-shell-body,.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.collapsed .pdx-shell-body{display:none}.pdx-shell.body-fill .pdx-shell-body{overflow:hidden}.pdx-shell.body-scroll .pdx-shell-body{overflow:auto}.pdx-shell.body-fill .pdx-shell-body>*,.pdx-shell.body-scroll .pdx-shell-body>*,.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen{position:fixed;inset:0;width:auto;height:auto;transform:none;border-radius:0;z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"] }]
33998
- }], propDecorators: { hostCollapsed: [{
34169
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{box-sizing:border-box;position:relative;height:100%;display:flex;flex-direction:column}.pdx-shell.no-shell{background:transparent;border:none;border-radius:0;box-shadow:none}.pdx-shell.dashboard{background:var( --pdx-shell-card-bg, var( --pdx-dashboard-card-bg, var(--md-sys-color-surface-container-low) ) );border:1px solid var( --pdx-shell-card-border, var( --pdx-dashboard-card-border, var(--md-sys-color-outline-variant) ) );border-radius:var(--pdx-shell-card-radius, 12px);box-shadow:var( --pdx-shell-card-shadow, 0 4px 12px rgba(15, 23, 42, .06) );overflow:hidden}.pdx-shell-header{flex-shrink:0;display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:8px 10px 7px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var( --pdx-shell-header-bg, var(--md-sys-color-surface-container) )}.pdx-shell-header--drag-enabled{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pdx-shell-header--drag-enabled:active{cursor:grabbing}.pdx-shell-header--drag-enabled:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 72%,white 28%);outline-offset:-2px}.pdx-shell-authoring-drag{flex:0 0 auto;align-self:flex-start;margin:4px 6px 0;z-index:2;cursor:grab;touch-action:none}.pdx-shell-authoring-drag:active{cursor:grabbing}.pdx-shell-title{display:flex;align-items:center;gap:8px;min-width:0;flex:1 1 14rem;max-width:100%;color:var(--pdx-shell-title-color, inherit)}.pdx-shell-title mat-icon{flex:0 0 auto;color:var(--pdx-shell-icon-color, currentColor)}.pdx-shell-text{min-width:0;flex:1}.pdx-shell-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 13px);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-subtitle{font-size:var(--pdx-shell-subtitle-size, 11px);color:var( --pdx-shell-subtitle-color, var(--md-sys-color-on-surface-variant, currentColor) );white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pdx-shell-actions,.pdx-shell-window-actions{display:flex;flex-wrap:wrap;align-items:center;gap:4px;max-width:100%}.pdx-shell-actions{margin-left:auto;min-width:0}.pdx-shell-actions>button{max-width:100%}.pdx-shell-window-actions{margin-left:auto}.pdx-shell-text{display:grid;gap:2px}.pdx-shell-title-text,.pdx-shell-subtitle{display:-webkit-box;white-space:normal;overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2}.pdx-action-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-action-text{padding:0 8px}.pdx-shell-action--pressed:not(.praxis-icon-button){color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)}.pdx-action-label{font-size:12px;font-weight:500}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 8px 10px 10px 10px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit)}.pdx-shell.no-shell .pdx-shell-body{padding:0}.pdx-shell-body.hidden{display:none}.pdx-shell.collapsed{height:auto}.pdx-shell.collapsed .pdx-shell-header{border-bottom-color:transparent}.pdx-shell.body-fill .pdx-shell-body,.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.expanded .pdx-shell-body,.pdx-shell.fullscreen .pdx-shell-body{overflow:auto;display:flex;flex-direction:column;min-height:0}.pdx-shell.collapsed .pdx-shell-body{display:none}.pdx-shell.body-fill .pdx-shell-body{overflow:hidden}.pdx-shell.body-scroll .pdx-shell-body,.pdx-shell.body-scroll.pdx-shell--scroll-recovery{overflow:auto}.pdx-shell.body-scroll.pdx-shell--scroll-recovery>.pdx-shell-body{flex:0 0 auto;overflow:visible}.pdx-shell.body-fill .pdx-shell-body>*,.pdx-shell.body-scroll .pdx-shell-body>*,.pdx-shell.expanded .pdx-shell-body>*,.pdx-shell.fullscreen .pdx-shell-body>*{flex:1 1 auto;min-height:0;width:100%}.pdx-shell.expanded,.pdx-shell-overlay-surface.expanded{position:fixed;top:10vh;left:50%;width:min(920px,92vw);height:min(640px,82vh);transform:translate(-50%);z-index:var(--praxis-layer-widget-shell-expanded, 1290);box-shadow:var(--mat-elevation-level8)}.pdx-shell.fullscreen,.pdx-shell-overlay-surface.fullscreen{position:fixed;inset:0;width:auto;height:auto;transform:none;border-radius:0;z-index:var(--praxis-layer-widget-shell-fullscreen, 1291);box-shadow:var(--mat-elevation-level8)}.pdx-shell-overlay-surface{background:var(--md-sys-color-surface);border-radius:var(--pdx-dashboard-card-radius, 16px);pointer-events:none}.pdx-shell-backdrop{position:fixed;inset:0;z-index:var(--praxis-layer-widget-shell-backdrop, 1280);background:#0000008c;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"] }]
34170
+ }], ctorParameters: () => [], propDecorators: { hostCollapsed: [{
33999
34171
  type: HostBinding,
34000
34172
  args: ['class.pdx-widget-shell-collapsed']
34001
34173
  }], shell: [{
@@ -38450,6 +38622,11 @@ function clone(value) {
38450
38622
  }
38451
38623
 
38452
38624
  class DynamicWidgetContextToolbarComponent {
38625
+ showResize = input(false, ...(ngDevMode ? [{ debugName: "showResize" }] : /* istanbul ignore next */ []));
38626
+ resizeLabel = input('', ...(ngDevMode ? [{ debugName: "resizeLabel" }] : /* istanbul ignore next */ []));
38627
+ resizeControls = input(null, ...(ngDevMode ? [{ debugName: "resizeControls" }] : /* istanbul ignore next */ []));
38628
+ resizeExpanded = input(false, ...(ngDevMode ? [{ debugName: "resizeExpanded" }] : /* istanbul ignore next */ []));
38629
+ resize = output();
38453
38630
  toolbarLabel = '';
38454
38631
  contextLabel = '';
38455
38632
  contextTooltip = '';
@@ -38471,7 +38648,7 @@ class DynamicWidgetContextToolbarComponent {
38471
38648
  shellSettings = new EventEmitter();
38472
38649
  remove = new EventEmitter();
38473
38650
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicWidgetContextToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
38474
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicWidgetContextToolbarComponent, isStandalone: true, selector: "praxis-dynamic-widget-context-toolbar", inputs: { toolbarLabel: { classPropertyName: "toolbarLabel", publicName: "toolbarLabel", isSignal: false, isRequired: false, transformFunction: null }, contextLabel: { classPropertyName: "contextLabel", publicName: "contextLabel", isSignal: false, isRequired: false, transformFunction: null }, contextTooltip: { classPropertyName: "contextTooltip", publicName: "contextTooltip", isSignal: false, isRequired: false, transformFunction: null }, showAssistant: { classPropertyName: "showAssistant", publicName: "showAssistant", isSignal: false, isRequired: false, transformFunction: null }, assistantLabel: { classPropertyName: "assistantLabel", publicName: "assistantLabel", isSignal: false, isRequired: false, transformFunction: null }, assistantTooltip: { classPropertyName: "assistantTooltip", publicName: "assistantTooltip", isSignal: false, isRequired: false, transformFunction: null }, showComponentSettings: { classPropertyName: "showComponentSettings", publicName: "showComponentSettings", isSignal: false, isRequired: false, transformFunction: null }, componentSettingsBusy: { classPropertyName: "componentSettingsBusy", publicName: "componentSettingsBusy", isSignal: true, isRequired: false, transformFunction: null }, componentSettingsLabel: { classPropertyName: "componentSettingsLabel", publicName: "componentSettingsLabel", isSignal: false, isRequired: false, transformFunction: null }, componentSettingsTooltip: { classPropertyName: "componentSettingsTooltip", publicName: "componentSettingsTooltip", isSignal: false, isRequired: false, transformFunction: null }, showShellSettings: { classPropertyName: "showShellSettings", publicName: "showShellSettings", isSignal: false, isRequired: false, transformFunction: null }, shellSettingsLabel: { classPropertyName: "shellSettingsLabel", publicName: "shellSettingsLabel", isSignal: false, isRequired: false, transformFunction: null }, shellSettingsTooltip: { classPropertyName: "shellSettingsTooltip", publicName: "shellSettingsTooltip", isSignal: false, isRequired: false, transformFunction: null }, showRemove: { classPropertyName: "showRemove", publicName: "showRemove", isSignal: false, isRequired: false, transformFunction: null }, moreActionsLabel: { classPropertyName: "moreActionsLabel", publicName: "moreActionsLabel", isSignal: false, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { assistant: "assistant", componentSettings: "componentSettings", shellSettings: "shellSettings", remove: "remove" }, ngImport: i0, template: `
38651
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicWidgetContextToolbarComponent, isStandalone: true, selector: "praxis-dynamic-widget-context-toolbar", inputs: { showResize: { classPropertyName: "showResize", publicName: "showResize", isSignal: true, isRequired: false, transformFunction: null }, resizeLabel: { classPropertyName: "resizeLabel", publicName: "resizeLabel", isSignal: true, isRequired: false, transformFunction: null }, resizeControls: { classPropertyName: "resizeControls", publicName: "resizeControls", isSignal: true, isRequired: false, transformFunction: null }, resizeExpanded: { classPropertyName: "resizeExpanded", publicName: "resizeExpanded", isSignal: true, isRequired: false, transformFunction: null }, toolbarLabel: { classPropertyName: "toolbarLabel", publicName: "toolbarLabel", isSignal: false, isRequired: false, transformFunction: null }, contextLabel: { classPropertyName: "contextLabel", publicName: "contextLabel", isSignal: false, isRequired: false, transformFunction: null }, contextTooltip: { classPropertyName: "contextTooltip", publicName: "contextTooltip", isSignal: false, isRequired: false, transformFunction: null }, showAssistant: { classPropertyName: "showAssistant", publicName: "showAssistant", isSignal: false, isRequired: false, transformFunction: null }, assistantLabel: { classPropertyName: "assistantLabel", publicName: "assistantLabel", isSignal: false, isRequired: false, transformFunction: null }, assistantTooltip: { classPropertyName: "assistantTooltip", publicName: "assistantTooltip", isSignal: false, isRequired: false, transformFunction: null }, showComponentSettings: { classPropertyName: "showComponentSettings", publicName: "showComponentSettings", isSignal: false, isRequired: false, transformFunction: null }, componentSettingsBusy: { classPropertyName: "componentSettingsBusy", publicName: "componentSettingsBusy", isSignal: true, isRequired: false, transformFunction: null }, componentSettingsLabel: { classPropertyName: "componentSettingsLabel", publicName: "componentSettingsLabel", isSignal: false, isRequired: false, transformFunction: null }, componentSettingsTooltip: { classPropertyName: "componentSettingsTooltip", publicName: "componentSettingsTooltip", isSignal: false, isRequired: false, transformFunction: null }, showShellSettings: { classPropertyName: "showShellSettings", publicName: "showShellSettings", isSignal: false, isRequired: false, transformFunction: null }, shellSettingsLabel: { classPropertyName: "shellSettingsLabel", publicName: "shellSettingsLabel", isSignal: false, isRequired: false, transformFunction: null }, shellSettingsTooltip: { classPropertyName: "shellSettingsTooltip", publicName: "shellSettingsTooltip", isSignal: false, isRequired: false, transformFunction: null }, showRemove: { classPropertyName: "showRemove", publicName: "showRemove", isSignal: false, isRequired: false, transformFunction: null }, moreActionsLabel: { classPropertyName: "moreActionsLabel", publicName: "moreActionsLabel", isSignal: false, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { resize: "resize", assistant: "assistant", componentSettings: "componentSettings", shellSettings: "shellSettings", remove: "remove" }, ngImport: i0, template: `
38475
38652
  <div
38476
38653
  class="pdx-widget-context-toolbar"
38477
38654
  [class.pdx-widget-context-toolbar--with-context]="!!contextLabel"
@@ -38490,6 +38667,13 @@ class DynamicWidgetContextToolbarComponent {
38490
38667
  {{ contextLabel }}
38491
38668
  </span>
38492
38669
  }
38670
+ @if (showResize()) {
38671
+ <button praxisIconButton="ms:open_in_full" type="button"
38672
+ data-testid="dynamic-widget-resize"
38673
+ [matTooltip]="resizeLabel()" [attr.aria-label]="resizeLabel()"
38674
+ [attr.aria-controls]="resizeControls()" [attr.aria-expanded]="resizeExpanded()"
38675
+ (click)="resize.emit()"></button>
38676
+ }
38493
38677
  @if (showAssistant) {
38494
38678
  <button
38495
38679
  praxisIconButton="auto_awesome"
@@ -38543,7 +38727,7 @@ class DynamicWidgetContextToolbarComponent {
38543
38727
  </mat-menu>
38544
38728
  }
38545
38729
  </div>
38546
- `, isInline: true, styles: [".pdx-widget-context-toolbar{position:absolute;top:-19px;right:12px;z-index:4;display:inline-flex;align-items:center;gap:4px;min-height:34px;padding:2px 4px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 88%,transparent);box-shadow:0 10px 28px #0f172a38,0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.pdx-widget-context-toolbar--with-context{border-radius:18px}.pdx-widget-context-toolbar__context{display:inline-flex;align-items:center;align-self:stretch;max-width:180px;padding:0 8px 0 10px;border-right:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 64%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:700;letter-spacing:.01em;line-height:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
38730
+ `, isInline: true, styles: [".pdx-widget-context-toolbar{position:absolute;top:-19px;right:12px;z-index:4;display:inline-flex;align-items:center;gap:4px;min-height:34px;padding:2px 4px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 88%,transparent);box-shadow:0 10px 28px #0f172a38,0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.pdx-widget-context-toolbar--with-context{border-radius:18px}.pdx-widget-context-toolbar__context{display:inline-flex;align-items:center;align-self:stretch;max-width:180px;padding:0 8px 0 10px;border-right:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 64%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:700;letter-spacing:.01em;line-height:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
38547
38731
  }
38548
38732
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicWidgetContextToolbarComponent, decorators: [{
38549
38733
  type: Component,
@@ -38572,6 +38756,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
38572
38756
  {{ contextLabel }}
38573
38757
  </span>
38574
38758
  }
38759
+ @if (showResize()) {
38760
+ <button praxisIconButton="ms:open_in_full" type="button"
38761
+ data-testid="dynamic-widget-resize"
38762
+ [matTooltip]="resizeLabel()" [attr.aria-label]="resizeLabel()"
38763
+ [attr.aria-controls]="resizeControls()" [attr.aria-expanded]="resizeExpanded()"
38764
+ (click)="resize.emit()"></button>
38765
+ }
38575
38766
  @if (showAssistant) {
38576
38767
  <button
38577
38768
  praxisIconButton="auto_awesome"
@@ -38626,7 +38817,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
38626
38817
  }
38627
38818
  </div>
38628
38819
  `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".pdx-widget-context-toolbar{position:absolute;top:-19px;right:12px;z-index:4;display:inline-flex;align-items:center;gap:4px;min-height:34px;padding:2px 4px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 88%,transparent);box-shadow:0 10px 28px #0f172a38,0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.pdx-widget-context-toolbar--with-context{border-radius:18px}.pdx-widget-context-toolbar__context{display:inline-flex;align-items:center;align-self:stretch;max-width:180px;padding:0 8px 0 10px;border-right:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 64%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:700;letter-spacing:.01em;line-height:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"] }]
38629
- }], propDecorators: { toolbarLabel: [{
38820
+ }], propDecorators: { showResize: [{ type: i0.Input, args: [{ isSignal: true, alias: "showResize", required: false }] }], resizeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizeLabel", required: false }] }], resizeControls: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizeControls", required: false }] }], resizeExpanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizeExpanded", required: false }] }], resize: [{ type: i0.Output, args: ["resize"] }], toolbarLabel: [{
38630
38821
  type: Input
38631
38822
  }], contextLabel: [{
38632
38823
  type: Input
@@ -38671,6 +38862,14 @@ const DYNAMIC_WIDGET_PAGE_I18N_CONFIG = {
38671
38862
  namespaces: {
38672
38863
  [DYNAMIC_WIDGET_PAGE_I18N_NAMESPACE]: {
38673
38864
  'pt-BR': {
38865
+ 'heightValidation.measureFirst': 'Use altura Automática para aplicar a nova geometria; depois reabra o editor para definir a altura ajustável.',
38866
+ 'heightValidation.minimum': 'Use pelo menos {{height}}px nesta largura. Ajuste a altura/máximo ou use Automática.',
38867
+ 'announcements.contentSize': '{{action}}. Largura {{columns}} colunas, altura {{height}} pixels, recuo superior {{top}} pixels.',
38868
+ 'resizeFeedback.valid': 'Ajuste disponível',
38869
+ 'resizeFeedback.minimum': 'Tamanho mínimo atingido',
38870
+ 'resizeFeedback.blocked': 'Limite excedido — prévia limitada ao espaço disponível',
38871
+ 'resizeFeedback.committedLimit': 'Layout ajustado até o limite permitido',
38872
+ 'resizeFeedback.unchanged': 'Tamanho mantido — nenhum ajuste aplicado',
38674
38873
  'controls.pageSettings': 'Configurar página',
38675
38874
  'controls.componentSettings': 'Configurar conteúdo',
38676
38875
  'controls.componentSettingsTooltip': 'Abrir configurações do componente',
@@ -38691,6 +38890,11 @@ const DYNAMIC_WIDGET_PAGE_I18N_CONFIG = {
38691
38890
  'controls.widgetLayoutToolbar': 'Ações de layout do widget',
38692
38891
  'controls.dragWidget': 'Arrastar widget',
38693
38892
  'controls.resizeWidget': 'Redimensionar widget',
38893
+ 'controls.resizeAlternative': 'Controles alternativos de tamanho',
38894
+ 'controls.resizeSelect': 'Selecione um widget',
38895
+ 'controls.resizeClose': 'Fechar controles de tamanho',
38896
+ 'controls.resizeContextHelp': 'Arraste um controle ou use as setas do teclado. Esc fecha os controles.',
38897
+ 'controls.resizeHelp': 'Selecione o widget. Arraste uma borda ou canto pelos botões, ou use as setas do teclado.',
38694
38898
  'controls.resize.north': 'Redimensionar widget pela borda superior',
38695
38899
  'controls.resize.south': 'Redimensionar widget pela borda inferior',
38696
38900
  'controls.resize.east': 'Redimensionar widget pela borda direita',
@@ -38702,11 +38906,20 @@ const DYNAMIC_WIDGET_PAGE_I18N_CONFIG = {
38702
38906
  'announcements.moved': 'Widget movido: {{widget}}',
38703
38907
  'announcements.swapped': 'Widget trocado com {{target}}: {{widget}}',
38704
38908
  'announcements.resized': 'Widget redimensionado: {{widget}}',
38909
+ 'announcements.interactionCancelled': 'Alteração de layout cancelada.',
38705
38910
  'announcements.position': '{{action}} para coluna {{col}}, linha {{row}}, largura {{colSpan}}, altura {{rowSpan}}.',
38706
38911
  'announcements.dragBlocked': 'Movimento bloqueado: o widget colidiria com outro item.',
38707
38912
  'announcements.resizeBlocked': 'Redimensionamento bloqueado: o widget colidiria com outro item.',
38708
38913
  },
38709
38914
  'en-US': {
38915
+ 'heightValidation.measureFirst': 'Use Automatic height to apply the new geometry, then reopen the editor to set an adjustable height.',
38916
+ 'heightValidation.minimum': 'Use at least {{height}}px at this width. Adjust the height/maximum, or use Automatic.',
38917
+ 'announcements.contentSize': '{{action}}. Width {{columns}} columns, height {{height}} pixels, top inset {{top}} pixels.',
38918
+ 'resizeFeedback.valid': 'Resize available',
38919
+ 'resizeFeedback.minimum': 'Minimum size reached',
38920
+ 'resizeFeedback.blocked': 'Limit exceeded — preview constrained to available space',
38921
+ 'resizeFeedback.committedLimit': 'Layout resized to the allowed limit',
38922
+ 'resizeFeedback.unchanged': 'Size unchanged — no adjustment applied',
38710
38923
  'controls.pageSettings': 'Configure page',
38711
38924
  'controls.componentSettings': 'Configure content',
38712
38925
  'controls.componentSettingsTooltip': 'Open component settings',
@@ -38727,6 +38940,11 @@ const DYNAMIC_WIDGET_PAGE_I18N_CONFIG = {
38727
38940
  'controls.widgetLayoutToolbar': 'Widget layout actions',
38728
38941
  'controls.dragWidget': 'Drag widget',
38729
38942
  'controls.resizeWidget': 'Resize widget',
38943
+ 'controls.resizeAlternative': 'Alternative resize controls',
38944
+ 'controls.resizeSelect': 'Select a widget',
38945
+ 'controls.resizeClose': 'Close resize controls',
38946
+ 'controls.resizeContextHelp': 'Drag a control or use the arrow keys. Esc closes the controls.',
38947
+ 'controls.resizeHelp': 'Select the widget. Drag an edge or corner using the buttons, or use the arrow keys.',
38730
38948
  'controls.resize.north': 'Resize widget from the top edge',
38731
38949
  'controls.resize.south': 'Resize widget from the bottom edge',
38732
38950
  'controls.resize.east': 'Resize widget from the right edge',
@@ -38738,6 +38956,7 @@ const DYNAMIC_WIDGET_PAGE_I18N_CONFIG = {
38738
38956
  'announcements.moved': 'Widget moved: {{widget}}',
38739
38957
  'announcements.swapped': 'Widget swapped with {{target}}: {{widget}}',
38740
38958
  'announcements.resized': 'Widget resized: {{widget}}',
38959
+ 'announcements.interactionCancelled': 'Layout change cancelled.',
38741
38960
  'announcements.position': '{{action}} to column {{col}}, row {{row}}, width {{colSpan}}, height {{rowSpan}}.',
38742
38961
  'announcements.dragBlocked': 'Move blocked: the widget would overlap another item.',
38743
38962
  'announcements.resizeBlocked': 'Resize blocked: the widget would overlap another item.',
@@ -38746,15 +38965,212 @@ const DYNAMIC_WIDGET_PAGE_I18N_CONFIG = {
38746
38965
  },
38747
38966
  };
38748
38967
 
38968
+ /** Internal materialization of the canonical content-row size, never DOM state. */
38969
+ function contentSize(item) {
38970
+ const size = item.contentSize;
38971
+ if (!size || size === 'auto' || !Number.isFinite(size.heightPx) || size.heightPx <= 0)
38972
+ return null;
38973
+ const { min, max } = contentHeightLimits(item);
38974
+ return {
38975
+ heightPx: Math.min(max, Math.max(min, Math.round(size.heightPx))),
38976
+ offsetTopPx: Number.isFinite(size.offsetTopPx) ? Math.max(0, Math.round(size.offsetTopPx)) : 0,
38977
+ };
38978
+ }
38979
+ function contentHeightLimits(item) {
38980
+ const c = item.constraints;
38981
+ const min = Number.isFinite(c?.minHeightPx) ? Math.max(160, Math.round(c.minHeightPx)) : 160;
38982
+ const max = Number.isFinite(c?.maxHeightPx) ? Math.max(min, Math.round(c.maxHeightPx)) : Number.MAX_SAFE_INTEGER;
38983
+ return { min, max };
38984
+ }
38985
+ /** Pixel delta applies to the captured outer rectangle, not changing rowSpan.
38986
+ * North growth stops at the track origin; shrinking retains the opposite edge.
38987
+ */
38988
+ function resizeContentHeight(item, startHeight, delta, north, renderedMinimum = 0) {
38989
+ if (!delta)
38990
+ return { item, constrained: false, minimum: false };
38991
+ const size = contentSize(item);
38992
+ const top = size?.offsetTopPx ?? 0;
38993
+ const height = size?.heightPx ?? startHeight;
38994
+ const limits = contentHeightLimits(item);
38995
+ const min = Math.max(limits.min, Number.isFinite(renderedMinimum) ? Math.ceil(renderedMinimum) : 0);
38996
+ // North gestures also have a spatial maximum: the fixed bottom minus the
38997
+ // track origin. A late content minimum cannot move that opposite edge.
38998
+ const max = north ? Math.min(limits.max, height + top) : limits.max;
38999
+ // A viewport observation must never override an authored maximum or leak
39000
+ // into persisted constraints. Leave an impossible gesture unchanged.
39001
+ if (min > max)
39002
+ return { item, constrained: true, minimum: true };
39003
+ const requested = height + (north ? -delta : delta);
39004
+ if (requested < height && height <= min)
39005
+ return { item, constrained: true, minimum: true };
39006
+ const next = Math.max(min, Math.min(max, requested));
39007
+ if (next === height)
39008
+ return { item, constrained: next !== requested, minimum: next === min };
39009
+ return {
39010
+ item: { ...item, contentSize: { heightPx: Math.round(next), offsetTopPx: north ? Math.max(0, Math.round(top + height - next)) : top } },
39011
+ constrained: next !== requested,
39012
+ minimum: next === min,
39013
+ };
39014
+ }
39015
+
39016
+ /** CSSOM resolves grid tracks to pixels. Unresolved/unsupported lists use the fallback. */
39017
+ function readCanvasTrackSizes(value) {
39018
+ const tracks = value.trim().split(/\s+/);
39019
+ if (!tracks.length || tracks.some((track) => !/^\d+(?:\.\d+)?px$/.test(track))) {
39020
+ return [];
39021
+ }
39022
+ return tracks.map((track) => Number.parseFloat(track));
39023
+ }
39024
+ /**
39025
+ * Snap the moved edge to the nearest rendered track, retaining the pointer's
39026
+ * initial offset. Resize uses the moving end edge for south/east handles, not
39027
+ * the widget origin. Snapshotting avoids feedback from transient layout previews.
39028
+ */
39029
+ function canvasAxisDelta(axis, startIndex, displacement, edge = 'start') {
39030
+ const fallback = Math.max(1, axis.fallbackSize);
39031
+ const gap = Math.max(0, axis.gap);
39032
+ const positions = [];
39033
+ let offset = 0;
39034
+ for (const size of axis.sizes) {
39035
+ positions.push(offset + (edge === 'end' ? size : 0));
39036
+ offset += size + gap;
39037
+ }
39038
+ const extensionStart = offset + (edge === 'end' ? fallback : 0);
39039
+ const step = fallback + gap;
39040
+ const positionAt = (index) => positions[index] ?? extensionStart + (index - positions.length) * step;
39041
+ const target = positionAt(startIndex) + displacement;
39042
+ let nearest = startIndex;
39043
+ let distance = Math.abs(displacement);
39044
+ const consider = (index, position) => {
39045
+ const nextDistance = Math.abs(position - target);
39046
+ // Prefer the original track on ties, including zero-height empty rows.
39047
+ if (nextDistance < distance) {
39048
+ nearest = index;
39049
+ distance = nextDistance;
39050
+ }
39051
+ };
39052
+ positions.forEach((position, index) => consider(index, position));
39053
+ const extensionIndex = positions.length + Math.max(0, Math.round((target - extensionStart) / step));
39054
+ consider(extensionIndex, positionAt(extensionIndex));
39055
+ return nearest - startIndex;
39056
+ }
39057
+
39058
+ const right = (item) => item.col + item.colSpan;
39059
+ const bottom = (item) => item.row + item.rowSpan;
39060
+ const overlaps = (a, b) => a.col < right(b) && right(a) > b.col && a.row < bottom(b) && bottom(a) > b.row;
39061
+ /** Resize only by yielding space, never by pushing unrelated items or swapping.
39062
+ * Opposite edges stay anchored. Ambiguous corner collisions fail closed. Inputs
39063
+ * are the normalized effective device layout, never the transient preview.
39064
+ */
39065
+ function resolveCanvasResizePlacement(key, candidate, source) {
39066
+ const start = source[key];
39067
+ const desired = { ...candidate };
39068
+ const limitedBy = new Set();
39069
+ const rejected = new Set();
39070
+ const sideOf = (other) => {
39071
+ const sides = [];
39072
+ if (right(start) <= other.col && right(desired) > right(start))
39073
+ sides.push('east');
39074
+ if (start.col >= right(other) && desired.col < start.col)
39075
+ sides.push('west');
39076
+ if (bottom(start) <= other.row && bottom(desired) > bottom(start))
39077
+ sides.push('south');
39078
+ if (start.row >= bottom(other) && desired.row < start.row)
39079
+ sides.push('north');
39080
+ return sides.length === 1 ? sides[0] : null;
39081
+ };
39082
+ let left = desired.col, top = desired.row, end = right(desired), foot = bottom(desired);
39083
+ for (const [otherKey, other] of Object.entries(source)) {
39084
+ if (otherKey === key || !overlaps(desired, other))
39085
+ continue;
39086
+ const side = sideOf(other);
39087
+ const constraints = other.constraints;
39088
+ const horizontal = side === 'east' || side === 'west';
39089
+ const minimum = Math.max(1, (horizontal ? constraints?.minColSpan : constraints?.minRowSpan) || 1);
39090
+ const locked = constraints?.lockSize || (constraints?.lockPosition && (side === 'east' || side === 'south'));
39091
+ if (!side || overlaps(start, other)) {
39092
+ rejected.add(otherKey);
39093
+ continue;
39094
+ }
39095
+ const available = locked ? (horizontal ? other.colSpan : other.rowSpan) : minimum;
39096
+ const before = [left, top, end, foot].join();
39097
+ if (side === 'east')
39098
+ end = Math.min(end, right(other) - available);
39099
+ if (side === 'west')
39100
+ left = Math.max(left, other.col + available);
39101
+ if (side === 'south')
39102
+ foot = Math.min(foot, bottom(other) - available);
39103
+ if (side === 'north')
39104
+ top = Math.max(top, other.row + available);
39105
+ if (before !== [left, top, end, foot].join()) {
39106
+ (locked ? rejected : limitedBy).add(otherKey);
39107
+ }
39108
+ }
39109
+ let primary = { ...desired, col: left, row: top, colSpan: end - left, rowSpan: foot - top };
39110
+ // A pre-existing invalid layout or an ambiguous corner must not be repaired by
39111
+ // this gesture. Also reject any clamp that would violate the selected minimum.
39112
+ const ambiguous = [...rejected].some(otherKey => !sideOf(source[otherKey]) || overlaps(start, source[otherKey]));
39113
+ if (ambiguous || primary.colSpan < Math.max(1, start.constraints?.minColSpan || 1)
39114
+ || primary.rowSpan < Math.max(1, start.constraints?.minRowSpan || 1))
39115
+ primary = { ...start };
39116
+ const items = { [key]: primary };
39117
+ const minimumKeys = new Set();
39118
+ for (const [otherKey, other] of Object.entries(source)) {
39119
+ if (otherKey === key || !overlaps(primary, other))
39120
+ continue;
39121
+ const side = sideOf(other);
39122
+ const next = { ...other };
39123
+ if (side === 'east') {
39124
+ next.col = right(primary);
39125
+ next.colSpan = right(other) - next.col;
39126
+ }
39127
+ if (side === 'west')
39128
+ next.colSpan = primary.col - other.col;
39129
+ if (side === 'south') {
39130
+ next.row = bottom(primary);
39131
+ next.rowSpan = bottom(other) - next.row;
39132
+ }
39133
+ if (side === 'north')
39134
+ next.rowSpan = primary.row - other.row;
39135
+ if (!side || overlaps(primary, next) || next.colSpan < Math.max(1, other.constraints?.minColSpan || 1)
39136
+ || next.rowSpan < Math.max(1, other.constraints?.minRowSpan || 1)) {
39137
+ return { items: { [key]: start }, primaryItem: start, limited: true,
39138
+ minimumKeys: [], blockedKeys: [otherKey] };
39139
+ }
39140
+ items[otherKey] = next;
39141
+ const horizontal = side === 'east' || side === 'west';
39142
+ if (horizontal ? next.colSpan === Math.max(1, other.constraints?.minColSpan || 1)
39143
+ : next.rowSpan === Math.max(1, other.constraints?.minRowSpan || 1))
39144
+ minimumKeys.add(otherKey);
39145
+ }
39146
+ // Several neighbors can constrain the same edge; only the tightest ones are
39147
+ // actually at minimum in the final distribution, not every earlier limiter.
39148
+ for (const otherKey of limitedBy) {
39149
+ const item = items[otherKey] || source[otherKey];
39150
+ const side = sideOf(source[otherKey]);
39151
+ const horizontal = side === 'east' || side === 'west';
39152
+ if (horizontal ? item.colSpan === Math.max(1, item.constraints?.minColSpan || 1)
39153
+ : item.rowSpan === Math.max(1, item.constraints?.minRowSpan || 1))
39154
+ minimumKeys.add(otherKey);
39155
+ }
39156
+ if ((primary.colSpan !== start.colSpan && primary.colSpan === Math.max(1, start.constraints?.minColSpan || 1))
39157
+ || (primary.rowSpan !== start.rowSpan && primary.rowSpan === Math.max(1, start.constraints?.minRowSpan || 1)))
39158
+ minimumKeys.add(key);
39159
+ return { items, primaryItem: primary,
39160
+ limited: primary.col !== desired.col || primary.row !== desired.row
39161
+ || primary.colSpan !== desired.colSpan || primary.rowSpan !== desired.rowSpan,
39162
+ minimumKeys: [...minimumKeys], blockedKeys: [...rejected] };
39163
+ }
39164
+
38749
39165
  const CANVAS_RESIZE_HANDLES = [
38750
- { id: 'north', className: 'pdx-canvas-resize--north' },
38751
- { id: 'south', className: 'pdx-canvas-resize--south' },
38752
- { id: 'east', className: 'pdx-canvas-resize--east' },
38753
- { id: 'west', className: 'pdx-canvas-resize--west' },
38754
- { id: 'north-east', className: 'pdx-canvas-resize--north-east' },
38755
- { id: 'north-west', className: 'pdx-canvas-resize--north-west' },
38756
- { id: 'south-east', className: 'pdx-canvas-resize--south-east' },
38757
- { id: 'south-west', className: 'pdx-canvas-resize--south-west' },
39166
+ { id: 'north', icon: 'north' },
39167
+ { id: 'north-east', icon: 'north_east' },
39168
+ { id: 'east', icon: 'east' },
39169
+ { id: 'south-east', icon: 'south_east' },
39170
+ { id: 'south', icon: 'south' },
39171
+ { id: 'south-west', icon: 'south_west' },
39172
+ { id: 'west', icon: 'west' },
39173
+ { id: 'north-west', icon: 'north_west' },
38758
39174
  ];
38759
39175
  class DynamicWidgetPageComponent {
38760
39176
  pageCanvasHost;
@@ -38798,6 +39214,10 @@ class DynamicWidgetPageComponent {
38798
39214
  gridAutoRows = 'auto';
38799
39215
  layoutAnnouncement = '';
38800
39216
  canvasResizeHandles = CANVAS_RESIZE_HANDLES;
39217
+ contextualResizeHandles = [...CANVAS_RESIZE_HANDLES].sort((a, b) => {
39218
+ const order = ['north-west', 'north', 'north-east', 'west', 'east', 'south-west', 'south', 'south-east'];
39219
+ return order.indexOf(a.id) - order.indexOf(b.id);
39220
+ });
38801
39221
  pageDefinition;
38802
39222
  /**
38803
39223
  * Last canonical definition accepted from the host or published by the
@@ -38823,9 +39243,23 @@ class DynamicWidgetPageComponent {
38823
39243
  activeTabs = {};
38824
39244
  widgetDiagnostics = {};
38825
39245
  selectedWidgetKeyState = signal(null, ...(ngDevMode ? [{ debugName: "selectedWidgetKeyState" }] : /* istanbul ignore next */ []));
39246
+ selectedCanvasWidget = computed(() => this.widgets().find((widget) => this.isWidgetSelected(widget.key)), ...(ngDevMode ? [{ debugName: "selectedCanvasWidget" }] : /* istanbul ignore next */ []));
38826
39247
  blockedCanvasWidgetKey = null;
38827
39248
  canvasPreviewState = signal(null, ...(ngDevMode ? [{ debugName: "canvasPreviewState" }] : /* istanbul ignore next */ []));
38828
39249
  canvasPreviewInvalidState = signal(false, ...(ngDevMode ? [{ debugName: "canvasPreviewInvalidState" }] : /* istanbul ignore next */ []));
39250
+ resizeFeedbackState = signal({}, ...(ngDevMode ? [{ debugName: "resizeFeedbackState" }] : /* istanbul ignore next */ []));
39251
+ resizeFeedbackOrigin = signal(null, ...(ngDevMode ? [{ debugName: "resizeFeedbackOrigin" }] : /* istanbul ignore next */ []));
39252
+ resizeFeedbackPositions = [
39253
+ { originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetX: 16, offsetY: 16 },
39254
+ { originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetX: -16, offsetY: 16 },
39255
+ { originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetX: 16, offsetY: -16 },
39256
+ { originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetX: -16, offsetY: -16 },
39257
+ ];
39258
+ prepareResizeFeedbackOverlay(element) {
39259
+ // The entire pane must pass through hits, not only its inner presentation.
39260
+ // No focus, backdrop or interactive control belongs to gesture feedback.
39261
+ element.style.pointerEvents = 'none';
39262
+ }
38829
39263
  transientCanvasItemsState = signal({}, ...(ngDevMode ? [{ debugName: "transientCanvasItemsState" }] : /* istanbul ignore next */ []));
38830
39264
  activeCanvasInteraction = null;
38831
39265
  appliedPersisted = false;
@@ -38870,6 +39304,16 @@ class DynamicWidgetPageComponent {
38870
39304
  runtimeObservationRegistration = null;
38871
39305
  hostElement = inject((ElementRef));
38872
39306
  changeDetector = inject(ChangeDetectorRef);
39307
+ static resizePopoverSequence = 0;
39308
+ resizePopoverId = `pdx-canvas-resize-${++DynamicWidgetPageComponent.resizePopoverSequence}`;
39309
+ resizePopoverOrigin = signal(null, ...(ngDevMode ? [{ debugName: "resizePopoverOrigin" }] : /* istanbul ignore next */ []));
39310
+ resizePopoverReturnFocus = null;
39311
+ projectedResizeActions = new WeakSet();
39312
+ resizePopoverPositions = [
39313
+ { originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top', offsetX: 8 },
39314
+ { originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top', offsetX: -8 },
39315
+ { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 8 },
39316
+ ];
38873
39317
  hostResizeObserver;
38874
39318
  containerWidth;
38875
39319
  widgetLoaders;
@@ -38878,6 +39322,10 @@ class DynamicWidgetPageComponent {
38878
39322
  afterNextRender({ read: () => this.observeHostWidth() });
38879
39323
  }
38880
39324
  ngOnDestroy() {
39325
+ this.closeResizePopover(false);
39326
+ if (this.activeCanvasInteraction) {
39327
+ this.cancelCanvasInteractionForWidget(this.activeCanvasInteraction.widgetKey);
39328
+ }
38881
39329
  this.destroyed = true;
38882
39330
  this.runtimeObservationRegistration?.destroy();
38883
39331
  this.runtimeObservationRegistration = null;
@@ -38886,6 +39334,15 @@ class DynamicWidgetPageComponent {
38886
39334
  this.compositionRuntime.destroy();
38887
39335
  }
38888
39336
  ngOnChanges(changes) {
39337
+ if (changes['pageIdentity'] || changes['enableCustomization'] || changes['authoringCapabilities']) {
39338
+ this.closeResizePopover(false);
39339
+ }
39340
+ if (this.activeCanvasInteraction &&
39341
+ (changes['page'] || changes['context'] || changes['pageIdentity'] ||
39342
+ changes['componentInstanceId'] || changes['enableCustomization'] ||
39343
+ changes['authoringCapabilities'])) {
39344
+ this.cancelCanvasInteractionForWidget(this.activeCanvasInteraction.widgetKey);
39345
+ }
38889
39346
  if (changes['page'] ||
38890
39347
  changes['context'] ||
38891
39348
  changes['enableCustomization'] ||
@@ -40358,6 +40815,10 @@ class DynamicWidgetPageComponent {
40358
40815
  && !this.hasVisibleWidgetShellHeader(widget));
40359
40816
  }
40360
40817
  widgetShellForRender(widget) {
40818
+ const shell = this.widgetShellWithActions(widget);
40819
+ return this.widgetContentSize(widget) ? { ...shell, bodyLayout: 'scroll' } : shell;
40820
+ }
40821
+ widgetShellWithActions(widget) {
40361
40822
  if (!this.shouldProjectWidgetHeaderActions(widget)) {
40362
40823
  return widget.shell;
40363
40824
  }
@@ -40403,7 +40864,8 @@ class DynamicWidgetPageComponent {
40403
40864
  && this.hasVisibleWidgetShellHeader(widget);
40404
40865
  }
40405
40866
  hasWidgetContextAuthoringActions(widget) {
40406
- return this.canRequestWidgetAssistant()
40867
+ return (this.canCustomizeCanvas() && this.isCanvasMode())
40868
+ || this.canRequestWidgetAssistant()
40407
40869
  || this.canOpenWidgetComponentSettings(widget.key)
40408
40870
  || this.canOpenWidgetShellSettings()
40409
40871
  || this.canRemoveWidgets();
@@ -40431,6 +40893,17 @@ class DynamicWidgetPageComponent {
40431
40893
  }
40432
40894
  buildProjectedWidgetShellActions(widget) {
40433
40895
  const actions = [];
40896
+ if (this.canCustomizeCanvas() && this.isCanvasMode()) {
40897
+ const resizeAction = {
40898
+ id: 'widget-resize-controls',
40899
+ label: this.resizeWidgetLabel(), tooltip: this.resizeWidgetLabel(),
40900
+ icon: 'ms:open_in_full', variant: 'icon', placement: 'header',
40901
+ ariaControls: this.resizePopoverId,
40902
+ ariaExpanded: !!this.resizePopoverOrigin() && this.isWidgetSelected(widget.key),
40903
+ };
40904
+ this.projectedResizeActions.add(resizeAction);
40905
+ actions.push(resizeAction);
40906
+ }
40434
40907
  if (this.canRequestWidgetAssistant()) {
40435
40908
  actions.push({
40436
40909
  id: 'widget-assistant',
@@ -40482,6 +40955,7 @@ class DynamicWidgetPageComponent {
40482
40955
  action.icon || '',
40483
40956
  action.variant || '',
40484
40957
  action.placement || '',
40958
+ String(action.ariaExpanded ?? ''),
40485
40959
  ].join(':'))
40486
40960
  .join('|');
40487
40961
  }
@@ -40524,7 +40998,13 @@ class DynamicWidgetPageComponent {
40524
40998
  this.widgetDiagnosticsChange.emit({ ...this.widgetDiagnostics });
40525
40999
  }
40526
41000
  onShellAction(fromKey, evt) {
40527
- if (evt.id === 'expand' || evt.id === 'fullscreen') {
41001
+ if (evt.id === 'widget-resize-controls' && evt.action && this.projectedResizeActions.has(evt.action)) {
41002
+ this.toggleResizePopover(fromKey);
41003
+ return;
41004
+ }
41005
+ if (this.resizePopoverOrigin())
41006
+ this.closeResizePopover(false);
41007
+ if (evt.id === 'expand' || evt.id === 'fullscreen' || evt.id === 'collapse') {
40528
41008
  this.cancelCanvasInteractionForWidget(fromKey);
40529
41009
  }
40530
41010
  if (evt.id === 'widget-assistant') {
@@ -41059,6 +41539,8 @@ class DynamicWidgetPageComponent {
41059
41539
  presets: uiShell?.presets || null,
41060
41540
  pagePreset: uiShell?.preset || null,
41061
41541
  authoringCapabilities: this.authoringCapabilities,
41542
+ // Transient Settings Panel data; never part of WidgetPageDefinition.
41543
+ validateRenderedCanvas: (candidate) => this.validateRenderedCanvas(candidate),
41062
41544
  },
41063
41545
  },
41064
41546
  });
@@ -41069,6 +41551,40 @@ class DynamicWidgetPageComponent {
41069
41551
  return this.isAuthoringCapabilityEnabled('pageSettings')
41070
41552
  && !!(this.pageEditorComponent || this.defaultPageEditor);
41071
41553
  }
41554
+ validateRenderedCanvas(candidate) {
41555
+ const device = this.resolveDeviceKind();
41556
+ const canvas = this.resolveCanvas(candidate.canvas, candidate.deviceLayouts?.[device]?.canvas);
41557
+ if (!canvas || canvas.autoRows !== 'content')
41558
+ return null;
41559
+ const baseline = this.authoredPageDefinition;
41560
+ for (const [key, item] of Object.entries(canvas.items)) {
41561
+ if (candidate.deviceLayouts?.[device]?.widgetOverrides?.[key]?.hidden)
41562
+ continue;
41563
+ const size = contentSize(item);
41564
+ if (!size)
41565
+ continue;
41566
+ const override = candidate.deviceLayouts?.[device]?.canvas?.items?.[key];
41567
+ const scope = override?.contentSize !== undefined ? device : 'base';
41568
+ const current = this.canvas?.items[key];
41569
+ const minimum = this.measureCanvasMinimumHeight(key);
41570
+ // A changed width or shell cannot reuse the old DOM as geometry proof.
41571
+ const sameGeometry = !this.destroyed && this.canvas?.autoRows === 'content'
41572
+ && canvas.columns === this.canvas.columns
41573
+ && (canvas.gap || candidate.deviceLayouts?.[device]?.layout?.gap || candidate.layout?.gap || '16px') === this.pageGap
41574
+ && item.colSpan === current?.colSpan
41575
+ && candidate.layoutPreset === baseline?.layoutPreset
41576
+ && candidate.themePreset === baseline?.themePreset
41577
+ && this.sameJsonStructure(candidate.widgets.find(widget => widget.key === key)?.shell, baseline?.widgets.find(widget => widget.key === key)?.shell)
41578
+ && this.sameJsonStructure(candidate.context?.['ui']?.shell ?? {}, baseline?.context?.['ui']?.shell ?? {});
41579
+ if (!sameGeometry || minimum === undefined) {
41580
+ return { widgetKey: key, scope, message: this.t('heightValidation.measureFirst', 'Use altura Automática para aplicar a nova geometria; depois reabra o editor para definir a altura ajustável.') };
41581
+ }
41582
+ if (size.heightPx < minimum) {
41583
+ return { widgetKey: key, scope, message: this.t('heightValidation.minimum', 'Use pelo menos {{height}}px nesta largura. Ajuste a altura/máximo ou use Automática.', { height: minimum }) };
41584
+ }
41585
+ }
41586
+ return null;
41587
+ }
41072
41588
  applyWidgetShell(key, result, persist) {
41073
41589
  if (!result)
41074
41590
  return;
@@ -41321,7 +41837,15 @@ class DynamicWidgetPageComponent {
41321
41837
  const interaction = this.activeCanvasInteraction;
41322
41838
  if (!interaction || interaction.pointerId !== event.pointerId)
41323
41839
  return;
41840
+ if (!this.canCustomizeCanvas() || !this.isCanvasMode()) {
41841
+ this.cancelCanvasInteractionForWidget(interaction.widgetKey);
41842
+ return;
41843
+ }
41324
41844
  event.preventDefault();
41845
+ interaction.minimumContentHeight = this.measureCanvasMinimumHeight(interaction.widgetKey);
41846
+ if (interaction.kind === 'resize') {
41847
+ this.resizeFeedbackOrigin.set({ x: event.clientX, y: event.clientY });
41848
+ }
41325
41849
  const { colDelta, rowDelta } = this.resolveCanvasInteractionDelta(interaction, event.clientX, event.clientY);
41326
41850
  if (interaction.kind === 'drag') {
41327
41851
  const result = this.updateCanvasItem(interaction.widgetKey, (item) => this.applyCanvasDrag(item, interaction, colDelta, rowDelta), false, undefined, undefined, 'drag');
@@ -41341,9 +41865,15 @@ class DynamicWidgetPageComponent {
41341
41865
  const interaction = this.activeCanvasInteraction;
41342
41866
  if (!interaction || interaction.pointerId !== event.pointerId)
41343
41867
  return;
41868
+ if (!this.canCustomizeCanvas() || !this.isCanvasMode()) {
41869
+ this.cancelCanvasInteractionForWidget(interaction.widgetKey);
41870
+ return;
41871
+ }
41344
41872
  event.preventDefault();
41345
- this.releaseCanvasPointerCapture(interaction);
41873
+ interaction.minimumContentHeight = this.measureCanvasMinimumHeight(interaction.widgetKey);
41346
41874
  this.activeCanvasInteraction = null;
41875
+ this.resizeFeedbackOrigin.set(null);
41876
+ this.releaseCanvasPointerCapture(interaction);
41347
41877
  this.canvasPreviewState.set(null);
41348
41878
  this.canvasPreviewInvalidState.set(false);
41349
41879
  this.transientCanvasItemsState.set({});
@@ -41372,13 +41902,21 @@ class DynamicWidgetPageComponent {
41372
41902
  const interaction = this.activeCanvasInteraction;
41373
41903
  if (!interaction || interaction.pointerId !== event.pointerId)
41374
41904
  return;
41375
- this.releaseCanvasPointerCapture(interaction);
41376
- this.activeCanvasInteraction = null;
41377
- this.canvasPreviewState.set(null);
41378
- this.canvasPreviewInvalidState.set(false);
41379
- this.transientCanvasItemsState.set({});
41380
- this.layoutAnnouncement = this.blockedCanvasAnnouncement(interaction.kind);
41381
- this.applyTransientPagePreview(interaction.startPage, this.buildStateRuntime(interaction.startPage.state, interaction.startPage.context));
41905
+ this.cancelCanvasGesture();
41906
+ }
41907
+ onCanvasEscape(event) {
41908
+ if (!(event instanceof KeyboardEvent) || event.key !== 'Escape'
41909
+ || event.defaultPrevented || !this.activeCanvasInteraction)
41910
+ return;
41911
+ event.preventDefault();
41912
+ event.stopPropagation();
41913
+ this.cancelCanvasGesture();
41914
+ }
41915
+ cancelCanvasGesture() {
41916
+ if (!this.activeCanvasInteraction)
41917
+ return;
41918
+ this.cancelCanvasInteractionForWidget(this.activeCanvasInteraction.widgetKey);
41919
+ this.layoutAnnouncement = this.t('announcements.interactionCancelled', 'Alteração de layout cancelada.');
41382
41920
  }
41383
41921
  resolveColumns(layout, deviceLayoutColumnsSelected = false) {
41384
41922
  const base = Math.max(1, Number(layout?.columns) || 2);
@@ -41668,7 +42206,10 @@ class DynamicWidgetPageComponent {
41668
42206
  selectWidget(widgetKey) {
41669
42207
  if (!this.canSelectWidgets())
41670
42208
  return;
42209
+ if (this.activeCanvasInteraction && this.activeCanvasInteraction.widgetKey !== widgetKey)
42210
+ return;
41671
42211
  if (this.selectedWidgetKeyState() !== widgetKey) {
42212
+ this.closeResizePopover(false);
41672
42213
  this.selectedWidgetKeyState.set(widgetKey);
41673
42214
  this.widgetSelectionChange.emit(widgetKey);
41674
42215
  }
@@ -41692,6 +42233,103 @@ class DynamicWidgetPageComponent {
41692
42233
  isWidgetSelected(widgetKey) {
41693
42234
  return this.selectedWidgetKeyState() === widgetKey;
41694
42235
  }
42236
+ canvasInteractionActive() {
42237
+ return this.activeCanvasInteraction !== null;
42238
+ }
42239
+ canShowCanvasEdges(widgetKey) {
42240
+ return this.canCustomizeCanvas() && this.isWidgetSelected(widgetKey)
42241
+ && !this.currentCanvasItem(widgetKey)?.constraints?.lockSize;
42242
+ }
42243
+ contextualResizeHandle() {
42244
+ const interaction = this.activeCanvasInteraction;
42245
+ return this.resizePopoverOrigin() && interaction?.kind === 'resize'
42246
+ && interaction.widgetKey === this.selectedCanvasWidget()?.key
42247
+ ? interaction.resizeHandle ?? null : null;
42248
+ }
42249
+ selectCanvasResizeTarget(event) {
42250
+ const key = event.target.value;
42251
+ if (this.widgets().some((widget) => widget.key === key)) {
42252
+ this.selectCanvasWidget(key);
42253
+ }
42254
+ }
42255
+ toggleResizePopover(widgetKey) {
42256
+ if (!this.canCustomizeCanvas() || !this.isCanvasMode() || this.canvasInteractionActive()
42257
+ || this.isCanvasWidgetInOverlay(widgetKey))
42258
+ return;
42259
+ if (this.resizePopoverOrigin() && this.isWidgetSelected(widgetKey)) {
42260
+ this.closeResizePopover(true);
42261
+ return;
42262
+ }
42263
+ const owner = Array.from(this.pageCanvasHost?.nativeElement.children || [])
42264
+ .find((element) => element.getAttribute('data-widget-key') === widgetKey);
42265
+ const header = owner?.querySelector('.pdx-shell-header')
42266
+ ?? owner?.querySelector('[data-testid="dynamic-widget-context-toolbar"]');
42267
+ if (!header)
42268
+ return;
42269
+ this.selectCanvasWidget(widgetKey);
42270
+ const focused = this.hostElement.nativeElement.ownerDocument.activeElement;
42271
+ this.resizePopoverReturnFocus = focused instanceof HTMLElement && header.contains(focused)
42272
+ ? focused : (header.querySelector('button[aria-haspopup="menu"]') ?? header.querySelector('button'));
42273
+ this.resizePopoverOrigin.set(header);
42274
+ }
42275
+ focusResizePopover(overlay) {
42276
+ overlay.querySelector('[data-resize-handle]')?.focus({ preventScroll: true });
42277
+ }
42278
+ closeResizePopover(restoreFocus) {
42279
+ if (!this.resizePopoverOrigin())
42280
+ return;
42281
+ const widget = this.selectedCanvasWidget();
42282
+ if (widget)
42283
+ this.cancelCanvasInteractionForWidget(widget.key);
42284
+ const target = this.resizePopoverReturnFocus;
42285
+ this.resizePopoverOrigin.set(null);
42286
+ this.resizePopoverReturnFocus = null;
42287
+ if (restoreFocus && target?.isConnected)
42288
+ target.focus({ preventScroll: true });
42289
+ }
42290
+ onResizePopoverOutsideClick(event) {
42291
+ if (this.canvasInteractionActive())
42292
+ return;
42293
+ const target = event.target;
42294
+ if (target instanceof Node && this.resizePopoverOrigin()?.contains(target))
42295
+ return;
42296
+ this.closeResizePopover(false);
42297
+ }
42298
+ onResizePopoverKeydown(event) {
42299
+ if (event.key !== 'Escape')
42300
+ return;
42301
+ event.preventDefault();
42302
+ event.stopPropagation();
42303
+ this.cancelCanvasGesture();
42304
+ this.closeResizePopover(true);
42305
+ }
42306
+ resizeCloseLabel() {
42307
+ return this.t('controls.resizeClose', 'Fechar controles de tamanho');
42308
+ }
42309
+ resizeContextHelpLabel() {
42310
+ return this.t('controls.resizeContextHelp', 'Arraste um controle ou use as setas do teclado. Esc fecha os controles.');
42311
+ }
42312
+ resizePopoverGridArea(handle) {
42313
+ const positions = {
42314
+ north: '1 / 2', 'north-east': '1 / 3', east: '2 / 3', 'south-east': '3 / 3',
42315
+ south: '3 / 2', 'south-west': '3 / 1', west: '2 / 1', 'north-west': '1 / 1',
42316
+ };
42317
+ return positions[handle];
42318
+ }
42319
+ onSelectedCanvasResizePointerDown(handle, event) {
42320
+ const widget = this.selectedCanvasWidget();
42321
+ if (!widget)
42322
+ return;
42323
+ this.startCanvasResize(widget.key, handle, event);
42324
+ if (this.activeCanvasInteraction?.pointerId === event.pointerId && event.currentTarget instanceof HTMLElement) {
42325
+ event.currentTarget.focus({ preventScroll: true });
42326
+ }
42327
+ }
42328
+ onSelectedCanvasResizeKeydown(handle, event) {
42329
+ const widget = this.selectedCanvasWidget();
42330
+ if (widget)
42331
+ this.onCanvasResizeHandleKeydown(widget.key, handle, event);
42332
+ }
41695
42333
  selectCanvasWidget(widgetKey) {
41696
42334
  this.selectWidget(widgetKey);
41697
42335
  }
@@ -41734,36 +42372,35 @@ class DynamicWidgetPageComponent {
41734
42372
  if (!horizontal && !vertical)
41735
42373
  return;
41736
42374
  event.preventDefault();
42375
+ event.stopPropagation();
41737
42376
  const step = event.shiftKey ? 2 : 1;
41738
42377
  const delta = event.key === 'ArrowLeft' || event.key === 'ArrowUp' ? -step : step;
41739
42378
  this.updateCanvasItem(widgetKey, (item) => {
41740
42379
  if (kind === 'drag') {
41741
42380
  return this.applyCanvasKeyboardDrag(item, event.key, delta);
41742
42381
  }
41743
- return this.applyCanvasKeyboardResize(item, event.key, delta);
42382
+ return this.applyCanvasKeyboardResize(item, event.key, delta, widgetKey);
41744
42383
  }, true, this.canvasAnnouncement(kind, widgetKey), this.blockedCanvasAnnouncement(kind), kind);
41745
42384
  }
41746
42385
  onCanvasResizeHandleKeydown(widgetKey, handle, event) {
41747
42386
  if (!this.canCustomizeCanvas() || !this.isCanvasMode())
41748
42387
  return;
42388
+ if (this.isCanvasWidgetInOverlay(widgetKey) || this.activeCanvasInteraction)
42389
+ return;
41749
42390
  this.selectCanvasWidget(widgetKey);
41750
42391
  const horizontal = event.key === 'ArrowLeft' || event.key === 'ArrowRight';
41751
42392
  const vertical = event.key === 'ArrowUp' || event.key === 'ArrowDown';
41752
42393
  if (!horizontal && !vertical)
41753
42394
  return;
41754
42395
  event.preventDefault();
42396
+ event.stopPropagation();
41755
42397
  const step = event.shiftKey ? 2 : 1;
41756
42398
  const delta = event.key === 'ArrowLeft' || event.key === 'ArrowUp' ? -step : step;
41757
42399
  const colDelta = horizontal ? delta : 0;
41758
42400
  const rowDelta = vertical ? delta : 0;
41759
42401
  const columns = this.canvas?.columns || 1;
42402
+ const contentHeight = this.measureCanvasContentHeight(widgetKey);
41760
42403
  this.updateCanvasItem(widgetKey, (item) => this.applyCanvasResize(item, {
41761
- kind: 'resize',
41762
- widgetKey,
41763
- pointerId: -1,
41764
- startPage: this.clonePageDefinition(this.ensurePageDefinition()),
41765
- startX: 0,
41766
- startY: 0,
41767
42404
  startItem: {
41768
42405
  ...item,
41769
42406
  constraints: item.constraints
@@ -41771,11 +42408,10 @@ class DynamicWidgetPageComponent {
41771
42408
  : undefined,
41772
42409
  },
41773
42410
  columns,
41774
- columnWidth: 1,
41775
- rowHeight: 1,
41776
42411
  resizeHandle: handle,
41777
- blocked: false,
41778
- }, colDelta, rowDelta), true, this.canvasAnnouncement('resize', widgetKey), this.blockedCanvasAnnouncement('resize'), 'resize');
42412
+ contentHeight,
42413
+ minimumContentHeight: this.measureCanvasMinimumHeight(widgetKey),
42414
+ }, colDelta, contentHeight !== undefined ? rowDelta * 16 : rowDelta), true, this.canvasAnnouncement('resize', widgetKey), this.blockedCanvasAnnouncement('resize'), 'resize');
41779
42415
  }
41780
42416
  applyWidgetLayoutOverrides(widgets, overrides) {
41781
42417
  const rendered = widgets
@@ -41821,7 +42457,10 @@ class DynamicWidgetPageComponent {
41821
42457
  startCanvasInteraction(widgetKey, event, kind, resizeHandle) {
41822
42458
  if (!this.canCustomizeCanvas() || !this.isCanvasMode())
41823
42459
  return;
41824
- if (this.isCanvasOverlayInteraction(event))
42460
+ // One gesture owns the preview until commit/cancel, including across pointer types.
42461
+ if (this.activeCanvasInteraction || event.button > 0 || event.isPrimary === false)
42462
+ return;
42463
+ if (this.isCanvasOverlayInteraction(event) || this.isCanvasWidgetInOverlay(widgetKey))
41825
42464
  return;
41826
42465
  event.preventDefault();
41827
42466
  event.stopPropagation();
@@ -41831,7 +42470,6 @@ class DynamicWidgetPageComponent {
41831
42470
  const metrics = this.currentCanvasMetrics();
41832
42471
  if (!item || !metrics)
41833
42472
  return;
41834
- const pageSnapshot = this.clonePageDefinition(this.ensurePageDefinition());
41835
42473
  const pointerTarget = event.currentTarget instanceof HTMLElement
41836
42474
  ? event.currentTarget
41837
42475
  : undefined;
@@ -41846,7 +42484,6 @@ class DynamicWidgetPageComponent {
41846
42484
  widgetKey,
41847
42485
  pointerId: event.pointerId,
41848
42486
  pointerTarget,
41849
- startPage: pageSnapshot,
41850
42487
  startX: event.clientX,
41851
42488
  startY: event.clientY,
41852
42489
  startItem: {
@@ -41854,8 +42491,10 @@ class DynamicWidgetPageComponent {
41854
42491
  constraints: item.constraints ? { ...item.constraints } : undefined,
41855
42492
  },
41856
42493
  columns: metrics.columns,
41857
- columnWidth: metrics.columnWidth,
41858
- rowHeight: metrics.rowHeight,
42494
+ columnGeometry: metrics.columnGeometry,
42495
+ rowGeometry: metrics.rowGeometry,
42496
+ contentHeight: this.measureCanvasContentHeight(widgetKey),
42497
+ minimumContentHeight: this.measureCanvasMinimumHeight(widgetKey),
41859
42498
  resizeHandle,
41860
42499
  blocked: false,
41861
42500
  swappedWith: null,
@@ -41867,12 +42506,14 @@ class DynamicWidgetPageComponent {
41867
42506
  const interaction = this.activeCanvasInteraction;
41868
42507
  if (!interaction || interaction.widgetKey !== widgetKey)
41869
42508
  return;
41870
- this.releaseCanvasPointerCapture(interaction);
41871
42509
  this.activeCanvasInteraction = null;
42510
+ this.resizeFeedbackOrigin.set(null);
42511
+ this.releaseCanvasPointerCapture(interaction);
41872
42512
  this.blockedCanvasWidgetKey = null;
41873
42513
  this.canvasPreviewState.set(null);
41874
42514
  this.canvasPreviewInvalidState.set(false);
41875
42515
  this.transientCanvasItemsState.set({});
42516
+ this.resizeFeedbackState.set({});
41876
42517
  }
41877
42518
  isCanvasOverlayInteraction(event) {
41878
42519
  const target = event.currentTarget instanceof HTMLElement
@@ -41882,13 +42523,20 @@ class DynamicWidgetPageComponent {
41882
42523
  : null;
41883
42524
  return !!target?.closest('.pdx-shell.expanded, .pdx-shell.fullscreen');
41884
42525
  }
42526
+ isCanvasWidgetInOverlay(widgetKey) {
42527
+ const owner = Array.from(this.pageCanvasHost?.nativeElement.children || [])
42528
+ .find((element) => element.getAttribute('data-widget-key') === widgetKey);
42529
+ return !!owner?.querySelector(':scope > praxis-widget-shell > .pdx-shell.expanded, :scope > praxis-widget-shell > .pdx-shell.fullscreen, :scope > praxis-widget-shell > .pdx-shell.collapsed');
42530
+ }
41885
42531
  currentCanvasMetrics() {
41886
42532
  const canvas = this.canvas;
41887
42533
  const host = this.pageCanvasHost?.nativeElement;
41888
42534
  if (!canvas || !host)
41889
42535
  return null;
41890
42536
  const rect = host.getBoundingClientRect();
41891
- const gap = this.parseCssPixelValue(this.pageGap, 16);
42537
+ const style = host.ownerDocument.defaultView?.getComputedStyle(host);
42538
+ const gap = this.parseCssPixelValue(style?.columnGap || this.pageGap, 16);
42539
+ const rowGap = this.parseCssPixelValue(style?.rowGap || this.pageGap, 16);
41892
42540
  const columns = Math.max(1, Number(canvas.columns) || 1);
41893
42541
  const availableWidth = Math.max(1, rect.width - gap * Math.max(0, columns - 1));
41894
42542
  const columnWidth = availableWidth / columns;
@@ -41897,19 +42545,48 @@ class DynamicWidgetPageComponent {
41897
42545
  : this.parseCssPixelValue(canvas.rowUnit || this.gridAutoRows || '88px', 88);
41898
42546
  return {
41899
42547
  columns,
41900
- columnWidth: Math.max(1, columnWidth),
41901
- rowHeight: Math.max(1, rowHeight),
42548
+ columnGeometry: {
42549
+ sizes: readCanvasTrackSizes(style?.gridTemplateColumns || ''),
42550
+ gap,
42551
+ fallbackSize: Math.max(1, columnWidth),
42552
+ },
42553
+ rowGeometry: {
42554
+ sizes: readCanvasTrackSizes(style?.gridTemplateRows || ''),
42555
+ gap: rowGap,
42556
+ fallbackSize: Math.max(1, rowHeight),
42557
+ },
41902
42558
  };
41903
42559
  }
42560
+ measureCanvasContentHeight(key) {
42561
+ if (this.canvas?.autoRows !== 'content')
42562
+ return undefined;
42563
+ const owner = Array.from(this.pageCanvasHost?.nativeElement.children || [])
42564
+ .find(element => element.getAttribute('data-widget-key') === key);
42565
+ const height = owner?.getBoundingClientRect().height;
42566
+ return height && height > 0 ? height : undefined;
42567
+ }
42568
+ measureCanvasMinimumHeight(key) {
42569
+ if (this.canvas?.autoRows !== 'content')
42570
+ return undefined;
42571
+ const owner = Array.from(this.pageCanvasHost?.nativeElement.children || [])
42572
+ .find(element => element.getAttribute('data-widget-key') === key);
42573
+ const shell = owner?.querySelector(':scope > praxis-widget-shell > .pdx-shell');
42574
+ return shell ? measureWidgetShellHeight(shell)?.minimum : undefined;
42575
+ }
41904
42576
  currentCanvasItem(widgetKey) {
41905
42577
  return this.canvas?.items?.[widgetKey];
41906
42578
  }
41907
42579
  resolveCanvasInteractionDelta(interaction, clientX, clientY) {
41908
42580
  const deltaX = clientX - interaction.startX;
41909
42581
  const deltaY = clientY - interaction.startY;
42582
+ const start = interaction.startItem;
42583
+ const east = interaction.kind === 'resize' &&
42584
+ (interaction.resizeHandle || 'south-east').includes('east');
42585
+ const south = interaction.kind === 'resize' &&
42586
+ (interaction.resizeHandle || 'south-east').includes('south');
41910
42587
  return {
41911
- colDelta: Math.round(deltaX / Math.max(1, interaction.columnWidth)),
41912
- rowDelta: Math.round(deltaY / Math.max(1, interaction.rowHeight)),
42588
+ colDelta: canvasAxisDelta(interaction.columnGeometry, start.col - 1 + (east ? start.colSpan - 1 : 0), deltaX, east ? 'end' : 'start'),
42589
+ rowDelta: interaction.kind === 'resize' && interaction.contentHeight !== undefined ? Math.round(deltaY) : canvasAxisDelta(interaction.rowGeometry, start.row - 1 + (south ? start.rowSpan - 1 : 0), deltaY, south ? 'end' : 'start'),
41913
42590
  };
41914
42591
  }
41915
42592
  updateCanvasItem(widgetKey, updater, persist, announcement, blockedAnnouncement, interactionKind = 'drag') {
@@ -41921,14 +42598,21 @@ class DynamicWidgetPageComponent {
41921
42598
  const current = effectiveCanvas?.items[widgetKey];
41922
42599
  if (!current)
41923
42600
  return { changed: false, blocked: false };
41924
- const candidate = this.normalizeCanvasItem(updater({
42601
+ const update = updater({
41925
42602
  ...current,
41926
42603
  constraints: current.constraints
41927
42604
  ? { ...current.constraints }
41928
42605
  : undefined,
41929
- }), effectiveCanvas?.columns || page.canvas.columns || 1);
42606
+ });
42607
+ const { item: candidateItem, constrained } = 'item' in update
42608
+ ? update : { item: update, constrained: false };
42609
+ const candidate = this.normalizeCanvasItem(candidateItem, effectiveCanvas?.columns || page.canvas.columns || 1);
42610
+ if (interactionKind === 'resize' && effectiveCanvas) {
42611
+ return this.updateCanvasResize(widgetKey, candidate, effectiveCanvas, page, persist, announcement, constrained);
42612
+ }
42613
+ this.resizeFeedbackState.set({});
41930
42614
  const collisionPolicy = effectiveCanvas
41931
- ? this.resolveCanvasCollisionPolicy(effectiveCanvas, interactionKind)
42615
+ ? this.resolveCanvasCollisionPolicy(effectiveCanvas)
41932
42616
  : 'block';
41933
42617
  const placement = effectiveCanvas
41934
42618
  ? this.resolveCanvasPlacement(widgetKey, current, candidate, effectiveCanvas, collisionPolicy)
@@ -41952,7 +42636,7 @@ class DynamicWidgetPageComponent {
41952
42636
  this.blockedCanvasWidgetKey = null;
41953
42637
  this.canvasPreviewInvalidState.set(false);
41954
42638
  const changed = placement.changed;
41955
- if (!changed && !persist) {
42639
+ if (!changed) {
41956
42640
  this.transientCanvasItemsState.set({});
41957
42641
  this.canvasPreviewState.set(null);
41958
42642
  this.canvasPreviewInvalidState.set(false);
@@ -42001,28 +42685,65 @@ class DynamicWidgetPageComponent {
42001
42685
  }
42002
42686
  return { changed, blocked: false, swappedWith: placement.swappedWith };
42003
42687
  }
42004
- applyTransientPagePreview(next, runtime = this.pageRuntime) {
42005
- const normalized = { ...next, state: runtime.state };
42006
- const previewProjection = this.compositionRuntime.projectStateWidgetInputs(this.compositionFactory.create(normalized), {
42007
- widgets: normalized.widgets || [],
42008
- state: {
42009
- primaryValues: this.cloneStateValues(runtime.primaryValues),
42010
- derivedValues: this.cloneStateValues(runtime.derivedValues),
42011
- transientValues: {},
42012
- changedPaths: [],
42013
- diagnostics: [],
42014
- },
42015
- });
42016
- const stateBoundWidgets = previewProjection.widgets;
42017
- const hydrated = this.resolvePagePresets({
42018
- ...normalized,
42019
- widgets: stateBoundWidgets,
42020
- });
42021
- this.pageDefinition = hydrated;
42022
- this.page = hydrated;
42023
- this.pageState = runtime.state;
42024
- this.pageRuntime = runtime;
42025
- this.applyResponsivePresentation(hydrated, stateBoundWidgets, runtime);
42688
+ resizeFeedback(key) {
42689
+ return this.resizeFeedbackState()[key] ?? null;
42690
+ }
42691
+ hasResizeFeedback() {
42692
+ return Object.keys(this.resizeFeedbackState()).length > 0;
42693
+ }
42694
+ resizeFeedbackLabel(state) {
42695
+ const fallback = {
42696
+ valid: 'Ajuste disponível', minimum: 'Tamanho mínimo atingido',
42697
+ blocked: 'Limite excedido — prévia limitada ao espaço disponível',
42698
+ };
42699
+ return this.t(`resizeFeedback.${state}`, fallback[state]);
42700
+ }
42701
+ updateCanvasResize(key, candidate, canvas, page, persist, announcement, constrained = false) {
42702
+ const placement = resolveCanvasResizePlacement(key, candidate, canvas.items);
42703
+ const changed = Object.entries(placement.items).some(([itemKey, item]) => !this.isSameCanvasItem(canvas.items[itemKey], item));
42704
+ const feedback = {};
42705
+ for (const itemKey of Object.keys(placement.items))
42706
+ feedback[itemKey] = 'valid';
42707
+ for (const itemKey of placement.minimumKeys)
42708
+ feedback[itemKey] = 'minimum';
42709
+ const bounded = contentSize(placement.primaryItem);
42710
+ const minimum = Math.max(contentHeightLimits(placement.primaryItem).min, this.measureCanvasMinimumHeight(key) || 0);
42711
+ if (bounded && bounded.heightPx <= minimum)
42712
+ feedback[key] = 'minimum';
42713
+ for (const itemKey of placement.blockedKeys)
42714
+ feedback[itemKey] = 'blocked';
42715
+ const limited = constrained || placement.limited;
42716
+ if (limited)
42717
+ feedback[key] = 'blocked';
42718
+ const message = this.resizeFeedbackLabel(feedback[key]);
42719
+ if (persist) {
42720
+ this.resizeFeedbackState.set({});
42721
+ this.transientCanvasItemsState.set({});
42722
+ this.canvasPreviewState.set(null);
42723
+ this.canvasPreviewInvalidState.set(false);
42724
+ this.blockedCanvasWidgetKey = null;
42725
+ if (changed) {
42726
+ const target = this.resolveCanvasTarget(page);
42727
+ for (const [itemKey, item] of Object.entries(placement.items)) {
42728
+ target.items[itemKey] = { ...item, constraints: item.constraints ? { ...item.constraints } : undefined };
42729
+ }
42730
+ this.applyAuthoringPageUpdate(page, true);
42731
+ }
42732
+ this.layoutAnnouncement = this.positionedCanvasAnnouncement(!changed ? this.t('resizeFeedback.unchanged', 'Tamanho mantido — nenhum ajuste aplicado')
42733
+ : limited ? this.t('resizeFeedback.committedLimit', 'Layout ajustado até o limite permitido') : announcement || message, placement.primaryItem);
42734
+ }
42735
+ else {
42736
+ if (JSON.stringify(feedback) !== JSON.stringify(this.resizeFeedbackState())) {
42737
+ this.layoutAnnouncement = Object.entries(feedback).map(([itemKey, state]) => `${this.widgetContextToolbarLabel(itemKey)}: ${this.resizeFeedbackLabel(state)}`).join('. ');
42738
+ }
42739
+ this.resizeFeedbackState.set(feedback);
42740
+ this.transientCanvasItemsState.set(placement.items);
42741
+ // Render the real clamped distribution, never an impossible overlapping ghost.
42742
+ this.canvasPreviewState.set(placement.primaryItem);
42743
+ this.canvasPreviewInvalidState.set(false);
42744
+ this.blockedCanvasWidgetKey = null;
42745
+ }
42746
+ return { changed, blocked: limited };
42026
42747
  }
42027
42748
  resolveCanvasTarget(page) {
42028
42749
  const kind = this.resolveDeviceKind();
@@ -42051,7 +42772,15 @@ class DynamicWidgetPageComponent {
42051
42772
  applyCanvasResize(item, interaction, colDelta, rowDelta) {
42052
42773
  const locked = item.constraints?.lockSize || interaction.startItem.constraints?.lockSize;
42053
42774
  if (locked)
42054
- return item;
42775
+ return { item, constrained: colDelta !== 0 || rowDelta !== 0 };
42776
+ if (interaction.contentHeight !== undefined) {
42777
+ const horizontal = this.applyCanvasResize(item, { ...interaction, contentHeight: undefined }, colDelta, 0);
42778
+ const handle = interaction.resizeHandle || 'south-east';
42779
+ if (!handle.includes('north') && !handle.includes('south'))
42780
+ return horizontal;
42781
+ const vertical = resizeContentHeight({ ...horizontal.item, contentSize: interaction.startItem.contentSize }, interaction.contentHeight, rowDelta, handle.includes('north'), interaction.minimumContentHeight);
42782
+ return { item: vertical.item, constrained: horizontal.constrained || vertical.constrained };
42783
+ }
42055
42784
  const handle = interaction.resizeHandle || 'south-east';
42056
42785
  const start = interaction.startItem;
42057
42786
  const constraints = this.resolveCanvasConstraints(start, interaction.columns);
@@ -42079,12 +42808,16 @@ class DynamicWidgetPageComponent {
42079
42808
  nextRow = this.clampNumber(start.row + rowDelta, minRow, maxRow);
42080
42809
  nextRowSpan = bottomEdge - nextRow + 1;
42081
42810
  }
42811
+ // Keep attempted edges until feedback is decided. Otherwise clamping here
42812
+ // makes a gesture past an own minimum/maximum look like a valid request.
42813
+ const requestedCol = start.col + (handle.includes('west') ? colDelta : 0);
42814
+ const requestedRow = start.row + (handle.includes('north') ? rowDelta : 0);
42815
+ const requestedColSpan = start.colSpan + (handle.includes('east') ? colDelta : handle.includes('west') ? -colDelta : 0);
42816
+ const requestedRowSpan = start.rowSpan + (handle.includes('south') ? rowDelta : handle.includes('north') ? -rowDelta : 0);
42082
42817
  return {
42083
- ...item,
42084
- col: nextCol,
42085
- row: nextRow,
42086
- colSpan: nextColSpan,
42087
- rowSpan: nextRowSpan,
42818
+ item: { ...item, col: nextCol, row: nextRow, colSpan: nextColSpan, rowSpan: nextRowSpan },
42819
+ constrained: nextCol !== requestedCol || nextRow !== requestedRow
42820
+ || nextColSpan !== requestedColSpan || nextRowSpan !== requestedRowSpan,
42088
42821
  };
42089
42822
  }
42090
42823
  applyCanvasKeyboardDrag(item, key, delta) {
@@ -42101,21 +42834,11 @@ class DynamicWidgetPageComponent {
42101
42834
  row: Math.max(1, item.row + delta),
42102
42835
  };
42103
42836
  }
42104
- applyCanvasKeyboardResize(item, key, delta) {
42105
- if (item.constraints?.lockSize)
42106
- return item;
42107
- const columns = this.canvas?.columns || 1;
42108
- const constraints = this.resolveCanvasConstraints(item, columns);
42109
- if (key === 'ArrowLeft' || key === 'ArrowRight') {
42110
- return {
42111
- ...item,
42112
- colSpan: this.clampNumber(item.colSpan + delta, constraints.minColSpan, Math.min(constraints.maxColSpan, columns - item.col + 1)),
42113
- };
42114
- }
42115
- return {
42116
- ...item,
42117
- rowSpan: this.clampNumber(item.rowSpan + delta, constraints.minRowSpan, constraints.maxRowSpan),
42118
- };
42837
+ applyCanvasKeyboardResize(item, key, delta, widgetKey) {
42838
+ const horizontal = key === 'ArrowLeft' || key === 'ArrowRight';
42839
+ const contentHeight = this.measureCanvasContentHeight(widgetKey);
42840
+ return this.applyCanvasResize(item, { startItem: item, columns: this.canvas?.columns || 1, resizeHandle: 'south-east', contentHeight,
42841
+ minimumContentHeight: this.measureCanvasMinimumHeight(widgetKey) }, horizontal ? delta : 0, horizontal ? 0 : contentHeight !== undefined ? delta * 16 : delta);
42119
42842
  }
42120
42843
  pageSettingsLabel() {
42121
42844
  return this.t('controls.pageSettings', 'Configurar página');
@@ -42126,6 +42849,15 @@ class DynamicWidgetPageComponent {
42126
42849
  resizeWidgetLabel() {
42127
42850
  return this.t('controls.resizeWidget', 'Redimensionar widget');
42128
42851
  }
42852
+ resizeAlternativeLabel() {
42853
+ return this.t('controls.resizeAlternative', 'Controles alternativos de tamanho');
42854
+ }
42855
+ resizeSelectLabel() {
42856
+ return this.t('controls.resizeSelect', 'Selecione um widget');
42857
+ }
42858
+ resizeHelpLabel() {
42859
+ return this.t('controls.resizeHelp', 'Selecione o widget. Arraste uma borda ou canto pelos botões, ou use as setas do teclado.');
42860
+ }
42129
42861
  resizeHandleLabel(handle) {
42130
42862
  return this.t(`controls.resize.${handle}`, this.resizeWidgetLabel());
42131
42863
  }
@@ -42147,6 +42879,11 @@ class DynamicWidgetPageComponent {
42147
42879
  return this.t('announcements.swapped', 'Widget trocado com {{target}}: {{widget}}', { widget: widgetKey, target: targetWidgetKey });
42148
42880
  }
42149
42881
  positionedCanvasAnnouncement(action, item) {
42882
+ const size = this.canvas?.autoRows === 'content' ? contentSize(item) : null;
42883
+ if (size)
42884
+ return this.t('announcements.contentSize', '{{action}}. Largura {{columns}} colunas, altura {{height}} pixels, recuo superior {{top}} pixels.', {
42885
+ action, columns: item.colSpan, height: size.heightPx, top: size.offsetTopPx,
42886
+ });
42150
42887
  return this.t('announcements.position', '{{action}} para coluna {{col}}, linha {{row}}, largura {{colSpan}}, altura {{rowSpan}}.', {
42151
42888
  action,
42152
42889
  col: item.col,
@@ -42164,6 +42901,8 @@ class DynamicWidgetPageComponent {
42164
42901
  const maxColSpan = Math.max(minColSpan, item.constraints?.maxColSpan || columns);
42165
42902
  const maxRowSpan = Math.max(minRowSpan, item.constraints?.maxRowSpan || Number.MAX_SAFE_INTEGER);
42166
42903
  return {
42904
+ minHeightPx: contentHeightLimits(item).min,
42905
+ maxHeightPx: contentHeightLimits(item).max,
42167
42906
  minColSpan,
42168
42907
  minRowSpan,
42169
42908
  maxColSpan,
@@ -42186,10 +42925,7 @@ class DynamicWidgetPageComponent {
42186
42925
  rowSpan,
42187
42926
  };
42188
42927
  }
42189
- resolveCanvasCollisionPolicy(canvas, interactionKind) {
42190
- if (interactionKind === 'resize') {
42191
- return 'block';
42192
- }
42928
+ resolveCanvasCollisionPolicy(canvas) {
42193
42929
  return canvas.collisionPolicy === 'swap' ? 'swap' : 'block';
42194
42930
  }
42195
42931
  resolveCanvasPlacement(widgetKey, current, candidate, canvas, collisionPolicy) {
@@ -42278,11 +43014,15 @@ class DynamicWidgetPageComponent {
42278
43014
  leftBottom >= right.row);
42279
43015
  }
42280
43016
  isSameCanvasItem(left, right) {
43017
+ const leftSize = typeof left.contentSize === 'object' ? left.contentSize : undefined;
43018
+ const rightSize = typeof right.contentSize === 'object' ? right.contentSize : undefined;
42281
43019
  return (left.col === right.col &&
42282
43020
  left.row === right.row &&
42283
43021
  left.colSpan === right.colSpan &&
42284
43022
  left.rowSpan === right.rowSpan &&
42285
- left.zIndex === right.zIndex);
43023
+ left.zIndex === right.zIndex &&
43024
+ leftSize?.heightPx === rightSize?.heightPx &&
43025
+ (leftSize?.offsetTopPx ?? 0) === (rightSize?.offsetTopPx ?? 0));
42286
43026
  }
42287
43027
  clampCanvasCol(col, span, columns) {
42288
43028
  return this.clampNumber(col, 1, Math.max(1, columns - span + 1));
@@ -42479,6 +43219,12 @@ class DynamicWidgetPageComponent {
42479
43219
  return null;
42480
43220
  return `${canvasItem.row} / span ${canvasItem.rowSpan}`;
42481
43221
  }
43222
+ widgetContentSize(widget) {
43223
+ if (this.canvas?.autoRows !== 'content')
43224
+ return null;
43225
+ const item = this.resolveRenderedCanvasItem(widget) || this.canvas.items[widget.key];
43226
+ return item ? contentSize(item) : null;
43227
+ }
42482
43228
  widgetZIndex(widget) {
42483
43229
  return this.resolveRenderedCanvasItem(widget)?.zIndex ?? null;
42484
43230
  }
@@ -42794,7 +43540,7 @@ class DynamicWidgetPageComponent {
42794
43540
  throw new Error('DynamicWidgetPageComponent no longer accepts `page.connections`. Use `composition.links` only.');
42795
43541
  }
42796
43542
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicWidgetPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
42797
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicWidgetPageComponent, isStandalone: true, selector: "praxis-dynamic-page", inputs: { page: "page", context: "context", strictValidation: "strictValidation", enableCustomization: "enableCustomization", authoringCapabilities: "authoringCapabilities", showPageSettingsButton: "showPageSettingsButton", shellEditorComponent: "shellEditorComponent", pageEditorComponent: "pageEditorComponent", autoPersist: "autoPersist", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId", showWidgetAssistantButton: "showWidgetAssistantButton" }, outputs: { pageChange: "pageChange", pageAuthoringChange: "pageAuthoringChange", widgetEvent: "widgetEvent", widgetSelectionChange: "widgetSelectionChange", widgetAssistantRequested: "widgetAssistantRequested", widgetDiagnosticsChange: "widgetDiagnosticsChange" }, host: { listeners: { "window:resize": "onWindowResize()", "window:pointermove": "onCanvasPointerMove($event)", "window:pointerup": "onCanvasPointerUp($event)", "window:pointercancel": "onCanvasPointerCancel($event)" } }, providers: [providePraxisI18nConfig(DYNAMIC_WIDGET_PAGE_I18N_CONFIG)], viewQueries: [{ propertyName: "pageCanvasHost", first: true, predicate: ["pageCanvasHost"], descendants: true }, { propertyName: "widgetLoaders", predicate: ["widgetLoader"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
43543
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicWidgetPageComponent, isStandalone: true, selector: "praxis-dynamic-page", inputs: { page: "page", context: "context", strictValidation: "strictValidation", enableCustomization: "enableCustomization", authoringCapabilities: "authoringCapabilities", showPageSettingsButton: "showPageSettingsButton", shellEditorComponent: "shellEditorComponent", pageEditorComponent: "pageEditorComponent", autoPersist: "autoPersist", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId", showWidgetAssistantButton: "showWidgetAssistantButton" }, outputs: { pageChange: "pageChange", pageAuthoringChange: "pageAuthoringChange", widgetEvent: "widgetEvent", widgetSelectionChange: "widgetSelectionChange", widgetAssistantRequested: "widgetAssistantRequested", widgetDiagnosticsChange: "widgetDiagnosticsChange" }, host: { listeners: { "lostpointercapture": "onCanvasPointerCancel($event)", "window:keydown.escape": "onCanvasEscape($event)", "window:resize": "onWindowResize()", "window:pointermove": "onCanvasPointerMove($event)", "window:pointerup": "onCanvasPointerUp($event)", "window:pointercancel": "onCanvasPointerCancel($event)" } }, providers: [providePraxisI18nConfig(DYNAMIC_WIDGET_PAGE_I18N_CONFIG)], viewQueries: [{ propertyName: "pageCanvasHost", first: true, predicate: ["pageCanvasHost"], descendants: true }, { propertyName: "widgetLoaders", predicate: ["widgetLoader"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
42798
43544
  <div
42799
43545
  class="pdx-page-wrapper"
42800
43546
  [class.editing]="enableCustomization"
@@ -42815,6 +43561,106 @@ class DynamicWidgetPageComponent {
42815
43561
  (click)="openPageSettings()"
42816
43562
  ></button>
42817
43563
  }
43564
+ @if (canCustomizeCanvas() && isCanvasMode()) {
43565
+ <details class="pdx-canvas-resize-alternative" data-testid="canvas-resize-alternative"
43566
+ [attr.inert]="resizePopoverOrigin() && selectedCanvasWidget() ? '' : null">
43567
+ <summary>{{ resizeAlternativeLabel() }}</summary>
43568
+ <div class="pdx-canvas-tools" data-testid="canvas-resize-tools"
43569
+ [attr.inert]="resizePopoverOrigin() && selectedCanvasWidget() ? '' : null"
43570
+ [attr.data-resize-widget-key]="selectedCanvasWidget()?.key || null"
43571
+ role="group" [attr.aria-label]="resizeWidgetLabel()">
43572
+ <label class="pdx-canvas-tools-target">
43573
+ <span>{{ resizeWidgetLabel() }}</span>
43574
+ <select data-testid="canvas-resize-target"
43575
+ [disabled]="canvasInteractionActive()"
43576
+ (change)="selectCanvasResizeTarget($event)">
43577
+ <option value="" disabled [selected]="!selectedCanvasWidget()">{{ resizeSelectLabel() }}</option>
43578
+ @for (widget of widgets(); track widget.key) {
43579
+ <option [value]="widget.key" [selected]="isWidgetSelected(widget.key)">{{ widgetContextLabel(widget) }}</option>
43580
+ }
43581
+ </select>
43582
+ </label>
43583
+ <div class="pdx-canvas-tools-directions">
43584
+ @for (handle of canvasResizeHandles; track handle.id) {
43585
+ <button class="pdx-canvas-resize" type="button"
43586
+ [praxisIconButton]="'ms:' + handle.icon"
43587
+ [attr.data-resize-handle]="handle.id"
43588
+ [attr.aria-label]="resizeHandleLabel(handle.id)"
43589
+ [matTooltip]="resizeHandleLabel(handle.id)"
43590
+ [disabled]="!selectedCanvasWidget()"
43591
+ (pointerdown)="onSelectedCanvasResizePointerDown(handle.id, $event)"
43592
+ (keydown)="onSelectedCanvasResizeKeydown(handle.id, $event)">
43593
+ </button>
43594
+ }
43595
+ </div>
43596
+ <p class="pdx-canvas-tools-hint">{{ resizeHelpLabel() }}</p>
43597
+ </div>
43598
+ </details>
43599
+ }
43600
+ @if (resizePopoverOrigin(); as origin) {
43601
+ @if (canCustomizeCanvas() && isCanvasMode() && selectedCanvasWidget(); as widget) {
43602
+ <ng-template cdkConnectedOverlay #resizeOverlay="cdkConnectedOverlay"
43603
+ [cdkConnectedOverlayOrigin]="origin"
43604
+ [cdkConnectedOverlayOpen]="true"
43605
+ [cdkConnectedOverlayPositions]="resizePopoverPositions"
43606
+ [cdkConnectedOverlayPush]="true"
43607
+ [cdkConnectedOverlayViewportMargin]="12"
43608
+ [cdkConnectedOverlayHasBackdrop]="false"
43609
+ (attach)="focusResizePopover(resizeOverlay.overlayRef.overlayElement)"
43610
+ (detach)="closeResizePopover(false)"
43611
+ (overlayOutsideClick)="onResizePopoverOutsideClick($event)"
43612
+ (overlayKeydown)="onResizePopoverKeydown($event)">
43613
+ <section class="pdx-resize-popover" data-testid="canvas-context-resize"
43614
+ [class.pdx-resize-popover--gesturing]="!!contextualResizeHandle()"
43615
+ role="region" [id]="resizePopoverId" [attr.aria-label]="resizeWidgetLabel()"
43616
+ (pointerdown)="$event.stopPropagation()" (click)="$event.stopPropagation()">
43617
+ <header>
43618
+ <div><strong>{{ resizeWidgetLabel() }}</strong><span>{{ widgetContextLabel(widget) }}</span></div>
43619
+ <button type="button" praxisIconButton="ms:close"
43620
+ [attr.aria-label]="resizeCloseLabel()" [matTooltip]="resizeCloseLabel()"
43621
+ (click)="closeResizePopover(true)"></button>
43622
+ </header>
43623
+ <div class="pdx-canvas-tools-directions">
43624
+ @for (handle of contextualResizeHandles; track handle.id) {
43625
+ <button class="pdx-canvas-resize" type="button"
43626
+ [praxisIconButton]="'ms:' + handle.icon"
43627
+ [attr.data-resize-handle]="handle.id"
43628
+ [style.grid-area]="resizePopoverGridArea(handle.id)"
43629
+ [class.pdx-resize-active-handle]="contextualResizeHandle() === handle.id"
43630
+ [attr.aria-label]="resizeHandleLabel(handle.id)"
43631
+ [matTooltip]="resizeHandleLabel(handle.id)"
43632
+ [matTooltipDisabled]="!!contextualResizeHandle()"
43633
+ (pointerdown)="onSelectedCanvasResizePointerDown(handle.id, $event)"
43634
+ (keydown)="onSelectedCanvasResizeKeydown(handle.id, $event)"></button>
43635
+ }
43636
+ </div>
43637
+ <p class="pdx-canvas-tools-hint">{{ resizeContextHelpLabel() }}</p>
43638
+ </section>
43639
+ </ng-template>
43640
+ }
43641
+ }
43642
+ @if (resizeFeedbackOrigin(); as origin) {
43643
+ @if (selectedCanvasWidget(); as widget) {
43644
+ @if (resizeFeedback(widget.key); as feedback) {
43645
+ <ng-template cdkConnectedOverlay #feedbackOverlay="cdkConnectedOverlay"
43646
+ [cdkConnectedOverlayOrigin]="origin"
43647
+ [cdkConnectedOverlayOpen]="true"
43648
+ [cdkConnectedOverlayPositions]="resizeFeedbackPositions"
43649
+ [cdkConnectedOverlayPush]="true"
43650
+ [cdkConnectedOverlayViewportMargin]="12"
43651
+ [cdkConnectedOverlayHasBackdrop]="false"
43652
+ [cdkConnectedOverlayDisableClose]="true"
43653
+ (attach)="prepareResizeFeedbackOverlay(feedbackOverlay.overlayRef.overlayElement)">
43654
+ <div class="pdx-resize-feedback pdx-resize-feedback--floating"
43655
+ data-testid="canvas-resize-feedback" [attr.data-feedback-widget]="widget.key"
43656
+ [attr.data-resize-feedback]="feedback">
43657
+ <mat-icon aria-hidden="true">{{ feedback === 'valid' ? 'check_circle' : feedback === 'minimum' ? 'warning' : 'block' }}</mat-icon>
43658
+ <span><strong>{{ widgetContextLabel(widget) }}</strong>{{ resizeFeedbackLabel(feedback) }}</span>
43659
+ </div>
43660
+ </ng-template>
43661
+ }
43662
+ }
43663
+ }
42818
43664
  <div
42819
43665
  #pageCanvasHost
42820
43666
  class="pdx-page"
@@ -42828,6 +43674,7 @@ class DynamicWidgetPageComponent {
42828
43674
  <div
42829
43675
  class="pdx-widget pdx-widget--canvas"
42830
43676
  [attr.data-widget-key]="w.key"
43677
+ [attr.data-resize-feedback]="resizeFeedback(w.key)"
42831
43678
  [class.pdx-widget--interactive]="canSelectWidgets()"
42832
43679
  [class.pdx-widget--selected]="
42833
43680
  canSelectWidgets() && isWidgetSelected(w.key)
@@ -42841,30 +43688,16 @@ class DynamicWidgetPageComponent {
42841
43688
  [class]="widgetClassName(w)"
42842
43689
  [style.gridColumn]="widgetGridColumn(w)"
42843
43690
  [style.gridRow]="widgetGridRow(w)"
43691
+ [style.height.px]="canvasShell.collapsed ? null : widgetContentSize(w)?.heightPx"
43692
+ [style.marginTop.px]="canvasShell.collapsed ? null : widgetContentSize(w)?.offsetTopPx"
43693
+ [style.alignSelf]="widgetContentSize(w) ? 'start' : null"
42844
43694
  [style.zIndex]="widgetZIndex(w)"
42845
43695
  (pointerdown)="selectWidget(w.key)"
42846
43696
  (click)="selectWidgetFromHostEvent(w.key, $event)"
42847
43697
  (focusin)="selectWidgetFromHostEvent(w.key, $event)"
42848
43698
  >
42849
- @if (canCustomizeCanvas()) {
42850
- @for (handle of canvasResizeHandles; track handle.id) {
42851
- <button
42852
- class="pdx-canvas-resize"
42853
- [ngClass]="handle.className"
42854
- type="button"
42855
- [attr.data-resize-handle]="handle.id"
42856
- [attr.aria-label]="resizeHandleLabel(handle.id)"
42857
- [title]="resizeHandleLabel(handle.id)"
42858
- (pointerdown)="startCanvasResize(w.key, handle.id, $event)"
42859
- (keydown)="
42860
- onCanvasResizeHandleKeydown(w.key, handle.id, $event)
42861
- "
42862
- >
42863
- <span class="pdx-canvas-resize-grip"></span>
42864
- </button>
42865
- }
42866
- }
42867
43699
  <praxis-widget-shell
43700
+ #canvasShell
42868
43701
  [shell]="widgetShellForRender(w)"
42869
43702
  [context]="mergedContext"
42870
43703
  [dragSurfaceEnabled]="canCustomizeCanvas() && isCanvasMode()"
@@ -42886,8 +43719,37 @@ class DynamicWidgetPageComponent {
42886
43719
  (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
42887
43720
  ></ng-container>
42888
43721
  </praxis-widget-shell>
43722
+ @if (resizeFeedback(w.key); as feedback) {
43723
+ @if (!resizeFeedbackOrigin() || selectedCanvasWidget()?.key !== w.key) {
43724
+ <div class="pdx-resize-feedback" data-testid="canvas-resize-feedback">
43725
+ <mat-icon aria-hidden="true">{{ feedback === 'valid' ? 'check_circle' : feedback === 'minimum' ? 'warning' : 'block' }}</mat-icon>
43726
+ <span>{{ resizeFeedbackLabel(feedback) }}</span>
43727
+ </div>
43728
+ }
43729
+ }
43730
+ @if (canShowCanvasEdges(w.key)) {
43731
+ <div class="pdx-canvas-edges" data-testid="canvas-edge-controls"
43732
+ [attr.inert]="resizePopoverOrigin() ? '' : null"
43733
+ role="group" [attr.aria-label]="resizeWidgetLabel()">
43734
+ @for (handle of canvasResizeHandles; track handle.id) {
43735
+ <button type="button" class="pdx-canvas-edge"
43736
+ [attr.data-canvas-edge]="handle.id"
43737
+ [attr.aria-label]="resizeHandleLabel(handle.id)"
43738
+ [matTooltip]="resizeHandleLabel(handle.id)"
43739
+ [matTooltipDisabled]="canvasInteractionActive()"
43740
+ (pointerdown)="onSelectedCanvasResizePointerDown(handle.id, $event)"
43741
+ (keydown)="onSelectedCanvasResizeKeydown(handle.id, $event)"
43742
+ (click)="$event.stopPropagation()"></button>
43743
+ }
43744
+ </div>
43745
+ }
42889
43746
  @if (shouldRenderWidgetContextOverlay(w)) {
42890
43747
  <praxis-dynamic-widget-context-toolbar
43748
+ [showResize]="canCustomizeCanvas()"
43749
+ [resizeLabel]="resizeWidgetLabel()"
43750
+ [resizeControls]="resizePopoverId"
43751
+ [resizeExpanded]="!!resizePopoverOrigin() && isWidgetSelected(w.key)"
43752
+ (resize)="toggleResizePopover(w.key)"
42891
43753
  [toolbarLabel]="widgetContextToolbarLabel(w.key)"
42892
43754
  [contextLabel]="widgetContextLabel(w)"
42893
43755
  [contextTooltip]="widgetContextTooltip(w)"
@@ -42916,7 +43778,7 @@ class DynamicWidgetPageComponent {
42916
43778
  }
42917
43779
  </div>
42918
43780
  }
42919
- @if (canvasPreviewItem()) {
43781
+ @if (canvasPreviewItem() && !hasResizeFeedback()) {
42920
43782
  <div
42921
43783
  class="pdx-canvas-snap-preview"
42922
43784
  [class.pdx-canvas-snap-preview--invalid]="canvasPreviewInvalid()"
@@ -43189,15 +44051,19 @@ class DynamicWidgetPageComponent {
43189
44051
  </div>
43190
44052
  }
43191
44053
  </div>
43192
- `, isInline: true, styles: [":host{display:block;min-width:0}.pdx-page-wrapper{position:relative;display:block;background:var(--pdx-page-bg, transparent);color:var(--pdx-page-color, inherit)}.pdx-page{display:grid;gap:var(--pdx-page-gap, 12px);grid-template-columns:minmax(0,1fr)}.pdx-page--canvas{align-items:start;grid-auto-flow:dense}.pdx-page-wrapper.editing .pdx-page--canvas{padding-block-start:var(--pdx-canvas-context-toolbar-safe-area, 22px);padding-block-end:22px;padding-inline:22px;box-sizing:border-box}.pdx-page-settings{position:sticky;top:8px;z-index:2;color:inherit;margin-bottom:6px}.pdx-widget{position:relative;background:var(--pfx-surface, transparent);border-radius:6px;min-width:0;min-height:0}.pdx-widget--interactive{cursor:pointer}.pdx-widget--selected:before{content:\"\";position:absolute;inset:0;border:1px dashed color-mix(in srgb,var(--md-sys-color-primary) 34%,transparent);border-radius:14px;pointer-events:none;z-index:1;box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent),0 8px 20px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent)}.pdx-widget--canvas{align-self:stretch;--pdx-resize-gradient-horizontal: linear-gradient( 90deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-vertical: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-diagonal-se: linear-gradient( 135deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-diagonal-sw: linear-gradient( 225deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-se)}.pdx-widget--canvas:after{content:\"\";position:absolute;inset:0;padding:2px;border-radius:14px;background:var(--pdx-active-resize-gradient);opacity:0;pointer-events:none;transition:opacity .14s ease,filter .14s ease;filter:saturate(1.02) drop-shadow(0 0 5px color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent));-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude}.pdx-widget--canvas-selected:before,.pdx-widget--canvas-blocked:before{content:\"\";position:absolute;inset:0;border-radius:14px;pointer-events:none;z-index:1;transition:opacity .14s ease,box-shadow .14s ease,border-color .14s ease}.pdx-widget--canvas-blocked:before{border:1px solid color-mix(in srgb,var(--md-sys-color-error) 74%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 20%,transparent),0 10px 24px color-mix(in srgb,var(--md-sys-color-error) 12%,transparent)}.pdx-widget--canvas:has(.pdx-canvas-resize:hover):after,.pdx-widget--canvas:has(.pdx-canvas-resize:focus-visible):after{opacity:.82}.pdx-widget--canvas:has(.pdx-canvas-resize--north:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-horizontal)}.pdx-widget--canvas:has(.pdx-canvas-resize--east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--east:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--west:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-vertical)}.pdx-widget--canvas:has(.pdx-canvas-resize--north-east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north-east:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south-west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south-west:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-sw)}.pdx-widget--canvas:has(.pdx-canvas-resize--north-west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north-west:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south-east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south-east:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-se)}.pdx-canvas-resize{position:absolute;z-index:7;border:0;padding:0;margin:0;background:transparent;touch-action:none;cursor:pointer;opacity:0;pointer-events:none;transform:scale(.94);transition:opacity .14s ease,transform .14s ease,filter .14s ease;filter:saturate(.9)}.pdx-widget--canvas:hover .pdx-canvas-resize,.pdx-widget--canvas:focus-within .pdx-canvas-resize,.pdx-widget--canvas-selected .pdx-canvas-resize{opacity:.88;pointer-events:auto;transform:scale(1);filter:saturate(1)}.pdx-widget--canvas:has(.pdx-shell.expanded) .pdx-canvas-resize,.pdx-widget--canvas:has(.pdx-shell.fullscreen) .pdx-canvas-resize{opacity:0;pointer-events:none;transform:scale(.94)}.pdx-canvas-resize-grip{display:block;width:9px;height:9px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant) 58%);background:color-mix(in srgb,var(--md-sys-color-surface) 92%,var(--md-sys-color-primary) 8%);box-shadow:0 1px 4px color-mix(in srgb,var(--md-sys-color-shadow) 10%,transparent);transition:transform .14s ease,border-color .14s ease,background .14s ease,box-shadow .14s ease}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{border-color:color-mix(in srgb,var(--md-sys-color-primary) 58%,var(--md-sys-color-outline-variant) 42%);background:color-mix(in srgb,var(--md-sys-color-surface) 84%,var(--md-sys-color-primary) 16%);box-shadow:0 2px 7px color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);transform:scale(1.04)}.pdx-canvas-resize--north,.pdx-canvas-resize--south{left:50%;width:52px;height:44px;margin-left:-26px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--north{top:-22px;cursor:ns-resize}.pdx-canvas-resize--south{bottom:-22px;cursor:ns-resize}.pdx-canvas-resize--east,.pdx-canvas-resize--west{top:50%;width:44px;height:52px;margin-top:-26px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--east{right:-22px;cursor:ew-resize}.pdx-canvas-resize--west{left:-22px;cursor:ew-resize}.pdx-canvas-resize--north-east,.pdx-canvas-resize--north-west,.pdx-canvas-resize--south-east,.pdx-canvas-resize--south-west{width:44px;height:44px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--north-east{top:-22px;right:-22px;cursor:nesw-resize}.pdx-canvas-resize--north-west{top:-22px;left:-22px;cursor:nwse-resize}.pdx-canvas-resize--south-east{bottom:-22px;right:-22px;cursor:nwse-resize}.pdx-canvas-resize--south-west{bottom:-22px;left:-22px;cursor:nesw-resize}.pdx-canvas-snap-preview{position:relative;align-self:stretch;border-radius:12px;pointer-events:none;z-index:0;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent),color-mix(in srgb,var(--md-sys-color-tertiary) 12%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 42%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 55%,transparent);animation:pdx-snap-preview-pulse .48s ease-out infinite alternate}.pdx-canvas-snap-preview:before,.pdx-canvas-snap-preview:after{content:\"\";position:absolute;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary) 82%,var(--md-sys-color-tertiary) 18%);opacity:.72}.pdx-canvas-snap-preview:before{inset:0 auto 0 0;width:3px}.pdx-canvas-snap-preview:after{inset:0 0 auto;height:3px}.pdx-canvas-snap-preview--invalid{background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-error) 18%,transparent),color-mix(in srgb,var(--md-sys-color-error-container) 22%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 58%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 40%,transparent)}.pdx-canvas-snap-preview--invalid:before,.pdx-canvas-snap-preview--invalid:after{background:color-mix(in srgb,var(--md-sys-color-error) 86%,var(--md-sys-color-error-container) 14%)}.pdx-canvas-resize:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{border-color:transparent;box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent),var(--mat-elevation-level3)}.pdx-canvas-resize--north:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-horizontal)}.pdx-canvas-resize--east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--east:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--west:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-vertical)}.pdx-canvas-resize--north-east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north-east:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south-west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south-west:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-diagonal-sw)}.pdx-canvas-resize--north-west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north-west:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south-east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south-east:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-diagonal-se)}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{transform:scale(1.08)}@keyframes pdx-snap-preview-pulse{0%{opacity:.72;transform:scale(.996)}to{opacity:1;transform:scale(1)}}.pdx-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.pdx-group{display:grid;gap:12px;grid-column:1 / -1;padding:12px;border-radius:16px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 76%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent)}.pdx-group--hero{padding:16px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-primary-container) 42%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-low) 86%,transparent))}.pdx-group--rail{align-self:start}.pdx-group-header{display:flex;align-items:center;justify-content:space-between;gap:12px}.pdx-group-title{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.pdx-group-content{display:grid;gap:12px}.pdx-group-content--stack{grid-template-columns:minmax(0,1fr)}.pdx-group-content--row{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.pdx-group-content--grid{grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.pdx-group-tabs{display:grid;gap:12px}.pdx-tabs-header{display:flex;flex-wrap:wrap;gap:8px}.pdx-tab-chip{appearance:none;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface);border-radius:999px;padding:8px 12px;font:inherit;cursor:pointer}.pdx-tab-chip.active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 78%,transparent);color:var(--md-sys-color-on-primary-container)}.pdx-page-wrapper.editing .pdx-widget-settings{opacity:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "component", type: DynamicWidgetContextToolbarComponent, selector: "praxis-dynamic-widget-context-toolbar", inputs: ["toolbarLabel", "contextLabel", "contextTooltip", "showAssistant", "assistantLabel", "assistantTooltip", "showComponentSettings", "componentSettingsBusy", "componentSettingsLabel", "componentSettingsTooltip", "showShellSettings", "shellSettingsLabel", "shellSettingsTooltip", "showRemove", "moreActionsLabel", "removeLabel"], outputs: ["assistant", "componentSettings", "shellSettings", "remove"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: WidgetShellComponent, selector: "praxis-widget-shell", inputs: ["shell", "context", "dragSurfaceEnabled", "dragSurfaceLabel"], outputs: ["action", "dragSurfacePointerDown", "dragSurfaceKeydown"] }] });
44054
+ `, isInline: true, styles: [":host{display:block;min-width:0}.pdx-page-wrapper{position:relative;display:block;background:var(--pdx-page-bg, transparent);color:var(--pdx-page-color, inherit)}.pdx-page{display:grid;gap:var(--pdx-page-gap, 12px);grid-template-columns:minmax(0,1fr)}.pdx-page--canvas{align-items:start;grid-auto-flow:dense}.pdx-page-wrapper.editing .pdx-page--canvas{padding-block-start:var(--pdx-canvas-context-toolbar-safe-area, 22px);padding-block-end:22px;padding-inline:22px;box-sizing:border-box}.pdx-page-settings{position:sticky;top:8px;z-index:2;color:inherit;margin-bottom:6px}.pdx-widget{position:relative;background:var(--pfx-surface, transparent);border-radius:6px;min-width:0;min-height:0}.pdx-widget--interactive{cursor:pointer}.pdx-widget--selected:before{content:\"\";position:absolute;inset:0;border:1px dashed color-mix(in srgb,var(--md-sys-color-primary) 34%,transparent);border-radius:14px;pointer-events:none;z-index:1;box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent),0 8px 20px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent)}.pdx-widget--canvas{align-self:stretch;--pdx-resize-gradient-diagonal-se: linear-gradient( 135deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-se)}.pdx-widget--canvas:after{content:\"\";position:absolute;inset:0;padding:2px;border-radius:14px;background:var(--pdx-active-resize-gradient);opacity:0;pointer-events:none;transition:opacity .14s ease,filter .14s ease;filter:saturate(1.02) drop-shadow(0 0 5px color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent));-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude}.pdx-widget--canvas-selected:before,.pdx-widget--canvas-blocked:before{content:\"\";position:absolute;inset:0;border-radius:14px;pointer-events:none;z-index:1;transition:opacity .14s ease,box-shadow .14s ease,border-color .14s ease}.pdx-widget--canvas-blocked:before{border:1px solid color-mix(in srgb,var(--md-sys-color-error) 74%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 20%,transparent),0 10px 24px color-mix(in srgb,var(--md-sys-color-error) 12%,transparent)}.pdx-widget--canvas-selected:has(>.pdx-canvas-edges .pdx-canvas-edge:hover):after,.pdx-widget--canvas-selected:has(>.pdx-canvas-edges .pdx-canvas-edge:focus-visible):after,.pdx-page-wrapper:has(>.pdx-canvas-resize-alternative .pdx-canvas-resize:hover)>.pdx-page>.pdx-widget--canvas-selected:after,.pdx-page-wrapper:has(>.pdx-canvas-resize-alternative .pdx-canvas-resize:focus-visible)>.pdx-page>.pdx-widget--canvas-selected:after{opacity:.82}.pdx-canvas-resize-alternative>summary{display:list-item;width:fit-content;padding:12px;min-height:44px;box-sizing:border-box;cursor:pointer;font-size:12px;color:var(--md-sys-color-on-surface-variant)}[data-resize-feedback=valid]{--pdx-resize-feedback-color: #27864b}[data-resize-feedback=minimum]{--pdx-resize-feedback-color: #bc8a00}[data-resize-feedback=blocked]{--pdx-resize-feedback-color: var(--md-sys-color-error)}.pdx-widget--canvas[data-resize-feedback]:after{background:var(--pdx-resize-feedback-color);opacity:1;z-index:2}.pdx-resize-feedback{position:absolute;inset-inline:8px;bottom:8px;width:fit-content;max-width:calc(100% - 16px);box-sizing:border-box;display:flex;align-items:center;gap:6px;padding:4px 8px;border:2px solid var(--pdx-resize-feedback-color);border-radius:8px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface);font-size:12px;line-height:18px;pointer-events:none;z-index:3}.pdx-resize-feedback mat-icon{flex:0 0 18px;width:18px;height:18px;font-size:18px}.pdx-resize-feedback--floating{position:static;max-width:min(320px,calc(100vw - 24px));overflow-wrap:anywhere}.pdx-resize-feedback--floating strong{display:block}.pdx-canvas-edges{position:absolute;inset:0;pointer-events:none;z-index:2}.pdx-canvas-edge{position:absolute;display:grid;place-items:center;box-sizing:border-box;width:24px;height:24px;padding:0;border:0;background:transparent;color:var(--md-sys-color-primary);pointer-events:auto;touch-action:none;transform:translate(-50%,-50%)}.pdx-canvas-edge:after{content:\"\";width:8px;height:8px;border:2px solid currentColor;border-radius:2px;background:var(--md-sys-color-surface)}.pdx-canvas-edge:hover:after,.pdx-canvas-edge:focus-visible:after{background:var(--md-sys-color-primary-container)}.pdx-canvas-edge[data-canvas-edge=north-west]{left:0;top:0;cursor:nwse-resize}.pdx-canvas-edge[data-canvas-edge=north]{left:50%;top:0;cursor:ns-resize}.pdx-canvas-edge[data-canvas-edge=north-east]{left:100%;top:0;cursor:nesw-resize}.pdx-canvas-edge[data-canvas-edge=east]{left:100%;top:50%;cursor:ew-resize}.pdx-canvas-edge[data-canvas-edge=south-east]{left:100%;top:100%;cursor:nwse-resize}.pdx-canvas-edge[data-canvas-edge=south]{left:50%;top:100%;cursor:ns-resize}.pdx-canvas-edge[data-canvas-edge=south-west]{left:0;top:100%;cursor:nesw-resize}.pdx-canvas-edge[data-canvas-edge=west]{left:0;top:50%;cursor:ew-resize}.pdx-page-wrapper:has(>.pdx-page>.pdx-widget>praxis-widget-shell>.pdx-shell.expanded)>.pdx-page>.pdx-widget>.pdx-canvas-edges,.pdx-page-wrapper:has(>.pdx-page>.pdx-widget>praxis-widget-shell>.pdx-shell.fullscreen)>.pdx-page>.pdx-widget>.pdx-canvas-edges{display:none}.pdx-canvas-tools{container-type:inline-size;display:flex;flex-wrap:wrap;align-items:end;gap:8px 16px;padding:12px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface-container-low);border-radius:12px}.pdx-resize-popover{box-sizing:border-box;display:grid;gap:12px;width:248px;max-width:calc(100vw - 24px);padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}.pdx-resize-popover header{display:flex;align-items:start;gap:8px}.pdx-resize-popover header div{display:grid;gap:4px;flex:1;min-width:0}.pdx-resize-popover strong{font-size:13px}.pdx-resize-popover header span{font-size:12px;overflow-wrap:anywhere;color:var(--md-sys-color-on-surface-variant)}.pdx-resize-popover header button{flex:0 0 44px;width:44px;height:44px}.pdx-resize-popover .pdx-canvas-tools-directions{grid-template-columns:repeat(3,44px);justify-content:space-between}.pdx-resize-popover--gesturing{background:transparent;border-color:transparent;pointer-events:none}.pdx-resize-popover--gesturing header,.pdx-resize-popover--gesturing .pdx-canvas-tools-hint,.pdx-resize-popover--gesturing .pdx-canvas-resize{visibility:hidden}.pdx-resize-popover--gesturing .pdx-canvas-resize.pdx-resize-active-handle{visibility:visible;pointer-events:auto;background:var(--md-sys-color-surface-container-high)}.pdx-canvas-tools-target{display:grid;gap:4px;flex:1 1 220px;min-width:0;font-size:12px;font-weight:600}.pdx-canvas-tools-target select{box-sizing:border-box;width:100%;min-width:0;min-height:44px;padding:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);font:inherit}.pdx-canvas-tools-directions{display:grid;grid-template-columns:repeat(4,44px);gap:4px;max-width:100%}@container (min-width: 650px){.pdx-canvas-tools-directions{grid-template-columns:repeat(8,44px)}}.pdx-canvas-tools-hint{flex-basis:100%;margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.pdx-page-wrapper:has(>.pdx-page>.pdx-widget>praxis-widget-shell>.pdx-shell.expanded)>.pdx-canvas-resize-alternative,.pdx-page-wrapper:has(>.pdx-page>.pdx-widget>praxis-widget-shell>.pdx-shell.fullscreen)>.pdx-canvas-resize-alternative{visibility:hidden}.pdx-canvas-resize{flex:0 0 44px;width:44px;height:44px;touch-action:none;cursor:grab}.pdx-canvas-resize:active{cursor:grabbing}.pdx-canvas-resize:focus-visible,.pdx-canvas-edge:focus-visible,.pdx-canvas-resize-alternative>summary:focus-visible,.pdx-canvas-tools-target select:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-canvas-snap-preview{position:relative;align-self:stretch;border-radius:12px;pointer-events:none;z-index:0;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent),color-mix(in srgb,var(--md-sys-color-tertiary) 12%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 42%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 55%,transparent);animation:pdx-snap-preview-pulse .48s ease-out infinite alternate}.pdx-canvas-snap-preview:before,.pdx-canvas-snap-preview:after{content:\"\";position:absolute;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary) 82%,var(--md-sys-color-tertiary) 18%);opacity:.72}.pdx-canvas-snap-preview:before{inset:0 auto 0 0;width:3px}.pdx-canvas-snap-preview:after{inset:0 0 auto;height:3px}.pdx-canvas-snap-preview--invalid{background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-error) 18%,transparent),color-mix(in srgb,var(--md-sys-color-error-container) 22%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 58%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 40%,transparent)}.pdx-canvas-snap-preview--invalid:before,.pdx-canvas-snap-preview--invalid:after{background:color-mix(in srgb,var(--md-sys-color-error) 86%,var(--md-sys-color-error-container) 14%)}@media(prefers-reduced-motion:reduce){.pdx-canvas-snap-preview{animation:none}.pdx-widget--canvas:after,.pdx-widget--canvas-selected:before,.pdx-widget--canvas-blocked:before{transition:none}}@media(forced-colors:active){.pdx-widget--canvas-selected:before{border:2px solid Highlight}.pdx-canvas-resize:focus-visible,.pdx-canvas-edge:focus-visible,.pdx-canvas-resize-alternative>summary:focus-visible,.pdx-canvas-tools-target select:focus-visible{outline-color:Highlight}}@keyframes pdx-snap-preview-pulse{0%{opacity:.72;transform:scale(.996)}to{opacity:1;transform:scale(1)}}.pdx-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.pdx-group{display:grid;gap:12px;grid-column:1 / -1;padding:12px;border-radius:16px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 76%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent)}.pdx-group--hero{padding:16px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-primary-container) 42%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-low) 86%,transparent))}.pdx-group--rail{align-self:start}.pdx-group-header{display:flex;align-items:center;justify-content:space-between;gap:12px}.pdx-group-title{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.pdx-group-content{display:grid;gap:12px}.pdx-group-content--stack{grid-template-columns:minmax(0,1fr)}.pdx-group-content--row{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.pdx-group-content--grid{grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.pdx-group-tabs{display:grid;gap:12px}.pdx-tabs-header{display:flex;flex-wrap:wrap;gap:8px}.pdx-tab-chip{appearance:none;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface);border-radius:999px;padding:8px 12px;font:inherit;cursor:pointer}.pdx-tab-chip.active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 78%,transparent);color:var(--md-sys-color-on-primary-container)}.pdx-page-wrapper.editing .pdx-widget-settings{opacity:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i4$2.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "component", type: DynamicWidgetContextToolbarComponent, selector: "praxis-dynamic-widget-context-toolbar", inputs: ["showResize", "resizeLabel", "resizeControls", "resizeExpanded", "toolbarLabel", "contextLabel", "contextTooltip", "showAssistant", "assistantLabel", "assistantTooltip", "showComponentSettings", "componentSettingsBusy", "componentSettingsLabel", "componentSettingsTooltip", "showShellSettings", "shellSettingsLabel", "shellSettingsTooltip", "showRemove", "moreActionsLabel", "removeLabel"], outputs: ["resize", "assistant", "componentSettings", "shellSettings", "remove"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: WidgetShellComponent, selector: "praxis-widget-shell", inputs: ["shell", "context", "dragSurfaceEnabled", "dragSurfaceLabel"], outputs: ["action", "dragSurfacePointerDown", "dragSurfaceKeydown"] }] });
43193
44055
  }
43194
44056
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicWidgetPageComponent, decorators: [{
43195
44057
  type: Component,
43196
- args: [{ selector: 'praxis-dynamic-page', standalone: true, imports: [
44058
+ args: [{ selector: 'praxis-dynamic-page', host: {
44059
+ '(lostpointercapture)': 'onCanvasPointerCancel($event)',
44060
+ '(window:keydown.escape)': 'onCanvasEscape($event)',
44061
+ }, standalone: true, imports: [
43197
44062
  CommonModule,
43198
44063
  MatIconModule,
43199
44064
  MatTooltipModule,
43200
44065
  PraxisIconButtonComponent,
44066
+ OverlayModule,
43201
44067
  DynamicWidgetContextToolbarComponent,
43202
44068
  DynamicWidgetLoaderDirective,
43203
44069
  WidgetShellComponent,
@@ -43222,6 +44088,106 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
43222
44088
  (click)="openPageSettings()"
43223
44089
  ></button>
43224
44090
  }
44091
+ @if (canCustomizeCanvas() && isCanvasMode()) {
44092
+ <details class="pdx-canvas-resize-alternative" data-testid="canvas-resize-alternative"
44093
+ [attr.inert]="resizePopoverOrigin() && selectedCanvasWidget() ? '' : null">
44094
+ <summary>{{ resizeAlternativeLabel() }}</summary>
44095
+ <div class="pdx-canvas-tools" data-testid="canvas-resize-tools"
44096
+ [attr.inert]="resizePopoverOrigin() && selectedCanvasWidget() ? '' : null"
44097
+ [attr.data-resize-widget-key]="selectedCanvasWidget()?.key || null"
44098
+ role="group" [attr.aria-label]="resizeWidgetLabel()">
44099
+ <label class="pdx-canvas-tools-target">
44100
+ <span>{{ resizeWidgetLabel() }}</span>
44101
+ <select data-testid="canvas-resize-target"
44102
+ [disabled]="canvasInteractionActive()"
44103
+ (change)="selectCanvasResizeTarget($event)">
44104
+ <option value="" disabled [selected]="!selectedCanvasWidget()">{{ resizeSelectLabel() }}</option>
44105
+ @for (widget of widgets(); track widget.key) {
44106
+ <option [value]="widget.key" [selected]="isWidgetSelected(widget.key)">{{ widgetContextLabel(widget) }}</option>
44107
+ }
44108
+ </select>
44109
+ </label>
44110
+ <div class="pdx-canvas-tools-directions">
44111
+ @for (handle of canvasResizeHandles; track handle.id) {
44112
+ <button class="pdx-canvas-resize" type="button"
44113
+ [praxisIconButton]="'ms:' + handle.icon"
44114
+ [attr.data-resize-handle]="handle.id"
44115
+ [attr.aria-label]="resizeHandleLabel(handle.id)"
44116
+ [matTooltip]="resizeHandleLabel(handle.id)"
44117
+ [disabled]="!selectedCanvasWidget()"
44118
+ (pointerdown)="onSelectedCanvasResizePointerDown(handle.id, $event)"
44119
+ (keydown)="onSelectedCanvasResizeKeydown(handle.id, $event)">
44120
+ </button>
44121
+ }
44122
+ </div>
44123
+ <p class="pdx-canvas-tools-hint">{{ resizeHelpLabel() }}</p>
44124
+ </div>
44125
+ </details>
44126
+ }
44127
+ @if (resizePopoverOrigin(); as origin) {
44128
+ @if (canCustomizeCanvas() && isCanvasMode() && selectedCanvasWidget(); as widget) {
44129
+ <ng-template cdkConnectedOverlay #resizeOverlay="cdkConnectedOverlay"
44130
+ [cdkConnectedOverlayOrigin]="origin"
44131
+ [cdkConnectedOverlayOpen]="true"
44132
+ [cdkConnectedOverlayPositions]="resizePopoverPositions"
44133
+ [cdkConnectedOverlayPush]="true"
44134
+ [cdkConnectedOverlayViewportMargin]="12"
44135
+ [cdkConnectedOverlayHasBackdrop]="false"
44136
+ (attach)="focusResizePopover(resizeOverlay.overlayRef.overlayElement)"
44137
+ (detach)="closeResizePopover(false)"
44138
+ (overlayOutsideClick)="onResizePopoverOutsideClick($event)"
44139
+ (overlayKeydown)="onResizePopoverKeydown($event)">
44140
+ <section class="pdx-resize-popover" data-testid="canvas-context-resize"
44141
+ [class.pdx-resize-popover--gesturing]="!!contextualResizeHandle()"
44142
+ role="region" [id]="resizePopoverId" [attr.aria-label]="resizeWidgetLabel()"
44143
+ (pointerdown)="$event.stopPropagation()" (click)="$event.stopPropagation()">
44144
+ <header>
44145
+ <div><strong>{{ resizeWidgetLabel() }}</strong><span>{{ widgetContextLabel(widget) }}</span></div>
44146
+ <button type="button" praxisIconButton="ms:close"
44147
+ [attr.aria-label]="resizeCloseLabel()" [matTooltip]="resizeCloseLabel()"
44148
+ (click)="closeResizePopover(true)"></button>
44149
+ </header>
44150
+ <div class="pdx-canvas-tools-directions">
44151
+ @for (handle of contextualResizeHandles; track handle.id) {
44152
+ <button class="pdx-canvas-resize" type="button"
44153
+ [praxisIconButton]="'ms:' + handle.icon"
44154
+ [attr.data-resize-handle]="handle.id"
44155
+ [style.grid-area]="resizePopoverGridArea(handle.id)"
44156
+ [class.pdx-resize-active-handle]="contextualResizeHandle() === handle.id"
44157
+ [attr.aria-label]="resizeHandleLabel(handle.id)"
44158
+ [matTooltip]="resizeHandleLabel(handle.id)"
44159
+ [matTooltipDisabled]="!!contextualResizeHandle()"
44160
+ (pointerdown)="onSelectedCanvasResizePointerDown(handle.id, $event)"
44161
+ (keydown)="onSelectedCanvasResizeKeydown(handle.id, $event)"></button>
44162
+ }
44163
+ </div>
44164
+ <p class="pdx-canvas-tools-hint">{{ resizeContextHelpLabel() }}</p>
44165
+ </section>
44166
+ </ng-template>
44167
+ }
44168
+ }
44169
+ @if (resizeFeedbackOrigin(); as origin) {
44170
+ @if (selectedCanvasWidget(); as widget) {
44171
+ @if (resizeFeedback(widget.key); as feedback) {
44172
+ <ng-template cdkConnectedOverlay #feedbackOverlay="cdkConnectedOverlay"
44173
+ [cdkConnectedOverlayOrigin]="origin"
44174
+ [cdkConnectedOverlayOpen]="true"
44175
+ [cdkConnectedOverlayPositions]="resizeFeedbackPositions"
44176
+ [cdkConnectedOverlayPush]="true"
44177
+ [cdkConnectedOverlayViewportMargin]="12"
44178
+ [cdkConnectedOverlayHasBackdrop]="false"
44179
+ [cdkConnectedOverlayDisableClose]="true"
44180
+ (attach)="prepareResizeFeedbackOverlay(feedbackOverlay.overlayRef.overlayElement)">
44181
+ <div class="pdx-resize-feedback pdx-resize-feedback--floating"
44182
+ data-testid="canvas-resize-feedback" [attr.data-feedback-widget]="widget.key"
44183
+ [attr.data-resize-feedback]="feedback">
44184
+ <mat-icon aria-hidden="true">{{ feedback === 'valid' ? 'check_circle' : feedback === 'minimum' ? 'warning' : 'block' }}</mat-icon>
44185
+ <span><strong>{{ widgetContextLabel(widget) }}</strong>{{ resizeFeedbackLabel(feedback) }}</span>
44186
+ </div>
44187
+ </ng-template>
44188
+ }
44189
+ }
44190
+ }
43225
44191
  <div
43226
44192
  #pageCanvasHost
43227
44193
  class="pdx-page"
@@ -43235,6 +44201,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
43235
44201
  <div
43236
44202
  class="pdx-widget pdx-widget--canvas"
43237
44203
  [attr.data-widget-key]="w.key"
44204
+ [attr.data-resize-feedback]="resizeFeedback(w.key)"
43238
44205
  [class.pdx-widget--interactive]="canSelectWidgets()"
43239
44206
  [class.pdx-widget--selected]="
43240
44207
  canSelectWidgets() && isWidgetSelected(w.key)
@@ -43248,30 +44215,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
43248
44215
  [class]="widgetClassName(w)"
43249
44216
  [style.gridColumn]="widgetGridColumn(w)"
43250
44217
  [style.gridRow]="widgetGridRow(w)"
44218
+ [style.height.px]="canvasShell.collapsed ? null : widgetContentSize(w)?.heightPx"
44219
+ [style.marginTop.px]="canvasShell.collapsed ? null : widgetContentSize(w)?.offsetTopPx"
44220
+ [style.alignSelf]="widgetContentSize(w) ? 'start' : null"
43251
44221
  [style.zIndex]="widgetZIndex(w)"
43252
44222
  (pointerdown)="selectWidget(w.key)"
43253
44223
  (click)="selectWidgetFromHostEvent(w.key, $event)"
43254
44224
  (focusin)="selectWidgetFromHostEvent(w.key, $event)"
43255
44225
  >
43256
- @if (canCustomizeCanvas()) {
43257
- @for (handle of canvasResizeHandles; track handle.id) {
43258
- <button
43259
- class="pdx-canvas-resize"
43260
- [ngClass]="handle.className"
43261
- type="button"
43262
- [attr.data-resize-handle]="handle.id"
43263
- [attr.aria-label]="resizeHandleLabel(handle.id)"
43264
- [title]="resizeHandleLabel(handle.id)"
43265
- (pointerdown)="startCanvasResize(w.key, handle.id, $event)"
43266
- (keydown)="
43267
- onCanvasResizeHandleKeydown(w.key, handle.id, $event)
43268
- "
43269
- >
43270
- <span class="pdx-canvas-resize-grip"></span>
43271
- </button>
43272
- }
43273
- }
43274
44226
  <praxis-widget-shell
44227
+ #canvasShell
43275
44228
  [shell]="widgetShellForRender(w)"
43276
44229
  [context]="mergedContext"
43277
44230
  [dragSurfaceEnabled]="canCustomizeCanvas() && isCanvasMode()"
@@ -43293,8 +44246,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
43293
44246
  (widgetDiagnostic)="onWidgetDiagnostic(w.key, $event)"
43294
44247
  ></ng-container>
43295
44248
  </praxis-widget-shell>
44249
+ @if (resizeFeedback(w.key); as feedback) {
44250
+ @if (!resizeFeedbackOrigin() || selectedCanvasWidget()?.key !== w.key) {
44251
+ <div class="pdx-resize-feedback" data-testid="canvas-resize-feedback">
44252
+ <mat-icon aria-hidden="true">{{ feedback === 'valid' ? 'check_circle' : feedback === 'minimum' ? 'warning' : 'block' }}</mat-icon>
44253
+ <span>{{ resizeFeedbackLabel(feedback) }}</span>
44254
+ </div>
44255
+ }
44256
+ }
44257
+ @if (canShowCanvasEdges(w.key)) {
44258
+ <div class="pdx-canvas-edges" data-testid="canvas-edge-controls"
44259
+ [attr.inert]="resizePopoverOrigin() ? '' : null"
44260
+ role="group" [attr.aria-label]="resizeWidgetLabel()">
44261
+ @for (handle of canvasResizeHandles; track handle.id) {
44262
+ <button type="button" class="pdx-canvas-edge"
44263
+ [attr.data-canvas-edge]="handle.id"
44264
+ [attr.aria-label]="resizeHandleLabel(handle.id)"
44265
+ [matTooltip]="resizeHandleLabel(handle.id)"
44266
+ [matTooltipDisabled]="canvasInteractionActive()"
44267
+ (pointerdown)="onSelectedCanvasResizePointerDown(handle.id, $event)"
44268
+ (keydown)="onSelectedCanvasResizeKeydown(handle.id, $event)"
44269
+ (click)="$event.stopPropagation()"></button>
44270
+ }
44271
+ </div>
44272
+ }
43296
44273
  @if (shouldRenderWidgetContextOverlay(w)) {
43297
44274
  <praxis-dynamic-widget-context-toolbar
44275
+ [showResize]="canCustomizeCanvas()"
44276
+ [resizeLabel]="resizeWidgetLabel()"
44277
+ [resizeControls]="resizePopoverId"
44278
+ [resizeExpanded]="!!resizePopoverOrigin() && isWidgetSelected(w.key)"
44279
+ (resize)="toggleResizePopover(w.key)"
43298
44280
  [toolbarLabel]="widgetContextToolbarLabel(w.key)"
43299
44281
  [contextLabel]="widgetContextLabel(w)"
43300
44282
  [contextTooltip]="widgetContextTooltip(w)"
@@ -43323,7 +44305,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
43323
44305
  }
43324
44306
  </div>
43325
44307
  }
43326
- @if (canvasPreviewItem()) {
44308
+ @if (canvasPreviewItem() && !hasResizeFeedback()) {
43327
44309
  <div
43328
44310
  class="pdx-canvas-snap-preview"
43329
44311
  [class.pdx-canvas-snap-preview--invalid]="canvasPreviewInvalid()"
@@ -43596,7 +44578,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
43596
44578
  </div>
43597
44579
  }
43598
44580
  </div>
43599
- `, styles: [":host{display:block;min-width:0}.pdx-page-wrapper{position:relative;display:block;background:var(--pdx-page-bg, transparent);color:var(--pdx-page-color, inherit)}.pdx-page{display:grid;gap:var(--pdx-page-gap, 12px);grid-template-columns:minmax(0,1fr)}.pdx-page--canvas{align-items:start;grid-auto-flow:dense}.pdx-page-wrapper.editing .pdx-page--canvas{padding-block-start:var(--pdx-canvas-context-toolbar-safe-area, 22px);padding-block-end:22px;padding-inline:22px;box-sizing:border-box}.pdx-page-settings{position:sticky;top:8px;z-index:2;color:inherit;margin-bottom:6px}.pdx-widget{position:relative;background:var(--pfx-surface, transparent);border-radius:6px;min-width:0;min-height:0}.pdx-widget--interactive{cursor:pointer}.pdx-widget--selected:before{content:\"\";position:absolute;inset:0;border:1px dashed color-mix(in srgb,var(--md-sys-color-primary) 34%,transparent);border-radius:14px;pointer-events:none;z-index:1;box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent),0 8px 20px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent)}.pdx-widget--canvas{align-self:stretch;--pdx-resize-gradient-horizontal: linear-gradient( 90deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-vertical: linear-gradient( 180deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-diagonal-se: linear-gradient( 135deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-resize-gradient-diagonal-sw: linear-gradient( 225deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-se)}.pdx-widget--canvas:after{content:\"\";position:absolute;inset:0;padding:2px;border-radius:14px;background:var(--pdx-active-resize-gradient);opacity:0;pointer-events:none;transition:opacity .14s ease,filter .14s ease;filter:saturate(1.02) drop-shadow(0 0 5px color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent));-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude}.pdx-widget--canvas-selected:before,.pdx-widget--canvas-blocked:before{content:\"\";position:absolute;inset:0;border-radius:14px;pointer-events:none;z-index:1;transition:opacity .14s ease,box-shadow .14s ease,border-color .14s ease}.pdx-widget--canvas-blocked:before{border:1px solid color-mix(in srgb,var(--md-sys-color-error) 74%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 20%,transparent),0 10px 24px color-mix(in srgb,var(--md-sys-color-error) 12%,transparent)}.pdx-widget--canvas:has(.pdx-canvas-resize:hover):after,.pdx-widget--canvas:has(.pdx-canvas-resize:focus-visible):after{opacity:.82}.pdx-widget--canvas:has(.pdx-canvas-resize--north:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-horizontal)}.pdx-widget--canvas:has(.pdx-canvas-resize--east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--east:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--west:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-vertical)}.pdx-widget--canvas:has(.pdx-canvas-resize--north-east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north-east:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south-west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south-west:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-sw)}.pdx-widget--canvas:has(.pdx-canvas-resize--north-west:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--north-west:focus-visible),.pdx-widget--canvas:has(.pdx-canvas-resize--south-east:hover),.pdx-widget--canvas:has(.pdx-canvas-resize--south-east:focus-visible){--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-se)}.pdx-canvas-resize{position:absolute;z-index:7;border:0;padding:0;margin:0;background:transparent;touch-action:none;cursor:pointer;opacity:0;pointer-events:none;transform:scale(.94);transition:opacity .14s ease,transform .14s ease,filter .14s ease;filter:saturate(.9)}.pdx-widget--canvas:hover .pdx-canvas-resize,.pdx-widget--canvas:focus-within .pdx-canvas-resize,.pdx-widget--canvas-selected .pdx-canvas-resize{opacity:.88;pointer-events:auto;transform:scale(1);filter:saturate(1)}.pdx-widget--canvas:has(.pdx-shell.expanded) .pdx-canvas-resize,.pdx-widget--canvas:has(.pdx-shell.fullscreen) .pdx-canvas-resize{opacity:0;pointer-events:none;transform:scale(.94)}.pdx-canvas-resize-grip{display:block;width:9px;height:9px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant) 58%);background:color-mix(in srgb,var(--md-sys-color-surface) 92%,var(--md-sys-color-primary) 8%);box-shadow:0 1px 4px color-mix(in srgb,var(--md-sys-color-shadow) 10%,transparent);transition:transform .14s ease,border-color .14s ease,background .14s ease,box-shadow .14s ease}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{border-color:color-mix(in srgb,var(--md-sys-color-primary) 58%,var(--md-sys-color-outline-variant) 42%);background:color-mix(in srgb,var(--md-sys-color-surface) 84%,var(--md-sys-color-primary) 16%);box-shadow:0 2px 7px color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);transform:scale(1.04)}.pdx-canvas-resize--north,.pdx-canvas-resize--south{left:50%;width:52px;height:44px;margin-left:-26px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--north{top:-22px;cursor:ns-resize}.pdx-canvas-resize--south{bottom:-22px;cursor:ns-resize}.pdx-canvas-resize--east,.pdx-canvas-resize--west{top:50%;width:44px;height:52px;margin-top:-26px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--east{right:-22px;cursor:ew-resize}.pdx-canvas-resize--west{left:-22px;cursor:ew-resize}.pdx-canvas-resize--north-east,.pdx-canvas-resize--north-west,.pdx-canvas-resize--south-east,.pdx-canvas-resize--south-west{width:44px;height:44px;display:flex;align-items:center;justify-content:center}.pdx-canvas-resize--north-east{top:-22px;right:-22px;cursor:nesw-resize}.pdx-canvas-resize--north-west{top:-22px;left:-22px;cursor:nwse-resize}.pdx-canvas-resize--south-east{bottom:-22px;right:-22px;cursor:nwse-resize}.pdx-canvas-resize--south-west{bottom:-22px;left:-22px;cursor:nesw-resize}.pdx-canvas-snap-preview{position:relative;align-self:stretch;border-radius:12px;pointer-events:none;z-index:0;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent),color-mix(in srgb,var(--md-sys-color-tertiary) 12%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 42%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 55%,transparent);animation:pdx-snap-preview-pulse .48s ease-out infinite alternate}.pdx-canvas-snap-preview:before,.pdx-canvas-snap-preview:after{content:\"\";position:absolute;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary) 82%,var(--md-sys-color-tertiary) 18%);opacity:.72}.pdx-canvas-snap-preview:before{inset:0 auto 0 0;width:3px}.pdx-canvas-snap-preview:after{inset:0 0 auto;height:3px}.pdx-canvas-snap-preview--invalid{background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-error) 18%,transparent),color-mix(in srgb,var(--md-sys-color-error-container) 22%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 58%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 40%,transparent)}.pdx-canvas-snap-preview--invalid:before,.pdx-canvas-snap-preview--invalid:after{background:color-mix(in srgb,var(--md-sys-color-error) 86%,var(--md-sys-color-error-container) 14%)}.pdx-canvas-resize:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{border-color:transparent;box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent),var(--mat-elevation-level3)}.pdx-canvas-resize--north:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-horizontal)}.pdx-canvas-resize--east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--east:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--west:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-vertical)}.pdx-canvas-resize--north-east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north-east:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south-west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south-west:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-diagonal-sw)}.pdx-canvas-resize--north-west:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--north-west:focus-visible .pdx-canvas-resize-grip,.pdx-canvas-resize--south-east:hover .pdx-canvas-resize-grip,.pdx-canvas-resize--south-east:focus-visible .pdx-canvas-resize-grip{background:var(--pdx-resize-gradient-diagonal-se)}.pdx-canvas-resize:hover .pdx-canvas-resize-grip,.pdx-canvas-resize:focus-visible .pdx-canvas-resize-grip{transform:scale(1.08)}@keyframes pdx-snap-preview-pulse{0%{opacity:.72;transform:scale(.996)}to{opacity:1;transform:scale(1)}}.pdx-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.pdx-group{display:grid;gap:12px;grid-column:1 / -1;padding:12px;border-radius:16px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 76%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent)}.pdx-group--hero{padding:16px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-primary-container) 42%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-low) 86%,transparent))}.pdx-group--rail{align-self:start}.pdx-group-header{display:flex;align-items:center;justify-content:space-between;gap:12px}.pdx-group-title{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.pdx-group-content{display:grid;gap:12px}.pdx-group-content--stack{grid-template-columns:minmax(0,1fr)}.pdx-group-content--row{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.pdx-group-content--grid{grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.pdx-group-tabs{display:grid;gap:12px}.pdx-tabs-header{display:flex;flex-wrap:wrap;gap:8px}.pdx-tab-chip{appearance:none;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface);border-radius:999px;padding:8px 12px;font:inherit;cursor:pointer}.pdx-tab-chip.active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 78%,transparent);color:var(--md-sys-color-on-primary-container)}.pdx-page-wrapper.editing .pdx-widget-settings{opacity:1}\n"] }]
44581
+ `, styles: [":host{display:block;min-width:0}.pdx-page-wrapper{position:relative;display:block;background:var(--pdx-page-bg, transparent);color:var(--pdx-page-color, inherit)}.pdx-page{display:grid;gap:var(--pdx-page-gap, 12px);grid-template-columns:minmax(0,1fr)}.pdx-page--canvas{align-items:start;grid-auto-flow:dense}.pdx-page-wrapper.editing .pdx-page--canvas{padding-block-start:var(--pdx-canvas-context-toolbar-safe-area, 22px);padding-block-end:22px;padding-inline:22px;box-sizing:border-box}.pdx-page-settings{position:sticky;top:8px;z-index:2;color:inherit;margin-bottom:6px}.pdx-widget{position:relative;background:var(--pfx-surface, transparent);border-radius:6px;min-width:0;min-height:0}.pdx-widget--interactive{cursor:pointer}.pdx-widget--selected:before{content:\"\";position:absolute;inset:0;border:1px dashed color-mix(in srgb,var(--md-sys-color-primary) 34%,transparent);border-radius:14px;pointer-events:none;z-index:1;box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent),0 8px 20px color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent)}.pdx-widget--canvas{align-self:stretch;--pdx-resize-gradient-diagonal-se: linear-gradient( 135deg, color-mix(in srgb, var(--md-sys-color-primary) 94%, white 6%), color-mix(in srgb, var(--md-sys-color-tertiary) 90%, white 10%), color-mix(in srgb, var(--md-sys-color-secondary) 88%, white 12%) );--pdx-active-resize-gradient: var(--pdx-resize-gradient-diagonal-se)}.pdx-widget--canvas:after{content:\"\";position:absolute;inset:0;padding:2px;border-radius:14px;background:var(--pdx-active-resize-gradient);opacity:0;pointer-events:none;transition:opacity .14s ease,filter .14s ease;filter:saturate(1.02) drop-shadow(0 0 5px color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent));-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude}.pdx-widget--canvas-selected:before,.pdx-widget--canvas-blocked:before{content:\"\";position:absolute;inset:0;border-radius:14px;pointer-events:none;z-index:1;transition:opacity .14s ease,box-shadow .14s ease,border-color .14s ease}.pdx-widget--canvas-blocked:before{border:1px solid color-mix(in srgb,var(--md-sys-color-error) 74%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 20%,transparent),0 10px 24px color-mix(in srgb,var(--md-sys-color-error) 12%,transparent)}.pdx-widget--canvas-selected:has(>.pdx-canvas-edges .pdx-canvas-edge:hover):after,.pdx-widget--canvas-selected:has(>.pdx-canvas-edges .pdx-canvas-edge:focus-visible):after,.pdx-page-wrapper:has(>.pdx-canvas-resize-alternative .pdx-canvas-resize:hover)>.pdx-page>.pdx-widget--canvas-selected:after,.pdx-page-wrapper:has(>.pdx-canvas-resize-alternative .pdx-canvas-resize:focus-visible)>.pdx-page>.pdx-widget--canvas-selected:after{opacity:.82}.pdx-canvas-resize-alternative>summary{display:list-item;width:fit-content;padding:12px;min-height:44px;box-sizing:border-box;cursor:pointer;font-size:12px;color:var(--md-sys-color-on-surface-variant)}[data-resize-feedback=valid]{--pdx-resize-feedback-color: #27864b}[data-resize-feedback=minimum]{--pdx-resize-feedback-color: #bc8a00}[data-resize-feedback=blocked]{--pdx-resize-feedback-color: var(--md-sys-color-error)}.pdx-widget--canvas[data-resize-feedback]:after{background:var(--pdx-resize-feedback-color);opacity:1;z-index:2}.pdx-resize-feedback{position:absolute;inset-inline:8px;bottom:8px;width:fit-content;max-width:calc(100% - 16px);box-sizing:border-box;display:flex;align-items:center;gap:6px;padding:4px 8px;border:2px solid var(--pdx-resize-feedback-color);border-radius:8px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface);font-size:12px;line-height:18px;pointer-events:none;z-index:3}.pdx-resize-feedback mat-icon{flex:0 0 18px;width:18px;height:18px;font-size:18px}.pdx-resize-feedback--floating{position:static;max-width:min(320px,calc(100vw - 24px));overflow-wrap:anywhere}.pdx-resize-feedback--floating strong{display:block}.pdx-canvas-edges{position:absolute;inset:0;pointer-events:none;z-index:2}.pdx-canvas-edge{position:absolute;display:grid;place-items:center;box-sizing:border-box;width:24px;height:24px;padding:0;border:0;background:transparent;color:var(--md-sys-color-primary);pointer-events:auto;touch-action:none;transform:translate(-50%,-50%)}.pdx-canvas-edge:after{content:\"\";width:8px;height:8px;border:2px solid currentColor;border-radius:2px;background:var(--md-sys-color-surface)}.pdx-canvas-edge:hover:after,.pdx-canvas-edge:focus-visible:after{background:var(--md-sys-color-primary-container)}.pdx-canvas-edge[data-canvas-edge=north-west]{left:0;top:0;cursor:nwse-resize}.pdx-canvas-edge[data-canvas-edge=north]{left:50%;top:0;cursor:ns-resize}.pdx-canvas-edge[data-canvas-edge=north-east]{left:100%;top:0;cursor:nesw-resize}.pdx-canvas-edge[data-canvas-edge=east]{left:100%;top:50%;cursor:ew-resize}.pdx-canvas-edge[data-canvas-edge=south-east]{left:100%;top:100%;cursor:nwse-resize}.pdx-canvas-edge[data-canvas-edge=south]{left:50%;top:100%;cursor:ns-resize}.pdx-canvas-edge[data-canvas-edge=south-west]{left:0;top:100%;cursor:nesw-resize}.pdx-canvas-edge[data-canvas-edge=west]{left:0;top:50%;cursor:ew-resize}.pdx-page-wrapper:has(>.pdx-page>.pdx-widget>praxis-widget-shell>.pdx-shell.expanded)>.pdx-page>.pdx-widget>.pdx-canvas-edges,.pdx-page-wrapper:has(>.pdx-page>.pdx-widget>praxis-widget-shell>.pdx-shell.fullscreen)>.pdx-page>.pdx-widget>.pdx-canvas-edges{display:none}.pdx-canvas-tools{container-type:inline-size;display:flex;flex-wrap:wrap;align-items:end;gap:8px 16px;padding:12px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface-container-low);border-radius:12px}.pdx-resize-popover{box-sizing:border-box;display:grid;gap:12px;width:248px;max-width:calc(100vw - 24px);padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}.pdx-resize-popover header{display:flex;align-items:start;gap:8px}.pdx-resize-popover header div{display:grid;gap:4px;flex:1;min-width:0}.pdx-resize-popover strong{font-size:13px}.pdx-resize-popover header span{font-size:12px;overflow-wrap:anywhere;color:var(--md-sys-color-on-surface-variant)}.pdx-resize-popover header button{flex:0 0 44px;width:44px;height:44px}.pdx-resize-popover .pdx-canvas-tools-directions{grid-template-columns:repeat(3,44px);justify-content:space-between}.pdx-resize-popover--gesturing{background:transparent;border-color:transparent;pointer-events:none}.pdx-resize-popover--gesturing header,.pdx-resize-popover--gesturing .pdx-canvas-tools-hint,.pdx-resize-popover--gesturing .pdx-canvas-resize{visibility:hidden}.pdx-resize-popover--gesturing .pdx-canvas-resize.pdx-resize-active-handle{visibility:visible;pointer-events:auto;background:var(--md-sys-color-surface-container-high)}.pdx-canvas-tools-target{display:grid;gap:4px;flex:1 1 220px;min-width:0;font-size:12px;font-weight:600}.pdx-canvas-tools-target select{box-sizing:border-box;width:100%;min-width:0;min-height:44px;padding:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);font:inherit}.pdx-canvas-tools-directions{display:grid;grid-template-columns:repeat(4,44px);gap:4px;max-width:100%}@container (min-width: 650px){.pdx-canvas-tools-directions{grid-template-columns:repeat(8,44px)}}.pdx-canvas-tools-hint{flex-basis:100%;margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.pdx-page-wrapper:has(>.pdx-page>.pdx-widget>praxis-widget-shell>.pdx-shell.expanded)>.pdx-canvas-resize-alternative,.pdx-page-wrapper:has(>.pdx-page>.pdx-widget>praxis-widget-shell>.pdx-shell.fullscreen)>.pdx-canvas-resize-alternative{visibility:hidden}.pdx-canvas-resize{flex:0 0 44px;width:44px;height:44px;touch-action:none;cursor:grab}.pdx-canvas-resize:active{cursor:grabbing}.pdx-canvas-resize:focus-visible,.pdx-canvas-edge:focus-visible,.pdx-canvas-resize-alternative>summary:focus-visible,.pdx-canvas-tools-target select:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-canvas-snap-preview{position:relative;align-self:stretch;border-radius:12px;pointer-events:none;z-index:0;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent),color-mix(in srgb,var(--md-sys-color-tertiary) 12%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 42%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 55%,transparent);animation:pdx-snap-preview-pulse .48s ease-out infinite alternate}.pdx-canvas-snap-preview:before,.pdx-canvas-snap-preview:after{content:\"\";position:absolute;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary) 82%,var(--md-sys-color-tertiary) 18%);opacity:.72}.pdx-canvas-snap-preview:before{inset:0 auto 0 0;width:3px}.pdx-canvas-snap-preview:after{inset:0 0 auto;height:3px}.pdx-canvas-snap-preview--invalid{background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-error) 18%,transparent),color-mix(in srgb,var(--md-sys-color-error-container) 22%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-error) 58%,transparent),inset 0 0 0 2px color-mix(in srgb,var(--md-sys-color-surface) 40%,transparent)}.pdx-canvas-snap-preview--invalid:before,.pdx-canvas-snap-preview--invalid:after{background:color-mix(in srgb,var(--md-sys-color-error) 86%,var(--md-sys-color-error-container) 14%)}@media(prefers-reduced-motion:reduce){.pdx-canvas-snap-preview{animation:none}.pdx-widget--canvas:after,.pdx-widget--canvas-selected:before,.pdx-widget--canvas-blocked:before{transition:none}}@media(forced-colors:active){.pdx-widget--canvas-selected:before{border:2px solid Highlight}.pdx-canvas-resize:focus-visible,.pdx-canvas-edge:focus-visible,.pdx-canvas-resize-alternative>summary:focus-visible,.pdx-canvas-tools-target select:focus-visible{outline-color:Highlight}}@keyframes pdx-snap-preview-pulse{0%{opacity:.72;transform:scale(.996)}to{opacity:1;transform:scale(1)}}.pdx-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.pdx-group{display:grid;gap:12px;grid-column:1 / -1;padding:12px;border-radius:16px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 76%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent)}.pdx-group--hero{padding:16px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-primary-container) 42%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-low) 86%,transparent))}.pdx-group--rail{align-self:start}.pdx-group-header{display:flex;align-items:center;justify-content:space-between;gap:12px}.pdx-group-title{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.pdx-group-content{display:grid;gap:12px}.pdx-group-content--stack{grid-template-columns:minmax(0,1fr)}.pdx-group-content--row{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.pdx-group-content--grid{grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}.pdx-group-tabs{display:grid;gap:12px}.pdx-tabs-header{display:flex;flex-wrap:wrap;gap:8px}.pdx-tab-chip{appearance:none;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface);border-radius:999px;padding:8px 12px;font:inherit;cursor:pointer}.pdx-tab-chip.active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 78%,transparent);color:var(--md-sys-color-on-primary-container)}.pdx-page-wrapper.editing .pdx-widget-settings{opacity:1}\n"] }]
43600
44582
  }], ctorParameters: () => [], propDecorators: { pageCanvasHost: [{
43601
44583
  type: ViewChild,
43602
44584
  args: ['pageCanvasHost']
@@ -44701,7 +45683,7 @@ class PraxisRelatedResourceOutletComponent {
44701
45683
  </div>
44702
45684
  }
44703
45685
  </section>
44704
- `, isInline: true, styles: [":host{display:block;min-width:0}.pdx-related-outlet{display:block;min-width:0;color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet__state{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--pdx-related-outlet-gap, 12px);min-height:var(--pdx-related-outlet-min-height, 64px);padding:var(--pdx-related-outlet-padding, 12px);border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .16));border-radius:var(--pdx-related-outlet-radius, 8px);background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface, transparent))}.pdx-related-outlet--compact .pdx-related-outlet__state{min-height:var(--pdx-related-outlet-compact-min-height, 48px);padding:var(--pdx-related-outlet-compact-padding, 8px 10px)}.pdx-related-outlet__state--ready{border-color:var(--md-sys-color-primary, currentColor)}.pdx-related-outlet__icon{display:inline-grid;place-items:center;width:32px;height:32px;color:var(--md-sys-color-primary, currentColor)}.pdx-related-outlet__state--busy .pdx-related-outlet__icon{color:var(--md-sys-color-secondary, currentColor)}.pdx-related-outlet__copy{display:grid;gap:2px;min-width:0}.pdx-related-outlet__copy h3,.pdx-related-outlet__copy p{margin:0}.pdx-related-outlet__copy h3{font:var(--md-sys-typescale-title-small, 600 .95rem/1.25rem system-ui);color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet__copy p{font:var(--md-sys-typescale-body-small, 400 .82rem/1.15rem system-ui);color:var(--md-sys-color-on-surface-variant, currentColor)}@media(max-width:600px){.pdx-related-outlet__state{grid-template-columns:auto minmax(0,1fr)}.pdx-related-outlet__state button{grid-column:1 / -1;justify-self:start}}\n"], dependencies: [{ kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], exportAs: ["dynamicWidgetLoader"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i3.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }] });
45686
+ `, isInline: true, styles: [":host{display:block;min-width:0}.pdx-related-outlet{display:block;min-width:0;color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet__state{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--pdx-related-outlet-gap, 12px);min-height:var(--pdx-related-outlet-min-height, 64px);padding:var(--pdx-related-outlet-padding, 12px);border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .16));border-radius:var(--pdx-related-outlet-radius, 8px);background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface, transparent))}.pdx-related-outlet--compact .pdx-related-outlet__state{min-height:var(--pdx-related-outlet-compact-min-height, 48px);padding:var(--pdx-related-outlet-compact-padding, 8px 10px)}.pdx-related-outlet__state--ready{border-color:var(--md-sys-color-primary, currentColor)}.pdx-related-outlet__icon{display:inline-grid;place-items:center;width:32px;height:32px;color:var(--md-sys-color-primary, currentColor)}.pdx-related-outlet__state--busy .pdx-related-outlet__icon{color:var(--md-sys-color-secondary, currentColor)}.pdx-related-outlet__copy{display:grid;gap:2px;min-width:0}.pdx-related-outlet__copy h3,.pdx-related-outlet__copy p{margin:0}.pdx-related-outlet__copy h3{font:var(--md-sys-typescale-title-small, 600 .95rem/1.25rem system-ui);color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet__copy p{font:var(--md-sys-typescale-body-small, 400 .82rem/1.15rem system-ui);color:var(--md-sys-color-on-surface-variant, currentColor)}@media(max-width:600px){.pdx-related-outlet__state{grid-template-columns:auto minmax(0,1fr)}.pdx-related-outlet__state button{grid-column:1 / -1;justify-self:start}}\n"], dependencies: [{ kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], exportAs: ["dynamicWidgetLoader"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i3$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }] });
44705
45687
  }
44706
45688
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisRelatedResourceOutletComponent, decorators: [{
44707
45689
  type: Component,
@@ -44964,7 +45946,7 @@ class PraxisIconPickerComponent {
44964
45946
  }
44965
45947
  </div>
44966
45948
  </div>
44967
- `, isInline: true, styles: [".pip-root{display:flex;flex-direction:column;min-width:340px;max-width:760px;max-height:80vh;overflow:hidden;padding:16px;color:var(--md-sys-color-on-surface)}.pip-head{display:flex;gap:12px;align-items:center;margin-bottom:12px;flex-wrap:wrap}.pip-search{flex:1;min-width:180px}.pip-spacer{flex:1}.pip-body{flex:1;overflow:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px;padding:4px}.pip-item{display:flex;gap:10px;align-items:center;justify-content:flex-start;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface);color:inherit;cursor:pointer;transition:background-color .18s ease,border-color .18s ease,box-shadow .18s ease}.pip-item:hover{background:var(--md-sys-color-surface-container)}.pip-item:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pip-item.selected{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px var(--md-sys-color-primary)}.pip-name{font-size:12px;color:var(--md-sys-color-on-surface-variant);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.pip-hint{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin:-6px 0 8px}.pip-stats{display:flex;justify-content:space-between;gap:8px;font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-bottom:8px}.pip-shortcut{opacity:.9}.pip-empty{padding:12px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:10px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);margin-top:8px}.pip-footer{display:flex;gap:12px;align-items:center;margin-top:10px}.pip-typed{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;color:var(--md-sys-color-on-surface)}.pip-family{display:flex;align-items:center}.pip-family .mat-mdc-chip-listbox{min-width:260px}.pip-root .mat-icon{font-family:Material Icons,Material Symbols Outlined,Material Symbols Rounded,Material Symbols Sharp!important;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24;color:currentColor}.material-symbols-outlined{font-family:Material Symbols Outlined;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}.material-symbols-rounded{font-family:Material Symbols Rounded;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}.material-symbols-sharp{font-family:Material Symbols Sharp;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i8$1.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i8$1.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
45949
+ `, isInline: true, styles: [".pip-root{display:flex;flex-direction:column;min-width:340px;max-width:760px;max-height:80vh;overflow:hidden;padding:16px;color:var(--md-sys-color-on-surface)}.pip-head{display:flex;gap:12px;align-items:center;margin-bottom:12px;flex-wrap:wrap}.pip-search{flex:1;min-width:180px}.pip-spacer{flex:1}.pip-body{flex:1;overflow:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px;padding:4px}.pip-item{display:flex;gap:10px;align-items:center;justify-content:flex-start;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface);color:inherit;cursor:pointer;transition:background-color .18s ease,border-color .18s ease,box-shadow .18s ease}.pip-item:hover{background:var(--md-sys-color-surface-container)}.pip-item:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pip-item.selected{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px var(--md-sys-color-primary)}.pip-name{font-size:12px;color:var(--md-sys-color-on-surface-variant);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.pip-hint{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin:-6px 0 8px}.pip-stats{display:flex;justify-content:space-between;gap:8px;font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-bottom:8px}.pip-shortcut{opacity:.9}.pip-empty{padding:12px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:10px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container);margin-top:8px}.pip-footer{display:flex;gap:12px;align-items:center;margin-top:10px}.pip-typed{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:12px;color:var(--md-sys-color-on-surface)}.pip-family{display:flex;align-items:center}.pip-family .mat-mdc-chip-listbox{min-width:260px}.pip-root .mat-icon{font-family:Material Icons,Material Symbols Outlined,Material Symbols Rounded,Material Symbols Sharp!important;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24;color:currentColor}.material-symbols-outlined{font-family:Material Symbols Outlined;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}.material-symbols-rounded{font-family:Material Symbols Rounded;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}.material-symbols-sharp{font-family:Material Symbols Sharp;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 24}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i8.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { 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: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
44968
45950
  }
44969
45951
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisIconPickerComponent, decorators: [{
44970
45952
  type: Component,
@@ -45586,7 +46568,7 @@ class PraxisRelatedResourceOutletConfigEditorComponent {
45586
46568
  </span>
45587
46569
  </aside>
45588
46570
  </form>
45589
- `, isInline: true, styles: [":host{display:block;color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet-editor{display:grid;gap:var(--pdx-spacing-lg, 24px);padding:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__header,.pdx-related-outlet-editor__boundary{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__header-icon{display:inline-grid;place-items:center;width:40px;height:40px;border-radius:var(--md-sys-shape-corner-medium, 12px);color:var(--md-sys-color-primary, currentColor);background:var(--md-sys-color-primary-container, transparent)}.pdx-related-outlet-editor__header strong,.pdx-related-outlet-editor__boundary strong,.pdx-related-outlet-editor__header small,.pdx-related-outlet-editor__boundary small{display:block}.pdx-related-outlet-editor__header strong{font:var(--md-sys-typescale-title-medium, 600 1rem/1.4 system-ui)}.pdx-related-outlet-editor__header small,.pdx-related-outlet-editor__boundary small,.pdx-related-outlet-editor__section-heading p{color:var(--md-sys-color-on-surface-variant, currentColor)}.pdx-related-outlet-editor__section{display:grid;gap:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__section-heading h3,.pdx-related-outlet-editor__section-heading p{margin:0}.pdx-related-outlet-editor__section-heading h3{font:var(--md-sys-typescale-title-small, 600 .95rem/1.3 system-ui)}.pdx-related-outlet-editor__section-heading p{margin-top:4px;font:var(--md-sys-typescale-body-small, 400 .82rem/1.35 system-ui)}.pdx-related-outlet-editor__fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__wide{grid-column:1 / -1}.pdx-related-outlet-editor__choice-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__appearance-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr));gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__appearance-cluster{display:grid;align-content:start;gap:var(--pdx-spacing-sm, 12px);min-width:0}.pdx-related-outlet-editor__appearance-cluster--wide{grid-column:1 / -1}.pdx-related-outlet-editor__appearance-cluster mat-button-toggle-group{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,132px),1fr))}.pdx-related-outlet-editor__appearance-cluster mat-button-toggle{min-height:44px}.pdx-related-outlet-editor__density-cluster{gap:var(--pdx-spacing-md, 16px)}fieldset{min-width:0;margin:0;padding:0;border:0}legend{margin-bottom:8px;font:var(--md-sys-typescale-label-large, 500 .88rem/1.2 system-ui)}mat-button-toggle-group{width:100%}mat-button-toggle{flex:1 1 0}mat-button-toggle mat-icon{margin-right:6px}.pdx-related-outlet-editor__boundary{padding:var(--pdx-spacing-sm, 12px);border:1px solid var(--md-sys-color-outline-variant, currentColor);border-radius:var(--md-sys-shape-corner-medium, 12px);background:var(--md-sys-color-surface-container-low, transparent)}.pdx-related-outlet-editor__boundary mat-icon{color:var(--md-sys-color-on-surface-variant, currentColor)}@media(max-width:640px){.pdx-related-outlet-editor__fields,.pdx-related-outlet-editor__choice-grid{grid-template-columns:minmax(0,1fr)}.pdx-related-outlet-editor__wide{grid-column:auto}mat-button-toggle-group{display:grid}}@media(max-width:420px){.pdx-related-outlet-editor__appearance-cluster mat-button-toggle-group{grid-template-columns:minmax(0,1fr)}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i3$1.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i3$1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
46571
+ `, isInline: true, styles: [":host{display:block;color:var(--md-sys-color-on-surface, currentColor)}.pdx-related-outlet-editor{display:grid;gap:var(--pdx-spacing-lg, 24px);padding:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__header,.pdx-related-outlet-editor__boundary{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__header-icon{display:inline-grid;place-items:center;width:40px;height:40px;border-radius:var(--md-sys-shape-corner-medium, 12px);color:var(--md-sys-color-primary, currentColor);background:var(--md-sys-color-primary-container, transparent)}.pdx-related-outlet-editor__header strong,.pdx-related-outlet-editor__boundary strong,.pdx-related-outlet-editor__header small,.pdx-related-outlet-editor__boundary small{display:block}.pdx-related-outlet-editor__header strong{font:var(--md-sys-typescale-title-medium, 600 1rem/1.4 system-ui)}.pdx-related-outlet-editor__header small,.pdx-related-outlet-editor__boundary small,.pdx-related-outlet-editor__section-heading p{color:var(--md-sys-color-on-surface-variant, currentColor)}.pdx-related-outlet-editor__section{display:grid;gap:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__section-heading h3,.pdx-related-outlet-editor__section-heading p{margin:0}.pdx-related-outlet-editor__section-heading h3{font:var(--md-sys-typescale-title-small, 600 .95rem/1.3 system-ui)}.pdx-related-outlet-editor__section-heading p{margin-top:4px;font:var(--md-sys-typescale-body-small, 400 .82rem/1.35 system-ui)}.pdx-related-outlet-editor__fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__wide{grid-column:1 / -1}.pdx-related-outlet-editor__choice-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--pdx-spacing-md, 16px)}.pdx-related-outlet-editor__appearance-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr));gap:var(--pdx-spacing-sm, 12px)}.pdx-related-outlet-editor__appearance-cluster{display:grid;align-content:start;gap:var(--pdx-spacing-sm, 12px);min-width:0}.pdx-related-outlet-editor__appearance-cluster--wide{grid-column:1 / -1}.pdx-related-outlet-editor__appearance-cluster mat-button-toggle-group{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,132px),1fr))}.pdx-related-outlet-editor__appearance-cluster mat-button-toggle{min-height:44px}.pdx-related-outlet-editor__density-cluster{gap:var(--pdx-spacing-md, 16px)}fieldset{min-width:0;margin:0;padding:0;border:0}legend{margin-bottom:8px;font:var(--md-sys-typescale-label-large, 500 .88rem/1.2 system-ui)}mat-button-toggle-group{width:100%}mat-button-toggle{flex:1 1 0}mat-button-toggle mat-icon{margin-right:6px}.pdx-related-outlet-editor__boundary{padding:var(--pdx-spacing-sm, 12px);border:1px solid var(--md-sys-color-outline-variant, currentColor);border-radius:var(--md-sys-shape-corner-medium, 12px);background:var(--md-sys-color-surface-container-low, transparent)}.pdx-related-outlet-editor__boundary mat-icon{color:var(--md-sys-color-on-surface-variant, currentColor)}@media(max-width:640px){.pdx-related-outlet-editor__fields,.pdx-related-outlet-editor__choice-grid{grid-template-columns:minmax(0,1fr)}.pdx-related-outlet-editor__wide{grid-column:auto}mat-button-toggle-group{display:grid}}@media(max-width:420px){.pdx-related-outlet-editor__appearance-cluster mat-button-toggle-group{grid-template-columns:minmax(0,1fr)}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i3$2.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i3$2.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
45590
46572
  }
45591
46573
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisRelatedResourceOutletConfigEditorComponent, decorators: [{
45592
46574
  type: Component,