@praxisui/dynamic-fields 3.0.0-beta.4 → 3.0.0-beta.5

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.
@@ -7450,9 +7450,33 @@ class MaterialButtonComponent extends SimpleBaseButtonComponent {
7450
7450
  // =============================================================================
7451
7451
  // LIFECYCLE
7452
7452
  // =============================================================================
7453
+ syncKeyboardShortcutEffect = effect((onCleanup) => {
7454
+ const shortcut = this.keyboardShortcut();
7455
+ if (!shortcut || !this.keyboardService) {
7456
+ return;
7457
+ }
7458
+ const unregister = this.keyboardService.registerShortcut(shortcut, {
7459
+ callback: () => { this.triggerAction(); },
7460
+ description: this.resolveDynamicFieldsMessage(null, 'button.shortcutDescription', 'Executar {{label}}', {
7461
+ label: this.metadata()?.label || this.tDynamicFields('button.defaultLabel', 'Button'),
7462
+ }),
7463
+ componentId: this.componentId(),
7464
+ priority: 10
7465
+ });
7466
+ this.unregisterShortcut = unregister;
7467
+ this.log('debug', 'Keyboard shortcut registered', { shortcut });
7468
+ onCleanup(() => {
7469
+ try {
7470
+ unregister?.();
7471
+ }
7472
+ catch { }
7473
+ if (this.unregisterShortcut === unregister) {
7474
+ this.unregisterShortcut = undefined;
7475
+ }
7476
+ });
7477
+ }, ...(ngDevMode ? [{ debugName: "syncKeyboardShortcutEffect" }] : []));
7453
7478
  ngOnInit() {
7454
7479
  super.ngOnInit();
7455
- this.setupKeyboardShortcuts();
7456
7480
  }
7457
7481
  ngOnDestroy() {
7458
7482
  super.ngOnDestroy();
@@ -7527,23 +7551,6 @@ class MaterialButtonComponent extends SimpleBaseButtonComponent {
7527
7551
  isIconOnly: this.isIconOnlyButton()
7528
7552
  };
7529
7553
  }
7530
- // =============================================================================
7531
- // MÉTODOS PRIVADOS
7532
- // =============================================================================
7533
- setupKeyboardShortcuts() {
7534
- const shortcut = this.keyboardShortcut();
7535
- if (shortcut && this.keyboardService) {
7536
- this.unregisterShortcut = this.keyboardService.registerShortcut(shortcut, {
7537
- callback: () => { this.triggerAction(); },
7538
- description: this.resolveDynamicFieldsMessage(null, 'button.shortcutDescription', 'Executar {{label}}', {
7539
- label: this.metadata()?.label || this.tDynamicFields('button.defaultLabel', 'Button'),
7540
- }),
7541
- componentId: this.componentId(),
7542
- priority: 10
7543
- });
7544
- this.log('debug', 'Keyboard shortcut registered', { shortcut });
7545
- }
7546
- }
7547
7554
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialButtonComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
7548
7555
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: MaterialButtonComponent, isStandalone: true, selector: "pdx-material-button", host: { properties: { "class": "componentCssClasses()", "attr.data-field-type": "\"button\"", "attr.data-field-name": "metadata()?.name", "attr.data-button-variant": "buttonVariant()", "attr.data-component-id": "componentId()" } }, usesInheritance: true, ngImport: i0, template: "<!-- Container principal do button -->\n<div class=\"pdx-button-container\" [class]=\"componentCssClasses()\">\n\n <!-- Button b\u00E1sico -->\n @if (buttonVariant() === 'basic') {\n <button\n mat-button\n [type]=\"buttonType()\"\n [color]=\"materialColor()\"\n [disabled]=\"isDisabled()\"\n [disableRipple]=\"shouldDisableRipple()\"\n [attr.aria-label]=\"metadata()?.label\"\n [attr.aria-describedby]=\"metadata()?.description ? componentId() + '-description' : null\"\n [matTooltip]=\"tooltipText()\"\n [matTooltipDisabled]=\"!tooltipText()\"\n matTooltipPosition=\"above\"\n (click)=\"handleClick($event)\"\n class=\"pdx-button-element\">\n \n @if (isLoading()) {\n <mat-spinner diameter=\"16\" class=\"pdx-button-spinner\"></mat-spinner>\n }\n \n @if (shouldShowIcon()) {\n <mat-icon class=\"pdx-button-icon\" [praxisIcon]=\"buttonIcon()\"></mat-icon>\n }\n \n <span class=\"pdx-button-text\">{{ buttonText() }}</span>\n </button>\n }\n\n <!-- Button raised -->\n @if (buttonVariant() === 'raised') {\n <button\n mat-raised-button\n [type]=\"buttonType()\"\n [color]=\"materialColor()\"\n [disabled]=\"isDisabled()\"\n [disableRipple]=\"shouldDisableRipple()\"\n [attr.aria-label]=\"metadata()?.label\"\n [attr.aria-describedby]=\"metadata()?.description ? componentId() + '-description' : null\"\n [matTooltip]=\"tooltipText()\"\n [matTooltipDisabled]=\"!tooltipText()\"\n matTooltipPosition=\"above\"\n (click)=\"handleClick($event)\"\n class=\"pdx-button-element\">\n \n @if (isLoading()) {\n <mat-spinner diameter=\"16\" class=\"pdx-button-spinner\"></mat-spinner>\n }\n \n @if (shouldShowIcon()) {\n <mat-icon class=\"pdx-button-icon\" [praxisIcon]=\"buttonIcon()\"></mat-icon>\n }\n \n <span class=\"pdx-button-text\">{{ buttonText() }}</span>\n </button>\n }\n\n <!-- Button stroked -->\n @if (buttonVariant() === 'stroked') {\n <button\n mat-stroked-button\n [type]=\"buttonType()\"\n [color]=\"materialColor()\"\n [disabled]=\"isDisabled()\"\n [disableRipple]=\"shouldDisableRipple()\"\n [attr.aria-label]=\"metadata()?.label\"\n [attr.aria-describedby]=\"metadata()?.description ? componentId() + '-description' : null\"\n [matTooltip]=\"tooltipText()\"\n [matTooltipDisabled]=\"!tooltipText()\"\n matTooltipPosition=\"above\"\n (click)=\"handleClick($event)\"\n class=\"pdx-button-element\">\n \n @if (isLoading()) {\n <mat-spinner diameter=\"16\" class=\"pdx-button-spinner\"></mat-spinner>\n }\n \n @if (shouldShowIcon()) {\n <mat-icon class=\"pdx-button-icon\" [praxisIcon]=\"buttonIcon()\"></mat-icon>\n }\n \n <span class=\"pdx-button-text\">{{ buttonText() }}</span>\n </button>\n }\n\n <!-- Button flat -->\n @if (buttonVariant() === 'flat') {\n <button\n mat-flat-button\n [type]=\"buttonType()\"\n [color]=\"materialColor()\"\n [disabled]=\"isDisabled()\"\n [disableRipple]=\"shouldDisableRipple()\"\n [attr.aria-label]=\"metadata()?.label\"\n [attr.aria-describedby]=\"metadata()?.description ? componentId() + '-description' : null\"\n [matTooltip]=\"tooltipText()\"\n [matTooltipDisabled]=\"!tooltipText()\"\n matTooltipPosition=\"above\"\n (click)=\"handleClick($event)\"\n class=\"pdx-button-element\">\n \n @if (isLoading()) {\n <mat-spinner diameter=\"16\" class=\"pdx-button-spinner\"></mat-spinner>\n }\n \n @if (shouldShowIcon()) {\n <mat-icon class=\"pdx-button-icon\" [praxisIcon]=\"buttonIcon()\"></mat-icon>\n }\n \n <span class=\"pdx-button-text\">{{ buttonText() }}</span>\n </button>\n }\n\n <!-- Button icon -->\n @if (buttonVariant() === 'icon') {\n <button\n mat-icon-button\n [type]=\"buttonType()\"\n [color]=\"materialColor()\"\n [disabled]=\"isDisabled()\"\n [disableRipple]=\"shouldDisableRipple()\"\n [attr.aria-label]=\"metadata()?.label || buttonIcon()\"\n [attr.aria-describedby]=\"metadata()?.description ? componentId() + '-description' : null\"\n [matTooltip]=\"tooltipText() || metadata()?.label\"\n [matTooltipDisabled]=\"!tooltipText() && !metadata()?.label\"\n matTooltipPosition=\"above\"\n (click)=\"handleClick($event)\"\n class=\"pdx-button-element\">\n \n @if (isLoading()) {\n <mat-spinner diameter=\"16\" class=\"pdx-button-spinner\"></mat-spinner>\n } @else {\n <mat-icon [praxisIcon]=\"buttonIcon() || 'mi:smart_button'\"></mat-icon>\n }\n </button>\n }\n\n <!-- Button FAB -->\n @if (buttonVariant() === 'fab') {\n <button\n mat-fab\n [type]=\"buttonType()\"\n [color]=\"materialColor()\"\n [disabled]=\"isDisabled()\"\n [disableRipple]=\"shouldDisableRipple()\"\n [attr.aria-label]=\"metadata()?.label || buttonIcon()\"\n [attr.aria-describedby]=\"metadata()?.description ? componentId() + '-description' : null\"\n [matTooltip]=\"tooltipText() || metadata()?.label\"\n [matTooltipDisabled]=\"!tooltipText() && !metadata()?.label\"\n matTooltipPosition=\"above\"\n (click)=\"handleClick($event)\"\n class=\"pdx-button-element\">\n \n @if (isLoading()) {\n <mat-spinner diameter=\"20\" class=\"pdx-button-spinner\"></mat-spinner>\n } @else {\n <mat-icon [praxisIcon]=\"buttonIcon() || 'add'\"></mat-icon>\n }\n </button>\n }\n\n <!-- Button Mini FAB -->\n @if (buttonVariant() === 'mini-fab') {\n <button\n mat-mini-fab\n [type]=\"buttonType()\"\n [color]=\"materialColor()\"\n [disabled]=\"isDisabled()\"\n [disableRipple]=\"shouldDisableRipple()\"\n [attr.aria-label]=\"metadata()?.label || buttonIcon()\"\n [attr.aria-describedby]=\"metadata()?.description ? componentId() + '-description' : null\"\n [matTooltip]=\"tooltipText() || metadata()?.label\"\n [matTooltipDisabled]=\"!tooltipText() && !metadata()?.label\"\n matTooltipPosition=\"above\"\n (click)=\"handleClick($event)\"\n class=\"pdx-button-element\">\n \n @if (isLoading()) {\n <mat-spinner diameter=\"16\" class=\"pdx-button-spinner\"></mat-spinner>\n } @else {\n <mat-icon [praxisIcon]=\"buttonIcon() || 'add'\"></mat-icon>\n }\n </button>\n }\n\n <!-- Descri\u00E7\u00E3o do bot\u00E3o (se dispon\u00EDvel) -->\n @if (metadata()?.description && !isIconOnlyButton()) {\n <div \n class=\"pdx-button-description\"\n [id]=\"componentId() + '-description'\">\n {{ metadata()?.description }}\n </div>\n }\n\n</div>\n\n<!-- Loading indicator para valida\u00E7\u00E3o ass\u00EDncrona -->\n@if (isLoading()) {\n <div class=\"pdx-validation-loading\" [attr.aria-label]=\"validationLoadingAriaLabel()\">\n <mat-icon class=\"pdx-loading-spinner\" [praxisIcon]=\"'mi:hourglass_empty'\"></mat-icon>\n <span class=\"pdx-sr-only\">{{ validationLoadingSrOnly() }}</span>\n </div>\n}\n\n<!-- Indicador de estado enterprise (debug) -->\n@if (false && metadata()?.security) {\n <div class=\"pdx-debug-info\">\n <small class=\"pdx-debug-security\">\n Security Level: {{ metadata()?.security?.securityLevel }}\n @if (metadata()?.security?.audit?.enabled) {\n | Audit: ON\n }\n | Clicks: {{ 0 }}\n @if (keyboardShortcut()) {\n | Shortcut: {{ keyboardShortcut() }}\n }\n </small>\n </div>\n}\n", styles: [".pdx-button-container{display:inline-block;position:relative}.pdx-button-container .pdx-button-element{position:relative;overflow:hidden;transition:all .2s ease}.pdx-button-container .pdx-button-element.pdx-button-with-icon .pdx-button-icon{margin-right:8px;font-size:18px;height:18px;width:18px}.pdx-button-container .pdx-button-element .pdx-button-spinner{margin-right:8px}.pdx-button-container .pdx-button-element .pdx-button-spinner:only-child{margin-right:0}.pdx-button-container .pdx-button-element .pdx-button-text{display:inline-block;vertical-align:middle}.pdx-button-container .pdx-button-element:disabled{cursor:not-allowed;opacity:.6}.pdx-button-container .pdx-button-element:focus{outline:2px solid var(--mat-focus-indicator-color, var(--md-sys-color-primary));outline-offset:2px}.pdx-button-container .pdx-button-description{margin-top:4px;font-size:12px;color:var(--mat-form-field-subscript-text-color);text-align:center;line-height:1.3}.pdx-button-container.pdx-button-loading .pdx-button-element{cursor:wait}.pdx-button-container.pdx-button-loading .pdx-button-element .pdx-button-text{opacity:.7}.pdx-button-container.pdx-button-pressed .pdx-button-element{transform:scale(.98);transition:transform .1s ease}.pdx-button-container.pdx-button-no-ripple .pdx-button-element .mat-ripple{display:none}.pdx-button-container.pdx-button-variant-raised .pdx-button-element{box-shadow:var(--md-sys-elevation-level1, var(--md-sys-elevation-level1))}.pdx-button-container.pdx-button-variant-raised .pdx-button-element:hover:not(:disabled){box-shadow:var(--md-sys-elevation-level2, var(--md-sys-elevation-level2))}.pdx-button-container.pdx-button-variant-stroked .pdx-button-element{border:1px solid var(--mat-stroked-button-outline-color)}.pdx-button-container.pdx-button-variant-icon .pdx-button-element{min-width:40px;width:40px;height:40px;border-radius:50%}.pdx-button-container.pdx-button-variant-icon .pdx-button-element .mat-icon{font-size:20px;height:20px;width:20px}.pdx-button-container.pdx-button-variant-fab .pdx-button-element{min-width:56px;width:56px;height:56px}.pdx-button-container.pdx-button-variant-fab .pdx-button-element .mat-icon{font-size:24px;height:24px;width:24px}.pdx-button-container.pdx-button-variant-mini-fab .pdx-button-element{min-width:40px;width:40px;height:40px}.pdx-button-container.pdx-button-variant-mini-fab .pdx-button-element .mat-icon{font-size:20px;height:20px;width:20px}.pdx-button-container.pdx-button-icon-only .pdx-button-description{max-width:120px;font-size:11px}.pdx-validation-loading{display:flex;align-items:center;gap:8px;margin-top:8px;color:var(--mat-form-field-subscript-text-color);font-size:12px}.pdx-validation-loading .pdx-loading-spinner{font-size:16px;height:16px;width:16px;animation:spin 1s linear infinite}.pdx-validation-loading .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-debug-info{margin-top:8px;padding:4px 8px;background-color:var(--mat-toolbar-container-background-color, var(--md-sys-color-surface-variant));border-radius:4px;max-width:200px}.pdx-debug-info .pdx-debug-security{font-family:monospace;font-size:10px;color:var(--mat-toolbar-container-text-color, var(--md-sys-color-on-surface-variant));word-break:break-all}@media(max-width:600px){.pdx-button-container.pdx-button-variant-fab .pdx-button-element{min-width:48px;width:48px;height:48px}.pdx-button-container.pdx-button-variant-fab .pdx-button-element .mat-icon{font-size:20px;height:20px;width:20px}.pdx-button-container .pdx-button-element.pdx-button-with-icon .pdx-button-icon{margin-right:6px;font-size:16px;height:16px;width:16px}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes buttonPulse{0%,to{transform:scale(1)}50%{transform:scale(1.02)}}.pdx-button-container .pdx-button-element:hover:not(:disabled){transform:translateY(-1px);transition:transform .2s ease}.pdx-button-container .pdx-button-element:active:not(:disabled){transform:translateY(0) scale(.98);transition:transform .1s ease}.pdx-button-container.pdx-button-loading .pdx-button-element{animation:buttonPulse 1.5s infinite ease-in-out}@media(prefers-reduced-motion:reduce){.pdx-button-container .pdx-button-element{transition:none;animation:none}.pdx-button-container .pdx-button-element:hover:not(:disabled){transform:none}.pdx-button-container .pdx-button-element:active:not(:disabled){transform:none}.pdx-loading-spinner,.pdx-button-loading .pdx-button-element{animation:none}}@media(prefers-contrast:high){.pdx-button-container .pdx-button-element:focus{outline:3px solid;outline-offset:2px}}@media(prefers-color-scheme:dark){.pdx-button-container.pdx-button-variant-raised .pdx-button-element{box-shadow:var(--md-sys-elevation-level2, var(--md-sys-elevation-level2))}.pdx-button-container.pdx-button-variant-raised .pdx-button-element:hover:not(:disabled){box-shadow:var(--md-sys-elevation-level3, var(--md-sys-elevation-level3))}}@media print{.pdx-button-container .pdx-button-element{box-shadow:none!important;border:1px solid var(--md-sys-color-outline);background:transparent!important;color:var(--md-sys-color-on-surface)!important}.pdx-button-container .pdx-button-element .pdx-button-spinner,.pdx-validation-loading,.pdx-debug-info{display:none}}.pdx-button-container .mat-primary.pdx-button-loading{background-color:var(--md-sys-color-primary)}.pdx-button-container .mat-accent.pdx-button-loading{background-color:var(--md-sys-color-secondary)}.pdx-button-container .mat-warn.pdx-button-loading{background-color:var(--md-sys-color-error)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.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: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i7.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }] });
7549
7556
  }
@@ -40285,6 +40292,7 @@ class MaterialAvatarComponent {
40285
40292
  defaultIcon;
40286
40293
  // Visual props
40287
40294
  appearanceTick = signal(0, ...(ngDevMode ? [{ debugName: "appearanceTick" }] : []));
40295
+ contentTick = signal(0, ...(ngDevMode ? [{ debugName: "contentTick" }] : []));
40288
40296
  _themeColor = 'primary';
40289
40297
  _rounded = 'full';
40290
40298
  _size = 'medium';
@@ -40382,6 +40390,7 @@ class MaterialAvatarComponent {
40382
40390
  }, ...(ngDevMode ? [{ debugName: "_syncControlValue" }] : []));
40383
40391
  // Resolved sources
40384
40392
  resolvedImageSrc = computed(() => {
40393
+ this.contentTick();
40385
40394
  // Priority: explicit input > form control value > metadata.defaultValue
40386
40395
  const byInput = this.normalizeImageUrl(this.imageSrc);
40387
40396
  if (byInput)
@@ -40419,6 +40428,7 @@ class MaterialAvatarComponent {
40419
40428
  // Host classes
40420
40429
  componentCssClasses = computed(() => {
40421
40430
  this.appearanceTick();
40431
+ this.contentTick();
40422
40432
  const classes = ['pfx-avatar'];
40423
40433
  classes.push(`theme-${this.themeColor || 'primary'}`);
40424
40434
  classes.push(`rounded-${this.rounded || 'full'}`);
@@ -40456,6 +40466,7 @@ class MaterialAvatarComponent {
40456
40466
  }, ...(ngDevMode ? [{ debugName: "resolvedStyle" }] : []));
40457
40467
  // Accessible label fallback
40458
40468
  computedAriaLabel = computed(() => {
40469
+ this.contentTick();
40459
40470
  const explicit = (this.ariaLabel || '').trim();
40460
40471
  if (explicit)
40461
40472
  return explicit;
@@ -40562,9 +40573,16 @@ class MaterialAvatarComponent {
40562
40573
  shouldShowDefaultIcon() {
40563
40574
  return !this.hasImage() && !this.hasExplicitIcon() && !this.hasInitials() && this.hasDefaultIcon();
40564
40575
  }
40565
- hasExplicitIcon = computed(() => this.resolveIconKind(this.icon) !== null, ...(ngDevMode ? [{ debugName: "hasExplicitIcon" }] : []));
40566
- hasDefaultIcon = computed(() => this.resolveIconKind(this.defaultIcon) !== null, ...(ngDevMode ? [{ debugName: "hasDefaultIcon" }] : []));
40576
+ hasExplicitIcon = computed(() => {
40577
+ this.contentTick();
40578
+ return this.resolveIconKind(this.icon) !== null;
40579
+ }, ...(ngDevMode ? [{ debugName: "hasExplicitIcon" }] : []));
40580
+ hasDefaultIcon = computed(() => {
40581
+ this.contentTick();
40582
+ return this.resolveIconKind(this.defaultIcon) !== null;
40583
+ }, ...(ngDevMode ? [{ debugName: "hasDefaultIcon" }] : []));
40567
40584
  normalizedInitials() {
40585
+ this.contentTick();
40568
40586
  // Prioritize explicit initials
40569
40587
  const explicitInitials = (this.initials || '').trim();
40570
40588
  if (explicitInitials) {
@@ -40604,6 +40622,7 @@ class MaterialAvatarComponent {
40604
40622
  }
40605
40623
  // ... (rest of methods)
40606
40624
  iconName() {
40625
+ this.contentTick();
40607
40626
  // Used in template inside specific blocks.
40608
40627
  // If showIcon() is true => icon is explicit.
40609
40628
  // If showDefaultIcon() is true => icon is default.
@@ -40627,6 +40646,7 @@ class MaterialAvatarComponent {
40627
40646
  return null;
40628
40647
  }
40629
40648
  iconSvgSafe() {
40649
+ this.contentTick();
40630
40650
  // Similar logic for SVG
40631
40651
  const source = this.hasExplicitIcon() ? this.icon : this.defaultIcon;
40632
40652
  const kind = this.resolveIconKind(source);
@@ -40650,6 +40670,7 @@ class MaterialAvatarComponent {
40650
40670
  return null;
40651
40671
  }
40652
40672
  iconFontClass() {
40673
+ this.contentTick();
40653
40674
  const source = this.hasExplicitIcon() ? this.icon : this.defaultIcon;
40654
40675
  const kind = this.resolveIconKind(source);
40655
40676
  if (kind === 'font') {
@@ -40657,66 +40678,78 @@ class MaterialAvatarComponent {
40657
40678
  }
40658
40679
  return null;
40659
40680
  }
40681
+ ngOnChanges(_changes) {
40682
+ this.contentTick.update((value) => value + 1);
40683
+ }
40660
40684
  // Allow DynamicFieldLoader to apply metadata extras
40661
40685
  setInputMetadata(meta) {
40686
+ const previousMeta = this.metadata();
40662
40687
  const typedMeta = meta;
40663
40688
  this.metadata.set(typedMeta);
40664
40689
  const extras = typedMeta?.extra || {};
40690
+ const hadPrevExtra = (key) => !!previousMeta?.extra &&
40691
+ Object.prototype.hasOwnProperty.call(previousMeta.extra, key);
40692
+ const hadPrevRoot = (key) => !!previousMeta &&
40693
+ Object.prototype.hasOwnProperty.call(previousMeta, key);
40694
+ const resolveExtra = (key, rootValue) => {
40695
+ if (extras[key] !== undefined) {
40696
+ return extras[key];
40697
+ }
40698
+ if (rootValue !== undefined) {
40699
+ return rootValue;
40700
+ }
40701
+ if (hadPrevExtra(String(key)) || hadPrevRoot(String(key))) {
40702
+ return undefined;
40703
+ }
40704
+ return undefined;
40705
+ };
40665
40706
  // Known keys: imageSrc, imageAlt, initials, name, icon, themeColor, rounded, size, fillMode, border, tooltip, ariaLabel
40666
- if (extras.imageSrc !== undefined)
40667
- this.imageSrc = extras.imageSrc;
40668
- else if (typedMeta?.imageSrc !== undefined)
40669
- this.imageSrc = String(typedMeta.imageSrc);
40670
- if (extras.imageAlt !== undefined)
40671
- this.imageAlt = extras.imageAlt;
40672
- else if (typedMeta?.imageAlt !== undefined)
40673
- this.imageAlt = typedMeta.imageAlt;
40674
- if (extras.initials !== undefined)
40675
- this.initials = extras.initials;
40676
- if (extras.name !== undefined)
40677
- this.name = extras.name;
40678
- if (extras.icon !== undefined)
40679
- this.icon = extras.icon;
40680
- if (extras.defaultIcon !== undefined)
40681
- this.defaultIcon = extras.defaultIcon;
40682
- if (extras.themeColor !== undefined)
40683
- this.themeColor = extras.themeColor;
40684
- if (extras.rounded !== undefined)
40685
- this.rounded = extras.rounded;
40686
- if (extras.size !== undefined)
40687
- this.size = extras.size;
40688
- if (extras.fillMode !== undefined)
40689
- this.fillMode = extras.fillMode;
40690
- if (extras.border !== undefined)
40691
- this.border = !!extras.border;
40692
- if (extras.sizePx !== undefined)
40693
- this.sizePx = typeof extras.sizePx === 'number' ? extras.sizePx : Number(extras.sizePx);
40694
- if (extras.sizeCss !== undefined)
40695
- this.sizeCss = extras.sizeCss;
40696
- if (extras.tooltip !== undefined)
40697
- this.tooltip = extras.tooltip;
40698
- if (extras.ariaLabel !== undefined)
40699
- this.ariaLabel = extras.ariaLabel;
40700
- if (extras.class !== undefined)
40701
- this.class = extras.class;
40702
- if (extras.style !== undefined) {
40703
- if (typeof extras.style === 'string') {
40707
+ this.imageSrc = resolveExtra('imageSrc', typedMeta?.imageSrc !== undefined ? String(typedMeta.imageSrc) : undefined);
40708
+ this.imageAlt = resolveExtra('imageAlt', typedMeta?.imageAlt);
40709
+ this.initials = resolveExtra('initials');
40710
+ this.name = resolveExtra('name');
40711
+ this.icon = resolveExtra('icon');
40712
+ this.defaultIcon = resolveExtra('defaultIcon');
40713
+ this.themeColor = resolveExtra('themeColor');
40714
+ this.rounded = resolveExtra('rounded');
40715
+ this.size = resolveExtra('size');
40716
+ this.fillMode = resolveExtra('fillMode');
40717
+ this.border = !!resolveExtra('border');
40718
+ const sizePxValue = resolveExtra('sizePx');
40719
+ this.sizePx =
40720
+ sizePxValue === undefined
40721
+ ? undefined
40722
+ : typeof sizePxValue === 'number'
40723
+ ? sizePxValue
40724
+ : Number(sizePxValue);
40725
+ this.sizeCss = resolveExtra('sizeCss');
40726
+ this.tooltip = resolveExtra('tooltip');
40727
+ this.ariaLabel = resolveExtra('ariaLabel');
40728
+ this.class = resolveExtra('class');
40729
+ const styleValue = resolveExtra('style');
40730
+ if (styleValue !== undefined) {
40731
+ if (typeof styleValue === 'string') {
40704
40732
  try {
40705
- const obj = JSON.parse(extras.style);
40733
+ const obj = JSON.parse(styleValue);
40706
40734
  if (obj && typeof obj === 'object')
40707
40735
  this.style = obj;
40708
40736
  }
40709
40737
  catch {
40710
40738
  // ignore invalid JSON
40739
+ this.style = undefined;
40711
40740
  }
40712
40741
  }
40713
- else if (typeof extras.style === 'object') {
40714
- this.style = extras.style;
40742
+ else if (typeof styleValue === 'object') {
40743
+ this.style = styleValue;
40715
40744
  }
40716
40745
  }
40746
+ else if (hadPrevExtra('style')) {
40747
+ this.style = undefined;
40748
+ }
40749
+ this.contentTick.update((value) => value + 1);
40717
40750
  }
40718
40751
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: MaterialAvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
40719
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: MaterialAvatarComponent, isStandalone: true, selector: "pdx-material-avatar", inputs: { imageSrc: "imageSrc", imageAlt: "imageAlt", initials: "initials", name: "name", icon: "icon", defaultIcon: "defaultIcon", themeColor: "themeColor", rounded: "rounded", size: "size", fillMode: "fillMode", border: "border", sizePx: "sizePx", sizeCss: "sizeCss", tooltip: "tooltip", ariaLabel: "ariaLabel", readonlyMode: "readonlyMode", disabledMode: "disabledMode", visible: "visible", presentationMode: "presentationMode", class: "class", style: "style" }, outputs: { imageError: "imageError" }, host: { properties: { "class": "componentCssClasses()", "style.display": "visible === false ? \"none\" : null", "attr.aria-hidden": "visible ? null : \"true\"", "attr.role": "\"img\"", "attr.aria-label": "computedAriaLabel() || null", "attr.aria-describedby": "hintId()", "attr.data-field-type": "\"avatar\"", "attr.data-field-name": "metadata()?.name", "attr.data-component-id": "componentId()", "class.praxis-disabled": "disabledMode === true", "class.praxis-readonly": "readonlyMode === true", "class.presentation-mode": "presentationMode === true" } }, ngImport: i0, template: `
40752
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: MaterialAvatarComponent, isStandalone: true, selector: "pdx-material-avatar", inputs: { imageSrc: "imageSrc", imageAlt: "imageAlt", initials: "initials", name: "name", icon: "icon", defaultIcon: "defaultIcon", themeColor: "themeColor", rounded: "rounded", size: "size", fillMode: "fillMode", border: "border", sizePx: "sizePx", sizeCss: "sizeCss", tooltip: "tooltip", ariaLabel: "ariaLabel", readonlyMode: "readonlyMode", disabledMode: "disabledMode", visible: "visible", presentationMode: "presentationMode", class: "class", style: "style" }, outputs: { imageError: "imageError" }, host: { properties: { "class": "componentCssClasses()", "style.display": "visible === false ? \"none\" : null", "attr.aria-hidden": "visible ? null : \"true\"", "attr.role": "\"img\"", "attr.aria-label": "computedAriaLabel() || null", "attr.aria-describedby": "hintId()", "attr.data-field-type": "\"avatar\"", "attr.data-field-name": "metadata()?.name", "attr.data-component-id": "componentId()", "class.praxis-disabled": "disabledMode === true", "class.praxis-readonly": "readonlyMode === true", "class.presentation-mode": "presentationMode === true" } }, usesOnChanges: true, ngImport: i0, template: `
40720
40753
  <span class="pfx-avatar__inner"
40721
40754
  [attr.aria-hidden]="presentationMode ? 'true' : null"
40722
40755
  [ngStyle]="resolvedStyle()"
@@ -44528,11 +44561,13 @@ class PdxColorPickerComponent extends SimpleBaseInputComponent {
44528
44561
  current = signal(null, ...(ngDevMode ? [{ debugName: "current" }] : []));
44529
44562
  draft = signal(null, ...(ngDevMode ? [{ debugName: "draft" }] : []));
44530
44563
  draftAlpha = signal(1, ...(ngDevMode ? [{ debugName: "draftAlpha" }] : []));
44564
+ configTick = signal(0, ...(ngDevMode ? [{ debugName: "configTick" }] : []));
44531
44565
  panelWidthPx = 340;
44532
44566
  constructor(bottomSheet) {
44533
44567
  super();
44534
44568
  this.bottomSheet = bottomSheet;
44535
44569
  effect(() => {
44570
+ this.configTick();
44536
44571
  this.panelWidthPx = this.coerceWidth(this.popupSettings?.width ?? 340);
44537
44572
  });
44538
44573
  // React to metadata changes to keep inputs in sync
@@ -44611,8 +44646,12 @@ class PdxColorPickerComponent extends SimpleBaseInputComponent {
44611
44646
  this.visible = !!md.visible;
44612
44647
  if (typeof md.presentationMode === 'boolean')
44613
44648
  this.presentationMode = !!md.presentationMode;
44649
+ this.configTick.update((value) => value + 1);
44614
44650
  });
44615
44651
  }
44652
+ ngOnChanges(_changes) {
44653
+ this.configTick.update((value) => value + 1);
44654
+ }
44616
44655
  resolveClearButtonConfig(md) {
44617
44656
  const metadata = md && typeof md === 'object' && !Array.isArray(md) ? md : {};
44618
44657
  const cfg = metadata.clearButton;
@@ -44727,8 +44766,14 @@ class PdxColorPickerComponent extends SimpleBaseInputComponent {
44727
44766
  onClose() { this.close.emit(); }
44728
44767
  // Views logic
44729
44768
  selectedTabIndex = signal(0, ...(ngDevMode ? [{ debugName: "selectedTabIndex" }] : []));
44730
- showGradient = computed(() => this.views.includes('gradient'), ...(ngDevMode ? [{ debugName: "showGradient" }] : []));
44731
- showPalette = computed(() => this.views.includes('palette'), ...(ngDevMode ? [{ debugName: "showPalette" }] : []));
44769
+ showGradient = computed(() => {
44770
+ this.configTick();
44771
+ return this.views.includes('gradient');
44772
+ }, ...(ngDevMode ? [{ debugName: "showGradient" }] : []));
44773
+ showPalette = computed(() => {
44774
+ this.configTick();
44775
+ return this.views.includes('palette');
44776
+ }, ...(ngDevMode ? [{ debugName: "showPalette" }] : []));
44732
44777
  onTabIndexChange(i) {
44733
44778
  this.selectedTabIndex.set(i);
44734
44779
  const v = this.views[i] || 'gradient';
@@ -44736,7 +44781,10 @@ class PdxColorPickerComponent extends SimpleBaseInputComponent {
44736
44781
  this.activeViewChange.emit(v);
44737
44782
  }
44738
44783
  // Draft preview strings
44739
- draftPreview = computed(() => this.toFormat(this.draft(), this.format, this.draftAlpha()), ...(ngDevMode ? [{ debugName: "draftPreview" }] : []));
44784
+ draftPreview = computed(() => {
44785
+ this.configTick();
44786
+ return this.toFormat(this.draft(), this.format, this.draftAlpha());
44787
+ }, ...(ngDevMode ? [{ debugName: "draftPreview" }] : []));
44740
44788
  draftSolidHex = computed(() => this.toHex(this.draft()) || this.defaultHex(), ...(ngDevMode ? [{ debugName: "draftSolidHex" }] : []));
44741
44789
  draftOpacity = computed(() => this.draftAlpha(), ...(ngDevMode ? [{ debugName: "draftOpacity" }] : []));
44742
44790
  // Preview swatch background for input prefix
@@ -44759,6 +44807,7 @@ class PdxColorPickerComponent extends SimpleBaseInputComponent {
44759
44807
  customColors = signal([], ...(ngDevMode ? [{ debugName: "customColors" }] : []));
44760
44808
  recentColors = signal([], ...(ngDevMode ? [{ debugName: "recentColors" }] : []));
44761
44809
  paletteColors = computed(() => {
44810
+ this.configTick();
44762
44811
  const base = this.buildPaletteColors(this.paletteSettings);
44763
44812
  const extra = this.customColors();
44764
44813
  // dedupe (case-insensitive)
@@ -45125,7 +45174,7 @@ class PdxColorPickerComponent extends SimpleBaseInputComponent {
45125
45174
  useExisting: forwardRef(() => PdxColorPickerComponent),
45126
45175
  multi: true,
45127
45176
  },
45128
- ], viewQueries: [{ propertyName: "toggleBtn", first: true, predicate: ["toggleBtn"], descendants: true }, { propertyName: "menuTrigger", first: true, predicate: MatMenuTrigger, descendants: true }], usesInheritance: true, ngImport: i0, template: `
45177
+ ], viewQueries: [{ propertyName: "toggleBtn", first: true, predicate: ["toggleBtn"], descendants: true }, { propertyName: "menuTrigger", first: true, predicate: MatMenuTrigger, descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
45129
45178
  <mat-form-field
45130
45179
  [appearance]="materialAppearance()"
45131
45180
  [color]="materialColor()"