@praxisui/dialog 10.0.0-rc.37 → 10.0.0-rc.39

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,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-10-21T22:13:30.176Z",
3
+ "generatedAt": "2026-10-26T17:40:14.409Z",
4
4
  "packageName": "@praxisui/dialog",
5
- "packageVersion": "10.0.0-rc.37",
5
+ "packageVersion": "10.0.0-rc.39",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 1,
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Directive, EventEmitter, inject, HostBinding, ContentChild, ViewChild, Output, Input, ViewEncapsulation, ChangeDetectionStrategy, Component, Injectable, Injector, ApplicationRef, TemplateRef, ENVIRONMENT_INITIALIZER } from '@angular/core';
2
+ import { InjectionToken, Directive, EventEmitter, inject, HostBinding, ContentChild, ViewChild, Output, Input, ViewEncapsulation, ChangeDetectionStrategy, Component, Injectable, Injector, ApplicationRef, TemplateRef, signal, computed, ENVIRONMENT_INITIALIZER } from '@angular/core';
3
3
  import { Subject, firstValueFrom } from 'rxjs';
4
4
  import * as i1 from '@angular/common';
5
5
  import { CommonModule } from '@angular/common';
@@ -9,7 +9,7 @@ import * as i3 from '@angular/cdk/a11y';
9
9
  import { A11yModule } from '@angular/cdk/a11y';
10
10
  import * as i4 from '@angular/material/icon';
11
11
  import { MatIconModule } from '@angular/material/icon';
12
- import { PraxisIconDirective, PraxisLayerScaleStyleService, SURFACE_DRAWER_REF, SURFACE_DRAWER_CONTENT_DATA, GlobalConfigService, GLOBAL_DIALOG_SERVICE, ComponentMetadataRegistry, markGlobalActionProviderOperational, GLOBAL_SURFACE_SERVICE, SurfaceOpenMaterializerService, LoggerService, SURFACE_DRAWER_BRIDGE, PraxisSurfaceHostComponent, SurfaceNavigationError } from '@praxisui/core';
12
+ import { PraxisIconDirective, PraxisLayerScaleStyleService, SURFACE_DRAWER_REF, SURFACE_DRAWER_CONTENT_DATA, GlobalConfigService, GLOBAL_DIALOG_SERVICE, ComponentMetadataRegistry, markGlobalActionProviderOperational, GLOBAL_SURFACE_SERVICE, SurfaceOpenMaterializerService, LoggerService, SURFACE_DRAWER_BRIDGE, PraxisSurfaceHostComponent, SurfaceNavigationError, PraxisI18nService, PraxisResourceIdentityComponent, isResourceQuickViewAnchorValid, PRAXIS_QUICK_VIEW_PRESENTER } from '@praxisui/core';
13
13
  import { Overlay, OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
14
14
  import * as i1$1 from '@angular/forms';
15
15
  import { FormsModule } from '@angular/forms';
@@ -1574,6 +1574,721 @@ function providePraxisSurfaceGlobalActions() {
1574
1574
  };
1575
1575
  }
1576
1576
 
1577
+ class PraxisQuickViewOverlayComponent {
1578
+ i18n = inject(PraxisI18nService, { optional: true });
1579
+ resolution = signal(null, ...(ngDevMode ? [{ debugName: "resolution" }] : /* istanbul ignore next */ []));
1580
+ bodyRenderer = signal(null, ...(ngDevMode ? [{ debugName: "bodyRenderer" }] : /* istanbul ignore next */ []));
1581
+ narrowModalMode = signal(false, ...(ngDevMode ? [{ debugName: "narrowModalMode" }] : /* istanbul ignore next */ []));
1582
+ pointerEnter = new EventEmitter();
1583
+ pointerLeave = new EventEmitter();
1584
+ openDetail = new EventEmitter();
1585
+ copyValue = new EventEmitter();
1586
+ dismiss = new EventEmitter();
1587
+ dialogSurface;
1588
+ ctaButton;
1589
+ closeButton;
1590
+ summaryItems = computed(() => this.resolution()?.summaryItems ?? [], ...(ngDevMode ? [{ debugName: "summaryItems" }] : /* istanbul ignore next */ []));
1591
+ headerIdentity = computed(() => {
1592
+ const identity = this.resolution()?.identity ?? null;
1593
+ if (!identity) {
1594
+ return null;
1595
+ }
1596
+ if (!this.shouldUseCustomBodyRenderer() && this.summaryItems().length > 0) {
1597
+ return {
1598
+ ...identity,
1599
+ metadata: [],
1600
+ };
1601
+ }
1602
+ return identity;
1603
+ }, ...(ngDevMode ? [{ debugName: "headerIdentity" }] : /* istanbul ignore next */ []));
1604
+ closeAriaLabel = computed(() => this.translate('quickView.closeAriaLabel', 'Fechar visualização rápida'), ...(ngDevMode ? [{ debugName: "closeAriaLabel" }] : /* istanbul ignore next */ []));
1605
+ copyButtonLabel = computed(() => this.translate('quickView.copyAction', 'Copiar'), ...(ngDevMode ? [{ debugName: "copyButtonLabel" }] : /* istanbul ignore next */ []));
1606
+ accessibleLabel = computed(() => {
1607
+ const res = this.resolution();
1608
+ const identityTitle = String(res?.identity?.title?.value ?? res?.identity?.displayLabel ?? '').trim();
1609
+ return (identityTitle ||
1610
+ res?.title ||
1611
+ this.translate('quickView.dialogAriaLabel', 'Visualização rápida do registro'));
1612
+ }, ...(ngDevMode ? [{ debugName: "accessibleLabel" }] : /* istanbul ignore next */ []));
1613
+ translate(key, fallback) {
1614
+ if (!this.i18n) {
1615
+ return fallback;
1616
+ }
1617
+ const translated = this.i18n.t(key, undefined, fallback);
1618
+ return typeof translated === 'string' && translated.trim().length > 0
1619
+ ? translated
1620
+ : fallback;
1621
+ }
1622
+ shouldUseCustomBodyRenderer = computed(() => {
1623
+ const res = this.resolution();
1624
+ const renderer = this.bodyRenderer();
1625
+ return Boolean(res?.state === 'ready' && renderer && res.binding.contentRef);
1626
+ }, ...(ngDevMode ? [{ debugName: "shouldUseCustomBodyRenderer" }] : /* istanbul ignore next */ []));
1627
+ customBodyInputs = computed(() => {
1628
+ const res = this.resolution();
1629
+ const renderer = this.bodyRenderer();
1630
+ if (!res || !renderer) {
1631
+ return {};
1632
+ }
1633
+ return renderer.buildInputs({
1634
+ resolution: res,
1635
+ onOpenDetail: () => this.openDetail.emit(),
1636
+ onCopyValue: (value, field) => this.copyValue.emit({ value, field }),
1637
+ onDismiss: () => this.dismiss.emit('programmatic'),
1638
+ });
1639
+ }, ...(ngDevMode ? [{ debugName: "customBodyInputs" }] : /* istanbul ignore next */ []));
1640
+ focusInteractiveEntry() {
1641
+ const target = this.ctaButton?.nativeElement ??
1642
+ this.closeButton?.nativeElement ??
1643
+ this.dialogSurface?.nativeElement;
1644
+ if (target && typeof target.focus === 'function') {
1645
+ try {
1646
+ target.focus({ preventScroll: true });
1647
+ }
1648
+ catch {
1649
+ try {
1650
+ target.focus();
1651
+ }
1652
+ catch { }
1653
+ }
1654
+ }
1655
+ }
1656
+ isBadgeOrChip(item) {
1657
+ const presenter = item.presentation?.presenter;
1658
+ return presenter === 'badge' || presenter === 'chip';
1659
+ }
1660
+ onCopyItem(item) {
1661
+ if (!item.formattedValue) {
1662
+ return;
1663
+ }
1664
+ this.copyValue.emit({
1665
+ value: item.formattedValue,
1666
+ field: item.field,
1667
+ });
1668
+ }
1669
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisQuickViewOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1670
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisQuickViewOverlayComponent, isStandalone: true, selector: "praxis-quick-view-overlay", outputs: { pointerEnter: "pointerEnter", pointerLeave: "pointerLeave", openDetail: "openDetail", copyValue: "copyValue", dismiss: "dismiss" }, viewQueries: [{ propertyName: "dialogSurface", first: true, predicate: ["dialogSurface"], descendants: true }, { propertyName: "ctaButton", first: true, predicate: ["ctaButton"], descendants: true }, { propertyName: "closeButton", first: true, predicate: ["closeButton"], descendants: true }], ngImport: i0, template: `
1671
+ <section
1672
+ #dialogSurface
1673
+ class="pdx-quick-view"
1674
+ [class.pdx-quick-view--narrow]="narrowModalMode()"
1675
+ role="dialog"
1676
+ [attr.aria-modal]="narrowModalMode() ? 'true' : null"
1677
+ [attr.aria-label]="accessibleLabel()"
1678
+ [attr.aria-busy]="resolution()?.state === 'loading' ? 'true' : null"
1679
+ [attr.data-quick-view-state]="resolution()?.state || 'idle'"
1680
+ tabindex="-1"
1681
+ (mouseenter)="pointerEnter.emit()"
1682
+ (mouseleave)="pointerLeave.emit()"
1683
+ >
1684
+ <header class="pdx-quick-view__header">
1685
+ <div class="pdx-quick-view__heading">
1686
+ @if (headerIdentity(); as identity) {
1687
+ <praxis-resource-identity
1688
+ [identity]="identity"
1689
+ [emptyTitle]="resolution()?.title || ''"
1690
+ density="compact"
1691
+ [showMetadataLabels]="false"
1692
+ />
1693
+ } @else {
1694
+ <h2 class="pdx-quick-view__title">{{ resolution()?.title }}</h2>
1695
+ }
1696
+ @if (resolution()?.subtitle; as subtitle) {
1697
+ <p class="pdx-quick-view__subtitle">{{ subtitle }}</p>
1698
+ }
1699
+ </div>
1700
+ <button
1701
+ #closeButton
1702
+ type="button"
1703
+ class="pdx-quick-view__close"
1704
+ [attr.aria-label]="closeAriaLabel()"
1705
+ (click)="dismiss.emit('programmatic')"
1706
+ >
1707
+ ×
1708
+ </button>
1709
+ </header>
1710
+
1711
+ <div class="pdx-quick-view__body">
1712
+ @switch (resolution()?.state) {
1713
+ @case ('loading') {
1714
+ <div class="pdx-quick-view__skeleton" data-testid="quick-view-loading">
1715
+ <div class="pdx-quick-view__skeleton-line pdx-quick-view__skeleton-line--wide"></div>
1716
+ <div class="pdx-quick-view__skeleton-line"></div>
1717
+ <div class="pdx-quick-view__skeleton-line pdx-quick-view__skeleton-line--short"></div>
1718
+ </div>
1719
+ }
1720
+ @case ('ready') {
1721
+ @if (shouldUseCustomBodyRenderer()) {
1722
+ <ng-container
1723
+ *ngComponentOutlet="
1724
+ bodyRenderer()!.component;
1725
+ inputs: customBodyInputs()
1726
+ "
1727
+ />
1728
+ } @else {
1729
+ @if (summaryItems().length > 0) {
1730
+ <dl class="pdx-quick-view__summary-list" data-testid="quick-view-summary-list">
1731
+ @for (item of summaryItems(); track item.field) {
1732
+ <div class="pdx-quick-view__summary-item">
1733
+ <dt class="pdx-quick-view__summary-label">{{ item.label }}</dt>
1734
+ <dd class="pdx-quick-view__summary-value-wrap">
1735
+ <span
1736
+ class="pdx-quick-view__summary-value"
1737
+ [class.pdx-quick-view__summary-value--badge]="isBadgeOrChip(item)"
1738
+ [attr.title]="item.formattedValue || null"
1739
+ >
1740
+ {{ item.formattedValue }}
1741
+ </span>
1742
+ @if (item.copyable && item.formattedValue) {
1743
+ <button
1744
+ type="button"
1745
+ class="pdx-quick-view__copy-btn"
1746
+ [attr.aria-label]="copyButtonLabel() + ' ' + item.label"
1747
+ (click)="onCopyItem(item)"
1748
+ >
1749
+ {{ copyButtonLabel() }}
1750
+ </button>
1751
+ }
1752
+ </dd>
1753
+ </div>
1754
+ }
1755
+ </dl>
1756
+ }
1757
+ }
1758
+ }
1759
+ @case ('empty') {
1760
+ <p class="pdx-quick-view__feedback pdx-quick-view__feedback--empty" data-testid="quick-view-empty">
1761
+ {{ resolution()?.failureReason || 'Nenhum atributo resumido está disponível para este registro.' }}
1762
+ </p>
1763
+ }
1764
+ @case ('unavailable') {
1765
+ <p class="pdx-quick-view__feedback pdx-quick-view__feedback--unavailable" data-testid="quick-view-unavailable">
1766
+ {{ resolution()?.failureReason || 'Este resumo não está disponível para o seu contexto atual.' }}
1767
+ </p>
1768
+ }
1769
+ @case ('error') {
1770
+ <p class="pdx-quick-view__feedback pdx-quick-view__feedback--error" data-testid="quick-view-error">
1771
+ {{ resolution()?.failureReason || 'Não foi possível carregar o resumo deste registro.' }}
1772
+ </p>
1773
+ }
1774
+ }
1775
+ </div>
1776
+
1777
+ @if (resolution()?.state === 'ready' && resolution()?.ctaAvailable) {
1778
+ <footer class="pdx-quick-view__footer">
1779
+ <button
1780
+ #ctaButton
1781
+ type="button"
1782
+ class="pdx-quick-view__cta"
1783
+ data-testid="quick-view-open-detail"
1784
+ (click)="openDetail.emit()"
1785
+ >
1786
+ {{ resolution()?.ctaLabel || 'Abrir detalhe' }}
1787
+ </button>
1788
+ </footer>
1789
+ }
1790
+ </section>
1791
+ `, isInline: true, styles: [":host{display:block;max-width:min(25rem,calc(100vw - 1.5rem));min-width:min(19rem,calc(100vw - 1.5rem));box-sizing:border-box}.pdx-quick-view{box-sizing:border-box;display:grid;grid-template-columns:minmax(0,1fr);gap:.625rem;padding:.875rem 1rem;border-radius:var(--pdx-quick-view-radius, .75rem);background:var( --pdx-quick-view-bg, var(--md-sys-color-surface-container-high, var(--mat-sys-surface-container-high)) );color:var(--md-sys-color-on-surface, var(--mat-sys-on-surface));border:1px solid color-mix(in srgb,var(--md-sys-color-outline, var(--mat-sys-outline)) 36%,var(--md-sys-color-outline-variant, var(--mat-sys-outline-variant)));box-shadow:var( --pdx-quick-view-shadow, 0 18px 38px -6px color-mix(in srgb, var(--md-sys-color-shadow, #000000) 32%, transparent), 0 6px 16px -4px color-mix(in srgb, var(--md-sys-color-shadow, #000000) 18%, transparent) );outline:none;overflow:hidden}.pdx-quick-view--narrow{width:calc(100vw - 1.5rem);max-width:28rem;border-radius:var(--pdx-quick-view-narrow-radius, 1rem);padding:.75rem 1rem 1rem}.pdx-quick-view--narrow:before{content:\"\";display:block;width:2.25rem;height:.25rem;margin:0 auto .25rem;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant)) 32%,transparent)}.pdx-quick-view__header{display:flex;align-items:flex-start;justify-content:space-between;gap:.75rem;min-width:0;padding-bottom:.5rem;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, var(--mat-sys-outline-variant)) 55%,transparent)}.pdx-quick-view__heading{min-width:0;flex:1 1 auto}.pdx-quick-view__title{margin:0;font-size:.9375rem;font-weight:600;line-height:1.35;color:var(--md-sys-color-on-surface, var(--mat-sys-on-surface));overflow-wrap:anywhere}.pdx-quick-view__subtitle{margin:.25rem 0 0;font-size:.75rem;line-height:1.35;color:var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant))}.pdx-quick-view__close{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border:none;border-radius:.375rem;background:transparent;color:var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant));font-size:1.125rem;line-height:1;cursor:pointer;transition:background-color .14s ease,color .14s ease}.pdx-quick-view__close:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface, var(--mat-sys-on-surface)) 8%,transparent);color:var(--md-sys-color-on-surface, var(--mat-sys-on-surface))}.pdx-quick-view__close:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--mat-sys-primary));outline-offset:2px;background:color-mix(in srgb,var(--md-sys-color-on-surface, var(--mat-sys-on-surface)) 8%,transparent);color:var(--md-sys-color-on-surface, var(--mat-sys-on-surface))}.pdx-quick-view__body{min-width:0}.pdx-quick-view__summary-list{margin:0;display:grid;grid-template-columns:minmax(0,1fr);gap:.4375rem;min-width:0}.pdx-quick-view__summary-item{display:flex;align-items:center;justify-content:space-between;gap:.625rem;min-width:0;font-size:.8125rem;line-height:1.35}.pdx-quick-view__summary-label{color:var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant));font-weight:500;flex:0 0 auto;max-width:42%;overflow-wrap:anywhere}.pdx-quick-view__summary-value-wrap{margin:0;flex:1 1 auto;display:inline-flex;align-items:center;justify-content:flex-end;gap:.375rem;min-width:0;text-align:right}.pdx-quick-view__summary-value{min-width:0;color:var(--md-sys-color-on-surface, var(--mat-sys-on-surface));font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-quick-view__summary-value--badge{padding:.125rem .5rem;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary, var(--mat-sys-primary)) 14%,transparent);color:var(--md-sys-color-primary, var(--mat-sys-primary));font-size:.75rem;font-weight:600}.pdx-quick-view__copy-btn{flex:0 0 auto;white-space:nowrap;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, var(--mat-sys-outline-variant)) 70%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container, var(--mat-sys-surface-container)) 65%,transparent);color:var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant));border-radius:.25rem;padding:.0625rem .375rem;font-size:.6875rem;font-weight:500;opacity:.78;cursor:pointer;transition:opacity .14s ease,background-color .14s ease,color .14s ease,border-color .14s ease}.pdx-quick-view__summary-item:hover .pdx-quick-view__copy-btn,.pdx-quick-view__copy-btn:focus-visible{opacity:1}.pdx-quick-view__copy-btn:hover{background:color-mix(in srgb,var(--md-sys-color-primary, var(--mat-sys-primary)) 10%,transparent);color:var(--md-sys-color-primary, var(--mat-sys-primary));border-color:color-mix(in srgb,var(--md-sys-color-primary, var(--mat-sys-primary)) 40%,transparent)}.pdx-quick-view__copy-btn:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--mat-sys-primary));outline-offset:2px}.pdx-quick-view__feedback{margin:0;font-size:.8125rem;line-height:1.4;color:var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant))}.pdx-quick-view__feedback--error{color:var(--md-sys-color-error, var(--mat-sys-error))}.pdx-quick-view__skeleton{display:grid;gap:.4375rem;padding:.125rem 0}.pdx-quick-view__skeleton-line{height:.75rem;border-radius:.25rem;background:color-mix(in srgb,var(--md-sys-color-on-surface, var(--mat-sys-on-surface)) 12%,transparent);width:75%}.pdx-quick-view__skeleton-line--wide{width:92%}.pdx-quick-view__skeleton-line--short{width:52%}.pdx-quick-view__footer{display:flex;justify-content:flex-end;padding-top:.5rem;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, var(--mat-sys-outline-variant)) 65%,transparent)}.pdx-quick-view__cta{display:inline-flex;align-items:center;justify-content:center;gap:.375rem;padding:.375rem .8125rem;border-radius:.375rem;border:none;background:var(--md-sys-color-primary, var(--mat-sys-primary));color:var(--md-sys-color-on-primary, var(--mat-sys-on-primary));font-size:.8125rem;font-weight:600;cursor:pointer;transition:filter .14s ease,box-shadow .14s ease}.pdx-quick-view__cta:hover{filter:brightness(1.06)}.pdx-quick-view__cta:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--mat-sys-primary));outline-offset:2px}.pdx-quick-view--narrow .pdx-quick-view__cta{width:100%;padding:.5rem .875rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: PraxisResourceIdentityComponent, selector: "praxis-resource-identity", inputs: ["identity", "emptyTitle", "density", "showMetadataLabels", "showKey", "showKeyLabel", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1792
+ }
1793
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisQuickViewOverlayComponent, decorators: [{
1794
+ type: Component,
1795
+ args: [{ selector: 'praxis-quick-view-overlay', standalone: true, imports: [CommonModule, PraxisResourceIdentityComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
1796
+ <section
1797
+ #dialogSurface
1798
+ class="pdx-quick-view"
1799
+ [class.pdx-quick-view--narrow]="narrowModalMode()"
1800
+ role="dialog"
1801
+ [attr.aria-modal]="narrowModalMode() ? 'true' : null"
1802
+ [attr.aria-label]="accessibleLabel()"
1803
+ [attr.aria-busy]="resolution()?.state === 'loading' ? 'true' : null"
1804
+ [attr.data-quick-view-state]="resolution()?.state || 'idle'"
1805
+ tabindex="-1"
1806
+ (mouseenter)="pointerEnter.emit()"
1807
+ (mouseleave)="pointerLeave.emit()"
1808
+ >
1809
+ <header class="pdx-quick-view__header">
1810
+ <div class="pdx-quick-view__heading">
1811
+ @if (headerIdentity(); as identity) {
1812
+ <praxis-resource-identity
1813
+ [identity]="identity"
1814
+ [emptyTitle]="resolution()?.title || ''"
1815
+ density="compact"
1816
+ [showMetadataLabels]="false"
1817
+ />
1818
+ } @else {
1819
+ <h2 class="pdx-quick-view__title">{{ resolution()?.title }}</h2>
1820
+ }
1821
+ @if (resolution()?.subtitle; as subtitle) {
1822
+ <p class="pdx-quick-view__subtitle">{{ subtitle }}</p>
1823
+ }
1824
+ </div>
1825
+ <button
1826
+ #closeButton
1827
+ type="button"
1828
+ class="pdx-quick-view__close"
1829
+ [attr.aria-label]="closeAriaLabel()"
1830
+ (click)="dismiss.emit('programmatic')"
1831
+ >
1832
+ ×
1833
+ </button>
1834
+ </header>
1835
+
1836
+ <div class="pdx-quick-view__body">
1837
+ @switch (resolution()?.state) {
1838
+ @case ('loading') {
1839
+ <div class="pdx-quick-view__skeleton" data-testid="quick-view-loading">
1840
+ <div class="pdx-quick-view__skeleton-line pdx-quick-view__skeleton-line--wide"></div>
1841
+ <div class="pdx-quick-view__skeleton-line"></div>
1842
+ <div class="pdx-quick-view__skeleton-line pdx-quick-view__skeleton-line--short"></div>
1843
+ </div>
1844
+ }
1845
+ @case ('ready') {
1846
+ @if (shouldUseCustomBodyRenderer()) {
1847
+ <ng-container
1848
+ *ngComponentOutlet="
1849
+ bodyRenderer()!.component;
1850
+ inputs: customBodyInputs()
1851
+ "
1852
+ />
1853
+ } @else {
1854
+ @if (summaryItems().length > 0) {
1855
+ <dl class="pdx-quick-view__summary-list" data-testid="quick-view-summary-list">
1856
+ @for (item of summaryItems(); track item.field) {
1857
+ <div class="pdx-quick-view__summary-item">
1858
+ <dt class="pdx-quick-view__summary-label">{{ item.label }}</dt>
1859
+ <dd class="pdx-quick-view__summary-value-wrap">
1860
+ <span
1861
+ class="pdx-quick-view__summary-value"
1862
+ [class.pdx-quick-view__summary-value--badge]="isBadgeOrChip(item)"
1863
+ [attr.title]="item.formattedValue || null"
1864
+ >
1865
+ {{ item.formattedValue }}
1866
+ </span>
1867
+ @if (item.copyable && item.formattedValue) {
1868
+ <button
1869
+ type="button"
1870
+ class="pdx-quick-view__copy-btn"
1871
+ [attr.aria-label]="copyButtonLabel() + ' ' + item.label"
1872
+ (click)="onCopyItem(item)"
1873
+ >
1874
+ {{ copyButtonLabel() }}
1875
+ </button>
1876
+ }
1877
+ </dd>
1878
+ </div>
1879
+ }
1880
+ </dl>
1881
+ }
1882
+ }
1883
+ }
1884
+ @case ('empty') {
1885
+ <p class="pdx-quick-view__feedback pdx-quick-view__feedback--empty" data-testid="quick-view-empty">
1886
+ {{ resolution()?.failureReason || 'Nenhum atributo resumido está disponível para este registro.' }}
1887
+ </p>
1888
+ }
1889
+ @case ('unavailable') {
1890
+ <p class="pdx-quick-view__feedback pdx-quick-view__feedback--unavailable" data-testid="quick-view-unavailable">
1891
+ {{ resolution()?.failureReason || 'Este resumo não está disponível para o seu contexto atual.' }}
1892
+ </p>
1893
+ }
1894
+ @case ('error') {
1895
+ <p class="pdx-quick-view__feedback pdx-quick-view__feedback--error" data-testid="quick-view-error">
1896
+ {{ resolution()?.failureReason || 'Não foi possível carregar o resumo deste registro.' }}
1897
+ </p>
1898
+ }
1899
+ }
1900
+ </div>
1901
+
1902
+ @if (resolution()?.state === 'ready' && resolution()?.ctaAvailable) {
1903
+ <footer class="pdx-quick-view__footer">
1904
+ <button
1905
+ #ctaButton
1906
+ type="button"
1907
+ class="pdx-quick-view__cta"
1908
+ data-testid="quick-view-open-detail"
1909
+ (click)="openDetail.emit()"
1910
+ >
1911
+ {{ resolution()?.ctaLabel || 'Abrir detalhe' }}
1912
+ </button>
1913
+ </footer>
1914
+ }
1915
+ </section>
1916
+ `, styles: [":host{display:block;max-width:min(25rem,calc(100vw - 1.5rem));min-width:min(19rem,calc(100vw - 1.5rem));box-sizing:border-box}.pdx-quick-view{box-sizing:border-box;display:grid;grid-template-columns:minmax(0,1fr);gap:.625rem;padding:.875rem 1rem;border-radius:var(--pdx-quick-view-radius, .75rem);background:var( --pdx-quick-view-bg, var(--md-sys-color-surface-container-high, var(--mat-sys-surface-container-high)) );color:var(--md-sys-color-on-surface, var(--mat-sys-on-surface));border:1px solid color-mix(in srgb,var(--md-sys-color-outline, var(--mat-sys-outline)) 36%,var(--md-sys-color-outline-variant, var(--mat-sys-outline-variant)));box-shadow:var( --pdx-quick-view-shadow, 0 18px 38px -6px color-mix(in srgb, var(--md-sys-color-shadow, #000000) 32%, transparent), 0 6px 16px -4px color-mix(in srgb, var(--md-sys-color-shadow, #000000) 18%, transparent) );outline:none;overflow:hidden}.pdx-quick-view--narrow{width:calc(100vw - 1.5rem);max-width:28rem;border-radius:var(--pdx-quick-view-narrow-radius, 1rem);padding:.75rem 1rem 1rem}.pdx-quick-view--narrow:before{content:\"\";display:block;width:2.25rem;height:.25rem;margin:0 auto .25rem;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant)) 32%,transparent)}.pdx-quick-view__header{display:flex;align-items:flex-start;justify-content:space-between;gap:.75rem;min-width:0;padding-bottom:.5rem;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, var(--mat-sys-outline-variant)) 55%,transparent)}.pdx-quick-view__heading{min-width:0;flex:1 1 auto}.pdx-quick-view__title{margin:0;font-size:.9375rem;font-weight:600;line-height:1.35;color:var(--md-sys-color-on-surface, var(--mat-sys-on-surface));overflow-wrap:anywhere}.pdx-quick-view__subtitle{margin:.25rem 0 0;font-size:.75rem;line-height:1.35;color:var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant))}.pdx-quick-view__close{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border:none;border-radius:.375rem;background:transparent;color:var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant));font-size:1.125rem;line-height:1;cursor:pointer;transition:background-color .14s ease,color .14s ease}.pdx-quick-view__close:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface, var(--mat-sys-on-surface)) 8%,transparent);color:var(--md-sys-color-on-surface, var(--mat-sys-on-surface))}.pdx-quick-view__close:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--mat-sys-primary));outline-offset:2px;background:color-mix(in srgb,var(--md-sys-color-on-surface, var(--mat-sys-on-surface)) 8%,transparent);color:var(--md-sys-color-on-surface, var(--mat-sys-on-surface))}.pdx-quick-view__body{min-width:0}.pdx-quick-view__summary-list{margin:0;display:grid;grid-template-columns:minmax(0,1fr);gap:.4375rem;min-width:0}.pdx-quick-view__summary-item{display:flex;align-items:center;justify-content:space-between;gap:.625rem;min-width:0;font-size:.8125rem;line-height:1.35}.pdx-quick-view__summary-label{color:var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant));font-weight:500;flex:0 0 auto;max-width:42%;overflow-wrap:anywhere}.pdx-quick-view__summary-value-wrap{margin:0;flex:1 1 auto;display:inline-flex;align-items:center;justify-content:flex-end;gap:.375rem;min-width:0;text-align:right}.pdx-quick-view__summary-value{min-width:0;color:var(--md-sys-color-on-surface, var(--mat-sys-on-surface));font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-quick-view__summary-value--badge{padding:.125rem .5rem;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary, var(--mat-sys-primary)) 14%,transparent);color:var(--md-sys-color-primary, var(--mat-sys-primary));font-size:.75rem;font-weight:600}.pdx-quick-view__copy-btn{flex:0 0 auto;white-space:nowrap;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, var(--mat-sys-outline-variant)) 70%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container, var(--mat-sys-surface-container)) 65%,transparent);color:var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant));border-radius:.25rem;padding:.0625rem .375rem;font-size:.6875rem;font-weight:500;opacity:.78;cursor:pointer;transition:opacity .14s ease,background-color .14s ease,color .14s ease,border-color .14s ease}.pdx-quick-view__summary-item:hover .pdx-quick-view__copy-btn,.pdx-quick-view__copy-btn:focus-visible{opacity:1}.pdx-quick-view__copy-btn:hover{background:color-mix(in srgb,var(--md-sys-color-primary, var(--mat-sys-primary)) 10%,transparent);color:var(--md-sys-color-primary, var(--mat-sys-primary));border-color:color-mix(in srgb,var(--md-sys-color-primary, var(--mat-sys-primary)) 40%,transparent)}.pdx-quick-view__copy-btn:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--mat-sys-primary));outline-offset:2px}.pdx-quick-view__feedback{margin:0;font-size:.8125rem;line-height:1.4;color:var(--md-sys-color-on-surface-variant, var(--mat-sys-on-surface-variant))}.pdx-quick-view__feedback--error{color:var(--md-sys-color-error, var(--mat-sys-error))}.pdx-quick-view__skeleton{display:grid;gap:.4375rem;padding:.125rem 0}.pdx-quick-view__skeleton-line{height:.75rem;border-radius:.25rem;background:color-mix(in srgb,var(--md-sys-color-on-surface, var(--mat-sys-on-surface)) 12%,transparent);width:75%}.pdx-quick-view__skeleton-line--wide{width:92%}.pdx-quick-view__skeleton-line--short{width:52%}.pdx-quick-view__footer{display:flex;justify-content:flex-end;padding-top:.5rem;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, var(--mat-sys-outline-variant)) 65%,transparent)}.pdx-quick-view__cta{display:inline-flex;align-items:center;justify-content:center;gap:.375rem;padding:.375rem .8125rem;border-radius:.375rem;border:none;background:var(--md-sys-color-primary, var(--mat-sys-primary));color:var(--md-sys-color-on-primary, var(--mat-sys-on-primary));font-size:.8125rem;font-weight:600;cursor:pointer;transition:filter .14s ease,box-shadow .14s ease}.pdx-quick-view__cta:hover{filter:brightness(1.06)}.pdx-quick-view__cta:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--mat-sys-primary));outline-offset:2px}.pdx-quick-view--narrow .pdx-quick-view__cta{width:100%;padding:.5rem .875rem}\n"] }]
1917
+ }], propDecorators: { pointerEnter: [{
1918
+ type: Output
1919
+ }], pointerLeave: [{
1920
+ type: Output
1921
+ }], openDetail: [{
1922
+ type: Output
1923
+ }], copyValue: [{
1924
+ type: Output
1925
+ }], dismiss: [{
1926
+ type: Output
1927
+ }], dialogSurface: [{
1928
+ type: ViewChild,
1929
+ args: ['dialogSurface']
1930
+ }], ctaButton: [{
1931
+ type: ViewChild,
1932
+ args: ['ctaButton']
1933
+ }], closeButton: [{
1934
+ type: ViewChild,
1935
+ args: ['closeButton']
1936
+ }] } });
1937
+
1938
+ const QUICK_VIEW_CONNECTED_POSITIONS = [
1939
+ {
1940
+ originX: 'start',
1941
+ originY: 'bottom',
1942
+ overlayX: 'start',
1943
+ overlayY: 'top',
1944
+ offsetY: 4,
1945
+ },
1946
+ {
1947
+ originX: 'end',
1948
+ originY: 'bottom',
1949
+ overlayX: 'end',
1950
+ overlayY: 'top',
1951
+ offsetY: 4,
1952
+ },
1953
+ {
1954
+ originX: 'start',
1955
+ originY: 'top',
1956
+ overlayX: 'start',
1957
+ overlayY: 'bottom',
1958
+ offsetY: -4,
1959
+ },
1960
+ {
1961
+ originX: 'end',
1962
+ originY: 'top',
1963
+ overlayX: 'end',
1964
+ overlayY: 'bottom',
1965
+ offsetY: -4,
1966
+ },
1967
+ {
1968
+ originX: 'end',
1969
+ originY: 'center',
1970
+ overlayX: 'start',
1971
+ overlayY: 'center',
1972
+ offsetX: 6,
1973
+ },
1974
+ {
1975
+ originX: 'start',
1976
+ originY: 'center',
1977
+ overlayX: 'end',
1978
+ overlayY: 'center',
1979
+ offsetX: -6,
1980
+ },
1981
+ ];
1982
+ /**
1983
+ * Apresentador conectado não-modal para Quick View em `@praxisui/dialog`.
1984
+ *
1985
+ * Regras arquiteturais:
1986
+ * - Em desktop (`hover`, `focus-shortcut`, `explicit-button`), utiliza `flexibleConnectedTo`
1987
+ * sem `aria-modal="true"` e sem trap global de foco;
1988
+ * - Em `narrow-tap` (ou viewport compacta <= 640px sob ativação explícita), utiliza folha compacta
1989
+ * inferior com backdrop e semântica modal real;
1990
+ * - Reposiciona em scroll/resize enquanto a âncora permanecer válida e fecha imediatamente
1991
+ * quando a âncora sai do DOM ou se torna inválida;
1992
+ * - Restaura o foco ao gatilho original quando o usuário fecha por `Escape` ou botão Fechar
1993
+ * estando com o foco dentro do card.
1994
+ */
1995
+ class QuickViewDialogPresenterService {
1996
+ overlay = inject(Overlay);
1997
+ injector = inject(Injector);
1998
+ layerScale = inject(PraxisLayerScaleStyleService);
1999
+ activeSession = null;
2000
+ present(options) {
2001
+ this.closeAll();
2002
+ this.layerScale.ensureInstalled();
2003
+ const narrowModalMode = this.shouldUseNarrowModalFallback(options);
2004
+ const overlayRef = this.overlay.create(this.buildOverlayConfig(options.anchor, narrowModalMode));
2005
+ const portal = new ComponentPortal(PraxisQuickViewOverlayComponent, null, this.injector);
2006
+ const compRef = overlayRef.attach(portal);
2007
+ compRef.instance.narrowModalMode.set(narrowModalMode);
2008
+ compRef.instance.bodyRenderer.set(options.bodyRenderer ?? null);
2009
+ compRef.instance.resolution.set(options.resolution);
2010
+ try {
2011
+ compRef.changeDetectorRef.detectChanges();
2012
+ }
2013
+ catch { }
2014
+ overlayRef.updatePosition();
2015
+ const session = new ActiveOverlaySession(overlayRef, compRef, options, narrowModalMode, (anchor) => this.resolveConnectedOrigin(anchor), () => {
2016
+ if (this.activeSession === session) {
2017
+ this.activeSession = null;
2018
+ }
2019
+ });
2020
+ this.activeSession = session;
2021
+ if (narrowModalMode ||
2022
+ options.trigger === 'explicit-button' ||
2023
+ options.trigger === 'focus-shortcut' ||
2024
+ options.trigger === 'narrow-tap') {
2025
+ queueMicrotask(() => {
2026
+ compRef.instance.focusInteractiveEntry();
2027
+ });
2028
+ }
2029
+ return session;
2030
+ }
2031
+ closeAll() {
2032
+ if (this.activeSession) {
2033
+ const current = this.activeSession;
2034
+ this.activeSession = null;
2035
+ current.close('programmatic');
2036
+ }
2037
+ }
2038
+ shouldUseNarrowModalFallback(options) {
2039
+ if (options.trigger === 'narrow-tap') {
2040
+ return true;
2041
+ }
2042
+ if (options.trigger === 'hover') {
2043
+ return false;
2044
+ }
2045
+ const width = typeof window !== 'undefined' && Number.isFinite(window.innerWidth)
2046
+ ? window.innerWidth
2047
+ : 1280;
2048
+ return (width <= 640 &&
2049
+ (options.trigger === 'explicit-button' ||
2050
+ options.trigger === 'focus-shortcut'));
2051
+ }
2052
+ buildOverlayConfig(anchor, narrowModalMode) {
2053
+ if (narrowModalMode) {
2054
+ const positionStrategy = this.overlay
2055
+ .position()
2056
+ .global()
2057
+ .centerHorizontally()
2058
+ .bottom('12px');
2059
+ return new OverlayConfig({
2060
+ hasBackdrop: true,
2061
+ panelClass: ['pdx-quick-view-overlay-pane', 'pdx-quick-view-overlay-pane--narrow'],
2062
+ backdropClass: 'pdx-quick-view-backdrop',
2063
+ positionStrategy,
2064
+ scrollStrategy: this.overlay.scrollStrategies.block(),
2065
+ });
2066
+ }
2067
+ const origin = this.resolveConnectedOrigin(anchor);
2068
+ const positionStrategy = this.overlay
2069
+ .position()
2070
+ .flexibleConnectedTo(origin)
2071
+ .withPositions(QUICK_VIEW_CONNECTED_POSITIONS)
2072
+ .withViewportMargin(12)
2073
+ .withPush(true)
2074
+ .withFlexibleDimensions(false);
2075
+ return new OverlayConfig({
2076
+ hasBackdrop: false,
2077
+ panelClass: 'pdx-quick-view-overlay-pane',
2078
+ positionStrategy,
2079
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
2080
+ });
2081
+ }
2082
+ resolveConnectedOrigin(anchor) {
2083
+ if (anchor.kind === 'element') {
2084
+ return anchor.element;
2085
+ }
2086
+ const rect = anchor.getViewportRect() ?? {
2087
+ x: 0,
2088
+ y: 0,
2089
+ width: 0,
2090
+ height: 0,
2091
+ };
2092
+ return {
2093
+ x: rect.x,
2094
+ y: rect.y,
2095
+ width: rect.width,
2096
+ height: rect.height,
2097
+ };
2098
+ }
2099
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: QuickViewDialogPresenterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2100
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: QuickViewDialogPresenterService, providedIn: 'root' });
2101
+ }
2102
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: QuickViewDialogPresenterService, decorators: [{
2103
+ type: Injectable,
2104
+ args: [{ providedIn: 'root' }]
2105
+ }] });
2106
+ class ActiveOverlaySession {
2107
+ overlayRef;
2108
+ compRef;
2109
+ options;
2110
+ narrowModalMode;
2111
+ resolveOrigin;
2112
+ onDisposed;
2113
+ closedSubject = new Subject();
2114
+ pointerEnterSubject = new Subject();
2115
+ pointerLeaveSubject = new Subject();
2116
+ subs = [];
2117
+ cleanupDomListeners = [];
2118
+ isClosed = false;
2119
+ closed$ = this.closedSubject.asObservable();
2120
+ pointerEnteredCard$ = this.pointerEnterSubject.asObservable();
2121
+ pointerLeftCard$ = this.pointerLeaveSubject.asObservable();
2122
+ constructor(overlayRef, compRef, options, narrowModalMode, resolveOrigin, onDisposed) {
2123
+ this.overlayRef = overlayRef;
2124
+ this.compRef = compRef;
2125
+ this.options = options;
2126
+ this.narrowModalMode = narrowModalMode;
2127
+ this.resolveOrigin = resolveOrigin;
2128
+ this.onDisposed = onDisposed;
2129
+ const inst = compRef.instance;
2130
+ this.subs.push(inst.pointerEnter.subscribe(() => this.pointerEnterSubject.next()), inst.pointerLeave.subscribe(() => this.pointerLeaveSubject.next()), inst.openDetail.subscribe(() => this.options.onOpenDetail()), inst.copyValue.subscribe(({ value, field }) => this.options.onCopyValue?.(value, field)), inst.dismiss.subscribe((reason) => this.close(reason)));
2131
+ if (narrowModalMode) {
2132
+ this.subs.push(overlayRef.backdropClick().subscribe(() => {
2133
+ this.close('outside-pointer');
2134
+ }));
2135
+ }
2136
+ this.installDomListeners();
2137
+ }
2138
+ update(resolution) {
2139
+ if (this.isClosed) {
2140
+ return;
2141
+ }
2142
+ const previousState = this.compRef.instance.resolution()?.state;
2143
+ const focusWasInside = this.wasFocusInsideOverlay();
2144
+ this.compRef.instance.resolution.set(resolution);
2145
+ try {
2146
+ this.compRef.changeDetectorRef.detectChanges();
2147
+ }
2148
+ catch { }
2149
+ this.updatePosition();
2150
+ if (previousState === 'loading' &&
2151
+ resolution.state === 'ready' &&
2152
+ (focusWasInside ||
2153
+ this.narrowModalMode ||
2154
+ this.options.trigger === 'explicit-button' ||
2155
+ this.options.trigger === 'focus-shortcut' ||
2156
+ this.options.trigger === 'narrow-tap')) {
2157
+ queueMicrotask(() => {
2158
+ if (!this.isClosed) {
2159
+ this.compRef.instance.focusInteractiveEntry();
2160
+ }
2161
+ });
2162
+ }
2163
+ }
2164
+ updatePosition() {
2165
+ if (this.isClosed) {
2166
+ return;
2167
+ }
2168
+ if (!isResourceQuickViewAnchorValid(this.options.anchor)) {
2169
+ this.close('anchor-invalid');
2170
+ return;
2171
+ }
2172
+ if (!this.narrowModalMode && this.options.anchor.kind === 'virtual-rect') {
2173
+ const strategy = this.overlayRef.getConfig().positionStrategy;
2174
+ strategy?.setOrigin?.(this.resolveOrigin(this.options.anchor));
2175
+ }
2176
+ this.overlayRef.updatePosition();
2177
+ }
2178
+ close(reason = 'programmatic') {
2179
+ if (this.isClosed) {
2180
+ return;
2181
+ }
2182
+ this.isClosed = true;
2183
+ const focusInside = this.wasFocusInsideOverlay();
2184
+ const isInteractiveTrigger = this.narrowModalMode ||
2185
+ this.options.trigger === 'explicit-button' ||
2186
+ this.options.trigger === 'focus-shortcut' ||
2187
+ this.options.trigger === 'narrow-tap';
2188
+ const shouldRestoreFocus = focusInside ||
2189
+ (isInteractiveTrigger &&
2190
+ (reason === 'escape' ||
2191
+ reason === 'programmatic' ||
2192
+ this.narrowModalMode));
2193
+ for (const cleanup of this.cleanupDomListeners) {
2194
+ cleanup();
2195
+ }
2196
+ this.cleanupDomListeners.length = 0;
2197
+ for (const sub of this.subs) {
2198
+ sub.unsubscribe();
2199
+ }
2200
+ this.subs.length = 0;
2201
+ try {
2202
+ this.overlayRef.dispose();
2203
+ }
2204
+ catch { }
2205
+ if (shouldRestoreFocus && reason !== 'cta') {
2206
+ this.restoreFocusToOrigin();
2207
+ }
2208
+ this.closedSubject.next(reason);
2209
+ this.closedSubject.complete();
2210
+ this.pointerEnterSubject.complete();
2211
+ this.pointerLeaveSubject.complete();
2212
+ this.onDisposed();
2213
+ this.options.onDismiss(reason);
2214
+ }
2215
+ installDomListeners() {
2216
+ if (typeof document !== 'undefined') {
2217
+ const onKeydown = (event) => {
2218
+ if (event.key === 'Escape') {
2219
+ event.preventDefault();
2220
+ event.stopPropagation();
2221
+ event.stopImmediatePropagation();
2222
+ this.close('escape');
2223
+ }
2224
+ };
2225
+ document.addEventListener('keydown', onKeydown, true);
2226
+ this.cleanupDomListeners.push(() => document.removeEventListener('keydown', onKeydown, true));
2227
+ if (!this.narrowModalMode) {
2228
+ const onPointerDown = (event) => {
2229
+ const target = event.target;
2230
+ if (!target) {
2231
+ return;
2232
+ }
2233
+ if (this.overlayRef.overlayElement?.contains(target)) {
2234
+ return;
2235
+ }
2236
+ const anchorEl = this.options.anchor.kind === 'element'
2237
+ ? this.options.anchor.element
2238
+ : this.options.anchor.hostElement;
2239
+ if (anchorEl && anchorEl.contains(target)) {
2240
+ return;
2241
+ }
2242
+ this.close('outside-pointer');
2243
+ };
2244
+ document.addEventListener('pointerdown', onPointerDown, true);
2245
+ this.cleanupDomListeners.push(() => document.removeEventListener('pointerdown', onPointerDown, true));
2246
+ }
2247
+ }
2248
+ if (typeof window !== 'undefined') {
2249
+ const onViewportChange = () => {
2250
+ this.updatePosition();
2251
+ };
2252
+ window.addEventListener('scroll', onViewportChange, true);
2253
+ window.addEventListener('resize', onViewportChange, { passive: true });
2254
+ this.cleanupDomListeners.push(() => {
2255
+ window.removeEventListener('scroll', onViewportChange, true);
2256
+ window.removeEventListener('resize', onViewportChange);
2257
+ });
2258
+ }
2259
+ }
2260
+ wasFocusInsideOverlay() {
2261
+ if (typeof document === 'undefined' || !document.activeElement) {
2262
+ return false;
2263
+ }
2264
+ return Boolean(this.overlayRef.overlayElement?.contains(document.activeElement));
2265
+ }
2266
+ restoreFocusToOrigin() {
2267
+ const anchor = this.options.anchor;
2268
+ const candidate = anchor.focusOrigin ??
2269
+ (anchor.kind === 'element' ? anchor.element : anchor.hostElement);
2270
+ if (candidate &&
2271
+ candidate.isConnected !== false &&
2272
+ typeof candidate.focus === 'function') {
2273
+ try {
2274
+ candidate.focus({ preventScroll: true });
2275
+ }
2276
+ catch {
2277
+ try {
2278
+ candidate.focus();
2279
+ }
2280
+ catch { }
2281
+ }
2282
+ }
2283
+ }
2284
+ }
2285
+ function providePraxisQuickViewDialogPresenter() {
2286
+ return {
2287
+ provide: PRAXIS_QUICK_VIEW_PRESENTER,
2288
+ useExisting: QuickViewDialogPresenterService,
2289
+ };
2290
+ }
2291
+
1577
2292
  class LongContentDialogExampleComponent {
1578
2293
  items = Array.from({ length: 40 }, (_, idx) => `Example line ${idx + 1}`);
1579
2294
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: LongContentDialogExampleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -2040,4 +2755,4 @@ const PRAXIS_DIALOG_AUTHORING_MANIFEST = {
2040
2755
  * Generated bundle index. Do not edit.
2041
2756
  */
2042
2757
 
2043
- export { LongContentDialogExampleComponent, PRAXIS_DIALOG_AUTHORING_MANIFEST, PRAXIS_DIALOG_COMPONENT_METADATA, PRAXIS_DIALOG_CONTENT_REGISTRY, PRAXIS_DIALOG_DATA, PRAXIS_DIALOG_DEFAULTS, PRAXIS_DIALOG_EXAMPLE_LONG_CONTENT, PRAXIS_DIALOG_GLOBAL_PRESETS, PRAXIS_DIALOG_I18N, PRAXIS_DIALOG_TEMPLATE_REGISTRY, PraxisDialog, PraxisDialogActionsDirective, PraxisDialogComponent, PraxisDialogContentDirective, PraxisDialogDirectives, PraxisDialogRef, PraxisDialogTitleDirective, provideDialogGlobalPresetsFromGlobalConfig, providePraxisDialogExamples, providePraxisDialogGlobalActions, providePraxisDialogMetadata, providePraxisSurfaceGlobalActions };
2758
+ export { LongContentDialogExampleComponent, PRAXIS_DIALOG_AUTHORING_MANIFEST, PRAXIS_DIALOG_COMPONENT_METADATA, PRAXIS_DIALOG_CONTENT_REGISTRY, PRAXIS_DIALOG_DATA, PRAXIS_DIALOG_DEFAULTS, PRAXIS_DIALOG_EXAMPLE_LONG_CONTENT, PRAXIS_DIALOG_GLOBAL_PRESETS, PRAXIS_DIALOG_I18N, PRAXIS_DIALOG_TEMPLATE_REGISTRY, PraxisDialog, PraxisDialogActionsDirective, PraxisDialogComponent, PraxisDialogContentDirective, PraxisDialogDirectives, PraxisDialogRef, PraxisDialogTitleDirective, PraxisQuickViewOverlayComponent, QuickViewDialogPresenterService, provideDialogGlobalPresetsFromGlobalConfig, providePraxisDialogExamples, providePraxisDialogGlobalActions, providePraxisDialogMetadata, providePraxisQuickViewDialogPresenter, providePraxisSurfaceGlobalActions };
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@praxisui/dialog",
3
- "version": "10.0.0-rc.37",
3
+ "version": "10.0.0-rc.39",
4
4
  "description": "Dialog helpers and components for Praxis UI with Angular Material integration.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
7
7
  "@angular/core": "^21.0.0",
8
8
  "@angular/cdk": "^21.0.0",
9
9
  "@angular/forms": "^21.0.0",
10
- "@praxisui/core": "^10.0.0-rc.37",
10
+ "@praxisui/core": "^10.0.0-rc.39",
11
11
  "@angular/material": "^21.0.0",
12
12
  "@angular/platform-browser": "^21.0.0",
13
13
  "rxjs": "~7.8.0"
@@ -3,8 +3,9 @@ import { Injector, ViewContainerRef, InjectionToken, TemplateRef, ComponentRef,
3
3
  import { OverlayRef } from '@angular/cdk/overlay';
4
4
  import { Observable, Subject } from 'rxjs';
5
5
  import { CdkPortalOutlet } from '@angular/cdk/portal';
6
+ import * as _praxisui_core from '@praxisui/core';
7
+ import { ResourceQuickViewResolution, PraxisQuickViewBodyRenderer, ResourceQuickViewDismissReason, ResourceQuickViewSummaryItem, PraxisQuickViewPresenter, PraxisQuickViewPresentOptions, PraxisQuickViewPresenterSession, ComponentDocMeta, ComponentAuthoringManifest } from '@praxisui/core';
6
8
  import * as _praxisui_dialog from '@praxisui/dialog';
7
- import { ComponentDocMeta, ComponentAuthoringManifest } from '@praxisui/core';
8
9
 
9
10
  type ActionsLayout = 'start' | 'center' | 'end' | 'stretched';
10
11
  type DialogThemeColor = 'primary' | 'light' | 'dark';
@@ -343,6 +344,65 @@ declare function providePraxisDialogGlobalActions(): Provider;
343
344
 
344
345
  declare function providePraxisSurfaceGlobalActions(): Provider;
345
346
 
347
+ declare class PraxisQuickViewOverlayComponent {
348
+ private readonly i18n;
349
+ readonly resolution: i0.WritableSignal<ResourceQuickViewResolution | null>;
350
+ readonly bodyRenderer: i0.WritableSignal<PraxisQuickViewBodyRenderer | null>;
351
+ readonly narrowModalMode: i0.WritableSignal<boolean>;
352
+ readonly pointerEnter: EventEmitter<void>;
353
+ readonly pointerLeave: EventEmitter<void>;
354
+ readonly openDetail: EventEmitter<void>;
355
+ readonly copyValue: EventEmitter<{
356
+ value: string;
357
+ field?: string;
358
+ }>;
359
+ readonly dismiss: EventEmitter<ResourceQuickViewDismissReason>;
360
+ private readonly dialogSurface?;
361
+ private readonly ctaButton?;
362
+ private readonly closeButton?;
363
+ protected readonly summaryItems: i0.Signal<readonly ResourceQuickViewSummaryItem[]>;
364
+ protected readonly headerIdentity: i0.Signal<_praxisui_core.MaterializedResourceIdentity | null>;
365
+ protected readonly closeAriaLabel: i0.Signal<string>;
366
+ protected readonly copyButtonLabel: i0.Signal<string>;
367
+ protected readonly accessibleLabel: i0.Signal<string>;
368
+ private translate;
369
+ protected readonly shouldUseCustomBodyRenderer: i0.Signal<boolean>;
370
+ protected readonly customBodyInputs: i0.Signal<Record<string, unknown>>;
371
+ focusInteractiveEntry(): void;
372
+ protected isBadgeOrChip(item: ResourceQuickViewSummaryItem): boolean;
373
+ protected onCopyItem(item: ResourceQuickViewSummaryItem): void;
374
+ static ɵfac: i0.ɵɵFactoryDeclaration<PraxisQuickViewOverlayComponent, never>;
375
+ static ɵcmp: i0.ɵɵComponentDeclaration<PraxisQuickViewOverlayComponent, "praxis-quick-view-overlay", never, {}, { "pointerEnter": "pointerEnter"; "pointerLeave": "pointerLeave"; "openDetail": "openDetail"; "copyValue": "copyValue"; "dismiss": "dismiss"; }, never, never, true, never>;
376
+ }
377
+
378
+ /**
379
+ * Apresentador conectado não-modal para Quick View em `@praxisui/dialog`.
380
+ *
381
+ * Regras arquiteturais:
382
+ * - Em desktop (`hover`, `focus-shortcut`, `explicit-button`), utiliza `flexibleConnectedTo`
383
+ * sem `aria-modal="true"` e sem trap global de foco;
384
+ * - Em `narrow-tap` (ou viewport compacta <= 640px sob ativação explícita), utiliza folha compacta
385
+ * inferior com backdrop e semântica modal real;
386
+ * - Reposiciona em scroll/resize enquanto a âncora permanecer válida e fecha imediatamente
387
+ * quando a âncora sai do DOM ou se torna inválida;
388
+ * - Restaura o foco ao gatilho original quando o usuário fecha por `Escape` ou botão Fechar
389
+ * estando com o foco dentro do card.
390
+ */
391
+ declare class QuickViewDialogPresenterService implements PraxisQuickViewPresenter {
392
+ private readonly overlay;
393
+ private readonly injector;
394
+ private readonly layerScale;
395
+ private activeSession;
396
+ present(options: PraxisQuickViewPresentOptions): PraxisQuickViewPresenterSession;
397
+ closeAll(): void;
398
+ private shouldUseNarrowModalFallback;
399
+ private buildOverlayConfig;
400
+ private resolveConnectedOrigin;
401
+ static ɵfac: i0.ɵɵFactoryDeclaration<QuickViewDialogPresenterService, never>;
402
+ static ɵprov: i0.ɵɵInjectableDeclaration<QuickViewDialogPresenterService>;
403
+ }
404
+ declare function providePraxisQuickViewDialogPresenter(): Provider;
405
+
346
406
  declare class LongContentDialogExampleComponent {
347
407
  readonly items: string[];
348
408
  static ɵfac: i0.ɵɵFactoryDeclaration<LongContentDialogExampleComponent, never>;
@@ -362,5 +422,5 @@ declare function providePraxisDialogMetadata(): Provider;
362
422
 
363
423
  declare const PRAXIS_DIALOG_AUTHORING_MANIFEST: ComponentAuthoringManifest;
364
424
 
365
- export { LongContentDialogExampleComponent, PRAXIS_DIALOG_AUTHORING_MANIFEST, PRAXIS_DIALOG_COMPONENT_METADATA, PRAXIS_DIALOG_CONTENT_REGISTRY, PRAXIS_DIALOG_DATA, PRAXIS_DIALOG_DEFAULTS, PRAXIS_DIALOG_EXAMPLE_LONG_CONTENT, PRAXIS_DIALOG_GLOBAL_PRESETS, PRAXIS_DIALOG_I18N, PRAXIS_DIALOG_TEMPLATE_REGISTRY, PraxisDialog, PraxisDialogActionsDirective, PraxisDialogComponent, PraxisDialogContentDirective, PraxisDialogDirectives, PraxisDialogRef, PraxisDialogTitleDirective, provideDialogGlobalPresetsFromGlobalConfig, providePraxisDialogExamples, providePraxisDialogGlobalActions, providePraxisDialogMetadata, providePraxisSurfaceGlobalActions };
425
+ export { LongContentDialogExampleComponent, PRAXIS_DIALOG_AUTHORING_MANIFEST, PRAXIS_DIALOG_COMPONENT_METADATA, PRAXIS_DIALOG_CONTENT_REGISTRY, PRAXIS_DIALOG_DATA, PRAXIS_DIALOG_DEFAULTS, PRAXIS_DIALOG_EXAMPLE_LONG_CONTENT, PRAXIS_DIALOG_GLOBAL_PRESETS, PRAXIS_DIALOG_I18N, PRAXIS_DIALOG_TEMPLATE_REGISTRY, PraxisDialog, PraxisDialogActionsDirective, PraxisDialogComponent, PraxisDialogContentDirective, PraxisDialogDirectives, PraxisDialogRef, PraxisDialogTitleDirective, PraxisQuickViewOverlayComponent, QuickViewDialogPresenterService, provideDialogGlobalPresetsFromGlobalConfig, providePraxisDialogExamples, providePraxisDialogGlobalActions, providePraxisDialogMetadata, providePraxisQuickViewDialogPresenter, providePraxisSurfaceGlobalActions };
366
426
  export type { ActionsLayout, AnimationDirection, ComponentType, DialogAction, DialogAnimation, DialogAnimationType, DialogContentDescriptor, DialogThemeColor, PraxisAlertConfig, PraxisConfirmConfig, PraxisDialogConfig, PraxisDialogGlobalPresets, PraxisDialogPosition, PraxisDialogStyleConfig, PraxisPromptConfig };